udata_acs
-ssp res 1
-
-st res 1 ; bitmask:
-st_writing equ 0
-st_subsequent equ 0
+sspstat res 1
+sspcon1 res 1
+sspcon2 res 1
+
+st res 1 ; bitmask, bit set in visible states:
+ ; master slave
+st_reading equ 0 ; Reading-* Transmitting
+st_writing equ 1 ; Writing-* [Idle-going-]Receiving
+st_subsequent equ 2 ; Receiving
+st_working equ 3 ; Writing-*,Reading-Busy,Stopping
+st_starting equ 4 ; Writing-Setup,Reading-Busy
code
rlc_w
return
+;----------
+check_wcolsspov
+ mov_fw SSPCON1
+ mov_wf ssp
+ and_lw 0xc0 ; WCOL,SSPOV
+ bra_z intr_wcolsspov
+ return
+
+;----------
+intr_wcolsspov
+ panic morse_SV
+
+;======================================================================
+; MASTER
+
+;----------
+i2cm_init
+ mov_lw 100-1 ; baud rate = Fosc/(4*(SSPADD+1))
+ mov_wf SSPADD ; Fosc=20MHz, so SSPADD==99 means 50kbit/s
+ mov_lw 0x08 ; !SSPEN, Master mode
+ mov_wf SSPCON1
+ clr_f SSPCON2 ; nothing going
+ mov_lw 0x80 ; SMP(noslew), !CKE(!smbus)
+ bra init_enable
+
+;----------
+i2cm_write_start
+; At call On return
+; State Idle Writing-Setup
+; W slave number any
+ tst_f_ifnz st
+ bra m_bad_write_start
+ bs_f st, st_writing
+m_start
+ bs_f st, st_starting
+ bs_f SSPCON2, SEN
+ return
+
+;----------
+m_bad_write_start
+ panic morse_SPW
+
+;----------
+i2cm_interrupt
+ ; Do we have a doomy clash ?
+ bsr check_wcolsspov
+
+ ; No ? Well, then the I2C should be idle now:
+ mov_fw SSPCON2
+ mov_wf ssp
+ and_lw ~0x60 ; ACKSTAT,ACKDT
+ bra_nz m_bad_sspcon2
+ ; OK, what's happening;
+
+ bt_f_if0 PIR1, SSPIF
+ return
+ ; We have an interrupt:
+
+ bt_f_if1 st, st_starting
+ bra m_event_starting
+ ; not just done SEN
+
+ fixme
+
+;----------
+m_bad_sspcon2
+ panic morse_SM
+
+
+;----------
+m_event_starting
+ mov_lw 0x88
+ bsr m_check_sspstat
+
+
+m_check_sspstat
+; W expected bit values any
+; Panics if (SSPSTAT ^ W) & mask != 0
+ mov_ff SSPSTAT, ssp
+
;======================================================================
; SLAVE
mov_wf SSPCON1
mov_lw 0x01 ; !GCEN, SEN
mov_wf SSPCON2
- mov_lw 0x8 ; SMP(noslew), !CKE, !BF(empty)
+ mov_lw 0x8 ; SMP(noslew), !CKE(!smbus)
mov_wf SSPSTAT
+ms_init_enable
+; Actually engages the I2C controller, which must already have
+; been set up (all but SSPEN):
+; SSPADD,SSPCON1,SSPCON2 configured correctly unchanged
+; SSPSTAT configured correctly unchanged, except:
+; SSPSTAT<SSPEN> 0 (disabled) 1 (enabled)
+; SSPIE 0 (disabled) 1 (enabled)
+; TRISB<1,0> any configured for I2C
+; SSPIP any configured correctly
+; GIEL 0 (disabled) 0 (disabled)
bs_f TRISB, 0
bs_f TRISB, 1
bc_f IPR1, SSPIP
bc_f PIR1, SSPIF
; Check that nothing obvious is wrong:
- mov_fw SSPCON1
- mov_wf ssp
- and_lw 0xc0 ; WCOL, SSPOV
- bra_nz i2cs_interrupt_wcolsspov_endif
- panic morse_SV
-i2cs_interrupt_wcolsspov_endif
+ bsr check_wcolsspov
bt_f_if0 st, st_reading
bra s_event_reading
bs_f st, st_subsequent
goto i2csu_write_begin
-;======================================================================
-; MASTER
-
-
-
;======================================================================
include i2clib.inc
; i2c controller any for use by i2clib
; i2c interrupt config any enabled, low priority
; global interrupt enable disabled unchanged
-; State Not-in-use Idle
+; State Not-in-use Idle (as master)
;--------------------
extern i2cs_init
; i2c controller any for use by i2clib
; i2c interrupt config any enabled, low priority
; global interrupt enable disabled unchanged
-; State Not-in-use Idle
+; State Not-in-use Idle (as slave)
; W slave number any
;--------------------
-extern i2cs_interrupt
extern i2cm_interrupt
+extern i2cs_interrupt
;
; Must be called by the main program's low priority interrupt handler.
; The main program's interrupt handler is responsible for saving W and
; from i2c?_inerrupt.
-;======================================================================
-; SLAVE
-;
-; States:
-;
-; [Not-in-use]
-; |
-; |init
-; v
-; [Idle]<-------------------------.
-; write_begin/ \ |
-; / \read_begin |
-; V V |
-; ,->[Receiving] [Transmitting]<-. |
-; `-----' | | `------' |
-; write_another | | read_another |
-; | read_done| |
-; write_done| \ |
- `--------------+->----------------'
-
-;========================================
-; SLAVE - WRITES (ie, reception of data from the master)
-
-;--------------------
-extern i2csu_write_begin
-;
-; Called to notify the main program that the master PIC has selected this
-; slave to talk to, for writing. Provides the first byte of data
-; we received from the master PIC.
-;
-; Beforehand At call On return
-; State Idle Receiving Receiving
-; W data from master any
-
-;--------------------
-extern i2csu_write_another
-;
-; Called to notify the main program that the master PIC has continued
-; by transmitting another byte of data. Provides the byte we received.
-;
-; Beforehand At call On return
-; State Receiving Receiving Receiving
-; W data from master any
-
-;--------------------
-extern i2csu_write_done
-;
-; Called to notify the main program that the master PIC has stopped
-; transmitting data (ie, finished the i2c conversation).
-;
-; Beforehand At call On return
-; State Receiving Idle
-
-;========================================
-; SLAVE - READS (ie, transmission of data to the master)
-
-;--------------------
-extern i2csu_read_begin
-;
-; Called to notify the main program that the master PIC has selected
-; this slave to talk to, for reading, and to obtain the first byte of
-; data that we should transmit to the master.
-;
-; Beforehand At call On return
-; State Idle Transmitting Transmitting
-; W any data for master
-
-;--------------------
-extern i2csu_read_another
-;
-; Called to notify the main program that the master PIC has continued
-; by asking for another byte of data. Must provide the byte.
-;
-; Beforehand At call On return
-; State Transmitting Transmitting Transmitting
-; W any data for master
-
-;--------------------
-extern i2csu_read_done
-;
-; Called to notify the main program that the master PIC has stopped
-; asking for data (ie, finished receiving).
-;
-; Beforehand At call On return
-; State Transmitting Idle
-
;======================================================================
; MASTER
;
; |init
; v
; [Idle]<-----------------------------.
-; write_start/ \ |
+; write_start/ \read_start |
; / \ |
; V V |
; [Writing-Setup] [Reading-Busy]<---------. |
; At call On return
; State Reading-Wait Stopping
+
+;======================================================================
+; SLAVE
+;
+; States:
+;
+; [Not-in-use]
+; |
+; |init
+; v
+; [Idle]<-------------------------.
+; write_begin/ \ |
+; / \read_begin |
+; V V |
+; ,->[Receiving] [Transmitting]<-. |
+; `-----' | | `------' |
+; write_another | | read_another |
+; | read_done| |
+; write_done| \ |
+ `--------------+->----------------'
+
+;========================================
+; SLAVE - WRITES (ie, reception of data from the master)
+
+;--------------------
+extern i2csu_write_begin
+;
+; Called to notify the main program that the master PIC has selected this
+; slave to talk to, for writing. Provides the first byte of data
+; we received from the master PIC.
+;
+; Beforehand At call On return
+; State Idle Receiving Receiving
+; W data from master any
+
+;--------------------
+extern i2csu_write_another
+;
+; Called to notify the main program that the master PIC has continued
+; by transmitting another byte of data. Provides the byte we received.
+;
+; Beforehand At call On return
+; State Receiving Receiving Receiving
+; W data from master any
+
+;--------------------
+extern i2csu_write_done
+;
+; Called to notify the main program that the master PIC has stopped
+; transmitting data (ie, finished the i2c conversation).
+;
+; Beforehand At call On return
+; State Receiving Idle
+
+;========================================
+; SLAVE - READS (ie, transmission of data to the master)
+
+;--------------------
+extern i2csu_read_begin
+;
+; Called to notify the main program that the master PIC has selected
+; this slave to talk to, for reading, and to obtain the first byte of
+; data that we should transmit to the master.
+;
+; Beforehand At call On return
+; State Idle Transmitting Transmitting
+; W any data for master
+
+;--------------------
+extern i2csu_read_another
+;
+; Called to notify the main program that the master PIC has continued
+; by asking for another byte of data. Must provide the byte.
+;
+; Beforehand At call On return
+; State Transmitting Transmitting Transmitting
+; W any data for master
+
+;--------------------
+extern i2csu_read_done
+;
+; Called to notify the main program that the master PIC has stopped
+; asking for data (ie, finished receiving).
+;
+; Beforehand At call On return
+; State Transmitting Idle
+
;======================================================================