16x16 square of neopixels for stm32f3 discovery board

Dependencies:   STM32F3-Discovery-minimal

Fork of neopixels by Martin Johnson

Revision:
1:6ed7aa3c8efa
Parent:
0:d89511b21e3d
--- 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;