16x16 square of neopixels for stm32f3 discovery board
Dependencies: STM32F3-Discovery-minimal
Fork of neopixels by
Revision 1:6ed7aa3c8efa, committed 2018-05-07
- Comitter:
- MartinJohnson
- Date:
- Mon May 07 10:34:40 2018 +0000
- Parent:
- 0:d89511b21e3d
- Commit message:
- 16x16 neopixel square with moving pattern
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/STM32F3-Discovery-minimal.lib Mon May 07 10:34:40 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/MartinJohnson/code/STM32F3-Discovery-minimal/#c65854d98061
--- a/STM32F3-Discovery.lib Wed May 25 23:54:30 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/MartinJohnson/code/STM32F3-Discovery/#404f5a4f1385
--- a/neopixel.c Wed May 25 23:54:30 2016 +0000 +++ b/neopixel.c Mon May 07 10:34:40 2018 +0000 @@ -1,25 +1,13 @@ #include <stm32f30x.h> -//#include <stm32f30x_misc.h> -//#define ARM_MATH_CM4 #include <math.h> #include "stm32f3_discovery_lsm303dlhc.h" +#include <stdio.h> #include <stdlib.h> -#define WS2812_GPIO GPIOB -#define WS2812_GPIO_AHB_PERIPHERAL RCC_AHBPeriph_GPIOB -#define WS2812_GPIO_AF GPIO_AF_1 -#define WS2812_PIN GPIO_Pin_8 // TIM16_CH1 -#define WS2812_PIN_SOURCE GPIO_PinSource8 -#define WS2812_TIMER TIM16 -#define WS2812_TIMER_APB2_PERIPHERAL RCC_APB2Periph_TIM16 -#define WS2812_DMA_CHANNEL DMA1_Channel3 -#define WS2812_IRQ DMA1_Channel3_IRQn -#define WS2812_DMA_TC_FLAG DMA1_FLAG_TC3 - #define PI 3.1415926f -#define WS2812_LED_STRIP_LENGTH 60 +#define WS2812_LED_STRIP_LENGTH 256 #define WS2812_BITS_PER_LED 24 #define WS2812_DELAY_BUFFER_LENGTH 42 // for 50us delay @@ -29,28 +17,117 @@ #define WS2812_DMA_BUFFER_SIZE (WS2812_DATA_BUFFER_SIZE + WS2812_DELAY_BUFFER_LENGTH) // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes) -static volatile uint8_t ledStripDMABuffer[WS2812_DMA_BUFFER_SIZE]; + +#define I2C_CR2_CLEAR_MASK ~(I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN | I2C_CR2_START | I2C_CR2_STOP) + +void i2cWrite(int address, int reg, int val) { + while(I2C1->ISR & I2C_ISR_BUSY); + I2C1->CR2 = (I2C1->CR2 & I2C_CR2_CLEAR_MASK) | I2C_CR2_RELOAD | I2C_CR2_START | (1<<16) | address; + while(!(I2C1->ISR & I2C_ISR_TXIS)); + I2C1->TXDR=reg; + while(!(I2C1->ISR & I2C_ISR_TCR)); + I2C1->CR2 = (I2C1->CR2 & I2C_CR2_CLEAR_MASK) | I2C_CR2_AUTOEND | (1<<16) | address; + while(!(I2C1->ISR & I2C_ISR_TXIS)); + I2C1->TXDR=val; + while(!(I2C1->ISR & I2C_ISR_STOPF)); + I2C1->ICR = I2C_ICR_STOPCF; +} -//static volatile uint8_t rgbData[WS2812_LED_STRIP_LENGTH*3]; +void i2cRead(int address, int reg, uint8_t *data, int nbytes) { + while(I2C1->ISR & I2C_ISR_BUSY); + I2C1->CR2 = (I2C1->CR2 & I2C_CR2_CLEAR_MASK) | I2C_CR2_START | (1<<16) | address; + while(!(I2C1->ISR & I2C_ISR_TXIS)); + if(nbytes>1) reg |= 0x80; + I2C1->TXDR=reg; + while(!(I2C1->ISR & I2C_ISR_TC)); + I2C1->CR2 = (I2C1->CR2 & I2C_CR2_CLEAR_MASK) | I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_RD_WRN | (nbytes<<16) | address; + while(nbytes--) { + while(!(I2C1->ISR & I2C_ISR_RXNE)); + *data++=I2C1->RXDR; + } + while(!(I2C1->ISR & I2C_ISR_STOPF)); + I2C1->ICR = I2C_ICR_STOPCF; +} +#define GPIO_MODE_INPUT 0 +#define GPIO_MODE_OUTPUT 1 +#define GPIO_MODE_AF 2 + +#define GPIO_PULL_UP 1 +#define GPIO_PULL_DOWN 2 + +#define GPIO_OUTPUT_PUSH_PULL 0 + +#define GPIO_SPEED_FAST 3 + +void gpio_set_mode(GPIO_TypeDef *g,int n,int mode) { + n=n<<1; + g->MODER = (g->MODER & ~(3<<n)) | (mode<<n); +} -static volatile uint8_t WS2812LedDataTransferInProgress = 0; -static uint16_t dmaBufferOffset; -static int16_t ledIndex; +void gpio_set_af(GPIO_TypeDef *g,int n,int af, int otype, int pupd, int speed) { + int reg=n>>3; + int pos=(n&7)*4; + g->AFR[reg] = (g->AFR[reg] & ~(0xf<<pos)) | (af<<pos); // alt func + pos=(n<<1); + g->OSPEEDR = (g->OSPEEDR & ~(3<<pos)) | (speed<<pos); + g->OTYPER = (g->OTYPER & ~(1<<n)) | (otype<<n); + gpio_set_mode(g,n,GPIO_MODE_AF); + g->PUPDR = (g->PUPDR & ~(3<<pos)) | (pupd<<pos); +} + +void i2cInit() { + RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; + RCC->AHBENR |= RCC_AHBENR_GPIOBEN; + // configure GPIOPB6 and 7 + gpio_set_af(GPIOB,6,4,GPIO_OUTPUT_PUSH_PULL,GPIO_PULL_DOWN,GPIO_SPEED_FAST); + gpio_set_af(GPIOB,7,4,GPIO_OUTPUT_PUSH_PULL,GPIO_PULL_DOWN,GPIO_SPEED_FAST); + + I2C1->TIMINGR = 0x00902025; + I2C1->CR1 |= I2C_CR1_PE; + +} + +void MemsConfig(void) +{ + i2cInit(); + i2cWrite(ACC_I2C_ADDRESS, LSM303DLHC_CTRL_REG1_A,LSM303DLHC_NORMAL_MODE | LSM303DLHC_ODR_50_HZ | LSM303DLHC_AXES_ENABLE); + i2cWrite(ACC_I2C_ADDRESS, LSM303DLHC_CTRL_REG4_A,LSM303DLHC_FULLSCALE_2G | LSM303DLHC_BlockUpdate_Continous | LSM303DLHC_BLE_LSB | LSM303DLHC_HR_ENABLE); + i2cWrite(ACC_I2C_ADDRESS, LSM303DLHC_CTRL_REG2_A,LSM303DLHC_HPM_NORMAL_MODE | LSM303DLHC_HPFCF_16 | LSM303DLHC_HPF_AOI1_DISABLE | LSM303DLHC_HPF_AOI2_DISABLE); + + i2cWrite(MAG_I2C_ADDRESS, LSM303DLHC_CRA_REG_M, LSM303DLHC_TEMPSENSOR_ENABLE | LSM303DLHC_ODR_30_HZ); + i2cWrite(MAG_I2C_ADDRESS, LSM303DLHC_CRB_REG_M, LSM303DLHC_FS_8_1_GA); + i2cWrite(MAG_I2C_ADDRESS, LSM303DLHC_MR_REG_M,LSM303DLHC_CONTINUOS_CONVERSION); +} + +void ReadAccelerometer(int16_t * data) { + i2cRead(ACC_I2C_ADDRESS, LSM303DLHC_OUT_X_L_A, (uint8_t *)data, 6); +} + +void ReadMagnetometer(int16_t * data) { + i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_L_M, (uint8_t *)data, 1); + i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_H_M, (uint8_t *)data+1, 1); + i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Y_L_M, (uint8_t *)data+2, 1); + i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Y_H_M, (uint8_t *)data+3, 1); + i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Z_L_M, (uint8_t *)data+4, 1); + i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Z_H_M, (uint8_t *)data+5, 1); +} + +int ReadTemperature() { + int t=0; + i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_TEMP_OUT_L_M, (uint8_t *)&t,1); + i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_TEMP_OUT_H_M, (uint8_t *)&t+1,1); + return t/64; +} + +static uint8_t ledStripDMABuffer[WS2812_DMA_BUFFER_SIZE]; + +static uint8_t WS2812LedDataTransferInProgress = 0; volatile unsigned sysTiming; volatile unsigned sysTicks = 0; -int sysInitSystemTimer(void) { - - if (SysTick_Config((SystemCoreClock / 1000) -1 )) { - return(0); - } - return(1); -} void sysDelayMs(unsigned dly) { - sysTiming = dly; - while (sysTiming > 0) __wfi(); } @@ -59,234 +136,88 @@ if (sysTiming > 0) --sysTiming; } -void AccelerometerConfig(void) -{ - LSM303DLHCMag_InitTypeDef LSM303DLHC_InitStructure; - LSM303DLHCAcc_InitTypeDef LSM303DLHCAcc_InitStructure; - LSM303DLHCAcc_FilterConfigTypeDef LSM303DLHCFilter_InitStructure; - - /* Configure MEMS magnetometer main parameters: temp, working mode, full Scale and Data rate */ - LSM303DLHC_InitStructure.Temperature_Sensor = LSM303DLHC_TEMPSENSOR_DISABLE; - LSM303DLHC_InitStructure.MagOutput_DataRate =LSM303DLHC_ODR_30_HZ ; - LSM303DLHC_InitStructure.MagFull_Scale = LSM303DLHC_FS_8_1_GA; - LSM303DLHC_InitStructure.Working_Mode = LSM303DLHC_CONTINUOS_CONVERSION; - LSM303DLHC_MagInit(&LSM303DLHC_InitStructure); - - /* Fill the accelerometer structure */ - LSM303DLHCAcc_InitStructure.Power_Mode = LSM303DLHC_NORMAL_MODE; - LSM303DLHCAcc_InitStructure.AccOutput_DataRate = LSM303DLHC_ODR_50_HZ; - LSM303DLHCAcc_InitStructure.Axes_Enable= LSM303DLHC_AXES_ENABLE; - LSM303DLHCAcc_InitStructure.AccFull_Scale = LSM303DLHC_FULLSCALE_2G; - LSM303DLHCAcc_InitStructure.BlockData_Update = LSM303DLHC_BlockUpdate_Continous; - LSM303DLHCAcc_InitStructure.Endianness=LSM303DLHC_BLE_LSB; - LSM303DLHCAcc_InitStructure.High_Resolution=LSM303DLHC_HR_ENABLE; - /* Configure the accelerometer main parameters */ - LSM303DLHC_AccInit(&LSM303DLHCAcc_InitStructure); - - /* Fill the accelerometer LPF structure */ - LSM303DLHCFilter_InitStructure.HighPassFilter_Mode_Selection =LSM303DLHC_HPM_NORMAL_MODE; - LSM303DLHCFilter_InitStructure.HighPassFilter_CutOff_Frequency = LSM303DLHC_HPFCF_16; - LSM303DLHCFilter_InitStructure.HighPassFilter_AOI1 = LSM303DLHC_HPF_AOI1_DISABLE; - LSM303DLHCFilter_InitStructure.HighPassFilter_AOI2 = LSM303DLHC_HPF_AOI2_DISABLE; - - /* Configure the accelerometer LPF main parameters */ - LSM303DLHC_AccFilterConfig(&LSM303DLHCFilter_InitStructure); -} - -void ReadAccelerometer(float * data) -{ - uint8_t buffer[6]; - - LSM303DLHC_Read(ACC_I2C_ADDRESS, LSM303DLHC_OUT_X_L_A, buffer, 6); - - for(int i=0; i<3; i++) { - data[i]=(float)((int16_t)((uint16_t)buffer[2*i+1] << 8) + buffer[2*i])/16; - } -} +void GPIO_init(void) { + + RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOEEN ; + RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM2EN; + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_TIM16EN; -void ReadMagnetometer (float* pfData) -{ - static uint8_t buffer[6] = {0}; - uint8_t CTRLB = 0; - uint16_t Magn_Sensitivity_XY = 0, Magn_Sensitivity_Z = 0; - uint8_t i =0; - LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_CRB_REG_M, &CTRLB, 1); - - LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_H_M, buffer, 1); - LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_L_M, buffer+1, 1); - LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Y_H_M, buffer+2, 1); - LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Y_L_M, buffer+3, 1); - LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Z_H_M, buffer+4, 1); - LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Z_L_M, buffer+5, 1); - /* Switch the sensitivity set in the CRTLB*/ - switch(CTRLB & 0xE0) - { - case LSM303DLHC_FS_1_3_GA: - Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_1_3Ga; - Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_1_3Ga; - break; - case LSM303DLHC_FS_1_9_GA: - Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_1_9Ga; - Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_1_9Ga; - break; - case LSM303DLHC_FS_2_5_GA: - Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_2_5Ga; - Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_2_5Ga; - break; - case LSM303DLHC_FS_4_0_GA: - Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_4Ga; - Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_4Ga; - break; - case LSM303DLHC_FS_4_7_GA: - Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_4_7Ga; - Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_4_7Ga; - break; - case LSM303DLHC_FS_5_6_GA: - Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_5_6Ga; - Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_5_6Ga; - break; - case LSM303DLHC_FS_8_1_GA: - Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_8_1Ga; - Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_8_1Ga; - break; - } - - for(i=0; i<2; i++) - { - pfData[i]=(float)((int16_t)(((uint16_t)buffer[2*i] << 8) + buffer[2*i+1])*1000)/Magn_Sensitivity_XY; - } - pfData[2]=(float)((int16_t)(((uint16_t)buffer[4] << 8) + buffer[5])*1000)/Magn_Sensitivity_Z; -} + SysTick_Config((SystemCoreClock / 1000) -1 ); + + gpio_set_af(GPIOB,8,1,GPIO_OUTPUT_PUSH_PULL,GPIO_PULL_UP,GPIO_SPEED_FAST); -void GPIO_init(void) { - GPIO_InitTypeDef GPIO_InitStructure; - // GPIOA Periph clock enable - RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); - RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOE, ENABLE); - RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); - RCC_APB2PeriphClockCmd(WS2812_TIMER_APB2_PERIPHERAL, ENABLE); - - sysInitSystemTimer(); - /* Configuration alternate function push-pull */ - GPIO_StructInit(&GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = WS2812_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_Init(WS2812_GPIO, &GPIO_InitStructure); - - GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1); // pb8 is tim16 ch1 - - GPIO_InitStructure.GPIO_Pin = - GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | - GPIO_Pin_14 | GPIO_Pin_15; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_Init(GPIOE, &GPIO_InitStructure); - - GPIO_StructInit(&GPIO_InitStructure); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_Init(GPIOA, &GPIO_InitStructure); - - - GPIOE->ODR ^= 0x100; + GPIOE->MODER = (GPIOE->MODER&0xffff) | 0x55550000; // output mode for PE8-15 + GPIOA->MODER = (GPIOA->MODER&0xfffffffc) ; // input mode for PA0 + GPIOA->PUPDR = (GPIOA->PUPDR & ~0x3) | 0x2; // pull down (10) } void TIM_init(void) { - TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; - TIM_OCInitTypeDef TIM_OCInitStructure; -// NVIC_InitTypeDef NVIC_InitStructure; - uint16_t PrescalerValue; - - PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; - /* Time base configuration */ - TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); - TIM_TimeBaseStructure.TIM_Period = 29; // 800kHz - TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; - TIM_TimeBaseStructure.TIM_ClockDivision = 0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInit(WS2812_TIMER, &TIM_TimeBaseStructure); + TIM16->CR1 &= ~TIM_CR1_CEN; + TIM16->PSC=(uint16_t) (SystemCoreClock / 24000000) - 1; + TIM16->CNT=0; + TIM16->ARR=29; // 24MHz/30=800KHz + TIM16->CR1 |= TIM_CR1_CEN; - /* PWM1 Mode configuration */ - TIM_OCStructInit(&TIM_OCInitStructure); - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; - TIM_OCInitStructure.TIM_Pulse = 0; - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; - TIM_OC1Init(WS2812_TIMER, &TIM_OCInitStructure); - TIM_OC1PreloadConfig(WS2812_TIMER, TIM_OCPreload_Enable); - TIM_CtrlPWMOutputs(WS2812_TIMER, ENABLE); + // disable Capture and Compare 1 + TIM16->CCER &= ~TIM_CCER_CC1E; + // set output compare 1 to PWM mode with preload + TIM16->CCMR1 = (TIM16->CCMR1 & ~(TIM_CCMR1_OC1M | TIM_CCMR1_CC1S)) | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE ; + // enable Capture and Compare 1 + TIM16->CCER |= TIM_CCER_CC1E; + // main output enable + TIM16->BDTR |= TIM_BDTR_MOE; } void DMA_init(void) { - DMA_InitTypeDef DMA_InitStructure; - /* configure DMA */ - /* DMA clock enable */ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); - /* DMA Channel Config */ - DMA_DeInit(WS2812_DMA_CHANNEL); - DMA_StructInit(&DMA_InitStructure); - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & WS2812_TIMER->CCR1; - DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) ledStripDMABuffer; - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; - DMA_InitStructure.DMA_BufferSize = WS2812_DMA_BUFFER_SIZE; - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; - DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; - DMA_InitStructure.DMA_Priority = DMA_Priority_High; - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; - DMA_Init(WS2812_DMA_CHANNEL, &DMA_InitStructure); - TIM_DMACmd(WS2812_TIMER, TIM_DMA_CC1, ENABLE); - DMA_ITConfig(WS2812_DMA_CHANNEL, DMA_IT_TC, ENABLE); - NVIC_InitTypeDef NVIC_InitStructure; - NVIC_InitStructure.NVIC_IRQChannel = WS2812_IRQ; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); + // enable DMA1 controller + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + // direction = peripheral dest, memory inc, peripheral size=halfword, memory size=byte, priority level=high, transmission complete interrupt enabled + DMA1_Channel3->CCR = DMA_CCR_DIR | DMA_CCR_MINC | DMA_CCR_PSIZE_0 | DMA_CCR_PL_1 | DMA_CCR_TCIE; + // bytes to transfer + DMA1_Channel3->CNDTR = WS2812_DMA_BUFFER_SIZE; + // peripheral address + DMA1_Channel3->CPAR =(uint32_t)&TIM16->CCR1; + // memory address + DMA1_Channel3->CMAR =(uint32_t)ledStripDMABuffer; + // enable CC DMA for TIM16 + TIM16->DIER |= TIM_DIER_CC1DE; + // configure NVIC + NVIC->IP[DMA1_Channel3_IRQn]=16; // Interrupt Priority, lower is higher priority + NVIC->ISER[DMA1_Channel3_IRQn >> 0x05] = 1 << (DMA1_Channel3_IRQn & 0x1F); // Interrupt enable + } void WS2812LedStripDMAEnable(void) { - DMA_SetCurrDataCounter(WS2812_DMA_CHANNEL, - WS2812_DMA_BUFFER_SIZE); // load number of bytes to be transferred - TIM_SetCounter(WS2812_TIMER, 0); - TIM_Cmd(WS2812_TIMER, ENABLE); - DMA_Cmd(WS2812_DMA_CHANNEL, ENABLE); + // bytes to transfer + DMA1_Channel3->CNDTR = WS2812_DMA_BUFFER_SIZE; + TIM16->CNT=0; + // start counter + TIM16->CCER |= TIM_CCER_CC1E; + // enable DMA + DMA1_Channel3->CCR |= DMA_CCR_EN; } void DMA1_Channel3_IRQHandler(void) { -// GPIOE->ODR ^= 0x1000; - if (DMA_GetFlagStatus(WS2812_DMA_TC_FLAG)) { - WS2812LedDataTransferInProgress = 0; - DMA_Cmd(WS2812_DMA_CHANNEL, DISABLE); - DMA_ClearFlag(WS2812_DMA_TC_FLAG); + // if transfer complete + if(DMA1->ISR & DMA_ISR_TCIF3) { + WS2812LedDataTransferInProgress = 0; + // disable DMA + DMA1_Channel3->CCR &= ~DMA_CCR_EN; + // clear flag + DMA1->IFCR = DMA_ISR_TCIF3; } } -void updateLEDDMABuffer(uint8_t componentValue) { - uint8_t bitIndex; - - for (bitIndex = 0; bitIndex < 8; bitIndex++) { - if ((componentValue << bitIndex) & - 0x80) // data sent MSB first, j = 0 is MSB j = 7 is LSB - { - ledStripDMABuffer[dmaBufferOffset] = BIT_COMPARE_1; - } - else { - ledStripDMABuffer[dmaBufferOffset] = BIT_COMPARE_0; // compare value for logical 0 - } - dmaBufferOffset++; +uint8_t *updateLEDDMABuffer(uint8_t *buffer, unsigned val) { + for (int i=0;i<8;i++) { + if ((val) & (0x80)) // data sent MSB first + *buffer++=BIT_COMPARE_1; // pwm level for 1 + else + *buffer++=BIT_COMPARE_0; // pwm level for 0 + val=val<<1; // move to next bit } + return buffer; } typedef struct { @@ -298,22 +229,13 @@ static volatile rgb_struct rgbData[WS2812_LED_STRIP_LENGTH]; void WS2812UpdateStrip(void) { - static uint32_t waitCounter = 0; - // wait until previous transfer completes - while (WS2812LedDataTransferInProgress) { - waitCounter++; - } - - dmaBufferOffset = 0; // reset buffer memory index - ledIndex = 0; // reset led index - - // fill transmit buffer with correct compare values to achieve - // correct pulse widths according to color values - while (ledIndex < WS2812_LED_STRIP_LENGTH) { - updateLEDDMABuffer(rgbData[ledIndex].green); - updateLEDDMABuffer(rgbData[ledIndex].red); - updateLEDDMABuffer(rgbData[ledIndex++].blue); + while (WS2812LedDataTransferInProgress) __wfi(); + uint8_t *buffer=ledStripDMABuffer; + for(int i=0;i<WS2812_LED_STRIP_LENGTH;i++) { + buffer=updateLEDDMABuffer(buffer,rgbData[i].green); + buffer=updateLEDDMABuffer(buffer,rgbData[i].red); + buffer=updateLEDDMABuffer(buffer,rgbData[i].blue); } WS2812LedDataTransferInProgress = 1; @@ -322,17 +244,6 @@ extern volatile unsigned sysTicks; int rndseed=0; -/* -void srand(int i) { - rndseed = i; -} - - -int rand() { - return (((rndseed = rndseed * 214013L + 2531011L) >> 16) & - 0x7fff); -} -*/ void WS2812LedStripInit(void) { int i; @@ -340,22 +251,17 @@ ledStripDMABuffer[i] = 0; WS2812UpdateStrip(); } -static float AccBuffer[3] = {0.0f}; -static float MagBuffer[3] = {0.0f}; +static short AccBuffer[3] = {0}; +static short MagBuffer[3] = {0}; -//extern float arm_sqrt_f32(float f); int getheading() { /* Read Compass data */ ReadMagnetometer(MagBuffer); ReadAccelerometer(AccBuffer); - int i; float fNormAcc, fSinRoll, fCosRoll, fSinPitch, fCosPitch = 0.0f, RollAng = 0.0f, PitchAng = 0.0f; float fTiltedX, fTiltedY = 0.0f; float HeadingValue; - - for (i = 0; i < 3; i++) - AccBuffer[i] /= 100.0f; - + fNormAcc = sqrtf((AccBuffer[0] * AccBuffer[0]) + (AccBuffer[1] * AccBuffer[1]) + (AccBuffer[2] * AccBuffer[2])); @@ -415,7 +321,6 @@ HeadingValue = HeadingValue + 360; } return HeadingValue; - } int main(void) { @@ -427,47 +332,68 @@ int btn=0; uint32_t rgb = 0x0ff0000ff; GPIO_init(); - GPIOE->ODR ^= 0x100; DMA_init(); - GPIOE->ODR ^= 0x200; TIM_init(); - AccelerometerConfig(); + MemsConfig(); WS2812LedDataTransferInProgress = 0; WS2812LedStripInit(); - btn=GPIOA->IDR; - if((GPIOA->IDR & 1)==1) { - // a giant compass! - while (1) { - int heading = getheading(); - int led = (heading * WS2812_LED_STRIP_LENGTH) / 360; - int next = (led + 1) % WS2812_LED_STRIP_LENGTH; - int v2 = (heading - (led * 360) / WS2812_LED_STRIP_LENGTH) * 10; - int v1 = 225 - v2; - - rgbData[led].red = v1; - rgbData[next].red = v2; + + float yo=7.5,xo=7.5; + float xs=1,ys=1; + float offset=0; + while(!(GPIOA->IDR & 1)) { + offset-=0.3f; + //int heading = getheading(); + ReadAccelerometer(AccBuffer); + int x=(int)AccBuffer[0]/32; + int y=(int)AccBuffer[1]/32; + ys=y/180.0+1; + xs=x/180.0+1; - WS2812UpdateStrip(); - // wait 5ms - sysDelayMs(15); - rgbData[led].red = 0; - rgbData[next].red = 0; + for (int i = 0; i < 256; i++) { + int y1=i/16; + int x1=i%16; + if(y1%2) x1=15-x1; + y1=15-y1; + + double d=(sqrt(abs(ys*(y1-yo)*(y1-yo)+xs*(x1-xo)*(x1-xo)))+offset)/4.0; + rgbData[i].red=(uint8_t)(round(4.0*sin(1.0299*d)+4.0)/1); + rgbData[i].green=(uint8_t)(round(4.0*cos(3.2235*d)+4.0)/1); + rgbData[i].blue=(uint8_t)(round(4.0*sin(5.1234*d)+4.0)/1); + } + WS2812UpdateStrip(); + // wait 5ms + sysDelayMs(5); + } - } + while (GPIOA->IDR & 1) { + int heading = getheading(); + int led = (heading * WS2812_LED_STRIP_LENGTH) / 360; + int next = (led + 1) % WS2812_LED_STRIP_LENGTH; + int v2 = (heading - (led * 360) / WS2812_LED_STRIP_LENGTH) * 10; + int v1 = 225 - v2; + + rgbData[led].red = v1; + rgbData[next].red = v2; + + WS2812UpdateStrip(); + // wait 15ms + sysDelayMs(15); + rgbData[led].red = 0; + rgbData[next].red = 0; + } + while (1) { // flashing lights moving along the strip - rgbData[j].red = (rgb & 255); // green - rgbData[j].green = (rgb >> 8) & 255; // red - rgbData[j].blue = (rgb >> 16) & 255; // blue - int NLIGHTS=4; + int NLIGHTS=32; i=j; - for(int k=1;k<NLIGHTS;k++) { - i=(i+WS2812_LED_STRIP_LENGTH/NLIGHTS)%WS2812_LED_STRIP_LENGTH; - rgbData[i].red = (rgb & 255); // green - rgbData[i].green = (rgb >> 8) & 255; // red - rgbData[i].blue = (rgb >> 16) & 255; // blue + for(int k=0;k<NLIGHTS;k++) { + rgbData[i].red = (rgb & 255)/8; // green + rgbData[i].green = ((rgb >> 8) & 255)/8; // red + rgbData[i].blue = ((rgb >> 16) & 255)/8; // blue + i=(i+WS2812_LED_STRIP_LENGTH/NLIGHTS)%WS2812_LED_STRIP_LENGTH; } WS2812UpdateStrip(); @@ -485,9 +411,7 @@ } ReadAccelerometer(AccBuffer); - int x=(int)AccBuffer[0]; - int y=(int)AccBuffer[1]; - int z=(int)AccBuffer[2]; + int y=(int)AccBuffer[1]/32; delay=10000-abs(y)*20; if(delay<0) delay=0;