/** @file
 * $Source: /home/cvsmanager/yoda/techmodel/TmtcReader.cpp,v $
 * $Id: TmtcReader.cpp,v 4.0 2005/03/06 04:33:02 kusanagi Exp $
 * $Author: kusanagi $
 * 
 * Implementation of the TmtcReader class.
* ToBeDone:
* Control the CRC for the entire data Packet not just for single records
 */

#include <string>
#include <log4cxx/logger.h>
extern "C" {
#include <sys/time.h>
#include "CRC.h"
}

#include <fstream>
#include "stdio.h"
#include "ReaderAlgorithms.h"

#include "event/tmtc/TmtcRecord.h"

using namespace pamela;
using namespace pamela::techmodel;

static log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(_T("pamela.techmodel.TmtcReader"));

/**
 * Constructor. 
 */
TmtcReader::TmtcReader(void): 
  TechmodelAlgorithm(PacketType::Tmtc, "TechmodelTmtcReader") { 
  logger->debug(_T("Constructor"));
  Tmtc = new TmtcEvent();
}

/**
 * Get a string with the version info of the algorithm.
 */
std::string TmtcReader::GetVersionInfo(void) const {
  return 
    "$Header: /home/cvsmanager/yoda/techmodel/TmtcReader.cpp,v 4.0 2005/03/06 04:33:02 kusanagi Exp $\n";
}

/**
 * Initialize the algorithm with a special run. This will initialize the
 * event reader routines for all packet types.
 */
void TmtcReader::Init(PamelaRun *run) {
  SetInputStream(run);
  run->WriteSubPacket(this, &Tmtc, Tmtc->Class());
}

/**
 * Unpack the Tmtc event from an input file.
 */
void TmtcReader::RunEvent(int EventNumber, long int length) throw (WrongCRCException){

    int i, j;
    char subData[TMTC_SUB_LENGTH];
    char CRCbuff[TMTC_SUBCRC_LENGTH];
    char eventCRC[TMTC_CRC_LENGTH];
    int numRecords = (length-TMTC_CRC_LENGTH)/(TMTC_SUB_LENGTH + TMTC_SUBCRC_LENGTH); //subtract the last two bytes because are the final CRC
    long int start;
    
    TmtcRecord* rec;    
    Tmtc->Records->Clear();
    TClonesArray &recs = *(Tmtc->Records);
    
    UINT16    partialCRC = 0; //partial CRC updated as mcmd packet is read (to compare with the last two bytes of this event)
    UINT16    readCRC = 0;    //partial CRC updated as mcmd packet is read (to compare with the last two bytes of this event)
    for(int i = 0; i < numRecords; i++) {
        start = InputFile->tellg();
        InputFile->read(subData, sizeof(subData));
        InputFile->read(CRCbuff, sizeof(CRCbuff));
        
        partialCRC = CM_Compute_CRC16(partialCRC, (UINT8*)&subData, TMTC_SUB_LENGTH);
        partialCRC = CM_Compute_CRC16(partialCRC, (UINT8*)&CRCbuff, TMTC_SUBCRC_LENGTH);

        //This == CRCBuff is not really parametric take care if have to change the static lengths
        if((UINT8)(CM_Compute_CRC16(0, (UINT8*)&subData, TMTC_SUB_LENGTH)) == (UINT8)CRCbuff[0]){
            rec = new(recs[i]) TmtcRecord(); //add a new TmtcRecord
            rec->TM_RECORD_OBT            = (((UINT32)subData[0]<<24)&0xFF000000) + (((UINT32)subData[1]<<16)&0x00FF0000) +  (((UINT32)subData[2]<<8)&0x0000FF00) + (((UINT32)subData[3])&0x000000FF);
            rec->TM_DIAG_AND_BILEVEL_ACQ  = (((UINT16)subData[4]<<8)&0x0000FF00) + (((UINT16)subData[5])&0x000000FF);
            
            for(int j = 0; j < 12; j++) {
                rec->TM_TH_ANA[j]    = ((((UINT16)subData[6 + 2*j]<<8)&0xFF00) + (((UINT16)subData[7 + 2*j])&0x00FF)); //20 is the size of TM_DEA_ANA(16) + OBT(4)
            }
            
            for(int j = 0; j < 6; j++) {
                rec->TM_DEA_ANA[j]   = subData[30+j];
            }

        } else {
            stringstream oss;
            oss.str("");
            oss << "Wrong CRC on Subpacket int TMTC Packet starting at position"
                << start;
            logger->warn(oss.str().c_str());
        }
    }    
    InputFile->read(eventCRC, sizeof(eventCRC));
    readCRC = (((UINT16)(eventCRC[0]<<8))&0xFF00) + (((UINT16)eventCRC[1])&0x00FF);
    if(partialCRC != readCRC) throw WrongCRCException(" Wrong Global CRC for TMTC Packet ");
}

/*
float TmtcReader::convert_th(int TH) {
  float a,q,deltax,deltay;
  static int chiama_fun=0;
  float gradi[22],grado=-1;
  int adc[22]={4095, 4036,2976,2213,1662,1259,983,742,576,450,
	       354, 281,224,179,145, 117 ,95, 77, 64, 52, 
	       43, 35};
  int maxpos=-1,minpos=-1,i;
  
  chiama_fun++;
  for (i=0;i<22;i++)
    {
      gradi[i]=-35+(i*5);
    }
  if (TH==4095) 
    {
      grado=-35.;
    }
  else
    {
      
      for (i=0;i<22;i++)
	{
	  if (TH>=adc[i]) 
	    {
	      minpos=i;
	      maxpos=i-1;
	      break;
	    }
	}
      //	grado=gradi[maxpos]-1./(adc[maxpos]-adc[minpos])*((float)TH-(float)adc[maxpos]) ;
      
      deltax=adc[maxpos]-adc[minpos];
      deltay=gradi[maxpos]-gradi[minpos];
      a=deltay/deltax;
      q=gradi[maxpos]-a*adc[maxpos];
      grado=a*TH+q;		
    }
  return (grado);
}
*/
