diff --git a/firmware/Makefile b/firmware/Makefile index 97717a2..4e927e5 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -12,7 +12,7 @@ endif #Add Files and Folders below######################################################### CFILES = main.c syscalls/syscalls.c setup/system_init.c startup/startup_stm32f0xx.c -ASFILES = +ASFILES = sk6812.S INCLUDEPATH = -Iinclude -Iinclude/cmsis OBJDIR=obj @@ -39,7 +39,7 @@ LFLAGS += -mfloat-abi=soft --disable-newlib-supplied-syscalls -nostartfiles LFLAGS += -Tstartup/stm32f030.ld -Wl,-Map=$(mapfile).map -Wl,--gc-sections -g CFLAGS = -c -fmessage-length=0 -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork -CFLAGS += -mfloat-abi=soft -nostartfiles -Wall -g +CFLAGS += -mfloat-abi=soft -nostartfiles -Wall -g -O3 #################################################################################### diff --git a/firmware/main.c b/firmware/main.c index c778c4a..9c1a859 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,19 +1,165 @@ #include +#include +#include +#define RING_MAX_LED 30u + +enum ring_modes { + RING_MODE_ALL, + RING_MODE_RED, + RING_MODE_GREEN, + RING_MODE_BLUE, + RING_MODE_WHITE, + RING_MODE_ARC, + RING_MODE_QUARTER, + RING_MODE_IN_FARBE_UND_BUNT, + RING_MODE_MAX +}; unsigned int i = 0x12345678; unsigned char c = 2; -int main(void) { - RCC->AHBENR |= RCC_AHBENR_GPIOBEN; - GPIOB->MODER |= (1<<1*2); - GPIOB->ODR |= (1<<1); +extern void sk6812_send_led(uint32_t rgbw); + +volatile uint32_t wait_tick = 0; + +static void wait_for_ticks(uint32_t ticks) +{ + wait_tick = 0; + while (wait_tick < ticks); +} + +int main(void) +{ + uint32_t led_val = 0x00UL; + uint32_t led_calc_val[RING_MAX_LED] = {0x00UL}; + bool button_pressed = false; + enum ring_modes mode = RING_MODE_ALL; + + RCC->AHBENR |= RCC_AHBENR_GPIOAEN; + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; + + GPIOA->MODER |= (2<<7*2)|(2<<6*2)|(1<<3*2); + + /* enable pullups on encoder inputs */ + GPIOA->PUPDR |= (1<<7*2)|(1<<6*2)|(1<<0*2); + /* enable TIM3 on encoder inputs */ + GPIOA->AFR[0] |= (1<<7*4)|(1<<6*4); + + TIM3->ARR = 0xFFFF; + TIM3->CNT = 0; + TIM3->CR2 = 0; + TIM3->SMCR = TIM_SMCR_SMS_0; + TIM3->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_1; + TIM3->CCER = TIM_CCER_CC1P | TIM_CCER_CC2P; + TIM3->PSC = 0; + TIM3->CR1 = TIM_CR1_CEN; + SysTick_Config(800000); while(1) { - i++; + + switch (mode) + { + case RING_MODE_ALL: + for(int i = 0; i < RING_MAX_LED; i ++) { + led_calc_val[i] = (led_val << 24) + (led_val << 16) + (led_val << 8) + led_val; + } + break; + case RING_MODE_RED: + for(int i = 0; i < RING_MAX_LED; i ++) { + led_calc_val[i] = led_val << 16; + } + break; + case RING_MODE_GREEN: + for(int i = 0; i < RING_MAX_LED; i ++) { + led_calc_val[i] = led_val << 24; + } + break; + case RING_MODE_BLUE: + for(int i = 0; i < RING_MAX_LED; i ++) { + led_calc_val[i] = led_val << 8; + } + break; + case RING_MODE_WHITE: + for(int i = 0; i < RING_MAX_LED; i ++) { + led_calc_val[i] = led_val; + } + break; + case RING_MODE_ARC: + for(int i = 0; i < RING_MAX_LED; i ++) { + if(led_val > i*8) { + led_calc_val[i] = 0xFFFFFFFFUL; + } + else { + led_calc_val[i] = 0x00000000UL; + } + } + break; + case RING_MODE_QUARTER: + for(int i = 0; i < RING_MAX_LED; i ++) { + if((led_val / 7 > i) && (led_val / 7 < (i + 7))) { + led_calc_val[i] = 0xFFFFFFFFUL; + } + else { + led_calc_val[i] = 0x00000000UL; + } + } + break; + case RING_MODE_IN_FARBE_UND_BUNT: + for(int i = 0; i < RING_MAX_LED; i ++) { + switch ((led_val + (i / 3)) % 3) + { + case 0: + led_calc_val[i] = 0x00FF0000UL; + break; + case 1: + led_calc_val[i] = 0xFF000000UL; + break; + case 2: + led_calc_val[i] = 0x0000FF00UL; + break; + + default: + break; + } + } + break; + default: + for(int i = 0; i < RING_MAX_LED; i ++) { + led_calc_val[i] = 0x00000000UL; + } + break; + } + __disable_irq(); + for(int i = 0; i < RING_MAX_LED; i ++) { + sk6812_send_led(led_calc_val[i]); + } + __enable_irq(); + wait_for_ticks(5); + + if((int16_t)TIM3->CNT > (int16_t)led_val) { + led_val = 0u; + } + else if(((int16_t)led_val - (int16_t)TIM3->CNT) > UINT8_MAX) { + led_val = 255u; + } + else { + led_val = (int16_t)led_val - (int16_t)TIM3->CNT; + } + TIM3->CNT = 0u; + + if(button_pressed) { + if(GPIOA->IDR & GPIO_IDR_0) { + button_pressed = false; + } + } + else if(!(GPIOA->IDR & GPIO_IDR_0)) { + mode = (mode + 1) % RING_MODE_MAX; + button_pressed = true; + } } } void SysTick_Handler(void) { - GPIOB->ODR ^= (1<<1); -} + wait_tick++; +} \ No newline at end of file diff --git a/firmware/setup/system_init.c b/firmware/setup/system_init.c index 380e59f..6b823c2 100644 --- a/firmware/setup/system_init.c +++ b/firmware/setup/system_init.c @@ -61,10 +61,44 @@ static void __init_default_clocks(void) RCC->CIR = 0x00000000; } +void __setup_clocks(void) +{ + uint32_t tmp; + + /* Switch PLL source to HSE OSC */ + RCC->CFGR |= RCC_CFGR_PLLSRC; + + /* Divide HSE by 2 to match HSI */ + RCC->CFGR2 = 0x00000001; + + /* Enable HSE and wait for it to become ready */ + RCC->CR |= RCC_CR_HSEON; + + /* Wait for HSE to be ready */ + while (!(RCC->CR & RCC_CR_HSERDY)); + + /* Set PLL multiplication to 12 (4 MHz * 12 = 48 MHz SysClk) */ + RCC->CFGR |= RCC_CFGR_PLLMUL_3 | RCC_CFGR_PLLMUL_1; + + /* HSI Already running. Switch on PLL */ + RCC->CR |= RCC_CR_PLLON; + + /* Wait for PLL to be ready */ + while (!(RCC->CR & RCC_CR_PLLRDY)); + + /* Switch System Clock to PLL */ + tmp = RCC->CFGR; + tmp &= ~0x3; + tmp |= RCC_CFGR_SW_1; + RCC->CFGR = tmp; + + /* Turn off HSI */ + RCC->CR &= ~RCC_CR_HSEON; +} void __system_init(void) { - __init_default_clocks(); - + __init_default_clocks(); + __setup_clocks(); } diff --git a/firmware/sk6812.S b/firmware/sk6812.S new file mode 100644 index 0000000..9dd764d --- /dev/null +++ b/firmware/sk6812.S @@ -0,0 +1,47 @@ +.global sk6812_send_led + +.equ BSRR_REGISTER, 0x48000018 +.equ PINNUM, 3 +.syntax unified + +sk6812_send_led: + push {lr} + push {r4, r5, r6} + ldr r1, =BSRR_REGISTER + ldr r2, =(1<