16x16 square of neopixels for stm32f3 discovery board

Dependencies:   STM32F3-Discovery-minimal

Fork of neopixels by Martin Johnson

Committer:
MartinJohnson
Date:
Mon May 07 10:34:40 2018 +0000
Revision:
1:6ed7aa3c8efa
Parent:
0:d89511b21e3d
16x16 neopixel square with moving pattern

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 <math.h>
MartinJohnson 0:d89511b21e3d 4 #include "stm32f3_discovery_lsm303dlhc.h"
MartinJohnson 1:6ed7aa3c8efa 5 #include <stdio.h>
MartinJohnson 0:d89511b21e3d 6 #include <stdlib.h>
MartinJohnson 0:d89511b21e3d 7
MartinJohnson 0:d89511b21e3d 8 #define PI 3.1415926f
MartinJohnson 0:d89511b21e3d 9
MartinJohnson 1:6ed7aa3c8efa 10 #define WS2812_LED_STRIP_LENGTH 256
MartinJohnson 0:d89511b21e3d 11 #define WS2812_BITS_PER_LED 24
MartinJohnson 0:d89511b21e3d 12 #define WS2812_DELAY_BUFFER_LENGTH 42 // for 50us delay
MartinJohnson 0:d89511b21e3d 13
MartinJohnson 0:d89511b21e3d 14 #define BIT_COMPARE_1 17 // timer compare value for logical 1
MartinJohnson 0:d89511b21e3d 15 #define BIT_COMPARE_0 9 // timer compare value for logical 0
MartinJohnson 0:d89511b21e3d 16 #define WS2812_DATA_BUFFER_SIZE (WS2812_BITS_PER_LED * WS2812_LED_STRIP_LENGTH)
MartinJohnson 0:d89511b21e3d 17
MartinJohnson 0:d89511b21e3d 18 #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 19
MartinJohnson 1:6ed7aa3c8efa 20
MartinJohnson 1:6ed7aa3c8efa 21 #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)
MartinJohnson 1:6ed7aa3c8efa 22
MartinJohnson 1:6ed7aa3c8efa 23 void i2cWrite(int address, int reg, int val) {
MartinJohnson 1:6ed7aa3c8efa 24 while(I2C1->ISR & I2C_ISR_BUSY);
MartinJohnson 1:6ed7aa3c8efa 25 I2C1->CR2 = (I2C1->CR2 & I2C_CR2_CLEAR_MASK) | I2C_CR2_RELOAD | I2C_CR2_START | (1<<16) | address;
MartinJohnson 1:6ed7aa3c8efa 26 while(!(I2C1->ISR & I2C_ISR_TXIS));
MartinJohnson 1:6ed7aa3c8efa 27 I2C1->TXDR=reg;
MartinJohnson 1:6ed7aa3c8efa 28 while(!(I2C1->ISR & I2C_ISR_TCR));
MartinJohnson 1:6ed7aa3c8efa 29 I2C1->CR2 = (I2C1->CR2 & I2C_CR2_CLEAR_MASK) | I2C_CR2_AUTOEND | (1<<16) | address;
MartinJohnson 1:6ed7aa3c8efa 30 while(!(I2C1->ISR & I2C_ISR_TXIS));
MartinJohnson 1:6ed7aa3c8efa 31 I2C1->TXDR=val;
MartinJohnson 1:6ed7aa3c8efa 32 while(!(I2C1->ISR & I2C_ISR_STOPF));
MartinJohnson 1:6ed7aa3c8efa 33 I2C1->ICR = I2C_ICR_STOPCF;
MartinJohnson 1:6ed7aa3c8efa 34 }
MartinJohnson 0:d89511b21e3d 35
MartinJohnson 1:6ed7aa3c8efa 36 void i2cRead(int address, int reg, uint8_t *data, int nbytes) {
MartinJohnson 1:6ed7aa3c8efa 37 while(I2C1->ISR & I2C_ISR_BUSY);
MartinJohnson 1:6ed7aa3c8efa 38 I2C1->CR2 = (I2C1->CR2 & I2C_CR2_CLEAR_MASK) | I2C_CR2_START | (1<<16) | address;
MartinJohnson 1:6ed7aa3c8efa 39 while(!(I2C1->ISR & I2C_ISR_TXIS));
MartinJohnson 1:6ed7aa3c8efa 40 if(nbytes>1) reg |= 0x80;
MartinJohnson 1:6ed7aa3c8efa 41 I2C1->TXDR=reg;
MartinJohnson 1:6ed7aa3c8efa 42 while(!(I2C1->ISR & I2C_ISR_TC));
MartinJohnson 1:6ed7aa3c8efa 43 I2C1->CR2 = (I2C1->CR2 & I2C_CR2_CLEAR_MASK) | I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_RD_WRN | (nbytes<<16) | address;
MartinJohnson 1:6ed7aa3c8efa 44 while(nbytes--) {
MartinJohnson 1:6ed7aa3c8efa 45 while(!(I2C1->ISR & I2C_ISR_RXNE));
MartinJohnson 1:6ed7aa3c8efa 46 *data++=I2C1->RXDR;
MartinJohnson 1:6ed7aa3c8efa 47 }
MartinJohnson 1:6ed7aa3c8efa 48 while(!(I2C1->ISR & I2C_ISR_STOPF));
MartinJohnson 1:6ed7aa3c8efa 49 I2C1->ICR = I2C_ICR_STOPCF;
MartinJohnson 1:6ed7aa3c8efa 50 }
MartinJohnson 1:6ed7aa3c8efa 51 #define GPIO_MODE_INPUT 0
MartinJohnson 1:6ed7aa3c8efa 52 #define GPIO_MODE_OUTPUT 1
MartinJohnson 1:6ed7aa3c8efa 53 #define GPIO_MODE_AF 2
MartinJohnson 1:6ed7aa3c8efa 54
MartinJohnson 1:6ed7aa3c8efa 55 #define GPIO_PULL_UP 1
MartinJohnson 1:6ed7aa3c8efa 56 #define GPIO_PULL_DOWN 2
MartinJohnson 1:6ed7aa3c8efa 57
MartinJohnson 1:6ed7aa3c8efa 58 #define GPIO_OUTPUT_PUSH_PULL 0
MartinJohnson 1:6ed7aa3c8efa 59
MartinJohnson 1:6ed7aa3c8efa 60 #define GPIO_SPEED_FAST 3
MartinJohnson 1:6ed7aa3c8efa 61
MartinJohnson 1:6ed7aa3c8efa 62 void gpio_set_mode(GPIO_TypeDef *g,int n,int mode) {
MartinJohnson 1:6ed7aa3c8efa 63 n=n<<1;
MartinJohnson 1:6ed7aa3c8efa 64 g->MODER = (g->MODER & ~(3<<n)) | (mode<<n);
MartinJohnson 1:6ed7aa3c8efa 65 }
MartinJohnson 0:d89511b21e3d 66
MartinJohnson 1:6ed7aa3c8efa 67 void gpio_set_af(GPIO_TypeDef *g,int n,int af, int otype, int pupd, int speed) {
MartinJohnson 1:6ed7aa3c8efa 68 int reg=n>>3;
MartinJohnson 1:6ed7aa3c8efa 69 int pos=(n&7)*4;
MartinJohnson 1:6ed7aa3c8efa 70 g->AFR[reg] = (g->AFR[reg] & ~(0xf<<pos)) | (af<<pos); // alt func
MartinJohnson 1:6ed7aa3c8efa 71 pos=(n<<1);
MartinJohnson 1:6ed7aa3c8efa 72 g->OSPEEDR = (g->OSPEEDR & ~(3<<pos)) | (speed<<pos);
MartinJohnson 1:6ed7aa3c8efa 73 g->OTYPER = (g->OTYPER & ~(1<<n)) | (otype<<n);
MartinJohnson 1:6ed7aa3c8efa 74 gpio_set_mode(g,n,GPIO_MODE_AF);
MartinJohnson 1:6ed7aa3c8efa 75 g->PUPDR = (g->PUPDR & ~(3<<pos)) | (pupd<<pos);
MartinJohnson 1:6ed7aa3c8efa 76 }
MartinJohnson 1:6ed7aa3c8efa 77
MartinJohnson 1:6ed7aa3c8efa 78 void i2cInit() {
MartinJohnson 1:6ed7aa3c8efa 79 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN;
MartinJohnson 1:6ed7aa3c8efa 80 RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
MartinJohnson 1:6ed7aa3c8efa 81 // configure GPIOPB6 and 7
MartinJohnson 1:6ed7aa3c8efa 82 gpio_set_af(GPIOB,6,4,GPIO_OUTPUT_PUSH_PULL,GPIO_PULL_DOWN,GPIO_SPEED_FAST);
MartinJohnson 1:6ed7aa3c8efa 83 gpio_set_af(GPIOB,7,4,GPIO_OUTPUT_PUSH_PULL,GPIO_PULL_DOWN,GPIO_SPEED_FAST);
MartinJohnson 1:6ed7aa3c8efa 84
MartinJohnson 1:6ed7aa3c8efa 85 I2C1->TIMINGR = 0x00902025;
MartinJohnson 1:6ed7aa3c8efa 86 I2C1->CR1 |= I2C_CR1_PE;
MartinJohnson 1:6ed7aa3c8efa 87
MartinJohnson 1:6ed7aa3c8efa 88 }
MartinJohnson 1:6ed7aa3c8efa 89
MartinJohnson 1:6ed7aa3c8efa 90 void MemsConfig(void)
MartinJohnson 1:6ed7aa3c8efa 91 {
MartinJohnson 1:6ed7aa3c8efa 92 i2cInit();
MartinJohnson 1:6ed7aa3c8efa 93 i2cWrite(ACC_I2C_ADDRESS, LSM303DLHC_CTRL_REG1_A,LSM303DLHC_NORMAL_MODE | LSM303DLHC_ODR_50_HZ | LSM303DLHC_AXES_ENABLE);
MartinJohnson 1:6ed7aa3c8efa 94 i2cWrite(ACC_I2C_ADDRESS, LSM303DLHC_CTRL_REG4_A,LSM303DLHC_FULLSCALE_2G | LSM303DLHC_BlockUpdate_Continous | LSM303DLHC_BLE_LSB | LSM303DLHC_HR_ENABLE);
MartinJohnson 1:6ed7aa3c8efa 95 i2cWrite(ACC_I2C_ADDRESS, LSM303DLHC_CTRL_REG2_A,LSM303DLHC_HPM_NORMAL_MODE | LSM303DLHC_HPFCF_16 | LSM303DLHC_HPF_AOI1_DISABLE | LSM303DLHC_HPF_AOI2_DISABLE);
MartinJohnson 1:6ed7aa3c8efa 96
MartinJohnson 1:6ed7aa3c8efa 97 i2cWrite(MAG_I2C_ADDRESS, LSM303DLHC_CRA_REG_M, LSM303DLHC_TEMPSENSOR_ENABLE | LSM303DLHC_ODR_30_HZ);
MartinJohnson 1:6ed7aa3c8efa 98 i2cWrite(MAG_I2C_ADDRESS, LSM303DLHC_CRB_REG_M, LSM303DLHC_FS_8_1_GA);
MartinJohnson 1:6ed7aa3c8efa 99 i2cWrite(MAG_I2C_ADDRESS, LSM303DLHC_MR_REG_M,LSM303DLHC_CONTINUOS_CONVERSION);
MartinJohnson 1:6ed7aa3c8efa 100 }
MartinJohnson 1:6ed7aa3c8efa 101
MartinJohnson 1:6ed7aa3c8efa 102 void ReadAccelerometer(int16_t * data) {
MartinJohnson 1:6ed7aa3c8efa 103 i2cRead(ACC_I2C_ADDRESS, LSM303DLHC_OUT_X_L_A, (uint8_t *)data, 6);
MartinJohnson 1:6ed7aa3c8efa 104 }
MartinJohnson 1:6ed7aa3c8efa 105
MartinJohnson 1:6ed7aa3c8efa 106 void ReadMagnetometer(int16_t * data) {
MartinJohnson 1:6ed7aa3c8efa 107 i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_L_M, (uint8_t *)data, 1);
MartinJohnson 1:6ed7aa3c8efa 108 i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_X_H_M, (uint8_t *)data+1, 1);
MartinJohnson 1:6ed7aa3c8efa 109 i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Y_L_M, (uint8_t *)data+2, 1);
MartinJohnson 1:6ed7aa3c8efa 110 i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Y_H_M, (uint8_t *)data+3, 1);
MartinJohnson 1:6ed7aa3c8efa 111 i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Z_L_M, (uint8_t *)data+4, 1);
MartinJohnson 1:6ed7aa3c8efa 112 i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_OUT_Z_H_M, (uint8_t *)data+5, 1);
MartinJohnson 1:6ed7aa3c8efa 113 }
MartinJohnson 1:6ed7aa3c8efa 114
MartinJohnson 1:6ed7aa3c8efa 115 int ReadTemperature() {
MartinJohnson 1:6ed7aa3c8efa 116 int t=0;
MartinJohnson 1:6ed7aa3c8efa 117 i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_TEMP_OUT_L_M, (uint8_t *)&t,1);
MartinJohnson 1:6ed7aa3c8efa 118 i2cRead(MAG_I2C_ADDRESS, LSM303DLHC_TEMP_OUT_H_M, (uint8_t *)&t+1,1);
MartinJohnson 1:6ed7aa3c8efa 119 return t/64;
MartinJohnson 1:6ed7aa3c8efa 120 }
MartinJohnson 1:6ed7aa3c8efa 121
MartinJohnson 1:6ed7aa3c8efa 122 static uint8_t ledStripDMABuffer[WS2812_DMA_BUFFER_SIZE];
MartinJohnson 1:6ed7aa3c8efa 123
MartinJohnson 1:6ed7aa3c8efa 124 static uint8_t WS2812LedDataTransferInProgress = 0;
MartinJohnson 0:d89511b21e3d 125
MartinJohnson 0:d89511b21e3d 126 volatile unsigned sysTiming;
MartinJohnson 0:d89511b21e3d 127 volatile unsigned sysTicks = 0;
MartinJohnson 0:d89511b21e3d 128
MartinJohnson 0:d89511b21e3d 129 void sysDelayMs(unsigned dly) {
MartinJohnson 0:d89511b21e3d 130 sysTiming = dly;
MartinJohnson 0:d89511b21e3d 131 while (sysTiming > 0) __wfi();
MartinJohnson 0:d89511b21e3d 132
MartinJohnson 0:d89511b21e3d 133 }
MartinJohnson 0:d89511b21e3d 134 void SysTick_Handler(void) {
MartinJohnson 0:d89511b21e3d 135 sysTicks++;
MartinJohnson 0:d89511b21e3d 136 if (sysTiming > 0) --sysTiming;
MartinJohnson 0:d89511b21e3d 137 }
MartinJohnson 0:d89511b21e3d 138
MartinJohnson 1:6ed7aa3c8efa 139 void GPIO_init(void) {
MartinJohnson 1:6ed7aa3c8efa 140
MartinJohnson 1:6ed7aa3c8efa 141 RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOEEN ;
MartinJohnson 1:6ed7aa3c8efa 142 RCC->APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_TIM2EN;
MartinJohnson 1:6ed7aa3c8efa 143 RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_TIM16EN;
MartinJohnson 0:d89511b21e3d 144
MartinJohnson 1:6ed7aa3c8efa 145 SysTick_Config((SystemCoreClock / 1000) -1 );
MartinJohnson 1:6ed7aa3c8efa 146
MartinJohnson 1:6ed7aa3c8efa 147 gpio_set_af(GPIOB,8,1,GPIO_OUTPUT_PUSH_PULL,GPIO_PULL_UP,GPIO_SPEED_FAST);
MartinJohnson 0:d89511b21e3d 148
MartinJohnson 1:6ed7aa3c8efa 149 GPIOE->MODER = (GPIOE->MODER&0xffff) | 0x55550000; // output mode for PE8-15
MartinJohnson 1:6ed7aa3c8efa 150 GPIOA->MODER = (GPIOA->MODER&0xfffffffc) ; // input mode for PA0
MartinJohnson 1:6ed7aa3c8efa 151 GPIOA->PUPDR = (GPIOA->PUPDR & ~0x3) | 0x2; // pull down (10)
MartinJohnson 0:d89511b21e3d 152 }
MartinJohnson 0:d89511b21e3d 153
MartinJohnson 0:d89511b21e3d 154 void TIM_init(void)
MartinJohnson 0:d89511b21e3d 155 {
MartinJohnson 1:6ed7aa3c8efa 156 TIM16->CR1 &= ~TIM_CR1_CEN;
MartinJohnson 1:6ed7aa3c8efa 157 TIM16->PSC=(uint16_t) (SystemCoreClock / 24000000) - 1;
MartinJohnson 1:6ed7aa3c8efa 158 TIM16->CNT=0;
MartinJohnson 1:6ed7aa3c8efa 159 TIM16->ARR=29; // 24MHz/30=800KHz
MartinJohnson 1:6ed7aa3c8efa 160 TIM16->CR1 |= TIM_CR1_CEN;
MartinJohnson 0:d89511b21e3d 161
MartinJohnson 1:6ed7aa3c8efa 162 // disable Capture and Compare 1
MartinJohnson 1:6ed7aa3c8efa 163 TIM16->CCER &= ~TIM_CCER_CC1E;
MartinJohnson 1:6ed7aa3c8efa 164 // set output compare 1 to PWM mode with preload
MartinJohnson 1:6ed7aa3c8efa 165 TIM16->CCMR1 = (TIM16->CCMR1 & ~(TIM_CCMR1_OC1M | TIM_CCMR1_CC1S)) | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE ;
MartinJohnson 1:6ed7aa3c8efa 166 // enable Capture and Compare 1
MartinJohnson 1:6ed7aa3c8efa 167 TIM16->CCER |= TIM_CCER_CC1E;
MartinJohnson 1:6ed7aa3c8efa 168 // main output enable
MartinJohnson 1:6ed7aa3c8efa 169 TIM16->BDTR |= TIM_BDTR_MOE;
MartinJohnson 0:d89511b21e3d 170 }
MartinJohnson 0:d89511b21e3d 171
MartinJohnson 0:d89511b21e3d 172 void DMA_init(void) {
MartinJohnson 1:6ed7aa3c8efa 173 // enable DMA1 controller
MartinJohnson 1:6ed7aa3c8efa 174 RCC->AHBENR |= RCC_AHBENR_DMA1EN;
MartinJohnson 1:6ed7aa3c8efa 175 // direction = peripheral dest, memory inc, peripheral size=halfword, memory size=byte, priority level=high, transmission complete interrupt enabled
MartinJohnson 1:6ed7aa3c8efa 176 DMA1_Channel3->CCR = DMA_CCR_DIR | DMA_CCR_MINC | DMA_CCR_PSIZE_0 | DMA_CCR_PL_1 | DMA_CCR_TCIE;
MartinJohnson 1:6ed7aa3c8efa 177 // bytes to transfer
MartinJohnson 1:6ed7aa3c8efa 178 DMA1_Channel3->CNDTR = WS2812_DMA_BUFFER_SIZE;
MartinJohnson 1:6ed7aa3c8efa 179 // peripheral address
MartinJohnson 1:6ed7aa3c8efa 180 DMA1_Channel3->CPAR =(uint32_t)&TIM16->CCR1;
MartinJohnson 1:6ed7aa3c8efa 181 // memory address
MartinJohnson 1:6ed7aa3c8efa 182 DMA1_Channel3->CMAR =(uint32_t)ledStripDMABuffer;
MartinJohnson 1:6ed7aa3c8efa 183 // enable CC DMA for TIM16
MartinJohnson 1:6ed7aa3c8efa 184 TIM16->DIER |= TIM_DIER_CC1DE;
MartinJohnson 1:6ed7aa3c8efa 185 // configure NVIC
MartinJohnson 1:6ed7aa3c8efa 186 NVIC->IP[DMA1_Channel3_IRQn]=16; // Interrupt Priority, lower is higher priority
MartinJohnson 1:6ed7aa3c8efa 187 NVIC->ISER[DMA1_Channel3_IRQn >> 0x05] = 1 << (DMA1_Channel3_IRQn & 0x1F); // Interrupt enable
MartinJohnson 1:6ed7aa3c8efa 188
MartinJohnson 0:d89511b21e3d 189 }
MartinJohnson 0:d89511b21e3d 190
MartinJohnson 0:d89511b21e3d 191 void WS2812LedStripDMAEnable(void) {
MartinJohnson 1:6ed7aa3c8efa 192 // bytes to transfer
MartinJohnson 1:6ed7aa3c8efa 193 DMA1_Channel3->CNDTR = WS2812_DMA_BUFFER_SIZE;
MartinJohnson 1:6ed7aa3c8efa 194 TIM16->CNT=0;
MartinJohnson 1:6ed7aa3c8efa 195 // start counter
MartinJohnson 1:6ed7aa3c8efa 196 TIM16->CCER |= TIM_CCER_CC1E;
MartinJohnson 1:6ed7aa3c8efa 197 // enable DMA
MartinJohnson 1:6ed7aa3c8efa 198 DMA1_Channel3->CCR |= DMA_CCR_EN;
MartinJohnson 0:d89511b21e3d 199 }
MartinJohnson 0:d89511b21e3d 200
MartinJohnson 0:d89511b21e3d 201 void DMA1_Channel3_IRQHandler(void) {
MartinJohnson 1:6ed7aa3c8efa 202 // if transfer complete
MartinJohnson 1:6ed7aa3c8efa 203 if(DMA1->ISR & DMA_ISR_TCIF3) {
MartinJohnson 1:6ed7aa3c8efa 204 WS2812LedDataTransferInProgress = 0;
MartinJohnson 1:6ed7aa3c8efa 205 // disable DMA
MartinJohnson 1:6ed7aa3c8efa 206 DMA1_Channel3->CCR &= ~DMA_CCR_EN;
MartinJohnson 1:6ed7aa3c8efa 207 // clear flag
MartinJohnson 1:6ed7aa3c8efa 208 DMA1->IFCR = DMA_ISR_TCIF3;
MartinJohnson 0:d89511b21e3d 209 }
MartinJohnson 0:d89511b21e3d 210 }
MartinJohnson 0:d89511b21e3d 211
MartinJohnson 1:6ed7aa3c8efa 212 uint8_t *updateLEDDMABuffer(uint8_t *buffer, unsigned val) {
MartinJohnson 1:6ed7aa3c8efa 213 for (int i=0;i<8;i++) {
MartinJohnson 1:6ed7aa3c8efa 214 if ((val) & (0x80)) // data sent MSB first
MartinJohnson 1:6ed7aa3c8efa 215 *buffer++=BIT_COMPARE_1; // pwm level for 1
MartinJohnson 1:6ed7aa3c8efa 216 else
MartinJohnson 1:6ed7aa3c8efa 217 *buffer++=BIT_COMPARE_0; // pwm level for 0
MartinJohnson 1:6ed7aa3c8efa 218 val=val<<1; // move to next bit
MartinJohnson 0:d89511b21e3d 219 }
MartinJohnson 1:6ed7aa3c8efa 220 return buffer;
MartinJohnson 0:d89511b21e3d 221 }
MartinJohnson 0:d89511b21e3d 222
MartinJohnson 0:d89511b21e3d 223 typedef struct {
MartinJohnson 0:d89511b21e3d 224 uint8_t red;
MartinJohnson 0:d89511b21e3d 225 uint8_t green;
MartinJohnson 0:d89511b21e3d 226 uint8_t blue;
MartinJohnson 0:d89511b21e3d 227 } rgb_struct;
MartinJohnson 0:d89511b21e3d 228
MartinJohnson 0:d89511b21e3d 229 static volatile rgb_struct rgbData[WS2812_LED_STRIP_LENGTH];
MartinJohnson 0:d89511b21e3d 230
MartinJohnson 0:d89511b21e3d 231 void WS2812UpdateStrip(void) {
MartinJohnson 0:d89511b21e3d 232 // wait until previous transfer completes
MartinJohnson 1:6ed7aa3c8efa 233 while (WS2812LedDataTransferInProgress) __wfi();
MartinJohnson 1:6ed7aa3c8efa 234 uint8_t *buffer=ledStripDMABuffer;
MartinJohnson 1:6ed7aa3c8efa 235 for(int i=0;i<WS2812_LED_STRIP_LENGTH;i++) {
MartinJohnson 1:6ed7aa3c8efa 236 buffer=updateLEDDMABuffer(buffer,rgbData[i].green);
MartinJohnson 1:6ed7aa3c8efa 237 buffer=updateLEDDMABuffer(buffer,rgbData[i].red);
MartinJohnson 1:6ed7aa3c8efa 238 buffer=updateLEDDMABuffer(buffer,rgbData[i].blue);
MartinJohnson 0:d89511b21e3d 239 }
MartinJohnson 0:d89511b21e3d 240
MartinJohnson 0:d89511b21e3d 241 WS2812LedDataTransferInProgress = 1;
MartinJohnson 0:d89511b21e3d 242 WS2812LedStripDMAEnable();
MartinJohnson 0:d89511b21e3d 243 }
MartinJohnson 0:d89511b21e3d 244
MartinJohnson 0:d89511b21e3d 245 extern volatile unsigned sysTicks;
MartinJohnson 0:d89511b21e3d 246 int rndseed=0;
MartinJohnson 0:d89511b21e3d 247
MartinJohnson 0:d89511b21e3d 248 void WS2812LedStripInit(void) {
MartinJohnson 0:d89511b21e3d 249 int i;
MartinJohnson 0:d89511b21e3d 250 for (i = 0; i < WS2812_DMA_BUFFER_SIZE; i++)
MartinJohnson 0:d89511b21e3d 251 ledStripDMABuffer[i] = 0;
MartinJohnson 0:d89511b21e3d 252 WS2812UpdateStrip();
MartinJohnson 0:d89511b21e3d 253 }
MartinJohnson 1:6ed7aa3c8efa 254 static short AccBuffer[3] = {0};
MartinJohnson 1:6ed7aa3c8efa 255 static short MagBuffer[3] = {0};
MartinJohnson 0:d89511b21e3d 256
MartinJohnson 0:d89511b21e3d 257 int getheading() {
MartinJohnson 0:d89511b21e3d 258 /* Read Compass data */
MartinJohnson 0:d89511b21e3d 259 ReadMagnetometer(MagBuffer);
MartinJohnson 0:d89511b21e3d 260 ReadAccelerometer(AccBuffer);
MartinJohnson 0:d89511b21e3d 261 float fNormAcc, fSinRoll, fCosRoll, fSinPitch, fCosPitch = 0.0f, RollAng = 0.0f, PitchAng = 0.0f;
MartinJohnson 0:d89511b21e3d 262 float fTiltedX, fTiltedY = 0.0f;
MartinJohnson 0:d89511b21e3d 263 float HeadingValue;
MartinJohnson 1:6ed7aa3c8efa 264
MartinJohnson 0:d89511b21e3d 265 fNormAcc = sqrtf((AccBuffer[0] * AccBuffer[0]) + (AccBuffer[1] * AccBuffer[1]) +
MartinJohnson 0:d89511b21e3d 266 (AccBuffer[2] * AccBuffer[2]));
MartinJohnson 0:d89511b21e3d 267
MartinJohnson 0:d89511b21e3d 268 fSinRoll = -AccBuffer[1] / fNormAcc;
MartinJohnson 0:d89511b21e3d 269 fCosRoll = sqrtf(1.0f - (fSinRoll * fSinRoll));
MartinJohnson 0:d89511b21e3d 270 fSinPitch = AccBuffer[0] / fNormAcc;
MartinJohnson 0:d89511b21e3d 271 fCosPitch = sqrtf(1.0f - (fSinPitch * fSinPitch));
MartinJohnson 0:d89511b21e3d 272 if (fSinRoll > 0) {
MartinJohnson 0:d89511b21e3d 273 if (fCosRoll > 0) {
MartinJohnson 0:d89511b21e3d 274 RollAng = acos(fCosRoll) * 180 / PI;
MartinJohnson 0:d89511b21e3d 275 }
MartinJohnson 0:d89511b21e3d 276 else {
MartinJohnson 0:d89511b21e3d 277 RollAng = acos(fCosRoll) * 180 / PI + 180;
MartinJohnson 0:d89511b21e3d 278 }
MartinJohnson 0:d89511b21e3d 279 }
MartinJohnson 0:d89511b21e3d 280 else {
MartinJohnson 0:d89511b21e3d 281 if (fCosRoll > 0) {
MartinJohnson 0:d89511b21e3d 282 RollAng = acos(fCosRoll) * 180 / PI + 360;
MartinJohnson 0:d89511b21e3d 283 }
MartinJohnson 0:d89511b21e3d 284 else {
MartinJohnson 0:d89511b21e3d 285 RollAng = acos(fCosRoll) * 180 / PI + 180;
MartinJohnson 0:d89511b21e3d 286 }
MartinJohnson 0:d89511b21e3d 287 }
MartinJohnson 0:d89511b21e3d 288 if (fSinPitch > 0) {
MartinJohnson 0:d89511b21e3d 289 if (fCosPitch > 0) {
MartinJohnson 0:d89511b21e3d 290 PitchAng = acos(fCosPitch) * 180 / PI;
MartinJohnson 0:d89511b21e3d 291 }
MartinJohnson 0:d89511b21e3d 292 else {
MartinJohnson 0:d89511b21e3d 293 PitchAng = acos(fCosPitch) * 180 / PI + 180;
MartinJohnson 0:d89511b21e3d 294 }
MartinJohnson 0:d89511b21e3d 295 }
MartinJohnson 0:d89511b21e3d 296 else {
MartinJohnson 0:d89511b21e3d 297 if (fCosPitch > 0) {
MartinJohnson 0:d89511b21e3d 298 PitchAng = acos(fCosPitch) * 180 / PI + 360;
MartinJohnson 0:d89511b21e3d 299 }
MartinJohnson 0:d89511b21e3d 300 else {
MartinJohnson 0:d89511b21e3d 301 PitchAng = acos(fCosPitch) * 180 / PI + 180;
MartinJohnson 0:d89511b21e3d 302 }
MartinJohnson 0:d89511b21e3d 303 }
MartinJohnson 0:d89511b21e3d 304
MartinJohnson 0:d89511b21e3d 305 if (RollAng >= 360) {
MartinJohnson 0:d89511b21e3d 306 RollAng = RollAng - 360;
MartinJohnson 0:d89511b21e3d 307 }
MartinJohnson 0:d89511b21e3d 308
MartinJohnson 0:d89511b21e3d 309 if (PitchAng >= 360) {
MartinJohnson 0:d89511b21e3d 310 PitchAng = PitchAng - 360;
MartinJohnson 0:d89511b21e3d 311 }
MartinJohnson 0:d89511b21e3d 312
MartinJohnson 0:d89511b21e3d 313 fTiltedX = MagBuffer[0] * fCosPitch + MagBuffer[2] * fSinPitch;
MartinJohnson 0:d89511b21e3d 314 fTiltedY = MagBuffer[0] * fSinRoll * fSinPitch + MagBuffer[1] * fCosRoll -
MartinJohnson 0:d89511b21e3d 315 MagBuffer[1] * fSinRoll * fCosPitch;
MartinJohnson 0:d89511b21e3d 316
MartinJohnson 0:d89511b21e3d 317 // fTiltedX=fTiltedX/sqrt(fTiltedX*fTiltedX+fTiltedY*fTiltedY);
MartinJohnson 0:d89511b21e3d 318 HeadingValue = (float) ((atan2f( (float)fTiltedY, (float)fTiltedX)) * 180) / PI;
MartinJohnson 0:d89511b21e3d 319
MartinJohnson 0:d89511b21e3d 320 if (HeadingValue < 0) {
MartinJohnson 0:d89511b21e3d 321 HeadingValue = HeadingValue + 360;
MartinJohnson 0:d89511b21e3d 322 }
MartinJohnson 0:d89511b21e3d 323 return HeadingValue;
MartinJohnson 0:d89511b21e3d 324 }
MartinJohnson 0:d89511b21e3d 325
MartinJohnson 0:d89511b21e3d 326 int main(void) {
MartinJohnson 0:d89511b21e3d 327 uint8_t i = 0;
MartinJohnson 0:d89511b21e3d 328 int j=0;
MartinJohnson 0:d89511b21e3d 329 int delay=2000;
MartinJohnson 0:d89511b21e3d 330 int dch=-1;
MartinJohnson 0:d89511b21e3d 331 int dir=1;
MartinJohnson 0:d89511b21e3d 332 int btn=0;
MartinJohnson 0:d89511b21e3d 333 uint32_t rgb = 0x0ff0000ff;
MartinJohnson 0:d89511b21e3d 334 GPIO_init();
MartinJohnson 0:d89511b21e3d 335 DMA_init();
MartinJohnson 0:d89511b21e3d 336 TIM_init();
MartinJohnson 1:6ed7aa3c8efa 337 MemsConfig();
MartinJohnson 0:d89511b21e3d 338
MartinJohnson 0:d89511b21e3d 339 WS2812LedDataTransferInProgress = 0;
MartinJohnson 0:d89511b21e3d 340 WS2812LedStripInit();
MartinJohnson 1:6ed7aa3c8efa 341
MartinJohnson 1:6ed7aa3c8efa 342 float yo=7.5,xo=7.5;
MartinJohnson 1:6ed7aa3c8efa 343 float xs=1,ys=1;
MartinJohnson 1:6ed7aa3c8efa 344 float offset=0;
MartinJohnson 1:6ed7aa3c8efa 345 while(!(GPIOA->IDR & 1)) {
MartinJohnson 1:6ed7aa3c8efa 346 offset-=0.3f;
MartinJohnson 1:6ed7aa3c8efa 347 //int heading = getheading();
MartinJohnson 1:6ed7aa3c8efa 348 ReadAccelerometer(AccBuffer);
MartinJohnson 1:6ed7aa3c8efa 349 int x=(int)AccBuffer[0]/32;
MartinJohnson 1:6ed7aa3c8efa 350 int y=(int)AccBuffer[1]/32;
MartinJohnson 1:6ed7aa3c8efa 351 ys=y/180.0+1;
MartinJohnson 1:6ed7aa3c8efa 352 xs=x/180.0+1;
MartinJohnson 0:d89511b21e3d 353
MartinJohnson 1:6ed7aa3c8efa 354 for (int i = 0; i < 256; i++) {
MartinJohnson 1:6ed7aa3c8efa 355 int y1=i/16;
MartinJohnson 1:6ed7aa3c8efa 356 int x1=i%16;
MartinJohnson 1:6ed7aa3c8efa 357 if(y1%2) x1=15-x1;
MartinJohnson 1:6ed7aa3c8efa 358 y1=15-y1;
MartinJohnson 1:6ed7aa3c8efa 359
MartinJohnson 1:6ed7aa3c8efa 360 double d=(sqrt(abs(ys*(y1-yo)*(y1-yo)+xs*(x1-xo)*(x1-xo)))+offset)/4.0;
MartinJohnson 1:6ed7aa3c8efa 361 rgbData[i].red=(uint8_t)(round(4.0*sin(1.0299*d)+4.0)/1);
MartinJohnson 1:6ed7aa3c8efa 362 rgbData[i].green=(uint8_t)(round(4.0*cos(3.2235*d)+4.0)/1);
MartinJohnson 1:6ed7aa3c8efa 363 rgbData[i].blue=(uint8_t)(round(4.0*sin(5.1234*d)+4.0)/1);
MartinJohnson 1:6ed7aa3c8efa 364 }
MartinJohnson 1:6ed7aa3c8efa 365 WS2812UpdateStrip();
MartinJohnson 1:6ed7aa3c8efa 366 // wait 5ms
MartinJohnson 1:6ed7aa3c8efa 367 sysDelayMs(5);
MartinJohnson 1:6ed7aa3c8efa 368 }
MartinJohnson 0:d89511b21e3d 369
MartinJohnson 1:6ed7aa3c8efa 370 while (GPIOA->IDR & 1) {
MartinJohnson 1:6ed7aa3c8efa 371 int heading = getheading();
MartinJohnson 1:6ed7aa3c8efa 372 int led = (heading * WS2812_LED_STRIP_LENGTH) / 360;
MartinJohnson 1:6ed7aa3c8efa 373 int next = (led + 1) % WS2812_LED_STRIP_LENGTH;
MartinJohnson 1:6ed7aa3c8efa 374 int v2 = (heading - (led * 360) / WS2812_LED_STRIP_LENGTH) * 10;
MartinJohnson 1:6ed7aa3c8efa 375 int v1 = 225 - v2;
MartinJohnson 1:6ed7aa3c8efa 376
MartinJohnson 1:6ed7aa3c8efa 377 rgbData[led].red = v1;
MartinJohnson 1:6ed7aa3c8efa 378 rgbData[next].red = v2;
MartinJohnson 1:6ed7aa3c8efa 379
MartinJohnson 1:6ed7aa3c8efa 380 WS2812UpdateStrip();
MartinJohnson 1:6ed7aa3c8efa 381 // wait 15ms
MartinJohnson 1:6ed7aa3c8efa 382 sysDelayMs(15);
MartinJohnson 1:6ed7aa3c8efa 383 rgbData[led].red = 0;
MartinJohnson 1:6ed7aa3c8efa 384 rgbData[next].red = 0;
MartinJohnson 1:6ed7aa3c8efa 385
MartinJohnson 0:d89511b21e3d 386 }
MartinJohnson 1:6ed7aa3c8efa 387
MartinJohnson 0:d89511b21e3d 388 while (1) { // flashing lights moving along the strip
MartinJohnson 0:d89511b21e3d 389
MartinJohnson 1:6ed7aa3c8efa 390 int NLIGHTS=32;
MartinJohnson 0:d89511b21e3d 391 i=j;
MartinJohnson 1:6ed7aa3c8efa 392 for(int k=0;k<NLIGHTS;k++) {
MartinJohnson 1:6ed7aa3c8efa 393 rgbData[i].red = (rgb & 255)/8; // green
MartinJohnson 1:6ed7aa3c8efa 394 rgbData[i].green = ((rgb >> 8) & 255)/8; // red
MartinJohnson 1:6ed7aa3c8efa 395 rgbData[i].blue = ((rgb >> 16) & 255)/8; // blue
MartinJohnson 1:6ed7aa3c8efa 396 i=(i+WS2812_LED_STRIP_LENGTH/NLIGHTS)%WS2812_LED_STRIP_LENGTH;
MartinJohnson 0:d89511b21e3d 397 }
MartinJohnson 0:d89511b21e3d 398
MartinJohnson 0:d89511b21e3d 399 WS2812UpdateStrip();
MartinJohnson 0:d89511b21e3d 400 sysDelayMs(delay/100);
MartinJohnson 0:d89511b21e3d 401 if((GPIOA->IDR & 1)==1 && btn==0)
MartinJohnson 0:d89511b21e3d 402 dir=-dir;
MartinJohnson 0:d89511b21e3d 403 btn=(GPIOA->IDR & 1);
MartinJohnson 0:d89511b21e3d 404 delay=delay+dch;
MartinJohnson 0:d89511b21e3d 405 if(delay<500 || delay>3000)
MartinJohnson 0:d89511b21e3d 406 dch=-dch;
MartinJohnson 0:d89511b21e3d 407 for(int k=0;k<WS2812_LED_STRIP_LENGTH;k++) {
MartinJohnson 0:d89511b21e3d 408 rgbData[k].red = 0;
MartinJohnson 0:d89511b21e3d 409 rgbData[k].green = 0;
MartinJohnson 0:d89511b21e3d 410 rgbData[k].blue = 0;
MartinJohnson 0:d89511b21e3d 411 }
MartinJohnson 0:d89511b21e3d 412
MartinJohnson 0:d89511b21e3d 413 ReadAccelerometer(AccBuffer);
MartinJohnson 1:6ed7aa3c8efa 414 int y=(int)AccBuffer[1]/32;
MartinJohnson 0:d89511b21e3d 415
MartinJohnson 0:d89511b21e3d 416 delay=10000-abs(y)*20;
MartinJohnson 0:d89511b21e3d 417 if(delay<0) delay=0;
MartinJohnson 0:d89511b21e3d 418 if(y<0)
MartinJohnson 0:d89511b21e3d 419 dir=1;
MartinJohnson 0:d89511b21e3d 420 else
MartinJohnson 0:d89511b21e3d 421 dir=-1;
MartinJohnson 0:d89511b21e3d 422
MartinJohnson 0:d89511b21e3d 423 j=(j+dir+WS2812_LED_STRIP_LENGTH)%WS2812_LED_STRIP_LENGTH;
MartinJohnson 0:d89511b21e3d 424
MartinJohnson 0:d89511b21e3d 425 rgb=(rgb<<1) /*^ (rand()&1 & rand()&1) ; */| (rgb>>24);
MartinJohnson 0:d89511b21e3d 426
MartinJohnson 0:d89511b21e3d 427 }
MartinJohnson 0:d89511b21e3d 428 }
MartinJohnson 0:d89511b21e3d 429
MartinJohnson 0:d89511b21e3d 430