Broadcom Raspberry Pi Zero2W neopixel timing fix

These changes result in working neopixel functionality. I've tested on
both the zero2w and the pi4b (The 4b didn't exhibit the original issue)
and the boards now behave properly with 1 to 30 pixels and the board hanging
no longer occurs.

Remove mod that didn't help during testing
Restoring back to original structure
Replace 2 microsecond delay w/deterministic loop
Remove unneded check for empty queue

Put transmit delay outside loop so Queue is used

Make sure last transmission is complete
This commit is contained in:
RetiredWizard 2023-02-09 01:14:01 -05:00
parent 795e46cedd
commit a2bbca1428
1 changed files with 32 additions and 8 deletions

View File

@ -45,7 +45,11 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
uint8_t *pixels, uint32_t num_bytes) {
// Wait to make sure we don't append onto the last transmission. This should only be a tick or
// two.
while (port_get_raw_ticks(NULL) < next_start_raw_ticks) {
int icnt;
while ((port_get_raw_ticks(NULL) < next_start_raw_ticks) &
(next_start_raw_ticks-port_get_raw_ticks(NULL) < 100)) {
RUN_BACKGROUND_TASKS;
}
BP_Function_Enum alt_function = GPIO_FUNCTION_OUTPUT;
@ -92,7 +96,8 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
// Wait for the clock to start up.
COMPLETE_MEMORY_READS;
while (CM_PWM->CS_b.BUSY == 0) {
icnt = 0;
while ((CM_PWM->CS_b.BUSY == 0) & (icnt++ < 1000)) {
}
}
@ -134,22 +139,41 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout,
expanded |= 0x80000000;
}
}
while (pwm->STA_b.FULL1 == 1) {
RUN_BACKGROUND_TASKS;
}
if (channel == 1) {
icnt=0;
while ((pwm->STA_b.FULL1 == 1) & (icnt++ < 150)) {
RUN_BACKGROUND_TASKS;
}
// Dummy value for the first channel.
pwm->FIF1 = 0x000000;
}
icnt=0;
while ((pwm->STA_b.FULL1 == 1) & (icnt++ < 150)) {
RUN_BACKGROUND_TASKS;
}
pwm->FIF1 = expanded;
if (channel == 0) {
icnt=0;
while ((pwm->STA_b.FULL1 == 1) & (icnt++ < 150)) {
RUN_BACKGROUND_TASKS;
}
// Dummy value for the second channel.
pwm->FIF1 = 0x000000;
}
}
// Wait just a little bit so that transmission can start.
common_hal_mcu_delay_us(2);
while (pwm->STA_b.STA1 == 1) {
icnt = 0;
while ((pwm->STA_b.EMPT1 == 0) & (icnt++ < 2500)) {
RUN_BACKGROUND_TASKS;
}
// Wait for transmission to start.
icnt = 0;
while (((pwm->STA_b.STA1 ==0) & (pwm->STA_b.STA2 == 0)) & (icnt++ < 150)) {
RUN_BACKGROUND_TASKS;
}
// Wait for transmission to complete.
icnt = 0;
while (((pwm->STA_b.STA1 == 1) | (pwm->STA_b.STA2 == 1)) & (icnt++ < 150)) {
RUN_BACKGROUND_TASKS;
}