28
28
#include "shared-bindings/neopixel_write/__init__.h"
29
29
30
30
#include "tick.h"
31
+ #include "py/mperrno.h"
32
+ #include "py/runtime.h"
31
33
#include "common-hal/microcontroller/Pin.h"
32
34
#include "stm32f4xx_hal.h"
33
35
#include "stm32f4xx_ll_gpio.h"
@@ -40,6 +42,9 @@ uint32_t next_start_tick_us = 1000;
40
42
#define MAGIC_800_T0H 2800000 // ~0.36 us -> 0.44 field
41
43
#define MAGIC_800_T1H 1350000 // ~0.74 us -> 0.84 field
42
44
45
+ #pragma GCC push_options
46
+ #pragma GCC optimize ("Os")
47
+
43
48
void common_hal_neopixel_write (const digitalio_digitalinout_obj_t * digitalinout , uint8_t * pixels ,
44
49
uint32_t numBytes ) {
45
50
uint8_t * p = pixels , * end = p + numBytes , pix = * p ++ , mask = 0x80 ;
@@ -48,7 +53,7 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
48
53
49
54
//assumes 800_000Hz frequency
50
55
//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
56
+ //TODO: try to get dynamic weighting working again
52
57
uint32_t sys_freq = HAL_RCC_GetSysClockFreq ();
53
58
uint32_t interval = sys_freq /MAGIC_800_INT ;
54
59
uint32_t t0 = (sys_freq /MAGIC_800_T0H );
@@ -63,23 +68,22 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
63
68
64
69
__disable_irq ();
65
70
// Enable DWT in debug core. Useable when interrupts disabled, as opposed to Systick->VAL
66
- //ITM->LAR = 0xC5ACCE55; //this should be required but isn't
67
71
CoreDebug -> DEMCR |= CoreDebug_DEMCR_TRCENA_Msk ;
68
72
DWT -> CTRL |= DWT_CTRL_CYCCNTENA_Msk ;
69
73
DWT -> CYCCNT = 0 ;
70
74
71
75
for (;;) {
76
+ cyc = (pix & mask ) ? t1 : t0 ;
72
77
start = DWT -> CYCCNT ;
73
78
LL_GPIO_SetOutputPin (p_port , p_mask );
74
- cyc = (pix & mask ) ? t1 : t0 ;
75
- while (DWT -> CYCCNT - start < cyc );
79
+ while ((DWT -> CYCCNT - start ) < cyc );
76
80
LL_GPIO_ResetOutputPin (p_port , p_mask );
81
+ while ((DWT -> CYCCNT - start ) < interval );
77
82
if (!(mask >>= 1 )) {
78
83
if (p >= end ) break ;
79
84
pix = * p ++ ;
80
85
mask = 0x80 ;
81
86
}
82
- while (DWT -> CYCCNT - start < interval ); //wait for interval to finish
83
87
}
84
88
85
89
// Enable interrupts again
@@ -94,3 +98,5 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
94
98
next_start_tick_us -= 100 ;
95
99
}
96
100
}
101
+
102
+ #pragma GCC pop_options
0 commit comments