ACwing Flow bridge firmware
STM32C011: PMW3901 optical flow over SPI, I2C target 0x3B
Loading...
Searching...
No Matches
pmw3901.c
Go to the documentation of this file.
1
12#include "pmw3901.h"
13
14#define PMW_PRODUCT_ID 0x49u
15#define PMW_INV_PRODUCT_ID 0xB6u
16#define PMW_REG_MOTION_BURST 0x16u
17
18static const pmw_bus_t *s_b;
19
20static void wr(uint8_t reg, uint8_t v)
21{
22 s_b->cs(0);
23 s_b->delay_us(50);
24 (void)s_b->xfer((uint8_t)(reg | 0x80u));
25 (void)s_b->xfer(v);
26 s_b->delay_us(50);
27 s_b->cs(1);
28 s_b->delay_us(200);
29}
30
31static uint8_t rd(uint8_t reg)
32{
33 s_b->cs(0);
34 s_b->delay_us(50);
35 (void)s_b->xfer((uint8_t)(reg & 0x7Fu));
36 s_b->delay_us(50);
37 const uint8_t v = s_b->xfer(0);
38 s_b->delay_us(100);
39 s_b->cs(1);
40 s_b->delay_us(20);
41 return v;
42}
43
44static const uint8_t k_init1[][2] = {
45 {0x7F,0x00},{0x61,0xAD},{0x7F,0x03},{0x40,0x00},{0x7F,0x05},{0x41,0xB3},{0x43,0xF1},{0x45,0x14},
46 {0x5B,0x32},{0x5F,0x34},{0x7B,0x08},{0x7F,0x06},{0x44,0x1B},{0x40,0xBF},{0x4E,0x3F},{0x7F,0x08},
47 {0x65,0x20},{0x6A,0x18},{0x7F,0x09},{0x4F,0xAF},{0x5F,0x40},{0x48,0x80},{0x49,0x80},{0x57,0x77},
48 {0x60,0x78},{0x61,0x78},{0x62,0x08},{0x63,0x50},{0x7F,0x0A},{0x45,0x60},{0x7F,0x00},{0x4D,0x11},
49 {0x55,0x80},{0x74,0x1F},{0x75,0x1F},{0x4A,0x78},{0x4B,0x78},{0x44,0x08},{0x45,0x50},{0x64,0xFF},
50 {0x65,0x1F},{0x7F,0x14},{0x65,0x60},{0x66,0x08},{0x63,0x78},{0x7F,0x15},{0x48,0x58},{0x7F,0x07},
51 {0x41,0x0D},{0x43,0x14},{0x4B,0x0E},{0x45,0x0F},{0x44,0x42},{0x4C,0x80},{0x7F,0x10},{0x5B,0x02},
52 {0x7F,0x07},{0x40,0x41},{0x70,0x00}
53};
54static const uint8_t k_init2[][2] = {
55 {0x32,0x44},{0x7F,0x07},{0x40,0x40},{0x7F,0x06},{0x62,0xF0},{0x63,0x00},{0x7F,0x0D},{0x48,0xC0},
56 {0x6F,0xD5},{0x7F,0x00},{0x5B,0xA0},{0x4E,0xA8},{0x5A,0x50},{0x40,0x80}
57};
58
59int pmw_init(const pmw_bus_t *bus)
60{
61 s_b = bus;
62 /* hardware reset, then the SPI port reset (NCS high-low-high) */
63 s_b->cs(1);
64 s_b->reset(0);
65 s_b->delay_us(1000);
66 s_b->reset(1);
67 s_b->delay_us(50000);
68 s_b->cs(0);
69 s_b->delay_us(1000);
70 s_b->cs(1);
71 s_b->delay_us(1000);
72
73 wr(0x3A, 0x5A); /* power-up reset */
74 s_b->delay_us(5000);
75 if (rd(0x00) != PMW_PRODUCT_ID || rd(0x5F) != PMW_INV_PRODUCT_ID) return -1;
76 for (uint8_t r = 0x02; r <= 0x06; ++r) (void)rd(r); /* clear the motion registers */
77 s_b->delay_us(1000);
78
79 for (unsigned i = 0; i < sizeof k_init1 / sizeof k_init1[0]; ++i) wr(k_init1[i][0], k_init1[i][1]);
80 s_b->delay_us(100000);
81 for (unsigned i = 0; i < sizeof k_init2 / sizeof k_init2[0]; ++i) wr(k_init2[i][0], k_init2[i][1]);
82 return 0;
83}
84
86{
87 uint8_t r[12];
88 s_b->cs(0);
89 s_b->delay_us(50);
91 s_b->delay_us(50); /* tSRAD-MOTBR >= 35 us */
92 for (int i = 0; i < 12; ++i) r[i] = s_b->xfer(0);
93 s_b->cs(1);
94 s_b->delay_us(20);
95 b->motion = r[0];
96 b->observation = r[1];
97 b->dx = (int16_t)((uint16_t)r[2] | ((uint16_t)r[3] << 8));
98 b->dy = (int16_t)((uint16_t)r[4] | ((uint16_t)r[5] << 8));
99 b->squal = r[6];
100 b->raw_sum = r[7];
101 b->raw_max = r[8];
102 b->raw_min = r[9];
103 b->shutter = (uint16_t)(((uint16_t)r[10] << 8) | r[11]);
104}
105
106uint8_t pmw_valid(const pmw_burst_t *b)
107{
108 return (uint8_t)!(b->squal < 0x19u && (b->shutter >> 8) == 0x1Fu);
109}
static const uint8_t k_init2[][2]
Definition pmw3901.c:54
int pmw_init(const pmw_bus_t *bus)
0 = product id ok, configured
Definition pmw3901.c:59
static const uint8_t k_init1[][2]
Definition pmw3901.c:44
#define PMW_PRODUCT_ID
Definition pmw3901.c:14
#define PMW_REG_MOTION_BURST
Definition pmw3901.c:16
uint8_t pmw_valid(const pmw_burst_t *b)
PixArt rule: SQUAL < 0x19 with the shutter at its maximum = no usable features.
Definition pmw3901.c:106
static void wr(uint8_t reg, uint8_t v)
Definition pmw3901.c:20
void pmw_burst(pmw_burst_t *b)
motion burst (register 0x16)
Definition pmw3901.c:85
static const pmw_bus_t * s_b
Definition pmw3901.c:18
static uint8_t rd(uint8_t reg)
Definition pmw3901.c:31
#define PMW_INV_PRODUCT_ID
Definition pmw3901.c:15
PixArt PMW3901MB optical flow sensor over SPI (mode 3, <= 2 MHz).
uint8_t observation
Definition pmw3901.h:21
uint8_t raw_min
Definition pmw3901.h:23
uint16_t shutter
Definition pmw3901.h:24
int16_t dx
Definition pmw3901.h:22
uint8_t raw_sum
Definition pmw3901.h:23
uint8_t squal
Definition pmw3901.h:23
uint8_t raw_max
Definition pmw3901.h:23
uint8_t motion
Definition pmw3901.h:21
int16_t dy
Definition pmw3901.h:22
uint8_t(* xfer)(uint8_t b)
one SPI byte, full duplex
Definition pmw3901.h:14
void(* reset)(uint8_t level)
NRESET: 0 = in reset
Definition pmw3901.h:16
void(* cs)(uint8_t level)
NCS: 0 = selected
Definition pmw3901.h:15
void(* delay_us)(uint32_t us)
Definition pmw3901.h:17