chiark / gitweb /
Send HELLO as a result of all slaves being online. Do not crash if slave is slow...
[trains.git] / detpic / mascan.asm
index ad3eb8dc9156415aff6c7f56c3e2f355911e0001..36c16f495fdfed36b1f8f1e6c31ce5d9a7334a06 100644 (file)
@@ -15,11 +15,16 @@ 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 due to lack of buffer space:
+       ;       ???? ???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 ; 
+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
 
 ;======================================================================
 ; HANDLING OF I2C EVENTS
@@ -34,6 +39,7 @@ i2c_getwritebyte_yes @
   code
 ;----------------------------------------
 i2cmu_write_next_byte
+       Dl 0x91
        ; add calls to getwritebyte_<foo> here:
        call    polarity_getwritebyte
        call    points_getwritebyte
@@ -46,6 +52,7 @@ i2cmu_write_next_byte
 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
@@ -54,6 +61,22 @@ i2cm_intrl @
 ;======================================================================
 ; 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
 ;              Beforehand      At call
@@ -65,6 +88,11 @@ 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
 
@@ -72,6 +100,9 @@ i2cmu_read_got_byte
        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
@@ -107,19 +138,20 @@ read_got_bad_first_reversers panic morse_MR
 
 ;----------
 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
 
@@ -140,13 +172,22 @@ read_got_detectbyte_prep_ifsomething
 ;  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
@@ -183,7 +224,10 @@ 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
@@ -199,21 +243,29 @@ i2c_arrange_next_byte
 ; DECIDING WHICH SLAVE TO ADDRESS
 ;...
 i2c_arrange_something
+i2cmu_done
 ; figure out what to do next - which pic to address, etc.
        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
 
- return ; do not scan yet
-
-       neg_fw  outmsg_begin
-       add_wfw outmsg_end
+       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
@@ -229,6 +281,7 @@ nextslave_nowrite
        bra     nextslave_looparound
        ; Ok, we have a slave:
 
+       Dl 0x91
        mov_fw  INDF1           ; W = new slave number
        goto    i2cm_read_start
 
@@ -236,26 +289,10 @@ 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
 
-;----------------------------------------
-i2cmu_done
-       ; So we've done one write.
-       bs_f    cbyte, cbyte_halted
-
-       tst_f_ifnz wslave       ; anyone asked in the meantime ?
-       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
-       bra     nextslave_nowrite
-
 ;----------------------------------------
 i2c_needwrite @
 ; Informs mascan that we need to write to some slave.
@@ -281,17 +318,39 @@ i2c_consider_restartread @
        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 + ste_size) & 0xff
-                ; start with 1st actual slave
+       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 ; serial output of `hello' will start us up
+       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
@@ -301,7 +360,9 @@ mascan_init_loop
        mov_fw  TABLAT                  ; W = EOOOOSSS, N = E
 
        tblrd_postinc_fixup             ; TABLAT = DSSSSSSS, N (still) = E
-       bra_nn  mascan_init_ifabsent
+       bra_nn  mascan_init_ifabsent    ;     E.......
+
+       inc_f   slaves_awaiting
 
        mov_ff  t, POSTINC0             ; ste_slave = slave
        mov_wf  u                       ; u = 1OOOOSSS
@@ -318,10 +379,13 @@ mascan_init_loop
        add_lw  -0xf8                   ; W = first - 0xf8 = detbasel
        mov_wf  POSTINC0                ; detbasel
 
-       clr_f   POSTINC0                ; lastd0
-       clr_f   POSTINC0                ; lastd1
-       clr_f   POSTINC0                ; lastd2
+       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
@@ -375,23 +439,23 @@ loopback_read_byte @
 ;======================================================================
 ; 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
 
 ;----------------------------------------
@@ -444,27 +508,34 @@ addmsgs_dethead   addmsg_testbit  0
 
 ;----------
 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