1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
19422: drivers/ws281x: improve timing for ESP32x r=maribu a=gschorcht

### Contribution description

This PR provides a small change which improves the timing for ESP32x SoCs.

If overhead like the loop control or the calculation of the waiting times for the next bit are performed while waiting for the end of the LOW phase, the time required for such operations is included in the LOW phase. This makes both the LOW phase and the period more precise.

According to the definitions
```c
#define WS281X_T_DATA_NS                (1250U)
#define WS281X_T_DATA_ONE_NS            (650U)
#define WS281X_T_DATA_ZERO_NS           (325U)
```
the following timing is used:
| Parameter    | Value | Master | this PR |
|:-------------|------:|-------:|--------:|
| 1-Bit Period | 1250  | 1820   | 1400    |
| 1-Bit HIGH   | 650   | 690    | 710     |
| 1-Bit LOW    | 600   | 1130   | 690     |
|              |       |        |         |
| 0-Bit Period | 1250  | 1880   | 1400    |
| 0-Bit HIGH   | 350   | 380    | 400     |
| 0-Bit LOW    | 900   | 1500   | 1000    |

Timing with current master:
![ws281x_esp32_current](https://user-images.githubusercontent.com/31932013/227731227-44d7283f-6591-4e11-9b79-9c49b08c64a4.png)

Timing with this PR:
![ws281x_esp32_improved](https://user-images.githubusercontent.com/31932013/227731250-22819d1a-524c-43db-ab73-1bbb34cddee3.png)

### Testing procedure

`tests/driver_ws281x` should still work.

### Issues/PRs references


Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
This commit is contained in:
bors[bot] 2023-03-25 20:14:23 +00:00 committed by GitHub
commit d50fd0b41e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -70,18 +70,23 @@ void ws281x_write_buffer(ws281x_t *dev, const void *buf, size_t size)
on_wait = zero_on;
off_wait = zero_off;
}
data <<= 1;
while (cpu_hal_get_cycle_count() < current_wait) { }
/* end of LOW phase and start of HIGH phase */
start = cpu_hal_get_cycle_count();
gpio_set(dev->params.pin);
current_wait = start + on_wait;
while (cpu_hal_get_cycle_count() < current_wait) { }
gpio_clear(dev->params.pin);
/* end of HIGH phase and start of HIGH phase */
start = cpu_hal_get_cycle_count();
gpio_clear(dev->params.pin);
current_wait = start + off_wait;
while (cpu_hal_get_cycle_count() < current_wait) { }
data <<= 1;
}
pos++;
}
/* final LOW phase */
current_wait = cpu_hal_get_cycle_count();
/* end of final LOW phase */
}
int ws281x_init(ws281x_t *dev, const ws281x_params_t *params)