;----------------------------------------------------------------------
; Common conventions for function register notation:
-; NOTE THAT THIS IS WRONG FIXME FIXME
-AND CHECK IT FIXME
+
; Master Slave
+; Registers etc.
; W Trashed Trashed
; STATUS Trashed Trashed
; BSR Not used Not used
-; TBLPTR*,TABLAT Reserved for ISR/init Not used except init
-; FSR0 Reserved for ISR/init Reserved for ISR/init
-; FSR1, FSR2 Trashed Reserved for I2C/init
+; t Low ISR Low ISR
+; TBLPTR*,TABLAT Low ISR Low ISR
+; FSR0 Low ISR Low ISR
+; FSR1 Low ISR High ISR (detect)
+; FSR2 Low ISR High ISR (detect)
+;
+; Trashed May be trashed by any routine anywhere. Saved
+; during every ISR entry/exit.
+;
+; Low ISR May be used/traashed by any routine run in low-priority
+; interrupt, or any routine run during initialisation.
+; May therefore not be used in background loop with
+; interrupts enabled. May not be used by high-priority
+; ISR (unless explicitly saved).
+;
+; High ISR May be used/trashed by any routine run in high-priority
+; interrupt, or any routine run during initialisation.
+; May therefore not be used elsewhere with interrupts
+; enabled.
+;
+; Only the routines specially noted as intended to
+; be called from the High ISR are safe.
+;
+; ... (subsystem)
+; Register is reserved for use by this subsystem, which
+; is allowed to expect the value to be preserved.
+; Anything else which uses it must save and restore (and
+; may also need to disable interrupts, depending on its
+; relative status).
+;
+; Not High May be used by any routine not running in high-priority
+; interrupt. Not saved by high-priority interrupt
+; entry/exit, so any high-priority interrupt routine which
+; uses this register must save and restore it.
+;
+; A routine which is allowed to trash a register may document that it
+; saves that register for the benefit of its callers.
+;
+; General-purpose hardware allocation:
+;
+; Master Slave
+; Timer 0 nmra Disabled
+; Timer 2 - -
+; Timer 1 1ms tick, int. low 1ms tick, int. low
+; CCP1 1ms tick, int. low 1ms tick, int. low
+; Timer 3 - -
+; ECCP - -
;----------------------------------------------------------------------
; MACROS
include common.inc
+; I2C protocol is as follows:
+;
+; Master periodically polls each slave, addressing it for reading.
+; The slave replies with the first byte of a self-delimiting message.
+; The master must then read the whole message before doing anything
+; else on the bus.
+;
+; First byte is like this:
+; MM 05 B2 B1 10 13 16 08 (detectors)
+; MM zz 01 02 03 00 04 05 (reversers)
+; where
+; B1 and B2 indicates that the is more detection data;
+; each bit corresponding to a subsequent byte:
+; if the bit is set the byte is present; otherwise
+; it is skipped and the contents can be presumed
+; to be the same as last time (initially: 0)
+; zz is a zero bit
+; MM indicates that there are extra message byte(s)
+;
+; Following that are the zero, one or two more bytes of
+; detection data,
+; X and Y indicate that further detection bytes exist
+; M indicates that more
+
;======================================================================
; variables and memory organisation
unattended res 1 ; counts down once for each det loop
; and if it reaches 0, led is set to red
-scana res 1 ; see bit-twiddling below
-scanb res 1
-scanc res 1
-scand res 1
-scane res 1
+scana res 1 ; see bit-twiddling below
+scanb res 1
+scanc res 1
+scand res 1
+scane res 1
-last1 res 1
-last2 res 1
+last1 res 1
+last2 res 1
buf0_startval res 1 ; reversers start with some det bits
buf0 res 1
message_buffer_end
;----------------------------------------------------------------------
-; buf0, message_buffer, and FSR1 look like this:
+; buf0, message_buffer, and FSR1 are used mainly for recording
+; non-detection messages. They look like this:
;
; +--------+--------+--------+--------+--------+
; | buf0 | message_buffer... |
; ^
; |1d0d0000|1aaaaaaa 0bbbbbbb ???????? ????????| two extra bytes
;
-; etc. (bits labelled `d' are detection data on reversers boards
+; etc. Bits labelled `d' are detection data on reversers boards
; 0 on detectors boards; `a' and `b' are extra message data;
-; `^' indicates the byte pointed to by FSR1)
+; `^' indicates the byte pointed to by FSR1
+;
+;----------------------------------------------------------------------
+;
+; outbuf and FSR2 are used (on slaves) for the message we are
+; transmitting. FSR2 points to the next byte to transmit (ie, which
+; will be read). outmsg_end points to the first byte after the
+; message, and is used for read overrun detection.
+;
+; During i2csu_read_start (High ISR), the actual first byte of the
+; message to be sent is calculated from buf0, and transmitted; the
+; extra detection bytes (if any) are stored in outbuf, and any extra
+; messages (from message_buffer) are also appended to outbuf.
;
-
;======================================================================
code
;----------
-det_common_setup
+det_common_init
mov_lw 0b111 ; turn off comparator, or we can't use pins
mov_wf CMCON ; RD0-RD4 as digital inputs
mov_lw 0b0110 ; turn off A/D except perhaps for pin
return
;----------
-det_slave_setup
- bsr det_common_setup
+det_slave_init
+ bsr det_common_init
set_f scana
set_f scanb
set_f scanc
mov_wf buf0_startval
+ mov_lfsr outbuf, 2
+ clr_f outmsg_end
+
goto reset_message_buffer
;----------
;----------
i2csu_read_begin
+; called from High ISR, see i2clib.inc
bt_f_if1 idloc1,idloc1_boarddet
bra det_slave_read_start_detectors
bra det_slave_read_start_reversers
;----------
i2csu_read_another
+; called from High ISR, see i2clib.inc
mov_fw POSTINC2
call i2cs_read_data
- bt_f_if0 FSR2L, outbuf_szln2
+ mov_fw outmsg_end
+ cmp_fw_ifle FSR2L
return
; oops
panic morse_DR
;----------
-det_scanloop_again macro det_scanloop_whatever
+backgroundloop_again macro backgroundloop_whatever
dec_f_ifnz unattended
- bra det_scanloop_whatever
+ bra backgroundloop_whatever
call led_red
- bra det_scanloop_whatever
+ bra backgroundloop_whatever
endm
;======================================================================
; buf0 MM zz B2 B1 zz zz zz zz
+ ; scheme for bit shuffling:
+ ;
; 1: ; _<A 19 09 12 15 18 xx xx xx
- ; >>B xx xx xx xx xx 04 20 17
-
+ ; ; >>B xx xx xx xx xx 04 20 17
+ ;
; 2: ; _>E 06 xx xx xx xx xx 03 00
- ; [*D xx 01 07 02 11 14 xx ?? C=08
-
+ ; ; [*D xx 01 07 02 11 14 xx ?? C=08
+ ;
; 0: ; [_C xx 05 xx xx 10 13 16 08
+ ;
+; ; where _ means do nothing
+ ; * swap nybbles
+ ; < rotate left
+ ; > rotate right
+ ; [ rotate left through carry (NB
+ ; that the carry bit propagates to
+ ; the subsequent [ or ] *in the
+ ; same column*).
+ ; and the operation done first (in backgroundloop)
+ ; is on the right next to the port letter and the one
+ ; done second (in i2csu_read_begin_...) is shown
+ ; on the left, above.
-det_scanloop_detectors
+;----------
+backgroundloop_detectors
rr_fw PORTB ; W xx xx xx xx 04 20 17 xx (now)
and_wff scanb ; b xx xx xx xx 04 20 17 xx (cumulative)
rl_fw PORTA ; W 19 09 12 15 18 xx xx xx (now)
mov_fw PORTC ; W xx xx 05 xx xx 10 13 16 (now)
and_wff scanc ; c xx xx 05 xx xx 10 13 16 (cumulative)
- det_scanloop_again det_scanloop_detectors
+ backgroundloop_again backgroundloop_detectors
;---------- ; buf0 MM zz zz zz zz zz zz zz
-det_slave_read_start_detectors
+i2csu_read_begin_detectors
; detection byte 1
mov_lw 0xf8 ; W yy yy yy yy yy zz zz zz
and_wff scana ; scana 19 09 12 15 18 zz zz zz
call i2cs_read_data
- mov_lfsr outbuf, 2
+ rcall new_i2c_outmsg
mov_fw scana
bt_f_if1 buf0,5
;----------------------------------------------------------------------
; both detectors and reversers
;
-both_startread_tail
+i2csu_read_start_either_tail
set_f scana
set_f scand
mov_wf POSTINC2
bra_n msg_copy_loop
+ mov_ff FSR2L, outmsg_lastbyte
+
reset_message_buffer
; FSR1/buf0/message_buffer any set to empty
+; may be called from High ISR or during init
mov_lfsr message_buffer, 1
mov_ff buf0_startval, buf0
clr_f INDF1
return
+;----------
+new_i2c_outmsg
+; Called from i2csu_read_start ISR to check that the whole of
+; the previous message was read, and to reset the FSR2 pointer
+; to point to the start of outbuf so that we can fill the outbuf.
+ mov_fw FSR2L ; W -> byte after the one we last sent
+ mov_lfsr outbuf, 2 ; FSR2 -> outbuf
+ cmp_fw_ifle outmsg_end ; transmitted the last byte ?
+ return
+ ; no, oops:
+ panic morse_DQ
+
;----------------------------------------------------------------------
; reversers
; A xx 01 xx 03 xx xx xx xx
; B xx xx xx xx xx xx xx xx
; C xx xx xx xx xx 00 xx xx
; D xx xx xx xx xx xx 04 05
- ; E xx xx xx xx xx 02 xx xx
-det_scanloop_reversers
+;---------- ; E xx xx xx xx xx 02 xx xx
+backgroundloop_reversers
rr_fw PORTA ; W xx xx 01 xx 03 xx xx xx (now)
and_wff scana ; a xx xx 01 xx 03 xx xx xx (cumulative)
mov_fw PORTD ; D xx xx xx xx xx xx 04 05 (now)
bc_f buf0,2 ; buf0 MM zz zz ss zz 00 zz zz (cumulative)
bt_f_if0 PORTE,2 ; 02 (now)
bc_f buf0,4 ; buf0 MM zz zz 02 zz ss zz zz (cumulative)
- det_scanloop_again det_scanloop_reversers
+ backgroundloop_again backgroundloop_reversers
;---------- ; buf0 MM zz zz 02 zz 00 zz zz
-det_slave_read_start_reversers
+i2csu_read_begin_reversers
mov_fw scana ; W xx xx 01 xx 03 xx xx xx
and_lw 0x28 ; W zz zz 01 zz 03 zz zz zz
ior_wff buf0 ; buf0 MM zz 01 02 03 00 zz zz
call i2cs_read_data
- mov_lfsr outbuf, 2
+ rcall new_i2c_outmsg
bra both_startread_tail
; ask sub-pic s for data
; (i.e. send i2c request - will need to work out how to differentiate this
-; from requests fior other data from subpics, or make a general routine to
+; from requests fior other data from subpics, or make a general routine to
; handle all sorts of data a subpic might send back)
; if no change, advance subpic # and return
; main loop of slave program
; Reads from detection legs as defined by bitmasks Ma-e applied to ports a-e.
-; Writes the result into registers Pa-e. On i2c interrupt, checks that there
+; Writes the result into registers Pa-e. On i2c interrupt, checks that there
; is new data to send to the master pic and if so sends it. Current state of
; master's knowledge is stored in Ca-e for comparison with Pa-e.
;