Skip to content

Commit 3a198b8

Browse files
committed
pbio/drv/adc_ev3: Drop poll_soon and just poll faster.
Now that the ADC uses DMA, there is little cost in just polling faster. This way we don't end up polling in a tight loop when many NXT light or color sensors are attached. Also add a way to await new samples so we don't have to hardcode delays at higher levels.
1 parent 02c12cb commit 3a198b8

File tree

5 files changed

+66
-65
lines changed

5 files changed

+66
-65
lines changed

lib/pbio/drv/adc/adc_ev3.c

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ enum {
4747
// 150 MHz / 8 = 18.75 MHz actual
4848
SPI_CLK_SPEED_ADC = 20000000,
4949

50-
ADC_SAMPLE_PERIOD = 10,
50+
ADC_SAMPLE_PERIOD = 2,
5151
};
5252

5353
// Construct both SPI peripheral settings (data format, chip select)
@@ -94,8 +94,6 @@ static const uint32_t channel_cmd[PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS + PBDRV_
9494
};
9595
static volatile uint16_t channel_data[PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS + PBDRV_ADC_EV3_NUM_DELAY_SAMPLES];
9696

97-
static int adc_soon;
98-
9997
static pbdrv_adc_callback_t pbdrv_adc_callbacks[1];
10098
static uint32_t pbdrv_adc_callback_count = 0;
10199

@@ -137,39 +135,33 @@ pbio_error_t pbdrv_adc_ev3_exit(pbio_os_state_t *state) {
137135
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
138136
}
139137

140-
pbio_error_t pbdrv_adc_ev3_process_thread(pbio_os_state_t *state, void *context) {
138+
static pbio_error_t pbdrv_adc_ev3_process_thread(pbio_os_state_t *state, void *context) {
141139
static pbio_os_timer_t timer;
142140

143141
PBIO_OS_ASYNC_BEGIN(state);
144142

145-
pbio_os_timer_set(&timer, ADC_SAMPLE_PERIOD);
146-
147-
for (;;) {
148-
PBIO_OS_AWAIT_UNTIL(state, pbdrv_adc_ev3_process.request || adc_soon || pbio_os_timer_is_expired(&timer));
149-
150-
// Here we can exit gracefully since no SPI operation is in progress.
151-
if (pbdrv_adc_ev3_process.request & PBIO_OS_PROCESS_REQUEST_TYPE_CANCEL) {
152-
break;
153-
}
154-
155-
if (adc_soon) {
156-
adc_soon = 0;
157-
pbio_os_timer_set(&timer, ADC_SAMPLE_PERIOD);
158-
} else {
159-
// TODO: There should probably be a pbio OS function for this
160-
timer.start += timer.duration;
161-
}
143+
// Poll continuously until cancellation is requested.
144+
while (!(pbdrv_adc_ev3_process.request & PBIO_OS_PROCESS_REQUEST_TYPE_CANCEL)) {
162145

163-
// Do a sample of all channels
146+
// Start a sample of all channels
164147
pbdrv_block_device_ev3_spi_begin_for_adc(
165148
channel_cmd,
166149
channel_data,
167150
PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS + PBDRV_ADC_EV3_NUM_DELAY_SAMPLES);
151+
152+
// Allow event loop to run once so that processes that await new
153+
// samples can begin awaiting completion of the transfer.
154+
PBIO_OS_AWAIT_ONCE_AND_POLL(state);
155+
156+
// Await for actual transfer to complete.
168157
PBIO_OS_AWAIT_WHILE(state, pbdrv_block_device_ev3_is_busy());
169158

170159
for (uint32_t i = 0; i < pbdrv_adc_callback_count; i++) {
171160
pbdrv_adc_callbacks[i]();
172161
}
162+
163+
pbio_os_timer_set(&timer, ADC_SAMPLE_PERIOD);
164+
PBIO_OS_AWAIT_UNTIL(state, pbdrv_adc_ev3_process.request || pbio_os_timer_is_expired(&timer));
173165
}
174166

175167
// Processes may be waiting on us to complete, so kick when done.
@@ -178,9 +170,11 @@ pbio_error_t pbdrv_adc_ev3_process_thread(pbio_os_state_t *state, void *context)
178170
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
179171
}
180172

181-
void pbdrv_adc_update_soon(void) {
182-
adc_soon = 1;
183-
pbio_os_request_poll();
173+
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state) {
174+
PBIO_OS_ASYNC_BEGIN(state);
175+
PBIO_OS_AWAIT_UNTIL(state, pbdrv_block_device_ev3_is_busy());
176+
PBIO_OS_AWAIT_UNTIL(state, !pbdrv_block_device_ev3_is_busy());
177+
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
184178
}
185179

186180
// Public init is not used.

lib/pbio/drv/adc/adc_stm32_hal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ PROCESS(pbdrv_adc_process, "ADC");
5050
void pbdrv_adc_set_callback(pbdrv_adc_callback_t callback) {
5151
}
5252

53-
void pbdrv_adc_update_soon(void) {
53+
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state) {
54+
return PBIO_ERROR_NOT_SUPPORTED;
5455
}
5556

5657
pbio_error_t pbdrv_adc_get_ch(uint8_t ch, uint16_t *value) {

lib/pbio/drv/adc/adc_stm32f0.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ void pbdrv_adc_init(void) {
6969
void pbdrv_adc_set_callback(pbdrv_adc_callback_t callback) {
7070
}
7171

72-
void pbdrv_adc_update_soon(void) {
72+
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state) {
73+
return PBIO_ERROR_NOT_SUPPORTED;
7374
}
7475

7576
// does a single conversion for the specified channel

lib/pbio/include/pbdrv/adc.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <pbdrv/config.h>
1515
#include <pbio/error.h>
16+
#include <pbio/os.h>
1617

1718
typedef void (*pbdrv_adc_callback_t)(void);
1819

@@ -38,11 +39,13 @@ pbio_error_t pbdrv_adc_get_ch(uint8_t ch, uint16_t *value);
3839
void pbdrv_adc_set_callback(pbdrv_adc_callback_t callback);
3940

4041
/**
41-
* Requests the ADC to update soon.
42+
* Awaits for ADC to have new samples ready to be read.
4243
*
43-
* NB: Not implemented on all platforms.
44+
* Not implemented on all platforms.
45+
*
46+
* @param [in] state Protothread state.
4447
*/
45-
void pbdrv_adc_update_soon(void);
48+
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state);
4649

4750
#else
4851

@@ -54,7 +57,8 @@ static inline pbio_error_t pbdrv_adc_get_ch(uint8_t ch, uint16_t *value) {
5457
static inline void pbdrv_adc_set_callback(pbdrv_adc_callback_t callback) {
5558
}
5659

57-
static inline void pbdrv_adc_update_soon(void) {
60+
static inline pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state) {
61+
return PBIO_ERROR_NOT_SUPPORTED;
5862
}
5963

6064
#endif

lib/pbio/src/port_dcm_ev3.c

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -317,25 +317,6 @@ static pbio_port_dcm_t dcm_state[PBIO_CONFIG_PORT_DCM_NUM_DEV];
317317
#define DCM_LOOP_STEADY_STATE_COUNT (20)
318318
#define DCM_LOOP_DISCONNECT_COUNT (5)
319319

320-
pbio_error_t pbio_port_dcm_await_new_nxt_analog_sample(pbio_port_dcm_t *dcm, pbio_os_timer_t *timer, const pbdrv_ioport_pins_t *pins, uint32_t *value) {
321-
pbio_os_state_t *state = &dcm->child;
322-
323-
PBIO_OS_ASYNC_BEGIN(state);
324-
325-
// Wait for LED to settle.
326-
PBIO_OS_AWAIT_MS(state, timer, 1);
327-
328-
// Request a new ADC sample. Revisit: Call back on completion instead of time.
329-
pbdrv_adc_update_soon();
330-
PBIO_OS_AWAIT_MS(state, timer, 4);
331-
332-
// Get the value.
333-
uint8_t pin = dcm->category == DCM_CATEGORY_NXT_COLOR ? 6 : 1;
334-
*value = pbio_port_dcm_get_mv(pins, pin);
335-
336-
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
337-
}
338-
339320
/**
340321
* Thread that detects the device type. It monitors the ID1 and ID2 pins
341322
* on the port to see when devices are connected or disconnected.
@@ -387,6 +368,25 @@ pbio_error_t pbio_port_dcm_thread(pbio_os_state_t *state, pbio_os_timer_t *timer
387368
continue;
388369
}
389370

371+
if (dcm->category == DCM_CATEGORY_NXT_LIGHT) {
372+
debug_pr("Reading NXT Light Sensor until disconnected.\n");
373+
// While plugged in, get reflected and ambient light intensity.
374+
while (!pbdrv_gpio_input(&pins->p2)) {
375+
// Reflected intensity.
376+
pbdrv_gpio_out_high(&pins->p5);
377+
PBIO_OS_AWAIT_MS(state, timer, 2);
378+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child));
379+
dcm->nxt_rgba.r = pbio_port_dcm_get_mv(pins, 1);
380+
381+
// Ambient intensity.
382+
pbdrv_gpio_out_low(&pins->p5);
383+
PBIO_OS_AWAIT_MS(state, timer, 2);
384+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child));
385+
dcm->nxt_rgba.a = pbio_port_dcm_get_mv(pins, 1);
386+
}
387+
continue;
388+
}
389+
390390
if (dcm->category == DCM_CATEGORY_NXT_COLOR) {
391391
debug_pr("Initializing NXT Color Sensor.\n");
392392

@@ -405,30 +405,31 @@ pbio_error_t pbio_port_dcm_thread(pbio_os_state_t *state, pbio_os_timer_t *timer
405405
pbio_port_dcm_nxt_color_rx_msg(&dcm->child, &dcm->nxt_color_state, pins, timer, (uint8_t *)&dcm->nxt_color_state.data + dcm->count));
406406
}
407407

408-
// Checksum and continue on failure.
408+
// REVISIT: Test checksum and exit on failure.
409409
debug_pr("Finished initializing NXT Color Sensor.\n");
410-
}
411410

412-
if (dcm->category == DCM_CATEGORY_NXT_LIGHT || dcm->category == DCM_CATEGORY_NXT_COLOR) {
413-
debug_pr("Reading NXT Light/Color Sensor until disconnected.\n");
414-
// While plugged in, toggle through available colors.
411+
// While plugged in, toggle through available colors and measure intensity.
415412
while (!pbdrv_gpio_input(&pins->p2)) {
416413

417414
pbdrv_gpio_out_low(&pins->p5);
418-
PBIO_OS_AWAIT(state, &dcm->child, pbio_port_dcm_await_new_nxt_analog_sample(dcm, timer, pins, &dcm->nxt_rgba.a));
419-
pbdrv_gpio_out_high(&pins->p5);
420-
PBIO_OS_AWAIT(state, &dcm->child, pbio_port_dcm_await_new_nxt_analog_sample(dcm, timer, pins, &dcm->nxt_rgba.r));
415+
PBIO_OS_AWAIT_MS(state, timer, 2);
416+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child));
417+
dcm->nxt_rgba.a = pbio_port_dcm_get_mv(pins, 6);
421418

422-
if (dcm->category == DCM_CATEGORY_NXT_LIGHT) {
423-
// Light sensor doesn't have green and blue.
424-
continue;
425-
}
419+
pbdrv_gpio_out_high(&pins->p5);
420+
PBIO_OS_AWAIT_MS(state, timer, 2);
421+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child));
422+
dcm->nxt_rgba.r = pbio_port_dcm_get_mv(pins, 6);
426423

427424
pbdrv_gpio_out_low(&pins->p5);
428-
PBIO_OS_AWAIT(state, &dcm->child, pbio_port_dcm_await_new_nxt_analog_sample(dcm, timer, pins, &dcm->nxt_rgba.g));
429-
pbdrv_gpio_out_high(&pins->p5);
430-
PBIO_OS_AWAIT(state, &dcm->child, pbio_port_dcm_await_new_nxt_analog_sample(dcm, timer, pins, &dcm->nxt_rgba.b));
425+
PBIO_OS_AWAIT_MS(state, timer, 2);
426+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child));
427+
dcm->nxt_rgba.g = pbio_port_dcm_get_mv(pins, 6);
431428

429+
pbdrv_gpio_out_high(&pins->p5);
430+
PBIO_OS_AWAIT_MS(state, timer, 2);
431+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child));
432+
dcm->nxt_rgba.b = pbio_port_dcm_get_mv(pins, 6);
432433
}
433434
pbdrv_gpio_out_low(&pins->p5);
434435
continue;

0 commit comments

Comments
 (0)