#include "archinc.h"
#include "config.h"
#include "v2xeprot.h"

#ifdef CONFIG_INCLUDE_V2XE

//
// V2XE compass protocol driver
//

v2xeDataType dataTypeByCID[10] = { NoType, SInt32, SInt32, Float32, Float32, Float32, Float32, Float32, Boolean, Boolean };
v2xeDataType dataTypeByPID[8] = { NoType, Float32, Boolean, UInt8, UInt8, UInt8, Boolean, UInt8 };
v2xeDataType calRespDataTypes[7] = {UInt8, SInt32, SInt32, SInt32, SInt32, Float32, Float32};

int v2xeprotInit(void)
{
  spiprotRegisterProtocol();
  return 0;
}

static int validateFrameType(char frameType, int bufferIndex)
{
  int retVal = SPIPROT_FRAME_TYPE_INVALID;
  
    switch(frameType) {
      case V2XE_FTYPE_MODINFORESP:
        retVal = SPIPROT_FRAME_TYPE_VALID;
        break;
      case V2XE_FTYPE_DATARESP:
        retVal = SPIPROT_FRAME_TYPE_VALID;
        break;
      case V2XE_FTYPE_CONFIGRESP:
        retVal = SPIPROT_FRAME_TYPE_VALID;
        break;
      case V2XE_FTYPE_CALDATARESP:
        retVal = SPIPROT_FRAME_TYPE_VALID;
        break;
      default:
        // unexpected frame type: return to sync seek state
        break;
      } /* switch(receivedData) */
}

void processConfigResponse(char *pFrame, int frameSize)
{
  char configParam = *pFrame++;
  frameSize--;
  
  switch(configParam) {
    case V2XE_PID_DECLINATION
      break;
    case V2XE_PID_TRUENORTH
      break;
    case V2XE_PID_CALSAMPLEFREQ
      break;
    case V2XE_PID_SAMPLEFREQ
      break;
    case V2XE_PID_PERIOD
      break;
    case V2XE_PID_BIGENDIAN
      break;
    case V2XE_PID_DAMPINGSIZE
      break;  
    default:
      break;
  }
  
  return;
}

void processCalDataResponse(char *pFrame, int frameSize)
{
  char byteCount = *pFrame++;
  frameSize--;
  
  spiparseSInt32(pFrame,);
}

void processDataComponents(char *pFrame, int frameSize, char componentCount)
{
  int i;
  char componentType;
  boolean boolResult;
  float floatResult;
  long int sint32Result;
  
  for(i=0;((i<(int)componentCount) && (frameSize > 0));i++) {
    // first, decode the component type
    componentType = *pFrame++;
    frameSize--;
    
    // now decode the component data
    switch(componentType) {
      case V2XE_CID_XRAW:
        sint32Result = spiparseSInt32(pFrame, );
        pFrame += 4;
        frameSize -= 4;
        // TODO: update data snapshot with result
        break;
      case V2XE_CID_YRAW:
        sint32Result = spiparseSInt32();
        pFrame += 4;
        frameSize -= 4;
        // TODO: update data snapshot with result
        break;
      case V2XE_CID_XCAL:
        floatResult = spiparseParseFloat32(char * pInBytes, int numBytes);
        pFrame += 4;
        frameSize -= 4;
        // TODO: update data snapshot with result
        break;
      case V2XE_CID_YCAL:
        floatResult = spiparseParseFloat32(char * pInBytes, int numBytes);
        pFrame += 4;
        frameSize -= 4;
        // TODO: update data snapshot with result
        break;
      case V2XE_CID_HEADING:
        floatResult = spiparseParseFloat32(char * pInBytes, int numBytes);
        pFrame += 4;
        frameSize -= 4;
        // TODO: update data snapshot with result
        break;
      case V2XE_CID_MAGNITUDE:
        floatResult = spiparseParseFloat32(char * pInBytes, int numBytes);
        pFrame += 4;
        frameSize -= 4;
        // TODO: update data snapshot with result
        break;
      case V2XE_CID_TEMPERATURE:
        floatResult = spiparseParseFloat32(char * pInBytes, int numBytes);
        pFrame += 4;
        frameSize -= 4;
        // TODO: update data snapshot with result
        break;
      case V2XE_CID_DISTORTION:
        boolean result = spiparseParseBoolean(char * pInBytes, int numBytes);
        pFrame += 1;
        frameSize -= 1;
        // TODO: update data snapshot with result
        break;
      case V2XE_CID_CALSTATUS:
        boolean result = spiparseParseBoolean(char * pInBytes, int numBytes);
        pFrame += 1;
        frameSize -= 1;
        // TODO: update data snapshot with result
        break;
      default:
        break;
      } // switch
    } // for
      
  return;
}

void processConfigResponse(pFrame)
{
  return;
}

void processCalDataResponse(pFrame)
{
  return;
}

static void processFrame(char frameType, int frameIndex, int frameSize, char * pFrame)
{
    switch(frameType) {
      case V2XE_FTYPE_MODINFORESP:
        break;
      case V2XE_FTYPE_DATARESP:
        componentCount = *pFrame++;
        frameSize--;
        processDataComponents(pFrame, frameSize, componentCount);
        // TODO: return buffer
        break;
      case V2XE_FTYPE_CONFIGRESP:
        processConfigResponse(pFrame);
        break;
      case V2XE_FTYPE_CALDATARESP:
        processCalDataResponse(pFrame);
        break;
      default:
        // unexpected frame type: return to sync seek state
        break;
      } /* switch(receivedData) */
  
}

int v2xeSendGetModInfo(void)
{
  return spiprotSendSimpleCommand(V2XE_FTYPE_GETMODINFO);
}

int v2xeSendSaveConfig(void)
{
  return spiprotSendSimpleCommand(V2XE_FTYPE_SAVECONFIG);
}

int v2xeSendStartCal(void)
{
  return spiprotSendSimpleCommand(V2XE_FTYPE_STARTCAL);
}

int v2xeSendStopCal(void)
{
  return spiprotSendSimpleCommand(V2XE_FTYPE_STOPCAL);
}

int v2xeSendGetCalData(void)
{
  return spiprotSendSimpleCommand(V2XE_FTYPE_GETCALDATA);
}

int v2xeSendGetConfig(unsigned char cfgParam)
{
  spiprotSendByte(SPIPROT_SYNC);
  spiprotSendByte(V2XE_FTYPE_GETCONFIG);
  spiprotSendByte(cfgParam);
  spiprotSendByte(SPIPROT_TERMINATOR);
  
  return 0;
}

#endif /* CONFIG_INCLUDE_V2XE */
