; Timer 3 Off On, counting up
; pointmsg undefined message from master
+ include common.inc
+
udata_acs
pointmsg res 1
- udata 0x300
-ptix2latbit res maxpoint * 2 ; bit and LAT*
+ptix2bitlat equ 0x300
+ udata ptix2bitlat
+ res maxpoint * 2 ; bit and LAT*
+ ; for unused point, 0x00 and 0x00
code
pt_timer13_prescale equ 0
pt_timer13_inithigh equ 0
-;----------
+;======================================================================
+; LOCAL POINTS
+; Actually doing points (on slave, or master's own)
+
+;--------------------
point_timer_init
mov_lw (1<<RD16) | (1<<T3ECCP1) | pt_timer13_prescale ; Fcy; !TMR3ON
mov_wf T3CON
mov_wf TMR3H ; we just leave this here, since we never read TMR3L
return
-;----------
+;----------------------------------------
point_do_here
; On slave, called during i2c receive, ie High ISR
; On master, called during serial receive, ie Low ISR
mov_wf pointmsg ; pointmsg = SS zz zz pp pp pp pp pp
rcall point_set_pin
- set_f TMR3L
+ set_f TMR3L ; also copies TMR3H into actual timer register
bs_f T3CON, TMR3ON
panic morse_UP
return
+;----------------------------------------
+points_interrupt
+; Low priority; checks for, and clears, any relevant interrupt.
+; Then returns.
+ bt_f_if0 PIR2, TMR3IF
+ return
+ ; OK, we're done:
+
+ bt_f_if0 T3CON, TMR3ON
+ bra point_spurious_intr
+
+ rcall point_set_pin
+ mask_int_high
+ bc_f T3CON, TMR3ON
+ bc_f PIR2, TMR3IF
+ unmask_int_high
+
+ mov_lw b'00100000'
+ goto message_for_master
+
;----------
+point_spurious_intr
+ panic morse_PI
+
+;--------------------
; Sets the pin appropriately:
; If we were idle, sets it H (to fire) unless pt0 in which case L
; If we were firing, sets it L (to stop) unless pt0 in which case H
point_set_pin
- mov_lw ptix2lat >> 8
+ mov_lw ptix2bitlat >> 8
mov_wf FSR0H ; FSR0H -> table
- rl_w pointmsg ; W = point addr, Z iff pt0
- mov_wf FSR0L ; FSR0 -> &LAT* [Z still iff pt0]
+ rl_fw pointmsg ; W = point addr, Z iff pt0
+ mov_wf FSR0L ; FSR0 -> &bit [Z still iff pt0]
bt_f_if1 T3CON, TMR3ON ; Were we firing ? [Z still iff pt0]
btg_f STATUS, Z ; Z iff (pt0 xor were_firing)
bra_z point_set_pin_l
+
point_set_pin_h
mov_fw POSTINC0 ; W = bit, FSR0 -> &LAT*
+ bra_z point_nonexistent
mov_ff INDF0, FSR0L ; W = bit, FSR0L -> LAT*
set_f FSR0H ; FSR0 -> LAT*, W = bit (still)
ior_wff INDF0 ; pin = H
return
+;----------
point_set_pin_l
com_fw POSTINC0 ; W = ~bit, FSR0 -> &LAT*
mov_ff INDF0, FSR0L ; W = ~bit, FSR0L -> LAT*
set_f FSR0H ; FSR0 -> LAT*, W = bit (still)
ior_wff INDF0 ; pin = H
- return
+point_set_pin_hl
+ tst_f_ifnz FSR0L ; err, did we just write to 0xf00 ?
+ return ; no; good.
+ ; oops, we did:
+ if 0xf00 == RXF0SIDH
+ ; This is actually OK; it's a `receive acceptance filter'
+ ; for the CAN controller, writing to which has no side
+ ; effects. And anyway the register starts at xxxx xxxx
+ ; so if we don't care about CAN that's fine, and we're about
+ ; to panic, of course.
+ ; See DS p212 (register summary), p228 (description),
+ ; p48 (location, 0xf00), p53 (POR value).
+ else
+ error "must check what 0xf00 is on this processor"
+ endif
+point_nonexistent
+ panic morse_PU
;----------
point_clash
panic morse_PB
-
-
-
- bt_f_if0
-
-
-
-
- bra_z point_do_if_pt0
-point_do_ifnot_pt0
- rcall point_pin_h
-point_do_endif_pt0_set_timer
- mov_lw
-
-point_do_if_pt0
- rcall point_pin_l
-
-
-
-point_pin_l
-
-
- rl_w
-
- bt_f_if0
-
- add_lw (ptix2lat >> 8) - 0x80
-
-
-
-; We use FSR1 so we have to save it
- mov_ff FSR1L, fsr1l_save ; we assume FSR1H is zero, since on
- ; W SS zz zz pp pp pp pp pp
-
;----------------------------------------------------------------------
points_init
; Initialises tables for points
; Clears TRIS* bits for all points and sets each pin to `not triggering'
-points_init
-
-
-;
-; Expected layout of data at data_points in flash:
-; 4 bytes for each point number
-; byte 0
-; pic number for this point
-; ff indicates unassigned point number
-; byte 1
-; index number for this point on relevant pic
-; byte 2
-; address of relevant LAT*
-; byte 3
-; bit in LAT (eg 0x40 for bit 6)
-; bytes 1-3 are not defined if number is not assigned
-; address of data_points is guaranteed to be multiple of 256
+; We do this in two stages.
+; Firstly, we scan the bitmap for this pic, setting
+; ptix2bitlat to 0xff,0x00 for used points and 0x00,0x00
+; to unused ones.
+; Secondly, we scan the bkptix2portnumbitnum, adjusting
+; ptix2bitlat to have actually correct data.
+; Doing it like this avoids having to constantly recompute
+; individual TBLPTR*'s.
+ mov_lfsr ptix2bitlat, 0 ; FSR0 -> this bit and LAT*
+ mov_lw maxpoint/8
+ mul_wf picno
+ mov_lw picno2ptmap & 0xff
+ add_wfw PRODL
+ mov_wf TBLPTRL
- udata_acs
-
- udata 0x300
-our_point_table_ctln2 equ 6
-our_point_table_count equ (1 << our_point_table_ctln2)
-our_point_table res our_point_table_count * 2
-; 2 bytes for each point, indexed by index number on this pic
-; 1st byte: LAT* address, or 0 for unassigned
-; 2nd byte: bit in LAT
-
- code
-
-;----------------------------------------------------------------------
-points_init
-; Clears TRIS* bits for all points and sets the
-; pin to `not triggering'
-
- mov_lfsr our_point_table, 0 ; FSR0 points to point lookup table
- mov_lw our_point_table_count * 2
-
-points_init_clear_loop
- clr_f POSTINC1
- dec_w_ifnz
- bra points_init_clear_loop
- ; otherwise, done:
-
- ; During this loop:
- clr_wf TBLPTRU
- mov_lw (data_points >> 8)
+ mov_lw picno2ptmap >> 8
+ addc_wfw PRODH
mov_wf TBLPTRH
- clr_f TBLPTRL ; TBLPTR* -> to point data
-
- set_f FSR1H ; FSR1 -> LAT*, TRIS*
-
- mov_lfsr our_point_table, 0 ; FSR0 -> point lookup table
-
-points_init_loop
- mov_lw (data_points_end >> 8)
- cmp_fw_ifge TBLPTRH
- bra points_init_loop_exit
- tblrd *+
- dw 0xffff ; TABLAT = pic number
+ clr_f TBLPTRU ; TBLPTR* -> our point data
+
+ mov_lw maxpoint/8
+ mov_wf t ; t = byte counter
+;...
+points_init_byte_loop
+ mov_lw 8 ; W = bit counter
+ clr_f INDF0 ; bit[current] := 0
+ tblrd_postinc_fixup ; TABLAT = bitmap data being processed
+;...
+points_init_bit_loop
+ rrc_f TABLAT
+ bra_nc points_init_ifnot_point
+points_init_if_point
+ set_f POSTINC0 ; bit[current] := 0xff, FSR0 -> LAT*[current]
+points_init_ifnot_point
+ clr_f POSTINC0 ; LAT*[current] := 0xff, FSR0 -> bit[current+1]
- mov_fw picno
- cmp_fw_ifne TABLAT
- bra points_init_loop_ifnot_ours
-
- tblrd *+
- dw 0xffff ; TABLAT = index number
-
- mov_lw 0xff << our_point_table_ctln2
- and_wfw TABLAT
- bra_nz bad_pointtable_index
-
- rl_fw TABLAT
- mov_wf FSR0L ; FSR0 -> our table entry
-
- tst_f_ifnz INDF0
- bra_nz bad_pointtable_clash
-
- tblrd *+
- dw 0xffff ; TABLAT = LAT* address
-
- mov_fw TABLAT
- mov_wf POSTINC0 ; store LAT* address; FSR0 -> bit
- mov_wf FSR1L ; FSR1 -> LAT*
+ dec_w_ifnz
+ bra points_init_bit_loop
+ dec_f_ifnz t
+ bra points_init_byte_loop
+;... end of loop:
+
+; We've scanned for points used on this board;
+; now find the actual pins.
+
+ mov_lfsr ptix2bitlat, 0 ; FSR0 -> this bit and LAT*
+ mov_lfsr bitnum2bit+7, 1 ; FSR1 -> bitnum2bit+7
+ set_f FSR2 ; FSR2 -> some SFR, will point to LAT/TRIS
+
+ mov_lw bkptix2portnumbitnum & 0xff
+ bt_f_if0 idloc1,idloc1_boarddet
+ add_lw maxpoint
+ mov_wf TBLPTRL
+
+ mov_lw bkptix2portnumbitnum >> 8
+ mov_wf TBLPTRH ; TBLPTR* -> point port/bit data
+
+ mov_lw maxpoint
+ mov_wf t ; t = loop counter
+;...
+points_init_portbit_loop
+ tblrd_postinc_fixup ; TABLAT = portnum4 || bitnum4
+
+ bt_f_if0 POSTINC0,7 ; zero?, FSR0 -> LAT*[this]
+ bra points_init_portbit_endif_used
+;...
+points_init_portbit_if_used
+ mov_wf TABLAT
+ bra_n point_initing_bad_point
- tblrd *+
- dw 0xffff ; TABLAT = bit value
-
- mov_fw TABLAT
- mov_wf INDF0 ; store bit value
-
- com_w ; W = ~bit
- and_wff INDF1 ; clear the LAT* bit (point inactive)
- pin_vh pall_pt0reverse ; except pt0 which is backwards
-
+ and_wff FSR1L ; FSR1 -> bit value for bit
+
+ swap_fw TABLAT ; W = bitnum4 || portnum4
+ and_lw 0x0f ; W = portnum4
+ add_lw LATA & 0xff ; W = LAT*
+ mov_wf POSTDEC0 ; LAT*[this] := LAT, FSR0 -> bit[this]
+ mov_wf FSR2L ; FSR2 -> LAT*
+
+ mov_wf INDF1 ; W = bit
+ mov_fw POSTINC0 ; bit[this] = bit, FSR0 -> LAT*[this]
+ com_w ; W = ~bit
+ and_wff INDF2 ; LAT* &= ~bit, ie pin set to L (still Z)
+ pin_vh pall_pt0reverse ; but pt0 pin is backwards, set to H
+ ; (still Z, unless we've done this already)
mov_lw TRISA-LATA
- add_wf FSR1L ; FSR1 -> TRIS*
- com_fw TABLAT ; W = ~bit
- and_wff INDF1 ; make the pin an output
-
- bra points_init_loop
-
-points_init_loop_ifnot_ours
- tblrd *+
- tblrd *+
- tblrd *+
- bra points_init_loop
-
+ add_wff FSR2L ; FSR2 -> TRIS*
+ com_fw INDF1 ; W = ~bit
+ and_wff INDF2 ; TRIS* &= ~bit, ie pin set to not Z
-
+ set_f FSR1L ; FSR1 -> bitnum2bit+7, again
+points_init_portbit_endif_used
+ ; so now we move on to the next one
+ mov_fw POSTINC0 ; FSR0 -> bit[this+1]
+ dec_f_ifnz t
+ bra points_init_portbit_loop
- clr_f INDF1
+ return
-
+;----------
+point_initing_bad_point
+ panic morse_PF
;----------------------------------------------------------------------
-cdu_init
+;cdu_init
; For master pic only. Sorts out the CDU's pin.
+ include final.inc