;======================================================================
; MASTER - SCANNING ETC.
- include common.inc
+ include common.inc
;----------------------------------------------------------------------
- udata_acs
+ udata_acs
+; for reading and detection:
b res 1 ; byte just read
cslot res 1 ; current slave in slave table, points to flags byte
cbyte res 1
; M0B1 0000 we're expecting more detection byte 1
; M010 0000 we're expecting more detection byte 2
; 1000 0000 we're expecting an extra byte
+ ; ???? ???1 reading halted for any reason:
+cbyte_halted equ 0 ; also set briefly while we decide what to do next
+
+wslave res 1 ; slave we need to write to
+outmsg_targetlen res 1 ;
+
+slaves_awaiting res 1 ; no. of slaves without stf_responding
+slavenoack_counter res 2 ; +0=L, +=H
+slavenoack_counter_init equ (i2c_kbitpersec * 100)
+ ; slaves/sec, @ 10clocks/slave
-;----------------------------------------------------------------------
-slavetable_section udata 0x400
-
-ste_szln2 equ 3
- ; each entry is a number of bytes, at these offsets:
-ste_slave equ 0 ; slave number
-ste_flags equ 1 ; flags (stf_...) cslot normally points here
-ste_detbasel equ 2 ; added to 11111bbb to make 0SSSSSSS; ie first-0xf8
-ste_lastd0 equ 3 ; } [o0]* ie every bit is either 0 (for an
-ste_lastd1 equ 4 ; } irrelevant bit) or o, meaning the
-ste_lastd2 equ 5 ; } previously seen detection data bit
-ste_detmsgh equ 7 ; 1 001 1 000 being 1 001 Y SSS
-ste_size equ (1<<ste_szln2)
-slavetable res maxpics * ste_size
-
-stf_detect equ 7
-
- code
;======================================================================
; HANDLING OF I2C EVENTS
+near_getwritebyteyes code
+;----------------------------------------
+i2c_getwritebyte_yes @
+ pop ; we don't care where we were in i2cmu_write_next_byte
+ bc_f STATUS, Z ; yes, we want to write this byte
+ return ; from i2cmu_write_next_byte
+
+ code
+;----------------------------------------
+i2cmu_write_next_byte
+ Dl 0x91
+ ; add calls to getwritebyte_<foo> here:
+ call polarity_getwritebyte
+ call points_getwritebyte
+ ; end of list of calls to getwritebyte_<foo>
+ ; so, no-one wants this slave:
+ bs_f STATUS, Z
+ return
+
;----------------------------------------
-i2cm_intrl
+i2cm_intrl @
; handles i2c interrupt using i2cm_interrupt[_definite],
; according to the rules for <something>_intrl.
+ Dl 0x90
bt_f_if0 PIR1, SSPIF
return
call i2cm_interrupt_definite
intrl_handled_nostack
-;----------------------------------------
-i2cmu_done panic morse_MD
-
-;----------------------------------------
-i2cmu_write_next_byte
- panic morse_UI
-
;======================================================================
-; PROCESSING OF INCOMING BYTES
+; PROCESSING OF INCOMING BYTES - CORE AND DETECTION
+
+;--------------------
+read_first_response
+; on entry on return
+; W received byte preserved
+; b received byte preserved
+; FSR0 any trashed
+; STATUS any trashed
+ bs_f INDF1, stf_responding
+ dec_f_ifnz slaves_awaiting
+ return
+; that's the last slave, excellent
+ mov_lw b'00001001' ; W trashed
+ call serial_addbyte
+ mov_fw b ; W = received byte (again)
+ return
;----------------------------------------
i2cmu_read_got_byte
; W = received byte
mov_wf b ; W = b = received byte
+ Dl 0x90
+ Df cslot
+ Df cbyte
+ Df b ; also restores b to W
+
mov_lfsr slavetable, 1
mov_ff cslot, FSR1L ; FSR1 -> slave's flags
bra read_got_notfirst
; this is a first (head) byte:
+ bt_f_if0 INDF1, stf_responding ; seen this PIC ack already ?
+ rcall read_first_response ; no, we might have to send HELLO
+
bt_f_if0 POSTINC1, stf_detect ; FSR1 -> detbasel
bra read_got_first_reversers
read_got_first_detectors ; b = MdBBdddd
;----------
read_got_detectors_b1 ; b = dddddddd
+; ; W = detbasel; FSR1 -> detbasel
+ add_lw 5 ; W = adjdetbasel
+ bs_f FSR1L, 2 ; FSR1L -> lastd1
bc_f cbyte, 4 ; cbyte = M0B00000
- mov_fw POSTINC1 ; W = detbasel; FSR1 -> lastd0
- inc_f FSR1L ; FSR1 -> lastd1
- add_lw 5 ; W = detbasel+8
rcall read_got_detectbyte_prep
goto addmsgs_all
;----------
read_got_detectors_b2 ; b = dddddddd
+; ; W = detbasel; FSR1 -> detbasel
+ add_lw 13 ; W = adjdetbasel
+ inc_f FSR1L ; FSR1 -> lastd0
+ inc_f FSR1L ; FSR1 -> lastd2
bc_f cbyte,5 ; cbyte = M0000000
- mov_fw POSTDEC1 ; W = detbasel; FSR1 -> flags
- bs_f FSR1L, 2 ; FSR1L -> lastd2
- add_lw 13 ; W = detbasel+16
rcall read_got_detectbyte_prep
goto addmsgs_all
; FSR1 -> lastd<n>
;
mov_wf u ; u = [C0]*
- xor_wfw INDF1 ; lastd<n> = [d0]*
+
+ Dl 0x94
+ Df FSR1L
+ Df u ; also restores u to W
+
+ xor_wff INDF1 ; lastd<n> = [d0]*
+ ; to force test of repeated detection notification,
+ ; comment out previous line
mov_lw 0x07
ior_wff FSR1L ; FSR1L -> detmsgh
return ; to addmsgs_<something>, very shortly
;----------------------------------------
read_got_notfirst
+; ; FSR1 -> flags
+ mov_fw PREINC1 ; W = detbasel; FSR1 -> detbasel
bt_f_if1 cbyte, 4
bra read_got_detectors_b1
bt_f_if1 cbyte, 5
bt_f_if0 b, 7 ; any more ?
bc_f cbyte, 7
bc_f b, 7
- rcall process_got_extra
+ call process_got_extra
bra i2c_arrange_next_byte
-;----------------------------------------
-process_got_extra
- mov_fw b
-loopback_read_byte
-;...
-; W message
- xor_lw 0x00 ^ 0x20
- bra_z got_pointed
- xor_lw 0x20 ^ 0xb0
- bra_z got_aargh
- panic morse_MX
-
;----------
read_got_detectbyte_prep
;
; NOS return address for i2cmu_read_got_byte
;
mov_wf t ; t = adjdetbasel
+ Dl 0x93
+ Df INDF1
mov_fw b ; W = [d0]*
+ Dv
xor_wfw INDF1 ; W = [C0]*, Z iff same
; where C set iff change to that detection segment
bra_nz read_got_detectbyte_prep_ifsomething
; DECIDING WHICH SLAVE TO ADDRESS
;...
i2c_arrange_something
+i2cmu_done
; figure out what to do next - which pic to address, etc.
- panic morse_UG
+ bs_f cbyte, cbyte_halted
+
+ tst_f_ifnz wslave ; anyone asked to write ?
+ bra arrange_write
+
+ ; Anyone else to write to ?
+ ; add calls to needwrite_<foo> here:
+ call polarity_needwrite
+ call points_needwrite
+ ; end of list of calls to needwrite_<foo>
+
+ ; no, if we're here, no-one wants to write:
+
+nextslave_nowrite
+ ; no writing needed, we consider reading:
+ bt_f_if1 flags, flags_polarising
+ return ; do not scan while booster PWM is off while polarising
+ ; to avoid all trains disappearing and reappearing
+
+ mov_fw outmsg_begin
+ sub_wfw outmsg_end
+ and_lw outbuf_size - 1
+ cmp_fw_ifle outmsg_targetlen
+ return ; target len < actual len, do not add anything
+ ; ok, there's space, go ahead:
+ bc_f cbyte, cbyte_halted
+
+ mov_lw ste_size
+ add_wff cslot ; cslot -> next ste_flags
+ mov_lfsr slavetable, 1 ; FSR1H -> slavetable
+ mov_ff cslot, FSR1L ; FSR1 -> new ste_flags
+
+ bt_f_if1 POSTDEC1, stf_sentinel ; FSR1 -> ste_slave
+ bra nextslave_looparound
+ ; Ok, we have a slave:
+
+ Dl 0x91
+ mov_fw INDF1 ; W = new slave number
+ goto i2cm_read_start
+
+nextslave_looparound
+ ; now we do our own detection
+ mov_lw (slavetable + ste_flags) & 0xff ; select our own slot
+ mov_wf cslot
+ Dl 0x92
+ call read_detection_head_master
+ goto i2cmu_read_got_byte
+
+;----------------------------------------
+i2c_needwrite @
+; Informs mascan that we need to write to some slave.
+; Some time after this, mascan will call getwritebyte_<everything>
+; and this must yield at least one byte to write.
+; W slave that we must write to
+ mov_wf wslave
+ bt_f_if0 cbyte, cbyte_halted
+ return ; we're currently doing something
+;...
+;----------
+arrange_write
+; wslave slave to write to
+ bc_f cbyte, cbyte_halted
+ mov_fw wslave
+ mov_wf cwslave
+ clr_f wslave
+ goto i2cm_write_start
+
+;----------------------------------------
+i2c_consider_restartread @
+ bt_f_if0 cbyte, cbyte_halted
+ return
+ bra nextslave_nowrite
+
+;----------------------------------------
+i2cmu_slave_no_ack
+ mov_lfsr slavetable, 1
+ mov_ff cslot, FSR1L ; FSR1 -> slave's flags
+ bt_f_if1 INDF1, stf_responding
+ bra slavenoack_crashed
+
+ dec_f_ifnz slavenoack_counter
+ return
+ dec_f_ifnz slavenoack_counter+1
+ return
+ panic morse_ST
+
+slavenoack_crashed
+ panic morse_SC
+
+;======================================================================
+; INITIALISATION
+
+mascan_init @
+ mov_lw (slavetable + ste_flags) & 0xff
+ ; pretend we've just done us, to start with 1st actual slave
+ mov_wf cslot
+ clr_f cbyte
+ bs_f cbyte, cbyte_halted
+ clr_f wslave
+
+ mov_lw slavenoack_counter_init & 0xff
+ mov_wf slavenoack_counter
+ mov_lw slavenoack_counter_init >> 8
+ mov_wf slavenoack_counter+1
+ clr_f slaves_awaiting
+
+ mov_lw 2
+ mov_lfsr slavetable, 0 ; FSR0 -> slavetable
+ load_tblptr pic2detinfo ; TBLPTR* -> pic2detinfo
+ clr_f t ; t = loop counter
+mascan_init_loop
+ tblrd_postinc_fixup ; TABLAT = EOOOOSSS
+ mov_fw TABLAT ; W = EOOOOSSS, N = E
+
+ tblrd_postinc_fixup ; TABLAT = DSSSSSSS, N (still) = E
+ bra_nn mascan_init_ifabsent ; E.......
+
+ inc_f slaves_awaiting
+
+ mov_ff t, POSTINC0 ; ste_slave = slave
+ mov_wf u ; u = 1OOOOSSS
+ and_lw 0x78
+ bra_nz mascan_bad_detinfo0
+ ; ok ; u = 10000SSS
+
+ mov_fw TABLAT ; W = DSSSSSSS
+ and_lw 0x80 ; W = D0000000
+ mov_wf POSTINC0 ; ste_flags = D0000000
+
+ mov_fw TABLAT ; W = DSSSSSSS
+ bc_w 7 ; W = 0SSSSSSS = first
+ add_lw -0xf8 ; W = first - 0xf8 = detbasel
+ mov_wf POSTINC0 ; detbasel
+
+ mov_lw 0x4f ; W = 01001111 for det., MM 05 B2 B1...
+ bt_f_if0 TABLAT, 7 ; D ? otherwise, rev. board:
+ mov_lw 0x3f ; W = 01111111 for rev., MM zz 01...
+ mov_wf POSTINC0 ; lastd0
+ set_f POSTINC0 ; lastd2
+ set_f POSTINC0 ; unused
+ set_f POSTINC0 ; lastd1
+
+ mov_fw u ; W = 10000SSS
+ xor_lw b'10011000' ^ 0x80 ; W = detmsgh
+ mov_wf POSTINC0 ; detmsgh
+
+mascan_init_ifabsent
+ inc_f t ; next slave
+ bt_f_if0 t, maxpics_ln2
+ bra mascan_init_loop
+ ; we've read the whole flash table
+
+ if slavetable == 0x400
+ bt_f_if1 FSR0H, 0
+ bra mascan_bad_toomany
+ endif
+
+ clr_f POSTINC0 ; ste_slave
+ mov_lw (1<<stf_detect)|(1<<stf_sentinel)
+ mov_wf POSTINC0 ; ste_flags
+ ; rest of final entry, and rest of table, is undefined
+
+ ; at 9600, it's about 1ms per char.
+ ; we allow 1ms to scan 2 pics via i2c.
+ ; so our target len is (no of pics)/2
+ ; plus 2 bytes of slop
+ rl_fw t
+ add_lw 2
+ mov_wf outmsg_targetlen
+
+ return
+
+mascan_bad_detinfo0 panic morse_DF
+mascan_bad_toomany panic morse_DG
+
+;======================================================================
+; PROCESSING OF INCOMING BYTES - EXTRA (NON-DETECTION)
+
+near_gots code
+;----------------------------------------
+process_got_extra @
+ mov_fw b
+loopback_read_byte @
+;...
+; W message
+ xor_lw 0x00 ^ 0x20
+ bra_z got_pointed
+ xor_lw 0x20 ^ 0xb0
+ bra_z got_aargh
+ panic morse_MX
;======================================================================
; GENERATION OF DETECTION MESSAGES FOR HOST - MAD BT_F_IF1 TABLES
-addmsg_testbit macro bit
- bt_f_if1 u, bit
+addmsg_testbit macro addmsg_macro_bit
+ bt_f_if1 u, addmsg_macro_bit
rcall addmsg_one
endm
-addmsg_return macro dummy_bit
+addmsg_return macro dummy_addmsg_macro_bit
goto i2c_arrange_next_byte
endm
-addmsg_ignore macro dummy_bit
+addmsg_ignore macro dummy_addmsg_macro_bit
nop
nop
endm
-addmsg_padding macro dummy_bit
+addmsg_padding macro dummy_addmsg_macro_bit
nop
- mov_lw dummy_bit
+ mov_lw dummy_addmsg_macro_bit
endm
;----------------------------------------
;----------
addmsg_one
-; TOS - 4 -> bt_f_if1 w, b'bbb'
+; TOS - 4 -> bt_f_if1 u, b'bbb'
; TOSL ???bbb00
; other conditions on entry and exit as for entry to addmsgs_<kind>, above
+ Dl 0x95
+ Df TOSL
rr_fw TOSL ; W = 0???bbb0
rr_w ; W = 00???bbb
- ior_wfw 0xf8 ; W = 11111bbb
+ ior_lw 0xf8 ; W = 11111bbb
mov_wf FSR0L ; FSR0L = 11111bbb
clr_f FSR0H ; FSR0 -> bitnum2bit[bbb]
add_wfw t ; W = adjdetbasel + 11111bbb
; ie = 0 SSSSSSS (det msg low byte)
mov_wf v ; v = 0 SSSSSSS (det msg low byte)
+ bra_n addmsg_bad
mov_fw b ; W = [d0]*
and_wfw INDF0 ; train: W = 0x00, Z=1; none: W = 0*d0*, Z=0
bt_f_if0 STATUS, Z
mov_lw 0x08 ; train: W = 0 000 0 000; none: W = 0 000 1 000
xor_wfw INDF1 ; W = 1 001 Y SSS (det msg high byte)
+ Dv
call serial_addbyte
mov_fw v ; W = 0 SSSSSSS (det msg low byte)
+ Dv
goto serial_addbyte_another
+addmsg_bad panic morse_DJ
+
;======================================================================
- include final.inc
+ include final.inc