Skip to content

Commit 9931dbf

Browse files
committed
repeated start
1 parent 46f0ce2 commit 9931dbf

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

main.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
#include "am1808.h"
44

55
// Shared RAM (control input)
6+
7+
#define I2C_CMD_QUIRK 0x02
8+
69
typedef struct i2c_command {
710
// bit[7:0] status and flags
811
// bit[15:8] write length
@@ -57,6 +60,7 @@ enum {
5760
I2C_STATE_NXT_QUIRK_WIGGLE,
5861
I2C_STATE_RX_BYTE,
5962
I2C_STATE_W_ACK,
63+
I2C_STATE_REP_START,
6064
};
6165

6266
typedef struct i2c_state_struct {
@@ -65,6 +69,7 @@ typedef struct i2c_state_struct {
6569
uint8_t addr;
6670
uint8_t wlen;
6771
uint8_t rlen;
72+
uint8_t flags;
6873

6974
uint8_t state;
7075
uint8_t phase;
@@ -94,8 +99,6 @@ static inline __attribute__((always_inline)) void i2c_hi(uint8_t gpio_bit) {
9499
:: handle_timeout \
95100
)
96101

97-
uint32_t debug_i;
98-
99102
static void handle_i2c(i2c_state_struct *i2c) {
100103
uint8_t state = i2c->state;
101104
uint8_t phase = i2c->phase;
@@ -108,14 +111,15 @@ static void handle_i2c(i2c_state_struct *i2c) {
108111
switch (state) {
109112
case I2C_STATE_IDLE: {
110113
uint32_t flags = SHARED->i2c.flags;
111-
if ((flags & 0xff) != 0xaa) {
114+
if ((flags & 0x81) != 0x01) {
112115
break;
113116
}
114117

115118
i2c->buffer = SHARED->i2c.buffer;
116119
i2c->addr = flags >> 24;
117120
i2c->rlen = flags >> 16;
118121
i2c->wlen = flags >> 8;
122+
i2c->flags = flags;
119123

120124
state = I2C_STATE_START;
121125
phase = 0;
@@ -216,17 +220,31 @@ static void handle_i2c(i2c_state_struct *i2c) {
216220

217221
phase = 0;
218222
if (i2c->wlen == 0) {
219-
// TODO: Normal repeated start
220223
if (state == I2C_STATE_R_ACK_ADDR && i2c->rlen > 0) {
224+
// There is data to be a read, and we just sent the device address.
225+
// We now turn around the bus and get ready for reading.
221226
state = I2C_STATE_RX_BYTE;
222227
work_bit = 7;
223228
work_byte = 0;
224229
goto i2c_state_rx;
230+
} else if (i2c->rlen > 0) {
231+
if (i2c->flags & I2C_CMD_QUIRK) {
232+
// The ultrasonic sensor needs a stoP, an extra clock, and then a Start
233+
state = I2C_STATE_STOP;
234+
goto i2c_state_stop;
235+
} else {
236+
state = I2C_STATE_REP_START;
237+
goto i2c_state_rep_start;
238+
}
225239
} else {
240+
// Empty ping
226241
state = I2C_STATE_STOP;
227242
goto i2c_state_stop;
228243
}
229244
} else {
245+
// There is data to send, either for a "write" type transaction
246+
// or for the initial register number for a "read" type transaction
247+
// before a repeated start (it works the same either way).
230248
i2c->wlen--;
231249
state = I2C_STATE_TX_BYTE;
232250
work_bit = 7;
@@ -252,12 +270,14 @@ static void handle_i2c(i2c_state_struct *i2c) {
252270
phase = 0;
253271
} else {
254272
state = I2C_STATE_IDLE;
255-
SHARED->i2c.flags = 0xaa55;
273+
SHARED->i2c.flags = 0xaa80;
256274
}
257275
}
258276
break;
259277

260278
case I2C_STATE_NXT_QUIRK_WIGGLE:
279+
case I2C_STATE_REP_START:
280+
i2c_state_rep_start:
261281
if (phase == 0) {
262282
i2c_low(scl_bit);
263283
phase = 1;
@@ -333,14 +353,14 @@ static void handle_i2c(i2c_state_struct *i2c) {
333353

334354
if (0) {
335355
handle_nak:
336-
SHARED->i2c.flags = 0x4e55;
356+
SHARED->i2c.flags = 0x4e80;
337357
state = I2C_STATE_IDLE;
338358
}
339359

340360
if (0) {
341361
handle_timeout:
342362
if (--i2c->timeout == 0) {
343-
SHARED->i2c.flags = 0x5455;
363+
SHARED->i2c.flags = 0x5480;
344364
state = I2C_STATE_IDLE;
345365
}
346366
}

0 commit comments

Comments
 (0)