Skip to content

Commit b77115b

Browse files
committed
pbio/drv/adc: Use microseconds for settling time delay.
A full ADC roundtrip is now close to 80 us, so we don't need to wait 2ms. This also avoids rounding errors where you might sometimes wait a whole millisecond longer. Also use pbio_os_timer_extend in the ADC loop for more constant loop time. Combined with previous runloop improvements, this makes the RGB light on the NXT Color Sensor blink without visual stutters. See pybricks/support#2301
1 parent 2000de2 commit b77115b

File tree

5 files changed

+24
-22
lines changed

5 files changed

+24
-22
lines changed

lib/pbio/drv/adc/adc_stm32_hal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ static uint32_t pbdrv_adc_last_error;
4747

4848
PROCESS(pbdrv_adc_process, "ADC");
4949

50-
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, pbio_os_timer_t *timer, uint32_t future) {
51-
return PBIO_ERROR_NOT_SUPPORTED;
50+
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, uint32_t *start_time_us, uint32_t future_us) {
51+
return PBIO_ERROR_NOT_IMPLEMENTED;
5252
}
5353

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

lib/pbio/drv/adc/adc_stm32f0.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ void pbdrv_adc_init(void) {
6666
process_start(&pbdrv_adc_process);
6767
}
6868

69-
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, pbio_os_timer_t *timer, uint32_t future) {
70-
return PBIO_ERROR_NOT_SUPPORTED;
69+
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, uint32_t *start_time_us, uint32_t future_us) {
70+
return PBIO_ERROR_NOT_IMPLEMENTED;
7171
}
7272

7373
// does a single conversion for the specified channel

lib/pbio/drv/block_device/block_device_ev3.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ static struct {
116116
uint8_t rx_dummy_byte;
117117
} spi_dev_bufs PBDRV_DMA_BUF;
118118

119-
static uint32_t last_spi_dma_complete_time;
119+
static uint32_t last_spi_dma_complete_time_us;
120120

121121
static void spi_dma_complete(void) {
122122
// Only complete once RX and TX complete.
@@ -129,7 +129,7 @@ static void spi_dma_complete(void) {
129129
if (spi_dev.rx_user_buf_addr && spi_dev.rx_user_buf_sz) {
130130
pbdrv_cache_prepare_after_dma((void *)spi_dev.rx_user_buf_addr, spi_dev.rx_user_buf_sz);
131131
}
132-
last_spi_dma_complete_time = pbdrv_clock_get_ms();
132+
last_spi_dma_complete_time_us = pbdrv_clock_get_us();
133133
}
134134

135135
/**
@@ -764,10 +764,10 @@ pbio_error_t pbdrv_adc_get_ch(uint8_t ch, uint16_t *value) {
764764
return PBIO_SUCCESS;
765765
}
766766

767-
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, pbio_os_timer_t *timer, uint32_t future) {
767+
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, uint32_t *start_time_us, uint32_t future_us) {
768768
PBIO_OS_ASYNC_BEGIN(state);
769-
pbio_os_timer_set(timer, 0);
770-
PBIO_OS_AWAIT_UNTIL(state, pbio_util_time_has_passed(last_spi_dma_complete_time, timer->start + future));
769+
*start_time_us = pbdrv_clock_get_us();
770+
PBIO_OS_AWAIT_UNTIL(state, pbio_util_time_has_passed(last_spi_dma_complete_time_us, *start_time_us + future_us));
771771
PBIO_OS_ASYNC_END(PBIO_SUCCESS);
772772
}
773773

@@ -916,6 +916,8 @@ pbio_error_t ev3_spi_process_thread(pbio_os_state_t *state, void *context) {
916916
pbdrv_block_device_load_err = err;
917917
pbio_busy_count_down();
918918

919+
pbio_os_timer_set(&timer, ADC_SAMPLE_PERIOD);
920+
919921
// Poll ADC continuously until cancellation is requested.
920922
while (!(ev3_spi_process.request & PBIO_OS_PROCESS_REQUEST_TYPE_CANCEL)) {
921923

@@ -928,8 +930,8 @@ pbio_error_t ev3_spi_process_thread(pbio_os_state_t *state, void *context) {
928930
// Await for transfer to complete.
929931
PBIO_OS_AWAIT_WHILE(state, (spi_dev.status & SPI_STATUS_WAIT_ANY));
930932

931-
pbio_os_timer_set(&timer, ADC_SAMPLE_PERIOD);
932-
PBIO_OS_AWAIT_UNTIL(state, ev3_spi_process.request || pbio_os_timer_is_expired(&timer));
933+
PBIO_OS_AWAIT_UNTIL(state, pbio_os_timer_is_expired(&timer));
934+
pbio_os_timer_extend(&timer);
933935
}
934936

935937
// Now that the ADC loop has ended, we can use the SPI bus to save user

lib/pbio/include/pbdrv/adc.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ pbio_error_t pbdrv_adc_get_ch(uint8_t ch, uint16_t *value);
3434
*
3535
* Not implemented on all platforms.
3636
*
37-
* @param [in] state Protothread state.
38-
* @param [in] timer Parent process timer, used to store time of calling this.
39-
* @param [in] future How far into the future the sample should be (ms).
37+
* @param [in] state Protothread state.
38+
* @param [out] start_time_us Persistent value used by this function to store the start time (µs).
39+
* @param [in] future_us How far into the future the sample should be (µs).
4040
*/
41-
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, pbio_os_timer_t *timer, uint32_t future);
41+
pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, uint32_t *start_time_us, uint32_t future_us);
4242

4343
#else
4444

@@ -47,7 +47,7 @@ static inline pbio_error_t pbdrv_adc_get_ch(uint8_t ch, uint16_t *value) {
4747
return PBIO_ERROR_NOT_SUPPORTED;
4848
}
4949

50-
static inline pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, pbio_os_timer_t *timer, uint32_t future) {
50+
static inline pbio_error_t pbdrv_adc_await_new_samples(pbio_os_state_t *state, uint32_t *start_time_us, uint32_t future_us) {
5151
return PBIO_ERROR_NOT_SUPPORTED;
5252
}
5353

lib/pbio/src/port_dcm_ev3.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,12 @@ pbio_error_t pbio_port_dcm_thread(pbio_os_state_t *state, pbio_os_timer_t *timer
374374
while (!pbdrv_gpio_input(&pins->p2)) {
375375
// Reflected intensity.
376376
pbdrv_gpio_out_high(&pins->p5);
377-
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, timer, 2));
377+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, &timer->start, 200));
378378
dcm->nxt_rgba.r = pbio_port_dcm_get_mv(pins, 1);
379379

380380
// Ambient intensity.
381381
pbdrv_gpio_out_low(&pins->p5);
382-
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, timer, 2));
382+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, &timer->start, 200));
383383
dcm->nxt_rgba.a = pbio_port_dcm_get_mv(pins, 1);
384384
}
385385
continue;
@@ -410,19 +410,19 @@ pbio_error_t pbio_port_dcm_thread(pbio_os_state_t *state, pbio_os_timer_t *timer
410410
while (!pbdrv_gpio_input(&pins->p2)) {
411411

412412
pbdrv_gpio_out_low(&pins->p5);
413-
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, timer, 2));
413+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, &timer->start, 200));
414414
dcm->nxt_rgba.a = pbio_port_dcm_get_mv(pins, 6);
415415

416416
pbdrv_gpio_out_high(&pins->p5);
417-
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, timer, 2));
417+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, &timer->start, 200));
418418
dcm->nxt_rgba.r = pbio_port_dcm_get_mv(pins, 6);
419419

420420
pbdrv_gpio_out_low(&pins->p5);
421-
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, timer, 2));
421+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, &timer->start, 2000));
422422
dcm->nxt_rgba.g = pbio_port_dcm_get_mv(pins, 6);
423423

424424
pbdrv_gpio_out_high(&pins->p5);
425-
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, timer, 2));
425+
PBIO_OS_AWAIT(state, &dcm->child, pbdrv_adc_await_new_samples(&dcm->child, &timer->start, 200));
426426
dcm->nxt_rgba.b = pbio_port_dcm_get_mv(pins, 6);
427427
}
428428
pbdrv_gpio_out_low(&pins->p5);

0 commit comments

Comments
 (0)