/**********************************************************************
 * Copyright (c) 2000 by Borst Automation, Fachingen
 * All rights reserved
 *
 * Filename:  UserApi.c
 * Project:   HART Slave
 * Date:      jul-29-00
 * Author(s): W. Borst
 *
 * Revision:
 * Date:      Name:       Version:  Description:
 * Jul-29-00  W. Borst    -----     Initial Draft
 *
 * Description: User's target implementations
 *
 **********************************************************************/
/**********************************************************************
 * Includes                                                           *
 **********************************************************************/
#include <String.h>
#include "..\Common\Types.h"
#include "..\Common\MemDecls.h"
#include "..\Common\Hart.h"
#include "..\Protocol\HartLoL.h"
#include "..\Api\UserApi.h"
#ifdef VC_STUDIO
  #include <math.h>
#endif
 
BOOL bLowLevelLocked; //Variable Decl

#ifdef VC_STUDIO
  BOOL sysEEPromIsValid(void)
  { return FALSE;
  }

  void sysEEPromWrite(EEPROM void * peeTrg, 
                      const void *  pSrc, 
										  BYTE size)
  { if (size)
      M_API_MEMCPY(peeTrg,pSrc,size); 
  }

  void sysEEPromRead(void * pTrg, 
                     const EEPROM void * peeSrc, 
									   BYTE size)
  { if (size)
      M_API_MEMCPY(pTrg,peeSrc,size);
  }

  void sysTriggerWatchdog(void)
  { return;
  }

  BOOL sysDevIsWrProtected(void)
  { return FALSE;
  }
#endif

void sysPutInt16(void * pTrg,UINT16 Val)
{ UINT16 uiBuf;
  
	uiBuf = Val;
	M_API_MEMCPY(pTrg,&uiBuf,2);
}

void sysPutInt24(void * pTrg,UINT24 Val)
{ union { ULONG ul;
          UCHR  uc[4];
        } unBuf;
  
	unBuf.ul = Val;
	M_API_MEMCPY(pTrg,&unBuf.uc[1],3);
}

void sysPutInt32(void * pTrg,UINT32 Val)
{ UINT32 ulBuf;

  ulBuf = Val;
	M_API_MEMCPY(pTrg,&ulBuf,4);
}

void sysPutFloat(void * pTrg,FLOAT Val)
{ FLOAT flBuf;

  flBuf = Val;
	M_API_MEMCPY(pTrg,&flBuf,4);
}

void sysSwap2(UCHR * pC)
{ UCHR ucB;

  ucB = pC[0];
	pC[0] = pC[1];
	pC[1] = ucB;
}

void sysSwap3(UCHR * pC)
{ UCHR ucB;

  ucB = pC[0];
	pC[0] = pC[2];
	pC[2] = ucB;
}

void sysSwap4(UCHR * pC)
{ UCHR ucB;

  ucB = pC[0];
	pC[0] = pC[3];
	pC[3] = ucB;
	ucB = pC[1];
	pC[1] = pC[2];
	pC[2] = ucB;
}

#ifdef VC_STUDIO
  void sysIEEEtoMSfloat(void * pfl_IO)
  {
   /* Convert from IEEE 754 into a float */
    DOUBLE dTmp;
    INT    iExp;   
    LONG   lV;
  
    sysSwap4(pfl_IO);
	  lV = *((LONG*)pfl_IO); 
    if (lV==0x7FA00000)
    { /* This was NaN !!! */
        dTmp = 1.0e+30;
    }
	  else
    { if (lV == 0)
      { dTmp = 0;
      }
      else
      { dTmp = ((DOUBLE)((lV & 0x7FFFFFL)| 0x800000)) / 0x800000;
        iExp = ((INT) (lV >> 23) & 0xFF) - 127;
        dTmp = ldexp(dTmp,iExp);
        if (lV & 0x80000000L)
        { dTmp = -dTmp;
        }
	    }		   
    }
    *((FLOAT*)pfl_IO) = (FLOAT) dTmp;
  }

  void sysMSfloatToIEEE(void * pfl_IO)
  {
   /* Convert from double into IEEE 754 */         
      INT    iExp;
      LONG   lRetVal;       
      DOUBLE dTmp;
      DOUBLE v;
  
    v = *((FLOAT*)pfl_IO);  
    if (v == 0)
    { lRetVal = 0;
    }
    else
    { dTmp = frexp(v,&iExp);
      if (v < 0 )
      { /* Negative float value */
        lRetVal = (((LONG) (-dTmp * 0x1000000L))) & 0x07FFFFFL;
        lRetVal |= 0x80000000L;
      }
      else
      { /* Positive float value */
        lRetVal = (((LONG) (dTmp * 0x02000000L)+1) >> 1) & 0x07FFFFFL;
      }
      /* Convert the exponent */
      iExp += (127-1);
      if (iExp > 255)
      { /* Exponent too large */
        /* exp = 127 */ 
        iExp = 0x7F;
        lRetVal |= 0x7FFFFFL; /* Maximum value into mantissa */
      }
      if (iExp < 0)
      { iExp = 0;
        lRetVal =0;
      }
      /* Put exponent to 754 expression */
      lRetVal |= ((LONG)(iExp & 0xFF)) << 23;
    }
	  sysSwap4((UCHR *) &lRetVal);
    memcpy(pfl_IO,&lRetVal,4);
  }
#endif

BOOL sysPackAscii(UCHR* Src,UINT SrcLen,UCHR* Dst,UINT* DstLen)
{ /* Convert from visible string (8 bit format) into packed ascii
     string (6 bit format) */
  BYTE e;
  BYTE byDstIdx = 0;
  BYTE bySrcIdx = 0;
  
  if (SrcLen == 0)
    return FALSE;
  /* initialize destination with default values */
  for (e=0;e<SrcLen;e++)
  { switch (e%3)
    { case 0:
        Dst[e] = 0x7d; break;
      case 1:
        Dst[e] = 0xf7; break;
      case 2:
        Dst[e] = 0xdf; break;
    }
  }
  *DstLen = 0;
  while (SrcLen)
  { /* First character */
    Dst[byDstIdx] &= 0x03;
    Dst[byDstIdx] |= (Src[bySrcIdx] & 0x3F) << 2;
    (*DstLen)++;
    if (--SrcLen == 0)
      return TRUE;
    /* Second character */
    Dst[byDstIdx] &= 0xFC;
    Dst[byDstIdx] |= (Src[bySrcIdx+1] & 0x30) >> 4;
    Dst[byDstIdx+1] &= 0x0F;
    Dst[byDstIdx+1] |= (Src[bySrcIdx] & 0x0F) << 4;
    (*DstLen)++;
    if (--SrcLen == 0)
      return TRUE;
    /* Third character */
    Dst[byDstIdx+1] &= 0xF0;
    Dst[byDstIdx+1] |= (Src[bySrcIdx+2] & 0x3C) >> 2;
    Dst[byDstIdx+2] &= 0x3F;
    Dst[byDstIdx+2] |= Src[bySrcIdx+2] << 6;
    (*DstLen)++;
    if (--SrcLen == 0)
      return TRUE; 
    /* Fourth character */
    Dst[byDstIdx+2] &= 0xC0;
    Dst[byDstIdx+2] |= Src[bySrcIdx+3] & 0x3F;
    if (--SrcLen == 0)
      return TRUE;
    Dst += 3; Src += 4; 
  }
  return FALSE;
}

BOOL sysUnpackAscii(UCHR* Src,UINT SrcLen,UCHR *Dst,UINT* DstLen)
{ /* Convert from packed ascii string (6 bit format) into visible
     string (8 bit format) */
  UCHR uc;
  BYTE e;
  BYTE byMyLen;

  *DstLen = 0;
  if (SrcLen < 3)
    return FALSE;
  if ((SrcLen % 3)>0)
    return FALSE;
  byMyLen = (BYTE) (SrcLen - (SrcLen % 3));
  for (e=0;e<(byMyLen-2);e+=3)
  { /* First character */
    uc = (UCHR)((Src[e] >> 2) & 0x3F);
    if (uc < 0x20) uc += 0x40;
    Dst[(*DstLen)++] = uc;
    /* Second character */
    uc = (UCHR)(((Src[e] << 4 ) & 0x3F) | ((Src[e+1] >> 4) & 0x3F));
    if (uc < 0x20) uc += 0x40;
    Dst[(*DstLen)++] = uc;
    /* Third character */
    uc = (UCHR)(((Src[e+1] << 2 ) & 0x3F) | ((Src[e+2] >> 6) & 0x3F));
    if (uc < 0x20) uc += 0x40;
    Dst[(*DstLen)++] = uc;
    /* Fourth character */
    uc = (UCHR)(Src[e+2] & 0x3F);
    if (uc < 0x20) uc += 0x40;
    Dst[(*DstLen)++] = uc;
  }
  return TRUE;
}
