• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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