// $RCSfile: data_hdl.c,v $Revision: 1.52 $Date: 2005/03/11 15:08:57 #include "allnodes.h" #include "data_hdl.dox" #include "node1.h" #include #include "configura.h" #include "pubfuncs.h" #include "time_tsk.h" #include "cmd_seq.h" #include "hs0.h" #include "ls.h" #include "cmd_exec.h" #include "tables.h" #include "hs_lib.h" #include "hs_hdl.h" #include "err_hdl.h" #include "hs1.h" #include "MM_misc.h" #include "data_hdl.h" //---------------------- Global Variables -------------------------------------- SD_TM_MSG sd_msg; // to hold the message to be sent in fifo SD_TM_QUEUE (i.e. towards task tmtc) unsigned int HRS_duration, WBS_duration; FRAME_BUF_HDL Sd_hdl[4]; // array of SD buffer handlers: one for each subsystem unsigned int AID_spectroscopy; //! Activity ID for the spectroscopy measurement. unsigned int Meas_spectr; // Spectrometers involved in current activity unsigned int wbs_att_setting[2]; // to store the wbs attenuator setting as required for wbs calibration (index 0 is for wbsh) unsigned int zero_switch_setting[2]; // to store the zero switch setting as required for wbs calibration (index 0 is for wbsh) // steps performed during a mixer magnet current tuning procedure (note: index 0 is for wbsh, and so on) unsigned int NSPECTR; // number of spectrometers involved in the current measurement (from 0 to 4) unsigned int NSP_HRS; // number of hrs spectrometers involved in the current measurement (from 0 to 2) unsigned int NSP_WBS; // number of wbs spectrometers involved in the current measurement (from 0 to 2) //----------------------- Local Variables -------------------------------------- static START_FRAME_DATA Spect_latched_time; // Spectroscopy latched time static unsigned int hrs_tuning_loops; // counter for the number of hrs loops static unsigned int hrs_init_loops; // counter for the number of hrs tuning init loops static unsigned int wbs_tuning_loops; // counter for the number of wbs loops static unsigned int wbs_cal_frame_counter; // counter of the number of wbs frames received during a calibration static unsigned int end_of_measure_flg; static unsigned int mixmag_loops = 0; // for mixer magnet tuning: counter of the number of steps executed, without polarization distinction static unsigned int dipscan_frames_received = 0; // for diplexer scan with if power: counter of the frames received during a dip scan static unsigned int dipscan_step = 0; // for diplexer scan with if power: counter of steps performed (it starts from zero) static unsigned int nloop[4] = {0,0,0,0}; // for each of the four spectrometers, it counts the number of //----------------------- Local Functions -------------------------------------- void packetize_HRS (unsigned int, unsigned int, unsigned int); void packetize_WBS (unsigned int, unsigned int, int, unsigned int, int); void write_science_headers (unsigned int, unsigned int, int); void write_hrs_start_frame (unsigned int, unsigned int, unsigned int, int, int *); void write_wbs_start_frame (unsigned int, unsigned int, unsigned int, int, int, int *, int); void packetize_IFHRS (unsigned int, unsigned int); void packetize_IFWBS (unsigned int, int, unsigned int); void check_if_measure_is_over (int); void check_termination_fast_chop (int); void trigger_next_step (unsigned int, unsigned int, int); void close_and_reinit (void); void send_IFWBS_report(unsigned int * ifpower_wbs, unsigned int subsysid, unsigned int phase); void send_IFHRS_report (unsigned int subsysid, unsigned int phase, unsigned int *conf_gaas, int *ifpower, int npar); void exec_attach_hk (START_FRAME_DATA * destination ); void attach_6_HK_to_start_frame(unsigned int * ptr, START_FRAME_DATA * Spect_latched_time); //----------------------- Task data_hdl ---------------------------------------- void data_hdl (void) { SD_PKT_MSG sd_in_queue; // to hold the message received from task hs1 while (1) { // wait for a message in the queue if (KS_FIFOGetW(SD_PKT_QUEUE, &sd_in_queue) != RC_OK) continue; // the data block coming from hs1 is attached to the message to be sent to tmtc sd_msg.block = sd_in_queue.block; // process data and prepare packets depending on field measID, which // contains, apart from special cases, the AID_spectroscopy value switch (sd_in_queue.measID) { /*---------------- special messages for HS chain status control --*/ // check if it is a special packet to reset the frame counters case FRAME_HRS_V_ID: if (fifo_3_pending_frames > 0) fifo_3_pending_frames--; break; case FRAME_HRS_H_ID: if (fifo_2_pending_frames > 0) fifo_2_pending_frames--; break; case FRAME_WBS_V_ID: if (fifo_1_pending_frames > 0) fifo_1_pending_frames--; break; case FRAME_WBS_H_ID: if (fifo_0_pending_frames > 0) fifo_0_pending_frames--; break; /*------------------------------------------------ attach Hk request --*/ case ATTACH_HK_REQ: exec_attach_hk( (START_FRAME_DATA*) sd_in_queue.subsysID ); // the start frame structure is passed by means of the subsysID break; /*------------------------------------------------ spectroscopy --*/ case TC_FUNMAN_SPCTRTP_AID: // total power case TC_FUNMAN_SPCTRSC_AID: // slow chop case TC_FUNMAN_SPCTRFS_AID: // frequency switch get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame if (sd_in_queue.subsysID == HRS_V_ID || sd_in_queue.subsysID == HRS_H_ID) { hrs_right_shift(); packetize_IFHRS(sd_in_queue.subsysID, sd_in_queue.phase); packetize_HRS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.transfer_cnt); } else { wbs_right_shift(); packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); } check_if_measure_is_over(sd_in_queue.subsysID); break; case TC_FUNMAN_SPCTRFC_AID: // fast chop get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame if (sd_in_queue.subsysID == HRS_V_ID || sd_in_queue.subsysID == HRS_H_ID) { hrs_right_shift(); packetize_IFHRS(sd_in_queue.subsysID, sd_in_queue.phase); packetize_HRS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.transfer_cnt); } else { wbs_right_shift(); packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); } check_termination_fast_chop(sd_in_queue.subsysID); break; case TC_FUNMAN_SPCTRSM_AID: // simulated science get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame if (sd_in_queue.subsysID == HRS_V_ID || sd_in_queue.subsysID == HRS_H_ID) { hrs_right_shift(); packetize_HRS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.transfer_cnt); } else { wbs_right_shift(); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); } break; /*------------------------------------------------ new wbs calibration --*/ case NEW_CALIB_INIT_AID: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame new_cal_init_loops--; save_hrs_status(sd_in_queue.block.pointer_to_data, sd_in_queue.subsysID); release_block((K_BLOCK *) &sd_in_queue.block); if ( new_cal_init_loops == 0 ) trigger_next_step(START_NEW_CALIB_RUN, sd_in_queue.subsysID, 0); break; case NEW_CALIB_RUN_AID: case NEW_CALIB_CLOSE_AID: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame if (sd_in_queue.subsysID == HRS_V_ID || sd_in_queue.subsysID == HRS_H_ID) { hrs_right_shift(); packetize_IFHRS(sd_in_queue.subsysID, sd_in_queue.phase); packetize_HRS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.transfer_cnt); } else { int pass_this_frame; int shift_this_frame; // in general we pass and shift the frame pass_this_frame = 1; shift_this_frame = 1; if ( sd_in_queue.subsysID == WBS_H_ID ) { // decrease the number of wbs frames to process new_cal_pending_wbs_h_frames--; // we have to kill the last wbs-h frame if (new_cal_pending_wbs_h_frames == 0) pass_this_frame = 0; // we have not to shift the first wbs frame if (new_cal_pending_wbs_h_frames == 2) shift_this_frame = 0; } else { // decrease the number of wbs frames to process new_cal_pending_wbs_v_frames--; // we have not to shift the first wbs frame if (new_cal_pending_wbs_v_frames == 2) shift_this_frame = 0; } if ( pass_this_frame ) { if ( shift_this_frame ) wbs_right_shift(); packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, shift_this_frame); } } // check termination if ( new_cal_pending_wbs_h_frames + new_cal_pending_wbs_v_frames == 0 ) { restore_hrs_status(); close_and_reinit(); } break; /*-------------------------------------------------- wbs tuning --*/ case ZSCAN_ID: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame zscan_WBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt); packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); wbs_tuning_loops++; if (wbs_tuning_loops == NSPECTR) trigger_next_step(WBS_ATTSETT2_ID, sd_in_queue.subsysID, 1); break; case WBS_ATTSETT2_ID: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame packetize_ATTWBS2(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt); packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); wbs_tuning_loops++; if (wbs_tuning_loops == NSPECTR*2) trigger_next_step(WBS_ATTSETT3_ID, sd_in_queue.subsysID, 1); break; case WBS_ATTSETT3_ID: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame packetize_ATTWBS2(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt); packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); wbs_tuning_loops++; if (wbs_tuning_loops == NSPECTR*3) close_and_reinit(); break; /*-------------------------------------------------- hrs functional test --*/ case HRS_FUNCTEST: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame hrs_right_shift(); packetize_IFHRS(sd_in_queue.subsysID, sd_in_queue.phase); packetize_HRS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.transfer_cnt); close_and_reinit(); break; /*-------------------------------------------------- hrs tuning --*/ case HRS_TUNE_INIT: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame hrs_init_loops++; save_hrs_status(sd_in_queue.block.pointer_to_data, sd_in_queue.subsysID); release_block((K_BLOCK *) &sd_in_queue.block); if ( hrs_init_loops == hrs_total_init_loops ) trigger_next_step(HRS_ATTSETT_ID, sd_in_queue.subsysID, 1); break; case HRS_ATTSETT_ID: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame packetize_ATTHRS(sd_in_queue.subsysID); packetize_IFHRS(sd_in_queue.subsysID, sd_in_queue.phase); packetize_HRS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.transfer_cnt); hrs_tuning_loops++; if (hrs_tuning_loops == NSPECTR) trigger_next_step(HRS_ATTSETT2_ID, sd_in_queue.subsysID, 1); break; case HRS_ATTSETT2_ID: get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame packetize_ATTHRS2(sd_in_queue.subsysID); packetize_IFHRS(sd_in_queue.subsysID, sd_in_queue.phase); packetize_HRS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.transfer_cnt); hrs_tuning_loops++; if (hrs_tuning_loops == (NSPECTR*2) ) { restore_hrs_status(); close_and_reinit(); } break; /*------------------------------------- wbs mixer magnet tuning --*/ case TUNE_WMIXMAG_ID: // wbs mixer magnet tuning get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame nloop[sd_in_queue.subsysID]++; tune_wmixmag(sd_in_queue.subsysID, nloop, sd_in_queue.int_scan_cnt); release_block((K_BLOCK *) &sd_in_queue.block); mixmag_loops++; // check completion of mixer magnet tuning procedure if (mixmag_loops == (NSP_WBS*WBS_duration*mixer_magnet_data[NMAGNET_IDX])) // end of tuning { set_magnet_opt_current(sd_in_queue.measID); // set currents to the opt value send_mixmag_rep(sd_in_queue.measID); // send the report tm packet nloop[WBS_V_ID] = nloop[WBS_H_ID] = 0; // reset the counters mixmag_loops = 0; close_and_reinit(); } break; /*------------------------------------- hrs mixer magnet tuning --*/ case TUNE_HMIXMAG_ID: // hrs mixer magnet tuning get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame nloop[sd_in_queue.subsysID]++; tune_hmixmag(sd_in_queue.subsysID, nloop); release_block((K_BLOCK *) &sd_in_queue.block); mixmag_loops++; // check completion of mixer magnet tuning procedure if (mixmag_loops == (NSP_HRS*HRS_duration*mixer_magnet_data[NMAGNET_IDX])) // end of tuning { set_magnet_opt_current(sd_in_queue.measID); // set currents to the opt value send_mixmag_rep(sd_in_queue.measID); // send the report tm packet nloop[HRS_V_ID] = nloop[HRS_H_ID] = 0; // reset the counters mixmag_loops = 0; close_and_reinit(); } break; /*----------------------------- diplexer scan with hrs if power --*/ case DIP_SCAN_IF_ID: // diplexer scan with if power get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame dipscan_compute_ifpower(sd_in_queue.subsysID, dipscan_step); // compute and store IF powers release_block((K_BLOCK *) &sd_in_queue.block); dipscan_frames_received++; // check completion of diplexer scan procedure if (dipscan_frames_received == (NSP_HRS*HRS_duration*dip_scan_if_data[TM_N_DIPLEXER_IDX])) // end of scan { // produce the report: we have all the data ready in array dip_scan_if_data[] generate_report(APID1026, TM_HK_TYPE, TM_HK_SUBT, 12 + DIP_SCAN_DATA*dip_scan_if_data[TM_N_DIPLEXER_IDX], dip_scan_if_data); dipscan_frames_received = dipscan_step = 0; // reset close_and_reinit(); } else if (NSP_HRS == 1 || dipscan_frames_received%2 == 0) // if NSP_HRS = 1 only one spectrometer is working; otherwise send the message every two frames dipscan_step++; // increment the step counter break; /*---------------------------------------------------- wbs comb --*/ case WBS_COMB_STEP1_ID: // wbs calibration: first step get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); wbs_cal_frame_counter++; if (wbs_cal_frame_counter == NSPECTR) trigger_next_step(WBS_COMB_STEP2_ID, sd_in_queue.subsysID, 1); break; case WBS_COMB_STEP2_ID: // wbs calibration: second step get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame wbs_right_shift(); packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); wbs_cal_frame_counter++; if (wbs_cal_frame_counter == NSPECTR*2) close_and_reinit(); break; /*---------------------------------------- wbs zero measurement --*/ case SPECTROSCOPY_WBS_ZERO_ID: // wbs zero measurement get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame wbs_right_shift(); packetize_IFWBS(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt, sd_in_queue.phase); packetize_WBS(sd_in_queue.subsysID, sd_in_queue.phase, sd_in_queue.int_scan_cnt, sd_in_queue.transfer_cnt, 1); wbs_cal_frame_counter++; if (wbs_cal_frame_counter == NSPECTR) close_and_reinit(); break; /*----------------------------------------------------- peak up --*/ case PEAKUP_ACQUIRE_HRS: // hrs peakup acquire get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame peakup_hrs_compute_ifpower(sd_in_queue.subsysID); // compute and store average IF power peakup_report(sd_in_queue.subsysID); // produces the step report release_block((K_BLOCK *) &sd_in_queue.block); close_and_reinit(); break; case PEAKUP_ACQUIRE_WBS: // wbs peakup acquire get_TS_in_pool(&Spect_latched_time, sd_in_queue.time_position); // refresh the time stamp if one is attached to the frame peakup_wbs_compute_ifpower(sd_in_queue.subsysID, sd_in_queue.int_scan_cnt); // compute and store average IF power peakup_report(sd_in_queue.subsysID); // produces the step report release_block((K_BLOCK *) &sd_in_queue.block); close_and_reinit(); break; /*----------------------------------------------------------------*/ default: generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_INVALID_MEAS_ID, 1, &(sd_in_queue.measID)); // here we could release the block, but not necessarily there is a block! break; } // end switch on sd_in_queue.measID } } //----------------------- check_if_measure_is_over ----------------------------- //! check if a measurement is over. If yes performs a reset of the HS subsystem void check_if_measure_is_over (int fifo_id) { int k; // decrease the duration field for fifo_id Sd_hdl[fifo_id].duration -= Sd_hdl[fifo_id].int_num; // if the duration field is <= 0, set the corresponding bit in the // end-of-measurement flag if (Sd_hdl[fifo_id].duration <= 0) end_of_measure_flg |= (0x40 >> (3-fifo_id)); // check if end of measurement (when end_of_measure_flg is equal to Meas_spectr) if (end_of_measure_flg == Meas_spectr) { // switch off the VM stop_VM(); // send completion ack enqueue_exec_compl(); // set AID_spectroscopy to 0 (i.e. reenable Hk acquisition from spectrometers) AID_spectroscopy = REQUIRING_HK; // set the duration field to 1 for (k = 0; k < 4; k++) Sd_hdl[k].duration = 1; } } //----------------------- check_termination_fast_chop -------------------------- //! check if a fast_chop measurement is over. If yes performs a reset of the HS subsystem void check_termination_fast_chop (int fifo_id) { int k; Sd_hdl[fifo_id].duration -= Sd_hdl[fifo_id].int_num; // Check if end of measurement, i.e. if no more frames are expected if ((Sd_hdl[0].duration <= 0) && (Sd_hdl[1].duration <= 0) && (Sd_hdl[2].duration <= 0) && (Sd_hdl[3].duration <= 0)) { // switch off the VM stop_VM(); // send completion ack enqueue_exec_compl(); // set AID_spectroscopy to 0 (i.e. reenable Hk acquisition from spectrometers) AID_spectroscopy = REQUIRING_HK; // set the duration field to 1 for (k = 0; k < 4; k++) Sd_hdl[k].duration = 1; } } //----------------------- close_and_reinit ------------------------------------- //! this function is called when a command is terminated and performs a sequence of actions needed upon termination. void close_and_reinit (void) { // execution completion ack enqueue_exec_compl(); // the following is to reinitialize some variables init_spec_table(); // set Activity ID to 0 (i.e. reenable Hk acquisition from spectrometers) AID_spectroscopy = REQUIRING_HK; } //----------------------- reset_data_hdl --------------------------------------- //! This function inits several static variables of the data_hdl module void reset_data_hdl (void) { int i, j; end_of_measure_flg = 0; // compute NSPECTR only if SS in ON and active in the measurement NSPECTR = 0; for (i=3, j=0x40; i>=0; j >>=1, i--) if ((Meas_spectr & j)) NSPECTR++; NSP_HRS = 0; for (i=3, j=0x40; i>=2; j >>=1, i--) if ((Meas_spectr & j)) NSP_HRS++; NSP_WBS = 0; for (i=1, j=0x10; i>=0; j >>=1, i--) if ((Meas_spectr & j)) NSP_WBS++; // then reset some counters hrs_tuning_loops = 0; hrs_init_loops = 0; wbs_tuning_loops = 0; mixmag_loops = 0; dipscan_frames_received = dipscan_step = 0; wbs_cal_frame_counter = 0; for (i = 0; i < 4; i++) nloop[i] = 0; } //----------------------- packetize_HRS ---------------------------------------- //! This function is used to format and pass a HRS Science Data frame to task tmtm_if for relaying to ground as a sequence of TM packets // argument phase represents the integration buffer (0 for buffer 1, 1 for buffer 2) void packetize_HRS (unsigned int subsysid, unsigned int phase, unsigned int transfer_cnt) { int k, l, n, m, packt_count = 0; unsigned int select, offset, head_chan[48]; select = Spectroscopy_table[Sd_hdl[subsysid].range_sel]; // if nothing has been selected, we can release the SD_POOL block and skip the following if ((select & 0xFF) == 0) { release_block(&sd_msg.block); return; } // span the datablock_id vector (k) and the range selection (l) // K is the block index within the pool block, not the absolute data block for (k = 0, l = 0x1; k < 8; l <<= 1, k++) { if (select & l) packt_count += 2; // extract and reorder the first 3 channels of each subblock before the right shifting for (m = 0; m < 2; m++) { for (n = 0; n < 3; n++) { offset = SD_TM_HEADER + m*HRS_SUBBLOCK_DATA_LEN+ k*HRS_BLOCK_DATA_LEN + n; head_chan[(k*6)+n+(m*3)] = *(unsigned int *)(sd_msg.block.pointer_to_data + offset); } } } // set the packing field of the message towards tmtc sd_msg.packing = 0x0FF & PACKING_24; sd_msg.packing |= SDH_SD_WLEN << 8; // write the TM packet header at the beginning of the memory block // referenced by the top level variable sd_msg.block write_science_headers(subsysid, phase, packt_count); // this call produces the start frame packet write_hrs_start_frame(subsysid, phase, transfer_cnt, packt_count, (int *) head_chan); Sd_hdl[subsysid].isn++; // increment integration sequence number for (k = 0, l = 0x1; k < 8; l <<= 1, k++) if (select & l) { sd_msg.first_ch = k * HRS_BLOCK_DATA_LEN; sd_msg.offset = SD_TM_HEADER + sd_msg.first_ch; sd_msg.count = (--packt_count); // pre-decrement packt_count as a packet will be produced sd_msg.length = HRS_SUBBLOCK_DATA_LEN; if (KS_FIFOPut(SD_TM_QUEUE, &sd_msg) == RC_FAIL) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_FIFOPUT_SD_TM_QUEUE, 0, NULL); // SECOND PACKET (second sub-block channels 259 to 516) sd_msg.first_ch = HRS_SUBBLOCK_DATA_LEN + k * HRS_BLOCK_DATA_LEN; sd_msg.offset = SD_TM_HEADER + sd_msg.first_ch; sd_msg.count = (--packt_count); // pre-decrement packt_count as a packet will be produced // note: field count must reach 0 to signal to task tmtc that the block in SD_POOL must be released sd_msg.length = HRS_SUBBLOCK_DATA_LEN; if (KS_FIFOPutWT(SD_TM_QUEUE, &sd_msg, 30) != RC_OK) // 30 msec time out { if (sd_msg.count == 0) release_block(&sd_msg.block); generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_FIFOPUT_SD_TM_QUEUE, 0, NULL); } } } //----------------------- packetize_WBS ---------------------------------------- //! This function is used to format and pass a WBS Science Data frame to task tmtm_if for relaying to ground as a sequence of TM packets // argument phase represents the integration buffer (0 for buffer 1, 1 for buffer 2) void packetize_WBS (unsigned int subsysid, unsigned int phase, int scan_count, unsigned int transfer_cnt, int frame_was_shifted) { unsigned int k, start, stop, byte_num, ch_per_pack, bytes_per_pack, ii = 0; int j, ll, offset, numpack = 0, packt_count[4]; unsigned int right_shift, dark_pix[16]; int *p_dark = dark_pix; // set packetization flag sd_msg.packing = 0x0FF & Spectroscopy_table[HIF_WBS_packing_IDX]; // set the length of data header sd_msg.packing |= SDH_SD_WLEN << 8; sd_msg.packing |= SCIP << 16; // cycle over the 8 parameters of the 4 range selections start = Sd_hdl[subsysid].range_sel; stop = start + 8; for (j = 0; j < 4; j++) packt_count[j] = 0; ch_per_pack = SD_TM_MAX_PKT / (Spectroscopy_table[HIF_WBS_packing_IDX] + 1); //adjust to have an even number of bytes-> even number of 16bit words if ( (ch_per_pack*(Spectroscopy_table[HIF_WBS_packing_IDX] + 1)) & 1) ch_per_pack--; bytes_per_pack = (ch_per_pack*(Spectroscopy_table[HIF_WBS_packing_IDX] + 1)); for (k = start; k < stop; k += 2, ii++) { for (ll = 0; ll < 4; ll++) { offset = SD_TM_HEADER + ii*WBS_BLOCK_DATA_LEN + ll; dark_pix[ii*4 + ll] = *(unsigned int *)(sd_msg.block.pointer_to_data + offset); } // compute the number of packets according to HIF_WBS_packing //ADG #channels * #bytes/channel byte_num = (Spectroscopy_table[k + 1] * (Spectroscopy_table[HIF_WBS_packing_IDX] + 1)); // number of packets for each CCD packt_count[ii] = byte_num / bytes_per_pack; if (IFSI_MOD(byte_num, bytes_per_pack) != 0) packt_count[ii]++; // adjust for possible last unfilled packet numpack += packt_count[ii]; //total number of packets in the frame } // if nothing has been selected, we can release the SD_POOL block and skip the following if (numpack == 0) { release_block(&sd_msg.block); return; } // right shift according to HIF_HRS_rshift parameter // NOTE: the right shift has been embedded in a function for optimization purposes // TODO: this cycle must take into account the measurement parameters which are // embedded into the head of each block if ( frame_was_shifted ) right_shift = Spectroscopy_table[HIF_WBS_rshift_IDX]; else right_shift = 0; // write the TM packet header at the beginning of the memory block // referenced by the top level variable sd_msg.block write_science_headers(subsysid, phase, numpack); // this call produces the start frame packet write_wbs_start_frame(subsysid, phase, transfer_cnt, scan_count, numpack, p_dark, right_shift); Sd_hdl[subsysid].isn++; // increment integration sequence number sd_msg.count = numpack; for (k = start; k < stop; k += 2) { ii = (k - start)/2; // cycle through packets for (j = 0; j < packt_count[ii]; j++) { // first channel of packet sd_msg.first_ch = Spectroscopy_table[k] + j*ch_per_pack; // calculate the offset of the running packet // sd_msg.offset = SD_TM_HEADER + sd_msg.first_ch - 1; sd_msg.offset = SD_TM_HEADER + sd_msg.first_ch; // after reordering - check // calculate the downcounter of the packet sd_msg.count--; // used in tmtc to detect the last packet of the block // calculate the number of data words to be packetized if ( (j == (packt_count[ii] - 1)) && (IFSI_MOD( Spectroscopy_table[k + 1], ch_per_pack) != 0) ) sd_msg.length = IFSI_MOD( Spectroscopy_table[k + 1], ch_per_pack); // last packet else sd_msg.length = ch_per_pack; // ordinary packet if (KS_FIFOPutWT(SD_TM_QUEUE, &sd_msg, 30) != RC_OK) // 30 msec time out { if (sd_msg.count == 0) release_block(&sd_msg.block); generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_FIFOPUT_SD_TM_QUEUE, 0, NULL); } } } } //------------ write_science_headers ------------------------------------------- //! Writes the header of a science data packet void write_science_headers (unsigned int subsysid, unsigned int phase, int numpack) { TM_SPECT_HEADER * sd_header; // write headers sd_header = (TM_SPECT_HEADER *) sd_msg.block.pointer_to_data; prepare_TM_packet(&sd_msg.block, TM_DFHF_REGULAR, Sd_hdl[subsysid].APID, 0, TM_SD_TYPE, TM_SD_SUBT); // set the appropriate sid value switch (subsysid) { case HRS_H_ID: // HRS-H sd_header->structure_ID = HRSH_INT_BUF1_24 + phase; // 17 or 18 break; case HRS_V_ID: // HRS-V sd_header->structure_ID = HRSV_INT_BUF1_24 + phase; // 19 or 20 break; case WBS_H_ID: // WBS-H sd_header->structure_ID = WBSH_INT_BUF1_16 + 8*(Spectroscopy_table[HIF_WBS_packing_IDX] - 1) + phase; break; case WBS_V_ID: // WBS-V sd_header->structure_ID = WBSV_INT_BUF1_16 + 8*(Spectroscopy_table[HIF_WBS_packing_IDX] - 1) + phase; break; } UNPACK(sd_header->obs_ID, Observation_ID); UNPACK(sd_header->bb_ID, Meas_BuildingBlock_ID); sd_header->int_seq_n = Sd_hdl[subsysid].isn; sd_header->n_pack_fr = numpack; sd_header->pack_n = numpack - sd_msg.count - 1; sd_header->f_ch_n = sd_msg.first_ch - 1; } //------------- attach_6_HK_to_start_frame ------------------------------------------ //! Prepares and sends a start frame packet for wbs void attach_6_HK_to_start_frame(unsigned int * ptr, START_FRAME_DATA * HK_set) { // ptr points to the transfer counter ptr[0] = (ptr[0] << 8) | ( ( HK_set->HK_rot_1 & 0x0000FF00) >> 8 ); // transfer counter plus first 8 bits of rot 1 ptr[1] = ( ( HK_set->HK_rot_1 & 0x000000FF) << 16 ) | ( ( HK_set->HK_rot_2 & 0x0000FFFF) ) ; // last 8 bits of rot 1 plus rot 2 ptr[2] = ( ( HK_set->HK_freq & 0x0000FFFF) << 8 ) | ( ( HK_set->HK_main_ms & 0x0000FF00) >> 8 ); // HK_freq plus first 8 bits of main_ms ptr[3] = ( ( HK_set->HK_main_ms & 0x000000FF) << 16 ) | ( ( HK_set->HK_main_lo & 0x0000FFFF) ) ; // last 8 bits of main_ms plus main_lo ptr[4] = ( HK_set->HK_off_lo & 0x0000FFFF); // last 16 bits: off_lo } //------------- write_hrs_start_frame ------------------------------------------ //! Prepares and sends a start frame packet for hrs void write_hrs_start_frame (unsigned int subsysid, unsigned int phase, unsigned int transfer_cnt, int numpack, int *p_ppp) { TM_HRS_SDSF * start_frame; K_BLOCK block; SD_TM_MSG message; unsigned int l, rep_isn_hrs = 0; // get a block from the STF_POOL if (get_block(&block, STF_POOL, SD_BLOCK_MIN_BYTES) == RC_FAIL) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_GET_STF_POOL_BLOCK, 0, NULL); return; } // initialize to zero the block init_block(&(block), SD_BLOCK_MIN_WORDS); rep_isn_hrs = Sd_hdl[subsysid].isn; start_frame = (TM_HRS_SDSF *) block.pointer_to_data; // determine the sid of the start frame packet if (subsysid == HRS_H_ID) start_frame->structure_ID = HRSH_INT_BUF1_SF + phase; // sid 1 or 2 else start_frame->structure_ID = HRSV_INT_BUF1_SF + phase; // sid 3 or 4 UNPACK(start_frame->obs_ID, Observation_ID); UNPACK(start_frame->bb_ID, Meas_BuildingBlock_ID); start_frame->frame_tranf_cnt = transfer_cnt; // counter of the last frame transfer integrated start_frame->int_seq_n = rep_isn_hrs; start_frame->n_pack_fr = numpack; start_frame->TS = Spect_latched_time.time_stamp; start_frame->HIF_N_HRS_INTEGR = Spectroscopy_table[HIF_N_HRS_INTEGR_IDX]; start_frame->HIF_HRS_rshift = Spectroscopy_table[HIF_HRS_rshift_IDX]; start_frame->HIF_HRS_SEL = Spectroscopy_table[Sd_hdl[subsysid].range_sel]; for (l = 0; l < 48; l++) start_frame->head_chan[l] = *(p_ppp + l); // now a brute patch (we are absolutely out of time) to attach the additional 6 Hks contained in spect latched time attach_6_HK_to_start_frame(&(start_frame->frame_tranf_cnt), &Spect_latched_time); // write headers prepare_TM_packet(&block, TM_DFHF_REGULAR, Sd_hdl[subsysid].APID, 0, TM_SD_TYPE, TM_SD_SUBT); // Now prepare the message for the queue message.block = block; message.offset = TM_HEADER_NWORDS + TM_DATAHEADER_NWORDS + SDH_HRSSF_LEN; // offset to start of data message.length = 48+4; // number of data words (all data) (+4 for the additional 6 Hks) message.count = 0; message.packing = 0x0FF & PACKING_24; // 16 bit data message.packing |= SDH_HRSSF_LEN << 8; if (KS_FIFOPut(SD_TM_QUEUE, (void *) &message) == RC_FAIL) { release_block(&message.block); generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_FIFOPUT_SD_TM_QUEUE, 0, NULL); } } //------------- write_wbs_start_frame ------------------------------------------ //! Prepares and sends a start frame packet for wbs void write_wbs_start_frame (unsigned int subsysid, unsigned int phase, unsigned int transfer_cnt, int int_scan_count, int numpack, int *p_ppp, int right_shift) { TM_WBS_SDSF * start_frame; K_BLOCK block; SD_TM_MSG message; unsigned int l, rep_isn = 0; // get a block from the STF_POOL if (get_block(&block, STF_POOL, SD_BLOCK_MIN_BYTES) == RC_FAIL) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_GET_STF_POOL_BLOCK, 0, NULL); return; } // initialize to zero the block init_block(&(block), SD_BLOCK_MIN_WORDS); rep_isn = Sd_hdl[subsysid].isn; start_frame = (TM_WBS_SDSF *) block.pointer_to_data; // determine the sid of the start frame packet if (subsysid == WBS_H_ID) start_frame->structure_ID = WBSH_INT_BUF1_SF + phase; // sid 5 or 6 else start_frame->structure_ID = WBSV_INT_BUF1_SF + phase; // sid 7 or 8 UNPACK(start_frame->obs_ID, Observation_ID); UNPACK(start_frame->bb_ID, Meas_BuildingBlock_ID); start_frame->frame_tranf_cnt = transfer_cnt; // counter of the last frame transfer integrated start_frame->int_seq_n = rep_isn; start_frame->n_pack_fr = numpack; start_frame->TS = Spect_latched_time.time_stamp; start_frame->HIF_N_WBS_INTEGR = Spectroscopy_table[HIF_N_WBS_INTEGR_IDX]; start_frame->HIF_WBS_rshift = right_shift; start_frame->HIF_WBS_OFFSET1 = Spectroscopy_table[Sd_hdl[subsysid].range_sel]; start_frame->HIF_WBS_WIDTH1 = Spectroscopy_table[Sd_hdl[subsysid].range_sel + 1]; start_frame->HIF_WBS_OFFSET2 = Spectroscopy_table[Sd_hdl[subsysid].range_sel + 2]; start_frame->HIF_WBS_WIDTH2 = Spectroscopy_table[Sd_hdl[subsysid].range_sel + 3]; start_frame->HIF_WBS_OFFSET3 = Spectroscopy_table[Sd_hdl[subsysid].range_sel + 4]; start_frame->HIF_WBS_WIDTH3 = Spectroscopy_table[Sd_hdl[subsysid].range_sel + 5]; start_frame->HIF_WBS_OFFSET4 = Spectroscopy_table[Sd_hdl[subsysid].range_sel + 6]; start_frame->HIF_WBS_WIDTH4 = Spectroscopy_table[Sd_hdl[subsysid].range_sel + 7]; start_frame->int_scan_cnt = int_scan_count; for (l = 0; l < 16; l++) start_frame->dark_pix[l] = *(p_ppp + l); // now a brute patch (we are absolutely out of time) to attach the additional 6 Hks contained in spect latched time attach_6_HK_to_start_frame(&(start_frame->frame_tranf_cnt), &Spect_latched_time); // write headers prepare_TM_packet(&block, TM_DFHF_REGULAR, Sd_hdl[subsysid].APID, 0, TM_SD_TYPE, TM_SD_SUBT); // Now prepare the message for the queue message.block = block; message.offset = TM_HEADER_NWORDS + TM_DATAHEADER_NWORDS + SDH_WBSSF_LEN; // offset to start of data message.length = 16+4; //number of data words (+4 for the additional 6 Hks) message.count = 0; message.packing = 0x0FF & PACKING_24; message.packing |= SDH_WBSSF_LEN << 8; if (KS_FIFOPut(SD_TM_QUEUE, (void *) &message) == RC_FAIL) { release_block(&message.block); generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_FIFOPUT_SD_TM_QUEUE, 0, NULL); } } //------------- hrs_right_shift ------------------------------------------------ //! Performs a right shift of the hrs data void hrs_right_shift (void) { unsigned int right_shift; int m, k; int conf_index; right_shift = Spectroscopy_table[HIF_HRS_rshift_IDX]; if (right_shift != 0) { for (k = 0; k < 8; k++) // 8 datablocks in each HRS frame { for (m = 0; m < 2; m++) // two sub-blocks (chip number) for each datablock { conf_index = SD_TM_HEADER + m*HRS_SUBBLOCK_DATA_LEN + k*HRS_BLOCK_DATA_LEN; shift_right((sd_msg.block.pointer_to_data + conf_index + 1), (HRS_SUBBLOCK_DATA_LEN - 1), right_shift); } } } } //------------- packetize_IFHRS ------------------------------------------------ //! Copmpute the IF power for hrs, formats a TM packet containing the power and passes it to tmtc void packetize_IFHRS (unsigned int subsysid, unsigned int phase) { int k, s, n, m; unsigned int select; unsigned int offset = 0, npar = 0; unsigned int head_chan[4], conf_gaas[16]; int ifpower[16]; float ifpo_r[16]; // read band selection select = Spectroscopy_table[Sd_hdl[subsysid].range_sel]; // if nothing is selected simply return if ((select & 0xFF) == 0) return; //span the datablock_id vector (k) and the range selection (s) for (k = 0, s = 0x1; k < 8; s <<= 1, k++) { if (select & s) // check the range selected { // extract the first 4 channels of each subblock necessary to calculate the ifpower for (m = 0; m < 2; m++) // index of the subblock (chip number) { for (n = 0; n < 4; n++) // span the first 4 data of each subblock { offset = SD_TM_HEADER + m*HRS_SUBBLOCK_DATA_LEN + k*HRS_BLOCK_DATA_LEN + n; head_chan[n] = *(unsigned int *)(sd_msg.block.pointer_to_data + offset); } conf_gaas[m + k*2] = head_chan[0]; if ((head_chan[1])!= 0) { ifpo_r[m + k*2] = (((float)(2*head_chan[3])-(float)(head_chan[1]))*65535.); ifpo_r[m + k*2] = ifpo_r[m + k*2]/(float)(head_chan[1]); } else generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_HRS_DURATION_NULL, 0, NULL); if (ifpo_r[m + k*2] < 0) ifpo_r[m + k*2] = 0; ifpower[m+k*2] = (int)ifpo_r[m+k*2]; // HK packet ICD 1.4 if (ifpower[m+k*2] > 0xffff) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_IFP_OVFL, 0, NULL); npar++; // total number of IFpowers calculated } } else { for (m = 0; m < 2; m++) { ifpower[m+k*2] = 0; // HK packet ICD 1.4 npar++; } } } // send the report send_IFHRS_report (subsysid, phase, conf_gaas, ifpower, npar); } //------------- send_IFHRS_report ------------------------------------------------ //! Prepare and send hrs if power report void send_IFHRS_report (unsigned int subsysid, unsigned int phase, unsigned int *conf_gaas, int *ifpower, int npar) { K_BLOCK block; HK_TM_MSG hk_msg; TM_ST3_HEADER *st3_header; int * p_aux, n; // get a block from the HK_POOL if (get_block(&block, HK_POOL, HK_BLOCK_LEN_BYTES) == RC_FAIL) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_GET_HK_POOL_BLOCK, 0, NULL); return; } // initialize to zero the block init_block(&(block), HK_BLOCK_LEN_WORDS); // prepare an auxiliary pointer p_aux = block.pointer_to_data + HK_TM_HEADER; for (n = 0; n < npar; n++) { p_aux[n] = (int)conf_gaas[n]; p_aux[npar + n] = ifpower[n]; } prepare_TM_packet(&block, TM_DFHF_REGULAR, TM_APID_HK, ((npar + DFH_WLEN + SDH_HK_WLEN + npar + 1)<<1 )- 1, TM_HK_TYPE, TM_HK_SUBT); // prepare the pointer to header st3_header = (TM_ST3_HEADER * ) block.pointer_to_data; // determine the sid of the tm packet if (subsysid == HRS_H_ID) st3_header->structure_ID = HRSH_IFHK_BUF1 + phase; // sid 25 or 26 (it depends on the buffer) else st3_header->structure_ID = HRSV_IFHK_BUF1 + phase; // sid 27 or 28 (it depends on the buffer) UNPACK(st3_header->obs_ID, Observation_ID); UNPACK(st3_header->bb_ID, Meas_BuildingBlock_ID); hk_msg.block = block; // prepare the block to be sent in various messages 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 = (((npar + DFH_WLEN+SDH_HK_WLEN + npar + 1) << 1) + 6); // number of data bytes (not relevant for packing 16) // 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, ERR_DATA_HDL_FIFOPUT_HK_TM_QUEUE, 0, NULL); } } //------------- wbs_right_shift ------------------------------------------------ //! Performs a right shift of the wbs data void wbs_right_shift (void) { int k, conf_index; unsigned int right_shift; right_shift = Spectroscopy_table[HIF_WBS_rshift_IDX]; if (right_shift != 0) { for (k = 0; k < 4; k++) // 4 datablocks in each WBS frame { conf_index = SD_TM_HEADER + k*WBS_BLOCK_DATA_LEN; shift_right((sd_msg.block.pointer_to_data + conf_index + 4), (WBS_BLOCK_DATA_LEN - 4), right_shift); } } } //------------- packetize_IFWBS ------------------------------------------------ //! Copmpute the IF power for wbs, formats a TM packet containing the power and passes it to tmtc void packetize_IFWBS (unsigned int subsysid, int scan_count, unsigned int phase) { int * p_data; int k, n; unsigned int ifpower_wbs[8]; unsigned int start_pix, npixels, totp_data = 0; float ifpo_r; int some_data_exist; some_data_exist = 0; // to keep track if some pixels were actually selected p_data = sd_msg.block.pointer_to_data + SD_TM_HEADER; // pointer to the data for (n = 0; n < WBS_BLOCK_NUM; n++) { start_pix = Spectroscopy_table[Sd_hdl[subsysid].range_sel + (n*2)]; npixels = Spectroscopy_table[Sd_hdl[subsysid].range_sel + (n*2) + 1]; // check that we are not out of range if ( start_pix + npixels > WBS_DATA_LEN) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_IDX_OVFL, 1, &n); if (npixels > 0) { some_data_exist = 1; // signal that some pixels were selected: we need to send the IF packet totp_data = 0; for (k = start_pix; k < start_pix + npixels; k++) totp_data = totp_data + p_data[k]; // add channels // if power estimate as the average of the output of the subband ifpo_r = (float)(totp_data)/(float)(npixels); if (scan_count != 0) ifpo_r = ifpo_r/scan_count; else generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_ZERO_DIV, 0, NULL); // scale by 2^6 the IF power to exploit the 16 bit allowable and make it integer ifpo_r = ifpo_r * 64.; ifpower_wbs[n] = (int)(ifpo_r + .5); } else ifpower_wbs[n] = 0; } // send the report if ( some_data_exist ) send_IFWBS_report(ifpower_wbs, subsysid, phase); } //------------- send_IFWBS_report ------------------------------------------------ //! Sends a IF wbs report void send_IFWBS_report(unsigned int * ifpower_wbs, unsigned int subsysid, unsigned int phase) { K_BLOCK block; HK_TM_MSG hk_msg; TM_ST3_HEADER *st3_header; int n, k,*p_aux; // get a block from the HK_POOL if (get_block(&block, HK_POOL, HK_BLOCK_LEN_BYTES) == RC_FAIL) { generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_GET_HK_POOL_BLOCK, 0, NULL); return; } // initialize to zero the block init_block(&(block), HK_BLOCK_LEN_WORDS); // prepare auxiliary pointer p_aux = block.pointer_to_data + HK_TM_HEADER; k=0; for (n = 0; n < (WBS_BLOCK_NUM*2); n+=2, k++) { p_aux[n] = (ifpower_wbs[k] >>16); p_aux[n+1] = (ifpower_wbs[k] & 0xffff); } // prepare TM packet prepare_TM_packet(&block, TM_DFHF_REGULAR , TM_APID_HK, ((WBS_BLOCK_NUM*2 + DFH_WLEN + SDH_HK_WLEN + 1) <<1) - 1, TM_HK_TYPE, TM_HK_SUBT); // prepare the pointer to header st3_header = (TM_ST3_HEADER * ) block.pointer_to_data; // determine the sid of the tm packet if (subsysid == WBS_H_ID) st3_header->structure_ID = WBSH_IFHK_BUF1 + phase; // SID set to 29 or 30 (it depends on the buffer) else st3_header->structure_ID = WBSV_IFHK_BUF1 + phase; // SID set to 31 or 32 (it depends on the buffer) UNPACK(st3_header->obs_ID, Observation_ID); UNPACK(st3_header->bb_ID, Meas_BuildingBlock_ID); hk_msg.block = block; // prepare the block to be sent in various messages 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 = (WBS_BLOCK_NUM*2); // number of data (not relevant for packing 16) // 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, ERR_DATA_HDL_FIFOPUT_HK_TM_QUEUE, 0, NULL); } } /*------------- init_sdh ---------------------------------------------------------*/ //! inits of SD buffer handlers void init_sdh (void) { int i; // inits of linker fields Sd_hdl[0].linker = WBS_H_ID; Sd_hdl[1].linker = WBS_V_ID; Sd_hdl[2].linker = HRS_H_ID; Sd_hdl[3].linker = HRS_V_ID; // init once for all the lengths and the APID fields of Sd_hdl elements for (i = 0; i < 4; i++) switch (Sd_hdl[i].linker) { case HRS_V_ID: Sd_hdl[i].APID = APID1029; break; case HRS_H_ID: Sd_hdl[i].APID = APID1028; break; case WBS_V_ID: Sd_hdl[i].APID = APID1031; break; case WBS_H_ID: Sd_hdl[i].APID = APID1030; break; default: break; } } //---- get_hrs_frames_per_wbs -------------------------------------------------- //! Returns the number of hrs starts per wbs start int get_hrs_frames_per_wbs (void) { return Spectroscopy_table[HIF_R_HRS_IDX]; } //---- init_science_data ------------------------------------------------------- //! Inizializes hs variables in order to allow a new total power spectroscopy measurement. //! I.E. copies Spectroscopy_table into sd_hdl and inits other stuff (Meas_spectr, the sd_hdl blocks...) int init_science_data (void) { unsigned int i; WBS_duration = Spectroscopy_table[HIF_N_WBS_START_IDX]; HRS_duration = Spectroscopy_table[HIF_R_HRS_IDX]; Meas_spectr = 0; if (HRS_duration != 0) { if (WBS_duration != 0) { HRS_duration = HRS_duration*WBS_duration; Meas_spectr = Active_spectr; // HRS + WBS working } else // WBS_duration = 0 Meas_spectr = (Active_spectr & 0x60); // only HRS working } else Meas_spectr = (Active_spectr & 0x18); // only WBS working for (i = 0; i < 4; i++) switch (Sd_hdl[i].linker) { case HRS_V_ID: if ((AID_spectroscopy == HRS_ATTSETT_ID) || (AID_spectroscopy == HRS_ATTSETT2_ID)) { Sd_hdl[i].duration = 1; Sd_hdl[i].int_num = 1; } else { Sd_hdl[i].duration = HRS_duration; if (Spectroscopy_table[HIF_N_HRS_INTEGR_IDX] != 0) Sd_hdl[i].int_num = Spectroscopy_table[HIF_N_HRS_INTEGR_IDX]; else Sd_hdl[i].int_num = 1; } Sd_hdl[i].coadded = 0; Sd_hdl[i].isn = 0; Sd_hdl[i].range_sel = HIF_HRSV_SEL_IDX; break; case HRS_H_ID: if ((AID_spectroscopy == HRS_ATTSETT_ID) ||(AID_spectroscopy == HRS_ATTSETT2_ID)) { Sd_hdl[i].duration = 1; Sd_hdl[i].int_num = 1; } else { Sd_hdl[i].duration = HRS_duration; if (Spectroscopy_table[HIF_N_HRS_INTEGR_IDX] != 0) Sd_hdl[i].int_num = Spectroscopy_table[HIF_N_HRS_INTEGR_IDX]; else Sd_hdl[i].int_num = 1; } Sd_hdl[i].coadded = 0; Sd_hdl[i].isn = 0; Sd_hdl[i].range_sel = HIF_HRSH_SEL_IDX; break; case WBS_V_ID: Sd_hdl[i].duration = WBS_duration; Sd_hdl[i].coadded = 0; Sd_hdl[i].isn = 0; if (Spectroscopy_table[HIF_N_WBS_INTEGR_IDX] != 0) Sd_hdl[i].int_num = Spectroscopy_table[HIF_N_WBS_INTEGR_IDX]; else Sd_hdl[i].int_num = 1; Sd_hdl[i].range_sel = HIF_WBSV_OFFSET1_IDX; break; case WBS_H_ID: Sd_hdl[i].duration = WBS_duration; Sd_hdl[i].coadded = 0; Sd_hdl[i].isn = 0; if (Spectroscopy_table[HIF_N_WBS_INTEGR_IDX] != 0) Sd_hdl[i].int_num = Spectroscopy_table[HIF_N_WBS_INTEGR_IDX]; else Sd_hdl[i].int_num = 1; Sd_hdl[i].range_sel = HIF_WBSH_OFFSET1_IDX; break; default: break; } return Meas_spectr; } //-------- pkt_complete -------------------------------------------------------- //! Checks the number of coadditions int pkt_complete (int fifo_id, int coadded) { if ( coadded >= Sd_hdl[fifo_id].int_num ) return 1; else return 0; } //----------------------- init_spec_table -------------------------------------- //! this function copies the 29 elements of the initialization table //! Spectroscopy_table_init[] into the first 29 elements of Spectroscopy_table[]. void init_spec_table (void) { int i; for (i = 0; i < WNUM_SPEC_TAB_INI; i++) Spectroscopy_table[i] = Spectroscopy_table_init[i]; } //----------------------- init_conf_spec_table --------------------------------- //! this function copies the 29 elements of the initialization table //! Spectroscopy_table_init[] into the first 29 elements of Conf_Spectroscopy_table[]. void init_conf_spec_table (void) { int i; for (i = 0; i < WNUM_SPEC_TAB_INI; i++) Conf_Spectroscopy_table[i] = Spectroscopy_table_init[i]; } //---------------- store_wbs_att_sett ------------------------------------------ //! at the end of the first step of wbs calibration we save the wbs attenuator setting //! into the array variable wbs_att_setting. This function is called by task hs1 during //! wbs frame processing. void store_wbs_att_sett (int fifo_id, int* pdata) { pdata += WBS_FRAME_SD_LEN + 1; // now it points to hk data (placed at the end of the wbs frame) switch (fifo_id) { case WBS_H_ID : wbs_att_setting[0] = pdata[1]; // wbs_att_setting[0] is for wbsh zero_switch_setting[0] = (pdata[2] & 0x01); // zero_switch_setting[0] is for wbsh break; case WBS_V_ID : wbs_att_setting[1] = pdata[1]; // wbs_att_setting[1] is for wbsv zero_switch_setting[1] = (pdata[2] & 0x01); // zero_switch_setting[1] is for wbsv break; default : generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_DATA_HDL_FIFO_ID, 1, &fifo_id); } } //---------------- trigger_next_step ------------------------------------------- // this function prepares a message and sends it to task hs_hdl via fifo HS_HDL_QUEUE; // the message triggers the next step of the current activity (tuning, scan, calibration); // global variable AID_spectroscopy is set to the value pertaining the next step; void trigger_next_step (unsigned int next_AID_spectr, unsigned int subsys_id, int update_aid_spec) { HS_HDL_MSG cmd_msg; // message to be sent to task hs_hdl // set variable AID_spectroscopy to the value for the next step if ( update_aid_spec) AID_spectroscopy = next_AID_spectr; // prepare the message to be sent in fifo HS_HDL_QUEUE to ask for another step cmd_msg.operation_id = next_AID_spectr; switch (subsys_id) { case WBS_H_ID: cmd_msg.command_number = fifo_0_command_number; break; case WBS_V_ID: cmd_msg.command_number = fifo_1_command_number; break; case HRS_H_ID: cmd_msg.command_number = fifo_2_command_number; break; case HRS_V_ID: cmd_msg.command_number = fifo_3_command_number; break; default: // the ongoing activity is stopped with an execution failure enqueue_exec_fail(EXF_DATA_HDL_INVALID_SUBSYS_ID, 0, NULL); // re-initialize some variables to bring the OBSW back to the "idle" state init_spec_table(); AID_spectroscopy = REQUIRING_HK; return; // exit the function } // signal that no block is attached to the msg cmd_msg.block_loaded = 0; // push the message in the fifo towards task hs_hdl if (KS_FIFOPut(HS_HDL_QUEUE, (void *) &cmd_msg) == RC_FAIL) { // since the next step will not be executed, it is here necessary to // produce an execution failure packet enqueue_exec_fail(EXF_DATA_HDL_FIFOPUT_HS_HDL_QUEUE, 0, NULL); // re-initialize some global variables to bring the OBSW back to the "idle" state init_spec_table(); AID_spectroscopy = REQUIRING_HK; } } //---------------- exec_attach_hk ------------------------------------------- // requires some HK that need to be sent to ground by means of the start frame void exec_attach_hk (START_FRAME_DATA * destination ) { static unsigned int req_HK_rot_1 = 0x8f50ffff; static unsigned int req_HK_rot_2 = 0x8f10ffff; static unsigned int req_HK_freq = 0xb086ffff; static unsigned int req_HK_main_ms = 0xb33affff; static unsigned int req_HK_main_lo = 0xb33cffff; static unsigned int req_HK_off_lo = 0xb33effff; static unsigned int set_page = 0xf30acc7a; if ( ls_put_msg_hp(&req_HK_rot_1, &(destination->HK_rot_1), 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if ( ls_put_msg_hp(&req_HK_rot_2, &(destination->HK_rot_2), 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if ( ls_put_msg_hp(&req_HK_freq, &(destination->HK_freq), 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if ( ls_put_msg_hp(&set_page, NULL, 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if ( ls_put_msg_hp(&req_HK_main_ms, &(destination->HK_main_ms), 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if ( ls_put_msg_hp(&set_page, NULL, 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if ( ls_put_msg_hp(&req_HK_main_lo, &(destination->HK_main_lo), 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if ( ls_put_msg_hp(&set_page, NULL, 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); if ( ls_put_msg_hp(&req_HK_off_lo, &(destination->HK_off_lo), 0, NULL) == RC_FAIL ) generate_event(EVENT_EVENT_REPORT, RUNTIME_ERROR_EVID, ERR_HK_ASK_FIFOPUT_LS_HP_QUEUE, 0, NULL); }