Skip to content

Commit b127490

Browse files
authored
Merge pull request #397 from adafruit/add-ch32v-support
add ch32 support
2 parents c96772c + 9dd0fcf commit b127490

File tree

2 files changed

+170
-4
lines changed

2 files changed

+170
-4
lines changed

Adafruit_NeoPixel.cpp

Lines changed: 169 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,162 @@ void Adafruit_NeoPixel::rp2040Show(uint8_t pin, uint8_t *pixels, uint32_t numBy
224224
// Bits for transmission must be shifted to top 8 bits
225225
pio_sm_put_blocking(pio, sm, ((uint32_t)*pixels++)<< 24);
226226
}
227+
#elif defined(ARDUINO_ARCH_CH32)
227228

229+
// F_CPU is defined to SystemCoreClock (not constant number)
230+
#if SYSCLK_FREQ_144MHz_HSE == 144000000 || SYSCLK_FREQ_HSE == 144000000 || \
231+
SYSCLK_FREQ_144MHz_HSI == 144000000 || SYSCLK_FREQ_HSI == 144000000
232+
#define CH32_F_CPU 144000000
233+
234+
#elif SYSCLK_FREQ_120MHz_HSE == 120000000 || SYSCLK_FREQ_HSE == 120000000 || \
235+
SYSCLK_FREQ_120MHz_HSI == 120000000 || SYSCLK_FREQ_HSI == 120000000
236+
#define CH32_F_CPU 120000000
237+
238+
#elif SYSCLK_FREQ_96MHz_HSE == 96000000 || SYSCLK_FREQ_HSE == 96000000 || \
239+
SYSCLK_FREQ_96MHz_HSI == 96000000 || SYSCLK_FREQ_HSI == 96000000
240+
#define CH32_F_CPU 96000000
241+
242+
#elif SYSCLK_FREQ_72MHz_HSE == 72000000 || SYSCLK_FREQ_HSE == 72000000 || \
243+
SYSCLK_FREQ_72MHz_HSI == 72000000 || SYSCLK_FREQ_HSI == 72000000
244+
#define CH32_F_CPU 72000000
245+
246+
#elif SYSCLK_FREQ_56MHz_HSE == 56000000 || SYSCLK_FREQ_HSE == 56000000 || \
247+
SYSCLK_FREQ_56MHz_HSI == 56000000 || SYSCLK_FREQ_HSI == 56000000
248+
#define CH32_F_CPU 56000000
249+
250+
#elif SYSCLK_FREQ_48MHz_HSE == 48000000 || SYSCLK_FREQ_HSE == 48000000 || \
251+
SYSCLK_FREQ_48MHz_HSI == 48000000 || SYSCLK_FREQ_HSI == 48000000
252+
#define CH32_F_CPU 48000000
253+
254+
#endif
255+
256+
static void ch32Show(GPIO_TypeDef* ch_port, uint32_t ch_pin, uint8_t* pixels, uint32_t numBytes, bool is800KHz) {
257+
// not support 400khz
258+
if (!is800KHz) return;
259+
260+
volatile uint32_t* set = &ch_port->BSHR;
261+
volatile uint32_t* clr = &ch_port->BCR;
262+
263+
uint8_t* ptr = pixels;
264+
uint8_t* end = ptr + numBytes;
265+
uint8_t p = *ptr++;
266+
uint8_t bitMask = 0x80;
267+
268+
// NVIC_DisableIRQ(SysTicK_IRQn);
269+
270+
while (1) {
271+
if (p & bitMask) { // ONE
272+
// High 800ns
273+
*set = ch_pin;
274+
__asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;"
275+
"nop; nop; nop; nop; nop; nop; nop; nop;"
276+
"nop; nop; nop; nop; nop; nop; nop; nop;"
277+
"nop; nop; nop; nop; nop; nop; nop; nop;"
278+
"nop; nop; nop; nop; nop; nop; nop; nop;"
279+
"nop;"
280+
#if CH32_F_CPU >= 72000000
281+
"nop; nop; nop; nop; nop; nop; nop;"
282+
"nop; nop; nop; nop; nop; nop;"
283+
#endif
284+
#if CH32_F_CPU >= 96000000
285+
"nop; nop;"
286+
"nop; nop; nop; nop; nop; nop; nop; nop;"
287+
"nop; nop; nop; nop; nop; nop; nop; nop;"
288+
#endif
289+
#if CH32_F_CPU >= 120000000
290+
"nop; nop; nop; nop; nop; nop; nop; nop;"
291+
"nop; nop; nop; nop; nop; nop; nop; nop;"
292+
"nop; nop; nop; nop; nop; nop; nop; nop;"
293+
#endif
294+
#if CH32_F_CPU >= 144000000
295+
"nop; nop; nop; nop; nop; nop; nop; nop;"
296+
"nop; nop; nop; nop; nop; nop; nop; nop;"
297+
#endif
298+
);
299+
300+
// Low 450ns
301+
*clr = ch_pin;
302+
__asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;"
303+
"nop; nop; nop; nop; nop; nop; nop; nop;"
304+
"nop;"
305+
#if CH32_F_CPU >= 72000000
306+
"nop; nop; nop; nop; nop; nop; nop; nop; nop;"
307+
#endif
308+
#if CH32_F_CPU >= 96000000
309+
"nop; nop; nop; nop; nop; nop;"
310+
#endif
311+
#if CH32_F_CPU >= 120000000
312+
"nop; nop; nop; nop; nop;"
313+
"nop; nop; nop; nop; nop; nop; nop; nop;"
314+
#endif
315+
#if CH32_F_CPU >= 144000000
316+
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
317+
#endif
318+
);
319+
} else { // ZERO
320+
// High 400ns
321+
*set = ch_pin;
322+
__asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;"
323+
"nop; nop; nop; nop; nop; nop; nop; nop;"
324+
"nop;"
325+
#if CH32_F_CPU >= 72000000
326+
"nop; nop; nop; nop; nop; nop; nop;"
327+
#endif
328+
#if CH32_F_CPU >= 96000000
329+
"nop; nop; nop; nop; nop; nop; nop; nop;"
330+
#endif
331+
#if CH32_F_CPU >= 120000000
332+
"nop; nop; nop; "
333+
"nop; nop; nop; nop; nop; nop; nop; nop;"
334+
#endif
335+
#if CH32_F_CPU >= 144000000
336+
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
337+
#endif
338+
);
339+
340+
// Low 850ns
341+
*clr = ch_pin;
342+
__asm volatile ("nop; nop; nop; nop; nop; nop; nop; nop;"
343+
"nop; nop; nop; nop; nop; nop; nop; nop;"
344+
"nop; nop; nop; nop; nop; nop; nop; nop;"
345+
"nop; nop; nop; nop; nop; nop; nop; nop;"
346+
"nop; nop; nop; nop; nop;"
347+
#if CH32_F_CPU >= 72000000
348+
"nop; nop; nop;"
349+
"nop; nop; nop; nop; nop; nop; nop; nop;"
350+
#endif
351+
#if CH32_F_CPU >= 96000000
352+
"nop; nop; nop; nop; nop; nop; nop; nop;"
353+
"nop; nop; nop; nop; nop; nop; nop; nop;"
354+
"nop; nop; nop; nop; nop; nop;"
355+
#endif
356+
#if CH32_F_CPU >= 120000000
357+
"nop; nop; nop; nop; nop; nop; nop; nop;"
358+
"nop; nop; nop; nop; nop; nop; nop; nop;"
359+
"nop; nop; nop; nop; nop; nop;"
360+
#endif
361+
#if CH32_F_CPU >= 144000000
362+
"nop; nop; nop; nop;"
363+
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
364+
#endif
365+
);
366+
}
367+
368+
if (bitMask >>= 1) {
369+
// Move on to the next pixel
370+
asm("nop;");
371+
}
372+
else {
373+
if (ptr >= end) {
374+
break;
375+
}
376+
p = *ptr++;
377+
bitMask = 0x80;
378+
}
379+
}
380+
381+
// NVIC_EnableIRQ(SysTicK_IRQn);
382+
}
228383
#endif
229384

230385
#if defined(ESP8266)
@@ -282,8 +437,8 @@ void Adafruit_NeoPixel::show(void) {
282437
// state, computes 'pin high' and 'pin low' values, and writes these back
283438
// to the PORT register as needed.
284439

285-
// NRF52 may use PWM + DMA (if available), may not need to disable interrupt
286-
// ESP32 may not disable interrupts because espShow() uses RMT which tries to acquire locks
440+
// NRF52 may use PWM + DMA (if available), may not need to disable interrupt
441+
// ESP32 may not disable interrupts because espShow() uses RMT which tries to acquire locks
287442
#if !(defined(NRF52) || defined(NRF52_SERIES) || defined(ESP32))
288443
noInterrupts(); // Need 100% focus on instruction timing
289444
#endif
@@ -3108,6 +3263,8 @@ if(is800KHz) {
31083263
}
31093264
}
31103265

3266+
#elif defined(ARDUINO_ARCH_CH32)
3267+
ch32Show(gpioPort, gpioPin, pixels, numBytes, is800KHz);
31113268
#else
31123269
#error Architecture not supported
31133270
#endif
@@ -3141,6 +3298,15 @@ void Adafruit_NeoPixel::setPin(int16_t p) {
31413298
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
31423299
gpioPort = digitalPinToPort(p);
31433300
gpioPin = STM_LL_GPIO_PIN(digitalPinToPinName(p));
3301+
#elif defined(ARDUINO_ARCH_CH32)
3302+
PinName const pin_name = digitalPinToPinName(pin);
3303+
gpioPort = get_GPIO_Port(CH_PORT(pin_name));
3304+
gpioPin = CH_GPIO_PIN(pin_name);
3305+
#if defined (CH32V20x_D6)
3306+
if (gpioPort == GPIOC && ((*(volatile uint32_t*)0x40022030) & 0x0F000000) == 0) {
3307+
gpioPin = gpioPin >> 13;
3308+
}
3309+
#endif
31443310
#endif
31453311
}
31463312

@@ -3553,4 +3719,4 @@ neoPixelType Adafruit_NeoPixel::str2order(const char *v) {
35533719
}
35543720
if (w < 0) w = r; // If 'w' not specified, duplicate r bits
35553721
return (w << 6) | (r << 4) | ((g & 3) << 2) | (b & 3);
3556-
}
3722+
}

Adafruit_NeoPixel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ class Adafruit_NeoPixel {
398398
volatile uint8_t *port; ///< Output PORT register
399399
uint8_t pinMask; ///< Output PORT bitmask
400400
#endif
401-
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32)
401+
#if defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32) || defined(ARDUINO_ARCH_CH32)
402402
GPIO_TypeDef *gpioPort; ///< Output GPIO PORT
403403
uint32_t gpioPin; ///< Output GPIO PIN
404404
#endif

0 commit comments

Comments
 (0)