Martin Johnson / neopixels

Dependencies:   STM32F3-Discovery

Committer:
MartinJohnson
Date:
Wed May 25 23:54:30 2016 +0000
Revision:
0:d89511b21e3d
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MartinJohnson 0:d89511b21e3d 1
MartinJohnson 0:d89511b21e3d 2 #include <stm32f30x.h>
MartinJohnson 0:d89511b21e3d 3 //#include <stm32f30x_misc.h>
MartinJohnson 0:d89511b21e3d 4 //#define ARM_MATH_CM4
MartinJohnson 0:d89511b21e3d 5 #include <math.h>
MartinJohnson 0:d89511b21e3d 6 #include "stm32f3_discovery_lsm303dlhc.h"
MartinJohnson 0:d89511b21e3d 7 #include <stdlib.h>
MartinJohnson 0:d89511b21e3d 8
MartinJohnson 0:d89511b21e3d 9 #define WS2812_GPIO GPIOB
MartinJohnson 0:d89511b21e3d 10 #define WS2812_GPIO_AHB_PERIPHERAL RCC_AHBPeriph_GPIOB
MartinJohnson 0:d89511b21e3d 11 #define WS2812_GPIO_AF GPIO_AF_1
MartinJohnson 0:d89511b21e3d 12 #define WS2812_PIN GPIO_Pin_8 // TIM16_CH1
MartinJohnson 0:d89511b21e3d 13 #define WS2812_PIN_SOURCE GPIO_PinSource8
MartinJohnson 0:d89511b21e3d 14 #define WS2812_TIMER TIM16
MartinJohnson 0:d89511b21e3d 15 #define WS2812_TIMER_APB2_PERIPHERAL RCC_APB2Periph_TIM16
MartinJohnson 0:d89511b21e3d 16 #define WS2812_DMA_CHANNEL DMA1_Channel3
MartinJohnson 0:d89511b21e3d 17 #define WS2812_IRQ DMA1_Channel3_IRQn
MartinJohnson 0:d89511b21e3d 18 #define WS2812_DMA_TC_FLAG DMA1_FLAG_TC3
MartinJohnson 0:d89511b21e3d 19
MartinJohnson 0:d89511b21e3d 20 #define PI 3.1415926f
MartinJohnson 0:d89511b21e3d 21
MartinJohnson 0:d89511b21e3d 22 #define WS2812_LED_STRIP_LENGTH 60
MartinJohnson 0:d89511b21e3d 23 #define WS2812_BITS_PER_LED 24
MartinJohnson 0:d89511b21e3d 24 #define WS2812_DELAY_BUFFER_LENGTH 42 // for 50us delay
MartinJohnson 0:d89511b21e3d 25
MartinJohnson 0:d89511b21e3d 26 #define BIT_COMPARE_1 17 // timer compare value for logical 1
MartinJohnson 0:d89511b21e3d 27 #define BIT_COMPARE_0 9 // timer compare value for logical 0
MartinJohnson 0:d89511b21e3d 28 #define WS2812_DATA_BUFFER_SIZE (WS2812_BITS_PER_LED * WS2812_LED_STRIP_LENGTH)
MartinJohnson 0:d89511b21e3d 29
MartinJohnson 0:d89511b21e3d 30 #define WS2812_DMA_BUFFER_SIZE (WS2812_DATA_BUFFER_SIZE + WS2812_DELAY_BUFFER_LENGTH) // number of bytes needed is #LEDs * 24 bytes + 42 trailing bytes)
MartinJohnson 0:d89511b21e3d 31
MartinJohnson 0:d89511b21e3d 32 static volatile uint8_t ledStripDMABuffer[WS2812_DMA_BUFFER_SIZE];
MartinJohnson 0:d89511b21e3d 33
MartinJohnson 0:d89511b21e3d 34 //static volatile uint8_t rgbData[WS2812_LED_STRIP_LENGTH*3];
MartinJohnson 0:d89511b21e3d 35
MartinJohnson 0:d89511b21e3d 36 static volatile uint8_t WS2812LedDataTransferInProgress = 0;
MartinJohnson 0:d89511b21e3d 37 static uint16_t dmaBufferOffset;
MartinJohnson 0:d89511b21e3d 38 static int16_t ledIndex;
MartinJohnson 0:d89511b21e3d 39
MartinJohnson 0:d89511b21e3d 40 volatile unsigned sysTiming;
MartinJohnson 0:d89511b21e3d 41 volatile unsigned sysTicks = 0;
MartinJohnson 0:d89511b21e3d 42
MartinJohnson 0:d89511b21e3d 43 int sysInitSystemTimer(void) {
MartinJohnson 0:d89511b21e3d 44
MartinJohnson 0:d89511b21e3d 45 if (SysTick_Config((SystemCoreClock / 1000) -1 )) {
MartinJohnson 0:d89511b21e3d 46 return(0);
MartinJohnson 0:d89511b21e3d 47 }
MartinJohnson 0:d89511b21e3d 48 return(1);
MartinJohnson 0:d89511b21e3d 49 }
MartinJohnson 0:d89511b21e3d 50 void sysDelayMs(unsigned dly) {
MartinJohnson 0:d89511b21e3d 51
MartinJohnson 0:d89511b21e3d 52 sysTiming = dly;
MartinJohnson 0:d89511b21e3d 53
MartinJohnson 0:d89511b21e3d 54 while (sysTiming > 0) __wfi();
MartinJohnson 0:d89511b21e3d 55
MartinJohnson 0:d89511b21e3d 56 }
MartinJohnson 0:d89511b21e3d 57 void SysTick_Handler(void) {
MartinJohnson 0:d89511b21e3d 58 sysTicks++;
MartinJohnson 0:d89511b21e3d 59 if (sysTiming > 0) --sysTiming;
MartinJohnson 0:d89511b21e3d 60 }
MartinJohnson 0:d89511b21e3d 61
MartinJohnson 0:d89511b21e3d 62 void AccelerometerConfig(void)
MartinJohnson 0:d89511b21e3d 63 {
MartinJohnson 0:d89511b21e3d 64 LSM303DLHCMag_InitTypeDef LSM303DLHC_InitStructure;
MartinJohnson 0:d89511b21e3d 65 LSM303DLHCAcc_InitTypeDef LSM303DLHCAcc_InitStructure;
MartinJohnson 0:d89511b21e3d 66 LSM303DLHCAcc_FilterConfigTypeDef LSM303DLHCFilter_InitStructure;
MartinJohnson 0:d89511b21e3d 67
MartinJohnson 0:d89511b21e3d 68 /* Configure MEMS magnetometer main parameters: temp, working mode, full Scale and Data rate */
MartinJohnson 0:d89511b21e3d 69 LSM303DLHC_InitStructure.Temperature_Sensor = LSM303DLHC_TEMPSENSOR_DISABLE;
MartinJohnson 0:d89511b21e3d 70 LSM303DLHC_InitStructure.MagOutput_DataRate =LSM303DLHC_ODR_30_HZ ;
MartinJohnson 0:d89511b21e3d 71 LSM303DLHC_InitStructure.MagFull_Scale = LSM303DLHC_FS_8_1_GA;
MartinJohnson 0:d89511b21e3d 72 LSM303DLHC_InitStructure.Working_Mode = LSM303DLHC_CONTINUOS_CONVERSION;
MartinJohnson 0:d89511b21e3d 73 LSM303DLHC_MagInit(&LSM303DLHC_InitStructure);
MartinJohnson 0:d89511b21e3d 74
MartinJohnson 0:d89511b21e3d 75 /* Fill the accelerometer structure */
MartinJohnson 0:d89511b21e3d 76 LSM303DLHCAcc_InitStructure.Power_Mode = LSM303DLHC_NORMAL_MODE;
MartinJohnson 0:d89511b21e3d 77 LSM303DLHCAcc_InitStructure.AccOutput_DataRate = LSM303DLHC_ODR_50_HZ;
MartinJohnson 0:d89511b21e3d 78 LSM303DLHCAcc_InitStructure.Axes_Enable= LSM303DLHC_AXES_ENABLE;
MartinJohnson 0:d89511b21e3d 79 LSM303DLHCAcc_InitStructure.AccFull_Scale = LSM303DLHC_FULLSCALE_2G;
MartinJohnson 0:d89511b21e3d 80 LSM303DLHCAcc_InitStructure.BlockData_Update = LSM303DLHC_BlockUpdate_Continous;
MartinJohnson 0:d89511b21e3d 81 LSM303DLHCAcc_InitStructure.Endianness=LSM303DLHC_BLE_LSB;
MartinJohnson 0:d89511b21e3d 82 LSM303DLHCAcc_InitStructure.High_Resolution=LSM303DLHC_HR_ENABLE;
MartinJohnson 0:d89511b21e3d 83 /* Configure the accelerometer main parameters */
MartinJohnson 0:d89511b21e3d 84 LSM303DLHC_AccInit(&LSM303DLHCAcc_InitStructure);
MartinJohnson 0:d89511b21e3d 85
MartinJohnson 0:d89511b21e3d 86 /* Fill the accelerometer LPF structure */
MartinJohnson 0:d89511b21e3d 87 LSM303DLHCFilter_InitStructure.HighPassFilter_Mode_Selection =LSM303DLHC_HPM_NORMAL_MODE;
MartinJohnson 0:d89511b21e3d 88 LSM303DLHCFilter_InitStructure.HighPassFilter_CutOff_Frequency = LSM303DLHC_HPFCF_16;
MartinJohnson 0:d89511b21e3d 89 LSM303DLHCFilter_InitStructure.HighPassFilter_AOI1 = LSM303DLHC_HPF_AOI1_DISABLE;
MartinJohnson 0:d89511b21e3d 90 LSM303DLHCFilter_InitStructure.HighPassFilter_AOI2 = LSM303DLHC_HPF_AOI2_DISABLE;
MartinJohnson 0:d89511b21e3d 91
MartinJohnson 0:d89511b21e3d 92 /* Configure the accelerometer LPF main parameters */
MartinJohnson 0:d89511b21e3d 93 LSM303DLHC_AccFilterConfig(&LSM303DLHCFilter_InitStructure);
MartinJohnson 0:d89511b21e3d 94 }
MartinJohnson 0:d89511b21e3d 95
MartinJohnson 0:d89511b21e3d 96 void ReadAccelerometer(float * data)
MartinJohnson 0:d89511b21e3d 97 {
MartinJohnson 0:d89511b21e3d 98 uint8_t buffer[6];
MartinJohnson 0:d89511b21e3d 99
MartinJohnson 0:d89511b21e3d 100 LSM303DLHC_Read(ACC_I2C_ADDRESS, LSM303DLHC_OUT_X_L_A, buffer, 6);
MartinJohnson 0:d89511b21e3d 101
MartinJohnson 0:d89511b21e3d 102 for(int i=0; i<3; i++) {
MartinJohnson 0:d89511b21e3d 103 data[i]=(float)((int16_t)((uint16_t)buffer[2*i+1] << 8) + buffer[2*i])/16;
MartinJohnson 0:d89511b21e3d 104 }
MartinJohnson 0:d89511b21e3d 105 }
MartinJohnson 0:d89511b21e3d 106
MartinJohnson 0:d89511b21e3d 107 void ReadMagnetometer (float* pfData)
MartinJohnson 0:d89511b21e3d 108 {
MartinJohnson 0:d89511b21e3d 109 static uint8_t buffer[6] = {0};
MartinJohnson 0:d89511b21e3d 110 uint8_t CTRLB = 0;
MartinJohnson 0:d89511b21e3d 111 uint16_t Magn_Sensitivity_XY = 0, Magn_Sensitivity_Z = 0;
MartinJohnson 0:d89511b21e3d 112 uint8_t i =0;
MartinJohnson 0:d89511b21e3d 113 LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_CRB_REG_M, &CTRLB, 1);
MartinJohnson 0:d89511b21e3d 114
MartinJohnson 0:d89511b21e3d 115 LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_H_M, buffer, 1);
MartinJohnson 0:d89511b21e3d 116 LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_L_M, buffer+1, 1);
MartinJohnson 0:d89511b21e3d 117 LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Y_H_M, buffer+2, 1);
MartinJohnson 0:d89511b21e3d 118 LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Y_L_M, buffer+3, 1);
MartinJohnson 0:d89511b21e3d 119 LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Z_H_M, buffer+4, 1);
MartinJohnson 0:d89511b21e3d 120 LSM303DLHC_Read(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Z_L_M, buffer+5, 1);
MartinJohnson 0:d89511b21e3d 121 /* Switch the sensitivity set in the CRTLB*/
MartinJohnson 0:d89511b21e3d 122 switch(CTRLB & 0xE0)
MartinJohnson 0:d89511b21e3d 123 {
MartinJohnson 0:d89511b21e3d 124 case LSM303DLHC_FS_1_3_GA:
MartinJohnson 0:d89511b21e3d 125 Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_1_3Ga;
MartinJohnson 0:d89511b21e3d 126 Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_1_3Ga;
MartinJohnson 0:d89511b21e3d 127 break;
MartinJohnson 0:d89511b21e3d 128 case LSM303DLHC_FS_1_9_GA:
MartinJohnson 0:d89511b21e3d 129 Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_1_9Ga;
MartinJohnson 0:d89511b21e3d 130 Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_1_9Ga;
MartinJohnson 0:d89511b21e3d 131 break;
MartinJohnson 0:d89511b21e3d 132 case LSM303DLHC_FS_2_5_GA:
MartinJohnson 0:d89511b21e3d 133 Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_2_5Ga;
MartinJohnson 0:d89511b21e3d 134 Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_2_5Ga;
MartinJohnson 0:d89511b21e3d 135 break;
MartinJohnson 0:d89511b21e3d 136 case LSM303DLHC_FS_4_0_GA:
MartinJohnson 0:d89511b21e3d 137 Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_4Ga;
MartinJohnson 0:d89511b21e3d 138 Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_4Ga;
MartinJohnson 0:d89511b21e3d 139 break;
MartinJohnson 0:d89511b21e3d 140 case LSM303DLHC_FS_4_7_GA:
MartinJohnson 0:d89511b21e3d 141 Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_4_7Ga;
MartinJohnson 0:d89511b21e3d 142 Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_4_7Ga;
MartinJohnson 0:d89511b21e3d 143 break;
MartinJohnson 0:d89511b21e3d 144 case LSM303DLHC_FS_5_6_GA:
MartinJohnson 0:d89511b21e3d 145 Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_5_6Ga;
MartinJohnson 0:d89511b21e3d 146 Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_5_6Ga;
MartinJohnson 0:d89511b21e3d 147 break;
MartinJohnson 0:d89511b21e3d 148 case LSM303DLHC_FS_8_1_GA:
MartinJohnson 0:d89511b21e3d 149 Magn_Sensitivity_XY = LSM303DLHC_M_SENSITIVITY_XY_8_1Ga;
MartinJohnson 0:d89511b21e3d 150 Magn_Sensitivity_Z = LSM303DLHC_M_SENSITIVITY_Z_8_1Ga;
MartinJohnson 0:d89511b21e3d 151 break;
MartinJohnson 0:d89511b21e3d 152 }
MartinJohnson 0:d89511b21e3d 153
MartinJohnson 0:d89511b21e3d 154 for(i=0; i<2; i++)
MartinJohnson 0:d89511b21e3d 155 {
MartinJohnson 0:d89511b21e3d 156 pfData[i]=(float)((int16_t)(((uint16_t)buffer[2*i] << 8) + buffer[2*i+1])*1000)/Magn_Sensitivity_XY;
MartinJohnson 0:d89511b21e3d 157 }
MartinJohnson 0:d89511b21e3d 158 pfData[2]=(float)((int16_t)(((uint16_t)buffer[4] << 8) + buffer[5])*1000)/Magn_Sensitivity_Z;
MartinJohnson 0:d89511b21e3d 159 }
MartinJohnson 0:d89511b21e3d 160
MartinJohnson 0:d89511b21e3d 161 void GPIO_init(void) {
MartinJohnson 0:d89511b21e3d 162 GPIO_InitTypeDef GPIO_InitStructure;
MartinJohnson 0:d89511b21e3d 163 // GPIOA Periph clock enable
MartinJohnson 0:d89511b21e3d 164 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
MartinJohnson 0:d89511b21e3d 165 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
MartinJohnson 0:d89511b21e3d 166 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOE, ENABLE);
MartinJohnson 0:d89511b21e3d 167 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
MartinJohnson 0:d89511b21e3d 168 RCC_APB2PeriphClockCmd(WS2812_TIMER_APB2_PERIPHERAL, ENABLE);
MartinJohnson 0:d89511b21e3d 169
MartinJohnson 0:d89511b21e3d 170 sysInitSystemTimer();
MartinJohnson 0:d89511b21e3d 171 /* Configuration alternate function push-pull */
MartinJohnson 0:d89511b21e3d 172 GPIO_StructInit(&GPIO_InitStructure);
MartinJohnson 0:d89511b21e3d 173 GPIO_InitStructure.GPIO_Pin = WS2812_PIN;
MartinJohnson 0:d89511b21e3d 174 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
MartinJohnson 0:d89511b21e3d 175 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
MartinJohnson 0:d89511b21e3d 176 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
MartinJohnson 0:d89511b21e3d 177 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
MartinJohnson 0:d89511b21e3d 178 GPIO_Init(WS2812_GPIO, &GPIO_InitStructure);
MartinJohnson 0:d89511b21e3d 179
MartinJohnson 0:d89511b21e3d 180 GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_1); // pb8 is tim16 ch1
MartinJohnson 0:d89511b21e3d 181
MartinJohnson 0:d89511b21e3d 182 GPIO_InitStructure.GPIO_Pin =
MartinJohnson 0:d89511b21e3d 183 GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 |
MartinJohnson 0:d89511b21e3d 184 GPIO_Pin_14 | GPIO_Pin_15;
MartinJohnson 0:d89511b21e3d 185 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
MartinJohnson 0:d89511b21e3d 186 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
MartinJohnson 0:d89511b21e3d 187 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
MartinJohnson 0:d89511b21e3d 188 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
MartinJohnson 0:d89511b21e3d 189 GPIO_Init(GPIOE, &GPIO_InitStructure);
MartinJohnson 0:d89511b21e3d 190
MartinJohnson 0:d89511b21e3d 191 GPIO_StructInit(&GPIO_InitStructure);
MartinJohnson 0:d89511b21e3d 192 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
MartinJohnson 0:d89511b21e3d 193 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
MartinJohnson 0:d89511b21e3d 194 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
MartinJohnson 0:d89511b21e3d 195 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
MartinJohnson 0:d89511b21e3d 196 GPIO_Init(GPIOA, &GPIO_InitStructure);
MartinJohnson 0:d89511b21e3d 197
MartinJohnson 0:d89511b21e3d 198
MartinJohnson 0:d89511b21e3d 199 GPIOE->ODR ^= 0x100;
MartinJohnson 0:d89511b21e3d 200 }
MartinJohnson 0:d89511b21e3d 201
MartinJohnson 0:d89511b21e3d 202 void TIM_init(void)
MartinJohnson 0:d89511b21e3d 203 {
MartinJohnson 0:d89511b21e3d 204 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
MartinJohnson 0:d89511b21e3d 205 TIM_OCInitTypeDef TIM_OCInitStructure;
MartinJohnson 0:d89511b21e3d 206 // NVIC_InitTypeDef NVIC_InitStructure;
MartinJohnson 0:d89511b21e3d 207 uint16_t PrescalerValue;
MartinJohnson 0:d89511b21e3d 208
MartinJohnson 0:d89511b21e3d 209 PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
MartinJohnson 0:d89511b21e3d 210 /* Time base configuration */
MartinJohnson 0:d89511b21e3d 211 TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
MartinJohnson 0:d89511b21e3d 212 TIM_TimeBaseStructure.TIM_Period = 29; // 800kHz
MartinJohnson 0:d89511b21e3d 213 TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
MartinJohnson 0:d89511b21e3d 214 TIM_TimeBaseStructure.TIM_ClockDivision = 0;
MartinJohnson 0:d89511b21e3d 215 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
MartinJohnson 0:d89511b21e3d 216 TIM_TimeBaseInit(WS2812_TIMER, &TIM_TimeBaseStructure);
MartinJohnson 0:d89511b21e3d 217
MartinJohnson 0:d89511b21e3d 218 /* PWM1 Mode configuration */
MartinJohnson 0:d89511b21e3d 219 TIM_OCStructInit(&TIM_OCInitStructure);
MartinJohnson 0:d89511b21e3d 220 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
MartinJohnson 0:d89511b21e3d 221 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
MartinJohnson 0:d89511b21e3d 222 TIM_OCInitStructure.TIM_Pulse = 0;
MartinJohnson 0:d89511b21e3d 223 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
MartinJohnson 0:d89511b21e3d 224 TIM_OC1Init(WS2812_TIMER, &TIM_OCInitStructure);
MartinJohnson 0:d89511b21e3d 225 TIM_OC1PreloadConfig(WS2812_TIMER, TIM_OCPreload_Enable);
MartinJohnson 0:d89511b21e3d 226 TIM_CtrlPWMOutputs(WS2812_TIMER, ENABLE);
MartinJohnson 0:d89511b21e3d 227 }
MartinJohnson 0:d89511b21e3d 228
MartinJohnson 0:d89511b21e3d 229 void DMA_init(void) {
MartinJohnson 0:d89511b21e3d 230 DMA_InitTypeDef DMA_InitStructure;
MartinJohnson 0:d89511b21e3d 231 /* configure DMA */
MartinJohnson 0:d89511b21e3d 232 /* DMA clock enable */
MartinJohnson 0:d89511b21e3d 233 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
MartinJohnson 0:d89511b21e3d 234 /* DMA Channel Config */
MartinJohnson 0:d89511b21e3d 235 DMA_DeInit(WS2812_DMA_CHANNEL);
MartinJohnson 0:d89511b21e3d 236 DMA_StructInit(&DMA_InitStructure);
MartinJohnson 0:d89511b21e3d 237 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & WS2812_TIMER->CCR1;
MartinJohnson 0:d89511b21e3d 238 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) ledStripDMABuffer;
MartinJohnson 0:d89511b21e3d 239 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
MartinJohnson 0:d89511b21e3d 240 DMA_InitStructure.DMA_BufferSize = WS2812_DMA_BUFFER_SIZE;
MartinJohnson 0:d89511b21e3d 241 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
MartinJohnson 0:d89511b21e3d 242 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
MartinJohnson 0:d89511b21e3d 243 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
MartinJohnson 0:d89511b21e3d 244 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
MartinJohnson 0:d89511b21e3d 245 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
MartinJohnson 0:d89511b21e3d 246 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
MartinJohnson 0:d89511b21e3d 247 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
MartinJohnson 0:d89511b21e3d 248 DMA_Init(WS2812_DMA_CHANNEL, &DMA_InitStructure);
MartinJohnson 0:d89511b21e3d 249 TIM_DMACmd(WS2812_TIMER, TIM_DMA_CC1, ENABLE);
MartinJohnson 0:d89511b21e3d 250 DMA_ITConfig(WS2812_DMA_CHANNEL, DMA_IT_TC, ENABLE);
MartinJohnson 0:d89511b21e3d 251 NVIC_InitTypeDef NVIC_InitStructure;
MartinJohnson 0:d89511b21e3d 252 NVIC_InitStructure.NVIC_IRQChannel = WS2812_IRQ;
MartinJohnson 0:d89511b21e3d 253 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
MartinJohnson 0:d89511b21e3d 254 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
MartinJohnson 0:d89511b21e3d 255 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
MartinJohnson 0:d89511b21e3d 256 NVIC_Init(&NVIC_InitStructure);
MartinJohnson 0:d89511b21e3d 257 }
MartinJohnson 0:d89511b21e3d 258
MartinJohnson 0:d89511b21e3d 259 void WS2812LedStripDMAEnable(void) {
MartinJohnson 0:d89511b21e3d 260 DMA_SetCurrDataCounter(WS2812_DMA_CHANNEL,
MartinJohnson 0:d89511b21e3d 261 WS2812_DMA_BUFFER_SIZE); // load number of bytes to be transferred
MartinJohnson 0:d89511b21e3d 262 TIM_SetCounter(WS2812_TIMER, 0);
MartinJohnson 0:d89511b21e3d 263 TIM_Cmd(WS2812_TIMER, ENABLE);
MartinJohnson 0:d89511b21e3d 264 DMA_Cmd(WS2812_DMA_CHANNEL, ENABLE);
MartinJohnson 0:d89511b21e3d 265 }
MartinJohnson 0:d89511b21e3d 266
MartinJohnson 0:d89511b21e3d 267 void DMA1_Channel3_IRQHandler(void) {
MartinJohnson 0:d89511b21e3d 268 // GPIOE->ODR ^= 0x1000;
MartinJohnson 0:d89511b21e3d 269 if (DMA_GetFlagStatus(WS2812_DMA_TC_FLAG)) {
MartinJohnson 0:d89511b21e3d 270 WS2812LedDataTransferInProgress = 0;
MartinJohnson 0:d89511b21e3d 271 DMA_Cmd(WS2812_DMA_CHANNEL, DISABLE);
MartinJohnson 0:d89511b21e3d 272 DMA_ClearFlag(WS2812_DMA_TC_FLAG);
MartinJohnson 0:d89511b21e3d 273 }
MartinJohnson 0:d89511b21e3d 274 }
MartinJohnson 0:d89511b21e3d 275
MartinJohnson 0:d89511b21e3d 276 void updateLEDDMABuffer(uint8_t componentValue) {
MartinJohnson 0:d89511b21e3d 277 uint8_t bitIndex;
MartinJohnson 0:d89511b21e3d 278
MartinJohnson 0:d89511b21e3d 279 for (bitIndex = 0; bitIndex < 8; bitIndex++) {
MartinJohnson 0:d89511b21e3d 280 if ((componentValue << bitIndex) &
MartinJohnson 0:d89511b21e3d 281 0x80) // data sent MSB first, j = 0 is MSB j = 7 is LSB
MartinJohnson 0:d89511b21e3d 282 {
MartinJohnson 0:d89511b21e3d 283 ledStripDMABuffer[dmaBufferOffset] = BIT_COMPARE_1;
MartinJohnson 0:d89511b21e3d 284 }
MartinJohnson 0:d89511b21e3d 285 else {
MartinJohnson 0:d89511b21e3d 286 ledStripDMABuffer[dmaBufferOffset] = BIT_COMPARE_0; // compare value for logical 0
MartinJohnson 0:d89511b21e3d 287 }
MartinJohnson 0:d89511b21e3d 288 dmaBufferOffset++;
MartinJohnson 0:d89511b21e3d 289 }
MartinJohnson 0:d89511b21e3d 290 }
MartinJohnson 0:d89511b21e3d 291
MartinJohnson 0:d89511b21e3d 292 typedef struct {
MartinJohnson 0:d89511b21e3d 293 uint8_t red;
MartinJohnson 0:d89511b21e3d 294 uint8_t green;
MartinJohnson 0:d89511b21e3d 295 uint8_t blue;
MartinJohnson 0:d89511b21e3d 296 } rgb_struct;
MartinJohnson 0:d89511b21e3d 297
MartinJohnson 0:d89511b21e3d 298 static volatile rgb_struct rgbData[WS2812_LED_STRIP_LENGTH];
MartinJohnson 0:d89511b21e3d 299
MartinJohnson 0:d89511b21e3d 300 void WS2812UpdateStrip(void) {
MartinJohnson 0:d89511b21e3d 301 static uint32_t waitCounter = 0;
MartinJohnson 0:d89511b21e3d 302
MartinJohnson 0:d89511b21e3d 303 // wait until previous transfer completes
MartinJohnson 0:d89511b21e3d 304 while (WS2812LedDataTransferInProgress) {
MartinJohnson 0:d89511b21e3d 305 waitCounter++;
MartinJohnson 0:d89511b21e3d 306 }
MartinJohnson 0:d89511b21e3d 307
MartinJohnson 0:d89511b21e3d 308 dmaBufferOffset = 0; // reset buffer memory index
MartinJohnson 0:d89511b21e3d 309 ledIndex = 0; // reset led index
MartinJohnson 0:d89511b21e3d 310
MartinJohnson 0:d89511b21e3d 311 // fill transmit buffer with correct compare values to achieve
MartinJohnson 0:d89511b21e3d 312 // correct pulse widths according to color values
MartinJohnson 0:d89511b21e3d 313 while (ledIndex < WS2812_LED_STRIP_LENGTH) {
MartinJohnson 0:d89511b21e3d 314 updateLEDDMABuffer(rgbData[ledIndex].green);
MartinJohnson 0:d89511b21e3d 315 updateLEDDMABuffer(rgbData[ledIndex].red);
MartinJohnson 0:d89511b21e3d 316 updateLEDDMABuffer(rgbData[ledIndex++].blue);
MartinJohnson 0:d89511b21e3d 317 }
MartinJohnson 0:d89511b21e3d 318
MartinJohnson 0:d89511b21e3d 319 WS2812LedDataTransferInProgress = 1;
MartinJohnson 0:d89511b21e3d 320 WS2812LedStripDMAEnable();
MartinJohnson 0:d89511b21e3d 321 }
MartinJohnson 0:d89511b21e3d 322
MartinJohnson 0:d89511b21e3d 323 extern volatile unsigned sysTicks;
MartinJohnson 0:d89511b21e3d 324 int rndseed=0;
MartinJohnson 0:d89511b21e3d 325 /*
MartinJohnson 0:d89511b21e3d 326 void srand(int i) {
MartinJohnson 0:d89511b21e3d 327 rndseed = i;
MartinJohnson 0:d89511b21e3d 328 }
MartinJohnson 0:d89511b21e3d 329
MartinJohnson 0:d89511b21e3d 330
MartinJohnson 0:d89511b21e3d 331 int rand() {
MartinJohnson 0:d89511b21e3d 332 return (((rndseed = rndseed * 214013L + 2531011L) >> 16) &
MartinJohnson 0:d89511b21e3d 333 0x7fff);
MartinJohnson 0:d89511b21e3d 334 }
MartinJohnson 0:d89511b21e3d 335 */
MartinJohnson 0:d89511b21e3d 336
MartinJohnson 0:d89511b21e3d 337 void WS2812LedStripInit(void) {
MartinJohnson 0:d89511b21e3d 338 int i;
MartinJohnson 0:d89511b21e3d 339 for (i = 0; i < WS2812_DMA_BUFFER_SIZE; i++)
MartinJohnson 0:d89511b21e3d 340 ledStripDMABuffer[i] = 0;
MartinJohnson 0:d89511b21e3d 341 WS2812UpdateStrip();
MartinJohnson 0:d89511b21e3d 342 }
MartinJohnson 0:d89511b21e3d 343 static float AccBuffer[3] = {0.0f};
MartinJohnson 0:d89511b21e3d 344 static float MagBuffer[3] = {0.0f};
MartinJohnson 0:d89511b21e3d 345
MartinJohnson 0:d89511b21e3d 346 //extern float arm_sqrt_f32(float f);
MartinJohnson 0:d89511b21e3d 347 int getheading() {
MartinJohnson 0:d89511b21e3d 348 /* Read Compass data */
MartinJohnson 0:d89511b21e3d 349 ReadMagnetometer(MagBuffer);
MartinJohnson 0:d89511b21e3d 350 ReadAccelerometer(AccBuffer);
MartinJohnson 0:d89511b21e3d 351 int i;
MartinJohnson 0:d89511b21e3d 352 float fNormAcc, fSinRoll, fCosRoll, fSinPitch, fCosPitch = 0.0f, RollAng = 0.0f, PitchAng = 0.0f;
MartinJohnson 0:d89511b21e3d 353 float fTiltedX, fTiltedY = 0.0f;
MartinJohnson 0:d89511b21e3d 354 float HeadingValue;
MartinJohnson 0:d89511b21e3d 355
MartinJohnson 0:d89511b21e3d 356 for (i = 0; i < 3; i++)
MartinJohnson 0:d89511b21e3d 357 AccBuffer[i] /= 100.0f;
MartinJohnson 0:d89511b21e3d 358
MartinJohnson 0:d89511b21e3d 359 fNormAcc = sqrtf((AccBuffer[0] * AccBuffer[0]) + (AccBuffer[1] * AccBuffer[1]) +
MartinJohnson 0:d89511b21e3d 360 (AccBuffer[2] * AccBuffer[2]));
MartinJohnson 0:d89511b21e3d 361
MartinJohnson 0:d89511b21e3d 362 fSinRoll = -AccBuffer[1] / fNormAcc;
MartinJohnson 0:d89511b21e3d 363 fCosRoll = sqrtf(1.0f - (fSinRoll * fSinRoll));
MartinJohnson 0:d89511b21e3d 364 fSinPitch = AccBuffer[0] / fNormAcc;
MartinJohnson 0:d89511b21e3d 365 fCosPitch = sqrtf(1.0f - (fSinPitch * fSinPitch));
MartinJohnson 0:d89511b21e3d 366 if (fSinRoll > 0) {
MartinJohnson 0:d89511b21e3d 367 if (fCosRoll > 0) {
MartinJohnson 0:d89511b21e3d 368 RollAng = acos(fCosRoll) * 180 / PI;
MartinJohnson 0:d89511b21e3d 369 }
MartinJohnson 0:d89511b21e3d 370 else {
MartinJohnson 0:d89511b21e3d 371 RollAng = acos(fCosRoll) * 180 / PI + 180;
MartinJohnson 0:d89511b21e3d 372 }
MartinJohnson 0:d89511b21e3d 373 }
MartinJohnson 0:d89511b21e3d 374 else {
MartinJohnson 0:d89511b21e3d 375 if (fCosRoll > 0) {
MartinJohnson 0:d89511b21e3d 376 RollAng = acos(fCosRoll) * 180 / PI + 360;
MartinJohnson 0:d89511b21e3d 377 }
MartinJohnson 0:d89511b21e3d 378 else {
MartinJohnson 0:d89511b21e3d 379 RollAng = acos(fCosRoll) * 180 / PI + 180;
MartinJohnson 0:d89511b21e3d 380 }
MartinJohnson 0:d89511b21e3d 381 }
MartinJohnson 0:d89511b21e3d 382 if (fSinPitch > 0) {
MartinJohnson 0:d89511b21e3d 383 if (fCosPitch > 0) {
MartinJohnson 0:d89511b21e3d 384 PitchAng = acos(fCosPitch) * 180 / PI;
MartinJohnson 0:d89511b21e3d 385 }
MartinJohnson 0:d89511b21e3d 386 else {
MartinJohnson 0:d89511b21e3d 387 PitchAng = acos(fCosPitch) * 180 / PI + 180;
MartinJohnson 0:d89511b21e3d 388 }
MartinJohnson 0:d89511b21e3d 389 }
MartinJohnson 0:d89511b21e3d 390 else {
MartinJohnson 0:d89511b21e3d 391 if (fCosPitch > 0) {
MartinJohnson 0:d89511b21e3d 392 PitchAng = acos(fCosPitch) * 180 / PI + 360;
MartinJohnson 0:d89511b21e3d 393 }
MartinJohnson 0:d89511b21e3d 394 else {
MartinJohnson 0:d89511b21e3d 395 PitchAng = acos(fCosPitch) * 180 / PI + 180;
MartinJohnson 0:d89511b21e3d 396 }
MartinJohnson 0:d89511b21e3d 397 }
MartinJohnson 0:d89511b21e3d 398
MartinJohnson 0:d89511b21e3d 399 if (RollAng >= 360) {
MartinJohnson 0:d89511b21e3d 400 RollAng = RollAng - 360;
MartinJohnson 0:d89511b21e3d 401 }
MartinJohnson 0:d89511b21e3d 402
MartinJohnson 0:d89511b21e3d 403 if (PitchAng >= 360) {
MartinJohnson 0:d89511b21e3d 404 PitchAng = PitchAng - 360;
MartinJohnson 0:d89511b21e3d 405 }
MartinJohnson 0:d89511b21e3d 406
MartinJohnson 0:d89511b21e3d 407 fTiltedX = MagBuffer[0] * fCosPitch + MagBuffer[2] * fSinPitch;
MartinJohnson 0:d89511b21e3d 408 fTiltedY = MagBuffer[0] * fSinRoll * fSinPitch + MagBuffer[1] * fCosRoll -
MartinJohnson 0:d89511b21e3d 409 MagBuffer[1] * fSinRoll * fCosPitch;
MartinJohnson 0:d89511b21e3d 410
MartinJohnson 0:d89511b21e3d 411 // fTiltedX=fTiltedX/sqrt(fTiltedX*fTiltedX+fTiltedY*fTiltedY);
MartinJohnson 0:d89511b21e3d 412 HeadingValue = (float) ((atan2f( (float)fTiltedY, (float)fTiltedX)) * 180) / PI;
MartinJohnson 0:d89511b21e3d 413
MartinJohnson 0:d89511b21e3d 414 if (HeadingValue < 0) {
MartinJohnson 0:d89511b21e3d 415 HeadingValue = HeadingValue + 360;
MartinJohnson 0:d89511b21e3d 416 }
MartinJohnson 0:d89511b21e3d 417 return HeadingValue;
MartinJohnson 0:d89511b21e3d 418
MartinJohnson 0:d89511b21e3d 419 }
MartinJohnson 0:d89511b21e3d 420
MartinJohnson 0:d89511b21e3d 421 int main(void) {
MartinJohnson 0:d89511b21e3d 422 uint8_t i = 0;
MartinJohnson 0:d89511b21e3d 423 int j=0;
MartinJohnson 0:d89511b21e3d 424 int delay=2000;
MartinJohnson 0:d89511b21e3d 425 int dch=-1;
MartinJohnson 0:d89511b21e3d 426 int dir=1;
MartinJohnson 0:d89511b21e3d 427 int btn=0;
MartinJohnson 0:d89511b21e3d 428 uint32_t rgb = 0x0ff0000ff;
MartinJohnson 0:d89511b21e3d 429 GPIO_init();
MartinJohnson 0:d89511b21e3d 430 GPIOE->ODR ^= 0x100;
MartinJohnson 0:d89511b21e3d 431 DMA_init();
MartinJohnson 0:d89511b21e3d 432 GPIOE->ODR ^= 0x200;
MartinJohnson 0:d89511b21e3d 433 TIM_init();
MartinJohnson 0:d89511b21e3d 434 AccelerometerConfig();
MartinJohnson 0:d89511b21e3d 435
MartinJohnson 0:d89511b21e3d 436 WS2812LedDataTransferInProgress = 0;
MartinJohnson 0:d89511b21e3d 437 WS2812LedStripInit();
MartinJohnson 0:d89511b21e3d 438 btn=GPIOA->IDR;
MartinJohnson 0:d89511b21e3d 439 if((GPIOA->IDR & 1)==1) {
MartinJohnson 0:d89511b21e3d 440 // a giant compass!
MartinJohnson 0:d89511b21e3d 441 while (1) {
MartinJohnson 0:d89511b21e3d 442 int heading = getheading();
MartinJohnson 0:d89511b21e3d 443 int led = (heading * WS2812_LED_STRIP_LENGTH) / 360;
MartinJohnson 0:d89511b21e3d 444 int next = (led + 1) % WS2812_LED_STRIP_LENGTH;
MartinJohnson 0:d89511b21e3d 445 int v2 = (heading - (led * 360) / WS2812_LED_STRIP_LENGTH) * 10;
MartinJohnson 0:d89511b21e3d 446 int v1 = 225 - v2;
MartinJohnson 0:d89511b21e3d 447
MartinJohnson 0:d89511b21e3d 448 rgbData[led].red = v1;
MartinJohnson 0:d89511b21e3d 449 rgbData[next].red = v2;
MartinJohnson 0:d89511b21e3d 450
MartinJohnson 0:d89511b21e3d 451 WS2812UpdateStrip();
MartinJohnson 0:d89511b21e3d 452 // wait 5ms
MartinJohnson 0:d89511b21e3d 453 sysDelayMs(15);
MartinJohnson 0:d89511b21e3d 454 rgbData[led].red = 0;
MartinJohnson 0:d89511b21e3d 455 rgbData[next].red = 0;
MartinJohnson 0:d89511b21e3d 456
MartinJohnson 0:d89511b21e3d 457 }
MartinJohnson 0:d89511b21e3d 458 }
MartinJohnson 0:d89511b21e3d 459 while (1) { // flashing lights moving along the strip
MartinJohnson 0:d89511b21e3d 460 rgbData[j].red = (rgb & 255); // green
MartinJohnson 0:d89511b21e3d 461 rgbData[j].green = (rgb >> 8) & 255; // red
MartinJohnson 0:d89511b21e3d 462 rgbData[j].blue = (rgb >> 16) & 255; // blue
MartinJohnson 0:d89511b21e3d 463
MartinJohnson 0:d89511b21e3d 464 int NLIGHTS=4;
MartinJohnson 0:d89511b21e3d 465 i=j;
MartinJohnson 0:d89511b21e3d 466 for(int k=1;k<NLIGHTS;k++) {
MartinJohnson 0:d89511b21e3d 467 i=(i+WS2812_LED_STRIP_LENGTH/NLIGHTS)%WS2812_LED_STRIP_LENGTH;
MartinJohnson 0:d89511b21e3d 468 rgbData[i].red = (rgb & 255); // green
MartinJohnson 0:d89511b21e3d 469 rgbData[i].green = (rgb >> 8) & 255; // red
MartinJohnson 0:d89511b21e3d 470 rgbData[i].blue = (rgb >> 16) & 255; // blue
MartinJohnson 0:d89511b21e3d 471 }
MartinJohnson 0:d89511b21e3d 472
MartinJohnson 0:d89511b21e3d 473 WS2812UpdateStrip();
MartinJohnson 0:d89511b21e3d 474 sysDelayMs(delay/100);
MartinJohnson 0:d89511b21e3d 475 if((GPIOA->IDR & 1)==1 && btn==0)
MartinJohnson 0:d89511b21e3d 476 dir=-dir;
MartinJohnson 0:d89511b21e3d 477 btn=(GPIOA->IDR & 1);
MartinJohnson 0:d89511b21e3d 478 delay=delay+dch;
MartinJohnson 0:d89511b21e3d 479 if(delay<500 || delay>3000)
MartinJohnson 0:d89511b21e3d 480 dch=-dch;
MartinJohnson 0:d89511b21e3d 481 for(int k=0;k<WS2812_LED_STRIP_LENGTH;k++) {
MartinJohnson 0:d89511b21e3d 482 rgbData[k].red = 0;
MartinJohnson 0:d89511b21e3d 483 rgbData[k].green = 0;
MartinJohnson 0:d89511b21e3d 484 rgbData[k].blue = 0;
MartinJohnson 0:d89511b21e3d 485 }
MartinJohnson 0:d89511b21e3d 486
MartinJohnson 0:d89511b21e3d 487 ReadAccelerometer(AccBuffer);
MartinJohnson 0:d89511b21e3d 488 int x=(int)AccBuffer[0];
MartinJohnson 0:d89511b21e3d 489 int y=(int)AccBuffer[1];
MartinJohnson 0:d89511b21e3d 490 int z=(int)AccBuffer[2];
MartinJohnson 0:d89511b21e3d 491
MartinJohnson 0:d89511b21e3d 492 delay=10000-abs(y)*20;
MartinJohnson 0:d89511b21e3d 493 if(delay<0) delay=0;
MartinJohnson 0:d89511b21e3d 494 if(y<0)
MartinJohnson 0:d89511b21e3d 495 dir=1;
MartinJohnson 0:d89511b21e3d 496 else
MartinJohnson 0:d89511b21e3d 497 dir=-1;
MartinJohnson 0:d89511b21e3d 498
MartinJohnson 0:d89511b21e3d 499 j=(j+dir+WS2812_LED_STRIP_LENGTH)%WS2812_LED_STRIP_LENGTH;
MartinJohnson 0:d89511b21e3d 500
MartinJohnson 0:d89511b21e3d 501 rgb=(rgb<<1) /*^ (rand()&1 & rand()&1) ; */| (rgb>>24);
MartinJohnson 0:d89511b21e3d 502
MartinJohnson 0:d89511b21e3d 503 }
MartinJohnson 0:d89511b21e3d 504 }
MartinJohnson 0:d89511b21e3d 505
MartinJohnson 0:d89511b21e3d 506