#include <stdio.h>
#include "MidWaterSampler.h"
#include "DmErrno.h"

MidWaterSampler::MidWaterSampler(const char *name, MicroApp *app)
  : MicroSampler(name, app)
{
  Int16 board;

  // Up-cast MicroApp pointer to MidwaterApp pointer
  _midwaterApp = (MidWaterApp *) _app;

  addCallback(2.0, (CallbackMethod) &MidWaterSampler::callback);
  addCallback(0.5, (CallbackMethod) &MidWaterSampler::humidityCallback);
  addCallback(10.0, (CallbackMethod) &MidWaterSampler::atodCallback);
  addCallback(10.0, (CallbackMethod) &MidWaterSampler::digitalInputCallback);

  initIbcCpuProvider(&_midwaterApp->dmItems->ibcDm, HUMIDITY_DM_PERIOD);


  initIbcGf5vProvider(&_midwaterApp->dmItems->gf5vDm, MWSLED_IBC_DM_PERIOD);

  for(board=0; board < LPS_BOARDS; board++)
     initIbcLpsProvider(&_midwaterApp->dmItems->lpsDm[board],
                        MWSLED_IBC_DM_PERIOD);

  for(board=0; board < HPS_BOARDS; board++)
     initIbcHpsProvider(&_midwaterApp->dmItems->hpsDm[board],
                        MWSLED_IBC_DM_PERIOD);

  initIbcVicorProvider(_midwaterApp->dmItems->vicorDm, MWSLED_IBC_DM_PERIOD);

  Errno err;
  char errorBuf[errorMsgSize];

  _midwaterApp->dmItems->portSwingArmPosition->startProvide(ATOD_PERIOD,
      ExclusiveProvider);
  _midwaterApp->dmItems->stbdSwingArmPosition->startProvide(ATOD_PERIOD,
      ExclusiveProvider);
  _midwaterApp->dmItems->spareADChannel0->startProvide(ATOD_PERIOD,
      ExclusiveProvider);
  _midwaterApp->dmItems->spareADChannel1->startProvide(ATOD_PERIOD,
      ExclusiveProvider);

  if ((err = _midwaterApp->dmItems->ssIndexSense->startProvide(DM_ASYNC,
      ExclusiveProvider)) != SUCCESS)
  {
      sprintDmError(err, "ssIndexSense->startProvide()", errorBuf);
      fprintf(stderr, "%s\n", errorBuf);
  }
  lastSSIndexSense = initIndexSense(_midwaterApp->sio32Interface->channel(),
                  _midwaterApp->dmItems);

}

MidWaterSampler::~MidWaterSampler()
{
}

void MidWaterSampler::callback()
{
  Int16 board;

  setError("MidWaterSampler::callback()\n");

  updateNewIbcGf5vDm(_midwaterApp->sio32Interface->channel(),
                     GF5V_BOARD_ADDR, &_midwaterApp->dmItems->gf5vDm);

  updateIbcVicorDm(_midwaterApp->sio32Interface->channel(),
                   VICOR_BOARD_ADDR, _midwaterApp->dmItems->vicorDm);

  for(board = 0; board< HPS_BOARDS; board++)
     updateIbcHpsDm(_midwaterApp->sio32Interface->channel(),
                    hpsBoardAddr[board],
                    &_midwaterApp->dmItems->hpsDm[board]);

  for(board = 0; board< LPS_BOARDS; board++)
     updateIbcLpsDm(_midwaterApp->sio32Interface->channel(),
                    lpsBoardAddr[board],
                    &_midwaterApp->dmItems->lpsDm[board]);
 return;
}

void MidWaterSampler::humidityCallback()
{
 updateIbcHumidityDm(_midwaterApp->sio32Interface->channel(),
                  _midwaterApp->dmItems->ibcDm.microHumidity);
 return;
}

void MidWaterSampler::atodCallback()
{
 updateAtoDValues(_midwaterApp->sio32Interface->channel(),
                  _midwaterApp->dmItems);
 return;
}

void MidWaterSampler::digitalInputCallback()
{
 updateInputValue(_midwaterApp->sio32Interface->channel(),
                  _midwaterApp->dmItems);
 return;
}


    STATUS
MidWaterSampler::updateAtoDValues( sio32Chan *serialChan,
    MwsledDconDmItems *dmItems)
{
    Int16 portSwingArmPot, stbdSwingArmPot;
    Int16 spareAtoD0, spareAtoD1;

    Int16   cmdStatus;              // Command Status
    Word    reply[5];               // Command Result from microcontroller
    Int16   value;

    DM_Time t;
                                    // Send command to MWSLED IBC micro
    if ( sendMicroCommand( serialChan, &reply, sizeof(Word) * 5,
         1, MIDWATER_SLED_APP | GET_ATOD_DATA) == ERROR )
     return(ERROR);

                                    // Check if command result is CMD OK
    if (wordFromBuf(&reply, 0) != CMD_OK)
        return(ERROR);              // Command failed so return ERROR

                                    // Command OK so update analog Channels
    wordsFromBuf(reply, 5, &cmdStatus,  &portSwingArmPot, &stbdSwingArmPot,
         &spareAtoD0, &spareAtoD1);

    gettimeofday(&t, NULL);

   // Debug Code To Write Raw Values
   // dmItems->portSwingArmPosition->write(portSwingArmPot, &t);
   // dmItems->stbdSwingArmPosition->write(stbdSwingArmPot, &t);

    // Convert To Degrees And Update DM Items
    value = BITS_TO_DEGS(portSwingArmPot);
    dmItems->portSwingArmPosition->write(value, &t);

    value = BITS_TO_DEGS(stbdSwingArmPot);
    dmItems->stbdSwingArmPosition->write(value, &t);

    // Write Raw Values To Spare Channels
    dmItems->spareADChannel0->write(spareAtoD0, &t);

    dmItems->spareADChannel1->write(spareAtoD1, &t);

    return(OK);
} // updateAtoDValues()

    STATUS
MidWaterSampler::updateInputValue( sio32Chan *serialChan,
    MwsledDconDmItems *dmItems)
{
    Word portWord;
    MBool ssIndexSense;

    Int16   cmdStatus;              // Command Status
    Word    reply[2];               // Command Result from microcontroller

                                    // Send command to MWSLED IBC micro
    if ( sendMicroCommand( serialChan, &reply, sizeof(Word) * 2,
         2, IBC_CPU_APP | ISO_IO_READ_PORT, ISOLATED_IO_BOARD_0_ADDR) == ERROR )

   return(ERROR);

                                    // Check if command result is CMD OK
    if (wordFromBuf(&reply, 0) != CMD_OK)
        return(ERROR);              // Command failed so return ERROR

                                    // Command OK so Update Port Word
    wordsFromBuf(reply, 2, &cmdStatus, &portWord);
                                    // Check Which Bit is Set
                                    // SS Index is the fist bit
    ssIndexSense = ((portWord & SS_INDEX_SENSE_BIT) ? TRUE : FALSE);
                                    // If Index State Changed
    if (ssIndexSense != lastSSIndexSense)
    {                               // Update Data Manager
       if(writeDmItem(dmItems->ssIndexSense->getHandle(),
                   &ssIndexSense, sizeof(ssIndexSense))==ERROR)
       {                            // report Errror if Failed
         logMsg("updateInputValue:writeDmItem failed for ssIndexSense\n");
         return(ERROR);
       }                            // Update Last State
       lastSSIndexSense = ssIndexSense;
    }
    return(OK);
} // updateInputValue()

    MBool
MidWaterSampler::initIndexSense( sio32Chan *serialChan,
    MwsledDconDmItems *dmItems)
{
    Word portWord;
    MBool ssIndexSense;

    Int16   cmdStatus;              // Command Status
    Word    reply[2];               // Command Result from microcontroller

                                    // Send command to MWSLED IBC micro
    if ( sendMicroCommand( serialChan, &reply, sizeof(Word) * 2,
         2, IBC_CPU_APP | ISO_IO_READ_PORT, ISOLATED_IO_BOARD_0_ADDR) == ERROR )

    return(ERROR);

                                    // Check if command result is CMD OK
    if (wordFromBuf(&reply, 0) != CMD_OK)
        return(ERROR);              // Command failed so return ERROR

                                    // Command OK so update Port Word
    wordsFromBuf(reply, 2, &cmdStatus, &portWord);
                                    // Check If SS Index Bit is Set
    ssIndexSense = ((portWord & SS_INDEX_SENSE_BIT) ? TRUE : FALSE);
                                    // Update DM Item
    writeDmItem(dmItems->ssIndexSense->getHandle(),
                   &ssIndexSense, sizeof(ssIndexSense));
                                    // Return State
    return(ssIndexSense);
} // initIndexSense()



