; DEBH.a -- Debug Support ; intended to be executed at C000 ; FSW Rev 7.0 -- debug serial port is on RST_3 ; by itself, not shared with Day Sensor include ioports.i include gbl.i org 0C000h; dw DEBUG_INIT dw DEBUG_PUTBYTE dw DEBUG_SHOW dw DEBUG_DUMP dw DEBUG_ASC dw DEBUG_ASC_HL dw DEBUG_ASC_DEC dw DEBUG_SHOWMET dw DEBUG_SHOWUT dw DEBUG_SHOWA dw DEBUG_ASSERT dw DEBUG_REGSET debug_function: call 0 ret ; send byte to output queue ; A - the byte DEBUG_PUTBYTE: push psw push b push d push h ; mov b,a lda dtp_present cpi 0 jz pxit ; DTP not attached ; lda trap_flag cpi 1 jz trapio ; special if we had a TRAP lhld qpw ; pointer for writing into queue mov M,b ; store byte in queue inx h ; step pointer lxi d,GBL_DTP_OUTQ_WRAP mov a,l cmp e jnz nowrapw mov a,h cmp d jnz nowrapw lxi h,GBL_DTP_OUTQ ; back to the beginning nowrapw: shld qpw ; store the pointer ; now enable output interrupt mvi a,3 ; both in and out out DTP_CTRL_O pxit: pop h pop d pop b pop psw ret ; ; if outputting within a TRAP, ; don't use the queues and interrupts; do programmed I/O trapio: wll: in DTP_STS_I ani 1 ; wait for xmtr ready jz wll mov a,b out DTP_TX_O ; send out byte jmp pxit DEBUG_ASC: ; text follows call: look for '$' or '~' in following string ; (don't show '~' or '$') xthl ; exchange top of stack (TOS) with HL push psw a1: mov a,M ; get string byte cpi '$' ; end of string? jz a2 ; yes cpi '~' ; end with no newline? jz a2nl call debug_putbyte ; no send out byte inx h ; keep looking jmp a1 a2: mvi a,10 ; send Newline call debug_putbyte a2nl: inx h pop psw xthl ; set new return-address as TOS ret ; DEBUG_ASC_HL: ; HL - data value to display in Hex ; text follows call: look for '=' in following string xthl ; exchange top of stack (TOS) with HL push psw stl1: mov a,M ; get string byte call debug_putbyte ; send it out cpi '=' ; end of string? jz found_eq ; yes inx h ; no; keep looking jmp stl1 found_eq: inx h pop psw xthl ; set new return-address as TOS call HEXOUT ; tell monitor to display (original) HL as hex ret ; DEBUG_ASC_DEC: ; HL - data value to display in decimal ; text follows call: look for '=' in following string xthl ; exchange top of stack (TOS) with HL push psw ttl1: mov a,M ; get string byte call debug_putbyte ; send it out cpi '=' ; end of string? jz fnd_eq ; yes inx h ; no; keep looking jmp ttl1 fnd_eq: inx h pop psw xthl ; set new return-address as TOS call DECOUT ; tell monitor to display (original) HL as decimal ret ; show A= as 2-digit hex DEBUG_SHOWA: push psw push b mov b,a call send_packet_prefix mvi a,SHOW_HEXA call debug_putbyte mov a,b call debug_putbyte pop b pop psw ret ; ; show A as 2-digit hex DEBUG_SHOW_HEX1: push psw push b mov b,a call send_packet_prefix mvi a,SHOW_HEX1 call debug_putbyte mov a,b call debug_putbyte pop b pop psw ret ; ; packet codes recognized by U include u.i dtp_present db 0 ; 1=DTP attached, 0=flight mode ; ; ; serial output queue qpr ds 2 ; pointer for reading the queue qpw ds 2 ; pointer for writing the queue idle_flag ds 1 ; 1 if no more interrupts will happen ; trap_flag db 0 ; =1 if a TRAP has happened ; input processing state-machine in_state ds 2 ; ; ================================ ; Serial Input or Output Handler ; ================================ public DEBUG_ISR DEBUG_ISR: push psw push b push d push h ; test UART status for output in DTP_STS_I ani 1 cnz xmtr_ready ; ; test UART status for input in DTP_STS_I ani 2 cnz rcvr_ready ; dismiss: pop h pop d pop b pop psw ei ret ; ================== ; TRAP handler ; ================== prior_imask ds 1 prior_bank ds 1 where ds 2 stack_pointer ds 2 ; DEBUG_TRAP: di ; no more interrupts xthl ; exchange top-of-stack with HL shld where ; this is where the Trap happened lxi h,0 dad sp shld stack_pointer xthl push psw push b push d push h ; ; capture the bank registers in BANK_SELECT_I sta prior_bank ; mvi a,1 ; in a TRAP routine; use programmed I/O sta trap_flag rim ; read (prior) interrupt mask sta prior_imask ; display "\nTRAP@addr" lxi h,trap_msg call DEBUG_SHOW lhld where ; get where the Trap happened call DEBUG_SHOW_HEXN ; display " IMASK=xx\n" lxi h,imaskmsg call DEBUG_SHOW lda prior_imask mov l,a mvi h,0 call DEBUG_SHOW_HEXN ; show interrupt mask mvi a,32 ; space call debug_putbyte ; display "SP=" lxi h,speq call DEBUG_SHOW lhld stack_pointer call DEBUG_SHOW_HEXN ; show Bank register lxi h,bankmsg call DEBUG_SHOW lda prior_bank call DEBUG_SHOW_HEX1 mvi a,10 ; newline call debug_putbyte ; show a register set pop h pop d pop b pop psw call DEBUG_REGSET dogbite: out software_reset_o ; ***jmp dogbite ; switch to DMON4 EEPROM mvi a,86h out BANK_SELECT_O jmp 4000h speq asc "SP=" db 0 trap_msg db 13 asc "TRAP@" db 0 imaskmsg asc " IMASK=" db 0 bankmsg asc " Bank=" db 0 rcvr_ready: in DTP_RX_I ; read input byte lhld in_state ; get input state-machine address pchl ; jump there ; ; xmtr_ready: ; send byte from output queue to serial port ; ; if the queue pointers are equal, nothing in queue lhld qpr xchg lhld qpw mov a,l cmp e jnz not_empty mov a,h cmp d jnz not_empty ; nothing else to send; declare idle state mvi a,1 sta idle_flag ; disable output interrupt (bit 0) mvi a,2 ; leave input (bit 1) enabled out DTP_CTRL_O ; UART_SETUP ret ; ; not empty; send out next byte not_empty: mvi a,0 sta idle_flag ; not idle; queue is not empty lhld qpr ; pointer for reading queue mov a,M ; get byte out DTP_TX_O ; send to serial port ; step queue inx h ; step the pointer ; wrap queue pointer if neccessary lxi d,GBL_DTP_OUTQ_WRAP mov a,l cmp e jnz nowrapr mov a,h cmp d jnz nowrapr lxi h,GBL_DTP_OUTQ ; wrap to start nowrapr: shld qpr ; store the pointer ret ; ; ; ; ; trap7: lxi b,7 jmp debug_trap trap6: lxi b,6 jmp debug_trap trap5: lxi b,5 jmp debug_trap trap4: lxi b,4 jmp debug_trap trap3: lxi b,3 jmp debug_trap trap2: lxi b,2 jmp debug_trap trap1: lxi b,1 jmp debug_trap trap05: lxi b,0a5h jmp debug_trap trap15: lxi b,15h jmp debug_trap trap25: lxi b,25h jmp debug_trap trap35: lxi b,35h jmp debug_trap trap45: lxi b,45h jmp debug_trap trap55: lxi b,55h jmp debug_trap trap65: lxi b,65h jmp debug_trap trap0: lxi b,0 jmp debug_trap ; =================== ; Initialization DEBUG_INIT: push psw push h ; stuff all the interrupt vectors except ; RST 3 (used by this DTP serial port) ; ; this will make jumps to 0000 do a Trap mvi a,0CDh ; "CALL" OPCODE sta RST_0 ; 0 lxi h,TRAP0 shld RST_0+1 ; wild RST 7 is also a trap sta RST_7 lxi h,TRAP7 shld RST_7+1 ; sta RST_0+4 ; 0.5 lxi h,TRAP05 shld RST_0+5 ; sta RST_1 ; 1 lxi h,TRAP1 shld RST_1+1 ; sta RST_1+4 ; 1.5 lxi h,TRAP15 shld RST_1+5 ; sta RST_2 ; 2 lxi h,TRAP2 shld RST_2+1 ; sta RST_2+4 ; 2.5 lxi h,TRAP25 shld RST_2+5 ; sta RST_3+4 ; 3.5 lxi h,TRAP35 shld RST_3+5 ; sta RST_4 ; 4 lxi h,TRAP4 shld RST_4+1 ; sta RST_4+4 lxi h,TRAP45 shld RST_4+5 ; sta RST_5 ; 5 lxi h,TRAP5 shld RST_5+1 ; sta RST_6 lxi h,TRAP6 shld RST_6+1 ; sta RST_55 lxi h,TRAP55 shld RST_55+1 ; sta RST_65 lxi h,TRAP65 shld RST_65+1 ; sta RST_75 lxi h,TRAP5 shld RST_75+1 ; ; set TRAP vector mvi a,JMP_OPCODE ; JMP opcode sta TRAP lxi h,DEBUG_TRAP ; address of Trap handler shld TRAP+1 ; set as JMP address mvi a,0 ; reset "trap happened" flag sta trap_flag ; ; Test for Diagnostic Test Pod (DTP) present mvi a,0 sta dtp_present ; assume no DTP mvi a,3 out DTP_CTRL_O in DTP_STS_I ani 60h cpi 60h jnz end_test mvi a,0 out DTP_CTRL_O in DTP_STS_I ani 60h cpi 0 jnz end_test ; DTP was there! mvi a,1 sta dtp_present end_test: ; ; Set up debug serial port UART ; This is a custom UART, implemented in an ACTEL ; Setup bits sent to port E5: ; 7 : 1=Reset the UART ; 3 : 1=Modem Signals enabled ; 2 : 1=set loop-back on ; 1 : 1=receive interrupt enable ; 0 : 1=transmit interrupt enable ; enable only the input interrupt ; (the output interrupt stays on when the transmitter is idle) mvi a,2 out DTP_CTRL_O ; ; clear any outstanding input status in DTP_SENSE_I in DTP_RX_I ; ; Setup and enable RST 3 mvi A,JMP_OPCODE sta RST_3 lxi h,DEBUG_ISR ; address of Interrupt handler shld RST_3+1 ; ; enable interrupt in IRQ_ENABLE_I ori 02h ; bit 1 enables DTP serial port RST3 interrupt ; (DTP xmt and rec have not been enabled, so no DTP interrupt yet) out IRQ_ENABLE_O ; Note: RST_3 is shared with "HKP Done", ; which is not used (and not enabled) ; ; setup output queue for serial port lxi h,GBL_DTP_OUTQ shld qpr shld qpw ; set the idle flag, so that PUT will fake an interrupt to start mvi a,1 sta idle_flag ; ; Initialize the input state-machine lxi h,s0 shld in_state ; ; pop h pop psw ret ; ; ; ; ; send_packet_prefix: push psw mvi a,0FEh call DEBUG_PUTBYTE mvi a,07Fh call DEBUG_PUTBYTE pop psw ret ; ; display message ; HL - points to null-terminated message string DEBUG_SHOW: push psw push h l1: mov a,M ; get byte cpi 0 ; null? jz done ; yes, end of string call DEBUG_PUTBYTE inx h ; next byte jmp l1 done: pop h pop psw ret ; ; ; ; ============================================= ; State-machine for debug input ... ; ============================================= start_over: lxi h,S0 shld in_state ret ; ; look for sync pattern FE 7F S0: call DEBUG_PUTBYTE ; echo cpi 0FEh rnz ; saw FE, now look for 7F lxi h,S1 shld in_state ret S1: call DEBUG_PUTBYTE ; echo cpi 07Fh jnz start_over ; saw 7F, now get the command code lxi h,S2 shld in_state ret ; ; Get command code; dispatch S2: call DEBUG_PUTBYTE ; echo ; pass code to debug function call DEBUG_FUNCTION jmp start_over ; hex: cpi 10 jm low adi 'A'-10 ret low: adi '0' ret ; ; make "U" packet to display number in HL as 4 Hex digits ; (with newline at end) HEXOUT: push psw call send_packet_prefix mvi a,SHOW_HEX ; function code for "U" program in PC call debug_putbyte mov a,h call debug_putbyte mov a,l call debug_putbyte pop psw ret ; ; make "U" packet to display number in HL as 4 Hex digits ; (with no newline) public DEBUG_SHOW_HEXN DEBUG_SHOW_HEXN: push psw call send_packet_prefix mvi a,SHOW_HEXN ; function code for "U" program in PC call debug_putbyte mov a,h call debug_putbyte mov a,l call debug_putbyte pop psw ret ; ; make "U" packet to display number in HL as signed decimal DECOUT: push psw call send_packet_prefix mvi a,SHOW_DECIMAL call debug_putbyte mov a,h call debug_putbyte mov a,l call debug_putbyte pop psw ret ; ; make "U" packet to display number in HL as signed decimal public DEBUG_SHOW_DECN DEBUG_SHOW_DECN push psw call send_packet_prefix mvi a,SHOW_DECN call debug_putbyte mov a,h call debug_putbyte mov a,l call debug_putbyte pop psw ret ; ; DEBUG_REGSET: push psw push b push psw call send_packet_prefix mvi a,SHOW_REGSET call debug_putbyte pop b mov a,b call debug_putbyte pop b mov a,c call debug_putbyte mov a,b call debug_putbyte mov a,c call debug_putbyte mov a,d call debug_putbyte mov a,e call debug_putbyte mov a,h call debug_putbyte mov a,l call debug_putbyte pop psw ret ; DEBUG_DUMP: ; dump bytes pointed to by HL ; C gives number of bytes push psw push b push h call send_packet_prefix mvi a,SHOW_DUMP call debug_putbyte mov a,c ; number of bytes to follow call debug_putbyte ddl: mov a,M call debug_putbyte inx h dcr c jnz ddl pop h pop b pop psw ret ; ; display spacecraft time as hh:mm:ss DEBUG_SHOWMET: ; HL - points to 6 bytes of MET push psw push b push h call send_packet_prefix mvi a,SHOW_MET call debug_putbyte mvi c,6 sml: mov a,M call debug_putbyte inx h dcr c jnz sml pop h pop b pop psw ret ; display ISUAL 10-byte time as hh:mm:ss.xxx DEBUG_SHOWUT: ; HL - points to 10 bytes of UT push psw push b push h call send_packet_prefix mvi a,SHOW_UT call debug_putbyte mvi c,10 sul: mov a,M call debug_putbyte inx h dcr c jnz sul pop h pop b pop psw ret ; ; Called from places the program shouldn't get to DEBUG_ASSERT: lxi h,ass call debug_show pop h ; get return address call hexout lxi h,asse call debug_show out WATCHDOG_PET_O ; let messages show ; Commit cyber-cuicide oogh: out software_reset_o ; ****jmp oogh ; provoke Watchdog ass: asc "ASSERT=" db 0 asse: db 10,0 END_DPU ds 1 lxi h,end_dpu