; program writes SOS msg into flash then turns LED green ; when serial interrupt received, turns off interrupts, turns off ; power, transmits contents of SSPCON1 by flashing LED red, repeats ; (next version will transmit SOS code first, then contents of ; SSPCON1) ; to start, need to write into flash, starting at 30 0000h: ; 10 10 10 00 | 1110 1110 | 1110 00 10 | 10 10 include common.inc include morse-auto.inc include ../iwjpictest/insn-aliases.inc include ../iwjpictest/clockvaries.inc extern led_green extern led_red extern led_black ;--------------------------------------------------------------------------- panic macro message movlw (message - morse_messages_start)/4 movwf PANIC_ADDRESS goto panic_routine endm ;--------------------------------------------------------------------------- ; reserved access bank locations WREG2 equ 00h ; a 2nd working reg :-) WREG3 equ 01h ; a 3rd working reg :-) WREG4 equ 02h ; a 4th working reg :-) BLANK equ 03h ; register full of zeros TESTFLASH equ 04h ; test LED flash pattern ; used in panic macro for temporary storage PANIC_MORSE equ 05h ; stores # bytes of morse msg in panic readout PANIC_REGS equ 06h ; stores # registers in panic readout PANIC_ADDRESS equ 07h ; stores condensed form of message start addr. ; constants MORSE_MSG_LENGTH equ 04h ; lenght of morse messages in bytes ;--------------------------------------------------------------------------- ; memory location definitions ERROR_BUF_PAGE equ 3 ; error codes on flash p3 F_ERROR_U equ 00h ; upper part of error memory locations F_SOS_H equ 40h ; high (middle) part of SOS error memory loc. F_SOS_L equ 00h ; lower part of SOS error memory loc. ;--------------------------------------------------------------------------- ; error messages err_SOS equ 0 ; msg 0 = SOS ;**************************************************************************** ; VECTORS: special locations, where the PIC starts executing ; after interrupts org 0 goto vector_reset ; high priority interrupt ; ; org 000008h ; goto interrupt_high ; low priority interrupt org 000018h goto interrupt_low ;**************************************************************************** ;ERROR MSGS ; org 4000h ; dw 1110111010101000b ; dw 1010000011100010b ;--------------------------------------------------------------------------- ; Main - go to interrupt goto interrupt_low ;**************************************************************************** code ;**************************************************************************** vector_reset ; serial set-up ; enable interrupts so that this can be used as a trigger for the ; panic routine ; initial config - TXSTA register p181 bcf TXSTA,6,0 ; p181, set 8-bit mode bsf TXSTA,5,0 ; transmit enable bcf TXSTA,4,0 ; asynchronous mode bsc_txsta_brgh ; set high or low baud rate ; initial config - RCSTA register p182 bsf RCSTA,7,0 ; serial port enable (p182) bcf RCSTA,6,0 ; 8-bit reception bsf RCSTA,4,0 ; enable continuous receive ; set SPBRG to get correct baud rate movlw_movwf_spbrg ; interrupt set-up for serial receive bcf IPR1,5,0 ; set to low-priority interrupt ;--------------------------------------------------------------------------- ; interrupt set-up ; globally enable interrupts - p77 bsf RCON,7,0 ; enable priority levels bsf INTCON,7,0 ; enable high-priority interrupts bsf INTCON,6,0 ; enable low-priority interrupts bsf PIE1,5,0 ; enable USART receive interrupt (p85) ;--------------------------------------------------------------------------- ;--------------------------------------------------------------------------- ; Main - go to interrupt goto interrupt_low ;**************************************************************************** ; INTERRUPT SUBROUTINES interrupt_low mov_lw 0x5a mov_wf TESTFLASH panic morse_TG panic_routine ; switch off interrupts and power ; reconfigure timer0 for writing diagnostic msg to the LED clrf INTCON,0 ; disable all interrupts EVER bcf PORTC,1,0 ; switch off booster ; re-initialise timer0 config bcf T0CON,6,0 ; p107 Timer0 -> 16bit mode bcf T0CON,5,0 ; timer0 use internal clock bsc_morse_t0con_012 ; use prescaler? and configure it ; get # bytes of morse msg, # registers in panic readout, message start addr. ; back from condensed message start addr. stored in PANIC_ADDRESS panic_loop movlw 4 mulwf PANIC_ADDRESS movff PRODL,TBLPTRL movff PRODH,WREG add_lw (morse_messages_start)/256 movwf TBLPTRH clr_f TBLPTRU tblrd *+ ; read 1st byte of error message ; (gives # bytes morse, # bytes registers) movff TABLAT,PANIC_MORSE movlw 00001111b and_wff PANIC_MORSE ; PANIC_MORSE now contains # bytes of morse msgs movff TABLAT,PANIC_REGS movlw 01110000b and_wff PANIC_REGS swap_f PANIC_REGS ; PANIC_REGS now contains # registers to read call led_black call waiting call waiting call waiting call waiting call morsemsg ; transmit SOS in red call led_black call waiting call waiting call waiting call waiting call registermsg ; transmit contents of TESTFLASH in ; red(=low) and blue(=high) goto panic_loop ;**************************************************************************** ; PANIC SUBROUTINES morsemsg ; wrapper round readout to flash the per-pic led red for a ; (currently 4-byte) morse msg morse_msg_start clrf WREG3,0 ; clear loop counter (WREG3) morse_loop mov_fw PANIC_MORSE cmp_fw_ifge WREG3 ; if loop counter >=MORSE_MSG_LENGTH, return ; return to panic tblrd *+ mov_ff TABLAT,WREG2 call morse_readout inc_f WREG3 goto morse_loop ;-------------------------- morse_readout ; Flashes the per-pic led red(0) in a specified pattern. ; ; The pattern is specified as the state for 8 identically-long time ; periods each as long as a morse `dot', encoded into a byte with ; most significant bit first. ; On entry On exit ; W any undefined ; WREG2 flash pattern preserved ; WREG4 any undefined clr_f WREG4 ; clear loop counter (WREG4) rr_f WREG2 morse_readout_loop mov_lw 8 cmp_fw_ifge WREG4 ; if loop counter >=8, return return rl_f WREG2 ; top bit goes into N, ie Negative if 1 bra_n morse_readout_if_led_1 morse_readout_if_led_0 call led_black bra morse_readout_endif_led morse_readout_if_led_1 call led_red morse_readout_endif_led inc_f WREG4 ; increment loop counter call waiting bra morse_readout_loop ;-------------------------- ;-------------------------- registermsg register_msg_start clrf WREG3,0 ; clear loop counter (WREG3) register_loop mov_fw PANIC_REGS cmp_fw_ifge WREG3 ; if loop counter >=MORSE_MSG_LENGTH, return ; return to panic tblrd *+ mov_fw TABLAT ; TABLAT has the 8-bit version mov_wf FSR0L ; of the address. So, 8 bits ; go straight into FSR0L. mov_lw 0x0f ; For FSR0H, we see if the mov_fw FSR0H ; address XX is >=0x60. ; If it is then we meant 0xfXX; mov_lw 0x5f ; if not then we meant 0x0XX. cmp_fw_ifle FSR0L ; (This is just like PIC does clr_f FSR0H ; for insns using Access Bank) mov_ff INDF0,WREG2 call register_readout inc_f WREG3 call waiting call waiting goto register_loop ;-------------------------- register_readout ; Flashes the per-pic led red(0) and green(1) in a specified pattern. ; (black gap between each bit) ; ; The pattern is specified as the state for 8 identically-long time ; periods each as long as a morse `dot', encoded into a byte with ; most significant bit first. ; On entry On exit ; W any undefined ; WREG2 flash pattern preserved ; WREG4 any undefined clrf WREG4,0 ; clear loop counter (WREG4) rrncf WREG2,1 register_readout_loop movlw 8 cpfslt WREG4,0 ; if loop counter >=8 (register ; length), return return movlw 4 cmp_fw_ifne WREG4 ; if loop counter !=4 (nybble length), ; skip insertion of extra black space goto not_nybble_boundary call waiting not_nybble_boundary rlncf WREG2,1 ; top bit goes into N flag, ; ie Negative if 1 bn register_readout_if_led_1 register_readout_if_led_0 call led_red bra register_readout_endif_led register_readout_if_led_1 call led_green register_readout_endif_led incf WREG4,1,0 ; increment loop counter call waiting call led_black call waiting bra register_readout_loop ;**************************************************************************** ; GENERAL SUBROUTINES ;---------------------------------------- waiting ; waits for a fixed interval, depending on the configuration of TMR0 bcf INTCON,2,0 ; clear timer0 interrupt bit (p109) clrf TMR0H,0 ; p107 set high byte of timer0 to 0 (buffered, ; only actually set when write to tmr0l occurs) clrf TMR0L,0 ; set timer0 low byte - timer now set to 0000h loop btfss INTCON,2,0 ; check whether timer0 interrupt has been set - ; skip next instruction if so bra loop return ;**************************************************************************** org 0x2000 dw 0xffff org 0x6000 dw 0xffff end