; ==== ISUAL Flight Software -- Univ of California, Berkeley, SSL ==== ; SOH.a -- Task to generate SOH Telemetry ; Generates 71C - Analog housekeeping packet ; 71D - Digital housekeeping packet ; ; Includes: ; Trigger Event interrupt service ; Start of Camera Exposure interrupt service ; Routines to manage the event queue ; Revision History: ; 18-Dec-2002 - SPG - ISUAL Flight Software rev 7.3 ; First Official Release ; 20-Dec-2002 - SPG - ISUAL Flight Software rev 7.4 ; Restored 50 byte/sec limit ; Bypass delay between packets if hskp rate=1 ; 20-Dec-2002 - SPG - ISUAL Flight Software rev F.F ; Invert polarity on FEC channel 8 ; Correct display in IDH_DAYS/DAYE ; Store Analog sample time in Digital packet ; 11-Jan-2003 - SPG ; make housekeeping cycle every 8 seconds ; wait 1 sec after 71D ; 18-Feb-2003 - SPG ; eliminate GBL_ARMSW ; eliminate NEV and IS_TRIG ; 25-Feb-2003 ; use GBL_SECONDS_CTR to make "1 second delay" ; between housekeeping packets ; (don't use downcounter timer) ; 9-May-2003 ; - eliminate extra "call task" in reading analog MUX ; - mask "TBD" bits in HKP_STS port ; - on Analog Fault, stop clobbering HL ; - Repeat Analogs readout when FEC selects channel 8 ; 17-May-2005 (FSW 7.9) ; - increment 4-byte IDH_N_EVENTS (GBL_SOH+23) include soh.i include task.i include ccsds.i include cmd.i include cdi.i include gbl.i include clock.i include ioports.i include util.i public DCT_SET include debug.i sq1C ds 2 sq1D ds 2 sq1E ds 2 edac ds 2 ; Array Photometer MUX selector apix ds 2 ap_mux_ptr ds 2 ; FEC MUX selector fecix ds 2 fec_mux_ptr ds 2 SOH_INIT: push psw push d push h ; Produce SOH telemetry every 15 seconds mvi a,15 sta GBL_SOH+22 ; IDH_SOH_INTERVAL lxi h,0 ; zero source sequence counters shld sq1C shld sq1D shld sq1E ; set first selection (0) for FEC MUX shld fecix ; set pointer to slot in telemetry lxi h,GBL_MON+106 shld fec_mux_ptr ; set first selection for AP MUX lxi h,0100h ; bit 8=1; select Chan B HV shld apix ; AP MUX selector ; set pointer to slot in telemetry lxi h,GBL_MON+130 shld ap_mux_ptr ; start SOH task lxi d,soh_task lxi h,GBL_SOH_STACK+stack_size call task_new ; Setup the Event Interrupt mvi A,JMP_OPCODE sta RST_6 lxi h,EVENT_ISR ; address of Interrupt handler shld RST_6+1 ; ; Set up "Camera Exposure Start" Interrupt Service mvi A,JMP_OPCODE sta RST_5 ; RST 5 lxi h,CAMEXP_ISR ; address of Interrupt handler shld RST_5+1 ; set as JMP address ; Event interrupt and Image Start interrupt ; are enabled and disabled dynamically by the software. ; Initially, both are disabled. ; set private fetch-pointer used by SOH task lhld GBL_EVENT_QUEUE_STORE_PTR shld e_fetch pop h pop d pop psw ret ; capture Time in Event queue element ; A - event type code SOH_TOEVQ: push psw push d push h lhld GBL_EVENT_QUEUE_STORE_PTR ; queue pointer mov M,a ; set code inx h ; point to time call CLOCK_READ ; step the queue lxi d,6 dad d ; step to next element ; need to wrap queue? lxi d,GBL_EVENT_QUEUE_WRAP mov a,l ; test for wrap cmp e jnz nowrap mov a,h cmp d jnz nowrap lxi h,GBL_EVENT_QUEUE ; wrap back to start nowrap: shld GBL_EVENT_QUEUE_STORE_PTR ; updated queue pointer pop h pop d pop psw ret TZERO ds 1 packet_pointer ds 2 soh_task: lda GBL_SECONDS_CTR sta TZERO again: call task ; GBL_TLM_ILK is used to control switching between nominal and redundant ; command, SOH and science telemetry link ; (not used for automatic switching; only manual) lda GBL_TLM_ILK cpi 0 ; 0 = no switch in progress jz go cpi 1 ; 1 = switch command has been received jnz go mvi a,2 ; change it to 2 - interlock set sta GBL_TLM_ILK ; wait for switch to happen ilkw: call task lda GBL_TLM_ILK cpi 2 ; 2 = switch in progress jz ilkw ; OK, we can continue go: ; If there are any elements in the Event Queue, ; generate an event packet lxi h,GBL_EVENT_DATA mvi M,0 ; zero the packet event-count inx h ; point to packet data shld packet_pointer eloop: lhld packet_pointer xchg lhld e_fetch ; local fetch-pointer call SOH_FROMEVQ shld e_fetch ; update fetch-pointer cpi 0 ; any more events? jz send_event_packet ; no, send packet ; skip exposure events (code 2) ; and buffer-switch events (30,31,32,33) mov a,c ; code cpi 2 jz eloop cpi 30 jp eloop ; this was either a trigger event (1) or non-trigger (0) ; convert time to 10-byte lhld packet_pointer mov d,h ; convert in-place mov e,l call CLOCK_6_TO_10 ; next element in packet ; lhld packet_pointer lxi d,10 ; advance pointer dad d shld packet_pointer lda GBL_EVENT_DATA inr a ; increment count sta GBL_EVENT_DATA cpi 4 ; max of 4 events jnz eloop send_event_packet: lda GBL_EVENT_DATA cpi 0 ; any events in this packet? jz noev ; no ; build Event packet and send it sta GBL_EVENT_DATA ; store number of events in packet mvi a,1Eh ; ApID 71E lxi b,74 ; total packet length lhld sq1E ; this ApID's source sequence number xchg lxi h,GBL_EVENT_DATA call CCSDS_HSKP ; send it out ; increment the source sequence count lhld sq1E inx h shld sq1E noev: ; Have SOH_INTERVAL seconds elapsed? lda GBL_SOH+22 ; IDH_SOH_INTERVAL mov b,a ; difference seconds from last time lda TZERO mov c,a lda GBL_SECONDS_CTR sub c cmp b jm again ; not yet gogo: lda GBL_SECONDS_CTR sta TZERO ; Send Echo packet (even if partially filled) call CMD_SEND_ECHO_PACKET ; Digital Packet lda GBL_SCIENCE_MODE sta GBL_SOH+10 in HKP_STS_I sta GBL_SOH+99 ; IDH_HKP_STATUS lda GBL_MM_STATUS sta GBL_SOH+108 ; IDH_MM_STATUS lda GBL_TM_STATUS sta GBL_SOH+110 ; IDH_TM_STATUS lda GBL_MMCB_STATUS sta GBL_SOH+109 ; IDH_MMCB_STATUS in DAY_LAT_STS_I ; IDH_DAYLATCH sta GBL_SOH+87 in STIM_CTL_I sta GBL_SOH+88 ; IDH_STIM_STATUS ; Day Sensors ... ; "IDH_DAYE" shows which Day sensors were selected in DAY_SENS_STS_I mov c,a sta GBL_SOH+17 ; IDH_DAYE sta GBL_MON+167 ; IAM_DAY_STATUS ; "IDH_DAYS" shows 1 if any enabled sensor sees day mov a,c ani 010h ; Sensor 1 enabled? jnz ds1 ; yes ck2: mov a,c ani 020h ; Sensor 2 enabled? jnz ds2 ; yes ; neither sensor enabled: show 0 neither: mvi a,0 sta GBL_SOH+18 ; IDH_DAYS jmp dsok ds1: mov a,c ani 1 ; sensor 1 sees day? jz ck2 ; no; try sensor 2 mvi a,1 ; days=1 sta GBL_SOH+18 ; IDH_DAYS jmp dsok ds2: mov a,c ani 2 ; sensor 2 sees day? jz neither mvi a,1 ; days=1 sta GBL_SOH+18 ; IDH_DAYS dsok: ; Other status ... lda GBL_DCM_STATUS sta GBL_SOH+111 ; IDH_DCM_STATUS in ISDPGLU_REV_I sta GBL_SOH+137 ; IDH_DPGLU in ISDPPWR_REV_I sta GBL_SOH+138 ; IDH_DPWR ; Power Service Status bits in PWR_STS_LO_I sta GBL_SOH+113 ; IDH_PSS_0_7 in PWR_STS_HI_I sta GBL_SOH+114 ; IDH_PSS_15_8 in STATUS6_I ani 80h ; state of PS16 is b7 jz sb0 ; need to show it as b0 mvi a,01h sb0: sta GBL_SOH+115 ; IDH_PSS_16 ; SCIF status in SCIF_STS_I sta GBL_SOH+148 ; IDH_SCIF_STATUS ; DCM Status lda GBL_DCM_STATUS cpi 0FBh jz nodcm in MM_IM_DCM_STS_I sta GBL_SOH+89 ; IHD_DCM_BUSY lxi h,GBL_SOH+90 mvi a,0E2h call CDI_READBACK nodcm: ; Cosmic Ray Counters lxi h,GBL_SOH+196 mvi a,SP_CR_CNT123 call CDI_READBACK lxi h,GBL_SOH+198 mvi a,SP_CR_CNT456 call CDI_READBACK ; If Array Photometer is on, read AP Status mvi a,0 sta GBL_SOH+104 ; IDH_AP_PWR (0=off) in HKP_STS_I ani 10h ; b4 jz noap mvi a,1 sta GBL_SOH+104 ; IDH_AP_PWR (1=on) lxi h,GBL_SOH+200 mvi a,AP_STATUS call CDI_READBACK noap: ; If Housekeeping power on, ; Read Analog Monitor Data in STATUS6_I ; b7=1 if PS16 on ani 80h jz bypass read_again: ; Set MUX selection for AP Housekeeping lhld APIX mvi a,AP_HKP_MUX ; set the index call CDI_AHL ; Set MUX selector for FEC lhld FECIX mvi a,IM_HKP_SEL call CDI_AHL ; set FEC HKP MUX ch no. ; *** Start FSW rev 7.5 changes: mov a,l cpi 08h ; FEC channel 8? jnz fec9_chk ; if not mvi a,PC_HKP_NEG ; if ch 8, set neg polarity lxi h,0001h ; 1=neg jmp fec89_cdi fec9_chk: cpi 09h ; FEC channel 9? jnz fec89_cont ; if not mvi a,PC_HKP_NEG ; if ch 9, set pos polarity lxi h,0000h ; 0=pos fec89_cdi: call CDI_AHL fec89_cont: ; Time-Stamp for Analog sampling ; (goes in Digital packet) lxi h,GBL_SOH+205 ; IAM_SAMPLE_TIME call CLOCK_READ lxi d,GBL_SOH+205 call CLOCK_6_TO_10 ; make 10-byte time ; *** end 7.5 changes ; Read Power and Temperature Monitors ; initialize housekeeping interface for readout mvi a,0 out HKP_CTL_O ; Read 128 channels into a special buffer lxi h,GBL_IAM ; 2 groups of 64 mvi b,2 in HKP_STS_I ani 83h ; zero TBD bits ** 9-May-03 ori 02h out HKP_CTL_O ; turn on HKP START to PC aml_64: ; wait for Power Controller (PC) ready call task ; extra delay ; call task ; **removed 9-May-2003 mvi c,255 ; (for timeout) aml0: call task in HKP_STS_I ani 4 ; b2=1 ? jnz is_on dcr c jnz aml0 ; timeout: log an Analogs Fault lxi h,GBL_SOH+203 inr M mvi a,1 sta GBL_SOH+12 ; at least one fault happened jmp bypass is_on: ; turn off Start (effective on 1st group of 64 only) in HKP_STS_I ani 0FDh out HKP_CTL_O mvi c,16 ; 16 groups of 4 = 64 bytes aml1: ; ask for 4 bytes in HKP_STS_I ori 01h ; b0=clock out HKP_CTL_O ; enable HKP CLOCK to PC ; wait for bytes to be received mvi e,64 ; timeout aml2: ; ** removed 9-May-2003 call task in HKP_STS_I ani 08h ; b3=1 : 4 bytes done jnz rbb dcr e jnz aml2 ; Timeout: Log an "Analogs Fault" push h ; preserve HL ** 9-May-03 lxi h,GBL_SOH+203 inr M pop h mvi a,1 sta GBL_SOH+12 ; at least one fault happened call debug_asc asc "ANLGFLT$" ; read the bytes and store them rbb: mvi a,00h out HKP_CTL_O ; disable HKP CLOCK to PC in HKP_DAT_0_I mov M,a inx h in HKP_DAT_1_I mov M,a inx h in HKP_DAT_2_I mov M,a inx h in HKP_DAT_3_I mov M,a inx h ; next group of 4 dcr c jnz aml1 aquit: mvi a,0 out HKP_CTL_O ; turn off clock enable call task dcr b jnz aml_64 ; second group of 64 ; Copy channels 0..95 to the Housekeeping Array lxi h,GBL_IAM lxi d,GBL_MON_ARRAY mvi c,96 call copy_bytes ; Store channel 96 in appropriate slot for FEC MUX lda GBL_IAM+96 lhld fec_mux_ptr mov M,a ; except when FEC MUX is on channel 8, ; Store channel 97 in appropriate slot for AP MUX lhld fecix mov a,l cpi 8 jz nostor lda GBL_IAM+97 lhld ap_mux_ptr mov M,a nostor: ; Step the MUXs ; AP -- step to next index (shift the bit left) lhld ap_mux_ptr inx h shld ap_mux_ptr lhld apix mov a,h ; watch for bit 15 dad h ; shift left ani 80h jz store_ap ; wrap back to bit 8 lxi h,GBL_MON+130 shld ap_mux_ptr lxi h,0100h store_ap: shld apix ; If FEC set to channel 9, then polarity ; was negative, which messes up all the other analogs ; If we just did channel 8, step to channel 9 and repeat the readout ; (which will set polarity to positive) ; FEC -- step to next lhld fec_mux_ptr inx h shld fec_mux_ptr lhld fecix inx h mov a,l cpi 10h ; 0F is max jnz store_fec lxi h,GBL_MON+106 shld fec_mux_ptr lxi h,0 ; wrap fecix to zero store_fec: ; If FEC channel is now 9, repeat the readout ; (which first sets polarity back to positive) shld fecix mov a,l cpi 9 jz read_again bypass: ; Read the HV settings in PHOS_DAY_I sta GBL_MON+138 ; IAM_PHOS_DAY in PHOS_SPR_AUR_I sta GBL_MON+139 ; IAM_PHOS_NIGHT in PHOS_MAX_I sta GBL_MON+169 ; IAM_PHOS_MAX in PHOS_DAC_I sta GBL_MON+171 ; IAM_PHOS_DAC in MCP_DAY_I sta GBL_MON+140 ; IAM_MCP_DAY in MCP_NITE_1_I sta GBL_MON+141 ; IAM_MCP_NIGHT1 in MCP_NITE_2_I sta GBL_MON+142 ; IAM_MCP_NIGHT2 in MCP_NITE_3_I sta GBL_MON+143 ; IAM_MCP_NIGHT3 in MCP_NITE_4_I sta GBL_MON+144 ; IAM_MCP_NIGHT4 in MCP_NITE_5_I sta GBL_MON+145 ; IAM_MCP_NIGHT5 in MCP_NITE_6_I sta GBL_MON+146 ; IAM_MCP_NIGHT6 in MCP_NITE_7_I sta GBL_MON+147 ; IAM_MCP_NIGHT7 in MCP_MAX_I sta GBL_MON+168 ; IAM_MCP_MAX in MCP_DAC_I sta GBL_MON+170 ; IAM_MCP_DAC in SP1_DAY_I sta GBL_MON+148 ; IAM_SP1_DAY in SP1_AUR_I sta GBL_MON+149 ; IAM_SP1_AURORA in SP1_SPR_I sta GBL_MON+150 ; IAM_SP1_SPRITE in SP1_DAC_I sta GBL_MON+172 ; IAM_SP1_DAC in SP2_DAY_I sta GBL_MON+151 ; IAM_SP2_DAY in SP2_AUR_I sta GBL_MON+152 ; IAM_SP2_AURORA in SP2_SPR_I sta GBL_MON+153 ; IAM_SP2_SPRITE in SP2_DAC_I sta GBL_MON+173 ; IAM_SP2_DAC in SP3_DAY_I sta GBL_MON+154 ; IAM_SP3_DAY in SP3_AUR_I sta GBL_MON+155 ; IAM_SP3_AURORA in SP3_SPR_I sta GBL_MON+156 ; IAM_SP3_SPRITE in SP3_DAC_I sta GBL_MON+174 ; IAM_SP3_DAC in SP4_DAY_I sta GBL_MON+157 ; IAM_SP4_DAY in SP4_AUR_I sta GBL_MON+158 ; IAM_SP4_AURORA in SP4_SPR_I sta GBL_MON+159 ; IAM_SP4_SPRITE in SP4_DAC_I sta GBL_MON+175 ; IAM_SP4_DAC in SP5_DAY_I sta GBL_MON+160 ; IAM_SP5_DAY in SP5_AUR_I sta GBL_MON+161 ; IAM_SP5_AURORA in SP5_SPR_I sta GBL_MON+162 ; IAM_SP5_SPRITE in SP5_DAC_I sta GBL_MON+176 ; IAM_SP5_DAC in SP6_DAY_I sta GBL_MON+163 ; IAM_SP6_DAY in SP6_AUR_I sta GBL_MON+164 ; IAM_SP6_AURORA in SP6_SPR_I sta GBL_MON+165 ; IAM_SP6_SPRITE in SP6_DAC_I sta GBL_MON+177 ; IAM_SP6_DAC ; store the HV status byte in HV_STS_I sta GBL_MON+166 ; is Mass Memory on? lda GBL_MM_STATUS cpi 1 jnz nomm ; Read the Mass Memory EDAC counters ; (which resets them) mvi a,0EAh lxi h,edac call CDI_READBACK ; add to accumulators ; multiple bit error count (bits 15..10) lda edac rar rar ani 3Fh mov c,a lda GBL_SOH+150 add c sta GBL_SOH+150 lda GBL_SOH+149 aci 0 ; propagate carry sta GBL_SOH+149 ; single bit error count (bits 9..0) lda edac ani 03h mov b,a lda edac+1 mov c,a lda GBL_SOH+152 add c sta GBL_SOH+152 lda GBL_SOH+151 adc b ; propagate carry sta GBL_SOH+151 nomm: ; send the Analog Monitors Packet mvi a,1Ch ; ApID 71C lxi b,188 ; total packet length is 188 lhld sq1C ; this ApID's source sequence number xchg lxi h,GBL_MON_ARRAY call CCSDS_HSKP ; send it out ; increment the source sequence count lhld sq1C inx h shld sq1C call delay_1_sec out WATCHDOG_PET_O ; Send "Digital Housekeeping Packet" (aka SOH Packet) ; Stamp with sample time ; *** removed rev 7.5 ; lxi h,GBL_SOH+205 ; IDH_SAMPLE_TIME ; call CLOCK_READ ; lxi d,GBL_SOH+205 ; call CLOCK_6_TO_10 ; (make a copy first, because some tasks write directly into GBL_SOH) lxi h,GBL_SOH_ARRAY lxi d,GBL_SOH_COPY mvi c,236 call copy_bytes mvi a,1Dh ; ApID 71D lxi b,254 ; total packet length is 254 lhld sq1D ; this ApID's source sequence number xchg lxi h,GBL_SOH_COPY call CCSDS_HSKP ; send it out ; increment the source sequence counter lhld sq1D inx h shld sq1D ; call delay_1_sec jmp again ; === SOH Output === ; Generate SOH telemetry on the SOH serial port. SOH_OUT: ; A - byte push psw push b mov b,a ; preserve byte ; loop until XMTR is ready loop: in CMD_SOH_STS_I ani 1 ; bit 0: 1=Xmt buffer ready jnz sendit call task ; non-preemptive multi-tasking jmp loop ; send byte sendit: mov a,b ; restore byte out SOH_TX_O ; send it pop b pop psw ret ; Event Queue pointer e_fetch ds 2 ; Sprite/Lightning Event Interrupt Service public EVENT_ISR EVENT_ISR: push psw ; clear RST_6 interrupt in IRQ_ENABLE_I ani 0BFh ; bit 6 =0 out IRQ_ENABLE_O ; Enable Exposure interrupt (RST5) ; and Re-enable Event interrupt ; b6=1 re-enables RST6 ; b5=1 enables Exposure interrupt ori 060h out IRQ_ENABLE_O ; Capture Time in Event queue, code=0 mvi a,0 ; code 0 - trigger event call SOH_TOEVQ ; ***7.9*** ; increment 4-byte IDH_N_EVENTS (GBL_SOH+23) ; byte 0 lxi h,GBL_SOH+23+3 ; point to low-order byte mov a,M ; fetch it adi 1 ; add 1 to it mov M,a ; replace ; byte 1 dcx h ; step back to next higher byte mov a,M ; fetch aci 0 ; add carry mov M,a ; replace ; byte 2 dcx h ; step back to next higher byte mov a,M ; fetch aci 0 ; add carry mov M,a ; replace ; byte 3 dcx h ; step back to next higher byte mov a,M ; fetch aci 0 ; add carry mov M,a ; replace ; *** ; delay before re-arming ; set timer ; lhld GBL_TRIGGER_DELAY ; call DCT_SET ; mvi a,1 ; sta GBL_DOING_TRIG_DELAY pop psw ei ret ; subroutine to get element from Event Queue SOH_FROMEVQ: ; HL - queue fetch-pointer value ; DE - where to store time (6 bytes) ; Returned: ; A - 0=no event, 1=event delivered ; C - code (1=trigger-event, 2=exposure, other=readout) ; HL - updated queue fetch-pointer value push d push d ; >>save where to store event time xchg ; HL(fetch-pointer) -> DE lhld GBL_EVENT_QUEUE_STORE_PTR ; if fetch=store, queue is empty mov a,h cmp d jnz notmt mov a,l cmp e jnz notmt ; queue was empty pop h ; <