// $RCSfile: ls_hdl.c,v $Revision: 1.59 $Date: 2005/03/11 15:08:57 //! To implement the LS long commands (scan, IVcurve etc) #include "ls_hdl.dox" #include "allnodes.h" #include "node1.h" #include #include "configura.h" #include "err_hdl.h" #include "pubfuncs.h" #include "cmd_seq.h" #include "cmd_exec.h" #include "ls.h" #include "tables.h" #include "conf_tab.h" #include "hs_hdl.h" #include "hs_lib.h" #include "hk_ask.h" #include "MM_misc.h" #include "ls_hdl.h" //---- local functions --------------------------------------------------------- int ls_hdl_check_cmd_number (LS_HDL_MSG * ); int measure_LCU_ivcurve(LS_HDL_MSG *cmd_in_queue); void read_status_LCU_ivcurve(LS_HDL_MSG *msg); int send_report_LCU_ivcurve (void); void load_vector_scan(LS_HDL_MSG *msg); int start_vector_scan(LS_HDL_MSG *msg); int mkstep_vector_scan(LS_HDL_MSG *msg); int send_vector_scan_report(void); int send_LO_tune_report (int *, int); int lo_tune_issue_commands (int *, int); int start_fcu_param_scan (LS_HDL_MSG *); int mkstep_fcu_param_scan (LS_HDL_MSG *); int start_dip_scan_noif (LS_HDL_MSG *); int mkstep_dip_scan_noif (LS_HDL_MSG *); void task_ls_hdl_sleep (unsigned int sleep_time); int monitor_scan_status (void); int start_verify_LCU (LS_HDL_MSG *, int mode, int next_step); int mkstep_verify_LCU (LS_HDL_MSG *, int mode, int next_step); int last_step_verify_LCU (LS_HDL_MSG *, int mode); int start_verify_LCU_chunk (LS_HDL_MSG *); int mkstep_verify_LCU_chunk (LS_HDL_MSG *); int last_step_verify_LCU_chunk (LS_HDL_MSG *); //---- local variables --------------------------------------------------------- static K_TIMER * ls_hdl_Timer; //!< timer used in function task_ls_hdl_sleep() // additional data for LO tuning static int unit_under_tune; // -1 if just vector scan, 0 if LO tuning H, 1 if LO tuning V. //----- task ls_hdl ------------------------------------------------------------ //! Get a pkt from the LS_HDL_QUEUE, check if it is relative to the currently running command and, if yes, calls the appropriate processing function void ls_hdl (void) { LS_HDL_MSG cmd_in_queue; ls_hdl_Timer = KS_LowTimerGet(); // allocate a timer while (1) { // wait for message in the fifo if (KS_FIFOGetW(LS_HDL_QUEUE, &cmd_in_queue) != RC_OK) continue; // chek 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) { /* ----------------------------------------------- vector scan -- */ case LOAD_VEC_SCAN_CMD: // load vector scan load_vector_scan(&cmd_in_queue); break; case VEC_SCAN_CMD: // start of vector scan unit_under_tune = -1; // -1: no tuning only vec scan LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_vector_scan(&cmd_in_queue); break; case MKSTEP_VEC_SCAN_CMD: // step of vector scan mkstep_vector_scan(&cmd_in_queue); break; /* ----------------------------------- local oscillator tuning -- */ case LO_TUNE_H_CMD: unit_under_tune = 0; // 0 if tuning H, 1 if tuning V. LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_vector_scan(&cmd_in_queue); break; case LO_TUNE_V_CMD: unit_under_tune = 1; // 0 if tuning H, 1 if tuning V. LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_vector_scan(&cmd_in_queue); break; /* -------------------------------------- measure lcu iv curve -- */ case LCU_IVCURVE_ID: LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; measure_LCU_ivcurve(&cmd_in_queue); break; case LCU_IVCURVE_STATUS: // read the LCU status read_status_LCU_ivcurve(&cmd_in_queue); break; case LCU_IVCURVE_REPORT: // send the final report send_report_LCU_ivcurve(); break; /* -------------------------------------- single hk FCU -- */ case START_SINGLE_HK: // single hk FCU LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_single_hk(&cmd_in_queue); break; case NP_HK_COMPLETED: // send the final report single_hk(); break; /* -------------------------------------- single hk LCU -- */ case START_SINGLE_HK_LCU: // single hk LCU LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_single_HK_LCU(&cmd_in_queue); break; case SEND_SINGLE_HK_REPORT: // send the final report send_single_HK_LCU_report(); break; /* ---------------------------------single hk mem LCU -- */ case START_MEM_HK_LCU: // single hk LCU LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_mem_HK_LCU(&cmd_in_queue); break; case SEND_MEM_HK_REPORT: // send the final report send_mem_HK_LCU_report(); break; /* --------------------------------- LCU crc check -- */ case START_VERIFY_LCU: // verify LCU CRC LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_verify_LCU(&cmd_in_queue, 0, MKSTEP_VERIFY_LCU); break; case MKSTEP_VERIFY_LCU: // verify LCU CRC mkstep_verify_LCU(&cmd_in_queue, 0, LAST_STEP_VERIFY_LCU); break; case LAST_STEP_VERIFY_LCU: // verify LCU CRC last_step_verify_LCU(&cmd_in_queue, 0); break; /* --------------------------------- lcu crc check from aut funct -- */ case START_VERIFY_LCU_MODE1: // verify LCU CRC LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_verify_LCU(&cmd_in_queue, 1, MKSTEP_VERIFY_LCU_MODE1); break; case MKSTEP_VERIFY_LCU_MODE1: // verify LCU CRC mkstep_verify_LCU(&cmd_in_queue, 1, LAST_STEP_VERIFY_LCU_MODE1); break; case LAST_STEP_VERIFY_LCU_MODE1: // verify LCU CRC last_step_verify_LCU(&cmd_in_queue, 1); break; /* --------------------------------- lcu crc check from aut funct -- */ case START_VERIFY_LCU_CHUNK: // verify LCU CRC LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_verify_LCU_chunk(&cmd_in_queue); break; case MKSTEP_VERIFY_LCU_CHUNK: // verify LCU CRC mkstep_verify_LCU_chunk(&cmd_in_queue); break; case LAST_STEP_VERIFY_LCU_CHUNK: // verify LCU CRC last_step_verify_LCU_chunk(&cmd_in_queue); break; /* ---------------------------------------- fcu parameter scan -- */ case START_FCU_PARAM_SCAN: // start of fcu param scan LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_fcu_param_scan(&cmd_in_queue); break; case MKSTEP_FCU_PARAM_SCAN: // step of fcu param scan mkstep_fcu_param_scan(&cmd_in_queue); break; /* ---------------------------- diplexer scan without if power -- */ case START_DIP_SCAN_NOIF: // start of diplexer scan no ifpower LS_activity_preparation(); if (ls_hdl_check_cmd_number(&cmd_in_queue)) break; start_dip_scan_noif(&cmd_in_queue); break; case MKSTEP_DIP_SCAN_NOIF: // step of diplexer scan no ifpower mkstep_dip_scan_noif(&cmd_in_queue); break; /*----------------------------------------------------------------*/ default: // wrong operation_id: generate an error message and free the block if loaded generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_LS_HDL_WRONG_CMD, 0, NULL); if (cmd_in_queue.block_loaded == 1) release_block(&(cmd_in_queue.block)); break; } // end of switch } // end of while(1) } //--------- ls_hdl_check_cmd_number -------------------------------------------- //! Checks whether the command carried by the message is obsolete or not. Returns 1 if obsolete, 0 if not. int ls_hdl_check_cmd_number (LS_HDL_MSG * msg) { // chek if the command is obsolete, if yes free the possible block and break if (msg->command_number != current_command_number) { // free the block if loaded if (msg->block_loaded == 1) release_block(&(msg->block)); // return 1 to signal that it's necessary to go out of the switch without // performing the rest of the case return 1; } return 0; } /*******************************************************************************************************/ /*******************************************************************************************************/ // Scan /*******************************************************************************************************/ /*******************************************************************************************************/ static int scan_cur_step; //! number of the step being performed within a scan procedure /*******************************************************************************************************/ /*******************************************************************************************************/ // LCU Vector scan and LO tuning /*******************************************************************************************************/ /*******************************************************************************************************/ //! The following functions implement the HIFI_vector_scan, HIFI_tune_LO_using_MXCH and HIFI_tune_LO_using_MXCV #define VEC_SCAN_PARS_LEN 14 /* number of parameters to scan */ #define VEC_SCAN_STEP_DATA_LEN 45 /* 28 for the commands echo + 17 for the HK (only two bytes significant) */ #define VEC_SCAN_MAX_STEP 10 /* Max number of steps */ #define DATA_IS_16_BIT 0 #define DATA_IS_32_BIT 1 // TC packet datas static int HL_SET[VEC_SCAN_PARS_LEN]; //! parameters (commands to be issued) of the vector scan command static int HL_STEP[VEC_SCAN_PARS_LEN]; //! increments of the parameters at each step static unsigned int loaded_scan_report_sid; //! to hold the band value of the last load vector scan TC to be used in the vec scan report static int HIF_Nsteps; //! Number of steps in vector scan static int HIF_step_time; //! wait time between two steps static int scan_conf_is_valid=0; //! flag that is set at evey vec scan configuration and reset at execution // TM packet data static int vector_scan_data[VEC_SCAN_STEP_DATA_LEN * VEC_SCAN_MAX_STEP]; //! buffer for the vector scan data // Additional data for LO tuning static int lo_tun_target_current; //! Target current for the LO tuning cmds // Additional data for LO re-tuning static unsigned int last_LCU_macro[VEC_SCAN_PARS_LEN]; //! Copy of the last LCU macro static int last_LCU_macro_is_valid = 0; //--------- load_vector_scan --------------------------------------------------- //! executes the load_vector_scan command. void load_vector_scan (LS_HDL_MSG *msg) { int *paux, i; // prepare an auxiliary pointer paux = (int *) (msg->block).pointer_to_data; // set the building block id Cur_BuildingBlock_ID = PACK(paux[7], paux[8]); Meas_BuildingBlock_ID = Cur_BuildingBlock_ID; // store the data into some static top level variables HIF_Nsteps = paux[9]; HIF_step_time = paux[10]; loaded_scan_report_sid = VEC_SCAN_REP_SID + (paux[13] & 0xF); // extract the band indice to be used in the vec scan report sid computation // Load the initial values(ICD 1.4): 14 parameters of 32 bits starting from byte 22 of the packet for (i=0; iblock)); // free the block from the TC_POOL } //------- exec_LO_retune ---------------------------------------------------- //! LO tuning based on the saved results: note: this is an immediate command executed within cmd_seq int exec_LO_retune (TC_packet * packet) { unsigned int freq_patch, main_patch, offset_patch; static int commands[VEC_SCAN_PARS_LEN]; int i; // set the building block id Cur_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); // check if LCU and FCU are on, otherwise abort vec scan if (((SubsysStatus & LCU_MASK) == 0) || ((SubsysStatus & FCU_MASK) == 0)) return EXF_LS_HDL_VSCAN_SYSOFF; // break, is over // check if LCU macro was issued if (! last_LCU_macro_is_valid) return EXF_LS_HDL_LAST_INVALID; // read command parameters freq_patch = packet->data[4] & 0xFFFF; // this is a 16 bits patch main_patch = ( (packet->data[5] & 0xF) << 16 ) | ( (packet->data[6] & 0xFFFF) ); // this is a 20 bits patch offset_patch = ( (packet->data[7] & 0xF) << 16 ) | ( (packet->data[8] & 0xFFFF) ); // this is a 20 bits patch // copy the last LCU macro for ( i=0; i< VEC_SCAN_PARS_LEN; i++) commands[i] = last_LCU_macro[i]; // patch the saved LCU macro commands[1] = ( last_LCU_macro[1] & 0xFFFF0000 ) | freq_patch; commands[2] = ( last_LCU_macro[2] & 0xFFF00000 ) | main_patch; commands[3] = ( last_LCU_macro[3] & 0xFFF00000 ) | offset_patch; // LCU crc computation commands[VEC_SCAN_PARS_LEN-1] = commands[VEC_SCAN_PARS_LEN-1] & 0xFFF00000; // set the last 20 bits to zero to force CRC computation compute_and_add_LCU_CRC( (unsigned int *) commands); // push command in queue towards ls task for ( i=0; i< VEC_SCAN_PARS_LEN; i++) { if (ls_put_msg_hp(&commands[i], NULL, 0, NULL) == RC_FAIL) return EXF_LS_HDL_ERROR_LS_HP_QUEUE; } // done return RC_OK; } //------- start_vector_scan ---------------------------------------------------- //! First step of a vector scan or LO tuning command int start_vector_scan (LS_HDL_MSG *msg) { LS_HDL_MSG mymsg; int i; TC_packet * packet; // prepare an auxiliary pointer to the TC packet packet = (TC_packet *) msg->block.pointer_to_data; // set the building block id Meas_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); Cur_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); // if it is a LO tuning, load the target current if ( unit_under_tune >= 0 ) lo_tun_target_current = packet->data[4]; // lo_tun_target_current is a top level variable for this file // we can free the block release_block((K_BLOCK *) &(msg->block)); // clear the data vector for (i=0; i < VEC_SCAN_STEP_DATA_LEN * VEC_SCAN_MAX_STEP; i++) vector_scan_data[i] = 0; // check if LCU and FCU are on, otherwise abort vec scan if (((SubsysStatus & LCU_MASK) == 0) || ((SubsysStatus & FCU_MASK) == 0)) return enqueue_exec_fail(EXF_LS_HDL_VSCAN_SYSOFF, 0, NULL); // break, vec scan is over // consistency check (HIF_Nsteps is a variable cointaining the value received with the last load vector scan TC) if ( HIF_Nsteps > VEC_SCAN_MAX_STEP || HIF_Nsteps < 1 ) return enqueue_exec_fail(EXF_LS_HDL_VSCAN_OVFL, 0, NULL); // break, vec scan is over // check the table: it contains 15 hk reqs for lcu and 2 hk reqs for FCU if ( LCU_vectorscan_commands_len != 17 ) return enqueue_exec_fail(EXF_LS_HDL_VEC_SCAN_TABLE, 0, NULL); // break, vec scan is over // check if the configuration is valid if ( scan_conf_is_valid ) scan_conf_is_valid = 0; // the configuration is about being used: it is thus expired else return enqueue_exec_fail(EXF_LS_HDL_VEC_SCAN_CONF_EXPIRED, 0, NULL); // break, the configuration is expired scan_cur_step = 0; // init static data // prepare and push a message into the LS_HDL_QUEUE fifo mymsg.operation_id = MKSTEP_VEC_SCAN_CMD; mymsg.command_number = msg->command_number; // the message is labeled with the id number of the received msg mymsg.block_loaded = 0; // send to task ls_hdl again if (KS_FIFOPut(LS_HDL_QUEUE, (void *) &mymsg) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_PUT_LS_HDL_QUEUE, 0, NULL); return RC_OK; } //---- monitor_scan_status ------------------------------------------------- //! checks if the scan or the LO tuning is over and keeps trak of the best step. If scan is over sends the reports and returns 1. Otherwise returns 0. int monitor_scan_status (void) { static int best_step, best_difference; int step, upper_step, lower_step, difference; int up_val, lo_val, bracketing_found; int interp_par, interp_coe; // interpolated parameter and interpolation coefficient int command_vector[VEC_SCAN_PARS_LEN]; // to store commands to be sent to ls task int i, upper_par, lower_par; // If this is a simple vector scan run all the steps if ( unit_under_tune < 0 ) { if ( scan_cur_step >= HIF_Nsteps ) { // we are over: send the reports and return 1 // send the last step as LO tune report if ((send_vector_scan_report() == RC_OK) && (send_LO_tune_report( &vector_scan_data[(HIF_Nsteps - 1)*VEC_SCAN_STEP_DATA_LEN], DATA_IS_16_BIT ) == RC_OK)) enqueue_exec_compl(); else enqueue_exec_fail(EXF_LS_HDL_VSCAN_REPORT_PROBLEMS, 0, NULL); // break, vec scan is over return 1; } else return 0; } // If we get here we are doing a LO tuning!!! // Keep the best step up to date if ( scan_cur_step == 0 ) { // no steps were performed yet: we have nothing to do return 0; } else if ( scan_cur_step == 1 ) { // first step was performed: init the best step data best_step = 0; best_difference = lo_tun_target_current - (vector_scan_data[VEC_SCAN_STEP_DATA_LEN-2+unit_under_tune]&0x0FFFF); if (best_difference < 0) best_difference = - best_difference; } else { // a successive step was performed: update the best step data step = scan_cur_step - 1; difference = lo_tun_target_current - (vector_scan_data[step * VEC_SCAN_STEP_DATA_LEN-2+unit_under_tune]&0x0FFFF); if (difference < 0) difference = - difference; if ( difference < best_difference ) { // update best step and difference best_step = step; best_difference = difference; } } // Now check if the last two steps bracket the target value. bracketing_found = 0; if ( scan_cur_step >= 2 ) { // inits lower_step = scan_cur_step-2; upper_step = scan_cur_step-1; up_val = vector_scan_data[(upper_step+1)*VEC_SCAN_STEP_DATA_LEN-2+unit_under_tune] & 0x0FFFF; lo_val = vector_scan_data[(lower_step+1)*VEC_SCAN_STEP_DATA_LEN-2+unit_under_tune] & 0x0FFFF; // check if these are a bracketing pair if ( ( up_val <= lo_tun_target_current && lo_tun_target_current <= lo_val ) || ( up_val >= lo_tun_target_current && lo_tun_target_current >= lo_val ) ) bracketing_found = 1; } // NOW let us check for termination // If a bracketing was found we are over: interpolate, issue reports and commands and return 1. if ( bracketing_found ) { // Compute interpolation coefficent. interp_coe = ( (lo_tun_target_current - lo_val) << 12 ) / (up_val - lo_val); // prepare vector of commands to be issued: extract params (last 12 bits) and interpolate them. for ( i=0; i < VEC_SCAN_PARS_LEN; i++) { // extract command parameters lower_par = vector_scan_data[lower_step*VEC_SCAN_STEP_DATA_LEN + 2*i+1] & 0xFFF; upper_par = vector_scan_data[upper_step*VEC_SCAN_STEP_DATA_LEN + 2*i+1] & 0xFFF; // compute iterpolated parameter interp_par = lower_par + ( (interp_coe * (upper_par - lower_par) ) >> 12 ); // construct command with interpolated param command_vector[i] = (HL_SET[i] & 0xFFFFF000) | (interp_par & 0x0FFF); } // add crc, issue commands and reports compute_and_add_LCU_CRC( (unsigned int *) command_vector); if ( ( lo_tune_issue_commands( command_vector, DATA_IS_32_BIT ) == RC_OK ) && ( send_vector_scan_report() == RC_OK ) && ( send_LO_tune_report( command_vector, DATA_IS_32_BIT ) == RC_OK ) ) enqueue_exec_compl(); else enqueue_exec_fail(EXF_LS_HDL_VSCAN_REPORT_PROBLEMS, 0, NULL); // signal termination return 1; } // If maximum of steps was reached we are over, signal no bracketing, issue reports and commands and return 1. if ( scan_cur_step >= HIF_Nsteps ) { // commented after scr 1769: decommented after scr 2260 generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_LS_HDL_LO_TUNE_FOUND_NO_BRACKET, 0, NULL); // issue commands and reports using the best step as the chosen step if ( ( lo_tune_issue_commands( &vector_scan_data[best_step*VEC_SCAN_STEP_DATA_LEN], DATA_IS_16_BIT ) == RC_OK ) && ( send_vector_scan_report() == RC_OK ) && ( send_LO_tune_report( &vector_scan_data[best_step*VEC_SCAN_STEP_DATA_LEN], DATA_IS_16_BIT ) == RC_OK ) ) enqueue_exec_compl(); else enqueue_exec_fail(EXF_LS_HDL_VSCAN_REPORT_PROBLEMS, 0, NULL); // signal termination return 1; } // we have to continue with the next step return 0; } //---- send_vector_scan_report ------------------------------------------------- //! prepares and sends the scan report int send_vector_scan_report (void) { K_BLOCK block; TM_ST3_HEADER *st3_header; HK_TM_MSG hk_msg; unsigned int *hk_data; int position, hk_source; int i, j; // get a memory block from the HK_POOL pool if (get_block(&block, HK_POOL, HK_BLOCK_LEN_BYTES) == RC_FAIL) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, EXF_LS_HDL_VSCAN_REP_GET_HK_BLOCK, 0, NULL); return RC_FAIL; } init_block(&(block), HK_BLOCK_LEN_WORDS); // initialize the block prepare_TM_packet(&block, TM_DFHF_REGULAR, TM_APID_HK, 25 + 2*HIF_Nsteps*VEC_SCAN_STEP_DATA_LEN, TM_HK_TYPE, TM_HK_SUBT); // copy the data hk_data = block.pointer_to_data; position = HK_TM_HEADER; // prepare auxiliary pointers hk_source = 0; hk_data[position++] = HIF_step_time; // copy step time hk_data[position++] = HIF_Nsteps; // copy Nstep for (i = 0; i < HIF_Nsteps; i++) for (j = 0; j < VEC_SCAN_STEP_DATA_LEN; j++) hk_data[position++] = vector_scan_data[hk_source++]; // prepare the pointer to header st3_header = (TM_ST3_HEADER * ) block.pointer_to_data; // write Source Data Header st3_header->structure_ID = loaded_scan_report_sid; UNPACK(st3_header->obs_ID, Observation_ID); UNPACK(st3_header->bb_ID, Meas_BuildingBlock_ID); hk_msg.block = block; hk_msg.packing = PACKING_16; // set the packetization flag to 16 bit hk_msg.packing |= SDH_HK_WLEN << 8; // set the length of data header hk_msg.packing |= HKP << 16; hk_msg.offset = HK_TM_HEADER; // no offset hk_msg.count = 0; // downcount of the packet hk_msg.length = 0; // useless // send message to tm_tc if (KS_FIFOPut(HK_TM_QUEUE, (void *) &hk_msg) == RC_FAIL) { release_block(&block); generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, EXF_LS_HDL_VSCAN_REP_PUT_HK_QUEUE, 0, NULL); return RC_FAIL; } return RC_OK; } //---- lo_tune_issue_commands -------------------------------------------------- //! send the commands int lo_tune_issue_commands(int * commands, int data_type) { int i; for (i = 0; i < VEC_SCAN_PARS_LEN; i++) { // build the command switch ( data_type ) { case DATA_IS_32_BIT: last_LCU_macro[i] = commands[i]; break; case DATA_IS_16_BIT: last_LCU_macro[i] = ((commands[2*i]&0xFFFF) << 16) | (commands[2*i+1]&0xFFFF); break; default: generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, EXF_LS_HDL_VEC_SCAN_INTERNAL, 0, NULL); return RC_FAIL; break; } // push command in queue towards ls task last_LCU_macro_is_valid = 1; if (ls_put_msg_hp(&last_LCU_macro[i], NULL, 0, NULL) == RC_FAIL) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); return RC_FAIL; } } return RC_OK; } //---- send_LO_tune_report ----------------------------------------------------- //! Finds the best vector scan step. Drives the subsystem into the best configuration. Prepares and sends the LO tune report. // the pointer params points to the vector of commanded positions int send_LO_tune_report (int * params, int data_type) { int i; unsigned int report_data[36]; // array for the data to be put into the report report_data[0] = CONF_LCU_NOMIN_REP; // fid/aid set to 0xC1E report_data[1] = LO_TUNE_REPORT_SID; // sid is 534 report_data[2] = Observation_ID >>16; report_data[3] = Observation_ID & 0x0FFFF; UNPACK(&report_data[4], Meas_BuildingBlock_ID); report_data[6] = 0; // spare report_data[7] = 0; // spare // now copy 14 params of 32 bits: they can be saved in single words or in two words of 16 bits each. // The report requires the 16 bit format switch( data_type ) { case DATA_IS_16_BIT: for (i = 0; i < 2*VEC_SCAN_PARS_LEN; i++) report_data[8 + i] = params[i]; break; case DATA_IS_32_BIT: for (i = 0; i < VEC_SCAN_PARS_LEN; i++) { report_data[8 + 2*i] = (params[i] & 0xFFFF0000) >> 16; report_data[8 + 2*i+1] = params[i] & 0xFFFF; } break; default: generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, EXF_LS_HDL_VEC_SCAN_INTERNAL, 0, NULL); return RC_FAIL; break; } // now call function generate_report(), that will produce the TM(8,6) report packet if (generate_report(APID1024, TM_FS_TYPE, TM_FS_SUBT, 36, report_data) == RC_FAIL) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, EXF_LS_HDL_GEN_REP_FAIL, 0, NULL); return RC_FAIL ; } return RC_OK; } //------------- mkstep_vector_scan --------------------------------------------- //! Performs the generic step of a vector scan or LO tuning command int mkstep_vector_scan (LS_HDL_MSG *msg) { static int command_vector[VEC_SCAN_PARS_LEN]; // to store commands to be sent to ls task int command_pars[VEC_SCAN_PARS_LEN]; int destination, i; // check if LCU and FCU are on otherwise abort vec scan if (((SubsysStatus & LCU_MASK) == 0) || ((SubsysStatus & FCU_MASK) == 0)) return enqueue_exec_fail(EXF_LS_HDL_VSCAN_SYSOFF, 0, NULL); // break, vec scan is over // check for bracketing, best step and termination if ( monitor_scan_status() == 1) return RC_OK; // HERE STARTS the vector scan STEP // build command parameter vector for (i = 0; i < VEC_SCAN_PARS_LEN; i++) { command_pars[i] = (HL_SET[i]& 0x0FFF) + scan_cur_step * HL_STEP[i]; // the param just computed is now checked against overflow if ( (command_pars[i] & 0xFFFFF000) != 0 ) // checking if > 0FFF or < 0 return enqueue_exec_fail(EXF_LS_HDL_VSCAN_OVFL, 0, NULL); // break, vec scan is over } // prepare destination index destination = scan_cur_step*VEC_SCAN_STEP_DATA_LEN; // prepare commands, send them, and store them for the echo for (i = 0; i < VEC_SCAN_PARS_LEN; i++) { // build the command vector command_vector[i] = (HL_SET[i] & 0xFFFFF000) | (command_pars[i] & 0x0FFF); // LCU crc computation if (i == VEC_SCAN_PARS_LEN-1 ) compute_and_add_LCU_CRC( (unsigned int *) command_vector); // push command in queue towards ls task if (ls_put_msg_hp(&command_vector[i], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // echo the commands just issued; they are separated in two parts of 16 bits each vector_scan_data[destination++] = ( command_vector[i] & 0xFFFF0000 ) >> 16; vector_scan_data[destination++] = ( command_vector[i] & 0x0FFFF ); } task_ls_hdl_sleep(HIF_step_time*100); // wait the specified time // require the 15 LCU HK for (i = 0; i < 15; i++) if (ls_put_msg_hp(&LCU_vectorscan_commands[i], &vector_scan_data[destination++], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // require the 2 FCU HK if (ls_put_msg_hp(&LCU_vectorscan_commands[15], &vector_scan_data[destination++], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&LCU_vectorscan_commands[16], &vector_scan_data[destination], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // push in ls queue the request for signalling upon termination if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, MKSTEP_VEC_SCAN_CMD, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); scan_cur_step++; // increment the number of steps performed return RC_OK; } /*******************************************************************************************************/ /*******************************************************************************************************/ // Verify LCU crc /*******************************************************************************************************/ /*******************************************************************************************************/ static unsigned int HK_status_storage; static unsigned int req_crc_computation; static unsigned int req_crc_read; static unsigned int verify_lcu_wait_time; static unsigned int expected_crc_value; static unsigned int read_crc_value; #define MAX_CHUNK 49 static unsigned int chunk_start[MAX_CHUNK]; static unsigned int chunk_len[MAX_CHUNK]; static unsigned int chunk_crc[MAX_CHUNK]; static unsigned int HL_critical; static unsigned int HL_band_mask; static unsigned int HL_block_when_nok; static unsigned int chunk_current; static unsigned int chunk_num; //---------------------- enqueue_crc_fail ----------------------------------- //! this function equeues a 1,8 or a 5,1 int enqueue_crc_fail( int mode, int error_code) { if ( mode == 0 ) enqueue_exec_fail(error_code, 0, NULL); else generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, error_code, 0, NULL); return RC_FAIL; } //---------------------- start_verify_LCU_chunk ----------------------------------- //! this function performs a check on the LCU crc int start_verify_LCU_chunk (LS_HDL_MSG * msg) { unsigned int i; TC_packet * packet; // prepare an auxiliary pointer to the TC packet packet = (TC_packet *) msg->block.pointer_to_data; // check that lcu is on if ((SubsysStatus & LCU_MASK) == 0) { release_block((K_BLOCK *) &(msg->block)); return enqueue_exec_fail(EXF_LS_HDL_LCU_OFF, 0, NULL); } /* notes: the start and len need to be completed with the most significant 16 bits (0xf00b and 0xf00c resp.) req_crc_read needs to be created and is used to read the partial CRC verify_lcu_wait_time is not needed and is used in the follwoing as a normal variable */ // read packet params HL_critical = (packet->data[4] & 0x0000FFFF); // 16 bit parameter that defines the type of checksum // next parameters: 32 bits parameter that is the command to issue in case of mismatch when HL_critical=2 HL_band_mask = (((packet->data[5] & 0x0000FFFF) << 16 ) | (packet->data[6] & 0x0000FFFF)); HL_block_when_nok = (packet->data[7] & 0x0000FFFF); // 16 bits flag for blocking in case of mismatch req_crc_read = (((packet->data[8] & 0x0000FFFF) << 16 ) | 0x0000FFFF); // 16 bits parameter extended with FFFF that is the command to pass to the LCU to ask the reading expected_crc_value = (packet->data[9] & 0x0000FFFF); // 16 bits parameter that is the expected crc chunk_num = (packet->data[10] & 0x0000FFFF); // 16 bits parameter that is the total number of chunks specified in the TC if (chunk_num > MAX_CHUNK) { release_block((K_BLOCK *) &(msg->block)); return enqueue_exec_fail(EXF_LS_HDL_LCU_CRC_MAX_CHUNK, 0, NULL); } for (i = 0; i < chunk_num ; i++) { chunk_start[i] = (0xF00B0000 | (packet->data[11+2*i] & 0x0000FFFF)); chunk_len[i] = (0xF00C0000 | (packet->data[12+2*i] & 0x0000FFFF)); } // we can free the block from the TC_POOL release_block((K_BLOCK *) &(msg->block)); // init chunk counter chunk_current = 0; while( (chunk_len[chunk_current] & 0xFFFF) == 0 && chunk_current < MAX_CHUNK ) chunk_current++; if (chunk_current == MAX_CHUNK) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_LS_HDL_LCU_CRC_NOCHECK, 0, NULL); return enqueue_exec_compl(); } // store HK status, switch LCU requests OFF and wait for the possible pending reqs two be processed HK_status_storage = HK_SubsysStatus; HK_SubsysStatus = HK_SubsysStatus & LCU_OFF_MASK; task_ls_hdl_sleep(1000); // wait 1 sec // set start of crc computation if (ls_put_msg_hp(&chunk_start[chunk_current], NULL, 0, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // ask for crc computation if (ls_put_msg_hp(&chunk_len[chunk_current], NULL, 0, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // ask feedback at end if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, MKSTEP_VERIFY_LCU_CHUNK, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // done return RC_OK; } //---------------------- mkstep_verify_LCU_chunk ----------------------------------- //! this function performs a check on the LCU crc int mkstep_verify_LCU_chunk (LS_HDL_MSG * msg) { // compute wait time // !!!!!!!!!!!!!!!!!! check wait time computation verify_lcu_wait_time = 2 + (chunk_len[chunk_current] & 0xFFFF)/66; // wait specified time task_ls_hdl_sleep(verify_lcu_wait_time); // readback crc if (ls_put_msg_hp(&req_crc_read, &chunk_crc[chunk_current], 0, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_exec_fail(EXF_LS_HDL_LCU_OFF, 0, NULL); } // check if additional chunk need to be read chunk_current++; while( (chunk_len[chunk_current] & 0xFFFF) == 0 && chunk_current < MAX_CHUNK ) chunk_current++; if (chunk_current < MAX_CHUNK) { // set start of crc computation if (ls_put_msg_hp(&chunk_start[chunk_current], NULL, 0, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // ask for crc computation if (ls_put_msg_hp(&chunk_len[chunk_current], NULL, 0, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // ask feedback at end if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, MKSTEP_VERIFY_LCU_CHUNK, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } } else { // ask feedback at end if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, LAST_STEP_VERIFY_LCU_CHUNK, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } } // done return RC_OK; } //---------------------- last_step_verify_LCU_chunk ----------------------------------- //! this function performs a check on the LCU crc int last_step_verify_LCU_chunk (LS_HDL_MSG * msg) { unsigned int i, params[5], EVID; static unsigned int HL_stdby = 0xF0020202; // compute total crc read_crc_value = 0; for (i=0; i< MAX_CHUNK; i++) if ( (chunk_len[i]&0xFFFF) != 0 ) read_crc_value = read_crc_value + chunk_crc[i]; // compare crc if (( expected_crc_value & 0x0000FFFF ) != ( read_crc_value & 0x0000FFFF ) ) { // generate alarm params[0] = expected_crc_value; params[1] = read_crc_value; params[2] = HL_critical; if ( (HL_critical == 2)) { params[3] = ((HL_band_mask >> 16) & 0x0000FFFF) ; params[4] = (HL_band_mask & 0x0000FFFF); generate_event(EVENT_ALARM_REPORT, ERR_HK_ASK_LCU_TABLE_CRC, ERR_HK_ASK_LCU_TABLE_CRC, 5, params); } else { EVID=ERR_HK_ASK_LCU_CRIT_CRC+HL_critical; generate_event(EVENT_ALARM_REPORT, EVID, EVID, 3, params); } // goto standby1 if (ls_put_msg_hp(&HL_stdby, NULL, 0, NULL) != RC_OK) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_CMDEX_FIFOPUT_LS_HP_QUEUE, 0, NULL); //block communication // if ( HL_critical & 0xFFFF == 0xb00c || HL_critical & 0xFFFF == 0xb00d) // critical or safe (what is the difference ?????) if (HL_block_when_nok == 1) // block { if (ls_put_msg_hp(NULL, NULL, BLOCK_LCU_REQUEST, NULL) != RC_OK) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_CMDEX_FIFOPUT_LS_HP_QUEUE, 0, NULL); } else { if ( (HL_critical == 2)) // critical or safe (what is the difference ?????) { if (ls_put_msg_hp(&HL_band_mask, NULL, 0, NULL) != RC_OK) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_CMDEX_FIFOPUT_LS_HP_QUEUE, 0, NULL); } } } // restore HK_status HK_SubsysStatus = HK_status_storage; return enqueue_exec_compl(); } //---------------------- start_verify_LCU ----------------------------------- //! this function performs a check on the LCU crc int start_verify_LCU (LS_HDL_MSG * msg, int mode, int next_step) { TC_packet * packet; // prepare an auxiliary pointer to the TC packet packet = (TC_packet *) msg->block.pointer_to_data; // check that lcu is on if ((SubsysStatus & LCU_MASK) == 0) { release_block((K_BLOCK *) &(msg->block)); return enqueue_crc_fail( mode, EXF_LS_HDL_LCU_OFF); } // read packet params req_crc_computation = ((packet->data[4] & 0x0000FFFF) << 16 ) | (packet->data[5] & 0x0000FFFF); // 32 bits parameter that is the command to pass to the LCU to ask the crc computation verify_lcu_wait_time = (packet->data[6] & 0x0000FFFF); // 16 bits parameter that is the time to wait before crc reading req_crc_read = ((packet->data[7] & 0x0000FFFF) << 16 ) | 0x0000FFFF; // 16 bits parameter extended with FFFF that is the command to pass to the LCU to ask the reading expected_crc_value = (packet->data[8] & 0x0000FFFF); // 16 bits parameter that is the expected crc // we can free the block from the TC_POOL release_block((K_BLOCK *) &(msg->block)); // store HK status, switch LCU requests OFF and wait for the possible pending reqs two be processed HK_status_storage = HK_SubsysStatus; HK_SubsysStatus = HK_SubsysStatus & LCU_OFF_MASK; task_ls_hdl_sleep(1000); // wait 1 sec // ask for crc computation if (ls_put_msg_hp(&req_crc_computation, NULL, 0, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_crc_fail( mode, EXF_LS_HDL_ERROR_LS_HP_QUEUE); } // ask feedback at end if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, next_step, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_crc_fail( mode, EXF_LS_HDL_ERROR_LS_HP_QUEUE); } // done return RC_OK; } //---------------------- mkstep_verify_LCU ----------------------------------- //! this function performs a check on the LCU crc int mkstep_verify_LCU (LS_HDL_MSG * msg, int mode, int next_step) { // wait specified time task_ls_hdl_sleep(verify_lcu_wait_time); // readback crc if (ls_put_msg_hp(&req_crc_read, &read_crc_value, 0, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_crc_fail( mode, EXF_LS_HDL_ERROR_LS_HP_QUEUE); } // ask feedback at end if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, next_step, NULL) == RC_FAIL) { HK_SubsysStatus = HK_status_storage; return enqueue_crc_fail( mode, EXF_LS_HDL_ERROR_LS_HP_QUEUE); } // done return RC_OK; } //---------------------- last_step_verify_LCU ----------------------------------- //! this function performs a check on the LCU crc int last_step_verify_LCU (LS_HDL_MSG * msg, int mode) { unsigned int params[2]; // compare crc if (( expected_crc_value & 0x0000FFFF ) != ( read_crc_value & 0x0000FFFF ) ) { params[0] = expected_crc_value; params[1] = read_crc_value; generate_event(EVENT_ALARM_REPORT, ERR_HK_ASK_LCU_CRC, ERR_HK_ASK_LCU_CRC, 2, params); // set flag LCU_safe_and_block(); } // restore HK_status HK_SubsysStatus = HK_status_storage; if ( mode == 0 ) return enqueue_exec_compl(); else return RC_OK; } /*******************************************************************************************************/ /*******************************************************************************************************/ // Diplexer Scan without if power /*******************************************************************************************************/ /*******************************************************************************************************/ static int dip_scan_noif_data[MAX_DIPSCAN_DATA]; //!< we build the tm report packet in it static int diplexer_noif_step, diplexer_noif_time_step; //!< to hold the step sizes static unsigned int diplexer_noif_num_step; //!< number of the steps to be performed static int dip_scan_noif_cur_step; //!< number of the step being performed within a scan procedure (starts from zero) //---------------------- start_dip_scan_noif ----------------------------------- //! this function performs the starting phase of a diplexer scan without ifpower int start_dip_scan_noif (LS_HDL_MSG * msg) { LS_HDL_MSG mymsg; TC_packet * packet; int i; // prepare an auxiliary pointer to the TC packet packet = (TC_packet *) msg->block.pointer_to_data; // check that fcu is on if ((SubsysStatus & FCU_MASK) == 0) { release_block((K_BLOCK *) &(msg->block)); return enqueue_exec_fail(EXF_LS_HDL_FCU_OFF, 0, NULL); } // check on the number of steps requested if (packet->data[TC_N_DIPLEXER_IDX] > MAX_NSTEP_DIPSCAN_NOIFP) { release_block((K_BLOCK *) &(msg->block)); return enqueue_exec_fail(EXF_LS_HDL_DIPSCAN_NUM_STEP, 0, NULL); } // set the building block id Meas_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); Cur_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); // initialize some variables diplexer_noif_num_step = packet->data[4]; // number of steps requested diplexer_noif_time_step = packet->data[5]*100; // time to wait at each step diplexer_noif_step = packet->data[8]; // step size for diplexer position dip_scan_noif_cur_step = 0; // initialize the current step variable // Correct the sign of the step: extend with 1 if negative (2complement representation) if ( diplexer_noif_step & 0x8000 ) diplexer_noif_step = diplexer_noif_step | 0xFFFF0000; // write in dip_scan_noif_data[] the first 12 16-bit words of the report dip_scan_noif_data[0] = DIP_SCAN_NOIF_REP_SID; // sid is 270 UNPACK(&dip_scan_noif_data[1], Observation_ID); // obsid UNPACK(&dip_scan_noif_data[3], Meas_BuildingBlock_ID); // bbid for (i = 0; i < 4; i++) // some echos from the tc packet dip_scan_noif_data[5 + i] = packet->data[5 + i]; dip_scan_noif_data[11] = diplexer_noif_num_step; // HIF_Ndiplexer // free the block from the TC_POOL release_block((K_BLOCK *) &(msg->block)); // now we have to ask for mixer band hk values if (ls_put_msg_hp(&FCU_PS_HK[HF_DH1_MXBAND_IDX], &dip_scan_noif_data[9], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&FCU_PS_HK[HF_DV1_MXBAND_IDX], &dip_scan_noif_data[10], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // prepare and push a message into the LS_HDL_QUEUE fifo mymsg.operation_id = MKSTEP_DIP_SCAN_NOIF; mymsg.command_number = msg->command_number; // the message is labeled with the id number of this scan mymsg.block_loaded = 0; if (KS_FIFOPut(LS_HDL_QUEUE, (void *) &mymsg) == RC_FAIL) // send to task ls_hdl again return enqueue_exec_fail(EXF_LS_HDL_PUT_LS_HDL_QUEUE, 0, NULL); // execution failure else return RC_OK; } //--------------------- mkstep_dip_scan_noif ----------------------------------- //! generic step of a diplexer scan with no if power. int mkstep_dip_scan_noif (LS_HDL_MSG * msg) { static unsigned int FCU_CMD1, FCU_CMD2; // to hold the commands int i; // check termination of the scan if (dip_scan_noif_cur_step >= diplexer_noif_num_step) { // produce the report: we have all the data ready in array dip_scan_noif_data[] if (generate_report(APID1026, TM_HK_TYPE, TM_HK_SUBT, 12 + 8*diplexer_noif_num_step, dip_scan_noif_data) == RC_OK) { enqueue_exec_compl(); return RC_OK; } else return enqueue_exec_fail(EXF_LS_HDL_GEN_REP_FAIL, 0, NULL); } // check if FCU is on, otherwise return with an execution failure if ((SubsysStatus & FCU_MASK) == 0) return enqueue_exec_fail(EXF_LS_HDL_FCU_OFF, 0, NULL); // break scan // HERE STARTS the diplexer scan STEP: command diplexer position, wait, read Hk. FCU_CMD1 = FCU_config[HF_CH1_DPACT_C_IDX] | ((dip_scan_noif_data[TM_CH1_DP_POS0_IDX] + dip_scan_noif_cur_step*diplexer_noif_step) & 0x0FFF); if (ls_put_msg_hp(&FCU_CMD1, NULL, 0, NULL) == RC_FAIL) // this sets diplexer h position return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); FCU_CMD2 = FCU_config[HF_CV1_DPACT_C_IDX] | ((dip_scan_noif_data[TM_CH2_DP_POS0_IDX] + dip_scan_noif_cur_step*diplexer_noif_step) & 0x0FFF); if (ls_put_msg_hp(&FCU_CMD2, NULL, 0, NULL) == RC_FAIL) // this sets diplexer v position return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); task_ls_hdl_sleep(diplexer_noif_time_step); // 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_noif_data[12 + 8*dip_scan_noif_cur_step + i], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // the following message will be recognized by ls, which will then ask for another scan step if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, MKSTEP_DIP_SCAN_NOIF, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); dip_scan_noif_cur_step++; // increment the number of steps performed return RC_OK; } /******************************************************************************/ /******************************************************************************/ // FCU parameter scan /******************************************************************************/ /******************************************************************************/ #define MAX_NUM_PARAM_FCU_SCAN 497 // max number of 16-bit parameters to be put into the fcu scan report // 17 (from sid to HIF_Npoints) + 80x6 (max num of hk values) = 497 static int fcu_scan_data[MAX_NUM_PARAM_FCU_SCAN]; // we construct the tm report packet in it static int fcu_N_voltage, fcu_N_magnet; // to hold the number of iterations requested static int fcu_mag_cur_step, fcu_bias_volt_step, fcu_wait_time_step; // to hold the step sizes static unsigned int total_num_step; //----------------- start_fcu_param_scan --------------------------------------- // this function performs the starting phase of a fcu par scan: it writes some // variables (whose scope is this file) that govern the entire procedure and // writes (in the array fcu_scan_data[]) the initial part of the report; then it // starts the first step of the scan by putting a message in the LS_HDL_QUEUE. int start_fcu_param_scan (LS_HDL_MSG * msg) { LS_HDL_MSG mymsg; TC_packet * packet; int i; // prepare an auxiliary pointer to the TC packet packet = (TC_packet *) msg->block.pointer_to_data; // check on the requested number of bias voltage steps (it has to be >= 1) if ((packet->data[TC_NVOL_IDX]) < 1) { enqueue_exec_fail(EXF_CMDEX_PAR_SCAN_WRONG_NVOLTAGE, 1, &(packet->data[TC_NVOL_IDX])); release_block((K_BLOCK *) &(msg->block)); return RC_FAIL; } // check on the total number of requested steps (it has to be <= 80) if (((packet->data[TC_NVOL_IDX])*(packet->data[TC_NMAG_IDX])) > 80) { enqueue_exec_fail(EXF_CMDEX_PAR_SCAN_WRONG_STEP_NUMBER, 2, &(packet->data[TC_NVOL_IDX])); release_block((K_BLOCK *) &(msg->block)); return RC_FAIL; } // check if FCU is on, otherwise return with an execution failure if ((SubsysStatus & FCU_MASK) == 0) { release_block((K_BLOCK *) &(msg->block)); return enqueue_exec_fail(EXF_LS_HDL_FCU_OFF, 0, NULL); } // set the building block id Meas_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); Cur_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); // extract some parameters from the TC and initialize some variables fcu_N_voltage = packet->data[4]; // number of bias voltage steps to be performed fcu_N_magnet = packet->data[5]; // number of magnet current steps to be performed fcu_wait_time_step = packet->data[6]*100; // time to wait fcu_bias_volt_step = packet->data[9]; // mixer bias voltage step fcu_mag_cur_step = packet->data[12]; // magnet current step // Correct the sign of the step: extend with 1 if negative (2complement representation) if ( fcu_mag_cur_step & 0x8000 ) fcu_mag_cur_step = fcu_mag_cur_step | 0xFFFF0000; // Correct the sign of the step: extend with 1 if negative (2complement representation) if ( fcu_bias_volt_step & 0x8000 ) fcu_bias_volt_step = fcu_bias_volt_step | 0xFFFF0000; // compute the total number of steps to be performed if (fcu_N_magnet == 0) total_num_step = fcu_N_voltage; else total_num_step = fcu_N_voltage*fcu_N_magnet; // write in fcu_scan_data[] the first 17 16-bit words of the report fcu_scan_data[0] = FCU_PSCAN_SID; // sid is 266 UNPACK(&fcu_scan_data[1], Observation_ID); // obsid UNPACK(&fcu_scan_data[3], Meas_BuildingBlock_ID); // bbid for (i = 0; i < 9; i++) // some echos from the tc packet fcu_scan_data[5 + i] = packet->data[4 + i]; fcu_scan_data[16] = total_num_step; // free the block from the TC_POOL release_block((K_BLOCK *) &(msg->block)); // now we have to ask once for all for mixer band hk values if (ls_put_msg_hp(&FCU_PS_HK[HF_DH1_MXBAND_IDX], &fcu_scan_data[14], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); if (ls_put_msg_hp(&FCU_PS_HK[HF_DV1_MXBAND_IDX], &fcu_scan_data[15], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); scan_cur_step = 0; // reset this important variable // prepare and push a message into the LS_HDL_QUEUE fifo mymsg.operation_id = MKSTEP_FCU_PARAM_SCAN; mymsg.command_number = msg->command_number; // the message is labeled with the id number of this scan mymsg.block_loaded = 0; if (KS_FIFOPut(LS_HDL_QUEUE, (void *) &mymsg) == RC_FAIL) // send to task ls_hdl again return enqueue_exec_fail(EXF_LS_HDL_PUT_LS_HDL_QUEUE, 0, NULL); // execution failure else return RC_OK; } //---------------- mkstep_fcu_param_scan --------------------------------------- // single step of a fcu scan procedure: 1) performs 3 checks (FCU on, label, // termination); 2) sets currents (if necessary) and voltages; 3) waits and then // asks for hk values; 4) asks for another step by putting a message in the // LS_HDL_QUEUE; 5) increments the number of steps performed. int mkstep_fcu_param_scan (LS_HDL_MSG * msg) { static unsigned int FCU_CMD1, FCU_CMD2, FCU_CMD3, FCU_CMD4; // to hold the commands int dest_index, i, k; // check if FCU is on, otherwise return with an execution failure if ((SubsysStatus & FCU_MASK) == 0) return enqueue_exec_fail(EXF_LS_HDL_FCU_OFF, 0, NULL); // break fcu scan // check termination of the scan if (scan_cur_step >= total_num_step) { // produce the report: we have all the data ready in array fcu_scan_data[] if (generate_report(APID1026, TM_HK_TYPE, TM_HK_SUBT, 17 + 6*total_num_step, fcu_scan_data) == RC_OK) { enqueue_exec_compl(); return RC_OK; } else return enqueue_exec_fail(EXF_LS_HDL_GEN_REP_FAIL, 0, NULL); } // HERE STARTS the fcu scan STEP // every fcu_N_voltage steps we have to set the magnet currents, provided // that fcu_N_magnet is != 0 if ((fcu_N_magnet != 0) && (IFSI_MOD(scan_cur_step, fcu_N_voltage) == 0)) { FCU_CMD1 = FCU_PS_CMD[HF_CH1_MX_MG_C_IDX] | ((fcu_scan_data[11] + (scan_cur_step / fcu_N_voltage)*fcu_mag_cur_step) & 0x0FFFF); if (ls_put_msg_hp(&FCU_CMD1, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); FCU_CMD2 = FCU_PS_CMD[HF_CV1_MX_MG_C_IDX] | ((fcu_scan_data[12] + (scan_cur_step / fcu_N_voltage)*fcu_mag_cur_step) & 0x0FFFF); if (ls_put_msg_hp(&FCU_CMD2, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); } // now set the voltages FCU_CMD3 = FCU_PS_CMD[HF_CH1_MXBIAS_V_IDX] | ((fcu_scan_data[8] + IFSI_MOD(scan_cur_step, fcu_N_voltage)*fcu_bias_volt_step) & 0x0FFFF); if (ls_put_msg_hp(&FCU_CMD3, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); FCU_CMD4 = FCU_PS_CMD[HF_CV1_MXBIAS_V_IDX] | ((fcu_scan_data[9] + IFSI_MOD(scan_cur_step, fcu_N_voltage)*fcu_bias_volt_step) & 0x0FFFF); if (ls_put_msg_hp(&FCU_CMD4, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); task_ls_hdl_sleep(fcu_wait_time_step); // wait the specified time period // prepare destination index into array fcu_scan_data[] dest_index = 17 + scan_cur_step*6; // each step produces 6 16-bit words for the report for (i = 2, k = 0; i < FCU_PS_HK_len; i++, k++) // request 6 hk values if (ls_put_msg_hp(&FCU_PS_HK[i], &fcu_scan_data[dest_index + k], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // the following message will be recognized by ls, which will then ask for another scan step if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, MKSTEP_FCU_PARAM_SCAN, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); scan_cur_step++; // increment the number of steps performed return RC_OK; } /******************************************************************************************/ /******************************************************************************************/ // LCU IV curve /******************************************************************************************/ /******************************************************************************************/ #define LCU_IV_REP_NUM_WORDS 17 // number of 16-bit words in the source data field of the LCU iv curve report static int lcu_ivcurve_data[LCU_IV_REP_NUM_WORDS]; // we write the source data field of the tm report in it static int LCU_status; //----- measure_LCU_ivcurve ---------------------------------------------------- // this function: 1) checks if LCU is on; 2) writes in the array lcu_ivcurve_data[] // some data to be put in the final report; 3) sends to ls task the command received // from the TC and then waits the amount of time specified by the tc; 4) asks // for 8 lcu parameters; 5) waits for an event to signal the end of transaction; int measure_LCU_ivcurve (LS_HDL_MSG *msg) { TC_packet * packet; unsigned int i, k, command, wait_time; static int goto_diagnostics = 0xF0040404; static int goto_normal = 0xF0030303; // prepare an auxiliary pointer to the TC packet packet = (TC_packet *) msg->block.pointer_to_data; // check if LCU is on, otherwise return with an execution failure if ((SubsysStatus & LCU_MASK) == 0) { release_block((K_BLOCK *) &(msg->block)); return enqueue_exec_fail(EXF_LS_HDL_LCU_OFF, 0, NULL); } // set the building block id Meas_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); Cur_BuildingBlock_ID = PACK(packet->data[TC_BBID_IDX], packet->data[TC_BBID_IDX + 1]); // write in lcu_ivcurve_data[] the first 8 16-bit words of the data field of the report lcu_ivcurve_data[0] = LCU_IV_SID; // sid is 259 UNPACK(&lcu_ivcurve_data[1], Observation_ID); // obsid UNPACK(&lcu_ivcurve_data[3], Meas_BuildingBlock_ID); // bbid // some echos from the tc packet for (i = 0; i < 3; i++) lcu_ivcurve_data[5 + i] = packet->data[4 + i]; // now we can free the block from the TC_POOL release_block((K_BLOCK *) &(msg->block)); // LCU needs to be in diagnostic mode during IV curve measurement (SCR979): set it if (ls_put_msg_hp(&goto_diagnostics, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // now build the 32-bit command and compute the delay time command = (lcu_ivcurve_data[5] << 16) | (lcu_ivcurve_data[6] & 0x0FFFF); wait_time = 1000*lcu_ivcurve_data[7]+3; // the time received is in sec: we convert it to msec // send to ls task the 32-bit command if (ls_put_msg_hp(&command, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // wait the specified time task_ls_hdl_sleep(wait_time); // send to ls task the HL_SET_PAge command if (ls_put_msg_hp(&LCU_IV_param[0], NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // now ask for commanded hk values for (i = 1, k = 0; i < LCU_IV_param_len; i++, k++) if (ls_put_msg_hp(&LCU_IV_param[i], &lcu_ivcurve_data[8 + k], 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // LCU needs to be in normal mode after IV curve measurement (SCR979): set it if (ls_put_msg_hp(&goto_normal, NULL, 0, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); // ask feedback to LS upon termination if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, LCU_IVCURVE_STATUS, NULL) == RC_FAIL) return enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); return RC_OK; } //------------------- read_status_LCU_ivcurve ---------------------------------- void read_status_LCU_ivcurve(LS_HDL_MSG *msg) { static int read_LCU_status = 0xB200FFFF; // when we are here the LCU goto normal command has jus been issued by LS: wait 37 msec and read the status, then trigger the report request // note that LS waits 3 msec so the total delay between the set and read status is around 40 msec task_ls_hdl_sleep(37); // read LCU status and ask for report as soon as the status has been read if (ls_put_msg_hp(&read_LCU_status, &LCU_status, 0, NULL) == RC_FAIL) { enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); return; } // ask feedback to LS upon termination this message will be recognized by ls, which will then ask for the final report generation if (ls_put_msg_hp(NULL, (unsigned int *) msg->command_number, LCU_IVCURVE_REPORT, NULL) == RC_FAIL) { enqueue_exec_fail(EXF_LS_HDL_ERROR_LS_HP_QUEUE, 0, NULL); return; } } //------------------- send_report_LCU_ivcurve ---------------------------------- int send_report_LCU_ivcurve (void) { // produce the report: we have all the data ready in the array lcu_ivcurve_data[] if (generate_report(APID1026, TM_HK_TYPE, TM_HK_SUBT, LCU_IV_REP_NUM_WORDS, lcu_ivcurve_data) == RC_OK) { // check that the LCU status is back to normal: otherwise issue exec failure if ( (LCU_status & 0x00F0) != 0x00A0 ) return enqueue_exec_fail(EXF_LS_HDL_LCU_NOT_NORM, 0, NULL); enqueue_exec_compl(); return RC_OK; } else { // execution failure // check that the LCU status is back to normal: otherwise issue exec failure if ( (LCU_status & 0x00F0) != 0x00A0 ) return enqueue_exec_fail(EXF_LS_HDL_LCU_NOT_NORM, 0, NULL); return enqueue_exec_fail(EXF_LS_HDL_GEN_REP_FAIL, 0, NULL); } } /******************************************************************************* ********************************* SERVICE FUNCTIONS **************************** *******************************************************************************/ //-------------- task_ls_hdl_sleep --------------------------------------------- // this function makes the ls_hdl task sleep for sleep_time by using the semaphore // LS_HDL_WAIT_SEMA signalled through the timer ls_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 LS_HDL_WAIT_SEMA; nevertheless note that // KS_TaskSleep() is still used when the sleep period is small or not commandable by TC. void task_ls_hdl_sleep (unsigned int sleep_time) { if ( sleep_time < 1 ) return; KS_SemaReset(LS_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(ls_hdl_Timer, sleep_time, 0, LS_HDL_WAIT_SEMA); // now make the task wait on the semaphore KS_SemaTestW(LS_HDL_WAIT_SEMA); }