; ==== ISUAL Flight Software -- Univ of California, Berkeley, SSL ====
; BGLOOP.a -- Initialization and Background Loop Task   
;  
; Includes:
;    Overall initialization (entry point MAIN)
;    BG Loop Task
;    PPS interrupt service
;    1-second interrupt service
;    downcounter timer
;    debug keystroke functions
;    filter wheel test
;    DCM debug monitor
;
; Revision History:
;  18-Dec-2002 - SPG
;    ISUAL Flight Software rev 7.3
;  20-Dec-2002 - SPG - ISUAL FSW 7.4
;    Changed rev number to 7.4
;  21-Dec-2002 - SPG - ISUAL FSW 7.5
;    Changed rev number to 7.5
;  31-Dec-2002 - 
;    F.F, using DEBHP
;    Check for validity of Debug code.
;    Removed ISRs for RST_0 and RST_7
;    Removed Filter Wheel test
;  15-Jan-2003
;    messages for Extension check rejects
;    remove keystroke functions
;   6-Feb-2003 
;    fix bank-select errors in "main"
;   7-Feb-2003 - SPG 
;    don't set SCIF_CTL_O to zero
;   14-Feb-2003 rev 7.7
;    Expect EEPROM rev 7.7
;    Init GBL_TRIGGER_DELAY=100
; 9-Sep-2003
;    execute I_SAFE on MM upset
; 3-Oct-2003
;    use CDIs to recover from MM upset
; 6-Oct-2003
;    display Rev 7.8
; 10-Oct-2003
;    MM_TEST called from BG Loop, not 1 Hz ISR
;    do I_STANDBY on upset (not I_SAFE)
; 30-Oct-2003
;    set default DCM s/w rev code = 02
; 10-Feb-2004
;    display rev 7.9
; 17-May-2005 
;    remove some debug displays
        include task.i
        include ioports.i
        include day.i
        include debug.i
        include htr.i
        include u.i
        include util.i
        include gbl.i
        include pwr.i
        include clock.i
        include cmd_in.i
        include mmcb.i
        include dcm.i
        include tm.i
        include cmd.i
        include soh.i
        include ccsds.i
        include pvcf.i
        include sc.i
        include mm.i
        include execute.i
        include cdi.i
        include filter.i
        include eeprom.i

;
;
mmtick ds 1

; Internal 1-Hz Interrupt Service
HZ_ISR: 
        push psw
        push b
        in IRQ_LEVELS_I
        mov c,a
; Is downcounter enabled?
        in IRQ_ENABLE_I
        ani 04h         ; b2
        jz tick         ; no, go check for 1-Hz tick  
; Counter is enabled; see if the request is there too
        mov a,c
        ani 04h         ; b2=1 if downcounter
        jz tick
; Interrupt was the downcounter timer
; mask the interrupt
        in IRQ_ENABLE_I
        ani 0FBh        ; b2=0
        out IRQ_ENABLE_O
        mvi a,1
        sta GBL_DCTIMER ; set "timer done" switch
; If this was timing the Trigger Delay, re-arm triggers
        lda GBL_DOING_TRIG_DELAY
        cpi 1
        jnz tick
        call MMCB_REARM
        mvi a,0
        sta GBL_DOING_TRIG_DELAY

; check for 1-Hz tick
tick:   mov a,c
        ani 1           ; b0=1 if 1-sec tick
        jz hzxit
; increment the global byte-counter
        lda GBL_SECONDS_CTR
        inr a
        sta GBL_SECONDS_CTR
; clear the 1-Hz interrupt latch 
        out ONE_HZ_CLR_O
; set flag to cause exec of MM_TEST
        mvi a,1
        sta mmtick

hzxit:  pop b
        pop psw
        ei              ; re-enable interrupts
        ret

; Pulse-per-Second (PPS) Interrupt Service
PPS_ISR: 
        push psw
; clear PPS1,PPS2 received latches
        in SCIF_STS_I
        ani 0Fh         ; keep nom/red (b0..2) bits and HV prot (b3)
        ori 80h         ; b7=1
        out SCIF_CTL_O
; increment the global byte-counter
        lda GBL_PPS_CTR
        inr a           
        sta GBL_PPS_CTR
        sta GBL_SOH+97  ; IDH_PPS_CTR
        pop psw
        ei              ; re-enable interrupts
        ret

; Set downcounter timer
; HL - count (1024 is one second)
        public DCT_SET
DCT_SET:
        push psw
        mvi a,0
        sta GBL_DCTIMER ; reset "done" flag
        mov a,l         ; low order of count
        out TIMER_SET_L_O
        mov a,h         ; high order of count
        out TIMER_SET_H_O ; This starts the timer
; enable the interrupt
        in IRQ_ENABLE_I
        ori 04h         ; b2=1
        out IRQ_ENABLE_O
        pop psw
        ret

; ===============
; Background Loop
; ===============
;
dcm_debug ds 4
istandby db 03Eh

bgloop: call task            ; cycle the tasks
        out WATCHDOG_PET_O   ; restart watchdog timer

; run Mass Memory test every second
        lda mmtick
        cpi 0
        jz nomm
; Now we're going to call the Mass-Memory test (in MM.a)
        call MM_TEST
        mvi a,0
        sta mmtick

nomm:
; if we had an MM upset, do an I_STANDBY
        lda GBL_MM_UPSET
        cpi 1
        jz got_upset
        cpi 2
        jnz noupset
; see if 2 seconds have passed
        lda MMSECS
        mov c,a
        lda GBL_SECONDS_CTR
        sub c
        sui 2         ; 2 seconds wait
        ani 80h
        jnz noupset   ; need more time
; enough time; turn MM banks back on
        mvi a,MM_PWR_A
        lxi h,1
        call CDI_AHL
        mvi a,MM_PWR_B
        call CDI_AHL
        mvi a,1
        sta GBL_MM_STATUS       ; it's on
        mvi a,0       ; reset switch
        sta GBL_MM_UPSET
; mvi a,'%'
; call debug_putbyte

        jmp noupset
MMSECS  ds 1

got_upset:
; mvi a,'U'
; call debug_putbyte
; Got a MM upset.  
; Issue a I_STANDBY command (MM was turned off by MM_TEST)
        lxi h,istandby
        call EXECUTE
; now set a switch which tells us to turn MM back on 
; after 2 seconds
        mvi a,2
        sta GBL_MM_UPSET
        lda GBL_SECONDS_CTR  
        sta MMSECS
noupset:

; display DCM debug code
        lda GBL_DCM_STATUS
        cpi 0FFh
        jz nodebug
        cpi 0FBh
        jz nodebug
         lda GBL_PWR+2
         ani 1
         jz nodebug
        lxi h,DCM_DEBUG
        lxi d,GBL_BPL_DEBUG
        lxi b,1
        call mm_fetch
; test for non-zero
        mov a,M
        inx h
        ora M
        inx h
        ora M
        inx h
        ora M
        jz nodebug
; display non-zero debug word
;        call debug_asc
;       asc "DCMdebug$"
;        lxi h,dcm_debug
;        mvi c,4
;        call debug_dump
; set it back to zero
        lxi h,GBL_ZERO
        lxi d,GBL_BPL_DEBUG
        lxi b,1
        call mm_store
nodebug:

        jmp bgloop



; === called from DPU.A
        public main
main:

; setup BG Loop Stack 
        lxi sp,GBL_BG_STACK+stack_size
        out WATCHDOG_PET_O  ; restart WATCHDOG timer

; Clear GBL memory (see GBL.I)
        lxi h,GBL       ; global memory
        lxi d,GBL_END   ; end of global memory
cgm:    mvi M,0         ; store zero
        inx h           ; next address
        mov a,h
        cmp d           ; when HL=DE, exit loop
        jnz cgm
        mov a,l
        cmp e
        jnz cgm

; Initially, 3= throw away debug packets 
; Later, patch GBL_720 to 0, to send packets on SOH channel
;                   or to 1, to send packets on science channel
        mvi a,3 
        sta GBL_720

; Check the integrity of the debug code 
DEBHP_BANK equ 0B2h     ; bank with DEBHP
;DEBHP_BANK equ 087h     ; bank with DEBH
        mvi a,DEBHP_BANK
        out BANK_SELECT_O         ; select bank [6Feb03]
        call CHKB       ; (in EXECUTE.a)
        cpi 0
        jz debugok
; failed checksum - default to no debug output
        call DEBUG_DISABLE  ; mark debug code "don't use"
        jmp pjt
debugok:
; Debug code is OK.
; copy DEBUG code (see DEBHP.a) from EEPROM bank to RAM C000h
        mvi a,DEBHP_BANK
        out BANK_SELECT_O         ; select bank
        lxi h,4000h     ; source -- banked memory window
        lxi d,0C000h    ; destination
        lxi b,520h      ; number of bytes
cpdb:   mov a,M
        stax d
        inx h
        inx d
        dcx b
        mov a,b
        ora c
        jnz cpdb

; patch jump table in debug code (see "DEBHP.L")
pjt:    lxi h,ccsds_hskp
        shld 0C001h
        lxi h,task
        shld 0C004h
        lxi h,task_new
        shld 0C007h

; Default Memory Bank Register setting
        mvi a,0
        out BANK_SELECT_O         ; bank=0

; Initialize SCIF_CTL_O
;  b7..4
;  b3 =0 enable HV protect
;  b2..0 =0 Nominal PPS,TLM,CMD/SOH
;*** rev 7.6 eliminate
;        mvi a,0
;        out SCIF_CTL_O


; Initialize non-preemptive multi-tasking
        call TASK_INIT

; start Debug output
        call DEBUG_INIT

; Day Sensor
        call DAY_INIT   

; Initialize Event Queue
        lxi h,GBL_EVENT_QUEUE
        shld GBL_EVENT_QUEUE_STORE_PTR

; Initialize Command and Status ports
        call CMD_IN_INIT ; (call this before SOH_INIT)
        call EXECUTE_INIT ; command executions

; Initialize SOH telemetry
; Start task to generate Housekeeping at regular intervals
        call SOH_INIT

; Initialize Command Handling
; Clear Time-tagged command list
        call  CMD_INIT

; Initialize DPU's time-of-day clock
        call CLOCK_INIT

; Filter Controller (after clock init)
        call FILTER_INIT

; Initialize Command-Data-Interface
        call CDI_INIT
;
; Initialize Power Services
        call PWR_INIT
;
; Turn on Housekeeping power
        mvi a,16        ; PS 16
        call PWR_SET_ON
;
; Turn on Mass Memory
        call MM_INIT
;
; none of these actually write into Mass Memory
        call CCSDS_INIT ; CCSDS packet builder
        call SC_INIT    ; PVCF storage for Spacecraft 
        call PVCF_INIT  ; generates PVCFs from packets
;
; Initialize Heater control (after CCSDS because of EEPROM)
        call HTR_INIT
;
; Start tasks to manage Mass Memory
        call MMCB_INIT 
; 
; Start DCM Manager
        call DCM_INIT
;
; Start Telemetry Generator task
        call TM_INIT

; establish code for what kind of DPU restart
        in STATUS6_I
        mov b,a

        mvi c,'P'
        ani 10h         ; power-on?
        jnz setc        ; yes

        mvi c,'S'
        mov a,b
        ani 20h         ; software?
        jnz setc

        mvi c,'W'       ; Watchdog timer?
        in WATCHDOG_STS_I
        ani 0F0h        ; any watchdog bites?
        jnz setc        ; yes, the dog indeed did bite

        mvi c,'?'       ; none of the above

        out WATCHDOG_PET_O  ; pacify watchdog

setc:   mov a,c
        sta GBL_SOH+136 ; IDH_P_RESET
        out RES_FLAG_CLR_O   ; clear the status bits
        out WATCHDOG_PET_O

; Setup the internal 1-Hz interrupt
        mvi A,JMP_OPCODE
        sta RST_2
        lxi h,HZ_ISR     ; address of Interrupt handler
        shld RST_2+1
; enable 1Hz interrupt request
        in IRQ_ENABLE_I     ; Interrupt Enable
        ori 01h             ; b0=1
        out IRQ_ENABLE_O

; Setup the Pulse-per-Second (PPS) spacecraft interrupt
        mvi A,JMP_OPCODE
        sta RST_65
        lxi h,PPS_ISR     ; address of Interrupt handler
        shld RST_65+1
; enable PPS interrupt request
        rim               ; RST 6.5 is handled by the 8085
; bit 3 1=mask-set enable
; bit 1 0=enable RST 6.5
        ori 08h         ; bit 3 =1  
; bits 4..7 off
        ani 0Dh         ; bit 1 =0
        sim


; Enable interrupts generally
        ei              ; enable interrupts
;
;  Fix the "no commands" bug (seen in IMAGE 17-March-1999)
        in CMD_RX_I     ; CMD Rx data

; get ISDPGLU Rev
        in ISDPGLU_REV_I
        cpi 077h
        jnz adda
        mvi a,'?'
        jmp showb
adda:   dcr a
        adi 'A'
showb:  sta GBL_SOH+137

        mvi a,10
; get ISDPWR  Rev
        in ISDPPWR_REV_I
        cpi 080h
        jnz adda1
        mvi a,'?'
        jmp showb1
adda1:  dcr a
        adi 'A'
showb1: sta GBL_SOH+138

; initially, set flag: no Time received from spacecraft
        mvi a,1
        sta GBL_SOH+30

        out WATCHDOG_PET_O    
 
; wait for a 1-Hz tick
        lda GBL_SECONDS_CTR
        mov c,a
w2sec:  out WATCHDOG_PET_O    
        call task
        lda GBL_SECONDS_CTR
        sub c
        jz w2sec

        mvi a,079h      ; 7.9 
        sta GBL_SOH+139         ; IDH_FSW_REV

; set default DSM s/w rev code (DCM02)
        mvi a,2
        sta GBL_SOH+140

; Get initial seconds-counter 
        lda GBL_PPS_CTR
        mov c,a

; Validate the EEPROM "extension" for this Software
        mvi c,078h      ; expected Revision is 7.8
ckok:   mvi a,EE_BANK ; in EEPROM bank
        out BANK_SELECT_O
        lda 7FFCh
;[6Feb03]        cpi EE_BANK ; should be same rev
        cmp c           ; should be same rev
        jz r1ok         ; yes

;        call debug_asc
;        asc "XREV$"
; allow time for debug packet to get out
rrr:    mvi c,200
rjj:    call task
        dcr c
        jnz rjj
; Software reset (back to PROM)
        out 0           

rchk:   
;       call debug_asc
;        asc "XCHK$"
        jmp rrr

; do a checksum of a bank
        public CHKB     ; (in EXECUTE.A)
r1ok:   call CHKB
        cpi 0
        jnz rchk        ; bad checksum

; EEPROM bank has been verified

; set default Trigger delay
        lxi h,100       ; 100 ms
        shld GBL_TRIGGER_DELAY  ; store little-endian

; Begin BG Loop
        mvi a,0
        out BANK_SELECT_O

; write 0 into BPL_debug
        lxi h,GBL_ZERO
        lxi d,GBL_BPL_DEBUG
        lxi b,1             
        call mm_store

        jmp bgloop



