Merge pull request #10558 from iNavFlight/MrD_Correct-comments-on-OSD-symbols
[inav.git] / src / main / drivers / bus_i2c_soft.c
blob5c7d866970e097f74b6cf5ab39f9da47dfdf9690
1 /*
2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdbool.h>
19 #include <stdint.h>
21 #include <platform.h>
23 #include "build/build_config.h"
25 #include "drivers/bus_i2c.h"
26 #include "drivers/time.h"
27 #include "drivers/io.h"
29 // Software I2C driver, using same pins as hardware I2C, with hw i2c module disabled.
30 // Can be configured for I2C2 pinout (SCL: PB10, SDA: PB11) or I2C1 pinout (SCL: PB6, SDA: PB7)
32 #ifdef SOFT_I2C
34 static IO_t scl;
35 static IO_t sda;
36 static volatile uint16_t i2cErrorCount = 0;
38 #define SCL_H IOHi(scl)
39 #define SCL_L IOLo(scl)
41 #define SDA_H IOHi(sda)
42 #define SDA_L IOLo(sda)
44 #define SCL_read IORead(scl)
45 #define SDA_read IORead(sda)
47 #if !defined(SOFT_I2C_SCL) || !defined(SOFT_I2C_SDA)
48 #error "Must define the software i2c pins (SOFT_I2C_SCL and SOFT_I2C_SDA) in target.h"
49 #endif
51 static uint32_t delayTicks = 90;
53 void i2cSetSpeed(uint8_t speed)
55 switch (speed) {
56 case I2C_SPEED_100KHZ:
57 delayTicks = SystemCoreClock / 100000 / 2;
58 break;
60 case I2C_SPEED_200KHZ:
61 delayTicks = SystemCoreClock / 200000 / 2;
62 break;
64 case I2C_SPEED_400KHZ:
65 delayTicks = SystemCoreClock / 400000 / 2;
66 break;
68 case I2C_SPEED_800KHZ:
69 delayTicks = SystemCoreClock / 800000 / 2;
70 break;
74 static void I2C_delay(void)
76 uint32_t now = ticks();
77 while ((ticks() - now) < delayTicks) {
82 static bool I2C_Start(void)
84 SDA_H;
85 SCL_H;
86 I2C_delay();
87 if (!SDA_read) {
88 return false;
90 SDA_L;
91 I2C_delay();
92 if (SDA_read) {
93 return false;
95 SCL_L;
96 I2C_delay();
97 return true;
100 static void I2C_Stop(void)
102 SCL_L;
103 I2C_delay();
104 SDA_L;
105 I2C_delay();
106 SCL_H;
107 I2C_delay();
108 SDA_H;
109 I2C_delay();
112 static void I2C_Ack(void)
114 SCL_L;
115 I2C_delay();
116 SDA_L;
117 I2C_delay();
118 SCL_H;
119 I2C_delay();
120 SCL_L;
121 I2C_delay();
124 static void I2C_NoAck(void)
126 SCL_L;
127 I2C_delay();
128 SDA_H;
129 I2C_delay();
130 SCL_H;
131 I2C_delay();
132 SCL_L;
133 I2C_delay();
136 static bool I2C_WaitAck(void)
138 SCL_L;
139 I2C_delay();
140 SDA_H;
141 I2C_delay();
142 SCL_H;
143 I2C_delay();
144 if (SDA_read) {
145 SCL_L;
146 return false;
148 SCL_L;
149 return true;
152 static void I2C_SendByte(uint8_t byte)
154 uint8_t i = 8;
155 while (i--) {
156 SCL_L;
157 I2C_delay();
158 if (byte & 0x80) {
159 SDA_H;
161 else {
162 SDA_L;
164 byte <<= 1;
165 I2C_delay();
166 SCL_H;
167 I2C_delay();
169 SCL_L;
172 static uint8_t I2C_ReceiveByte(void)
174 uint8_t i = 8;
175 uint8_t byte = 0;
177 SDA_H;
178 while (i--) {
179 byte <<= 1;
180 SCL_L;
181 I2C_delay();
182 SCL_H;
183 I2C_delay();
184 if (SDA_read) {
185 byte |= 0x01;
188 SCL_L;
189 return byte;
192 void i2cInit(I2CDevice device)
194 UNUSED(device);
196 scl = IOGetByTag(IO_TAG(SOFT_I2C_SCL));
197 sda = IOGetByTag(IO_TAG(SOFT_I2C_SDA));
199 IOConfigGPIOAF(scl, IOCFG_OUT_OD, 0);
200 IOConfigGPIOAF(sda, IOCFG_OUT_OD, 0);
203 bool i2cWriteBuffer(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t len, const uint8_t * data, bool allowRawAccess)
205 UNUSED(device);
207 int i;
208 if (!I2C_Start()) {
209 i2cErrorCount++;
210 return false;
212 I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
213 if (!I2C_WaitAck()) {
214 I2C_Stop();
215 return false;
217 if (!allowRawAccess || reg != 0xFF) {
218 I2C_SendByte(reg);
219 I2C_WaitAck();
221 for (i = 0; i < len; i++) {
222 I2C_SendByte(data[i]);
223 if (!I2C_WaitAck()) {
224 I2C_Stop();
225 i2cErrorCount++;
226 return false;
229 I2C_Stop();
230 return true;
233 bool i2cWrite(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t data, bool allowRawAccess)
235 UNUSED(device);
237 if (!I2C_Start()) {
238 return false;
240 I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
241 if (!I2C_WaitAck()) {
242 I2C_Stop();
243 i2cErrorCount++;
244 return false;
246 if (!allowRawAccess || reg != 0xFF) {
247 I2C_SendByte(reg);
248 I2C_WaitAck();
250 I2C_SendByte(data);
251 I2C_WaitAck();
252 I2C_Stop();
253 return true;
256 bool i2cRead(I2CDevice device, uint8_t addr, uint8_t reg, uint8_t len, uint8_t *buf, bool allowRawAccess)
258 UNUSED(device);
260 if (!I2C_Start()) {
261 return false;
264 if (!allowRawAccess || reg != 0xFF) {
265 I2C_SendByte(addr << 1 | I2C_Direction_Transmitter);
266 if (!I2C_WaitAck()) {
267 I2C_Stop();
268 i2cErrorCount++;
269 return false;
271 I2C_SendByte(reg);
272 I2C_WaitAck();
273 I2C_Start();
276 I2C_SendByte(addr << 1 | I2C_Direction_Receiver);
277 I2C_WaitAck();
278 while (len) {
279 *buf = I2C_ReceiveByte();
280 if (len == 1) {
281 I2C_NoAck();
283 else {
284 I2C_Ack();
286 buf++;
287 len--;
289 I2C_Stop();
290 return true;
293 uint16_t i2cGetErrorCounter(void)
295 return i2cErrorCount;
298 #endif