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
12int
13lws_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
31void
32lws_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
47int
48lws_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
73int
74lws_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
94void
95lws_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