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 ;============================================================
11 ; COMMON ADMINISTRATIVE ROUTINES
25 ; W slave number undefined
29 mov_lw 0x1e ; !SSPEN, CKP(release), I2C 7-bit slave S&P
31 mov_lw 0x01 ; !GCEN, SEN
33 mov_lw 0x8 ; SMP(noslew), !CKE, !BF(empty)
46 ; We have an interrupt:
48 ; Firstly, clear the interrupt flag so that if something else happens
49 ; while we faff, the interrupt will be regenerated:
52 ; Check that nothing obvious is wrong:
56 bra_nz i2cs_interrupt_wcolsspov_endif
58 i2cs_interrupt_wcolsspov_endif
60 ; Find out what's just happened:
62 ; bits we want to check
63 ; 80 60 20 10 08 04 02 01
64 ; SMP CKE D_A P S R_W UA BF
65 ; set clr data? stop start read? clr full?
68 chkval_lastvalue equ 0
70 chkval macro value, label
71 xor_lw value ^ chkval_lastvalue
72 chkval_lastvalue equ value
76 chkval 0x89, s_case_addr_recv_write
77 chkval 0x8d, s_case_addr_recv_read
78 chkval 0xa9, s_case_write_data_recv
80 bt_f_if0 st, st_reading
83 ; only check this if we're reading; otherwise
84 ; this will be handled by s_case_uninteresting_start
85 chkval 0xac, s_case_read_data_sent
86 chkval 0xa8, s_case_read_data_nack
90 chkvalm macro mask, value, label
96 chkvalm 0xdf, 0x90, s_case_something_stop
97 chkvalm 0xdb, 0x88, s_case_uninteresting_start
99 mov_ff ssp, WREG2 ; fixme
103 s_case_something_stop
104 s_case_something_start
106 mov_fw st ; were we doing something ?
113 ; now we're not (but W still has old st)
115 bt_f_if1 WREG, st_writing
116 goto i2csu_write_done
118 bt_f_if1 WREG, st_reading
121 mov_wf st ; put it back and then ...
123 s_panic_st_unexpected
127 s_case_addr_recv_write
129 bs_f SSPCON, 3; we'll need the Stop interrupt
131 ; well, now this is all fine so do carry on:
134 ; W any byte from master
135 ; i2c controller waiting due to SEN etc continuing with next byte
141 s_case_write_data_recv
142 bt_f_if0 st, st_writing
143 bra s_panic_st_unexpected
144 ; ok, we are writing:
146 rcall s_write_slurpbyte
148 bt_f_if1 st, st_subsequent
149 goto i2csu_write_another
150 ; not subsequent (yet):
152 bs_f st, st_subsequent
153 goto i2csu_write_begin
156 s_case_addr_recv_read
159 call i2csu_read_begin
160 bra s_cases_read_data_send
163 s_case_read_data_sent
164 call i2csu_read_another
166 s_cases_read_data_send
172 s_case_read_data_nack
177 s_cases_write_alliswell
181 bt_f_if1 ssp, I2C_START
185 ; So it should be stop
188 xor_lw 0x90 ; SMP, !CKE, P; !S, !R_W, !UA, !BF
195 bt_f_if1 ssp, R_W ;read?
196 bra si_if_bufferempty_reading
197 si_if_bufferempty_notreading
198 ; So we think this is just a START (which we want to ignore)
201 xor_lw 0x88 ; SMP, !CKE, !P; S, !R_W, !UA, !BF
217 s_case_got_write_addr
228 and_lw 0xe7 ; all except P and S
231 ; bits which might sensibly be set
234 chkval macro value, label
235 xor_lw value ^ chkval_last
237 chkval_last equ value
239 chkval 0x80 ; addr dunno
244 bt_f_if0 DATA_ADDRESS, SSPSTAT
248 ; computes slave address in form suitable for use in i2c controller
249 ; actual i2c slave address is (slave number) + 0b0001000
250 ; W slave number i2c address * 2