|
29 | 29 |
|
30 | 30 | #include "tick.h"
|
31 | 31 |
|
32 |
| -// This magical macro makes sure the delay isn't optimized out and is the |
33 |
| -// minimal three instructions. |
34 |
| -#define delay_cycles(cycles) \ |
35 |
| -{ \ |
36 |
| - uint32_t t; \ |
37 |
| - asm volatile ( \ |
38 |
| - "movs %[t], %[c]\n\t" \ |
39 |
| - "loop%=:\n\t" \ |
40 |
| - "subs %[t], #1\n\t" \ |
41 |
| - "bne.n loop%=" : [t] "=r"(t) : [c] "I" (cycles)); \ |
42 |
| - } |
43 |
| - |
44 |
| -uint64_t next_start_tick_ms = 0; |
45 |
| -uint32_t next_start_tick_us = 1000; |
46 |
| - |
47 | 32 | void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes) {
|
48 |
| -// TODO: Figure out timing delays on nRF. Turn off cache using ICACHECNF register. |
49 |
| -/* |
50 |
| - // This is adapted directly from the Adafruit NeoPixel library SAMD21G18A code: |
51 |
| - // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp |
52 |
| - uint8_t *ptr, *end, p, bitMask; |
53 |
| - uint32_t pinMask; |
54 |
| - PortGroup* port; |
55 |
| -
|
56 |
| - // This must be called while interrupts are on in case we're waiting for a |
57 |
| - // future ms tick. |
58 |
| - wait_until(next_start_tick_ms, next_start_tick_us); |
59 |
| -
|
60 |
| - // Turn off interrupts of any kind during timing-sensitive code. |
61 |
| - mp_hal_disable_all_interrupts(); |
62 |
| -
|
63 |
| -
|
64 |
| - // Make sure the NVM cache is consistently timed. |
65 |
| -
|
66 |
| - NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_DETERMINISTIC_Val; |
67 |
| - #endif |
68 |
| -
|
69 |
| - uint32_t pin = digitalinout->pin->number; |
70 |
| - port = &PORT->Group[GPIO_PORT(pin)]; // Convert GPIO # to port register |
71 |
| - pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code. |
72 |
| - ptr = pixels; |
73 |
| - end = ptr + numBytes; |
74 |
| - p = *ptr++; |
75 |
| - bitMask = 0x80; |
76 |
| -
|
77 |
| - volatile uint32_t *set = &(port->OUTSET.reg), |
78 |
| - *clr = &(port->OUTCLR.reg); |
79 |
| -
|
80 |
| - for(;;) { |
81 |
| - *set = pinMask; |
82 |
| - // This is the time where the line is always high regardless of the bit. |
83 |
| - // For the SK6812 its 0.3us +- 0.15us |
84 |
| - #ifdef SAMD21 |
85 |
| - asm("nop; nop;"); |
86 |
| - #endif |
87 |
| - #ifdef SAMD51 |
88 |
| - delay_cycles(3); |
89 |
| - #endif |
90 |
| - if(p & bitMask) { |
91 |
| - // This is the high delay unique to a one bit. |
92 |
| - // For the SK6812 its 0.3us |
93 |
| - #ifdef SAMD21 |
94 |
| - asm("nop; nop; nop; nop; nop; nop; nop;"); |
95 |
| - #endif |
96 |
| - #ifdef SAMD51 |
97 |
| - delay_cycles(11); |
98 |
| - #endif |
99 |
| - *clr = pinMask; |
100 |
| - } else { |
101 |
| - *clr = pinMask; |
102 |
| - // This is the low delay unique to a zero bit. |
103 |
| - // For the SK6812 its 0.3us |
104 |
| - #ifdef SAMD21 |
105 |
| - asm("nop; nop;"); |
106 |
| - #endif |
107 |
| - #ifdef SAMD51 |
108 |
| - delay_cycles(3); |
109 |
| - #endif |
110 |
| - } |
111 |
| - if((bitMask >>= 1) != 0) { |
112 |
| - // This is the delay between bits in a byte and is the 1 code low |
113 |
| - // level time from the datasheet. |
114 |
| - // For the SK6812 its 0.6us +- 0.15us |
115 |
| - #ifdef SAMD21 |
116 |
| - asm("nop; nop; nop; nop; nop;"); |
117 |
| - #endif |
118 |
| - #ifdef SAMD51 |
119 |
| - delay_cycles(20); |
120 |
| - #endif |
121 |
| - } else { |
122 |
| - if(ptr >= end) break; |
123 |
| - p = *ptr++; |
124 |
| - bitMask = 0x80; |
125 |
| - // This is the delay between bytes. It's similar to the other branch |
126 |
| - // in the if statement except its tuned to account for the time the |
127 |
| - // above operations take. |
128 |
| - // For the SK6812 its 0.6us +- 0.15us |
129 |
| - #ifdef SAMD51 |
130 |
| - delay_cycles(15); |
131 |
| - #endif |
132 |
| - } |
133 |
| - } |
134 |
| -
|
135 |
| - #ifdef SAMD21 |
136 |
| - // Speed up! (But inconsistent timing.) |
137 |
| - NVMCTRL->CTRLB.bit.READMODE = NVMCTRL_CTRLB_READMODE_NO_MISS_PENALTY_Val; |
138 |
| - #endif |
139 |
| -
|
140 |
| - #ifdef SAMD51 |
141 |
| - // Turn instruction, data, and NVM caches back on. |
142 |
| - hri_cmcc_clear_CFG_reg(CMCC, CMCC_CFG_DCDIS | CMCC_CFG_ICDIS); |
143 |
| - hri_nvmctrl_clear_CTRLA_CACHEDIS0_bit(NVMCTRL); |
144 |
| - hri_nvmctrl_clear_CTRLA_CACHEDIS1_bit(NVMCTRL); |
145 |
| -
|
146 |
| - #endif |
147 |
| -
|
148 |
| - // ticks_ms may be out of date at this point because we stopped the |
149 |
| - // interrupt. We'll risk it anyway. |
150 |
| - current_tick(&next_start_tick_ms, &next_start_tick_us); |
151 |
| - if (next_start_tick_us < 100) { |
152 |
| - next_start_tick_ms += 1; |
153 |
| - next_start_tick_us = 100 - next_start_tick_us; |
154 |
| - } else { |
155 |
| - next_start_tick_us -= 100; |
156 |
| - } |
157 |
| -
|
158 |
| - // Turn on interrupts after timing-sensitive code. |
159 |
| - mp_hal_enable_all_interrupts(); |
160 |
| -*/ |
| 33 | + // stub |
161 | 34 | }
|
0 commit comments