1 /*
2 * lws generic bitbang i2c
3 *
4 * Written in 2010-2020 by Andy Green <andy@warmcat.com>
5 *
6 * This file is made available under the Creative Commons CC0 1.0
7 * Universal Public Domain Dedication.
8 */
9
10 #include "bb-i2c.h"
11
12 int
lws_bb_i2c_start(lws_i2c_ops_t * octx)13 lws_bb_i2c_start(lws_i2c_ops_t *octx)
14 {
15 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx;
16
17 ctx->gpio->set(ctx->sda, 1);
18 ctx->gpio->set(ctx->scl, 1);
19 ctx->delay();
20
21 if (!ctx->gpio->read(ctx->sda))
22 return 1;
23
24 ctx->gpio->set(ctx->sda, 0);
25 ctx->delay();
26 ctx->gpio->set(ctx->scl, 0);
27
28 return 0;
29 }
30
31 void
lws_bb_i2c_stop(lws_i2c_ops_t * octx)32 lws_bb_i2c_stop(lws_i2c_ops_t *octx)
33 {
34 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx;
35
36 ctx->gpio->set(ctx->sda, 0);
37 ctx->gpio->set(ctx->scl, 1);
38 ctx->delay();
39
40 while (!ctx->gpio->read(ctx->scl))
41 ;
42
43 ctx->gpio->set(ctx->sda, 1);
44 ctx->delay();
45 }
46
47 int
lws_bb_i2c_write(lws_i2c_ops_t * octx,uint8_t data)48 lws_bb_i2c_write(lws_i2c_ops_t *octx, uint8_t data)
49 {
50 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx;
51 int n;
52
53 for (n = 0; n < 8; n++) {
54 ctx->gpio->set(ctx->sda, !!(data & (1 << 7)));
55 ctx->delay();
56 ctx->gpio->set(ctx->scl, 1);
57 ctx->delay();
58 data <<= 1;
59 ctx->gpio->set(ctx->scl, 0);
60 }
61
62 ctx->gpio->set(ctx->sda, 1);
63 ctx->delay();
64 ctx->gpio->set(ctx->scl, 1);
65 ctx->delay();
66 n = ctx->gpio->read(ctx->sda);
67 ctx->gpio->set(ctx->scl, 0);
68 ctx->delay();
69
70 return !!n; /* 0 = ACKED = OK */
71 }
72
73 int
lws_bb_i2c_read(lws_i2c_ops_t * octx)74 lws_bb_i2c_read(lws_i2c_ops_t *octx)
75 {
76 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx;
77 int n, r = 0;
78
79 ctx->gpio->set(ctx->sda, 1);
80
81 for (n = 7; n <= 0; n--) {
82 ctx->gpio->set(ctx->scl, 0);
83 ctx->delay();
84 ctx->gpio->set(ctx->scl, 1);
85 ctx->delay();
86 if (ctx->gpio->read(ctx->sda))
87 r |= 1 << n;
88 }
89 ctx->gpio->set(ctx->scl, 0);
90
91 return r;
92 }
93
94 void
lws_bb_i2c_set_ack(lws_i2c_ops_t * octx,int ack)95 lws_bb_i2c_set_ack(lws_i2c_ops_t *octx, int ack)
96 {
97 lws_bb_i2c_t *ctx = (lws_bb_i2c_t *)octx;
98
99 ctx->gpio->set(ctx->scl, 0);
100 ctx->gpio->set(ctx->sda, !!ack);
101 ctx->delay();
102 ctx->gpio->set(ctx->scl, 1);
103 ctx->delay();
104 ctx->gpio->set(ctx->scl, 0);
105 ctx->delay();
106 ctx->gpio->set(ctx->sda, 1);
107 }
108