/*
Copyright by Nick Mueller // http://www.yadro.de
This code is as it is and just a sample. No liability for functionality.
Use at your own risk.
Compiler is OpenWatcom
C is C99
The macro YFLOAT expands to a double
*/
/* ---------------------------------------- */
char FlipNibble(const char nibble) {
  switch (nibble) {
    case '0': return  0;
    case '1': return  8;
    case '2': return  4;
    case '3': return 12;
    case '4': return  2;
    case '5': return 10;
    case '6': return  6;
    case '7': return 14;
    case '8': return  1;
    case '9': return  9;
    case 'a':
    case 'A': return  5;
    case 'b':
    case 'B': return 13;
    case 'c':
    case 'C': return  3;
    case 'd':
    case 'D': return 11;
    case 'e':
    case 'E': return  7;
    case 'f':
    case 'F': return 15;
  }

  return 0;
}
/* ----------------------------------------- */
YFLOAT DecodeString(const char* buffer, const int devID) {
  YFLOAT retVal = 0.0;
  int32_t iVal;
  int sign;

  /* pattern is DRO#nt:0x.... n:number t:type('B' or 'L')*/
  if (strncmp("DRO#", buffer, 4) != 0)
    return _NAN;

  if (buffer[4] - '0' != devID)
    return _NAN;

  if (buffer[5] == 'B') {
    if (strlen(buffer) < 16)
      return _NAN;

    iVal = (int32_t)FlipNibble(buffer[10]);
    iVal+= (int32_t)FlipNibble(buffer[11]) * 10;
    iVal+= (int32_t)FlipNibble(buffer[12]) * 100;
    iVal+= (int32_t)FlipNibble(buffer[13]) * 1000;
    iVal+= (int32_t)FlipNibble(buffer[14]) * 10000;
    iVal+= (int32_t)FlipNibble(buffer[15]) * 100000l;

    retVal = iVal;

    sign = FlipNibble(buffer[16]);

    if (!(sign & 0x04)) {  /* inch */
      if (sign & 0x08)
        retVal+= 0.5;

      retVal = retVal * 2.54;
    }

    if (sign & 0x01)
      retVal *= -1.0;
  }
  if (buffer[5] == 'L') { /*  dro#nL:0xiiiiii012345  in 2's complement*/
    if (strlen(buffer) < 21)
      return _NAN;

    iVal = (int32_t)FlipNibble(buffer[15]);
    iVal+= (int32_t)FlipNibble(buffer[16]) * 16l;
    iVal+= (int32_t)FlipNibble(buffer[17]) * 256l;
    iVal+= (int32_t)FlipNibble(buffer[18]) * 4096l;
    iVal+= (int32_t)FlipNibble(buffer[19]) * 65536l;
    iVal+= (int32_t)FlipNibble(buffer[20]) * 1048576l;

    if (FlipNibble(buffer[20]) & 0x01) {  /* negative */
      iVal = 16777216l - iVal;      /* 16777216 = 2^24 */
      iVal = -iVal;
    }

    retVal = iVal;
  }

  return retVal;
}
