diff --git a/.cproject b/.cproject index 4ae66d1..371d3d3 100644 --- a/.cproject +++ b/.cproject @@ -105,42 +105,11 @@ - - - - - - + + @@ -250,285 +219,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/App/App.cpp b/App/App.cpp index ddcb009..f481d60 100644 --- a/App/App.cpp +++ b/App/App.cpp @@ -6,6 +6,7 @@ */ #include +#include #include "main.h" #include "dma.h" @@ -15,35 +16,11 @@ #include #include #include "Config.h" -#include "Pixel.h" -#include "LedBuffers.h" +#include "WS28xxStrip.h" #include "Sparkle.h" +WS28xxStrip g_strip( { DEFAULT_COLOR } ); Sparkle g_sparkles[NUMSPARKLES]; -volatile uint8_t g_spi_idle = 0; -volatile uint8_t g_buffer_in_transmit; -volatile uint16_t g_pixels_converted = 0; - -volatile uint32_t g_tick = 0; - -#define MIN(a,b) ((a) < (b) ? (a) : (b)) - -void convert(uint8_t *src, uint8_t *dst, uint16_t src_size) -{ - static uint16_t const bits[16] = { // due to LE-ness the bit order is 1 0 3 2 - 0b1000100010001000, 0b1000111010001000, 0b1110100010001000, 0b1110111010001000, - 0b1000100010001110, 0b1000111010001110, 0b1110100010001110, 0b1110111010001110, - 0b1000100011101000, 0b1000111011101000, 0b1110100011101000, 0b1110111011101000, - 0b1000100011101110, 0b1000111011101110, 0b1110100011101110, 0b1110111011101110 - }; - - uint16_t *dstptr = (uint16_t*)dst; - while(src_size--) { - uint8_t tmp =*src++; - *dstptr++ = bits[tmp >> 4]; - *dstptr++ = bits[tmp & 0x0f]; - } -} inline uint16_t rr(uint16_t top) { @@ -59,7 +36,7 @@ uint16_t ChoosePixel() do { chosen = rr(NUMPIXELS); for(spi=0; spi(g_sparkles[spi]) && static_cast(g_sparkles[spi]) == &g_pixels[chosen]) + if(static_cast(g_sparkles[spi]) && static_cast(g_sparkles[spi]) == &g_strip[chosen]) break; } } while(spi < NUMSPARKLES); @@ -72,92 +49,39 @@ uint16_t ChoosePixel() void StartSparkle( Sparkle &s ) { #ifndef DBG_CHOSEN_PIXEL - s.Start(g_pixels+ChoosePixel(), rr(32), Pixel(255,255,255), Pixel(rr(8)+3,rr(8)+3,rr(8)+3)); + s.Start(&g_strip[ChoosePixel()], rr(32), { 255,255,255 }, + { static_cast(rr(8)+3), static_cast(rr(8)+3), static_cast(rr(8)+3) }); #else - s.Start(g_pixels+ChoosePixel(), 0, Pixel(255,255,255), Pixel(1, 1, 1)); + s.Start(g_pixels+ChoosePixel(), 0, { 255,255,255 }, { 1, 1, 1 }); #endif } -extern "C" void HandleSystick() -{ - ++ g_tick; -} - extern "C" uint32_t GetTick() { return g_tick; } - extern "C" void HandleSpiDmaIrq() { - static bool endframe = false; - static bool endprev = false; - - if(LL_DMA_IsActiveFlag_TE3(DMA1)) { - LL_DMA_ClearFlag_TE3(DMA1); - } - else if(LL_DMA_IsActiveFlag_HT3(DMA1) || LL_DMA_IsActiveFlag_TC3(DMA1)) - { - if(LL_DMA_IsActiveFlag_HT3(DMA1)) - { - LL_DMA_ClearFlag_HT3(DMA1); - g_buffer_in_transmit = 1; - if(endframe) - LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MODE_NORMAL); - } - else if(LL_DMA_IsActiveFlag_TC3(DMA1)) - { - LL_DMA_ClearFlag_TC3(DMA1); - g_buffer_in_transmit = 0; - if(endframe && endprev) { - LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_3); - LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MODE_CIRCULAR); - g_spi_idle = true; - endframe = endprev = false; - return; - } - } - - endprev = endframe; - - uint8_t convert_now = MIN(NUMPIXELS - g_pixels_converted, SPIBUFFER_PIXELS); - - if(convert_now) - { - LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_13); - convert((uint8_t*)&g_pixels[g_pixels_converted], - g_spibuffer[g_buffer_in_transmit ^ 1], - convert_now * sizeof(pixel_t)); - LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_13); - g_pixels_converted += convert_now; - } - - if(convert_now < SPIBUFFER_PIXELS) { - memset(g_spibuffer[g_buffer_in_transmit ^ 1] + convert_now * SPIBUFFER_PIXEL_SIZE, - 0, SPIBUFFER_SIZE - convert_now * SPIBUFFER_PIXEL_SIZE); - endframe = true; - } - } + g_strip.SpiDmaIsr(); } - extern "C" void App() { uint32_t lastTick = GetTick(); - for(uint16_t px = 0; px < NUMPIXELS; ++px) - g_pixels[px] = Pixel(DEFAULT_COLOR); - LL_SYSTICK_EnableIT(); LL_SPI_Enable(SPI1); LL_SPI_EnableDMAReq_TX(SPI1); while(1) { - while(GetTick() - lastTick < FRAMETIME ); + while(GetTick() - lastTick < FRAMETIME ) + DoNothing(); lastTick += FRAMETIME; + LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_13); + for(int16_t spi = 0; spi < NUMSPARKLES; ++spi) { if(static_cast(g_sparkles[spi])) g_sparkles[spi].Step(); @@ -165,24 +89,6 @@ extern "C" void App() StartSparkle(g_sparkles[spi]); } - g_pixels_converted = 0; - - convert((uint8_t*)g_pixels, g_spibuffer[0], SPIBUFFER_PIXELS * sizeof(pixel_t)); - g_pixels_converted += SPIBUFFER_PIXELS; - convert((uint8_t*)&g_pixels[g_pixels_converted], g_spibuffer[1], SPIBUFFER_PIXELS * sizeof(pixel_t)); - g_pixels_converted += SPIBUFFER_PIXELS; - - g_buffer_in_transmit = 0; - g_spi_idle = false; - - LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_3, (uint32_t)g_spibuffer, LL_SPI_DMA_GetRegAddr(SPI1), LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_3, sizeof(g_spibuffer)); - LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_3); - LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_3); - LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_3); - LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_3); - - while(!g_spi_idle); - + g_strip.Update(); } } diff --git a/App/LedBuffers.cpp b/App/LedBuffers.cpp deleted file mode 100644 index 45a7f83..0000000 --- a/App/LedBuffers.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * LedBuffers.c - * - * Created on: Dec 16, 2018 - * Author: abody - */ -#include "LedBuffers.h" - -pixel_t g_pixels[NUMPIXELS]; - -uint8_t g_spibuffer[2][SPIBUFFER_SIZE]; diff --git a/App/LedBuffers.h b/App/LedBuffers.h deleted file mode 100644 index c0ad896..0000000 --- a/App/LedBuffers.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * LedBuffers.h - * - * Created on: Dec 16, 2018 - * Author: abody - */ - -#ifndef LEDBUFFERS_H_ -#define LEDBUFFERS_H_ - -#include "Config.h" -#include "Pixel.h" - -extern pixel_t g_pixels[NUMPIXELS]; - -#define SPIBUFFER_PIXEL_SIZE ( sizeof(pixel_t) * 4) // each raw pixel bit represented by 4 bits in SPI transfer -#define SPIBUFFER_SIZE (SPIBUFFER_PIXELS * SPIBUFFER_PIXEL_SIZE) - -extern uint8_t g_spibuffer[2][SPIBUFFER_SIZE]; - -#endif /* LEDBUFFERS_H_ */ diff --git a/App/Pixel.h b/App/Pixel.h deleted file mode 100644 index 79fe085..0000000 --- a/App/Pixel.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Pixel.h - * - * Created on: Dec 16, 2018 - * Author: abody - */ - -#ifndef PIXEL_H_ -#define PIXEL_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint8_t g; - uint8_t r; - uint8_t b; -} pixel_t; - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus -struct Pixel : public pixel_t { - Pixel(uint8_t _r, uint8_t _g, uint8_t _b) { - g =_g; - r = _r; - b = _b; - } -}; -#endif - -#endif /* PIXEL_H_ */ diff --git a/App/Sparkle.h b/App/Sparkle.h index 86922a8..d7b5da3 100644 --- a/App/Sparkle.h +++ b/App/Sparkle.h @@ -8,7 +8,7 @@ #ifndef SPARKLE_H_ #define SPARKLE_H_ #include -#include "Pixel.h" +#include "WS28xxStrip.h" class Sparkle { public: diff --git a/App/WS28xxStrip.h b/App/WS28xxStrip.h new file mode 100644 index 0000000..b8dfe0c --- /dev/null +++ b/App/WS28xxStrip.h @@ -0,0 +1,167 @@ +/* + * WS28xxStrip.h + * + * Created on: Dec 2, 2020 + * Author: compi + */ + +#ifndef WS28XXSTRIP_H_ +#define WS28XXSTRIP_H_ + +#include +#include +#include +#include + +struct pixel_t { + uint8_t g; + uint8_t r; + uint8_t b; +}; + +extern "C" void HandleSpiDmaIrq(); + +template class WS28xxStrip { +public: + WS28xxStrip(pixel_t defcolor); + + pixel_t& operator[](int16_t index); + + friend void HandleSpiDmaIrq(); + void Update(); + +private: + void SpiDmaIsr(); + void Refill(); + void Convert(uint8_t *src, uint8_t *dst, uint16_t src_size); + template T Min(T a, T b) { return a < b ? a : b; } + + static constexpr const unsigned int SPI_PIXEL_SIZE = sizeof(pixel_t) * 4; + static constexpr const unsigned int SPI_BUFFER_SIZE = spi_pixels * SPI_PIXEL_SIZE; + + pixel_t m_pixels[pixels]; + uint8_t m_spi_buffer[2][SPI_BUFFER_SIZE]; + + volatile uint8_t m_spi_idle = 0; + volatile uint8_t m_buffer_in_transmit; + volatile uint16_t m_pixels_converted = 0; + volatile bool m_endframe = false; + volatile bool m_endprev = false; + volatile bool m_need_refill = false; +}; + +template WS28xxStrip::WS28xxStrip(pixel_t defcolor) +{ + for(uint16_t p=0; p < pixels; ++p) + m_pixels[p] = defcolor; +} + +template pixel_t& WS28xxStrip::operator[](int16_t index) +{ + return m_pixels[index]; +} + +template void WS28xxStrip::SpiDmaIsr() +{ + if(LL_DMA_IsActiveFlag_TE3(DMA1)) { + LL_DMA_ClearFlag_TE3(DMA1); + } + else if(LL_DMA_IsActiveFlag_HT3(DMA1) || LL_DMA_IsActiveFlag_TC3(DMA1)) + { + if(LL_DMA_IsActiveFlag_HT3(DMA1)) + { + LL_DMA_ClearFlag_HT3(DMA1); + m_buffer_in_transmit = 1; + if(m_endframe) + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MODE_NORMAL); + } + else if(LL_DMA_IsActiveFlag_TC3(DMA1)) + { + LL_DMA_ClearFlag_TC3(DMA1); + m_buffer_in_transmit = 0; + if(m_endframe && m_endprev) { + LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_3); + LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MODE_CIRCULAR); + m_spi_idle = true; + m_endframe = m_endprev = false; + return; + } + } + + m_need_refill = true; + } +} + + +template void WS28xxStrip::Refill() +{ + m_need_refill = false; + m_endprev = m_endframe; + + uint8_t convert_now = Min((uint8_t)(pixels - m_pixels_converted), spi_pixels); + + if(convert_now) + { + LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_13); + Convert((uint8_t*)&m_pixels[m_pixels_converted], + m_spi_buffer[m_buffer_in_transmit ^ 1], + convert_now * sizeof(pixel_t)); + LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_13); + m_pixels_converted += convert_now; + } + + if(convert_now < spi_pixels) { + memset(m_spi_buffer[m_buffer_in_transmit ^ 1] + convert_now * SPI_PIXEL_SIZE, + 0, SPI_BUFFER_SIZE - convert_now * SPI_PIXEL_SIZE); + m_endframe = true; + } + +} + + +template void WS28xxStrip::Update() +{ + m_pixels_converted = 0; + + Convert((uint8_t*)m_pixels, m_spi_buffer[0], spi_pixels * sizeof(pixel_t)); + m_pixels_converted += spi_pixels; + Convert((uint8_t*)&m_pixels[m_pixels_converted], m_spi_buffer[1], spi_pixels * sizeof(pixel_t)); + m_pixels_converted += spi_pixels; + + m_buffer_in_transmit = 0; + m_spi_idle = false; + + LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_3, (uint32_t)m_spi_buffer, LL_SPI_DMA_GetRegAddr(SPI1), LL_DMA_DIRECTION_MEMORY_TO_PERIPH); + LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_3, sizeof(m_spi_buffer)); + LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_3); + LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_3); + LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_3); + LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_3); + + while(!m_spi_idle) { + while(!m_spi_idle && !m_need_refill); + if(m_need_refill) + Refill(); + } +} + + +template void WS28xxStrip::Convert(uint8_t *src, uint8_t *dst, uint16_t src_size) +{ + static uint16_t const bits[16] = { // due to LE-ness the bit order is 1 0 3 2 + 0b1000100010001000, 0b1000111010001000, 0b1110100010001000, 0b1110111010001000, + 0b1000100010001110, 0b1000111010001110, 0b1110100010001110, 0b1110111010001110, + 0b1000100011101000, 0b1000111011101000, 0b1110100011101000, 0b1110111011101000, + 0b1000100011101110, 0b1000111011101110, 0b1110100011101110, 0b1110111011101110 + }; + + uint16_t *dstptr = (uint16_t*)dst; + while(src_size--) { + uint8_t tmp =*src++; + *dstptr++ = bits[tmp >> 4]; + *dstptr++ = bits[tmp & 0x0f]; + } +} + + +#endif /* WS28XXSTRIP_H_ */ diff --git a/Inc/main.h b/Inc/main.h index 6175e12..40afecc 100644 --- a/Inc/main.h +++ b/Inc/main.h @@ -51,6 +51,7 @@ extern "C" { /* Exported types ------------------------------------------------------------*/ /* USER CODE BEGIN ET */ +extern volatile uint32_t g_tick; /* USER CODE END ET */ @@ -68,6 +69,7 @@ extern "C" { void Error_Handler(void); /* USER CODE BEGIN EFP */ +void DoNothing(); /* USER CODE END EFP */ diff --git a/Src/main.c b/Src/main.c index bf566a5..ce0a0d6 100644 --- a/Src/main.c +++ b/Src/main.c @@ -26,8 +26,6 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include -#include "App/Pixel.h" -#include "App/LedBuffers.h" /* USER CODE END Includes */ @@ -49,6 +47,7 @@ /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ +volatile uint32_t g_tick = 0; /* USER CODE END PV */ @@ -61,6 +60,11 @@ void App(); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ +void DoNothing() +{ + static volatile uint32_t cntr = 0; + ++ cntr; +} /* USER CODE END 0 */ @@ -106,12 +110,14 @@ int main(void) MX_SPI1_Init(); /* USER CODE BEGIN 2 */ + LL_SYSTICK_EnableIT(); + /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while(1) { - App(); + App(); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ diff --git a/Src/stm32f1xx_it.c b/Src/stm32f1xx_it.c index 09e085c..1c8ed59 100644 --- a/Src/stm32f1xx_it.c +++ b/Src/stm32f1xx_it.c @@ -184,7 +184,7 @@ void PendSV_Handler(void) void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ - HandleSystick(); + ++g_tick; /* USER CODE END SysTick_IRQn 0 */ /* USER CODE BEGIN SysTick_IRQn 1 */