chiark / gitweb /
before reorg for state-based
[trains.git] / detpic / i2clib.asm
1 ;######################################################################
2 ; i2clib.inc - I2C LIBRARY - IMPLEMENTATION
3 ;
4 ; See i2clib.asm for documentation of the interface to this file.
5
6  include /usr/share/gputils/header/p18f458.inc
7  radix dec
8  include ../iwjpictest/insn-aliases.inc
9
10 ;============================================================
11 ; COMMON ADMINISTRATIVE ROUTINES
12
13                 udata_acs
14
15 ssp             res     1
16
17 st              res     1       ; bitmask:
18 st_writing      equ     0
19 st_subsequent   equ     0
20
21                 code
22
23 ;--------------------
24 i2cs_init
25 ;       W               slave number            undefined
26                 rcall   slave2addr2
27                 mov_wf  SSPADD
28                 clr_f   st
29                 mov_lw  0x1e ; !SSPEN, CKP(release), I2C 7-bit slave S&P
30                 mov_wf  SSPCON1
31                 mov_lw  0x01 ; !GCEN, SEN
32                 mov_wf  SSPCON2
33                 mov_lw  0x8 ; SMP(noslew), !CKE, !BF(empty)
34                 mov_wf  SSPSTAT
35                 bs_f    TRISB, 0
36                 bs_f    TRISB, 1
37                 bc_f    IPR1, SSPIP
38                 bs_f    SSPCON1, SSPEN
39                 bs_f    PIE1, SSPIE
40                 return
41
42 ;--------------------
43 i2cs_interrupt
44                 bt_f_if0 PIR1, SSPIF
45                 return
46                 ; We have an interrupt:
47
48 ; Firstly, clear the interrupt flag so that if something else happens
49 ; while we faff, the interrupt will be regenerated:
50                 bc_f    PIR1, SSPIF
51
52 ; Check that nothing obvious is wrong:
53                 mov_fw  SSPCON1
54                 mov_wf  ssp
55                 and_lw  0xc0
56                 bra_nz  i2cs_interrupt_wcolsspov_endif
57                 panic   morse_SV
58 i2cs_interrupt_wcolsspov_endif
59
60 ; Find out what's just happened:
61                 mov_ff  SSPSTAT, ssp
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?
66
67                 mov_fw  ssp
68 chkval_lastvalue equ 0
69
70 chkval macro value, label
71                 xor_lw  value ^ chkval_lastvalue
72  chkval_lastvalue equ value
73                 bra_z   label
74                 endm
75
76                 chkval  0x89, s_case_addr_recv_write
77                 chkval  0x8d, s_case_addr_recv_read
78                 chkval  0xa9, s_case_write_data_recv
79
80                 bt_f_if0 st, st_reading
81                 bra     s_ifnot_reading
82
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
87
88 s_ifnot_reading
89
90 chkvalm macro mask, value, label
91                 mov_fw  ssp
92                 xor_lw  value
93                 bra_z   label
94                 endm
95
96                 chkvalm 0xdf, 0x90, s_case_something_stop
97                 chkvalm 0xdb, 0x88, s_case_uninteresting_start
98
99                 mov_ff  ssp, WREG2 ; fixme
100                 panic   morse_SS
101
102 ;----------
103 s_case_something_stop
104 s_case_something_start
105 s_ensure_idle
106                 mov_fw  st ; were we doing something ?
107                 bt_f_if1 STATUS,Z
108                 return
109                 ; we were, it seems:
110
111                 bc_f    SSPCON, 3
112                 clr_f   st
113                 ; now we're not (but W still has old st)
114
115                 bt_f_if1 WREG, st_writing
116                 goto    i2csu_write_done
117
118                 bt_f_if1 WREG, st_reading
119                 goto    i2csu_read_done
120
121                 mov_wf  st ; put it back and then ...
122
123 s_panic_st_unexpected
124                 panic   morse_ST
125
126 ;----------
127 s_case_addr_recv_write
128                 rcall   s_ensure_idle
129                 bs_f    SSPCON, 3; we'll need the Stop interrupt
130                 bs_f    st, st_writing
131                 ; well, now this is all fine so do carry on:
132
133 s_write_slurpbyte
134 ;       W               any                     byte from master
135 ;       i2c controller  waiting due to SEN etc  continuing with next byte
136                 mov_fw  SSPBUF
137                 bs_f    SSPCON1, CKP
138                 return
139
140 ;----------
141 s_case_write_data_recv
142                 bt_f_if0 st, st_writing
143                 bra     s_panic_st_unexpected
144                 ; ok, we are writing:
145
146                 rcall   s_write_slurpbyte
147
148                 bt_f_if1 st, st_subsequent
149                 goto    i2csu_write_another
150                 ; not subsequent (yet):
151
152                 bs_f    st, st_subsequent
153                 goto    i2csu_write_begin
154
155 ;----------
156 s_case_addr_recv_read
157                 rcall   s_ensure_idle
158                 bs_f    st, st_reading
159                 call    i2csu_read_begin
160                 bra     s_cases_read_data_send
161
162 ;----------
163 s_case_read_data_sent
164                 call    i2csu_read_another
165
166 s_cases_read_data_send
167                 mov_wf  SSPBUF
168                 bs_f    SSPCON1, CKP
169                 return
170
171 ;----------
172 s_case_read_data_nack
173                 rcall   s_ensure_idle
174                 goto    i2csu_read_done
175
176
177 s_cases_write_alliswell
178                 
179
180
181                 bt_f_if1 ssp, I2C_START
182                 bra     si_if_start
183
184 si_if_notstart
185                 ; So it should be stop
186                 mov_fw  ssp
187                 and_lw  0xdf ; ?D_A
188                 xor_lw  0x90 ; SMP, !CKE, P; !S, !R_W, !UA, !BF
189                 bra_nz  si_if_bad
190
191 si_if_start
192                 bt_f_if1 ssp, BF
193                 bra     si_if_bufferfull
194 si_if_bufferempty
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)
199                 mov_fw  ssp
200                 and_lw  0xdf ; ?D_A
201                 xor_lw  0x88 ; SMP, !CKE, !P; S, !R_W, !UA, !BF
202                 bra_nz  si_if_bad
203
204                 ; OK, ignore it
205                 return
206
207
208                 
209
210
211 ;----------
212 s_case_unknown_stop
213 s_case_unknown_start
214                 return
215
216 ;----------
217 s_case_got_write_addr
218                 
219
220                 mov_fw  SSPBUF
221                 and_lw  0xfe
222                 bra_nz  nonzero
223
224                 mov_wf  ssp
225                 
226
227                 mov_fw  SSPSTAT
228                 and_lw  0xe7 ; all except P and S
229
230                 xor_lw  0x80
231                         ; bits which might sensibly be set
232
233 chkval_last equ 0
234 chkval macro value, label
235                 xor_lw  value ^ chkval_last
236                 bra_z   label
237 chkval_last equ value
238                 endm
239                 chkval  0x80 ;     addr  dunno 
240
241                 mov_lw  0x8
242
243
244                 bt_f_if0 DATA_ADDRESS, SSPSTAT
245                 bra     data
246
247 slave2addr
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
251                 add_lw  0b0001000
252                 rlc_w
253                 return
254
255
256
257
258  include i2clib.inc
259  end