Skip to content

Commit b4937e9

Browse files
committed
Move uart sensor data into a struct
By doing so you could theoretically now have multiple uart sensors working at the same time.
1 parent c3ef1db commit b4937e9

File tree

3 files changed

+121
-114
lines changed

3 files changed

+121
-114
lines changed

src/Primitives/Mindstorms/uart_sensor.cpp

Lines changed: 85 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -3,69 +3,52 @@
33
#include <cstdio>
44
#include <zephyr/drivers/uart.h>
55

6-
static const struct device *const uart_dev =
7-
DEVICE_DT_GET(DT_PROP(DT_PATH(zephyr_user), warduino_uarts));
8-
9-
// Variables used for setting up the sensor.
10-
int payload_bytes = 0;
11-
int payload_index = 0;
12-
unsigned int current_payload = 0;
13-
unsigned char checksum;
14-
bool data_byte = false;
15-
16-
// Variables that are used during setup but also by the heartbeat function.
17-
int baudrate = -1;
18-
uint8_t mode = 0;
19-
volatile int sensor_value = 0;
20-
21-
volatile uint32_t receive_state = ReceiveState::advertise;
22-
bool baudrate_configured = false;
23-
24-
void serial_cb([[maybe_unused]] const struct device *dev, [[maybe_unused]] void *user_data) {
6+
void serial_cb(const struct device *dev, void *user_data) {
7+
auto *sensor = static_cast<UartSensor*>(user_data);
258
uint8_t data;
269

27-
if (!uart_irq_update(uart_dev)) {
10+
if (!uart_irq_update(dev)) {
2811
return;
2912
}
3013

31-
if (!uart_irq_rx_ready(uart_dev)) {
14+
if (!uart_irq_rx_ready(dev)) {
3215
return;
3316
}
3417

35-
while (uart_fifo_read(uart_dev, &data, 1) == 1) {
36-
if (receive_state == ReceiveState::data) {
37-
if (data_byte) {
38-
sensor_value = data;
39-
data_byte = false;
18+
while (uart_fifo_read(dev, &data, 1) == 1) {
19+
if (sensor->receive_state == ReceiveState::data) {
20+
if (sensor->data_byte) {
21+
sensor->sensor_value = data;
22+
sensor->data_byte = false;
4023
}
4124
// Check if it's a data message. This indicates the byte after this
4225
// will contain data.
4326
else if (data >> 6 == 0b11) {
4427
// Next byte will be data
45-
data_byte = true;
28+
sensor->data_byte = true;
4629
}
4730
continue;
4831
}
4932

50-
if (payload_bytes > 0) {
51-
payload_bytes--;
33+
if (sensor->payload_bytes > 0) {
34+
sensor->payload_bytes--;
5235

53-
if (payload_bytes > 1) {
54-
if (receive_state == ReceiveState::final_mode_format && payload_bytes == 5 && data != 0x80) {
55-
receive_state = ReceiveState::advertise;
56-
payload_bytes = 0;
36+
if (sensor->payload_bytes > 1) {
37+
if (sensor->receive_state == ReceiveState::final_mode_format && sensor->payload_bytes == 5 && data != 0x80) {
38+
sensor->receive_state = ReceiveState::advertise;
39+
sensor->payload_bytes = 0;
5740
}
58-
checksum ^= data;
59-
current_payload = current_payload |
60-
(((unsigned long)data) << payload_index * 8);
61-
payload_index++;
62-
} else if (checksum == data) {
63-
if (receive_state == ReceiveState::advertise) {
64-
printf("Baudrate = %d\n", current_payload);
65-
baudrate = (int) current_payload;
41+
sensor->checksum ^= data;
42+
sensor->current_payload = sensor->current_payload |
43+
(((unsigned long)data) << sensor->payload_index * 8);
44+
sensor->payload_index++;
45+
} else if (sensor->checksum == data) {
46+
if (sensor->receive_state == ReceiveState::advertise) {
47+
printf("Baudrate = %d\n", sensor->current_payload);
48+
sensor->baudrate = (int) sensor->current_payload;
6649
}
67-
else if (receive_state == ReceiveState::final_mode_format){
68-
receive_state = ReceiveState::modes_complete;
50+
else if (sensor->receive_state == ReceiveState::final_mode_format){
51+
sensor->receive_state = ReceiveState::modes_complete;
6952
}
7053
}
7154
}
@@ -75,10 +58,10 @@ void serial_cb([[maybe_unused]] const struct device *dev, [[maybe_unused]] void
7558
// If we receive an ACK after the final format message and we
7659
// know which speed to communicate at then we should send an ACK to
7760
// switch to data mode.
78-
if (receive_state == ReceiveState::modes_complete && baudrate > 0) {
61+
if (sensor->receive_state == ReceiveState::modes_complete && sensor->baudrate > 0) {
7962
printf("Completing pairing sequence\n");
80-
uart_poll_out(uart_dev, 0b00000100); // Send ACK back
81-
receive_state = ReceiveState::data;
63+
uart_poll_out(dev, 0b00000100); // Send ACK back
64+
sensor->receive_state = ReceiveState::data;
8265
}
8366
}
8467

@@ -87,98 +70,96 @@ void serial_cb([[maybe_unused]] const struct device *dev, [[maybe_unused]] void
8770
uint8_t sensor_mode = data & 0b111;
8871
printf("FORMAT for mode %d\n", sensor_mode);
8972
if (sensor_mode == 0) {
90-
receive_state = ReceiveState::final_mode_format;
91-
payload_bytes = 6;
92-
payload_index = 0;
93-
current_payload = 0;
94-
checksum = 0xff ^ data;
73+
sensor->receive_state = ReceiveState::final_mode_format;
74+
sensor->payload_bytes = 6;
75+
sensor->payload_index = 0;
76+
sensor->current_payload = 0;
77+
sensor->checksum = 0xff ^ data;
9578
}
9679
}
9780

9881
// Handle speed command.
9982
if (data == 0b01010010) {
100-
payload_bytes = 5;
101-
payload_index = 0;
102-
current_payload = 0;
103-
checksum = 0xff ^ 0b01010010;
83+
sensor->payload_bytes = 5;
84+
sensor->payload_index = 0;
85+
sensor->current_payload = 0;
86+
sensor->checksum = 0xff ^ 0b01010010;
10487
}
10588
}
10689
}
10790

108-
void set_sensor_mode(uint8_t new_mode) {
109-
uart_poll_out(uart_dev, 0x43);
110-
uart_poll_out(uart_dev, new_mode);
111-
uart_poll_out(uart_dev, 0xff ^ 0x43 ^ new_mode);
91+
void set_sensor_mode(UartSensor *sensor, uint8_t new_mode) {
92+
uart_poll_out(sensor->dev, 0x43);
93+
uart_poll_out(sensor->dev, new_mode);
94+
uart_poll_out(sensor->dev, 0xff ^ 0x43 ^ new_mode);
11295

11396
// Invalidate current sensor values. This prevents the program reading values that it normally cannot read in a
11497
// particular mode.
115-
sensor_value = -1;
98+
sensor->sensor_value = -1;
11699
}
117100

118-
void uartHeartbeat() {
119-
if (receive_state != ReceiveState::data) {
101+
bool configure_uart_sensor(UartSensor *sensor, uint8_t new_mode) {
102+
if (!sensor_ready(sensor)) {
103+
printf("Input port is not ready!\n");
104+
return false;
105+
}
106+
107+
printf("Setting up uart\n");
108+
int ret = uart_irq_callback_user_data_set(sensor->dev, serial_cb, sensor);
109+
if (ret < 0) {
110+
if (ret == -ENOTSUP) {
111+
printf("Interrupt-driven UART API support not enabled\n");
112+
} else if (ret == -ENOSYS) {
113+
printf("UART device does not support interrupt-driven API\n");
114+
} else {
115+
printf("Error setting UART callback: %d\n", ret);
116+
}
117+
return false;
118+
}
119+
uart_irq_rx_enable(sensor->dev);
120+
if (sensor->receive_state == ReceiveState::data && sensor->mode != new_mode) {
121+
set_sensor_mode(sensor, new_mode);
122+
}
123+
sensor->mode = new_mode;
124+
return true;
125+
}
126+
127+
void uartHeartbeat(UartSensor *sensor) {
128+
if (sensor->receive_state != ReceiveState::data) {
120129
return;
121130
}
122131

123-
if (!baudrate_configured) {
124-
printf("Changing baudrate to %d\n", baudrate);
132+
if (!sensor->baudrate_configured) {
133+
printf("Changing baudrate to %d\n", sensor->baudrate);
125134
uart_config cfg{};
126-
uart_config_get(uart_dev, &cfg);
127-
cfg.baudrate = baudrate;
135+
uart_config_get(sensor->dev, &cfg);
136+
cfg.baudrate = sensor->baudrate;
128137

129-
int config_err = uart_configure(uart_dev, &cfg);
138+
int config_err = uart_configure(sensor->dev, &cfg);
130139
printf("config_err = %d\n", config_err);
131140
if (config_err) {
132141
printf("UART configure error %d", config_err);
133142
}
134143

135-
config_err = uart_config_get(uart_dev, &cfg);
144+
config_err = uart_config_get(sensor->dev, &cfg);
136145
printf("current baudrate after config change = %d\n", cfg.baudrate);
137146
printf("config_err = %d\n", config_err);
138-
baudrate_configured = true;
147+
sensor->baudrate_configured = true;
139148

140149
// Change to the desired mode.
141-
set_sensor_mode(mode);
150+
set_sensor_mode(sensor, sensor->mode);
142151
}
143152

144-
if (baudrate_configured) {
145-
uart_poll_out(uart_dev, 0b00000010);
146-
}
153+
uart_poll_out(sensor->dev, 0b00000010);
147154
}
148155

149-
bool sensor_ready() {
150-
return device_is_ready(uart_dev);
156+
bool sensor_ready(UartSensor *sensor) {
157+
return device_is_ready(sensor->dev);
151158
}
152159

153-
int get_sensor_value() {
154-
if (!baudrate_configured || sensor_value < 0) {
160+
int get_sensor_value(UartSensor *sensor) {
161+
if (!sensor->baudrate_configured || sensor->sensor_value < 0) {
155162
return 0;
156163
}
157-
return sensor_value;
158-
}
159-
160-
bool configure_uart_sensor(uint8_t new_mode) {
161-
if (!sensor_ready()) {
162-
printf("Input port is not ready!\n");
163-
return false;
164-
}
165-
166-
printf("Setting up uart\n");
167-
int ret = uart_irq_callback_user_data_set(uart_dev, serial_cb, nullptr);
168-
if (ret < 0) {
169-
if (ret == -ENOTSUP) {
170-
printf("Interrupt-driven UART API support not enabled\n");
171-
} else if (ret == -ENOSYS) {
172-
printf("UART device does not support interrupt-driven API\n");
173-
} else {
174-
printf("Error setting UART callback: %d\n", ret);
175-
}
176-
return false;
177-
}
178-
uart_irq_rx_enable(uart_dev);
179-
if (receive_state == ReceiveState::data && mode != new_mode) {
180-
set_sensor_mode(new_mode);
181-
}
182-
mode = new_mode;
183-
return true;
164+
return sensor->sensor_value;
184165
}
Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include <cstdint>
3+
#include <zephyr/device.h>
34

45
enum ReceiveState {
56
advertise,
@@ -8,14 +9,33 @@ enum ReceiveState {
89
data
910
};
1011

11-
void serial_cb([[maybe_unused]] const struct device *dev, [[maybe_unused]] void *user_data);
12+
struct UartSensor {
13+
// Variables used for setting up the sensor.
14+
int payload_bytes = 0;
15+
int payload_index = 0;
16+
unsigned int current_payload = 0;
17+
unsigned char checksum = 0;
18+
bool data_byte = false;
1219

13-
void set_sensor_mode(uint8_t new_mode);
20+
// Variables that are used during setup but also by the heartbeat function.
21+
int baudrate = -1;
22+
uint8_t mode = 0;
23+
volatile int sensor_value = 0;
24+
volatile uint32_t receive_state = ReceiveState::advertise;
25+
bool baudrate_configured = false;
1426

15-
void uartHeartbeat();
27+
// Associated UART device.
28+
const struct device *dev;
1629

17-
bool sensor_ready();
30+
explicit UartSensor(const struct device *dev) : dev(dev) {}
31+
};
32+
33+
void serial_cb(const struct device *dev, void *user_data);
34+
35+
void uartHeartbeat(UartSensor *sensor);
36+
37+
bool sensor_ready(UartSensor *sensor);
1838

19-
int get_sensor_value();
39+
int get_sensor_value(UartSensor *sensor);
2040

21-
bool configure_uart_sensor(uint8_t new_mode);
41+
bool configure_uart_sensor(UartSensor *sensor, uint8_t new_mode);

src/Primitives/zephyr.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,11 @@ def_prim_serialize(drive_motor_degrees) {
413413
}
414414
}
415415

416+
static const struct device *const uart_dev =
417+
DEVICE_DT_GET(DT_PROP(DT_PATH(zephyr_user), warduino_uarts));
418+
419+
UartSensor sensor(uart_dev);
420+
416421
extern void read_debug_messages();
417422

418423
void debug_work_handler(struct k_work *work) {
@@ -423,24 +428,25 @@ K_WORK_DEFINE(debug_work, debug_work_handler);
423428

424429
struct k_timer heartbeat_timer;
425430
void heartbeat_timer_func(struct k_timer *timer_id) {
426-
uartHeartbeat();
431+
uartHeartbeat(&sensor);
427432
k_work_submit(&debug_work);
428433
}
429434

430435
def_prim(setup_uart_sensor, twoToNoneU32) {
431-
bool result = configure_uart_sensor(arg0.uint32);
436+
bool result = configure_uart_sensor(&sensor, arg0.uint32);
432437
pop_args(2);
433438
return result;
434439
}
435440

436441
def_prim(color_sensor, oneToOneU32) {
437-
if (!sensor_ready()) {
442+
if (!sensor_ready(&sensor)) {
438443
printk("Input port is not ready!\n");
439444
return false;
440445
}
441446

442447
pop_args(1);
443-
pushUInt32(get_sensor_value());
448+
int value = get_sensor_value(&sensor);
449+
pushUInt32(value);
444450
return true;
445451
}
446452

0 commit comments

Comments
 (0)