// $RCSfile: hs_hdl.c,v $Revision: 1.47 $Date: 2005/03/11 15:08:57 //! Contains task hs_hdl which executes many OBS commands and specifically all commands requiring interaction with the HS subsystem #include "hs_hdl.dox" #include "allnodes.h" #include "node1.h" #include "configura.h" #include "pubfuncs.h" #include "cmd_exec.h" #include "cmd_seq.h" #include "hs0.h" #include "ls.h" #include "tables.h" #include "err_hdl.h" #include "data_hdl.h" #include "hs_lib.h" #include "mem_serv.h" #include "vm_lib.h" #include "time_tsk.h" #include "hs0.h" #include "hs_hdl.h" #include "MM_MISC.h" //------------------------- Local functions ------------------------------------ int wbs_att_set (int aid, int command_number); int mkstep_tune_mixer_magnet (unsigned int, int); int wbs_calibration_step2 (int); int spec_wbs_zero (int, int); int mkstep_dip_scan_if (int); void task_hs_hdl_sleep (unsigned int sleep_time); //----------------------- local variables -------------------------------------- static K_TIMER * hs_hdl_Timer; //!< timer used in function task_hs_hdl_sleep() //---------------------- Global variables -------------------------------------- // note: these two semaphores are to be accessed only by functions task_hs_hdl_sleep(), // task_ls_hdl_sleep() and by the calls to KS_SemaGroupSignal() placed in cmd_seq task // in order to interrupt a possible sleep state. K_SEMA Sema_Wait_Group[] = {HS_HDL_WAIT_SEMA, LS_HDL_WAIT_SEMA, ENDLIST}; //!< semaphores on which the hs_hdl and ls_hdl tasks are put in wait int current_command_number = 0; //!< progressive number labeling the current command int fifo_0_pending_frames = 0; //!< counter of the frames for this fifo still being processed by the OBS HS system int fifo_1_pending_frames = 0; //!< counter of the frames for this fifo still being processed by the OBS HS system int fifo_2_pending_frames = 0; //!< counter of the frames for this fifo still being processed by the OBS HS system int fifo_3_pending_frames = 0; //!< counter of the frames for this fifo still being processed by the OBS HS system int fifo_0_command_number = 0; //!< command number for which the last frame was requested int fifo_1_command_number = 0; //!< command number for which the last frame was requested int fifo_2_command_number = 0; //!< command number for which the last frame was requested int fifo_3_command_number = 0; //!< command number for which the last frame was requested int abort_is_running = 0; //!< if equal to 1 an abort_measurement command is running int perform_goto_safe_after_abort = 0; //!< if equal to 1 a goto_safe is performed at end of abort // some variables for mixer_magnet_tuning and diplexer scan int mixer_magnet_data[MAX_MIXMAG_DATA]; //!< to store the data that must be put in a mixer magnet tuning report int dip_scan_if_data[MAX_DIPSCAN_DATA]; //!< to store the data that must be put in a diplexer scan with ifpower report int mixer_mag_steps_performed; //!< counts the steps of a mixer magnet tuning procedure: it is useful for function mkstep_tune_mixer_magnet() int dip_scan_if_cur_step; //!< counts (starting from zero) the steps of a dip scan with ifpower: used in diplexer_scan_if_step() //----------------------- task hs_hdl ------------------------------------------ //! Get a pkt from the HS_HDL_QUEUE, check if it is relative to the currently running command and, if yes, calls the appropriate processing function void hs_hdl (void) { HS_HDL_MSG cmd_in_queue; int ret_val; // to store the return value from functions calls hs_hdl_Timer = KS_LowTimerGet(); // allocate a timer while (1) { // get the command from the queue if (KS_FIFOGetW(HS_HDL_QUEUE, &cmd_in_queue) != RC_OK) continue; // check if the command is obsolete, if yes free the possible block and drop it if ( cmd_in_queue.command_number != current_command_number ) { // free the block if loaded if (cmd_in_queue.block_loaded == 1) release_block(&(cmd_in_queue.block)); continue; } // switch on the operation id switch (cmd_in_queue.operation_id) { /* ----------------------------------------------------- abort -- */ case START_ABORT: // abort function case START_MEM_ABORT_DUMP: // abort function ret_val = start_abort(&cmd_in_queue); break; /* ------------------------------------------------ new_wbs_calibrate -- */ case START_NEW_CALIB_INIT: // start of new wbs calibrate init ret_val = start_new_calib_init(&cmd_in_queue); break; case MKSTEP_NEW_CALIB_INIT: // step of init of new calibrate ret_val = mkstep_new_calib_init(cmd_in_queue.command_number); break; case START_NEW_CALIB_RUN: // start of run of new calibrate ret_val = start_new_calib_run(cmd_in_queue.command_number); break; case MKSTEP_NEW_CALIB_RUN: // step of run of new calibrate ret_val = mkstep_new_calib_run(cmd_in_queue.command_number); break; /* ------------------------------------------------ hrs tuning -- */ case START_HRS_TUNING: // start of hrs tuning ret_val = start_hrs_tune(&cmd_in_queue); break; case HRS_TUNE_INIT: // start of hrs tuning ret_val = hrs_tune_init(cmd_in_queue.command_number); break; case HRS_ATTSETT_ID: // hrs tuning first loop ret_val = mkstep1_hrs_tune(cmd_in_queue.command_number); break; case HRS_ATTSETT2_ID: // hrs tuning second loop ret_val = mkstep2_hrs_tune(cmd_in_queue.command_number); break; /* ---------------------------------------------- spectroscopy -- */ case START_TOTAL_POWER: // start of total power measurement ret_val = start_total_power(&cmd_in_queue); break; case START_SLOW_CHOP: // start of slow chop measurement ret_val = start_slow_chop(&cmd_in_queue); break; case START_FAST_CHOP: // start of total power measurement ret_val = start_fast_chop(&cmd_in_queue); break; case START_FREQ_SWITCH: // start of total power measurement ret_val = start_freq_switch(&cmd_in_queue); break; /* ------------------------------------------------ wbs tuning -- */ case START_WBS_TUNING: // start of wbs tuning ret_val = start_wbs_tune(&cmd_in_queue); break; case WBS_ATTSETT_ID: // wbs tuning first loop ret_val = wbs_att_set(WBS_ATTSETT_ID, cmd_in_queue.command_number); break; case WBS_ATTSETT2_ID: // wbs tuning second loop ret_val = wbs_att_set(WBS_ATTSETT2_ID, cmd_in_queue.command_number); break; case WBS_ATTSETT3_ID: // wbs tuning third loop ret_val = wbs_att_set(WBS_ATTSETT3_ID, cmd_in_queue.command_number); break; /* ---------------------------------------------- mixer_magnet -- */ case START_HRS_MIXMAG: // start of hrs mixer magnet current tuning ret_val = start_tune_mixer_magnet(&cmd_in_queue, TUNE_HMIXMAG_ID); break; case START_WBS_MIXMAG: // start of wbs mixer magnet current tuning ret_val = start_tune_mixer_magnet(&cmd_in_queue, TUNE_WMIXMAG_ID); break; case TUNE_HMIXMAG_ID: // step of hrs mixer magnet current tuning ret_val = mkstep_tune_mixer_magnet(TUNE_HMIXMAG_ID, cmd_in_queue.command_number); break; case TUNE_WMIXMAG_ID: // step of wbs mixer magnet current tuning ret_val = mkstep_tune_mixer_magnet(TUNE_WMIXMAG_ID, cmd_in_queue.command_number); break; /* ------------------------------------------- hrs functional test -- */ case START_HRS_FUNCTEST: // start of hrs func test ret_val = start_hrs_functest(&cmd_in_queue); break; /* ------------------------------------------- wbs calibration -- */ case START_SPECTR_WBS_COMB_ID: // start of wbs calibration case START_SPECTR_WBS_ZERO_ID: // start of wbs zero measurement ret_val = start_wbs_calibrate(&cmd_in_queue); break; case WBS_COMB_STEP1_ID: // wbs calibration: first step ret_val = spec_wbs_zero(cmd_in_queue.command_number, TRUE); break; case WBS_COMB_STEP2_ID: // wbs calibration: second step ret_val = wbs_calibration_step2(cmd_in_queue.command_number); break; case SPECTROSCOPY_WBS_ZERO_ID: // wbs zero measurement ret_val = spec_wbs_zero(cmd_in_queue.command_number, FALSE); break; /* ------------------------------------ diplexer scan if power -- */ case START_DIPSCAN_IFP: // start of diplexer scan with if power ret_val = start_dip_scan_ifp(&cmd_in_queue); break; case DIP_SCAN_IF_ID: // step of diplexer scan with if power ret_val = mkstep_dip_scan_if(cmd_in_queue.command_number); break; /* ------------------------------------------ engineering scan -- */ case START_ENGSCAN_ROUTINE: // start of engineering scan ret_val = start_eng_scan(&cmd_in_queue); break; case ENGSCAN_ROUTINE: // perform engineering scan ret_val = perform_eng_scan(cmd_in_queue.command_number); break; case ENGSCAN_REPORT: // report generation ret_val = send_eng_scan_report(); break; /* --------------------------------------------------- peak up -- */ case ACQUIRE_PEAKUP_HRS: // acquire hrs frame ret_val = start_peakup_acquire_hrs(&cmd_in_queue); break; case ACQUIRE_PEAKUP_WBS: // acquire wbs frame ret_val = start_peakup_acquire_wbs(&cmd_in_queue); break; /* ----------------------------------------- memory management -- */ case START_MEM_CHECK: // start of memory check ret_val = start_memory_check(&cmd_in_queue); break; case START_CHECK_PM: // start of check PM ret_val = start_check_pm(&cmd_in_queue); break; case MKSTEP_CHECK_PM: // make a memory dump step ret_val = mkstep_check_pm(cmd_in_queue.command_number); break; case START_COPY_OBS: // start of copy OBS ret_val = start_copy_obs(&cmd_in_queue); break; case START_MEM_DUMP: // start of memory dump ret_val = start_memory_dump(&cmd_in_queue); break; case MKSTEP_MEM_DUMP: // make a memory dump step ret_val = mkstep_memory_dump(cmd_in_queue.command_number); break; case START_EEPROM_WRITE: // write in eeprom ret_val = start_write_in_eeprom(&cmd_in_queue); break; case SEND_MEM_DUMP_LCU_REPORT: // send an LCU mem dump report ret_val = send_mem_dump_LCU_report(); break; /* ------------------------------------------ simulate science -- */ case START_SIM_SCI: // starts simulated science ret_val = start_sim_sci(&cmd_in_queue); break; case MKSTEP_SIM_SCI: // send a set of simulated frames ret_val = mkstep_sim_sci(cmd_in_queue.command_number); break; /* ------------------------------------- internal VM activity -- */ case VM_CODE_UPLOAD: ret_val = upload_VM_code(&cmd_in_queue); break; case START_VM_PROGRAM: ret_val = start_VM_prog(&cmd_in_queue); break; /* ------------------------------------- internal VM activity -- */ case START_GOTO_SAFE: ret_val = start_HIFI_goto_safe(&cmd_in_queue); break; /* ---------------------------------------------------------------*/ default: // free the block if loaded if (cmd_in_queue.block_loaded == 1) release_block(&(cmd_in_queue.block)); // send a runtime error tm packet generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HS_HDL_OPERATION_ID, 0, NULL); ret_val = RC_FAIL; // to cause an abort break; } // end of switch // if the function called inside the above switch failed, an abort is required for a correct error recovery if (ret_val != RC_OK) abort_measurement(); } // end of while(1) } //----------------------- wbs_att_set ------------------------------------------ //! Implements step 1,2 or 3 of the wbs tuning procedure, depending on the aid int wbs_att_set (int aid, int command_number) { switch (aid) { case WBS_ATTSETT_ID: if (AID_spectroscopy != ZSCAN_ID) return enqueue_exec_fail(EXF_HS_HDL_WRONG_SPECT_AID, 0, NULL); if (ls_put_msg_hp(&WBS_H_CMD[ZERO_ON_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // zero on for wbsh if (ls_put_msg_hp(&WBS_V_CMD[ZERO_ON_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // zero on for wbsv if (ls_put_msg_hp(&WBS_H_CMD[COMB_OFF_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // comb off for wbsh if (ls_put_msg_hp(&WBS_V_CMD[COMB_OFF_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // comb off for wbsv KS_TaskSleep(100); // wait 100 ms as in wbs calibration // perform start int, stop int and transfer if (wbs_integrate(1005, 1, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); break; case WBS_ATTSETT2_ID: if (AID_spectroscopy != WBS_ATTSETT2_ID) return enqueue_exec_fail(EXF_HS_HDL_WRONG_SPECT_AID, 0, NULL); if (ls_put_msg_hp(&WBS_H_CMD[ATT_MAX_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[ATT_MAX_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_H_CMD[ZERO_OFF_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[ZERO_OFF_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); KS_TaskSleep(100); // wait 100 ms as in wbs calibration if (wbs_integrate(1005, 1, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); break; case WBS_ATTSETT3_ID: if (AID_spectroscopy != WBS_ATTSETT3_ID) return enqueue_exec_fail(EXF_HS_HDL_WRONG_SPECT_AID, 0, NULL); if (wbs_integrate(2565, 1, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); break; default: return enqueue_exec_fail(ERR_HS_HDL_WRONG_SPECT_AID, 0, NULL); break; } return RC_OK; } //-------------------- mkstep_tune_mixer_magnet -------------------------------- //! this function handles both wbs and hrs cases through argument AID_sp; this // function performs the operations of commanding required for a single step of the // mixer magnet current tuning procedure. int mkstep_tune_mixer_magnet (unsigned int AID_sp, int command_number) { unsigned int j, FCU_CMD1, FCU_CMD2; HS_HDL_MSG cmd_queue; // check the activity ID if (AID_spectroscopy != AID_sp) return enqueue_exec_fail(EXF_HS_HDL_WRONG_SPECT_AID, 0, NULL); // check that fcu is on if ((SubsysStatus & FCU_MASK) == 0) return enqueue_exec_fail(EXF_HS_HDL_FCU_SUB_OFF, 0, NULL); // execution failure // if it's the first step of a tuning procedure: get two values that must be put into the report if (mixer_mag_steps_performed == 0) { if (ls_put_msg_hp(&FCU_PS_HK[HF_DH1_MXBAND_IDX], &mixer_magnet_data[HFDH1_MXBAND_IDX], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&FCU_PS_HK[HF_DV1_MXBAND_IDX], &mixer_magnet_data[HFDH1_MXBAND_IDX + 1], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // check the number of steps: this is only a check, it doesn't govern the end of the procedure (that is done into data_hdl) if ( mixer_mag_steps_performed >= mixer_magnet_data[NMAGNET_IDX] ) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HS_HDL_MIXMAG_STEPS, 1, &mixer_mag_steps_performed); return RC_FAIL; } // one loop on Nmagnet: command magnet current, read Hk and store them for report FCU_CMD1 = FCU_PS_CMD[HF_CH1_MX_MG_C_IDX] | ((mixer_magnet_data[CH1_C0_IDX] + mixer_mag_steps_performed*mixer_magnet_data[STEPSIZE_IDX]) & 0x0FFFF); if (ls_put_msg_hp(&FCU_CMD1, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // set the magnet current h FCU_CMD2 = FCU_PS_CMD[HF_CV1_MX_MG_C_IDX] | ((mixer_magnet_data[CV1_C0_IDX] + mixer_mag_steps_performed*mixer_magnet_data[STEPSIZE_IDX]) & 0x0FFFF); if (ls_put_msg_hp(&FCU_CMD2, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // set the magnet current v task_hs_hdl_sleep(mixer_magnet_data[STEPTIME_IDX]*100); // wait the specified time // now a loop for requesting some HK values for (j = 0; j < MIX_MAG_HK_len; j++) if (ls_put_msg_hp(&MIX_MAG_HK[j], &mixer_magnet_data[MIX_MAG_HKOFFSET + mixer_mag_steps_performed*MIX_MAG_DATA + j], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // now send a dummy command to set the event # to ls if (ls_put_msg_hp(NULL, NULL, MEAS_EVENT, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // wait for the event MEAS_EVENT, to be raised by ls task to communicate that all previous commands have been processed KS_EventTestW(MEAS_EVENT); // now perform spectroscopy readout switch (AID_sp) { case TUNE_HMIXMAG_ID: if (hrs_integrate(100, 0, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); break; case TUNE_WMIXMAG_ID: if (wbs_integrate(1005, 0, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); break; } mixer_mag_steps_performed++; // increment the step counter // now ask for the next step if needed, otherwise request a fifo flush. if ( mixer_mag_steps_performed < mixer_magnet_data[NMAGNET_IDX] ) { // prepare and send command for the next step to hs_hdl task cmd_queue.operation_id = AID_sp; cmd_queue.command_number = command_number; cmd_queue.block_loaded = 0; if (KS_FIFOPut(HS_HDL_QUEUE, (void *) &cmd_queue) == RC_FAIL) { enqueue_exec_fail(EXF_HS_LIB_QUEUE, 0, NULL); // execution failure return RC_FAIL; } } else { // this is the last science data frame: request fifo flush if (ls_put_msg_hp(NULL, NULL, FLUSH_REQUEST, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // all right, we are over return RC_OK; } //------------ spec_wbs_zero --------------------------------------------------- //! sends to the ls task the commands for spectroscopy wbs zero int spec_wbs_zero (int command_number, int is_calibration) { if (ls_put_msg_hp(&WBS_H_CMD[ZERO_ON_IDX], NULL, 0, NULL) == RC_FAIL) // zero on for wbsh return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[ZERO_ON_IDX], NULL, 0, NULL) == RC_FAIL) // zero on for wbsv return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_H_CMD[COMB_OFF_IDX], NULL, 0, NULL) == RC_FAIL) // comb off for wbsh return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[COMB_OFF_IDX], NULL, 0, NULL) == RC_FAIL) // comb off for wbsv return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); KS_TaskSleep(100); // wait 100 ms // perform start int, stop int and transfer if (wbs_integrate(1005, 1, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // if it is a calibration we are over if (is_calibration == TRUE) return RC_OK; if (ls_put_msg_hp(&WBS_H_CMD[ZERO_OFF_IDX], NULL, 0, NULL) == RC_FAIL) // zero off for wbsh return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[ZERO_OFF_IDX], NULL, 0, NULL) == RC_FAIL) // zero off for wbsv return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); return RC_OK; } //------------ wbs_calibration_step2 ------------------------------------------- //! sends to the ls task the commands for wbs calibration second step int wbs_calibration_step2 (int command_number) { // set attenuators for wbsh according to TC parameters if (ls_put_msg_hp(&WBS_H_CMD[ATT_COMB_MEAS_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // set attenuators for wbsv according to TC parameters if (ls_put_msg_hp(&WBS_V_CMD[ATT_COMB_MEAS_IDX], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_H_CMD[COMB_ON_IDX], NULL, 0, NULL) == RC_FAIL) // comb on for wbsh return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[COMB_ON_IDX], NULL, 0, NULL) == RC_FAIL) // comb on for wbsv return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); KS_TaskSleep(100); // wait 100 ms // perform start int, stop int and transfer if (wbs_integrate(1005, 1, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_H_CMD[COMB_OFF_IDX], NULL, 0, NULL) == RC_FAIL) // comb off for wbsh return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[COMB_OFF_IDX], NULL, 0, NULL) == RC_FAIL) // comb off for wbsv return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // now send this two commands for attenuator setting restoration if (ls_put_msg_hp(&WBS_H_CMD[ATT_RESTORE_COMB_IDX], NULL, 0, NULL) == RC_FAIL) // restore att sett for wbsh return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[ATT_RESTORE_COMB_IDX], NULL, 0, NULL) == RC_FAIL) // restore att sett for wbsv return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // now send this two commands for zero switch setting restoration if (ls_put_msg_hp(&WBS_H_CMD[ATT_RESTORE_ZERO_IDX], NULL, 0, NULL) == RC_FAIL) // restore zero sett for wbsh return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&WBS_V_CMD[ATT_RESTORE_ZERO_IDX], NULL, 0, NULL) == RC_FAIL) // restore zero sett for wbsv return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); return RC_OK; } //****************************************************************************** //****************************************************************************** //----------------- mkstep_dip_scan_if ----------------------------------------- //! this function performs the operations of a single step of the dip scan with ifpower int mkstep_dip_scan_if (int command_number) { unsigned int i, FCU_CMD1, FCU_CMD2; HS_HDL_MSG cmd_queue; // message to be sent to the hs_hdl task // check variable AID_spectroscopy if (AID_spectroscopy != DIP_SCAN_IF_ID) return enqueue_exec_fail(EXF_HS_HDL_WRONG_SPECT_AID, 0, NULL); // check that hrs is on, otherwise return with an execution failure if ( (SubsysStatus & HRS_H_MASK) == 0 && (SubsysStatus & HRS_V_MASK) == 0 ) { enqueue_exec_fail(EXF_HS_HDL_HRS_SUB_OFF, 0, NULL); return RC_FAIL; } // check if FCU is on, otherwise return with an execution failure if ((SubsysStatus & FCU_MASK) == 0) { enqueue_exec_fail(EXF_HS_HDL_FCU_SUB_OFF, 0, NULL); return RC_FAIL; } // now perform the step: command diplexer position, wait, read Hk, spectroscopy readout FCU_CMD1 = FCU_config[HF_CH1_DPACT_C_IDX] | ((dip_scan_if_data[TM_CH1_DP_POS0_IDX] + dip_scan_if_cur_step*dip_scan_if_data[TM_DP_STEP_IDX]) & 0x0FFF); if (ls_put_msg_hp(&FCU_CMD1, NULL, 0, NULL) == RC_FAIL) // this sets diplexer h position return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); FCU_CMD2 = FCU_config[HF_CV1_DPACT_C_IDX] | ((dip_scan_if_data[TM_CH2_DP_POS0_IDX] + dip_scan_if_cur_step*dip_scan_if_data[TM_DP_STEP_IDX]) & 0x0FFF); if (ls_put_msg_hp(&FCU_CMD2, NULL, 0, NULL) == RC_FAIL) // this sets diplexer v position return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); task_hs_hdl_sleep(dip_scan_if_data[TM_DP_STEP_TIME_IDX]*100); // wait the specified time // now a loop for requesting some HK values for (i = 0; i < DIP_SCAN_param_len; i++) if (ls_put_msg_hp(&DIP_SCAN_param[i], &dip_scan_if_data[12 + dip_scan_if_cur_step*DIP_SCAN_DATA + i], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // now send a dummy message with a particular event_number: ls will recognize it and signal MEAS_EVENT if (ls_put_msg_hp(NULL, NULL, MEAS_EVENT, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // wait for the event MEAS_EVENT, to be raised by ls task to communicate that all previous commands have been processed KS_EventTestW(MEAS_EVENT); dip_scan_if_cur_step++; // increment the step counter // now ask for the next step if needed, otherwise request a fifo flush. if ( dip_scan_if_cur_step < dip_scan_if_data[TM_N_DIPLEXER_IDX] ) { // perform spectroscopy readout if (hrs_integrate(100, 0, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // notice: task data_hdl, after reception of the frames, will check termination and, // if necessary, will ask for the next step putting a message into hs_hdl fifo // prepare and send command for the next step to hs_hdl task cmd_queue.operation_id = DIP_SCAN_IF_ID; cmd_queue.command_number = command_number; cmd_queue.block_loaded = 0; if (KS_FIFOPut(HS_HDL_QUEUE, (void *) &cmd_queue) == RC_FAIL) { enqueue_exec_fail(EXF_HS_LIB_QUEUE, 0, NULL); // execution failure return RC_FAIL; } } else { // this is the last science data frame: request fifo flush: perform spectroscopy readout if (hrs_integrate(100, 1, command_number) != RC_OK) return enqueue_exec_fail(EXF_HS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // all right, we are over return RC_OK; } /******************************************************************************* ********************************* SERVICE FUNCTIONS **************************** *******************************************************************************/ //----------------------- asynchronous_ls_access ---------------------------------------- /* This function is used to perform an immediate acces to the ls system, bypassing the ls task and queues. IT SHOULD NOT BE USED WHEN VM IS RUNNING !!!! since it uses the VM data Irq3_flag */ void asynchronous_ls_access(unsigned int * cmd_address) { Irq3_flag = TRUE; // set this flag to reserve the ls port KS_TaskSleep(WAIT_LS_END_TIME); // wait for possible task ls to end using ls port (3 ms is the worst case) SendLss(cmd_address); // writes command directly into trx register KS_TaskSleep(COMMAND_TRANSMIT_TIME); // time needed to transmit properly Irq3_flag = FALSE; // reset the flag to free the ls port } //----------------------- wbs_integrate ---------------------------------------- // note: in order to guarantee the exact integration time, the commands of start // and stop integration are sent to the ls interface without using task ls, but // simply writing into the transmission register, after having reserved the ls port // by means of the Irq3_flag; a preliminary check on the status of the LS_HP_QUEUE // is needed to ensure the correct sequential order in the transmission of commands // to the subsystems; note: data transfer commands are instead sent to task ls. //! perform a variable duration wbs integration. Can require to issue a flush req at end. Integration blocked if the command is obsolete. int wbs_integrate (unsigned int integ_time, int flush_at_end, int command_number) { START_FRAME_DATA time_stamp; // the following while loop is essential when using tuning since we must be sure that, before // commanding the start integration, the previous tuning commands sent to task // ls through the high priority fifo have already been processed by this task. while (KS_FIFOStatus(LS_HP_QUEUE) != 0) KS_TaskSleep(1); // wait 1 ms // integrate asynchronous_ls_access(&WBS_H_CMD[START_INT_IDX]); // start integration get_TS(&(time_stamp.time_stamp)); // store the time when the integration was requested task_hs_hdl_sleep(integ_time - COMMAND_TRANSMIT_TIME - WAIT_LS_END_TIME); // wait int_time -( COMMAND_TRANSMIT_TIME + WAIT_LS_END_TIME) so the overall time between start and stop int is integ_time. asynchronous_ls_access(&WBS_H_CMD[STOP_INT_IDX]); // stop integration KS_TaskSleep(12); // wait at least 12 msec between stop int and start transfer if (command_number == current_command_number) // check if current_command_number is valid { // WBS-H if (ls_put_msg_hp(&WBS_H_CMD[DATA_TRANS_IDX], NULL, 0, NULL) == RC_FAIL) return RC_FAIL; if ( SubsysStatus & WBS_H_MASK ) { fifo_0_pending_frames++; push_TS(time_stamp, WBS_H_ID, DO_NOT_ATTACH_HK);} // update the global variables used to control HS status fifo_0_command_number = command_number; // WBS-V if (flush_at_end == 1) { if (ls_put_msg_hp(&WBS_V_CMD[DATA_TRANS_IDX], NULL, HS_FLUSH_EVENT, NULL) == RC_FAIL) return RC_FAIL; } else { if (ls_put_msg_hp(&WBS_V_CMD[DATA_TRANS_IDX], NULL, 0, NULL) == RC_FAIL) return RC_FAIL; // no hw fifo flush to be requested } if ( SubsysStatus & WBS_V_MASK ) {fifo_1_pending_frames++; push_TS(time_stamp, WBS_V_ID, DO_NOT_ATTACH_HK);} fifo_1_command_number = command_number; } return RC_OK; } //----------------------- hrs_integrate ---------------------------------------- // note: when the data transfer is requested we have to appropriately update those // global variables used to control HS status //! perform a variable duration hrs integration. Can require to issue a flush req at end. Integration blocked if the command is obsolete. int hrs_integrate (unsigned int integ_time, int flush_at_end, int command_number) { START_FRAME_DATA time_stamp; // select buffer A if (RC_FAIL == ls_put_msg_hp(&HRS_H_CMD[SEL_A_IDX], NULL, 0, NULL)) return RC_FAIL; if (RC_FAIL == ls_put_msg_hp(&HRS_V_CMD[SEL_A_IDX], NULL, 0, NULL)) return RC_FAIL; // reset buffer A if (RC_FAIL == ls_put_msg_hp(&HRS_H_CMD[RESET_A_IDX], NULL, 0, NULL)) return RC_FAIL; if (RC_FAIL == ls_put_msg_hp(&HRS_V_CMD[RESET_A_IDX], NULL, 0, NULL)) return RC_FAIL; // store the time when the integration was requested get_TS(&(time_stamp.time_stamp)); // integrate if (integ_time > 0) { if (RC_FAIL == ls_put_msg_hp(&HRS_H_CMD[START_INT_IDX], NULL, 0, NULL)) return RC_FAIL; task_hs_hdl_sleep(integ_time); // wait integration time if (RC_FAIL == ls_put_msg_hp(&HRS_H_CMD[STOP_INT_IDX], NULL, 0, NULL)) return RC_FAIL; } KS_TaskSleep(7); // select buffer B if (RC_FAIL == ls_put_msg_hp(&HRS_H_CMD[SEL_B_IDX], NULL, 0, NULL)) return RC_FAIL; if (RC_FAIL == ls_put_msg_hp(&HRS_V_CMD[SEL_B_IDX], NULL, 0, NULL)) return RC_FAIL; // now ask for the data transfer, but only if the current_command_number // has not been incremented by a new incoming TC if (command_number == current_command_number) { if (ls_put_msg_hp(&HRS_H_CMD[DATA_TRANS_IDX], NULL, 0, NULL) == RC_FAIL) return RC_FAIL; // now update the global variables used to control hs state if ( SubsysStatus & HRS_H_MASK ) { fifo_2_pending_frames++; push_TS( time_stamp, HRS_H_ID, DO_NOT_ATTACH_HK); } fifo_2_command_number = command_number; if (flush_at_end == 1) { if (ls_put_msg_hp(&HRS_V_CMD[DATA_TRANS_IDX], NULL, HS_FLUSH_EVENT, NULL) == RC_FAIL) return RC_FAIL; } else // no hw fifo flush to be requested if (ls_put_msg_hp(&HRS_V_CMD[DATA_TRANS_IDX], NULL, 0, NULL) == RC_FAIL) return RC_FAIL; // now update the global variables used to control hs state if ( SubsysStatus & HRS_V_MASK ) { fifo_3_pending_frames++; push_TS( time_stamp, HRS_V_ID, DO_NOT_ATTACH_HK); } fifo_3_command_number = command_number; } return RC_OK; } //-------------- task_hs_hdl_sleep --------------------------------------------- // this function makes the hs_hdl task sleep for sleep_time by using the semaphore // HS_HDL_WAIT_SEMA signalled through the timer hs_hdl_Timer; we prefer this solution // to the call to KS_TaskSleep() because in this way the sleep can be easily interrupted // by any other task who signals the semaphore HS_HDL_WAIT_SEMA; nevertheless note that // KS_TaskSleep() is still used when the sleep period is small or not commandable by TC. //! Interruptible task sleep void task_hs_hdl_sleep (unsigned int sleep_time) { if ( sleep_time < 1 ) return; KS_SemaReset(HS_HDL_WAIT_SEMA); // reset the sema, because its level is incremented every // time that task cmd_seq increments the global variable current_command_number // command one-shot signal of the semaphore after sleep_time virtuoso ticks KS_LowTimerStart(hs_hdl_Timer, sleep_time, 0, HS_HDL_WAIT_SEMA); // now make the task wait on the semaphore KS_SemaTestW(HS_HDL_WAIT_SEMA); } //----------- check_fifo_pending_frames ---------------------------------------- #define MAX_PENDING 20 //! checks the fifo_pending_frames counters, issues a warning if out of limit and returns 0 if warn issued, 1 otherwise int check_fifo_pending_frames (void) { int ret_val = 1; if ( fifo_0_pending_frames < 0 || fifo_0_pending_frames > MAX_PENDING ) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HS_HDL_FIFO_0_OOL, 1, &fifo_0_pending_frames); ret_val = 0; } if ( fifo_1_pending_frames < 0 || fifo_1_pending_frames > MAX_PENDING ) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HS_HDL_FIFO_1_OOL, 1, &fifo_1_pending_frames); ret_val = 0; } if ( fifo_2_pending_frames < 0 || fifo_2_pending_frames > MAX_PENDING ) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HS_HDL_FIFO_2_OOL, 1, &fifo_2_pending_frames); ret_val = 0; } if ( fifo_3_pending_frames < 0 || fifo_3_pending_frames > MAX_PENDING ) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HS_HDL_FIFO_3_OOL, 1, &fifo_3_pending_frames); ret_val = 0; } return ret_val; } /*************************************************************************************************************************************** *************************************************************************************************************************************** VM monitoring *************************************************************************************************************************************** ***************************************************************************************************************************************/ static unsigned int hif_n_wbs_copy=1; static unsigned int wbs_start_integration_received = 0; //----- reset_vm_mon -------------------------------------------------------- //! To reset the vm_mon task in case of fast chop void reset_vm_mon ( unsigned int this_hif_n_wbs ) { hif_n_wbs_copy = this_hif_n_wbs; wbs_start_integration_received = 0; } //----- vm_mon -------------------------------------------------------- //! To handle the event VM_REQ_EVENT void vm_mon ( void ) { START_FRAME_DATA time_stamp; while(1) { // Wait for VM_REQ_EVENT KS_EventTestW(VM_REQ_EVENT); // transfer handling: increase OBS counters and decrease VM counters if (VM_Spectroscopy_table[VM_START_TRANSF_HRS_H_IDX]) { VM_Spectroscopy_table[VM_START_TRANSF_HRS_H_IDX]--; if (SubsysStatus & HRS_H_MASK) fifo_2_pending_frames++;} if (VM_Spectroscopy_table[VM_START_TRANSF_HRS_V_IDX]) { VM_Spectroscopy_table[VM_START_TRANSF_HRS_V_IDX]--; if (SubsysStatus & HRS_V_MASK) fifo_3_pending_frames++;} if (VM_Spectroscopy_table[VM_START_TRANSF_WBS_H_IDX]) { VM_Spectroscopy_table[VM_START_TRANSF_WBS_H_IDX]--; if (SubsysStatus & WBS_H_MASK) fifo_0_pending_frames++;} if (VM_Spectroscopy_table[VM_START_TRANSF_WBS_V_IDX]) { VM_Spectroscopy_table[VM_START_TRANSF_WBS_V_IDX]--; if (SubsysStatus & WBS_V_MASK) fifo_1_pending_frames++;} // integration handling: get time stamp if (VM_Spectroscopy_table[VM_START_INT_HRS_IDX] || VM_Spectroscopy_table[VM_START_INT_WBS_IDX]) get_TS(&(time_stamp.time_stamp)); // integration handling: push time stamp if (VM_Spectroscopy_table[VM_START_INT_HRS_IDX]) { VM_Spectroscopy_table[VM_START_INT_HRS_IDX]--; if (SubsysStatus & HRS_H_MASK) push_TS( time_stamp, HRS_H_ID, ATTACH_HK); if (SubsysStatus & HRS_V_MASK) push_TS( time_stamp, HRS_V_ID, ATTACH_HK); } if (VM_Spectroscopy_table[VM_START_INT_WBS_IDX]) { VM_Spectroscopy_table[VM_START_INT_WBS_IDX]--; if ( AID_spectroscopy == TC_FUNMAN_SPCTRFC_AID ) // fast chop needs different handling { if ( IFSI_MOD(wbs_start_integration_received, hif_n_wbs_copy) == 0 ) { // push TS for phase A if (SubsysStatus & WBS_H_MASK) push_TS( time_stamp, WBS_H_ID, ATTACH_HK); if (SubsysStatus & WBS_V_MASK) push_TS( time_stamp, WBS_V_ID, ATTACH_HK); } if ( IFSI_MOD(wbs_start_integration_received, hif_n_wbs_copy) == 1 ) { // push TS for phase B if (SubsysStatus & WBS_H_MASK) push_TS( time_stamp, WBS_H_ID, ATTACH_HK); if (SubsysStatus & WBS_V_MASK) push_TS( time_stamp, WBS_V_ID, ATTACH_HK); } wbs_start_integration_received++; } else { if (SubsysStatus & WBS_H_MASK) push_TS( time_stamp, WBS_H_ID, ATTACH_HK); if (SubsysStatus & WBS_V_MASK) push_TS( time_stamp, WBS_V_ID, ATTACH_HK); } } } }