Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: STM32F3-Discovery
Diff: neopixel.c
- Revision:
- 0:d89511b21e3d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/neopixel.c Wed May 25 23:54:30 2016 +0000
@@ -0,0 +1,506 @@
+
+#include <stm32f30x.h>
+//#include <stm32f30x_misc.h>
+//#define ARM_MATH_CM4
+#include <math.h>
+#include "stm32f3_discovery_lsm303dlhc.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_BITS_PER_LED 24
+#define WS2812_DELAY_BUFFER_LENGTH 42 // for 50us delay
+
+#define BIT_COMPARE_1 17 // timer compare value for logical 1
+#define BIT_COMPARE_0 9 // timer compare value for logical 0
+#define WS2812_DATA_BUFFER_SIZE (WS2812_BITS_PER_LED * WS2812_LED_STRIP_LENGTH)
+
+#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];
+
+//static volatile uint8_t rgbData[WS2812_LED_STRIP_LENGTH*3];
+
+static volatile uint8_t WS2812LedDataTransferInProgress = 0;
+static uint16_t dmaBufferOffset;
+static int16_t ledIndex;
+
+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();
+
+}
+void SysTick_Handler(void) {
+ sysTicks++;
+ 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 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;
+}
+
+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;
+}
+
+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);
+
+ /* 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);
+}
+
+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);
+}
+
+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);
+}
+
+ 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);
+ }
+}
+
+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++;
+ }
+}
+
+typedef struct {
+ uint8_t red;
+ uint8_t green;
+ uint8_t blue;
+} rgb_struct;
+
+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);
+ }
+
+ WS2812LedDataTransferInProgress = 1;
+ WS2812LedStripDMAEnable();
+}
+
+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;
+ for (i = 0; i < WS2812_DMA_BUFFER_SIZE; i++)
+ ledStripDMABuffer[i] = 0;
+ WS2812UpdateStrip();
+}
+static float AccBuffer[3] = {0.0f};
+static float MagBuffer[3] = {0.0f};
+
+//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]));
+
+ fSinRoll = -AccBuffer[1] / fNormAcc;
+ fCosRoll = sqrtf(1.0f - (fSinRoll * fSinRoll));
+ fSinPitch = AccBuffer[0] / fNormAcc;
+ fCosPitch = sqrtf(1.0f - (fSinPitch * fSinPitch));
+ if (fSinRoll > 0) {
+ if (fCosRoll > 0) {
+ RollAng = acos(fCosRoll) * 180 / PI;
+ }
+ else {
+ RollAng = acos(fCosRoll) * 180 / PI + 180;
+ }
+ }
+ else {
+ if (fCosRoll > 0) {
+ RollAng = acos(fCosRoll) * 180 / PI + 360;
+ }
+ else {
+ RollAng = acos(fCosRoll) * 180 / PI + 180;
+ }
+ }
+ if (fSinPitch > 0) {
+ if (fCosPitch > 0) {
+ PitchAng = acos(fCosPitch) * 180 / PI;
+ }
+ else {
+ PitchAng = acos(fCosPitch) * 180 / PI + 180;
+ }
+ }
+ else {
+ if (fCosPitch > 0) {
+ PitchAng = acos(fCosPitch) * 180 / PI + 360;
+ }
+ else {
+ PitchAng = acos(fCosPitch) * 180 / PI + 180;
+ }
+ }
+
+ if (RollAng >= 360) {
+ RollAng = RollAng - 360;
+ }
+
+ if (PitchAng >= 360) {
+ PitchAng = PitchAng - 360;
+ }
+
+ fTiltedX = MagBuffer[0] * fCosPitch + MagBuffer[2] * fSinPitch;
+ fTiltedY = MagBuffer[0] * fSinRoll * fSinPitch + MagBuffer[1] * fCosRoll -
+ MagBuffer[1] * fSinRoll * fCosPitch;
+
+// fTiltedX=fTiltedX/sqrt(fTiltedX*fTiltedX+fTiltedY*fTiltedY);
+ HeadingValue = (float) ((atan2f( (float)fTiltedY, (float)fTiltedX)) * 180) / PI;
+
+ if (HeadingValue < 0) {
+ HeadingValue = HeadingValue + 360;
+ }
+ return HeadingValue;
+
+}
+
+int main(void) {
+ uint8_t i = 0;
+ int j=0;
+ int delay=2000;
+ int dch=-1;
+ int dir=1;
+ int btn=0;
+ uint32_t rgb = 0x0ff0000ff;
+ GPIO_init();
+ GPIOE->ODR ^= 0x100;
+ DMA_init();
+ GPIOE->ODR ^= 0x200;
+ TIM_init();
+ AccelerometerConfig();
+
+ 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;
+
+ WS2812UpdateStrip();
+ // wait 5ms
+ 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;
+ 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
+ }
+
+ WS2812UpdateStrip();
+ sysDelayMs(delay/100);
+ if((GPIOA->IDR & 1)==1 && btn==0)
+ dir=-dir;
+ btn=(GPIOA->IDR & 1);
+ delay=delay+dch;
+ if(delay<500 || delay>3000)
+ dch=-dch;
+ for(int k=0;k<WS2812_LED_STRIP_LENGTH;k++) {
+ rgbData[k].red = 0;
+ rgbData[k].green = 0;
+ rgbData[k].blue = 0;
+ }
+
+ ReadAccelerometer(AccBuffer);
+ int x=(int)AccBuffer[0];
+ int y=(int)AccBuffer[1];
+ int z=(int)AccBuffer[2];
+
+ delay=10000-abs(y)*20;
+ if(delay<0) delay=0;
+ if(y<0)
+ dir=1;
+ else
+ dir=-1;
+
+ j=(j+dir+WS2812_LED_STRIP_LENGTH)%WS2812_LED_STRIP_LENGTH;
+
+ rgb=(rgb<<1) /*^ (rand()&1 & rand()&1) ; */| (rgb>>24);
+
+ }
+}
+
+