/************************************************************************* $Archive: /pacs/OnBoard/Seq.c $ $Revision: 1.12 $ $Date: 2010/09/29 12:36:11 $ $Author: amazy $ $Log: Seq.c,v $ Revision 1.12 2010/09/29 12:36:11 amazy v6.030 * * 10 9/16/10 4:30p Pacs1 * * 9 16/09/10 9:00 Amazy * enable EDAC at startup * * 8 4/23/09 3:46p Pacs1 * 6.029 * * 6 10/09/08 10:17p Pacs1 * * 5 30/09/08 15:19 Amazy * - increased grating power limit to 150mA and made it commandable * - added a synchro counter in HK * - new parameters value for DMC_SYNCHRONIZE_ON_DET to avoid using the * synchro to trigger the mechanisms move * - In photo, the RedSpuTransmission mode was not copied into red science * headers. It is now corrected * * 140 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 "seq_msg.h" #include "u_bits.h" #include "params.h" #include "error.h" #include "det.h" #include "links.h" #include "l_memory.h" #include "l_pscgen.h" //This had to be included to avoid link errors when we removed the host drivers //and the debug options. //root_netload is the first function called in the main. void root_netload() { }; int WAIT_BOOT_IS_FINISHED = 6000; //time to wait at startup of the software (between the SMCS chip reset and the real start of tasks) //**************************************************************** // INTERRUPT HANDLER DECLARATION //**************************************************************** #ifndef SIMULATOR // no irq in the simulator #include "smcs\basedef.h" __asm("#include ;"); extern void user_isr(); #endif //SIMULATOR //**************************************************************** // LOCAL COMPILATION FLAGS DEFINITION //**************************************************************** #define INCLUDE_DEFAULT_SEQUENCE 1 /**************************************************************** FUNCTIONS DECLARATION ****************************************************************/ // two functions for sending ACK or NACK to the DPU Sender void SequencerSendNack(int param, uint errorCode); void SequencerSendAck(uint commandId); void InterpreteAndExecute(Command command, int mode, int SID); void InitializeSequencer(); int GetDetectorTimeOut(); /*************************************************************************** LIST OF COMMAND FUNCTIONS ***************************************************************************/ // in this file extern BOOL CommandLoop(CommandParameter param); extern BOOL CommandEndOfLoop(CommandParameter param); extern BOOL CommandWaitForRamps(CommandParameter param); extern BOOL CommandEndOfSequence(CommandParameter param); extern BOOL CommandLabel(CommandParameter param); extern BOOL CommandStartSequence(CommandParameter param); extern BOOL CommandStopSequence(CommandParameter param); extern BOOL CommandResumeSequence(CommandParameter param); extern BOOL CommandAbortSequence(CommandParameter param); extern BOOL CommandSetTime(CommandParameter param); extern BOOL CommandSetOBSID(CommandParameter param); extern BOOL CommandSetBBID(CommandParameter param); extern BOOL CommandSynchronizeOnDetector(CommandParameter param); extern BOOL CommandNotImplemented(CommandParameter param); extern BOOL CommandInvalid(CommandParameter param); extern BOOL CommandCopyObsToEeprom(CommandParameter paramNotUsed); // in "BDecCtrl.c" extern BOOL CommandSwitchOnBlueDEC(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffBlueDEC(CommandParameter paramNotUsed); extern BOOL CommandValidateScienceDataBlue(CommandParameter param); extern BOOL CommandInvalidateScienceDataBlue(CommandParameter param); extern BOOL CommandSetBlueSpectroParameters(CommandParameter paramNotUsed); extern BOOL CommandSetBothSpectroParameters(CommandParameter paramNotUsed); extern BOOL CommandValidateScienceDataBoth(CommandParameter param); extern BOOL CommandInvalidateScienceDataBoth(CommandParameter param); extern BOOL CommandSwitchOnBlueSpectroArray(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffBlueSpectroArray(CommandParameter paramNotUsed); extern BOOL CommandSendCommandToBlueDEC(CommandParameter param); extern BOOL CommandSetBlueSpectroHeaterCurrent(CommandParameter param); extern BOOL CommandSetBlueSpectroFlasherCurrent(CommandParameter param); extern BOOL CommandSwOnBlueHeater(CommandParameter paramNotUsed); extern BOOL CommandSwOffBlueHeater(CommandParameter paramNotUsed); extern BOOL CommandSwOnBlueFlasher(CommandParameter paramNotUsed); extern BOOL CommandSwOffBlueFlasher(CommandParameter paramNotUsed); // in "RDecCtrl.c" extern BOOL CommandSwitchOnRedDEC(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffRedDEC(CommandParameter paramNotUsed); extern BOOL CommandValidateScienceDataRed(CommandParameter param); extern BOOL CommandInvalidateScienceDataRed(CommandParameter param); extern BOOL CommandSetRedSpectroParameters(CommandParameter paramNotUsed); extern BOOL CommandSwitchOnRedSpectroArray(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffRedSpectroArray(CommandParameter paramNotUsed); extern BOOL CommandSetRedSpectroHeaterCurrent(CommandParameter param); extern BOOL CommandSetRedSpectroFlasherCurrent(CommandParameter param); extern BOOL CommandSwOnRedHeater(CommandParameter paramNotUsed); extern BOOL CommandSwOffRedHeater(CommandParameter paramNotUsed); extern BOOL CommandSwOnRedFlasher(CommandParameter paramNotUsed); extern BOOL CommandSwOffRedFlasher(CommandParameter paramNotUsed); // in "BolCtrl.c" extern BOOL CommandSendCommandToBOLC(CommandParameter param);; extern BOOL CommandResetBolReadoutCounter(CommandParameter paramNotUsed); // in "DetSim.c" extern BOOL CommandStopDetectorSimulator(CommandParameter param); extern BOOL CommandStartDetectorSimulator(CommandParameter paramNotUsed); // in "ChopCtrl.c" extern BOOL CommandMoveChopperAbsolute(CommandParameter param); extern BOOL CommandMoveChopperRelative(CommandParameter param); extern BOOL CommandMoveChopperAbsoluteWithDither(CommandParameter param); extern BOOL CommandMoveChopperRelativeWithDither(CommandParameter param); extern BOOL CommandSwitchOnChopperController(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffChopperController(CommandParameter paramNotUsed); extern BOOL CommandEnableChopperController(CommandParameter paramNotUsed); extern BOOL CommandDisableChopperController(CommandParameter paramNotUsed); extern BOOL CommandSetCoilDriveMode(CommandParameter param); // in "GratCtrl.c" extern BOOL CommandMoveGratingAbsolute(CommandParameter param); extern BOOL CommandMoveGratingRelative(CommandParameter param); extern BOOL CommandSwitchOnGratingController(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffGratingController(CommandParameter paramNotUsed); extern BOOL CommandEnableGratingController(CommandParameter paramNotUsed); extern BOOL CommandDisableGratingController(CommandParameter paramNotUsed); extern BOOL CommandHomeGrating(CommandParameter param); extern BOOL CommandEnterGratingDegradedMode(CommandParameter param); extern BOOL CommandExitGratingDegradedMode(CommandParameter paramNotUsed); extern BOOL CommandLockGrating(CommandParameter param); extern BOOL CommandUnlockGrating(CommandParameter paramNotUsed); extern BOOL CommandFwGrDacOut(CommandParameter param); // in "pid_ctrl.c" extern BOOL CommandSelectMechControlMode(CommandParameter param); // in "FWCtrl.c" extern BOOL CommandMoveFWSpec(CommandParameter param); extern BOOL CommandMoveFWSpecToLocation(CommandParameter param); extern BOOL CommandMoveFWPhoto(CommandParameter param); extern BOOL CommandMoveFWPhotoToLocation(CommandParameter param); extern BOOL CommandSwitchOnFWSpec(CommandParameter paramNotUsed); extern BOOL CommandSwitchOnFWPhoto(CommandParameter paramNotUsed); // in "CsCtrl1.c" extern BOOL CommandSwitchOnCS1Ctrl(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffCS1Ctrl(CommandParameter paramNotUsed); extern BOOL CommandSetCS1Temp(CommandParameter param); extern BOOL CommandSetCS1Voltage(CommandParameter param); extern BOOL CommandEnableCS1Ctrl(CommandParameter paramNotUsed); extern BOOL CommandDisableCS1Ctrl(CommandParameter paramNotUsed); // in "CsCtrl2.c" extern BOOL CommandSwitchOnCS2Ctrl(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffCS2Ctrl(CommandParameter paramNotUsed); extern BOOL CommandSetCS2Temp(CommandParameter param); extern BOOL CommandSetCS2Voltage(CommandParameter param); extern BOOL CommandEnableCS2Ctrl(CommandParameter paramNotUsed); extern BOOL CommandDisableCS2Ctrl(CommandParameter paramNotUsed); // in "SimChop.c" #ifdef CHOP_SIM extern BOOL CommandStartChopperSimulator(CommandParameter param); extern BOOL CommandStopChopperSimulator(CommandParameter paramNotUsed); #endif //CHOP_SIM // in "HkDiag.c" extern BOOL CommandStartDiagnosticHk(CommandParameter param); extern BOOL CommandStopDiagnosticHk(CommandParameter param); // in "Hk.c" extern BOOL CommandStartHk(CommandParameter param); // in "Mim.c" extern BOOL CommandSetTimingFpgaParameters(CommandParameter param); #ifdef VERBOSE // in "u_verb.c" extern BOOL CommandSetVerboseLevel(CommandParameter param); extern BOOL CommandSetVerboseCategories(CommandParameter param); #endif //VERBOSE // in "SmcsDrv.c" extern BOOL CommandStartRedSpuLink(CommandParameter param); extern BOOL CommandStartBlueSpuLink(CommandParameter param); extern BOOL CommandResetSmcsChip2(CommandParameter paramNotUsed); // in "TempSens.c" extern BOOL CommandSwitchOnTempSensors(CommandParameter paramNotUsed); extern BOOL CommandSwitchOffTempSensors(CommandParameter paramNotUsed); //**************************************************************** // LOCAL PARAMETERS //**************************************************************** //stores the start address (pointer index) of each of the nested loop static uint aSequenceLoopBegin[MAX_NESTED_LOOPS] = {0, 0, 0, 0, 0}; // initialize the InterpreterFunctionArray //**************************************** #undef COMMAND #define COMMAND(CommandId, CommandFunctionPointer, Availability, paramType) CommandFunctionPointer, static SequencerCommandFunction InterpreterFunctionArray[NB_COMMANDS] = { #include "Com_list.h" }; // initialize the FunctionAvailabilityArray //***************************************** #undef COMMAND #define COMMAND(CommandId, CommandFunctionPointer, Availability, paramType) Availability, static int FunctionAvailabilityArray[NB_COMMANDS] = { #include "Com_list.h" }; // initialize the CommandParamDesc //******************************** #undef COMMAND #define COMMAND(CommandId, CommandFunctionPointer, Availability, paramType) paramType, static int CommandParamDesc[NB_COMMANDS] = { #include "Com_list.h" }; //**************************************************************** // FUNCTION IMPLEMENTATION //**************************************************************** /* FUNCTION : int InitAssembly(void* notUsed) ****************************************** AUTHOR : Amazy USE : Initialisation of the interrupt routines. */ int InitAssembly(void* notUsed) { #ifndef SIMULATOR // no irq in the simulator int dmConfBank0; int dmConfBank1; /*switch to alternate registers*/ __asm(" bit set MODE1 SRCU|SRD1H|SRD1L|SRD2H|SRD2L|SRRFH|SRRFL; "); __asm(" nop; "); __asm(" i0=dm(_gpGratingController); "); __asm(" i1=dm(_gpFWSpecController); "); __asm(" i2=dm(_gpFWPhotoController); "); __asm(" i3=dm(_gpChopperController); "); __asm(" i6=dm(_gpHkAnalogMeasures); "); __asm(" i7=0; "); /* i7 is a temporary address register */ __asm(" i15=0; "); /* ISR call counter */ __asm(" i14=0; "); /* spare */ __asm(" i13=0; "); /* spare */ __asm(" i12=0; "); /* spare */ __asm(" i11=0; "); /* spare */ __asm(" i10=0; "); /* rate divider for grating and fw in open loop mode */ __asm(" i9=0; "); /* phase B waveform pointer, initialized at start of open loop move */ __asm(" i8=0; "); /* phase A waveform pointer, initialized at start of open loop move */ /* switch back to primary register set */ /* do not forget to set Virtuoso timer to low priority in configuration */ __asm(" bit clr MODE1 SRCU|SRD1H|SRD1L|SRD2H|SRD2L|SRRFH|SRRFL; "); __asm(" nop;"); //Configure 6 wait states for MIM FPGA accesses dmConfBank1 = *((int*)K_DMADD_DMPSC_CONFBANK1); SET_BITS(dmConfBank1, 0x001E0000, 0x00080000); *((int*)K_DMADD_DMPSC_CONFBANK1) = dmConfBank1; //Enable EDAC on DRAM dmConfBank0 = *((int*)K_DMADD_DMPSC_CONFBANK0); SET_BIT(dmConfBank0, 0x00000004); *((int*)K_DMADD_DMPSC_CONFBANK0) = dmConfBank0; //Enable EDAC on PRAM MEM_WriteBitInPM32bitMSWord(K_PMADD_PMPSC_CONFBANK1, 2, 1); //initialize FPGA WriteFpgaRegisters(); //enable IRQ3 (8KHz interrupt) KS_IRQSetHandler(5, user_isr); // 5 is the bit number of IRQ3 in IMASK __asm(" bit set MODE2 IRQ3E;"); // must be edge sensitive interrupt __asm(" nop;"); KS_ISREnable(5); #endif // not def SIMULATOR return 0; } /* FUNCTION : void InitializeSequencer() ************************************* AUTHOR : AMazy USE : initializes the Sequencer and perform all the global initialization : - link 1355 initializations - initializations of all the parameters (PID, ...) */ void InitializeSequencer() { // initialize all the parameters structure SetParametersDefaultValues(); // wait a certain time to let other system start (mandatory when connecting to a SimDPU) #ifndef SIMULATOR KS_TaskSleep(WAIT_BOOT_IS_FINISHED); #endif // initialize the SequenceBuffer with and empty sequence gParameters.Sequencer.SequenceBuffer[0].Id = DMC_END_SEQUENCE; gParameters.Sequencer.SequenceBuffer[0].Param.Uint = 0; // initialize the task status LOCK_WRITE_RES_PARAMS; gpSequencer->TaskStatus = K_BMASK_TASK_STATUS_ALIVE | K_BMASK_TASK_STATUS_SEQ_IDLE | K_BMASK_TASK_STATUS_NO_ERROR_IN_TASK; gpSequencer->Options = BLUE_SPEC; UNLOCK_WRITE_RES_PARAMS; // initialize the sequencer variables gpSequencer->Pointer = 0; gpSequencer->WaitForRampsIndex = 0; gpSequencer->aCurrentLoopIndex[0] = 0; gpSequencer->aCurrentLoopIndex[1] = 0; gpSequencer->aCurrentLoopIndex[2] = 0; gpSequencer->aCurrentLoopIndex[3] = 0; gpSequencer->aCurrentLoopIndex[4] = 0; gpSequencer->OBSID = 0; gpSequencer->BBID = 0; gpSequencer->TemporaryTime[0] = 0; gpSequencer->TemporaryTime[1] = 0; gpSequencer->Time[0] = 0; gpSequencer->Time[1] = 0; //Initialize other structures InitializeChopperControllerParams(gpChopperController); InitializeGratingControllerParams(gpGratingController); InitializeFwControllerParams(gpFWSpecController); InitializeFwControllerParams(gpFWPhotoController); InitializeFpgaParameters(); InitializeMimParameters(); // intialize hardware related variables KS_CriticalSection(InitAssembly, NULL); } /* FUNCTION : void Seq() ********************* AUTHOR : Amazy USE : Implementation of the Sequencer Task. */ void Seq() { SequencerMsg msg; // used to store the messages received on the FIFO int timeOut = 0; InitializeSequencer(); #ifndef SIMULATOR // start all the other tasks KS_TaskGroupStart(GROUP_DPU); KS_TaskGroupStart(GROUP_BLUE_CHANNEL); KS_TaskGroupStart(GROUP_RED_CHANNEL); KS_TaskGroupStart(GROUP_BOL); KS_TaskGroupStart(GROUP_CS); KS_TaskGroupStart(GROUP_HK); KS_TaskGroupStart(GROUP_SIM_DET); #endif //SIMULATOR //start the communication on 1355 links (init is done in SmcsDrvState) KS_SemaSignal(SEMA_SMCS_DRV_STATE); while (1) { timeOut = GetDetectorTimeOut(); //wait for a message on the FIFO (it can be a SYNCHRO signal or a TRIGGER command) if (KS_FIFOGetWT(SEQUENCER_FIFO, &msg, timeOut) == RC_TIME) { //if we had to wait longuer than timeOut, and if a sequence was being executed, signal an error. LOCK_READ_RES_PARAMS; if (IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING)) { UNLOCK_READ_RES_PARAMS; SetSequencerError(ERR_SEQUENCER_SYNC_TIME_OUT); } else { UNLOCK_READ_RES_PARAMS; } } else { // react according to the message type switch(msg.Type) { case SINGLE_COMMAND_AVAILABLE : { //execute the single command we just received in the message InterpreteAndExecute(msg.Content.Cmd, TRIG, msg.SID); };break; case SEQUENCE_SYNCHRO : { // take the message into account only if a sequence is being executed LOCK_READ_RES_PARAMS; if (IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING)) { UNLOCK_READ_RES_PARAMS; // execute the current command in the sequence InterpreteAndExecute(gpSequencer->SequenceBuffer[gpSequencer->Pointer], IN_SEQ, -1); } else { UNLOCK_READ_RES_PARAMS; } };break; default : SetSequencerError(ERR_SEQUENCER_UNKNOWN_MESSAGE_TYPE); } } } } /* FUNCTION : void InterpreteAndExecute(Command command, int mode, int SID) ************************************************************************ AUTHOR : Amazy USE : Interprets the command and executes it if the command is available in this mode. PARAMS : command : the command identifiers and its parameter mode : the mode in which the command has been received (TRIG if the command was received as a direct command IN_SEQ if the command was in a sequence INT if it was an internal command) SID : the number of parameters attached to the command (used for trigger commands only) RETURN VALUE: TRUE : if the next command in the sequence must be executed right now FALSE : if the next command in the sequence must wait the end of the next ramp to execute. */ void InterpreteAndExecute(Command command, int mode, int SID) { SequencerMsg msg; int commandId = command.Id; //check that the command exists if (commandId >= NB_COMMANDS) { SequencerSendNack(commandId, INVALID_TRIGGER_COMMAND_ID); SetSequencerError(ERR_SEQUENCER_UNKNOWN_COMMAND); return; } //check that the command is available in this operating mode else if (! TEST_ONE_BIT(mode, FunctionAvailabilityArray[commandId])) { SequencerSendNack(0, INVALID_MODE); SetSequencerError(ERR_SEQUENCER_COMMAND_NOT_AVAILABLE_IN_THIS_MODE); return; } else { // If command is valid, execute it. // At this point, we still don't know the type of the argument; // so, we pass a pointer on a void*; the pointer will be cast to the right type // inside the function. LOCK_READ_RES_PARAMS; if (IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING)) { UNLOCK_READ_RES_PARAMS; // we have received a trigger command while a sequence was running if (mode == TRIG) { // if it is an abort sequence, accept it if (commandId == DMC_ABORT_SEQUENCE) { InterpreterFunctionArray[commandId](command.Param); //don't execute the next command in the sequence return; } else // if it is another command reject it and continue the execution of the sequence. { SequencerSendNack(0, INVALID_MODE); return; } } // execute the current command in the sequence if (InterpreterFunctionArray[commandId](command.Param)) { // if the execution of the previous command returned TRUE, // execute the next command else, exit gpSequencer->Pointer++; msg.Type = SEQUENCE_SYNCHRO; KS_FIFOPut(SEQUENCER_FIFO, &msg); } } else { UNLOCK_READ_RES_PARAMS; //execute the single command //first check that the number of parameters received is correct if (((CommandParamDesc[commandId] == PAR_NONE) && (SID == 0)) || ((CommandParamDesc[commandId] != PAR_NONE) && (SID != 0))) { InterpreterFunctionArray[commandId](command.Param); } else { SequencerSendNack(0, INVALID_SID); SetSequencerError(ERR_SEQUENCER_INVALID_SID); return; } } } } /* FUNCTION : void SequencerSendNack(int param, uint8 errorCode) ************************************************************* AUTHOR : Amazy USE : Sends a NACK to the DPU Sender (it will be forwarded to DPU). It is used by the command functions. Note : when a sequence is being executed, ACK and NACK are not sent. PARAMS : errorCode param INVALID_TRIGGER_COMMAND_ID the invalid command Id INVALID_SID the invalid SID INVALID_PARAMETER the invalid parameter INVALID_MODE null */ void SequencerSendNack(int param, uint errorCode) { DpuSenderMsg msg; msg.Header = TRIGGER_NACK; msg.Field1.ErrorCode = errorCode; msg.Field2.Parameter = param; KS_FIFOPut(DPUSENDER_FIFO, &msg); } /* FUNCTION : void SequencerSendAck(uint8 commandId) ************************************************* AUTHOR : Amazy USE : Sends an ACK to the DPU Sender (it will be forwarded to DPU). It is used by the command functions. Note : when a sequence is being executed, ACK and NACK are not sent. PARAMS : commandId : the id of the command that has been accepted */ void SequencerSendAck(uint commandId) { DpuSenderMsg msg; // if we are inside a sequence, we don't send any ACK or NACK LOCK_READ_RES_PARAMS; if (IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING)) { UNLOCK_READ_RES_PARAMS; return; } UNLOCK_READ_RES_PARAMS; msg.Header = TRIGGER_ACK; KS_FIFOPut(DPUSENDER_FIFO, &msg); } /*************************************************************************** LIST OF COMMAND FUNCTIONS ***************************************************************************/ /* CMD_FUNCTION : BOOL CommandLoop(CommandParameter param) ******************************************************* AUTHOR : Amazy USE : Begins a loop (only available inside a sequence) PARAMS : uint p_param : number of times to repeat the loop */ BOOL CommandLoop(CommandParameter param) { // check that nesting level is valid if (gpSequencer->CurrentLoopLevel >= (MAX_NESTED_LOOPS - 1)) { /*generate error*/ SetSequencerError(ERR_SEQUENCER_TOO_MANY_NESTED_LOOPS); return FALSE; } else { //if loop 0 times (or less), find the end of loop and continue. if (param.Uint == 0) { while (gpSequencer->SequenceBuffer[gpSequencer->Pointer].Id != DMC_END_LOOP) { gpSequencer->Pointer++; } // execute first command after the loop return TRUE; } else { gpSequencer->CurrentLoopLevel++; // increment the nesting level of loops // store the number of repetition gpSequencer->aCurrentLoopIndex[gpSequencer->CurrentLoopLevel] = param.Uint; // store the address of the loop command aSequenceLoopBegin[gpSequencer->CurrentLoopLevel] = gpSequencer->Pointer; // execute first command of the loop return TRUE; } } } /* CMD_FUNCTION : BOOL CommandEndOfLoop(CommandParameter paramNotUsed) ******************************************************************* AUTHOR : Amazy USE : Ends a loop (only available inside a sequence) PARAMS : Not used */ BOOL CommandEndOfLoop(CommandParameter paramNotUsed) { // check that nesting level is valid if (gpSequencer->CurrentLoopLevel < 0) { /*generate error*/ SetSequencerError(ERR_SEQUENCER_LOOP_END_OF_LOOP_MISMATCH); return FALSE; } else { // decrement the number of repetition gpSequencer->aCurrentLoopIndex[gpSequencer->CurrentLoopLevel]--; // if we did not reach yet the number of repetition if (gpSequencer->aCurrentLoopIndex[gpSequencer->CurrentLoopLevel] > 0) { // go back to the loop command gpSequencer->Pointer = aSequenceLoopBegin[gpSequencer->CurrentLoopLevel]; } // if we reach the number of repetition else { // we will automatically move to the first command after the end of the loop // decrement the nesting level gpSequencer->CurrentLoopLevel--; } // execute the new current command return TRUE; } } /* CMD_FUNCTION : BOOL CommandEndOfSequence(CommandParameter paramNotUsed) *********************************************************************** AUTHOR : Amazy USE : Last command of a sequence. PARAMS : Not used */ BOOL CommandEndOfSequence(CommandParameter paramNotUsed) { LOCK_WRITE_RES_PARAMS; SET_BITS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_IDLE); UNLOCK_WRITE_RES_PARAMS; return FALSE; } /* CMD_FUNCTION : BOOL CommandStartSequence(CommandParameter paramNotUsed) *********************************************************************** AUTHOR : Amazy USE : Starts the execution of the sequence stored in the SequenceBuffer */ BOOL CommandStartSequence(CommandParameter paramNotUsed) { // if sequencer is not idle, reject the command LOCK_READ_RES_PARAMS; if (! IS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_IDLE)) { UNLOCK_READ_RES_PARAMS; SetSequencerError(ERR_SEQUENCER_COMMAND_NOT_AVAILABLE_IN_THIS_MODE); SequencerSendNack(0, INVALID_MODE); } else // if sequencer was idle { UNLOCK_READ_RES_PARAMS; //reset variables and accept the command gpSequencer->Pointer = 0; gpSequencer->CurrentLoopLevel = -1; gpSequencer->WaitForRampsIndex = 0; gpSequencer->aCurrentLoopIndex[0] = 0; gpSequencer->aCurrentLoopIndex[1] = 0; gpSequencer->aCurrentLoopIndex[2] = 0; gpSequencer->aCurrentLoopIndex[3] = 0; gpSequencer->aCurrentLoopIndex[4] = 0; gpSequencer->Label = 0; // send the ack before modifying the execution status (when status is running, // no ack are sent) SequencerSendAck(DMC_START_SEQUENCE); LOCK_WRITE_RES_PARAMS; SET_BITS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_RUNNING); UNLOCK_WRITE_RES_PARAMS; } return FALSE; }; /* CMD_FUNCTION : BOOL CommandAbortSequence(CommandParameter paramNotUsed) *********************************************************************** AUTHOR : Amazy USE : Abort the execution of the sequence currently executed or suspended. From any state, the sequencer goes in IDLE */ BOOL CommandAbortSequence(CommandParameter paramNotUsed) { LOCK_WRITE_RES_PARAMS; SET_BITS(gpSequencer->TaskStatus, K_BMASK_TASK_STATUS_SEQ_EXECUTION_STATUS, K_BMASK_TASK_STATUS_SEQ_IDLE); UNLOCK_WRITE_RES_PARAMS; SequencerSendAck(DMC_ABORT_SEQUENCE); return FALSE; } /* CMD_FUNCTION : BOOL CommandLabel(CommandParameter param) ******************************************************** AUTHOR : Amazy USE : Change the current label (used to identify the science data) PARAMS : param is a uint8 containing the new label (0-255) */ BOOL CommandLabel(CommandParameter param) { gpSequencer->Label = param.Uint; return TRUE; } /* CMD_FUNCTION : BOOL CommandSetTime(CommandParameter paramNotUsed) ***************************************************************** AUTHOR : Amazy USE : Copy the temporary Time (that has been loaded through a write command before) to the final destination. In the same time, BOLC's and DEC's counters are reset. And, if HkDiagnostic is active, the current packet is sent (since the Time is inserted in the header, each time you modify it, you have to start a new packet). */ BOOL CommandSetTime(CommandParameter paramNotUsed) { // ask the HkDiagnosticController to send its current packet if we are in diagnostic mode. LOCK_READ_RES_PARAMS; if (TEST_ONE_BIT(gpHkDiagnosticController->TaskStatus, K_BMASK_TASK_STATUS_HK_DIAG_DIAGNOSTIC_MODE_ACTIVE)) { UNLOCK_READ_RES_PARAMS; KS_EventSignal(EVENT_HK_DIAG_SEND_PACKET); } else { UNLOCK_READ_RES_PARAMS; } // copy the temporary Time to its final location // TemporaryTime contains : the number of seconds in the first words // and the number of 65535th/sec in the second word (only the 2 LSB are used) (actually, we don't care // since TemporaryTime is written through a write command and simply copied as is in the header) gpSequencer->Time[0] = gpSequencer->TemporaryTime[0]; gpSequencer->Time[1] = gpSequencer->TemporaryTime[1]; // reset the BOLC and DEC counters gpBolRec->ReadoutCounter = 0; gpBlueDecRec->ReadoutCounter = 0; gpRedDecRec->ReadoutCounter = 0; // reset OBT Counter CLEAR_BIT(gpFPGA->ControlRegister, K_BMASK_TIMING_COUNT_ENB); WriteFpgaRegisters(); SET_BIT(gpFPGA->ControlRegister, K_BMASK_TIMING_COUNT_ENB); WriteFpgaRegisters(); SequencerSendAck(DMC_SET_TIME); return FALSE; } /* CMD_FUNCTION : BOOL CommandSetOBSID(CommandParameter param) *********************************************************** AUTHOR : Amazy USE : Modify the OBSID. */ BOOL CommandSetOBSID(CommandParameter param) { //Modify OBSID gpSequencer->OBSID = param.Uint; SequencerSendAck(DMC_SET_OBSID); return FALSE; } /* CMD_FUNCTION : BOOL CommandSetBBID(CommandParameter param) ********************************************************** AUTHOR : Amazy USE : Modify the BBID. */ BOOL CommandSetBBID(CommandParameter param) { //Modify BBID gpSequencer->BBID = param.Uint; SequencerSendAck(DMC_SET_BBID); return FALSE; } /* CMD_FUNCTION : BOOL CommandSynchronizeOnDetector(CommandParameter param) ************************************************************************ AUTHOR : Amazy USE : Select the detector on which the sequencer will synchronize itself. PARAMS : */ BOOL CommandSynchronizeOnDetector(CommandParameter param) { LOCK_WRITE_RES_PARAMS; SET_BITS(gpSequencer->Options, DETECTOR_MASK, param.Uint & 0x00000007); UNLOCK_WRITE_RES_PARAMS; if (param.Uint & 0x000000800) { //modidfy bits in timing FPGA register gpFPGA->SynchroSourceSelection = (param.Uint & 0x00000700) >> 8; } else // use default values { if (param.Uint & 0x00000008) { gpMim->MechanismsUseSynchro = 0; } else { gpMim->MechanismsUseSynchro = 1; } switch (param.Uint & 0x00000007) { case BLUE_SPEC : gpFPGA->SynchroSourceSelection = 3; // use left blue DEC break; case RED_SPEC : gpFPGA->SynchroSourceSelection = 1; // use left red DEC break; case BOL : gpFPGA->SynchroSourceSelection = 5; // use BOLC sync break; default : SequencerSendNack(param.Int, INVALID_PARAMETER); SetSequencerError(ERR_SEQUENCER_INVALID_PARAMETERS); return FALSE; } } WriteFpgaRegisters(); SequencerSendAck(DMC_SYNCHRONIZE_ON_DET); return FALSE; } /* CMD_FUNCTION : BOOL CommandWaitForRamps(CommandParameter param) *************************************************************** AUTHOR : Amazy USE : waits for param ramps and then, passes to the next command PARAMS : Uint : number of ramps to wait for [1..65535] DETAILS : Consider a sequence containing the command WAIT_FOR_RAMPS(5). Since the Sequencer must be able to receive trigger commands at any time, we cannot enter the function, wait for the 5 ramps and then, exit the function. The CommandWaitForRamps function must simply count the number of ramps that the Sequencer still has to wait for. This will be done in the SequenceWaitForRampsIndex variable. This variable is set to 0 by default. */ BOOL CommandWaitForRamps(CommandParameter param) { uint nbRampsToWaitFor = param.Uint; // Note : we can not wait for less than 1 ramp if (nbRampsToWaitFor < 1) { SetSequencerError(ERR_SEQUENCER_INVALID_PARAMETERS); return FALSE; } // if we have not yet waited for enough ramps, increment the counter if (gpSequencer->WaitForRampsIndex != nbRampsToWaitFor) { gpSequencer->WaitForRampsIndex++; return FALSE; } else { // if this is the last ramp, reset the counter and execute the next command // in the sequence. gpSequencer->WaitForRampsIndex = 0; return TRUE; } } /* CMD_FUNCTION : BOOL CommandNotImplemented(CommandParameter paramNotUsed) ************************************************************************ AUTHOR : Amazy USE : If a command is not implemented, this command is called It returns a positive acknowledge PARAMS : Not used */ BOOL CommandNotImplemented(CommandParameter paramNotUsed) { SequencerSendAck(0); //the command ID is actually not used. return FALSE; } /* CMD_FUNCTION : BOOL CommandCopyObsToEeprom(CommandParameter paramNotUsed) ************************************************************************* AUTHOR : Amazy USE : This function copies the PRAM into EEPROM. 2 segments are copied (INIT + PMCODE). The size of segments has been computed on 14/03/2006. A margin is applied in case the code grows in the future. */ BOOL CommandCopyObsToEeprom(CommandParameter paramNotUsed) { int i=0; SequencerSendAck(DMC_COPY_OBS_TO_EEPROM); #ifndef SIMULATOR gParameters.CopyInEepromInProgress = TRUE; //configure the EEPROM wait states (15 ws for writing the EEPROM) PSC_WritePMPSCReg(K_PMADD_PMPSC_CONFBANK1, 0xB21FBF06); //enable writing in EEPROM PSC_SetGPOutput(K_GPOUTPUT_EEPROMWREN,K_LOW); //then, copy the Program Memory into EEPROM (one page at a time) // ******** if you modify the adresses below, you must also update upload_obs files ********** // //copy SEG_INIT for (i=0; i < 0X4000; i+=128) // on 14/03/2006 => 6666 words used { MEM_CopyPMToPM(0x06EE00+i, K_PMADDR_BASE_EEPROM +i, 128); KS_TaskSleep(12); } //copy SEG_PMCO for (i=0x0; i < 0x8000; i+=128) // on 14/03/2006 => 30155 words used { MEM_CopyPMToPM(0x8000+i, K_PMADDR_BASE_EEPROM + 0x8000 + i, 128); KS_TaskSleep(12); } //disable writing in EEPROM PSC_SetGPOutput(K_GPOUTPUT_EEPROMWREN,K_HIGH); gParameters.CopyInEepromInProgress = FALSE; #endif //SIMULATOR return FALSE; } /* FUNCTION : int GetDetectorTimeOut() *********************************** AUTHOR : Amazy This command, returns the time-out that shall be used when waiting for a synchro signal used by the sequencer. In spectro, it takes the theoretical ramp duration and adds a margin. In photo, it takes the theoretical readout interval and adds a margin. */ int GetDetectorTimeOut() { int timeOut = 0; #ifndef SIMULATOR // compute the timeOut value if (IS(gpSequencer->Options, DETECTOR_MASK, BLUE_SPEC)) { if (IS(gpBlueDecRec->TaskStatus, K_BMASK_SIMULATION_DATA, K_BMASK_SIMULATED_READOUTS)) { // when simulating DEC, we take the theoretical value and take a margin of 3ms timeOut = gpDetectorSimulator->Period * gpBlueDecController->DetectorParams.ReadoutsPerRamp + 3; } else { // when using real DEC readouts, // time-out = clockperReadout * readoutPerRamp; (expressed in CRE Clock (8192Hz) // we then divide it by 7 to express it in ms and have a 13% margin // we then add 2 ms such that it's not too tight with small integer values (4-5ms). timeOut = gpBlueDecController->DetectorParams.ClocksPerReadout * gpBlueDecController->DetectorParams.ReadoutsPerRamp / 7 + 2; } } else if (IS(gpSequencer->Options, DETECTOR_MASK, RED_SPEC)) { if (IS(gpRedDecRec->TaskStatus, K_BMASK_SIMULATION_DATA, K_BMASK_SIMULATED_READOUTS)) { // when simulating DEC, we take the theoretical value and take a margin of 3ms timeOut = gpDetectorSimulator->Period * gpRedDecController->DetectorParams.ReadoutsPerRamp+ 3; } else { // when using real DEC readouts, // time-out = clockperReadout * readoutPerRamp; (expressed in CRE Clock (8192Hz) // we then divide it by 7 to express it in ms and have a 13% margin // we then add 2 ms such that it's not too tight with small integer values (4-5ms). timeOut = gpRedDecController->DetectorParams.ClocksPerReadout * gpRedDecController->DetectorParams.ReadoutsPerRamp / 7 + 2; } } else //BOLC { if (IS(gpBolRec->TaskStatus, K_BMASK_SIMULATION_DATA, K_BMASK_SIMULATED_READOUTS)) { // when simulating BOLC, we take the theoretical value and take a margin of 3ms timeOut = gpDetectorSimulator->Period + 3; } else { timeOut = 1200; //supposed to get a readout every 25 to 1000ms; } } #else //SIMULATOR timeOut = 20000; // no real time out when working with the simulator #endif //SIMULATOR //right now, this function need some validation so, we do not need a real time out. timeOut = 20000; return timeOut; }