; ==== ISUAL Flight Software -- Univ of California, Berkeley, SSL ====
; PVCFDCM - generate PVCFs from Packets -- DCM version
;  uses DCM functions

; Revision History:
;  18-Dec-2002 - SPG - ISUAL Flight Software rev 7.3
;    First Official Release
;  26-Mar-2003 - SPG - FSW rev 7.7
;    PVCF_FLUSH writes dummy packet with PVCF_DPU, not PVCF_MM
;  6-Aug-2003
;    fixed PVCF_FLUSH to not write last PVCF
;    from partly undefined MM
; 13-Oct-2003 if MM off, pretend SC buffers are full
; (which prevents writing any more PVCFs)
; 16-Oct-2003
; implement GBL_PVSTART
; 21-Oct-2003 - eliminate "P" debug output
; 30-Oct-03 - release ILK if SC fault
        include pvcf.i
        include util.i
        include gbl.i
        include mm.i
        include cdi.i
        include task.i
        include debug.i

PVCF_INIT:
        mvi a,0FFh
        sta GBL_DCM_STATUS
        mvi a,0
        sta GBL_PVCF_ILK
        ret

; message sent to DCM
kludge  ds 32          ; room for 8 words of "PP" commands
        db 0,0,0,9     ; op=9 (end of command list)
wurd    ds 4
t0      ds 1

PVCF_START:
        push psw
        push b
        push d
        push h
; Store initial parameters to DCM, into MM
        lxi h,GBL_PP_OP
        lxi d,kludge
        mvi c,8*4           ; 8 words of PP commands
        call copy_bytes
        lxi d,GBL_BPL_CMD
        lxi h,kludge
        lxi b,8+1           ; include op=9
        call mm_store
; Send CDI 33 to DCM
        mvi a,33h
        call cdi_send
; set switch: "PVCF_START has been called"
        mvi a,1
        sta GBL_PVSTART

        pop h
        pop d
        pop b
        pop psw
        ret

; internal subroutine to compare 2-byte counts
; DE - points to one 2-byte count
; HL - points to the other
;  (return with condition code set)
compare_counts:
        ldax d
        cmp M
        rnz
        inx d
        inx h
        ldax d
        cmp M
        ret


; -- check for last op completed (if not, return A=1)
; -- fetch number of PVCFs in each buffer
; -- check for both buffers full (return A=1) 
; if all OK, return A=0
get_pvcf_counts:
        push b
        push d
        push h

; If MM is off, pretend SC buffers are full
        lda GBL_MM_STATUS
        cpi 0
        jz bothfull
; same if PVCF_START has yet to be called
        lda GBL_PVSTART
        cpi 0
        jz bothfull

; Fetch number of PVCFs in each buffer
        lxi d,GBL_PP_N_SC1  ; get PVCF count for buffer 1
        lxi h,WURD
        lxi b,1
        call mm_fetch
        lxi h,WURD+2     ; (max is 4095)
        lxi d,GBL_SOH+71
        mvi c,2
        call copy_bytes  ; copy into telemetry
        lxi h,GBL_SOH+71
; MAXNPVCFS is a 4-byte allocation; we look at just the low 2 bytes
        lxi d,GBL_PP_MAXNPVCFS+2
        call compare_counts  ; is it max?
        jnz notfull1
        mvi a,1         ; flag: SC1 is full
        sta GBL_SC_BUF1
notfull1:
        lxi d,GBL_PP_N_SC2  ; get PVCF count for buffer 2
        lxi h,WURD
        lxi b,1
        call mm_fetch
        lxi h,WURD+2
        lxi d,GBL_SOH+73
        mvi c,2
        call copy_bytes     ; copy into telemetry
        lxi h,GBL_SOH+73
        lxi d,GBL_PP_MAXNPVCFS+2
        call compare_counts
        jnz notfull2
        mvi a,1         ; flag: SC2 is full
        sta GBL_SC_BUF2
notfull2:
; are both full?
        lda GBL_SC_BUF1
        mov c,a
        lda GBL_SC_BUF2
        add c
        cpi 2           ; both?
        jz bothfull
        mvi a,0         ; no, return A=0
rchk:   pop h
        pop d
        pop b
        ret
bothfull:
        mvi a,1
        jmp rchk        ; yes, return A=1

; Command list which is sent to DCM, to tell DCM
; to process packet into PVCFs
pproc   db 0,0,0,1      ; op=1
nbhdr   db 0,0,0,0      ; N bytes in 2ndary and other headers
mmdata  ds 4            ; MM addr of data
        db 0,0,0,9      ; end of list


; Send packet from DPU memory
;  HL - address of Primary and Secondary headers
;  DE - address of data

; This is typically non-science packets.
; The primary and secondary headers (16 bytes)
; are copied into a fixed place in MM,
; followed by the data part of the packet.

; The second word of the command gives the total number of bytes 
; in the primary and secondary headers (16)
PVCF_DPU:
        push psw
        push b
        push d
        push h
        call get_pvcf_counts
; if both SC buffers full, throw away data
        cpi 1           ; A=1 if both full (or timeout)
        jnz okdpu
; declare "Spacecraft fault"
scfault:
        lxi h,GBL_SOH+75   ; SC Fault
        inr M              ; increment fault-counter
        mvi a,1
        sta GBL_SOH+12  ; flag: at least one fault happened
        jmp opdone         ; ***30-Oct-03 (was xit)

okdpu:
        push d          ; >>save data pointer 
; write headers to Mass Memory
        lxi d,GBL_PP_MMHDRS
        lxi b,4         ; 16 bytes
        call mm_store
; number of bytes in secondary header is 10
        mvi a,0
        sta nbhdr+2
        mvi a,10
        sta nbhdr+3
; follow by data
; (data address is GBL_PP_MMHDRS + 4)
        lxi h,GBL_PP_MMHDRS
        lxi d,mmdata
        mvi c,4
        call copy_bytes
; add 4 to last byte 
; (value for GBL_PP_MMHDRS chosen so there will not be a carry)
        lda mmdata+3
        adi 4
        sta mmdata+3
; (always copy 256 bytes - data headers never exceed this)
        lxi d,mmdata    ; MM address
        pop h           ; <<restore data pointer
        lxi b,64        ; 256 bytes
        call mm_store
go:
        lxi h,pproc
        lxi d,GBL_BPL_CMD
        lxi b,4         ; command list is 4 words
        call mm_store
; prevent DCM task from sending CDI to DCM
; to start compression
ckilk:  lda GBL_PVCF_ILK
        cpi 0
        jz prevent
        call task
        jmp ckilk
prevent:
        mvi a,1
        sta GBL_PVCF_ILK
; now send CDI 33 to start the processing
        mvi a,33h
        call cdi_send
; wait for operation to complete
        lda GBL_SECONDS_CTR
        sta t0          ; for timeout
ckop:   call task
        lxi d,GBL_BPL_CMD
        lxi h,WURD
        lxi b,1         ; fetch one word
        call mm_fetch
; if first word of command list is -1, this means the
; commands were executed
        lda WURD        ; (just check 1st byte)
        cpi 0FFh
        jz opdone
        lda t0
        mov c,a
        lda GBL_SECONDS_CTR
        sub c
        cpi 4
        jm ckop
; timeout.  DCM didn't complete operation
 call debug_asc
 asc "PVCF t/o$"
; declare SC fault
        jmp scfault

; release interlock with DCM
opdone: mvi a,0
        sta GBL_PVCF_ILK
; mvi a,'P'
; call debug_putbyte
xit:    pop h
        pop d
        pop b
        pop psw
        ret


; Send Data Packet, getting data from Mass Memory
;  HL - points to Headers plus 
;   other Science Data Packet stuff (4 more bytes)
;  DE - points to MM address of data
PVCF_MM:
        push psw
        push b
        push d
        push h
        call get_pvcf_counts
; if both SC buffers full, throw away data
        cpi 1           ; A=1 if both full (or timeout)
        jz scfault
       
        push d          ; >>save data MM pointer 
; write headers to Mass Memory
        lxi d,GBL_PP_MMHDRS
        lxi b,5         ; 20 bytes
        call mm_store

; store the MM address of data in the command list
        lxi d,mmdata
        pop h           ; <<restore data MM pointer
        mvi c,4         ; copy the MM address
        call copy_bytes

; number of bytes in secondary header (plus 4 more bytes)
        mvi a,0
        sta nbhdr+2
        mvi a,14
        sta nbhdr+3

        jmp go

dummy_packet
        db 0,0,0,0
        ds 2

PVCF_FLUSH:
; force a flush of the current PVCF by sending
; a dummy packet which begins with zero
; (marking the end of a PVCF stream for the
; ground software) and a length of 1105
;
; do nothing if PVCF_START hasn't been called
        lda GBL_PVSTART
        cpi 0
        rz 

        lxi h,1105
        mov a,h
        sta dummy_packet+4
        mov a,l
        sta dummy_packet+5
        lxi h,dummy_packet ; (header)
; ***6-Aug-2003 
        lxi d,GBL_PP_MMSC1  ; (MM addr of data)
        call PVCF_MM 
; ***
; make sure PVCF commands completed
        call get_pvcf_counts
        ret

