/* * LEDDriver.c * * Created on: Aug 26, 2013 * Author: Omri Iluz */ #include "ws2812.h" #include "stdlib.h" static uint8_t *fb; static int sLeds; static stm32_gpio_t *sPort; static uint32_t sMask; uint8_t* dma_source; void setColor(uint8_t color, uint8_t *buf,uint32_t mask){ int i; for (i=0;i<8;i++){ buf[i]=((color<BSRR.H.clear)); dmaStreamSetMemory0(STM32_DMA1_STREAM2, fb); dmaStreamSetTransactionSize(STM32_DMA1_STREAM2, (sLeds) * 24); dmaStreamSetMode( STM32_DMA1_STREAM2, STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(2)); // DMA stream 3, triggered by pwm update event. output high at beginning of signal dmaStreamAllocate(STM32_DMA1_STREAM3, 10, NULL, NULL); dmaStreamSetPeripheral(STM32_DMA1_STREAM3, &(sPort->BSRR.H.set)); dmaStreamSetMemory0(STM32_DMA1_STREAM3, dma_source); dmaStreamSetTransactionSize(STM32_DMA1_STREAM3, 1); dmaStreamSetMode( STM32_DMA1_STREAM3, STM32_DMA_CR_TEIE | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); // DMA stream 6, triggered by channel1 update event. reset output value late to indicate "1" bit to ws2812. // always triggers but no affect if dma stream 2 already change output value to 0 dmaStreamAllocate(STM32_DMA1_STREAM6, 10, NULL, NULL); dmaStreamSetPeripheral(STM32_DMA1_STREAM6, &(sPort->BSRR.H.clear)); dmaStreamSetMemory0(STM32_DMA1_STREAM6, dma_source); dmaStreamSetTransactionSize(STM32_DMA1_STREAM6, 1); dmaStreamSetMode( STM32_DMA1_STREAM6, STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); pwmStart(&PWMD2, &pwmc2); pwmStart(&PWMD3, &pwmc3); // set pwm3 as slave, triggerd by pwm2 oc1 event. disables pwmd2 for synchronization. PWMD3.tim->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2 | TIM_SMCR_TS_0; PWMD2.tim->CR1 &= ~TIM_CR1_CEN; // set pwm values. // 28 (duty in ticks) / 90 (period in ticks) * 1.25uS (period in S) = 0.39 uS pwmEnableChannel(&PWMD3, 2, 28); // 58 (duty in ticks) / 90 (period in ticks) * 1.25uS (period in S) = 0.806 uS pwmEnableChannel(&PWMD3, 0, 58); // active during transfer of 90 cycles * sLeds * 24 bytes * 1/90 multiplier pwmEnableChannel(&PWMD2, 0, 90 * sLeds * 24 / 90); // stop and reset counters for synchronization PWMD2.tim->CNT = 0; // Slave (TIM3) needs to "update" immediately after master (TIM2) start in order to start in sync. // this initial sync is crucial for the stability of the run PWMD3.tim->CNT = 89; PWMD3.tim->DIER |= TIM_DIER_CC3DE | TIM_DIER_CC1DE | TIM_DIER_UDE; dmaStreamEnable(STM32_DMA1_STREAM3); dmaStreamEnable(STM32_DMA1_STREAM6); dmaStreamEnable(STM32_DMA1_STREAM2); // all systems go! both timers and all channels are configured to resonate // in complete sync without any need for CPU cycles (only DMA and timers) // start pwm2 for system to start resonating PWMD2.tim->CR1 |= TIM_CR1_CEN; } void ledDriverWaitCycle(void){ while (PWMD2.tim->CNT < 90 * sLeds * 24 / 90){chThdSleepMicroseconds(1);}; } void testPatternFB(uint8_t *fb){ int i; Color tmpC = {rand()%256, rand()%256, rand()%256}; for (i=0;i