ACwing Flow bridge firmware
STM32C011: PMW3901 optical flow over SPI, I2C target 0x3B
Loading...
Searching...
No Matches
bridge.c
Go to the documentation of this file.
1
5#include "bridge.h"
6#include "flow_regs.h"
7#include <string.h>
8
9static volatile int32_t s_dx, s_dy; /* accumulated since the last FRAME read */
10static volatile uint32_t s_dt_us;
11static volatile uint8_t s_count, s_squal, s_status;
12static volatile uint16_t s_shutter;
13
14static uint8_t s_ptr, s_first, s_wr;
15static uint8_t s_img[FLOW_REG_SPACE];
16static uint8_t s_rd; /* index in s_img during a read */
17static volatile uint8_t s_ctrl, s_reads;
18
19void bridge_init(void)
20{
21 s_dx = s_dy = 0; s_dt_us = 0;
22 s_count = s_squal = 0; s_status = 0; s_shutter = 0;
23 s_ptr = 0; s_first = 0; s_wr = 0; s_rd = 0; s_ctrl = 0; s_reads = 0;
24}
25
26void bridge_set_sensor_ok(uint8_t ok)
27{
28 if (ok) s_status |= FLOW_S_SENSOR_OK;
29 else s_status &= (uint8_t)~FLOW_S_SENSOR_OK;
30}
31
32void bridge_add_sample(int16_t dx, int16_t dy, uint8_t squal, uint16_t shutter,
33 uint8_t valid, uint32_t dt_us)
34{
35 s_squal = squal;
36 s_shutter = shutter;
37 if (!valid) { s_status |= FLOW_S_REJECTED; return; }
38 s_status &= (uint8_t)~FLOW_S_REJECTED;
39 s_dx += dx;
40 s_dy += dy;
41 s_dt_us += dt_us;
42 s_count++;
44}
45
46static int16_t sat16(int32_t v, uint8_t *ovf)
47{
48 if (v > 32767) { *ovf = 1; return 32767; }
49 if (v < -32768) { *ovf = 1; return -32768; }
50 return (int16_t)v;
51}
52
53static void put16(uint8_t *p, uint16_t v) { p[0] = (uint8_t)v; p[1] = (uint8_t)(v >> 8); }
54
55/* register image; a read starting at FRAME latches and clears the accumulators */
56static void snapshot(uint8_t latch)
57{
58 memset(s_img, 0, sizeof s_img);
61 uint8_t ovf = 0;
62 const int16_t dx = sat16(s_dx, &ovf), dy = sat16(s_dy, &ovf);
63 uint32_t dt = s_dt_us / 100u;
64 if (dt > 0xFFFFu) dt = 0xFFFFu;
65 s_img[FLOW_R_STATUS] = (uint8_t)(s_status | (ovf ? FLOW_S_OVERFLOW : 0u));
67 put16(&s_img[FLOW_R_DX], (uint16_t)dx);
68 put16(&s_img[FLOW_R_DY], (uint16_t)dy);
71 put16(&s_img[FLOW_R_DT], (uint16_t)dt);
72 if (latch) {
73 /* keep the sub-100 us remainder so no time is lost between frames */
74 s_dx = 0; s_dy = 0;
75 s_dt_us -= dt * 100u;
76 if (dt == 0xFFFFu) s_dt_us = 0;
77 s_status &= (uint8_t)~FLOW_S_NEW;
78 s_reads++;
79 }
80}
81
82void bridge_i2c_addr_write(void) { s_first = 1; s_wr = 0; }
83
84void bridge_i2c_rx(uint8_t b)
85{
86 if (s_first) { s_ptr = b; s_first = 0; return; }
87 if (s_ptr == FLOW_R_CTRL) s_ctrl |= b; /* the only writable register */
88 s_ptr++;
89 s_wr++;
90}
91
93{
95 s_rd = s_ptr;
96}
97
98uint8_t bridge_i2c_tx(void)
99{
100 const uint8_t v = (s_rd < FLOW_REG_SPACE) ? s_img[s_rd] : 0xFFu;
101 if (s_rd < 0xFFu) s_rd++;
102 return v;
103}
104
105void bridge_i2c_stop(void) { s_first = 0; }
106
107uint8_t bridge_take_ctrl(void)
108{
109 const uint8_t c = s_ctrl;
110 s_ctrl = 0;
111 return c;
112}
113
114uint8_t bridge_reads(void) { return s_reads; }
void bridge_add_sample(int16_t dx, int16_t dy, uint8_t squal, uint16_t shutter, uint8_t valid, uint32_t dt_us)
one motion burst: deltas since the previous burst, dt_us = time between the two bursts; valid = 0 for...
Definition bridge.c:32
void bridge_i2c_addr_read(void)
address matched, master reads: snapshot
Definition bridge.c:92
static volatile uint8_t s_reads
Definition bridge.c:17
static volatile uint8_t s_squal
Definition bridge.c:11
static void snapshot(uint8_t latch)
Definition bridge.c:56
void bridge_i2c_addr_write(void)
address matched, master writes
Definition bridge.c:82
void bridge_i2c_rx(uint8_t b)
first byte = register pointer
Definition bridge.c:84
static uint8_t s_ptr
Definition bridge.c:14
static volatile uint16_t s_shutter
Definition bridge.c:12
static uint8_t s_img[FLOW_REG_SPACE]
Definition bridge.c:15
void bridge_set_sensor_ok(uint8_t ok)
Definition bridge.c:26
static volatile uint8_t s_count
Definition bridge.c:11
uint8_t bridge_reads(void)
FRAME reads since boot (LED activity), wraps.
Definition bridge.c:114
static uint8_t s_first
Definition bridge.c:14
static volatile uint8_t s_ctrl
Definition bridge.c:17
static uint8_t s_wr
Definition bridge.c:14
void bridge_init(void)
Definition bridge.c:19
uint8_t bridge_take_ctrl(void)
CTRL bits written by the master, cleared.
Definition bridge.c:107
static int16_t sat16(int32_t v, uint8_t *ovf)
Definition bridge.c:46
static volatile int32_t s_dx
Definition bridge.c:9
static void put16(uint8_t *p, uint16_t v)
Definition bridge.c:53
uint8_t bridge_i2c_tx(void)
next byte to send
Definition bridge.c:98
static volatile uint32_t s_dt_us
Definition bridge.c:10
static volatile int32_t s_dy
Definition bridge.c:9
void bridge_i2c_stop(void)
Definition bridge.c:105
static uint8_t s_rd
Definition bridge.c:16
static volatile uint8_t s_status
Definition bridge.c:11
Register file of the flow bridge and the I2C target protocol.
I2C register map of the ACwing Flow bridge (STM32C011 at 0x3B).
#define FLOW_FW_VERSION
1.0
Definition flow_regs.h:32
#define FLOW_WHO_AM_I_VAL
Definition flow_regs.h:31
#define FLOW_S_SENSOR_OK
Definition flow_regs.h:47
#define FLOW_R_COUNT
Definition flow_regs.h:36
#define FLOW_S_REJECTED
Definition flow_regs.h:50
#define FLOW_R_CTRL
Definition flow_regs.h:42
#define FLOW_R_WHO_AM_I
Definition flow_regs.h:33
#define FLOW_R_SHUTTER
Definition flow_regs.h:40
#define FLOW_S_NEW
Definition flow_regs.h:48
#define FLOW_R_DT
Definition flow_regs.h:41
#define FLOW_R_DY
Definition flow_regs.h:38
#define FLOW_R_FRAME
Definition flow_regs.h:43
#define FLOW_REG_SPACE
Definition flow_regs.h:45
#define FLOW_R_SQUAL
Definition flow_regs.h:39
#define FLOW_R_VERSION
Definition flow_regs.h:34
#define FLOW_R_STATUS
Definition flow_regs.h:35
#define FLOW_R_DX
Definition flow_regs.h:37
#define FLOW_S_OVERFLOW
Definition flow_regs.h:49