1 ;######################################################################
2 ; i2clib.inc - I2C LIBRARY - IMPLEMENTATION
4 ; See i2clib.asm for documentation of the interface to this file.
6 include /usr/share/gputils/header/p18f458.inc
8 include ../iwjpictest/insn-aliases.inc
10 include morse+auto.inc
12 ;======================================================================
17 ; m_... routines used by master only
18 ; s_... routines used by slave only
19 ; <any other name> routines used by both
21 ; [ms]_event_... event handler, branched to from interrupt
22 ; handler; conditions are as in the name;
23 ; should `return' at end which will return
24 ; from i2c[ms]_interrupt
26 ; [sm]_event_bad[_...] event handler which panics; called when i2c
27 ; controller did something unexpected
29 ; m_improper_... panics; called when main program
30 ; does something wrong
32 ; [ms]_<anything else> routines or labels of some other kind
34 ; Whenever flow does not pass past the end of some code, we
35 ; have a boundary `;----------', and when flow passes past
36 ; an important label we sometimes mark it specially with `;...',
41 ; bt_f_if0 st, st_something
45 ; m_event_several_including_spong
46 ; bs_f st, st_sponging
47 ; bra metasyntacticing
52 ;============================================================
53 ; COMMON ADMINISTRATIVE ROUTINES and VARIABLES
59 sspcon2 res 1 ; master only
60 slave res 1 ; master only
64 ; st is a bitmask, bit set in visible states:
66 st_starting equ 7 ; Writing-Setup?,Reading-Busy?
67 st_addressing equ 6 ; Writing-Setup?,Reading-Busy?
68 st_writing equ 5 ; Writing-* [Idle-going-]Receiving
69 st_subsequent equ 4 ; Writing? Receiving
70 st_reading equ 3 ; Reading-* Transmitting
71 st_awaiting equ 2 ; Reading-Wait
72 st_acking equ 1 ; Reading-Busy?,Stopping(from read)
73 st_stopping equ 0 ; Stopping
74 ; ...? means not always set in that state
80 ; computes slave address in form suitable for use in i2c controller
81 ; actual i2c slave address is (slave number) + 0b0001000
82 ; W slave number i2c address * 2
87 ;======================================================================
92 mov_lw 100-1 ; baud rate = Fosc/(4*(SSPADD+1))
93 mov_wf SSPADD ; Fosc=20MHz, so SSPADD==99 means 50kbit/s
95 mov_lw 0x08 ; !SSPEN, Master mode
97 clr_f SSPCON2 ; nothing going
98 mov_lw 0x80 ; SMP(noslew), !CKE(!smbus)
105 ; We have an interrupt:
107 mov_ff SSPSTAT, sspstat
108 mov_ff SSPCON1, sspcon1
109 mov_ff SSPCON2, sspcon2
111 bt_f_if1 sspcon1, WCOL
113 bt_f_if1 sspcon1, SSPOV
116 ; No ? Well, then the I2C should be idle now:
118 and_lw ~0x60 ; ACKSTAT,ACKDT
122 bt_f_if1 sspstat, R_W
125 bt_f_if1 st, st_stopping
126 bra m_event_done_stopping
128 bt_f_if1 st, st_starting
129 bra m_event_done_starting
132 bt_f_if1 st, st_addressing
133 bra m_event_done_addressing
135 bt_f_if1 st, st_writing
136 bra m_event_done_writing
138 bt_f_if1 st, st_acking
139 bra m_event_done_acking
141 bt_f_if1 st, st_reading
142 bra m_event_done_reading
147 ;========================================
148 ; MASTER - STARTING, ADDRESSING, STOPPING
152 ; st checked for busyness correct
153 ; st_reading/writing set unchanged
154 ; st_starting clear set
156 ; slave any slave_number
157 ; expects to return directly to main program (caller)
159 bra_z m_improper_slave
161 bra_nz m_improper_slave
167 m_event_done_starting
171 bt_f_if1 st, st_reading
172 bs_w 0 ; address bottom bit means read
176 bs_f st, st_addressing
180 m_event_done_addressing
181 bt_f_if1 sspcon2, ACKSTAT
182 bra m_bad_address_ack
185 bc_f st, st_addressing
186 bt_f_if1 st, st_reading
187 bra m_event_done_addressing_read
188 bra m_event_done_addressing_write
192 ; st_stopping clear set
193 ; st_reading/acking/writing any unchanged
194 ; expects to return directly to main program or to end interrupt handler
200 m_event_done_stopping
213 ;========================================
219 ; State Idle Writing-Setup
222 bra m_improper_write_start
229 ; Did slave ack our byte ? It had better have done !
230 bt_f_if1 sspcon2, ACKSTAT
233 bs_f st, st_subsequent
236 m_event_done_addressing_write
238 ; st_addressing cleared
239 call i2cmu_write_next_byte
240 bra_z m_event_write_mustfinish
241 ; OK, we have the next byte:
247 m_event_write_mustfinish
248 bt_f_if0 st, st_subsequent
249 bra m_improper_write_finish
254 m_improper_write_start
258 m_improper_write_finish
261 ;========================================
267 ; State Idle Reading-Busy
270 bra m_improper_read_start
276 m_event_done_addressing_read
277 m_event_done_acking_readmore
279 ; st_addressing/acking cleared
291 goto i2cmu_read_got_byte
295 ; State Reading-Wait Reading-Busy
296 bt_f_if0 st, st_awaiting
297 bra m_improper_read_another
298 ; OK, we're fine to read another:
302 ; st_reading 1 iff not done unchanged
303 ; st_awaiting still set cleared
304 ; st_acking clear set
305 ; expects to return directly to main program or to end interrupt handler
308 bc_f SSPCON2, ACKDT ; ACKDT=0 means to acknowledge
314 ; State Reading-Wait Stopping
317 bt_f_if0 st, st_awaiting
318 bra m_improper_read_done
327 bt_f_if1 st, st_reading
328 bra m_event_done_acking_readmore
333 m_improper_read_start
337 m_improper_read_another
344 ;======================================================================
349 ; W slave number undefined
353 mov_lw 0x16 ; !SSPEN, CKP(release), I2C 7-bit slave no-SP-int
355 mov_lw 0x01 ; !GCEN, SEN
357 mov_lw 0x8 ; SMP(noslew), !CKE(!smbus)
360 ; Actually engages the I2C controller, which must already have
361 ; been set up (all but SSPEN):
362 ; SSPADD,SSPCON1,SSPCON2 configured correctly unchanged
363 ; SSPSTAT configured correctly unchanged, except:
364 ; SSPSTAT<SSPEN> 0 (disabled) 1 (enabled)
365 ; SSPIE 0 (disabled) 1 (enabled)
366 ; TRISB<1,0> any configured for I2C
367 ; SSPIP any configured correctly
368 ; GIEL 0 (disabled) 0 (disabled)
369 ; ssp* shadows any all bits set
380 ;========================================
381 ; SLAVE - INTERRUPT HANDLING
383 ; In general, we figure out our state and then see what kind of events
384 ; we were expecting. Bits we want to check:
385 ; 80 60 20 10 08 04 02 01
386 ; SMP CKE D_A P S R_W UA BF
387 ; set clr data? stop start read? clr full?
388 ; (we don't usually mention SMP, CKE and UA below)
392 chkvals_start_sspstat macro
396 chkval macro lastval, value, label
397 xor_lw value ^ lastval
401 chkvals_addrrecv macro lastval
402 chkval lastval, 0x8c, s_event_idle_addrrecvread ; A,!P, S,R,!BF
403 chkval 0x8c, 0x89, s_event_idle_addrrecvwrite ; A,!P, S,W,BF
405 chkvals_addrrecv_lastval equ 0x89
411 ; We have an interrupt:
413 bt_f_if1 sspcon1, WCOL
415 bt_f_if1 sspcon1, SSPOV
418 ; Firstly, clear the interrupt flag so that if something else happens
419 ; while we faff, the interrupt will be regenerated:
422 mov_ff SSPSTAT, sspstat
423 mov_ff SSPCON1, sspcon1
425 bt_f_if0 st, st_reading
428 bt_f_if0 st, st_writing
432 chkvals_start_sspstat
435 panic morse_SS ; slave, interrupt, controller in bad state
437 ;========================================
441 s_event_idle_addrrecvread
443 call i2csu_read_begin
444 bra s_events_reading_datasend
448 chkvals_start_sspstat
449 chkval 0, 0xac, s_event_reading_datasent ; D,!P, S,R,!BF
451 ; Whatever is happening, we're done reading now !
455 chkvals_start_sspstat
456 chkval 0, 0xa8, s_event_reading_datanack ; D,!P, S,!R,!BF
457 ; Or, maybe it was nack and then we were reselected:
458 chkvals_addrrecv 0xa8
463 s_event_reading_datasent
464 call i2csu_read_another
465 s_events_reading_datasend
468 s_event_reading_datanack
471 ;========================================
475 s_event_idle_addrrecvwrite
476 bs_f SSPCON1, 3 ; we'll need the Stop interrupt
478 ; well, this is all fine so far, so do carry on:
481 ; W any byte from master
482 ; i2c controller waiting due to SEN etc continuing with next byte
489 chkvals_start_sspstat
490 chkval 0, 0xa9, s_event_writing_datarecv ; D,!P, S,W,BF
492 ; Well, we're done writing now in any case
494 bc_f SSPCON1, 3 ; no Start and Stop interrupts any more
495 call i2csu_write_done
497 ; Who knows what might have happened. We may have
498 ; missed a number of S and P due to delay between
499 ; clearing SSPIF and SSPM3(s&p-intrs) so we can't be
502 ; First, the nice cases:
503 chkvals_start_sspstat
508 and_lw 0xc7 ; ?D_A, ?P; ?S
509 xor_lw 0x80 ; SMP, !CKE, !R_W, !UA, !BF
517 s_event_writing_datarecv
518 rcall s_write_slurpbyte
520 bt_f_if1 st, st_subsequent
521 goto i2csu_write_another
522 ; not subsequent (yet):
524 bs_f st, st_subsequent
525 goto i2csu_write_begin
527 ;======================================================================