Skip to content

Commit 51078cc

Browse files
committed
timing tweaks with testing
1 parent 98fd372 commit 51078cc

File tree

1 file changed

+16
-9
lines changed

1 file changed

+16
-9
lines changed

ports/stm32f4/common-hal/neopixel_write/__init__.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,39 +35,46 @@
3535
uint64_t next_start_tick_ms = 0;
3636
uint32_t next_start_tick_us = 1000;
3737

38+
//sysclock divisors
39+
#define MAGIC_800_INT 900000 // ~1.11 us -> 1.2 field
40+
#define MAGIC_800_T0H 2800000 // ~0.36 us -> 0.44 field
41+
#define MAGIC_800_T1H 1350000 // ~0.74 us -> 0.84 field
42+
3843
void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels,
3944
uint32_t numBytes) {
4045
uint8_t *p = pixels, *end = p + numBytes, pix = *p++, mask = 0x80;
4146
uint32_t start = 0;
4247
uint32_t cyc = 0;
4348

4449
//assumes 800_000Hz frequency
50+
//Theoretical values here are 800_000 -> 1.25us, 2500000->0.4us, 1250000->0.8us
51+
//But they don't work, possibly due to bad optimization? Use tested magic values instead
4552
uint32_t sys_freq = HAL_RCC_GetSysClockFreq();
46-
uint32_t interval = sys_freq/800000; // cycles per interval (1.25 us). 210@168MHz
47-
uint32_t t0 = interval - (sys_freq/2500000); // 0.4 us
48-
uint32_t t1 = interval - (sys_freq/1250000); // 0.8 us
53+
uint32_t interval = sys_freq/MAGIC_800_INT;
54+
uint32_t t0 = (sys_freq/MAGIC_800_T0H);
55+
uint32_t t1 = (sys_freq/MAGIC_800_T1H);
4956

5057
// This must be called while interrupts are on in case we're waiting for a
5158
// future ms tick.
5259
wait_until(next_start_tick_ms, next_start_tick_us);
5360

61+
GPIO_TypeDef * p_port = pin_port(digitalinout->pin->port);
62+
uint32_t p_mask = pin_mask(digitalinout->pin->number);
63+
5464
__disable_irq();
5565
// Enable DWT in debug core. Useable when interrupts disabled, as opposed to Systick->VAL
56-
//ITM->LAR = 0xC5ACCE55; //is this required?
66+
//ITM->LAR = 0xC5ACCE55; //this should be required but isn't
5767
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
5868
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
5969
DWT->CYCCNT = 0;
6070

61-
GPIO_TypeDef * p_port = pin_port(digitalinout->pin->port);
62-
uint32_t p_mask = pin_mask(digitalinout->pin->number);
63-
6471
for(;;) {
72+
start = DWT->CYCCNT;
6573
LL_GPIO_SetOutputPin(p_port, p_mask);
6674
cyc = (pix & mask) ? t1 : t0;
67-
start = DWT->CYCCNT;
6875
while(DWT->CYCCNT - start < cyc);
6976
LL_GPIO_ResetOutputPin(p_port, p_mask);
70-
if(!(mask >>= 1)) { //max has shifted all the way
77+
if(!(mask >>= 1)) {
7178
if(p >= end) break;
7279
pix = *p++;
7380
mask = 0x80;

0 commit comments

Comments
 (0)