diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 3e07c245afd787ddb2209581f3b1ac02fbc99996..bea67b2a546714da791a3f92d85800417df8e3ec 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -4789,6 +4789,18 @@ RV_STATIC_INLINE void NVIC_SystemReset(void) NVIC->CFGR = NVIC_KEY3|(1<<7); } +// For configuring INTSYSCR, for interrupt nesting + hardware stack enable. +static inline uint32_t __get_INTSYSCR(void) +{ + uint32_t result; + asm volatile("csrr %0, 0x804": "=r"(result)); + return (result); +} + +static inline void __set_INTSYSCR( uint32_t value ) +{ + asm volatile("csrw 0x804, %0" : : "r"(value)); +} /********************************************************************* diff --git a/extralibs/ws2812b_dma_spi_led_driver.h b/extralibs/ws2812b_dma_spi_led_driver.h index 433fff7f92c439cab899d58bc35691694ebeba6e..115fea5078f5d6d760b856f17c8fe4a9a80c451a 100644 --- a/extralibs/ws2812b_dma_spi_led_driver.h +++ b/extralibs/ws2812b_dma_spi_led_driver.h @@ -3,13 +3,18 @@ to generate outputs very efficiently. So, for now, SPI Port. Additionally, it uses FAR less internal bus resources than to do the same thing with timers. - For the CH32V003 this means output will be on PORTC Pin 6 + **For the CH32V003 this means output will be on PORTC Pin 6** Copyright 2023 <>< Charles Lohr, under the MIT-x11 or NewBSD License, you choose! If you are including this in main, simply #define WS2812DMA_IMPLEMENTATION + Other defines inclue: + #define WSRBG + #define WSGRB + #define ALLOW_INTERRUPT_NESTING + You will need to implement the following two functions, as callbacks from the ISR. uint32_t WS2812BLEDCallback( int ledno ); @@ -219,6 +224,11 @@ void WS2812BDMAInit( ) // NVIC_SetPriority( DMA1_Channel3_IRQn, 0<<4 ); //We don't need to tweak priority. NVIC_EnableIRQ( DMA1_Channel3_IRQn ); DMA1_Channel3->CFGR |= DMA_CFGR1_EN; + +#ifdef ALLOW_INTERRUPT_NESTING + __set_INTSYSCR( 2 ); // Enable interrupt nesting. + PFIC->IPRIOR[24] = 0b10000000; // Turn on preemption for DMA1Ch3 +#endif } #endif diff --git a/extralibs/ws2812b_simple.h b/extralibs/ws2812b_simple.h new file mode 100644 index 0000000000000000000000000000000000000000..8c569fec01ebcb5b1e72b5f2d42065417f1ff6dc --- /dev/null +++ b/extralibs/ws2812b_simple.h @@ -0,0 +1,88 @@ +/* Single-File-Header for using asynchronous LEDs with the CH32V003 using DMA to the SPI port. + I may write another version of this to use DMA to timer ports, but, the SPI port can be used + to generate outputs very efficiently. So, for now, SPI Port. Additionally, it uses FAR less + internal bus resources than to do the same thing with timers. + + For the CH32V003 this means output will be on PORTC Pin 6 + + Copyright 2023 <>< Charles Lohr, under the MIT-x11 or NewBSD License, you choose! + + If you are including this in main, simply + #define WS2812BSIMPLE_IMPLEMENTATION + + You may also want to define + #define WS2812BSIMPLE_NO_IRQ_TWEAKING + +*/ + +#ifndef _WS2812B_SIMPLE +#define _WS2812B_SIMPLE + +#include <stdint.h> + +void WS2812BSimpleSend( GPIO_TypeDef * port, int pin, uint8_t * data, int len_in_bytes ); + +#ifdef WS2812BSIMPLE_IMPLEMENTATION + +#include "funconfig.h" + +#if FUNCONF_SYSTICK_USE_HCLK != 1 +#error WS2812B Driver Requires FUNCONF_SYSTICK_USE_HCLK +#endif + +void WS2812BSimpleSend( GPIO_TypeDef * port, int pin, uint8_t * data, int len_in_bytes ) +{ + int port_id = (((intptr_t)port-(intptr_t)GPIOA)>>10); + RCC->APB2PCENR |= (RCC_APB2Periph_GPIOA<<port_id); // Make sure port is enabled. + + int poffset = (pin*4); + port->CFGLR = ( port->CFGLR & (~(0xf<<poffset))) | ((GPIO_Speed_2MHz | GPIO_CNF_OUT_PP)<<(poffset)); + + int maskon = 1<<pin; + int maskoff = 1<<(16+pin); + + port->BSHR = maskoff; + + uint8_t * end = data + len_in_bytes; + while( data != end ) + { + uint8_t byte = *data; + + int i; + for( i = 0; i < 8; i++ ) + { + if( byte & 0x80 ) + { + // WS2812B's need AT LEAST 625ns for a logical "1" + port->BSHR = maskon; + DelaySysTick(25); + port->BSHR = maskoff; + DelaySysTick(1); + } + else + { + // WS2812B's need BETWEEN 62.5 to about 500 ns for a logical "0" +#ifndef WS2812BSIMPLE_NO_IRQ_TWEAKING + __disable_irq(); +#endif + port->BSHR = maskon; + asm volatile( "nop\nnop\nnop\nnop" ); + port->BSHR = maskoff; +#ifndef WS2812BSIMPLE_NO_IRQ_TWEAKING + __enable_irq(); +#endif + DelaySysTick(15); + } + byte <<= 1; + } + + data++; + } + + port->BSHR = maskoff; +} + +#endif + +#endif +