/************************************************************************* $Archive: /pacs/OnBoard/HkDiag.c $ $Revision: 1.11 $ $Date: 2009/04/23 13:51:12 $ $Author: amazy $ $Log: HkDiag.c,v $ Revision 1.11 2009/04/23 13:51:12 amazy 6.029 * * 7 4/23/09 3:46p Pacs1 * 6.029 * * 71 3/14/06 4:32p Pacs Egse * Version 6.001 * Cleaned and commented *************************************************************************/ #ifdef SIMULATOR #include "virtuosoSim.h" #else // SIMULATOR #include "v_macro.h" #include "node1.h" #include "k_struct.h" #endif #include "params.h" #include "error.h" #include "u_bits.h" #include "det.h" #include "u_res.h" //**************************************************************** // MACRO //**************************************************************** //macro to signal an error in HK Diag Controller Task #define SetError(newError) \ {\ SetGlobalError(newError);\ LOCK_WRITE_RES_PARAMS;\ SET_BITS(gpHkDiagnosticController->TaskStatus, K_BMASK_TASK_STATUS_ERROR_STATUS | K_BMASK_TASK_STATUS_ERROR_CODE, K_BMASK_TASK_STATUS_TASK_IN_ERROR + newError); \ UNLOCK_WRITE_RES_PARAMS;\ }\ //**************************************************************** // LOCAL PARAMETERS //**************************************************************** static DpuSenderMsg DpuSendMsg; // used to send messages to DpuSender static int NbMeasureBySample = 0; static int SizeOfSample = 0; static int NbSamples = 0; static int CurrentSizeOfHkDiagBufferInBytes = SIZE_OF_HK_DIAG_PACKET_HEADER_IN_BYTES; // place current position after header static K_TIMER* gpHkDiagnosticTimer = NULL; //**************************************************************** // GLOBAL PARAMETERS //**************************************************************** // there are two buffers used to store the diagnostic hk. By this // way, one can be filled by the HkDiagnosticController while the other // is being sent by the DpuSender. int gaaHkDiagPacketBuffer[2][MAXIMUM_SIZE_OF_HK_DIAG_PACKET_IN_WORDS]; int gCurrentHkDiagPacketBuffer = 0; //**************************************************************** // FUNCTION DECLARATION //**************************************************************** void InitializeHkDiagnosticController(); void HkDiag(); void HkDiagSendPacket(); void HkDiagFillHeader(); // commands function BOOL CommandStartDiagnosticHk(CommandParameter param); BOOL CommandStopDiagnosticHk(CommandParameter param); //**************************************************************** // FUNCTION IMPLEMENTATION //**************************************************************** /* FUNCTION : void InitializeHkDiagnosticController() ************************************************** AUTHOR : AMazy USE : Initializes the Hk Diagnostic Controller task */ void InitializeHkDiagnosticController() { // initialize task status LOCK_WRITE_RES_PARAMS; gpHkDiagnosticController->TaskStatus = K_BMASK_TASK_STATUS_ALIVE | K_BMASK_TASK_STATUS_NO_ERROR_IN_TASK; UNLOCK_WRITE_RES_PARAMS; CurrentSizeOfHkDiagBufferInBytes = SIZE_OF_HK_DIAG_PACKET_HEADER_IN_BYTES; // initialize msg sent to DpuSender (its type is always the same) DpuSendMsg.Header = HK_DIAG_PACKET; // the list is empty by default gpHkDiagnosticController->HkDiagList[0] = END_OF_HK_LIST; // create the timer : gpHkDiagnosticTimer = KS_LowTimerGet(); if (gpHkDiagnosticTimer == NULL) { SetError(ERR_HK_DIAG_COULD_NOT_CREATE_HK_DIAG_TIMER); #ifndef SIMULATOR KS_TaskAbort(HKDIAG); #endif //SIMULATOR } } /* TASK_FUNCTION : void HkDiag() ***************************** AUTHOR : AMazy */ void HkDiag() { InitializeHkDiagnosticController(); while (1) { KS_SemaTestW(SEMA_TIMER_HOUSEKEEPING_DIAGNOSTIC); // if sequencer has received a command to stop the diagnostic HK if (KS_EventTest(EVENT_HK_DIAG_STOP) == RC_OK) { // stops the old timer if there were one. if (gpHkDiagnosticController->HkDiagnosticPeriod > 0) { KS_LowTimerStop(gpHkDiagnosticTimer); } // reset diagnostic period so, if the housekeeping is synchronized with the readouts // of one of the detector, the DecReceiver and the BolReceiver stops signaling the // SEMA_TIMER_HOUSEKEEPING_DIAGNOSTIC each time they receive a readout. gpHkDiagnosticController->HkDiagnosticPeriod = 0; gpHkDiagnosticController->HkDiagnosticPeriodCommanded = 0; // diagnostic mode is no longer active LOCK_WRITE_RES_PARAMS; CLEAR_BIT(gpHkDiagnosticController->TaskStatus, K_BMASK_TASK_STATUS_HK_DIAG_DIAGNOSTIC_MODE_ACTIVE); UNLOCK_WRITE_RES_PARAMS; // sends the current (and last) packet to the DPU HkDiagSendPacket(); } else { // if sequencer forces the sending of the current packet (i.e : because SequenceID has changed) if (KS_EventTest(EVENT_HK_DIAG_SEND_PACKET) == RC_OK) { // sends the current packet to the DPU HkDiagSendPacket(); } // normal behaviour : perform the acquisition // if this is the first sample of the packet, fill the header // Its important to set it at the beginning since it may change at any time // and it is used as a time reference. if (NbSamples == 0) { HkDiagFillHeader(); } PerformHkAcquisitions( HK_DIAG, &(gpHkDiagnosticController->TaskStatus), gpHkDiagnosticController->HkDiagList, &(gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][0]), &CurrentSizeOfHkDiagBufferInBytes, MAXIMUM_SIZE_OF_HK_DIAG_PACKET_IN_BYTES ); NbSamples++; // if there is no place for next acquisition in the HkDiagPacketBuffer, send the packet now // or if we receive the order to send it now (i.e. because we stopped the diagnostic HK) if (((CurrentSizeOfHkDiagBufferInBytes + SizeOfSample) >= MAXIMUM_SIZE_OF_HK_DIAG_PACKET_IN_BYTES)) { HkDiagSendPacket(); } } } }; /* FUNCTION : void HkDiagSendPacket() ********************************** AUTHOR : AMazy USE: This function is used to send the gHkDiagPacket to the DPU. It is used when : - the buffer is full - the Diagnostic acquisition is stopped (in this case, it is called by the sequencer) - the Sequence ID is changed (since the SequenceId (in combination with readout counter) is the normal way to identify the diagnostic acquisition, each time we modify it, we start a new packet). */ void HkDiagSendPacket() { // if the packet is empty, do not send it if (NbSamples < 1) { return; } //NOTE : HkDiagnosticController never waits that the DpuSender has actually sent the last // buffer that has been filled. Since we are working with two buffers, we assume that // DpuSender has enough time to send one buffer while the HkDiagnostic controller is filling // the other one. DpuSendMsg.Field1.Length = (CurrentSizeOfHkDiagBufferInBytes+3)/4 -2; // convert SizeInBytes to SizeInWords and round to upper size (this explains the "+3"); "-2" because we don't take the 2 first words into account for the length computation DpuSendMsg.Field2.BufferToSend = gCurrentHkDiagPacketBuffer; // the header has been filled when the HkDiag started except the NbSamples field. gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][5] += NbSamples; // change buffer and reset the size counter gCurrentHkDiagPacketBuffer = (gCurrentHkDiagPacketBuffer+1) %2; CurrentSizeOfHkDiagBufferInBytes = SIZE_OF_HK_DIAG_PACKET_HEADER_IN_BYTES; // place current position after header NbSamples = 0; //signal DPU Sender that a new HkDiagPacket is available KS_FIFOPut(DPUSENDER_FIFO, &DpuSendMsg); }; /* FUNCTION : void HkDiagFillHeader() ********************************** AUTHOR : AMazy USE: This function is used to fill the header of the HkDiag packet before starting to fill it. This is important to fill the header at the beginning of the acquisition since most of the fields are used as time references. */ void HkDiagFillHeader() { int i=0; int nbMeasures = 0; //count the number of measures in the current HK_DIAG_LIST while (gpHkDiagnosticController->HkDiagList[nbMeasures] != END_OF_HK_LIST) { nbMeasures++; } // fill in the header gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][2] = gpSequencer->OBSID; gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][3] = gpSequencer->BBID; gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][4] = gpSequencer->Time[0]; gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][5] = (gpSequencer->Time[1] << 16) + (nbMeasures << 8); //nb samples will be filled when we send the packet gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][6] = gpBlueDecRec->ReadoutCounter; gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][7] = gpRedDecRec->ReadoutCounter; gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][8] = gpMim->PeriodCount; if (gpHkDiagnosticController->HkDiagnosticPeriod == 0) { gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][9] = -gpHkDiagnosticController->HkDiagnosticPeriodCommanded; } else { gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][9] = gpHkDiagnosticController->HkDiagnosticPeriod; } // copy the List of measures in the next 4 words for (i=0; i < 8; ++i) { gaaHkDiagPacketBuffer[gCurrentHkDiagPacketBuffer][10+i] = (gpHkDiagnosticController->HkDiagList[2*i] << 16) | (gpHkDiagnosticController->HkDiagList[2*i+1]); } } /* CMD_FUNCTION : BOOL CommandStartDiagnosticHk(CommandParameter param) ******************************************************************** AUTHOR : Amazy USE : Start a diagnostic acquisition (we assume the HK list have been written by DPU before). PARAMS : Uint : new period (in ms) with the following special values : BLUE_SPEC RED_SPEC BOL */ BOOL CommandStartDiagnosticHk(CommandParameter param) { // check parameters validity if (param.Uint > 65535) { SequencerSendNack(param.Uint, INVALID_PARAMETER); SetSequencerError(ERR_SEQUENCER_INVALID_PARAMETERS); return FALSE; } if (TEST_ONE_BIT(gpHkDiagnosticController->TaskStatus, K_BMASK_TASK_STATUS_HK_DIAG_DIAGNOSTIC_MODE_ACTIVE)) { SequencerSendNack(param.Uint, COULD_NOT_EXECUTE_COMMAND); SetSequencerError(ERR_SEQUENCER_COULD_NOT_EXECUTE_COMMAND); return FALSE; } //keep a record of the command to report in the header of the packet gpHkDiagnosticController->HkDiagnosticPeriodCommanded = param.Uint; // note in the status that the diagnostic mode is now active LOCK_WRITE_RES_PARAMS; SET_BIT(gpHkDiagnosticController->TaskStatus, K_BMASK_TASK_STATUS_HK_DIAG_DIAGNOSTIC_MODE_ACTIVE); UNLOCK_WRITE_RES_PARAMS; // counts the number of measure in a sample (and the size of a sample) GetSizeOfSample(gpHkDiagnosticController->HkDiagList, &SizeOfSample, &NbMeasureBySample); //reset the current pointer in the hk diag packets NbSamples = 0; CurrentSizeOfHkDiagBufferInBytes = SIZE_OF_HK_DIAG_PACKET_HEADER_IN_BYTES; if (param.Uint == 0) { gpHkDiagnosticController->HkDiagnosticPeriod = 1; // timer has been allocated, we can initialize it (we assume that TICKFREQ = 1000) KS_LowTimerStart(gpHkDiagnosticTimer, gpHkDiagnosticController->HkDiagnosticPeriod, gpHkDiagnosticController->HkDiagnosticPeriod, SEMA_TIMER_HOUSEKEEPING_DIAGNOSTIC); } else { // copy the new period gpHkDiagnosticController->HkDiagnosticPeriod = param.Uint; // if the new period is not one of the special values if (gpHkDiagnosticController->HkDiagnosticPeriod > BOL) { // timer has been allocated, we can initialize it (we assume that TICKFREQ = 1000) KS_LowTimerStart(gpHkDiagnosticTimer, gpHkDiagnosticController->HkDiagnosticPeriod, gpHkDiagnosticController->HkDiagnosticPeriod, SEMA_TIMER_HOUSEKEEPING_DIAGNOSTIC); } else { gpHkDiagnosticController->HkDiagnosticPeriod = 0; // if the new period is one of the special values, //do nothing (it will be done in DecReceiver and BolReceiver). } } SequencerSendAck(DMC_START_DIAG_HK); return TRUE; } /* CMD_FUNCTION : BOOL CommandStopDiagnosticHk(CommandParameter paramNotUsed) ************************************************************************** AUTHOR : Amazy USE : Stop a diagnostic acquisition. PARAMS : Not used. */ BOOL CommandStopDiagnosticHk(CommandParameter paramNotUsed) { // ask the HkDiagController to stop itself at next acquisition KS_EventSignal(EVENT_HK_DIAG_STOP); // trigger the next acquisition KS_SemaSignal(SEMA_TIMER_HOUSEKEEPING_DIAGNOSTIC); SequencerSendAck(DMC_STOP_DIAG_HK); return TRUE; }