Skip to content

Commit

Permalink
Better unflickerify LEDs
Browse files Browse the repository at this point in the history
Brittany figured out the logical reason LEDs were flickering and
devised this fix, setting the timer count 0.

Runnign the ADC and the timer at the same time results in a situation
where the timer's CNT isn't correctly reset to 0.

The timer was sometimes moving to 0 later, causing a late MINC (memory
increment) in the DMA request, and this lateness cascades, causing
corrupted data to be written to the LEDs. Manually ensuring CNT is 0
before starting the LED DMA stuff effectively prevents this issue.
  • Loading branch information
michd committed Nov 17, 2020
1 parent afe72cc commit 38ed766
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 15 deletions.
1 change: 1 addition & 0 deletions Src/adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ void adc_init(){
init_adc_gpio();
init_adc_channels();
init_adc_dma();
adc_start();
}

void adc_read_into(uint8_t * destination) {
Expand Down
20 changes: 5 additions & 15 deletions Src/led.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,14 +132,6 @@ void led_send_buffer() {

sending_buffer = true;

// Stop ADC collection while sending LED buffer
adc_stop();

// This NOP is pretty critical; without it, the LEDs tend to become a
// flickery mess. Likely something to do with properly shutting off the
// the DMA requests from the ADC prior to starting our ones here.
NOP;

// Set all LED data pins high on timer update event
HAL_DMA_Start_IT(
&dma_ch2_tim_ch1,
Expand All @@ -166,6 +158,11 @@ void led_send_buffer() {
LEN_BUFFER
);

// Very important to ensure LEDs are synchronised right.
// Without this there can be an off-by-one error that causes a flickery
// mess on the LEDs.
TIM1->CNT = 0;

__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_CC1 | TIM_DMA_CC2 | TIM_DMA_CC3);
HAL_TIM_Base_Start(&htim1);
}
Expand Down Expand Up @@ -322,15 +319,8 @@ static void transfer_complete_handler(DMA_HandleTypeDef *dma_handle){
if (dma_handle != &dma_ch2_tim_ch1) return;

HAL_TIM_Base_Stop(&htim1);

// As in led_send_buffer, this NOP instruction is important to properly
// finish DMA; otherwise, flickery mess.
NOP;

LED_PORT->BRR |= led_pin_pos;

// Restart the ADC now LED transfer is complete
adc_start();

// Clear LED data
// This is also done elsewhere, but leaving it here reduces LED flickering
Expand Down

0 comments on commit 38ed766

Please sign in to comment.