-PROGRAMS= detect
+PROGRAMS= test-sofar
INCLUDES= common.inc final.inc morse-auto.inc \
../iwjpictest/insn-aliases.inc
-LIBS= panic.o routines-led.o variables.o
+LIBS= vectors.o panic.o routines-led.o variables.o \
+ i2clib.o
PICNOS= 0 1 2
CEBPIC= ../cebpic/
TARGETS= $(foreach i, $(PICNOS), perpic$i.hex)
include /usr/share/gputils/header/p18f458.inc
radix dec
+ include panic.inc
+ include ../iwjpictest/insn-aliases.inc
;****************************************************************************
; MACROS
-;----------------------------------------
-; ifbit1(REGISTER,BITNUMBER)
-; executes the next instruction but only if bit BITNUMBER
-; in REGISTER (which must be in the access bank) is set
-ifbit1 macro REGISTER, BITNUMBER
- btfsc REGISTER, BITNUMBER, 0
- endm
+; debug* and ifbit[01] were here but they're cruft, really,
+; so I have removed them -iwj
-;----------------------------------------
-; ifbit0(REGISTER,BITNUMBER)
-; executes the next instruction but only if bit BITNUMBER
-; in REGISTER (which must be in the access bank) is clear
-ifbit0 macro REGISTER, BITNUMBER
- btfss REGISTER, BITNUMBER, 0
- endm
-
-;----------------------------------------
-; debug(BYTE)
-; writes BYTE through the serial port
-; serial port hardware must be suitably initialised
-; serial port transmit interrupts must be disabled
-; will spin until the byte is transmitted
-; Before After
-; W any undefined
-; S any undefined
-
-; macro to call subroutine to transmit over serial port for debugging
-; takes 8-bit value, puts in W, invokes debug_serial_transmit
- ifndef SLOW_VERSION
-debug macro debugvalue
- endm
- endif
-
- ifdef SLOW_VERSION
-debug macro debugvalue
- movlw debugvalue
- call polling_serial_transmit
- endm
- endif
-
-;----------------------------------------
-; debughf(REGISTER)
-; reads REGISTER once and writes it to the serial port in hex
-; for conditions etc. see "debug", above
-; Before After
-; W any undefined
-; S any undefined
- ifdef SLOW_VERSION
-DEBUGHF_VALUE equ 0x040 ; getting on towards end of access bank
- ; FIXME if all of program used udata that
- ; would be very nice
-
-debughf macro register
- movff register, DEBUGHF_VALUE
- call debughf_subroutine
- endm
-
-debughf_subroutine
- call debughf_digit
- call debughf_digit
- return
-
-;--------------------
-debughf_digit
-; transmits top nybble of DEBUGHF_VALUE in hex
-; through serial port, as above, and swaps nybbles
-; Before After
-; W any undefined
-; DEBUGHF_VALUE BBBBaaaa aaaaBBBB (BBBB was sent)
-
- swapf DEBUGHF_VALUE,1,0
- movf DEBUGHF_VALUE,0,0
- andlw 0x0f
- sublw 10
- sublw 0
- bn debughf_digit_ifnot_ge10
- addlw 'a'-('0'+10)
-debughf_digit_ifnot_ge10
- addlw '0'+10
- goto polling_serial_transmit
-
- else
-debughf macro register
- endm
- endif
-
-
-
;****************************************************************************
-
extern informative_panic
-;****************************************************************************
-; VECTORS: special locations, where the PIC starts executing
-; after reset and interrupts
-
- org 0
- goto vector_reset
-
- org 000008h
-; goto vector_interrupt_high
-
- org 000018h
-; goto vector_interrupt_low
-
;****************************************************************************
code
-; from routines-led.asm
- extern led_green
- extern led_red
- extern led_black
+; from test-sofar.asm
+; stuff for testing only
+ extern ch
-; from panic.asm
- extern informative_panic
+ include vectors.fin
+ include i2clib.inc
+ include panic.fin
+ include routines-led.fin
end
TI3 ; for iwj
TI4 ; for iwj
TI5 ; for iwj
+X ch ; bad character received from host
# Messages for i2clib, S*
SM i2c_st,i2c_sspstat,i2c_sspcon1,i2c_sspcon2 ; m.,i., ctrlr bad state
SS i2c_st,i2c_sspstat,i2c_sspcon1 ; slave, intr, controller bad state
-SK slave ; m. couldn't address slave (no ack)
-SN slave ; improper slave number
+SK i2c_slave ; m. couldn't address slave (no ack)
+SN i2c_slave ; improper slave number
SW i2c_st ; improper i2cm_write_start
SF i2c_st ; improper i2cmu_write_next_byte Z
SR i2c_st ; improper i2cm_read_start
-; 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
+;======================================================================
+; panic.asm
+;
+; This file implements panic_routine, which is called by the
+; `panic' macro in panic.inc. See panic.inc for the functionality
+; of `panic'.
include common.inc
- include morse-auto.inc
- include ../iwjpictest/insn-aliases.inc
-
- extern led_green
- extern led_red
- extern led_black
;---------------------------------------------------------------------------
; reserved access bank locations
+ udata_acs
+
flash_pattern res 1
morse_counter res 1
register_counter res 1
bit_counter res 1
-BLANK res 1 ; register full of zeros
-TESTFLASH res 1 ; test LED flash pattern
; used in panic macro for temporary storage
-PANIC_ADDRESS res 1 ; stores condensed form of message start addr.
-PANIC_MORSE res 1 ; stores # bytes of morse msg in panic readout
-PANIC_REGS res 1 ; stores # registers in panic readout
-
-
-;---------------------------------------------------------------------------
-; 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.
+panic_address res 1 ; stores condensed form of message start addr.
+panic_morse res 1 ; stores # bytes of morse msg in panic readout
+panic_regs res 1 ; stores # registers in panic readout
;****************************************************************************
bs_f T0CON,0 ; }
; get # bytes of morse msg, # registers in panic readout, message start addr.
-; back from condensed message start addr. stored in PANIC_ADDRESS
+; back from condensed message start addr. stored in panic_address
panic_loop
mov_lw 4
- mul_wf PANIC_ADDRESS
+ mul_wf panic_address
mov_ff PRODL,TBLPTRL
mov_ff PRODH,WREG
add_lw (morse_messages_start)/256
tblrd *+ ; read 1st byte of error message
; (gives # bytes morse, # bytes registers)
- mov_ff TABLAT,PANIC_MORSE
+ mov_ff TABLAT,panic_morse
mov_lw 00001111b
- and_wff PANIC_MORSE ; PANIC_MORSE now contains # bytes of morse msgs
+ and_wff panic_morse ; panic_morse now contains # bytes of morse msgs
- mov_ff TABLAT,PANIC_REGS
+ mov_ff TABLAT,panic_regs
mov_lw 01110000b
- and_wff PANIC_REGS
- swap_f PANIC_REGS ; PANIC_REGS now contains # registers to read
+ 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 registermsg ; transmit contents of TESTFLASH in
+ call registermsg ; transmit contents of registers in
; red(=low) and blue(=high)
goto panic_loop
clr_f morse_counter ; clear loop counter
morse_loop
- mov_fw PANIC_MORSE
- cmp_fw_ifge morse_counter ; if loop counter >=PANIC_MORSE
+ mov_fw panic_morse
+ cmp_fw_ifge morse_counter ; if loop counter >=panic_morse
return ; return to panic
tblrd *+
rr_f flash_pattern
morse_readout_loop
- mov_fw PANIC_REGS
- cmp_fw_ifge bit_counter ; if loop counter >=PANIC_REGS, return
+ mov_fw panic_regs
+ cmp_fw_ifge bit_counter ; if loop counter >=panic_regs, return
return
rl_f flash_pattern ; top bit goes into N,
clr_f register_counter ; clear loop counter
register_loop
- mov_fw PANIC_REGS
- cmp_fw_ifge register_counter ; if loop counter >=PANIC_REGS
+ mov_fw panic_regs
+ cmp_fw_ifge register_counter ; if loop counter >=panic_regs
return ; return to panic
tblrd *+
; flash_pattern flash pattern preserved
; bit_counter any undefined
- clr_f bit ; clear loop counter
+ clr_f bit_counter ; clear loop counter
rr_f flash_pattern
call led_green
register_readout_endif_led
- inc_f bit_counter,1 ; increment loop counter
+ inc_f bit_counter ; increment loop counter
call waiting
call led_black
call waiting
--- /dev/null
+ extern led_green
+ extern led_red
+ extern led_black
--- /dev/null
+;======================================================================
+;
+; test-sofar test harness which tests functionality written `so far'
+; (as new functionality is available this will be extended)
+;
+;----------------------------------------------------------------------
+;
+; Current behaviour:
+;
+; Starts up, reads PIC number from flash
+; Flashes Red N times for PIC N
+; Sets LED to black on slave, blue on master
+; prints | on master
+;
+; Then, on master PIC
+; initialises i2c controller with i2clib
+; sets buffer to empty, first byte is 0xff
+; and then:
+; on serial interrupt
+; call some i2cm_... function
+; on i2c interrupt
+; write out some character
+; in main loop
+; flashes blue flash every once in a while
+;
+; Input characters:
+; 1-9 if first byte of buffer is not negative:
+; i2cm_write_start; i2cmu_write_next_byte will be handled
+; automatically: if next byte in buffer is negative we
+; set Z on return.
+; afterwards, buffer pointer is reset to start
+; but buffer contents is not changed
+; if first byte of buffer _is_ negative:
+; i2cm_read_start (buffer empty)
+;
+; < 0x20 panic, showing character code
+;
+; , i2cm_read_another
+; . i2cm_read_done
+;
+; SPC set buffer pointer to start, set that byte to 0xff
+; 0 set buffer pointer to start, clear that byte
+; other append char to buffer, clear byte at buffer pointer
+;
+; Output characters:
+; SPC i2cmu_done
+; other i2cmu_read_got_byte
+;
+; On slave PIC:
+; we maintain a circular buffer with a separate
+; read and write pointer, initially initialised to
+; 01234567 (ascii)
+; ^
+; i2csu_write_begin sets led to red, writes byte to buffer
+; i2csu_write_another writes byte to buffer
+; i2csu_write_done writes '$' to current buffer loc, sets led to black
+; i2csu_read_begin sets led to green, reads byte from buffer
+; i2csu_read_another reads byte from buffer
+; i2csu_read_done sets led to black
+; special byte values that when written aren't just
+; writen to the buffer:
+; < reset read and write pointers
+; ! do that and also erase buffer
+; set led to red when writing, blue when reading
+;
+;======================================================================
+
+ include common.inc
+
+ udata_acs
+
+t res 1
+ch res 1
+picno res 1
+
+delay_countfast res 1
+delay_countmedium res 1
+delay_countslow res 1
+delay_slowexp equ 2 ; 2^2 * 40ms = 160ms
+
+ code
+
+;----------
+vector_reset
+ clr_f INTCON
+ bs_f RCON, IPEN ; interrupt priorities
+
+ ; read pic no from ID locations
+ mov_lw 0x20
+ mov_wf TBLPTRU
+ clr_f TBLPTRH
+ clr_f TBLPTRL
+
+ tblrd *
+ mov_fw TABLAT
+ mov_wf picno
+ bra_z master
+ goto slave
+
+;----------
+vector_interrupt_low
+ tst_f_ifnz picno
+ bra s_vector_interrupt
+ ; Master:
+ call i2cm_interrupt
+ call serial_interrupt
+ retfie_r
+
+s_vector_interrupt
+ call i2cs_interrupt
+ retfie_r
+
+;----------
+vector_interrupt_high
+ panic morse_IP
+
+;----------------------------------------------------------------------
+; MASTER
+;
+; buffer is 0x200 onwards
+; FSR0 is buffer pointer
+; FSR1 permanently points to start of buffer
+
+master
+ call serial_setup
+ call i2cm_init
+ call led_green
+
+ rcall m_buffer_reset
+ set_f INDF0
+
+ mov_lw '|'
+ rcall serial_write_char
+ mov_lw (1<<GIEH) | (1<<GIEL)
+ mov_wf INTCON
+
+m_infinite
+ call delay
+ call led_black
+ call delay
+ call delay
+ call delay
+ call delay
+ call delay
+ call delay
+ call delay
+ call led_green
+ bra m_infinite
+
+;----------
+serialu_read_char
+; W character read any
+ mov_wf ch
+
+ mov_lw ~0x1f
+ and_wfw ch
+ bra_z m_ch_bad
+
+ mov_lw ','
+ xor_wfw ch
+ bra_z m_ch_comma
+
+ mov_lw '.'
+ xor_wfw ch
+ bra_z m_ch_stop
+
+ mov_lw ' '
+ xor_wfw ch
+ bra_z m_ch_spc
+
+ mov_fw ch
+ add_lw -('9'+1)
+ bra_nn m_ch_notdigit
+ add_lw ('9'+1) - '0'
+ bra_z m_ch_0
+ bra_nn m_ch_digit
+
+m_ch_notdigit
+ mov_lfsr 0x0200, 0
+ mov_lfsr 0x0200, 1
+ mov_wf FSR0H ; prevent crashes due to wrapping
+ return
+
+;----------
+m_ch_bad
+ panic morse_X
+
+;----------
+m_ch_comma
+ goto i2cm_read_another
+
+;----------
+m_ch_stop
+ goto i2cm_read_done
+
+;----------
+m_ch_digit
+; W now contains intended slave number
+ bt_f_if1 INDF1,7 ; first byte negative ?
+ bra i2cm_read_start
+ ; writing, eh ?
+
+ mov_lfsr 0x200, 2
+ bra i2cm_write_start ; positive
+
+;----------
+m_ch_spc
+ rcall m_buffer_reset
+ set_f INDF0
+ return
+
+;----------
+m_ch_0
+ rcall m_buffer_reset
+ clr_f INDF0
+ return
+
+;----------
+m_buffer_reset
+ mov_lw 0x02
+ mov_wf FSR0H
+ clr_f FSR0L
+ return
+
+;----------------------------------------
+i2cmu_done
+ mov_lw ' '
+i2cmu_read_got_byte
+ bra serial_write_char
+
+;----------
+i2cmu_write_next_byte
+ mov_fw POSTINC2
+ return
+
+;----------------------------------------------------------------------
+; SLAVE
+; buffer is at 0x300..0x307
+; FSR0 is write pointer
+; FSR1 is read pointer
+s_bufbit equ 3 ; ln2(buffer size)
+
+slave
+ mov_fw picno
+ mov_wf t
+
+s_shownum_loop
+ call delay
+ call led_red
+ call delay
+ call led_black
+
+ dec_f_ifnz t
+ bra s_shownum_loop
+ ; OK:
+
+ rcall s_buffer_erase
+
+ mov_fw picno
+ call i2cs_init
+ mov_lw (1<<GIEH) | (1<<GIEL)
+ mov_wf INTCON
+
+s_infinite
+ bra s_infinite
+
+;----------
+i2csu_write_begin
+ rcall led_red
+i2csu_write_another
+ mov_wf t
+
+ mov_fw t
+ xor_lw '<'
+ bra_z s_buffer_reset
+
+ mov_fw t
+ xor_lw '!'
+ bra_z s_buffer_erase
+
+ mov_fw t
+ mov_wf POSTINC0
+ bc_f FSR0L, s_bufbit
+ return
+
+;----------
+i2csu_write_done
+ mov_lw '$'
+ mov_wf INDF0
+i2csu_read_done
+ bra led_black
+
+;----------
+i2csu_read_begin
+ rcall led_green
+i2csu_read_another
+ mov_fw POSTINC1
+ bc_f FSR1L, s_bufbit
+ return
+
+;----------
+s_buffer_erase
+ mov_lfsr 0x300, 0
+ mov_lw '0'
+
+;----------
+s_buffer_erase_loop
+ mov_wf POSTINC0
+ inc_w
+ bt_w_if0 s_bufbit
+ bra s_buffer_erase_loop
+
+;----------
+s_buffer_reset
+ mov_lfsr 0x300, 0
+ mov_lfsr 0x300, 1
+ return
+
+;======================================================================
+; delay routine, nicked from flasher.asm
+
+delay
+ ; set a bit which says how fast the led
+ ; should flash and count down from 2^(that bit)
+ bsf delay_countslow, delay_slowexp, 0
+delayslow_loop
+
+delaymedium_loop
+
+delayfast_loop
+ decfsz delay_countfast, 1, 0 ; 1 cycle
+ goto delayfast_loop ; 2 cycles (skipped or not)
+; exited delayfast_loop ; total: 3 * 256 = 768 cycles
+
+
+ decfsz delay_countmedium, 1, 0 ; 1 cycle
+ goto delaymedium_loop ; 2 cycles (skipped or not)
+; exited delaymedium_loop ; total: ~198000 cycles
+
+ ; each cycle 0.2us
+ ; so each medium loop is ~40ms
+
+ decfsz delay_countslow, 1, 0
+ goto delayslow_loop
+; exited delayslow_loop
+
+ return
+
+
+;======================================================================
+; SERIAL LIBRARY
+; cribbed from iwjpictest/harness.asm and now mangled
+; so that it is interrupt-driven for receiving but
+; polling for transmission
+
+;----------------------------------------
+serial_setup
+; W undefined undefined
+ mov_lw (1<<TXEN) | (1<<BRGH) | (1<<TRMT)
+ mov_wf TXSTA ; asynch xmit enabled, high baud rate, 8-bit,
+ mov_lw 129
+ mov_wf SPBRG ; 9600bps (with BRGH)
+serial_receive_reset ;from serial_read_if_error
+ mov_lw (1<<SPEN) | (1<<CREN)
+ mov_wf RCSTA ; enable serial port, continuous rx, 8-bit
+ bc_f IPR1, RCIP ; low priority
+ bs_f PIE1, RCIE ; interrupt enable
+ return
+
+;----------------------------------------
+serial_interrupt
+; on errors, sets LED red and transmits *
+ bt_f_if0 PIR1, RCIF
+ return
+
+ mov_fw RCSTA
+ and_lw (1<<CREN) | (1<<FERR) | (1<<OERR)
+ xor_lw (1<<CREN)
+ bra_nz serial_read_if_error
+ mov_fw RCREG
+ goto serialu_read_char
+
+serial_read_if_error
+ mov_lw '*'
+ rcall serial_write_char
+ rcall serial_receive_reset
+ return
+
+;----------------------------------------
+serial_write_char
+; W character undefined
+serial_write_char_loop
+ bt_f_if0 PIR1, TXIF
+ bra serial_write_char_loop
+ mov_wf TXREG
+ return
+
+ include final.inc
+
+ end
--- /dev/null
+;======================================================================
+; VECTORS: special locations, where the PIC starts executing
+; after reset and interrupts
+
+ org 0
+ goto vector_reset
+
+ org 000008h
+ goto vector_interrupt_high
+
+ org 000018h
+ goto vector_interrupt_low
+
+ include vectors.fin
+ end
--- /dev/null
+ extern vector_reset
+ extern vector_interrupt_low
+ extern vector_interrupt_high