4 * This file is part of BeRTOS.
6 * Bertos is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * As a special exception, you may use this file as part of a free software
21 * library without restriction. Specifically, if other files instantiate
22 * templates or use macros or inline functions from this file, or you compile
23 * this file and link it with other files to produce an executable, this
24 * file does not by itself cause the resulting executable to be covered by
25 * the GNU General Public License. This exception does not however
26 * invalidate any other reasons why the executable file might be covered by
27 * the GNU General Public License.
29 * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
33 * \brief I2C bitbang driver (implementation)
35 * \author Francesco Sacchi <batt@develer.com>
36 * \author Daniele Basile <asterix@develer.com>
39 #include "hw/hw_i2c_bitbang.h"
41 #include "cfg/cfg_i2c.h"
43 #define LOG_LEVEL I2C_LOG_LEVEL
44 #define LOG_FORMAT I2C_LOG_FORMAT
47 #include <cfg/macros.h>
48 #include <cfg/module.h>
50 #include <drv/timer.h>
57 #if !CONFIG_I2C_DISABLE_OLD_API
59 INLINE bool i2c_bitbang_start(void)
70 void i2c_bitbang_stop(void)
78 bool i2c_bitbang_put(uint8_t _data)
81 uint16_t data = (_data << 1) | 1;
83 for (uint16_t i = 0x100; i != 0; i >>= 1)
102 bool i2c_bitbang_start_w(uint8_t id)
106 * Loop on the select write sequence: when the device is busy
107 * writing previously sent data it will reply to the SLA_W
108 * control byte with a NACK. In this case, we must
109 * keep trying until the deveice responds with an ACK.
111 ticks_t start = timer_clock();
112 while (i2c_bitbang_start())
114 if (i2c_bitbang_put(id))
116 else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
118 LOG_ERR("Timeout on I2C start write\n");
121 //LOG_INFO("Rep start\n");
127 bool i2c_bitbang_start_r(uint8_t id)
130 if (i2c_bitbang_start())
132 if (i2c_bitbang_put(id))
135 LOG_ERR("NACK on I2c start read\n");
141 int i2c_bitbang_get(bool ack)
144 for (uint8_t i = 0x80; i != 0; i >>= 1)
168 /* avoid sign extension */
169 return (int)(uint8_t)data;
172 #endif /* !CONFIG_I2C_DISABLE_OLD_API */
177 static bool old_api = false;
178 #define I2C_DEV(i2c) ((int)((i2c)->hw))
180 static void i2c_bitbang_stop_1(struct I2c *i2c)
191 i2c_sdaLo(I2C_DEV(i2c));
192 i2c_sclHi(I2C_DEV(i2c));
193 i2c_halfbitDelay(I2C_DEV(i2c));
194 i2c_sdaHi(I2C_DEV(i2c));
198 INLINE bool i2c_bitbang_start_1(struct I2c *i2c)
201 /* Clear all error, we restart */
202 i2c->errors &= ~(I2C_NO_ACK | I2C_ARB_LOST);
216 i2c_sdaHi(I2C_DEV(i2c));
217 i2c_sclHi(I2C_DEV(i2c));
218 i2c_halfbitDelay(I2C_DEV(i2c));
219 i2c_sdaLo(I2C_DEV(i2c));
220 i2c_halfbitDelay(I2C_DEV(i2c));
222 ret = !i2c_sdaIn(I2C_DEV(i2c));
229 static uint8_t i2c_bitbang_getc(struct I2c *i2c)
234 for (uint8_t i = 0x80; i != 0; i >>= 1)
248 /* Generate ACK/NACK */
249 if (i2c->xfer_size > 1)
262 for (uint8_t i = 0x80; i != 0; i >>= 1)
264 i2c_sclLo(I2C_DEV(i2c));
265 i2c_halfbitDelay(I2C_DEV(i2c));
266 i2c_sclHi(I2C_DEV(i2c));
267 if (i2c_sdaIn(I2C_DEV(i2c)))
272 i2c_halfbitDelay(I2C_DEV(i2c));
274 i2c_sclLo(I2C_DEV(i2c));
276 /* Generate ACK/NACK */
277 if (i2c->xfer_size > 1)
278 i2c_sdaLo(I2C_DEV(i2c));
280 i2c_sdaHi(I2C_DEV(i2c));
282 i2c_halfbitDelay(I2C_DEV(i2c));
283 i2c_sclHi(I2C_DEV(i2c));
284 i2c_halfbitDelay(I2C_DEV(i2c));
285 i2c_sclLo(I2C_DEV(i2c));
286 i2c_sdaHi(I2C_DEV(i2c));
289 /* Generate stop condition (if requested) */
290 if ((i2c->xfer_size == 1) && (i2c->flags & I2C_STOP))
291 i2c_bitbang_stop_1(i2c);
296 INLINE void i2c_bitbang_putcStop(struct I2c *i2c, uint8_t _data, bool stop)
299 uint16_t data = (_data << 1) | 1;
304 for (uint16_t i = 0x100; i != 0; i >>= 1)
323 for (uint16_t i = 0x100; i != 0; i >>= 1)
325 i2c_sclLo(I2C_DEV(i2c));
327 i2c_sdaHi(I2C_DEV(i2c));
329 i2c_sdaLo(I2C_DEV(i2c));
330 i2c_halfbitDelay(I2C_DEV(i2c));
332 i2c_sclHi(I2C_DEV(i2c));
333 i2c_halfbitDelay(I2C_DEV(i2c));
335 ack = !i2c_sdaIn(I2C_DEV(i2c));
337 i2c_sclLo(I2C_DEV(i2c));
338 i2c_halfbitDelay(I2C_DEV(i2c));
342 i2c->errors |= I2C_NO_ACK;
344 /* Generate stop condition (if requested) */
345 if (stop || i2c->errors)
346 i2c_bitbang_stop_1(i2c);
349 static void i2c_bitbang_putc(struct I2c *i2c, uint8_t data)
351 i2c_bitbang_putcStop(i2c, data,
352 (i2c->xfer_size == 1) && (i2c->flags & I2C_STOP));
355 static void i2c_bitbang_start_2(struct I2c *i2c, uint16_t slave_addr)
357 if (i2c->flags & I2C_START_R)
358 slave_addr |= I2C_READBIT;
360 slave_addr &= ~I2C_READBIT;
363 * Loop on the select write sequence: when the device is busy
364 * writing previously sent data it will reply to the SLA_W
365 * control byte with a NACK. In this case, we must
366 * keep trying until the device responds with an ACK.
368 ticks_t start = timer_clock();
369 while (i2c_bitbang_start_1(i2c))
371 i2c_bitbang_putcStop(i2c, slave_addr, false);
373 if (!(i2c->errors & I2C_NO_ACK))
375 else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
377 LOG_ERR("Timeout on I2C start\n");
378 i2c->errors |= I2C_START_TIMEOUT;
379 i2c_bitbang_stop_1(i2c);
384 LOG_ERR("START arbitration lost\n");
385 i2c->errors |= I2C_ARB_LOST;
386 i2c_bitbang_stop_1(i2c);
391 static const I2cVT i2c_bitbang_vt =
393 .start = i2c_bitbang_start_2,
394 .getc = i2c_bitbang_getc,
395 .putc = i2c_bitbang_putc,
396 .write = i2c_genericWrite,
397 .read = i2c_genericRead,
402 * Initialize i2c module.
404 void i2c_hw_bitbangInit(I2c *i2c, int dev)
407 if (dev == I2C_BITBANG_OLD)
410 i2c->hw = (struct I2cHardware *)(dev - I2C_BITBANG0);
412 i2c->vt = &i2c_bitbang_vt;
422 i2c_bitbangInit(I2C_DEV(i2c));
423 i2c_sdaHi(I2C_DEV(i2c));
424 i2c_sclHi(I2C_DEV(i2c));