;====================================================================== ; DETECTION AND SLAVE I2C ; FSR1 is used as pointer to where to add bytes of message; it ; points to previous byte whose top bit must be set before ; adding another bit ; FSR2 is used as readout pointer 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) ; two digits indicates that the bit is the corresponding ; detection information. The bit is clear iff current ; was detected since the last poll by the master. ; The bit value is not defined for unused sense ; segments. ; ; Following that are the zero, one or two more bytes of ; detection data: ; 19 09 12 15 18 04 20 17 iff reversers and B1 was set ; 06 01 07 02 11 14 03 00 iff reversers and B2 was set ; ; Finally, zero or more bytes of extra messages: ; MM XX XX XX XX XX XX XX ; where ; MM indicates that further extra message bytes follow; ; it is clear iff this is the last extra message byte. ; XX are the lower 7 bits of a POINTED ; or AAARGH message (see README.protocol). ; Master may also write to slave. Every written byte is independent: ; ; 11RRRRRR Set reverse to RRRRRR, see reverse.asm ; 100PPPPP Fire point PPPPP ; ; 00000000 Acknowlege that slave has crashed, and ; switch into crash readout mode ;====================================================================== ; variables and memory organisation max_messages equ 4 udata_acs unattendedl res 1 ; counts up; each det loop it is unattendedh res 1 ; incremented by no. of bytes of pc in unattendedu res 1 ; det loop; if it overflows, led is set to red 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 buf0_startval res 1 ; reversers start with some det bits buf0 res 1 message_buffer res max_messages message_buffer_end res 0 ;---------------------------------------------------------------------- ; buf0, message_buffer, and FSR1 are used mainly for recording ; non-detection messages. They look like this: ; ; +--------+--------+--------+--------+--------+ ; | buf0 | message_buffer... | ; +--------+--------+--------+--------+--------+ ; ; |0d0d0000|???????? ???????? ???????? ????????| no extra messages ; ^ ; |1d0d0000|0aaaaaaa ???????? ???????? ????????| one extra byte ; ^ ; |1d0d0000|1aaaaaaa 0bbbbbbb ???????? ????????| two extra bytes ; ; 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 ; ;---------------------------------------------------------------------- ; ; 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_begin (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 ;---------- detect_local_init @ mov_lw b'111' ; turn off comparator, or we can't use pins mov_wf CMCON ; RD0-RD4 as digital inputs mov_lw b'0110' ; turn off A/D except perhaps for pin ior_wff ADCON1 ; AN0 ie SPARE ie RA0 (same reason as above) ; compute buf0_startval clr_w bt_f_if0 idloc1,idloc1_boarddet mov_lw 0x14 ; see under reversers, below mov_wf buf0_startval set_f scana set_f scanb set_f scanc set_f scand set_f scane set_f last1 set_f last2 mov_ff buf0_startval, buf0 return ;---------- detect_slave_init @ mov_lfsr outbuf, 2 clr_f outmsg_end goto reset_detectread ;---------------------------------------- slave_add_short_message @ ; Queues a message byte for transmission to the master. ; It will be transmitted as an extra message byte, when we are polled. ; W message unchanged ; GIEH set set intrh_mask bs_f INDF1,7 mov_wf PREINC1 intrh_unmask mov_lw message_buffer_end-1 cmp_fw_ifle FSR1L return panic morse_DB ;---------- backgroundloop_again macro backgroundloop_whatever local branchposition inc_f_ifnz unattendedl bra backgroundloop_whatever mov_lw branchposition - backgroundloop_whatever branchposition add_wff unattendedh bra_nc backgroundloop_whatever inc_f_ifz unattendedu call led_red bra backgroundloop_whatever endm near_i2csu code ;---------- i2csu_read_begin ; called from High ISR, see i2clib.inc bt_f_if1 idloc1,idloc1_boarddet bra i2csu_read_begin_detectors bra i2csu_read_begin_reversers ;---------- i2csu_read_another ; called from High ISR, see i2clib.inc mov_fw POSTINC2 i2cs_read_data_macro mov_fw outmsg_end cmp_fw_ifle FSR2L return ; oops panic morse_DR ;====================================================================== ; main detection bit-twiddling ; 80 40 20 10 08 04 02 01 ; 7 6 5 4 3 2 1 0 ;---------------------------------------------------------------------- ; detectors ; A xx 19 09 12 15 18 xx xx ; B xx xx xx 04 20 17 xx xx ; C xx xx 05 xx xx 10 13 16 ; D 02 11 14 xx 08 xx 01 07 ; E xx xx xx xx xx 03 00 06 ; buf0 MM zz B2 B1 zz zz zz zz ; scheme for bit shuffling: ; ; 1: ; _>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 ; ; 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. ;---------- 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) and_wff scana ; a 19 09 12 15 18 xx xx xx (cumulative) rr_fw PORTE ; W 06 xx xx xx xx xx 03 00 (now) and_wff scane ; e 06 xx xx xx xx xx 03 00 (cumulative) swap_fw PORTD ; W 08 xx 01 07 02 11 14 xx (now) and_wff scand ; d 08 xx 01 07 02 11 14 xx (cumulative) 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) backgroundloop_again backgroundloop_detectors ;---------- ; buf0 MM zz zz zz zz zz zz zz 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 rr_fw scanb ; W xx xx xx xx xx 04 20 17 and_lw 0x07 ; W zz zz zz zz zz 04 20 17 ior_wff scana ; scana 19 09 12 15 18 04 20 17 mov_fw scana cmp_fw_ifne last1 bs_f buf0,4 ; buf0 MM zz zz B1 zz zz zz zz ; detection byte 2 mov_lw 0x83 ; W yy zz zz zz zz zz yy yy and_wff scane ; scane 06 zz zz zz zz zz 03 00 rlc_fw scand ; W xx 01 07 02 11 14 xx xx C=08 and_lw 0x7c ; W zz 01 07 02 11 14 zz zz C=08 ior_wff scane ; scane 06 01 07 02 11 14 03 00 C=08 mov_fw scane cmp_fw_ifne last2 bs_f buf0,5 ; buf0 MM zz B2 B1 zz zz zz zz ; detection and lead byte, 0 rlc_fw scanc ; W xx 05 xx xx 10 13 16 08 and_lw 0x4f ; W zz 05 zz zz 10 13 16 08 ior_wfw buf0 ; W MM 05 B2 B1 10 13 16 08 i2cs_read_data_macro rcall new_i2c_outmsg mov_fw scana bt_f_if1 buf0,4 mov_wf POSTINC2 mov_wf last1 mov_fw scane bt_f_if1 buf0,5 mov_wf POSTINC2 mov_wf last2 set_f scanb set_f scanc set_f scane ;... ;---------------------------------------------------------------------- ; both detectors and reversers ; i2csu_read_begin_either_tail set_f scana set_f scand mov_lfsr message_buffer, 1 bt_f_if0 buf0, 7 bra msg_copy_exitnone ; some extra bytes to copy ;... msg_copy_loop mov_fw POSTINC1 mov_wf POSTINC2 bra_n msg_copy_loop ;... msg_copy_exitnone mov_ff FSR2L, outmsg_end mov_ff buf0_startval, buf0 mov_lfsr outbuf, 2 reset_detectread ; FSR1/buf0/message_buffer any set to empty ; unattended* any reset ; Per-PIC LED any black ; may be called from High ISR or during init mov_lfsr buf0, 1 call led_black unattended_timeout equ 100 ; ms set_f unattendedl ; Fosc = sclock [kHz] ; Fcy = sclock / 4 [kHz] ; program counter advance rate = 2 * sclock / 4 [bytes/ms] ; unattendedh increment rate = pc advance rate / 256 ; = 2 * sclock / (4 * 256) [counts/ms] ; count needed before show unattended = uah rate * ua timeout ; = (2 * sclock / (4 * 256) [counts/ms]) ; * (unattended_timeout [ms]) ; = (2 * sclock / (4 * 256)) * unattended_timeout [counts] ; = sclock * unattended_timeout / 512 [counts] ; we count up until overflow, so unattended_init equ 65535 - (sclock * unattended_timeout / 512) mov_lw unattended_init / 256 mov_wf unattendedu mov_lw unattended_init & 255 mov_wf unattendedh return ;---------- new_i2c_outmsg ; Called from i2csu_read_begin 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 backgroundloop_reversers_core macro 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) and_wff scand ; d xx xx xx xx xx xx 04 05 (cumulative) bt_f_if0 PORTC,2 ; 00 (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) endm backgroundloop_reversers @ backgroundloop_reversers_core backgroundloop_again backgroundloop_reversers ;---------- ; buf0 MM zz zz 02 zz 00 zz zz read_begin_calc_buf0_reversers macro 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 mov_fw scand ; W xx xx xx xx xx xx 04 05 and_lw 0x03 ; W zz zz zz zz zz zz 04 05 ior_wfw buf0 ; W MM zz 01 02 03 00 04 05 endm i2csu_read_begin_reversers read_begin_calc_buf0_reversers call i2cs_read_data rcall new_i2c_outmsg bra i2csu_read_begin_either_tail ;====================================================================== ; FOR MASTER ;---------- backgroundloop_master @ backgroundloop_reversers_core bra backgroundloop_master ;---------- read_detection_head_master @ read_begin_calc_buf0_reversers bra_n read_detection_head_master_badmore set_f scana set_f scand mov_ff buf0_startval, buf0 return ;----- read_detection_head_master_badmore panic morse_DM ;====================================================================== include final.inc