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-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;
