-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathi2c.asm
259 lines (212 loc) · 7 KB
/
i2c.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
; Copyright 2023-2024 Stefan Jakobsson
;
; Redistribution and use in source and binary forms, with or without modification,
; are permitted provided that the following conditions are met:
;
; 1. Redistributions of source code must retain the above copyright notice, this
; list of conditions and the following disclaimer.
;
; 2. Redistributions in binary form must reproduce the above copyright notice,
; this list of conditions and the following disclaimer in the documentation
; and/or other materials provided with the distribution.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
; BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
; THE POSSIBILITY OF SUCH DAMAGE.
; Slave settings
.equ I2C_SLAVE_ADDRESS = 0x42
; USICR - Control Register values
.equ I2C_IDLE = 0b10101000
.equ I2C_ACTIVE = 0b11111000
; USISR - Status register values
.equ I2C_CLEAR_STARTFLAG = 0b10000000
.equ I2C_COUNT_BYTE = 0b01110000
.equ I2C_COUNT_BIT = 0b01111110
;******************************************************************************
; Function...: i2c_main
; Description: I2C main function
; In.........: Nothing
; Out........: Nothing
i2c_main:
; Pin setup
cbi DDRB,I2C_SDA ; SDA as input
sbi DDRB,I2C_CLK ; CLK as output, don't touch!
sbi PORTB,I2C_SDA ; SDA = high, don't touch!
sbi PORTB,I2C_CLK ; CLK = high, don't touch!
; Fallthrough to i2c_reset
;******************************************************************************
; Function...: i2c_reset
; Description: USI control & status register setup, then waits for start/stop
; condition
; In.........: Nothing
; Out........: Nothing
i2c_reset:
; USI control & status register setup
ldi r16, I2C_IDLE
out USICR,r16
ldi r16, I2C_COUNT_BYTE
out USISR,r16
; Wait for start/stop condition
rcall i2c_poll
; i2c_poll is guaranteed not to return here (OVF not active)
;******************************************************************************
; Function...: i2c_start
; Description: Handles I2C start/stop conditions
; In.........: Nothing
; Out........: Nothing
i2c_start:
; Pin setup
cbi DDRB,I2C_SDA ; SDA as input
i2c_start2:
; Wait for CLK low (=start condition) or SDA high (=stop condition)
in r16,PINB
andi r16,(1<<I2C_CLK) | (1<<I2C_SDA)
cpi r16, (1<<I2C_CLK) | (0<<I2C_SDA)
breq i2c_start2
sbrc r16, I2C_CLK
rjmp i2c_reset ; Stop condition
; Fallthrough to i2c_check_address
;******************************************************************************
; Function...: i2c_check_address
; Description: Check address match
; In.........: Nothing
; Out........: Nothing
i2c_check_address:
; Configure to read one byte
ldi r16, I2C_ACTIVE
out USICR, r16
ldi r16, (I2C_CLEAR_STARTFLAG | I2C_COUNT_BYTE)
out USISR, r16
; Wait for I2C overflow condition
rcall i2c_poll
; Get address + R/W bit
in r16, USIDR
mov r17, r16 ; Copy address + R/W to r17
; Compare address
lsr r16
cpi r16, I2C_SLAVE_ADDRESS
brne i2c_reset
; Store DDR bit
mov i2c_ddr, r17
; Clear internal offset/command if master write
sbrs i2c_ddr, 0
clr i2c_command
; Fallthrough to i2c_send_ack
;******************************************************************************
; Function...: i2c_send_ack
; Description: Sends ack bit to master
; In.........: Nothing
; Out........: Nothing
i2c_send_ack:
; Clear Data Register bit 7 to send ACK
cbi USIDR, 7
; Configure to send one bit
sbi DDRB, I2C_SDA
ldi r16, I2C_COUNT_BIT
out USISR, r16
; Wait for I2C overflow condition
rcall i2c_poll
; Select receive or transmit
sbrc i2c_ddr, 0
rjmp i2c_transmit
; Fallthrough to i2c_receive
;******************************************************************************
; Function...: i2c_receive
; Description: Receives one byte sent by the master
; In.........: Nothing
; Out........: Nothing
i2c_receive:
; Configure to read a byte
cbi DDRB, I2C_SDA
ldi r16, I2C_COUNT_BYTE
out USISR, r16
; Wait for I2C overflow condition
rcall i2c_poll
; Get byte from Data Register
in r16, USIDR
; Set command, if not previously set
cpi i2c_command, 0
brne i2c_receive2
mov i2c_command, r16
; Reboot command
cpi i2c_command, 0x82
brne i2c_send_ack
CMD_REBOOT ; Guaranteed not to return
i2c_receive2:
cpi i2c_command, 0x80
brne i2c_receive3
CMD_RECEIVE_PACKET
i2c_receive3:
cpi i2c_command, 0x84
brne i2c_receive4
CMD_REWIND_TARGET_ADDR
i2c_receive4:
clr i2c_command
rjmp i2c_send_ack
;******************************************************************************
; Function...: i2c_transmit
; Description: Transmits one byte to the master
; In.........: Nothing
; Out........: Nothing
i2c_transmit:
; Load default value
ldi r17, 0x00
; Command 0x81 - Commit
cpi i2c_command,0x81
brne i2c_transmit2
CMD_COMMIT
i2c_transmit2:
; Command 0x83 - Get version
cpi i2c_command, 0x83
brne i2c_transmit3
CMD_GET_VERSION
i2c_transmit3:
; Command 0x85 - Read flash
cpi i2c_command, 0x85
brne i2c_transmit4
CMD_READ_FLASH
i2c_transmit4:
; Store value in data register
out USIDR, r17
; Configure to send one byte
sbi DDRB, I2C_SDA
ldi r16, I2C_COUNT_BYTE
out USISR, r16
; Clear command
clr i2c_command
; Wait for I2C overflow condition
rcall i2c_poll
; Configure to read master response (ACK/NACK)
cbi DDRB, I2C_SDA
ldi r16, I2C_COUNT_BIT
out USISR, r16
; Wait for I2C overflow condition
rcall i2c_poll
; Get master response (ACK/NACK)
sbic USIDR, 0
rjmp i2c_reset ; NACK
rjmp i2c_transmit ; ACK
;******************************************************************************
; Function...: i2c_poll
; Description: Polls I2C status flags until start/stop or overflow occurs
; In.........: Nothing
; Out........: Nothing
i2c_poll:
; Overflow flag
sbic USISR, 6
ret
; Start flag
sbis USISR, 7
rjmp i2c_poll
i2c_poll2:
pop r16
pop r16
rjmp i2c_start