-
Notifications
You must be signed in to change notification settings - Fork 3
/
i2c.s
170 lines (145 loc) · 3.54 KB
/
i2c.s
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
/* ULP Example: Read temperautre in deep sleep
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
This file contains assembly code which runs on the ULP.
*/
/* ULP assembly files are passed through C preprocessor first, so include directives
and C macros may be used in these files
*/
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"
#include "stack.s"
// RTC_GPIO_6 == GPIO_25
// RTC_GPIO_7 == GPIO_26
// RTC_GPIO_9 == GPIO_32
// RTC_GPIO_8 == GPIO_33
.bss
i2c_started:
.long 0
i2c_didInit:
.long 0
.text
.global i2c_start_cond
.global i2c_stop_cond
.global i2c_write_bit
.global i2c_read_bit
.global i2c_write_byte
.global i2c_read_byte
.macro I2C_delay
wait 5 // if number equ 10 then clock gap is minimal 4.7us // was 50
.endm
.macro read_SCL
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + SCL_PIN, 1)
.endm
.macro read_SDA
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + SDA_PIN, 1)
.endm
.macro set_SCL
WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC_S + SCL_PIN, 1, 1)
.endm
.macro clear_SCL
WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS_S + SCL_PIN, 1, 1)
.endm
.macro set_SDA
WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC_S + SDA_PIN, 1, 1)
.endm
.macro clear_SDA
WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS_S + SDA_PIN, 1, 1)
.endm
i2c_start_cond:
move r1,i2c_didInit
ld r0,r1,0
jumpr didInit,1,ge
move r0,1
st r0,r1,0
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + SCL_PIN, 1, 0)
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + SDA_PIN, 1, 0)
didInit:
move r2,i2c_started
ld r0,r2,0
jumpr not_started,1,lt // if started, do a restart condition
set_SDA // set SDA to 1
I2C_delay
set_SCL
clock_stretch: // TODO: Add timeout
read_SCL
jumpr clock_stretch,1,lt
I2C_delay // Repeated start setup time, minimum 4.7us
not_started:
clear_SDA // SCL is high, set SDA from 1 to 0.
I2C_delay
clear_SCL
move r0,1
st r0,r2,0
ret
i2c_stop_cond:
clear_SDA // set SDA to 0
I2C_delay
set_SCL
clock_stretch_stop:
read_SCL
jumpr clock_stretch_stop,1,lt
I2C_delay // Stop bit setup time, minimum 4us
set_SDA // SCL is high, set SDA from 0 to 1
I2C_delay
move r2,i2c_started
move r0,0
st r0,r2,0
ret
i2c_write_bit: // Write a bit to I2C bus
jumpr bit0,1,lt
set_SDA
jump bit1
bit0:
clear_SDA
bit1:
I2C_delay // SDA change propagation delay
set_SCL
I2C_delay
clock_stretch_write:
read_SCL
jumpr clock_stretch_write,1,lt
clear_SCL
ret
i2c_read_bit: // Read a bit from I2C bus
set_SDA // Let the slave drive data
I2C_delay
set_SCL
clock_stretch_read:
read_SCL
jumpr clock_stretch_read,1,lt
I2C_delay
read_SDA // SCL is high, read out bit
clear_SCL
ret // bit in r0
i2c_write_byte: // Return 0 if ack by the slave.
stage_rst
next_bit:
and r0,r2,0x80
psr
jump i2c_write_bit
lsh r2,r2,1
stage_inc 1
jumps next_bit,8,lt
psr
jump i2c_read_bit
ret
i2c_read_byte: // Read a byte from I2C bus
push r2
move r2,0
stage_rst
next_bit_read:
psr
jump i2c_read_bit
lsh r2,r2,1
or r2,r2,r0
stage_inc 1
jumps next_bit_read,8,lt
pop r0
psr
jump i2c_write_bit
move r0,r2
ret