; ==== ISUAL Flight Software -- Univ of California, Berkeley, SSL ==== ; dcm.a -- Interface with the Data Compression Module (DCM) ; Compatible with DCM DSP software revision 1.0 ; Revision History: ; 13-Nov-2002 - SPG ; ISUAL Flight Software rev 7.3 ; 24-Sep-2003 ; replaced dogbite with out SOFTWARE_RESET_O ; 30-Oct-03 - watch for DCM_STATUS=FF during OP wait ; increase MMCB compression t/o to 120 sec ; 11-Feb-04 - remove PRI_FLAG include dcm.i include debug.i include gbl.i include util.i include task.i include mmcb.i include mm.i include cdi.i include ioports.i NClist equ 16 ; number of MMCBs in Compression List ncc ds 1 ; counts number of entries ncmax ds 1 ; number of MMCBs actually loaded clist_pointer ds 4 Dcm_stuff ds 8 dcm_loaded ds 1 ; flag Busy_T0 ds 1 ; for timeouts ; local pointer to DCM queue dcm_qp ds 3 ; banked memory pointer remember ds 3 dcm_init: mvi a,0 sta dcm_loaded ; MMCB compression list not loaded ; start the DCM Task lxi d,DCM_Task lxi h,GBL_DCM_STACK+stack_size call task_new ret m1 db 255,255,255,255 bpl_status ds 4 ; =====DCM Task===== DCM_TASK: call task ; task is idle -- nothing on DCM queue, or being compressed mvi a,1 sta GBL_DCM_IDLE ; task is idle ; if DCM disabled (Status=FB), bypass DCM startup lda GBL_DCM_STATUS cpi 0FBh jz after_DCM_start ; Wait for /I_DCM_ON to set DCM_STATUS=01 lda GBL_DCM_STATUS cpi 01h jnz DCM_TASK ; Wait for Busy=False (while off, DCM shows busy=true) wbusy: call task ; Wait for DCM Busy=false in MM_IM_DCM_STS_I ani 10h ; bit 4: 1 -- busy=true jnz wbusy mvi a,2 sta GBL_DCM_STATUS ; status=02 ; DCM BIOS has initialized. ; Now store the "Base Parameter List" (BPL) into MM ; at MM address 'nnnn0000' lxi d,GBL_BPL_MMADDR ; MM addr of BPL lxi h,GBL_BPL_STATUS ; the BPL lxi b,5 ; 5 words call mm_store ; Write -1 into first word of command list lxi h,m1 ; -1 as word lxi d,GBL_BPL_CMD ; MM addr of command list lxi b,1 ; one word call mm_store ; write 0 into BPL_Status lxi h,GBL_ZERO lxi d,GBL_BPL_STATUS lxi b,1 call mm_store ; send CDI 30 to DCM, with data 'nnnn' lxi h,GBL_BPL_MMADDR mvi a,30h call cdi_send ; now wait for BPL Status = 1 wbpl: call task lda GBL_DCM_STATUS cpi 0FFh jz DCM_TASK ; DCM was turned off lxi d,GBL_BPL_STATUS lxi h,bpl_status lxi b,1 call mm_fetch lda bpl_status+3 cpi 01h jnz wbpl ; set DCM status = 03 mvi a,03h sta GBL_DCM_STATUS after_dcm_start: ; ===MMCB Processing Section=== more_work: call task lda GBL_DCM_STATUS cpi 0FFh jz dcm_task ; DCM was shut down ; DCM is available for work. ; If there are entries on the DCM queue, ; copy some of them into Mass Memory lda GBL_DCM_QHEAD cpi 0 jz more_work ; queue still undefined cpi 0FFh jnz do_work ; DCM is idle mvi a,1 sta GBL_DCM_IDLE jmp more_work do_work: ; DCM is not longer idle mvi a,0 sta GBL_DCM_IDLE ; As we load the Compression List, ; we use a local queue pointer (dcm_qp), because we don't ; want to take these entries off the DCM queue just yet. lxi h,GBL_DCM_QHEAD lxi d,dcm_qp ; local queue pointer mvi c,3 call copy_bytes ; mvi a,0 ; entry-counter = 0 sta ncc ; set MM address of 1st entry of compression list lxi h,GBL_BPL_MMCB lxi d,clist_pointer mvi c,4 call copy_bytes ; Fill the list with MMCBs copy_more: ; Fetch the DCM entry lxi d,dcm_qp lxi h,mmcb_status call mmcb_fetch ; Status is Readout? lda mmcb_status cpi status_Readout jnz end_copy ; not readout ; *** 11-Feb-04 remove PRI_FLAG code ; count another entry lda ncc inr a sta ncc ; copy MMCB to Compression list ; Store in Compression List call clist_store ; follow queue chain: dcm_qp = mmcb_link lxi h,mmcb_link lxi d,dcm_qp mvi c,3 call copy_bytes ; any more entries to copy? lda dcm_qp cpi 0FFh ; null link? jz end_copy ; yes; no more call next_clist_entry ; keep track of how many actual-data entries copied lda ncc cpi NClist ; max allowed jnz copy_more end_copy: lda ncc sta ncmax ; actual max ; Fill unused Compression List entries mvi a,status_Idle sta mmcb_status ; unused element ; how many el'ts to fill lda ncc mov c,a mvi a,NCList sub c jz lloaded mov c,a filll: call next_clist_entry call clist_store dcr c jnz filll lloaded: ; MMCB's have been copied to Compression List ; We leave the MMCBs on the DCM queue. ; When the DCM finishes this processing cycle, ; we will move the MMCBs from the DCM queue ; to the TM queue. ; It is possible that the DCM will "latch up" ; and we'll have to start it again, ; with the same set of MMCBs. ; Set flag: DCM is loaded mvi a,1 sta DCM_loaded lda GBL_DCM_STATUS cpi 0FFh jz DCM_TASK cpi 0FBh ; bypassing DCM jz ucl2 ; Signal the DCM to start work again ... ; First, set BPL Status word to 0 lxi h,GBL_zero lxi d,GBL_BPL_STATUS lxi b,1 ; 1 word call mm_store mvi a,'b' call debug_putbyte ; delay until PVCF op is complete wpvcf: call task lda GBL_DCM_STATUS cpi 0FFh jz dcm_task ; watch for DCM shut off lda GBL_PVCF_ILK cpi 1 jz wpvcf mvi a,1 sta GBL_PVCF_ILK ; Then send CDI 32 mvi a,32h call cdi_AHL call task ; The DCM should set Busy=true, then do its thing. ; When complete, DCM sets BPL Status to 1 ; and sets Busy=false lda GBL_SECONDS_CTR sta dto jmp waitc dto ds 1 waitc: call task lda GBL_DCM_STATUS cpi 0FFh jz dcm_task ; watch for DCM shut off ; test for busy in MM_IM_DCM_STS_I ani 10h ; bit 4 jnz waitc ; Busy=false, now check BPL Status=1 lxi h,bpl_status lxi d,GBL_BPL_STATUS lxi b,1 ; 1 word call mm_fetch lda bpl_status+3 cpi 1 jz ucl ; status=1; compression complete lda dto mov c,a lda GBL_SECONDS_CTR sub c cpi 120 ; ****30-Oct-03 15 jm waitc call debug_asc asc "MMCB t/o$" in MM_IM_DCM_STS_I call debug_showa ; DCM successfully finished with the MMCB list ; Unload the Compression List, ; copy entries to the TM queue ucl: mvi a,01h sta GBL_DCM_STATUS mvi a,0 ; release interlock sta GBL_PVCF_ILK mvi a,'e' call debug_putbyte ucl2: lxi h,GBL_BPL_MMCB ; point to start of Compression List lxi d,clist_pointer mvi c,4 call copy_bytes mvi a,0 ; entry_count=0 sta ncc unload: ; get Compression List entry lxi d,clist_pointer call clist_fetch cpi 1 ; checksum OK? jnz skippit ; no, skip this MMCB lda GBL_DCM_STATUS cpi 0FBh ; bypassing DCM? jz bypass lda mmcb_status cpi status_Idle jz unload_done ; not a full list cpi status_Compressed jz processed cpi status_UC ; DCM didn't compress it jz pass_thru ; If it's still 'Readout', the DCM must have ; seen bad checksum and skipped the MMCB cpi status_Readout jz skippit jmp processed bypass: mvi a,status_UC sta mmcb_status ; pass thru un-compressible data pass_thru: lxi h,mmcb_owords lxi d,dcm_stuff ; output N words = input mvi c,4 call copy_bytes jmp proc2 ; Clist entry had bad checksum or other problem ; Skip this MMCB; log a DCM fault skippit: call debug_asc asc "skp$" lxi h,GBL_SOH+202 inr M mvi a,1 sta GBL_SOH+12 ; at least one fault happened ; Fetch the corresponding MMCB from the DCM queue lxi d,GBL_DCM_QHEAD lxi h,mmcb_status call mmcb_fetch ; re-cycle it mvi a,status_Recycle sta mmcb_status jmp to_tm ; MMCB has been processed by DCM, now ready for TM processed: ; Capture owords and ockw, which the DCM may have changed lxi h,mmcb_owords lxi d,dcm_stuff mvi c,4 call copy_bytes lxi h,mmcb_ockw mvi c,4 call copy_bytes proc2: lda mmcb_status push psw ; preserve status ; Fetch the corresponding MMCB from the DCM queue lxi d,GBL_DCM_QHEAD lxi h,mmcb_status call mmcb_fetch ; Copy in the data from the List MMCB lxi h,dcm_stuff lxi d,mmcb_owords mvi c,4 call copy_bytes lxi d,mmcb_ockw mvi c,4 call copy_bytes pop psw sta mmcb_status ; restore status to_tm: ; Now take this MMCB off the DCM queue ; and put it on the TM queue ; Set remember=GBL_DCM_QHEAD lxi h,GBL_DCM_QHEAD lxi d,remember mvi c,3 call copy_bytes ; make a new head for DCM queue ; GBL_DCM_QHEAD = mmcb_link lxi h,mmcb_link lxi d,GBL_DCM_QHEAD mvi c,3 call copy_bytes ; Attach MMCB to TM queue ; First, set link of this MMCB to null mvi a,0FFh sta mmcb_link lxi d,remember lxi h,mmcb_status call mmcb_store ; store this MMCB back in banked RAM ; fetch tail of TM queue lda GBL_TM_QTAIL cpi 0FFh jz newTMtail ; no tail -- make a new one ; set Link of Tail pointing to this MMCB lxi d,GBL_TM_QTAIL ; fetch Tail lxi h,mmcb_status call mmcb_fetch ; set link to point to the current MMCB lxi h,remember lxi d,mmcb_link mvi c,3 call copy_bytes ; re-store lxi h,mmcb_status lxi d,GBL_TM_QTAIL call mmcb_store newTMtail: ; set current MMCB as new TM queue tail lxi h,remember lxi d,GBL_TM_QTAIL mvi c,3 call copy_bytes ; If head is null, make same as tail lda GBL_TM_QHEAD cpi 0FFh jnz nnh lxi h,GBL_TM_QTAIL lxi d,GBL_TM_QHEAD mvi c,3 call copy_bytes nnh: ; decrement number of MMCB's on DCM queue lxi h,GBL_SOH+27 ; IDH_N_MC call DECBIG ; if negative, force to zero mov a,M ani 80h jz notneg mvi M,0 inx h mvi M,0 notneg: ; continue with next Compression List entry call next_clist_entry lda ncc inr a sta ncc mov c,a lda ncmax sub c jnz unload unload_done: ; DCM is now no longer loaded mvi a,0 sta dcm_loaded jmp more_work ; step to next MMCB in clist next_clist_entry: push h ; advance the Clist pointer lxi h,clist_pointer+3 ; 4-byte add mov a,M adi mmcb_length/4 mov M,a dcx h ; mov a,M aci 0 ; propagate carry mov M,a dcx h ; mov a,M aci 0 ; propagate carry mov M,a dcx h ; mov a,M aci 0 ; propagate carry mov M,a pop h ret ck4 ds 4 ; calculate 32 bit (4-byte) MMCB checksum ; by doing 4 passes, one for each byte calc_ck4: push psw push b push d push h ; lxi d,4 lxi h,mmcb_status ; start of MMCB mvi c,10 ; 10 words mvi a,0 ck0l: xra M dad d dcr c jnz ck0l sta ck4 ; lxi h,mmcb_status+1 ; 2nd byte mvi c,10 mvi a,0 ck1l: xra M dad d dcr c jnz ck1l sta ck4+1 ; lxi h,mmcb_status+2 mvi c,10 mvi a,0 ck2l: xra M dad d dcr c jnz ck2l sta ck4+2 ; lxi h,mmcb_status+3 mvi c,10 mvi a,0 ck3l: xra M dad d dcr c jnz ck3l sta ck4+3 ; pop h pop d pop b pop psw ret ; =============== ; Read an MMCB from Compression List in Mass Memory ; DE - points to 4-byte MM address ; A - returned: 1=OK, 0=checksum failed clist_fetch: push b push d push h ldax d mmler: cpi 0FFh ; null MM pointer? ;**** jz mmler ; yes; force a dog bite jnz ok out software_reset_o ok: ; fetch from Mass Memory lxi b,mmcb_length/4 ; number of words in an MMCB ; BC - number of 32-bit MM words ; DE - points to 4-byte MM address ; HL - where data is to be stored in DPU memory lxi h,mmcb_status call mm_fetch ; verify 4-byte MMCB checksum call calc_ck4 lxi h,ck4 lxi d,mmcb_ckw mvi c,4 vl1: ldax d cmp M jnz badck inx h inx d dcr c jnz vl1 mvi a,1 ; checksum OK retu: pop h pop d pop b ret badck: mvi a,0 ; checksum failed jmp retu ; Write an MMCB to Mass Memory ; MM address at clist_pointer ; write from local mmcb storage clist_store: push psw push b push h ; calculate 32 bit MMCB checksum call calc_ck4 lxi h,ck4 lxi d,mmcb_ckw mvi c,4 call copy_bytes ; copy the MMCB to Mass Memory lxi b,mmcb_length/4 ; number of words to write lxi d,clist_pointer ; pointer to MM addr lxi h,mmcb_status ; 1st byte of MMCB call MM_STORE pop h pop b pop psw ret