chiark / gitweb /
wip; before undo redo i2cs_interrupt
[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 t               res     1
16
17 st              res     1       ; bitmask:
18 st_writing      equ     0
19
20                 code
21
22 ;--------------------
23 i2cs_init
24 ;       W               slave number            undefined
25                 rcall   slave2addr2
26                 mov_wf  SSPADD
27                 clr_f   st
28                 mov_lw  0x1e ; !SSPEN, CKP(release), I2C 7-bit slave S&P
29                 mov_wf  SSPCON1
30                 mov_lw  0x01 ; !GCEN, SEN
31                 mov_wf  SSPCON2
32                 mov_lw  0x8 ; SMP(noslew), !CKE, !BF(empty)
33                 mov_wf  SSPSTAT
34                 bs_f    TRISB, 0
35                 bs_f    TRISB, 1
36                 bc_f    IPR1, SSPIP
37                 bs_f    SSPCON1, SSPEN
38                 bs_f    PIE1, SSPIE
39                 return
40
41 ;--------------------
42 i2cs_interrupt
43                 bt_f_if0 PIR1, SSPIF
44                 return
45
46 ; We have an interrupt.  Firstly, clear the interrupt flag
47 ; so that if something else happens while we faff, the interrupt
48 ; will be regenerated:
49                 bc_f    PIR1, SSPIF
50
51 ; Check that nothing is wrong:
52                 mov_fw  SSPCON1
53                 mov_wf  t
54                 and_lw  0xc0
55                 bra_nz  i2cs_interrupt_wcolsspov_endif
56                 panic   morse_SV
57 i2cs_interrupt_wcolsspov_endif
58
59 ; Find out what's just happened:
60                 mov_ff  SSPSTAT, t
61                         ; bits we want to check
62                         ;  80  60  20    10    08    04    02  01
63                         ;  SMP CKE D_A   P     S     R_W   UA  BF
64                         ;  set clr data? stop  start read? clr full?
65
66                 bt_f_if1 t, I2C_START
67                 bra     si_if_start
68
69 si_if_notstart
70                 ; So it should be stop
71                 mov_fw  t
72                 and_lw  0xdf ; ?D_A
73                 xor_lw  0x90 ; SMP, !CKE, P; !S, !R_W, !UA, !BF
74                 bra_nz  si_if_bad
75
76                 ; Were we receiving ?
77                 bt_f_if0 st, st_writing
78                 return
79
80                 ; Yes, we were receiving:
81                 bc_f    st, st_writing
82                 goto    i2csu_write_done
83                 ; tail call; we couldn't do anything after that
84                 ; anyway since it might well reenter us.
85
86 si_if_start
87                 bt_f_if1 t, BF
88                 bra     si_if_bufferfull
89 si_if_bufferempty
90                 bt_f_if1 t, R_W ;read?
91                 bra     si_if_bufferempty_reading
92 si_if_bufferempty_notreading
93                 ; So we think this is just a START (which we want to ignore)
94                 mov_fw  t
95                 and_lw  0xdf ; ?D_A
96                 xor_lw  0x88 ; SMP, !CKE, !P; S, !R_W, !UA, !BF
97                 bra_nz  si_if_bad
98
99                 ; OK, ignore it
100                 return
101
102
103                 
104
105 chkval macro mask, value, label
106                 mov_fw  t
107  if mask ^ 0xff
108                 and_lw  mask
109  endif
110                 xor_lw  value
111                 bra_z   label
112                 endm
113                         ; bits we want to check
114                         ;  80  60  20    10    08    04    02  01
115                         ;  SMP CKE D_A   P     S     R_W   UA  BF
116                         ;  set clr data? stop  start read? clr full?
117
118                 chkval  0xff, 0x90, s_case_writing_stop
119                 chkval  0xff, 0x89, s_case_addr_recv_write
120                 chkval  0xff, 0x8d, s_case_addr_recv_read
121                 chkval  0xff, 0xa9, s_case_write_data_recv
122                 chkval  0xff, 0xac, s_case_read_data_sent
123                 chkval  0xff, 0xa8, s_case_read_data_nack
124                 chkval  0xdb, 0x90, s_case_unknown_stop
125                 chkval  0xdb, 0x88, s_case_unknown_start
126
127                 mov_ff  t, WREG2 ; fixme
128                 panic   morse_SI
129
130 ;----------
131 s_case_unknown_stop
132 s_case_unknown_start
133                 return
134
135 ;----------
136 s_case_got_write_addr
137                 
138
139                 mov_fw  SSPBUF
140                 and_lw  0xfe
141                 bra_nz  nonzero
142
143                 mov_wf  t
144                 
145
146                 mov_fw  SSPSTAT
147                 and_lw  0xe7 ; all except P and S
148
149                 xor_lw  0x80
150                         ; bits which might sensibly be set
151
152 chkval_last equ 0
153 chkval macro value, label
154                 xor_lw  value ^ chkval_last
155                 bra_z   label
156 chkval_last equ value
157                 endm
158                 chkval  0x80 ;     addr  dunno 
159
160                 mov_lw  0x8
161
162
163                 bt_f_if0 DATA_ADDRESS, SSPSTAT
164                 bra     data
165
166 slave2addr
167 ; computes slave address in form suitable for use in i2c controller
168 ; actual i2c slave address is (slave number) + 0b0001000
169 ;       W               slave number            i2c address * 2
170                 add_lw  0b0001000
171                 rlc_w
172                 return
173
174
175
176
177  include i2clib.inc
178  end