Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
decd6ba84c | |||
22be779d75 | |||
be3efc07d3 | |||
8dc30f15fb | |||
60f1923abe | |||
d06b2b7eaf | |||
3faab7173c | |||
4166396f75 | |||
d7ce66b1d8 | |||
3fc6e81569 | |||
1cc3a85471 | |||
|
a3e1e72a9e | ||
f4cf90ca65 | |||
8589a69a3b | |||
994899038c | |||
c3074bcb6a | |||
534f917636 | |||
89adf30a2c | |||
677bf2c9b5 | |||
93d15fc549 | |||
d9769e7b34 | |||
b9a01bcad9 | |||
4f33816f2b | |||
c458d5cfce | |||
b79bbc82cb |
9
firmware/.gitignore
vendored
9
firmware/.gitignore
vendored
@ -1,3 +1,12 @@
|
|||||||
*.elf
|
*.elf
|
||||||
memmap.map
|
memmap.map
|
||||||
obj/
|
obj/
|
||||||
|
*.creator
|
||||||
|
*.user
|
||||||
|
*.user*
|
||||||
|
*.cflags
|
||||||
|
*.cxxflags
|
||||||
|
*.files
|
||||||
|
*.includes
|
||||||
|
*.config
|
||||||
|
.qtc_clangd/*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
################################Shimatta Makefile####################################
|
################################Shimatta Makefile####################################
|
||||||
#CPU: STM32F030
|
#CPU: STM32F030F4P6
|
||||||
#Compiler: arm-none-eabi
|
#Compiler: arm-none-eabi
|
||||||
#####################################################################################
|
#####################################################################################
|
||||||
|
|
||||||
@ -13,6 +13,7 @@ endif
|
|||||||
#Add Files and Folders below#########################################################
|
#Add Files and Folders below#########################################################
|
||||||
CFILES = main.c syscalls/syscalls.c setup/system_init.c startup/startup_stm32f0xx.c
|
CFILES = main.c syscalls/syscalls.c setup/system_init.c startup/startup_stm32f0xx.c
|
||||||
CFILES += temp-adc.c
|
CFILES += temp-adc.c
|
||||||
|
CFILES += dmx.c
|
||||||
ASFILES = sk6812.S
|
ASFILES = sk6812.S
|
||||||
INCLUDEPATH = -Iinclude -Iinclude/cmsis
|
INCLUDEPATH = -Iinclude -Iinclude/cmsis
|
||||||
|
|
||||||
@ -30,14 +31,15 @@ mapfile = memmap
|
|||||||
|
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
CC=arm-none-eabi-gcc
|
CROSS_COMPILE ?= arm-none-eabi-
|
||||||
OBJCOPY=arm-none-eabi-objcopy
|
CC := $(CROSS_COMPILE)gcc
|
||||||
OBJDUMP=arm-none-eabi-objdump
|
OBJCOPY := $(CROSS_COMPILE)objcopy
|
||||||
SIZE=arm-none-eabi-size
|
OBJDUMP := $(CROSS_COMPILE)objdump
|
||||||
|
SIZE := $(CROSS_COMPILE)size
|
||||||
|
|
||||||
LFLAGS = -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork
|
LFLAGS = -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork
|
||||||
LFLAGS += -mfloat-abi=soft --disable-newlib-supplied-syscalls -nostartfiles
|
LFLAGS += -mfloat-abi=soft --disable-newlib-supplied-syscalls -nostartfiles
|
||||||
LFLAGS += -Tstartup/stm32f030.ld -Wl,-Map=$(mapfile).map -Wl,--gc-sections -g
|
LFLAGS += -Tstartup/stm32f030.ld -Wl,-Map=$(mapfile).map -Wl,--gc-sections -Wl,--print-memory-usage -g
|
||||||
|
|
||||||
CFLAGS = -c -fmessage-length=0 -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork
|
CFLAGS = -c -fmessage-length=0 -mlittle-endian -mthumb -mcpu=cortex-m0 -mthumb-interwork
|
||||||
CFLAGS += -mfloat-abi=soft -nostartfiles -Wall -g3 -O0
|
CFLAGS += -mfloat-abi=soft -nostartfiles -Wall -g3 -O0
|
||||||
@ -49,8 +51,6 @@ ASOBJ = $(ASFILES:%.S=$(OBJDIR)/%.S.o)
|
|||||||
|
|
||||||
default: $(target).elf
|
default: $(target).elf
|
||||||
|
|
||||||
binary: $(target).bin $(target).hex
|
|
||||||
|
|
||||||
%.bin: %.elf
|
%.bin: %.elf
|
||||||
$(OBJCOPY) -O binary $^ $@
|
$(OBJCOPY) -O binary $^ $@
|
||||||
%.hex: %.elf
|
%.hex: %.elf
|
||||||
@ -64,18 +64,16 @@ $(target).elf: $(OBJ) $(ASOBJ)
|
|||||||
|
|
||||||
#Compiling
|
#Compiling
|
||||||
$(OBJ):
|
$(OBJ):
|
||||||
@echo Compiling $@
|
@echo [CC] $@
|
||||||
$(eval OUTPATH=$(dir $@))
|
@mkdir -p $(@D)
|
||||||
@mkdir -p $(OUTPATH)
|
|
||||||
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.c.o=%.c)
|
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.c.o=%.c)
|
||||||
|
|
||||||
$(ASOBJ):
|
$(ASOBJ):
|
||||||
@echo Compiling $@
|
@echo [AS] $@
|
||||||
$(eval OUTPATH=$(dir $@))
|
@mkdir -p $(@D)
|
||||||
@mkdir -p $(OUTPATH)
|
|
||||||
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.S.o=%.S)
|
$(QUIET)$(CC) $(CFLAGS) -MMD -MT $@ $(INCLUDEPATH) $(DEFINES) -o $@ $(@:$(OBJDIR)/%.S.o=%.S)
|
||||||
|
|
||||||
.PHONY: qtproject clean mrproper objcopy disassemble
|
.PHONY: clean mrproper objcopy disassemble binary
|
||||||
|
|
||||||
disassemble: $(target).elf
|
disassemble: $(target).elf
|
||||||
$(OBJDUMP) -D -s $< > $(target).lss
|
$(OBJDUMP) -D -s $< > $(target).lss
|
||||||
@ -85,19 +83,12 @@ objcopy: $(target).bin $(target).hex
|
|||||||
mrproper:
|
mrproper:
|
||||||
rm -f $(target).pro
|
rm -f $(target).pro
|
||||||
|
|
||||||
clean:
|
binary: $(target).bin $(target).hex
|
||||||
rm -f $(target).elf $(target).bin $(target).hex $(OBJ) $(ASOBJ) $(mapfile).map $(target).lss
|
|
||||||
rm -rfv $(OBJDIR)
|
|
||||||
|
|
||||||
qtproject:
|
clean:
|
||||||
echo -e "TEMPLATE = app\nCONFIG -= console app_bundle qt" > $(target).pro
|
@echo [CLEAN] $(OBJDIR)
|
||||||
echo -e "SOURCES += $(CFILES) $(ASFILES)" >> $(target).pro
|
@rm -f $(target).elf $(target).bin $(target).hex $(OBJ) $(ASOBJ) $(mapfile).map $(target).lss
|
||||||
echo -ne "INCLUDEPATH += " >> $(target).pro
|
@rm -rf $(OBJDIR)/*
|
||||||
echo "$(INCLUDEPATH)" | sed "s!-I!./!g" >> $(target).pro
|
|
||||||
echo -ne "HEADERS += " >> $(target).pro
|
|
||||||
find -name "*.h" | tr "\\n" " " >> $(target).pro
|
|
||||||
echo -ne "\nDEFINES += " >> $(target).pro
|
|
||||||
echo "$(DEFINES)" | sed "s/-D//g" >> $(target).pro
|
|
||||||
|
|
||||||
-include $(CFILES:%.c=$(OBJDIR)/%.c.d) $(ASFILES:%.S=$(OBJDIR)/%.S.d)
|
-include $(CFILES:%.c=$(OBJDIR)/%.c.d) $(ASFILES:%.S=$(OBJDIR)/%.S.d)
|
||||||
|
|
||||||
|
136
firmware/dmx.c
Normal file
136
firmware/dmx.c
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
#include <ring-light/dmx.h>
|
||||||
|
#include <stm32f0xx.h>
|
||||||
|
|
||||||
|
static uint32_t dmx_base_channel;
|
||||||
|
|
||||||
|
|
||||||
|
enum dmx_rx_state_enum {
|
||||||
|
DMX_RX_WAIT_FOR_BREAK = 0,
|
||||||
|
DMX_RX_DATA,
|
||||||
|
};
|
||||||
|
|
||||||
|
static volatile enum dmx_rx_state_enum dmx_state;
|
||||||
|
|
||||||
|
|
||||||
|
static volatile bool break_received;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief DMX data received. Contains the whole DMX universe including the first 0 byte.
|
||||||
|
* The controller does check the first byte to be zero.
|
||||||
|
*/
|
||||||
|
static volatile uint8_t dmx_channel_data[DMX_UNIVERSE_SIZE + 1];
|
||||||
|
|
||||||
|
void dmx_init(uint32_t base_channel)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
volatile uint8_t *ptr;
|
||||||
|
|
||||||
|
for (i = 0, ptr = dmx_channel_data; i < DMX_USED_CHANNEL_COUNT; i++, ptr++) {
|
||||||
|
*ptr = 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
dmx_base_channel = base_channel;
|
||||||
|
break_received = false;
|
||||||
|
|
||||||
|
/* Enable GPIOA and USART1 clock */
|
||||||
|
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_DMAEN;
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||||
|
|
||||||
|
/* Switch RXTX pin low, activating permanent READ mode */
|
||||||
|
GPIOA->MODER |= (0x1<<(2*5));
|
||||||
|
GPIOA->BRR |= (1<<5);
|
||||||
|
|
||||||
|
/* Switch PA10 to RX alternate function of USART1 (AF1) */
|
||||||
|
GPIOA->MODER |= (0x2<<(2*10));
|
||||||
|
GPIOA->AFR[1] |=(0x1<<(4*2));
|
||||||
|
|
||||||
|
/* Set baudrate: 48MHz / 250k = 129 */
|
||||||
|
USART1->BRR = 192u;
|
||||||
|
USART1->CR3 = USART_CR3_EIE;
|
||||||
|
USART1->CR2 = USART_CR2_STOP_1;
|
||||||
|
USART1->CR1 = USART_CR1_RXNEIE | USART_CR1_RE | USART_CR1_UE;
|
||||||
|
|
||||||
|
/* Map USART1 RX to DMA Channel 3 */
|
||||||
|
SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_USART1RX_DMA_RMP;
|
||||||
|
|
||||||
|
DMA1_Channel3->CCR = DMA_CCR_PL_1 | DMA_CCR_MINC | DMA_CCR_TCIE;
|
||||||
|
|
||||||
|
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
||||||
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t *dmx_get_data()
|
||||||
|
{
|
||||||
|
return (const uint8_t *)dmx_channel_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART1_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint32_t isr;
|
||||||
|
|
||||||
|
isr = USART1->ISR;
|
||||||
|
USART1->ICR = USART_ICR_ORECF | USART_ICR_NCF | USART_ICR_FECF;
|
||||||
|
|
||||||
|
if (isr & USART_ISR_FE) {
|
||||||
|
/* Frame error received. Start of DMX frame */
|
||||||
|
/* Flush RX data */
|
||||||
|
USART1->CR3 &= ~USART_CR3_DMAR;
|
||||||
|
USART1->RQR = USART_RQR_RXFRQ;
|
||||||
|
DMA1_Channel3->CCR &= ~DMA_CCR_EN;
|
||||||
|
while (DMA1_Channel3->CCR & DMA_CCR_EN);
|
||||||
|
DMA1_Channel3->CMAR = (uint32_t)dmx_channel_data;
|
||||||
|
DMA1_Channel3->CPAR = (uint32_t)&USART1->RDR;
|
||||||
|
DMA1_Channel3->CNDTR = DMX_UNIVERSE_SIZE + 1;
|
||||||
|
DMA1_Channel3->CCR |= DMA_CCR_EN;
|
||||||
|
USART1->RQR = USART_RQR_RXFRQ;
|
||||||
|
USART1->CR3 |= USART_CR3_DMAR;
|
||||||
|
break_received = true;
|
||||||
|
dmx_state = DMX_RX_DATA;
|
||||||
|
} else if (isr & USART_ISR_RXNE) {
|
||||||
|
if (dmx_state != DMX_RX_DATA) {
|
||||||
|
USART1->RQR = USART_RQR_RXFRQ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__DSB();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DMA_CH2_3_DMA2_CH1_2_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint32_t isr;
|
||||||
|
|
||||||
|
isr = DMA1->ISR;
|
||||||
|
/* Only clear the interupts of channel 2 (bits 11:9) */
|
||||||
|
DMA1->IFCR = isr & 0xF00;
|
||||||
|
|
||||||
|
if (isr & DMA_ISR_TCIF3) {
|
||||||
|
DMA1->ISR;
|
||||||
|
dmx_state = DMX_RX_WAIT_FOR_BREAK;
|
||||||
|
}
|
||||||
|
__DSB();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dmx_poll_break_received(void)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
/* Atomically reset the flag */
|
||||||
|
__disable_irq();
|
||||||
|
ret = break_received;
|
||||||
|
break_received = false;
|
||||||
|
__enable_irq();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dmx_enough_data_received()
|
||||||
|
{
|
||||||
|
uint32_t received_count = (DMX_UNIVERSE_SIZE + 1) - DMA1_Channel3->CNDTR;
|
||||||
|
|
||||||
|
if (received_count > (dmx_base_channel + DMX_USED_CHANNEL_COUNT)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
49
firmware/include/ring-light/dmx.h
Normal file
49
firmware/include/ring-light/dmx.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef _DMX_H_
|
||||||
|
#define _DMX_H_
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define DMX_UNIVERSE_SIZE (512u)
|
||||||
|
#define DMX_USED_CHANNEL_COUNT (129u)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Init DMX reception
|
||||||
|
*
|
||||||
|
* DMX data is received from the base channel onwards:
|
||||||
|
* - R LED1
|
||||||
|
* - G LED1
|
||||||
|
* - B LED1
|
||||||
|
* - W LED1
|
||||||
|
* - R LED2
|
||||||
|
* ...
|
||||||
|
* - W LED32
|
||||||
|
* - W DISCRETE
|
||||||
|
*
|
||||||
|
* In Sum: 129 8 bit channels
|
||||||
|
*
|
||||||
|
* @param base_channel Base channel the ring light will listen on
|
||||||
|
*/
|
||||||
|
void dmx_init(uint32_t base_channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the array of the 129 DMX channels
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
const uint8_t *dmx_get_data(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a break was received. This resets the flag
|
||||||
|
* @return true if a break was received since the last time calling this function
|
||||||
|
*/
|
||||||
|
bool dmx_poll_break_received(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The DMX receiver has received all data for the ring light. It can be read
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool dmx_enough_data_received(void);
|
||||||
|
|
||||||
|
#endif /* _DMX_H_ */
|
201
firmware/main.c
201
firmware/main.c
@ -2,19 +2,23 @@
|
|||||||
#include <cmsis/core_cm0.h>
|
#include <cmsis/core_cm0.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <ring-light/temp-adc.h>
|
#include <ring-light/temp-adc.h>
|
||||||
|
#include <ring-light/dmx.h>
|
||||||
|
|
||||||
#define RING_MAX_LED 30u
|
#define RING_MAX_LED 32u
|
||||||
|
#define MAX_TEMP_CELSIUS 70
|
||||||
|
|
||||||
enum ring_modes {
|
enum ring_modes {
|
||||||
RING_MODE_ALL,
|
RING_MODE_WHITE_DISCRETE, /*!< only discrete white LEDs */
|
||||||
RING_MODE_RED,
|
RING_MODE_RED, /*!< only red SK6812 */
|
||||||
RING_MODE_GREEN,
|
RING_MODE_GREEN, /*!< only green SK6812 */
|
||||||
RING_MODE_BLUE,
|
RING_MODE_BLUE, /*!< only blue SK6812 */
|
||||||
RING_MODE_WHITE,
|
RING_MODE_ALL, /*!< control all LEDs at once */
|
||||||
RING_MODE_ARC,
|
RING_MODE_ARC, /*!< SK6812 closing ring */
|
||||||
RING_MODE_QUARTER,
|
RING_MODE_QUARTER, /*!< SK6812 walking quarter */
|
||||||
RING_MODE_IN_FARBE_UND_BUNT,
|
RING_MODE_IN_FARBE_UND_BUNT, /*!< SK6812 color mix */
|
||||||
RING_MODE_MAX
|
RING_MODE_MAX, /*!< end of list */
|
||||||
|
RING_MODE_WAIT_DMX,
|
||||||
|
RING_MODE_WAIT_DMX_BREAK
|
||||||
};
|
};
|
||||||
|
|
||||||
volatile int32_t temperature;
|
volatile int32_t temperature;
|
||||||
@ -22,6 +26,7 @@ volatile int32_t temperature;
|
|||||||
extern void sk6812_send_led(uint32_t rgbw);
|
extern void sk6812_send_led(uint32_t rgbw);
|
||||||
|
|
||||||
volatile uint32_t wait_tick = 0;
|
volatile uint32_t wait_tick = 0;
|
||||||
|
volatile bool blink_tick = false;
|
||||||
|
|
||||||
static void wait_for_ticks(uint32_t ticks)
|
static void wait_for_ticks(uint32_t ticks)
|
||||||
{
|
{
|
||||||
@ -32,13 +37,22 @@ static void wait_for_ticks(uint32_t ticks)
|
|||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
uint32_t led_val = 0x00UL;
|
uint32_t led_val = 0x00UL;
|
||||||
|
uint32_t last_led_val = 0x00UL;
|
||||||
uint32_t led_calc_val[RING_MAX_LED] = {0x00UL};
|
uint32_t led_calc_val[RING_MAX_LED] = {0x00UL};
|
||||||
|
uint8_t led_pwm_val = 0u;
|
||||||
|
const uint8_t *dmx_data;
|
||||||
|
|
||||||
bool button_pressed = false;
|
bool button_pressed = false;
|
||||||
enum ring_modes mode = RING_MODE_ALL;
|
bool force_led_update;
|
||||||
|
bool overtemp_flag = false;
|
||||||
|
enum ring_modes mode;
|
||||||
|
|
||||||
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
|
/* Led value / mode before going to DMX */
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
|
uint32_t led_val_before_dmx = 0u;
|
||||||
|
enum ring_modes mode_before_dmx = RING_MODE_RED; /* Init to save value */
|
||||||
|
|
||||||
|
RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN;
|
||||||
|
|
||||||
GPIOA->MODER |= (2<<7*2)|(2<<6*2)|(1<<3*2);
|
GPIOA->MODER |= (2<<7*2)|(2<<6*2)|(1<<3*2);
|
||||||
|
|
||||||
@ -47,6 +61,11 @@ int main(void)
|
|||||||
/* enable TIM3 on encoder inputs */
|
/* enable TIM3 on encoder inputs */
|
||||||
GPIOA->AFR[0] |= (1<<7*4)|(1<<6*4);
|
GPIOA->AFR[0] |= (1<<7*4)|(1<<6*4);
|
||||||
|
|
||||||
|
/* enable PWM output for magic LED regulator */
|
||||||
|
GPIOB->MODER |= (2<<1*2);
|
||||||
|
GPIOB->AFR[0] &= ~(0<<1*4);
|
||||||
|
|
||||||
|
/*! -# init the TIM3 to read the encoder */
|
||||||
TIM3->ARR = 0xFFFF;
|
TIM3->ARR = 0xFFFF;
|
||||||
TIM3->CNT = 0;
|
TIM3->CNT = 0;
|
||||||
TIM3->CR2 = 0;
|
TIM3->CR2 = 0;
|
||||||
@ -56,17 +75,69 @@ int main(void)
|
|||||||
TIM3->PSC = 0;
|
TIM3->PSC = 0;
|
||||||
TIM3->CR1 = TIM_CR1_CEN;
|
TIM3->CR1 = TIM_CR1_CEN;
|
||||||
|
|
||||||
|
/*! -# Init TIM14 for PWM control of the magic LED driver */
|
||||||
|
/*! -# Count up to 255 (8 bit resolution) */
|
||||||
|
TIM14->ARR = 0x00FFu;
|
||||||
|
TIM14->CNT = 0u;
|
||||||
|
TIM14->CCR1 = 0u;
|
||||||
|
/*! -# Set prescaler to 11 ==> ca. 17 KHz */
|
||||||
|
TIM14->PSC = 11u - 1u;
|
||||||
|
/*! -# PWM Mode 1 + prefetch */
|
||||||
|
TIM14->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE;
|
||||||
|
/*! -# Enable Output compare 1 */
|
||||||
|
TIM14->CCER = TIM_CCER_CC1E;
|
||||||
|
/*! -# Finally, enable TIM14 */
|
||||||
|
TIM14->CR2 = 0;
|
||||||
|
TIM14->CR1 = TIM_CR1_CEN;
|
||||||
|
|
||||||
|
/*! -# Set initial state to all 25% */
|
||||||
|
led_val = 64u;
|
||||||
|
mode = RING_MODE_WHITE_DISCRETE;
|
||||||
|
|
||||||
temperature_adc_init();
|
temperature_adc_init();
|
||||||
|
dmx_init(0u);
|
||||||
|
|
||||||
SysTick_Config(800000);
|
SysTick_Config(800000);
|
||||||
while(1) {
|
while(1) {
|
||||||
|
force_led_update = false;
|
||||||
temperature = temperature_adc_get_temp();
|
temperature = temperature_adc_get_temp();
|
||||||
|
|
||||||
|
if (led_val != last_led_val || button_pressed) {
|
||||||
|
force_led_update = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! -# Gradually dim down the LED brightness in case the temperature is too high */
|
||||||
|
if (overtemp_flag) {
|
||||||
|
if (temperature < (MAX_TEMP_CELSIUS-15) * 10) {
|
||||||
|
overtemp_flag = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
overtemp_flag = temperature > ((MAX_TEMP_CELSIUS) * 10) ? true : false;
|
||||||
|
}
|
||||||
|
if (overtemp_flag) {
|
||||||
|
if (led_val > 2 && mode < RING_MODE_MAX)
|
||||||
|
led_val--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dmx_poll_break_received()) {
|
||||||
|
/* DMX received. Go to DMX mode.
|
||||||
|
* Save old state
|
||||||
|
*/
|
||||||
|
if (mode < RING_MODE_MAX) {
|
||||||
|
led_val_before_dmx = led_val;
|
||||||
|
mode_before_dmx = mode;
|
||||||
|
}
|
||||||
|
mode = RING_MODE_WAIT_DMX;
|
||||||
|
}
|
||||||
|
|
||||||
|
led_pwm_val = 0u;
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case RING_MODE_ALL:
|
case RING_MODE_ALL:
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
led_calc_val[i] = (led_val << 24) + (led_val << 16) + (led_val << 8) + led_val;
|
led_calc_val[i] = (led_val << 24) + (led_val << 16) + (led_val << 8) + led_val;
|
||||||
}
|
}
|
||||||
|
led_pwm_val = led_val;
|
||||||
break;
|
break;
|
||||||
case RING_MODE_RED:
|
case RING_MODE_RED:
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
@ -75,23 +146,24 @@ int main(void)
|
|||||||
break;
|
break;
|
||||||
case RING_MODE_GREEN:
|
case RING_MODE_GREEN:
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
led_calc_val[i] = led_val << 24;
|
led_calc_val[i] = led_val << 24;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RING_MODE_BLUE:
|
case RING_MODE_BLUE:
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
led_calc_val[i] = led_val << 8;
|
led_calc_val[i] = led_val << 8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RING_MODE_WHITE:
|
case RING_MODE_WHITE_DISCRETE:
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
led_calc_val[i] = led_val;
|
led_calc_val[i] = 0u;
|
||||||
}
|
}
|
||||||
|
led_pwm_val = led_val;
|
||||||
break;
|
break;
|
||||||
case RING_MODE_ARC:
|
case RING_MODE_ARC:
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
if(led_val > i*8) {
|
if(led_val > i*8) {
|
||||||
led_calc_val[i] = 0xFFFFFFFFUL;
|
led_calc_val[i] = 0xFFFFFFFFUL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
led_calc_val[i] = 0x00000000UL;
|
led_calc_val[i] = 0x00000000UL;
|
||||||
@ -101,7 +173,7 @@ int main(void)
|
|||||||
case RING_MODE_QUARTER:
|
case RING_MODE_QUARTER:
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
if((led_val / 7 > i) && (led_val / 7 < (i + 7))) {
|
if((led_val / 7 > i) && (led_val / 7 < (i + 7))) {
|
||||||
led_calc_val[i] = 0xFFFFFFFFUL;
|
led_calc_val[i] = 0xFFFFFFFFUL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
led_calc_val[i] = 0x00000000UL;
|
led_calc_val[i] = 0x00000000UL;
|
||||||
@ -121,48 +193,107 @@ int main(void)
|
|||||||
case 2:
|
case 2:
|
||||||
led_calc_val[i] = 0x0000FF00UL;
|
led_calc_val[i] = 0x0000FF00UL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case RING_MODE_WAIT_DMX:
|
||||||
|
force_led_update = false;
|
||||||
|
if (dmx_enough_data_received() && !overtemp_flag) {
|
||||||
|
dmx_data = dmx_get_data();
|
||||||
|
mode = RING_MODE_WAIT_DMX_BREAK;
|
||||||
|
if (dmx_data[0] != 0)
|
||||||
|
break;
|
||||||
|
for (int i = 0; i < RING_MAX_LED; i++) {
|
||||||
|
led_calc_val[i] = (dmx_data[1 + i*4 + 3]) |
|
||||||
|
(dmx_data[1 + i*4 + 2] << 8) |
|
||||||
|
(dmx_data[1 + i*4 + 0] << 16) |
|
||||||
|
(dmx_data[1 + i*4 + 1] << 24);
|
||||||
|
}
|
||||||
|
led_pwm_val = dmx_data[129];
|
||||||
|
force_led_update = true;
|
||||||
|
} else if (overtemp_flag) {
|
||||||
|
force_led_update = true;
|
||||||
|
for (int i = 0; i < RING_MAX_LED; i++) {
|
||||||
|
led_calc_val[i] = 0ul;
|
||||||
|
}
|
||||||
|
led_pwm_val = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RING_MODE_WAIT_DMX_BREAK:
|
||||||
|
force_led_update = false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
led_calc_val[i] = 0x00000000UL;
|
led_calc_val[i] = 0x00000000UL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
__disable_irq();
|
|
||||||
for(int i = 0; i < RING_MAX_LED; i ++) {
|
if (overtemp_flag) {
|
||||||
sk6812_send_led(led_calc_val[i]);
|
force_led_update = true;
|
||||||
|
led_calc_val[0] = blink_tick ? 0x00FF0000UL : 0UL;
|
||||||
}
|
}
|
||||||
__enable_irq();
|
|
||||||
wait_for_ticks(5);
|
if (force_led_update) {
|
||||||
|
TIM14->CCR1 = led_pwm_val;
|
||||||
|
|
||||||
|
for(int i = 0; i < RING_MAX_LED; i ++) {
|
||||||
|
/* Allow interrupts in between LEDs.
|
||||||
|
* They must not exceed the reset length of 80us of SK6812.
|
||||||
|
*/
|
||||||
|
__disable_irq();
|
||||||
|
sk6812_send_led(led_calc_val[i]);
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
last_led_val = led_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only wait in case of non-DMX mode */
|
||||||
|
if (!(mode == RING_MODE_WAIT_DMX_BREAK || mode == RING_MODE_WAIT_DMX) || overtemp_flag)
|
||||||
|
wait_for_ticks(5);
|
||||||
|
|
||||||
if((int16_t)TIM3->CNT > (int16_t)led_val) {
|
if((int16_t)TIM3->CNT > (int16_t)led_val) {
|
||||||
led_val = 0u;
|
led_val = 0u;
|
||||||
}
|
} else if(((int16_t)led_val - (int16_t)TIM3->CNT) > UINT8_MAX) {
|
||||||
else if(((int16_t)led_val - (int16_t)TIM3->CNT) > UINT8_MAX) {
|
|
||||||
led_val = 255u;
|
led_val = 255u;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
led_val = (int16_t)led_val - (int16_t)TIM3->CNT;
|
led_val = (int16_t)led_val - (int16_t)TIM3->CNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
TIM3->CNT = 0u;
|
TIM3->CNT = 0u;
|
||||||
|
|
||||||
|
|
||||||
if(button_pressed) {
|
if(button_pressed) {
|
||||||
if(GPIOA->IDR & GPIO_IDR_0) {
|
if(GPIOA->IDR & GPIO_IDR_0) {
|
||||||
button_pressed = false;
|
button_pressed = false;
|
||||||
}
|
}
|
||||||
}
|
} else if(!(GPIOA->IDR & GPIO_IDR_0)) {
|
||||||
else if(!(GPIOA->IDR & GPIO_IDR_0)) {
|
|
||||||
mode = (mode + 1) % RING_MODE_MAX;
|
|
||||||
button_pressed = true;
|
button_pressed = true;
|
||||||
|
/* Button pressed */
|
||||||
|
if (mode > RING_MODE_MAX) {
|
||||||
|
/* In DMX mode. Abort DMX mode */
|
||||||
|
mode = mode_before_dmx;
|
||||||
|
led_val = led_val_before_dmx;
|
||||||
|
} else {
|
||||||
|
/* Normal mode switching */
|
||||||
|
mode = (mode + 1) % RING_MODE_MAX;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysTick_Handler(void) {
|
void SysTick_Handler(void)
|
||||||
|
{
|
||||||
|
static uint32_t tick = 10;
|
||||||
|
|
||||||
|
if (!--tick) {
|
||||||
|
tick = 10;
|
||||||
|
blink_tick = !blink_tick;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
wait_tick++;
|
wait_tick++;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ void __setup_clocks(void)
|
|||||||
RCC->CFGR = tmp;
|
RCC->CFGR = tmp;
|
||||||
|
|
||||||
/* Turn off HSI */
|
/* Turn off HSI */
|
||||||
RCC->CR &= ~RCC_CR_HSEON;
|
RCC->CR &= ~RCC_CR_HSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __system_init(void)
|
void __system_init(void)
|
||||||
|
@ -38,16 +38,14 @@ MEMORY
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
.vectors :
|
.vectors : ALIGN(4)
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
|
||||||
KEEP(*(.vectors))
|
KEEP(*(.vectors))
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
.text :
|
.text : ALIGN(4)
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
|
||||||
*(.text) /* .text sections (code) */
|
*(.text) /* .text sections (code) */
|
||||||
*(.text*) /* .text* sections (code) */
|
*(.text*) /* .text* sections (code) */
|
||||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||||
@ -57,49 +55,54 @@ SECTIONS
|
|||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
KEEP(*(.init)) /* Constructors */
|
KEEP(*(.init)) /* Constructors */
|
||||||
KEEP(*(.fini)) /* Destructors */
|
KEEP(*(.fini)) /* Destructors */
|
||||||
} >FLASH
|
. = ALIGN(4);
|
||||||
|
} >FLASH =0xFF
|
||||||
|
|
||||||
.ARM.extab :
|
.ARM.extab : ALIGN(4)
|
||||||
{
|
{
|
||||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||||
} >FLASH
|
. = ALIGN(4);
|
||||||
|
} >FLASH =0xFF
|
||||||
|
|
||||||
.ARM :
|
.ARM : ALIGN(4)
|
||||||
{
|
{
|
||||||
__exidx_start = .;
|
__exidx_start = .;
|
||||||
*(.ARM.exidx*)
|
*(.ARM.exidx*)
|
||||||
__exidx_end = .;
|
__exidx_end = .;
|
||||||
} >FLASH
|
. = ALIGN(4);
|
||||||
|
} >FLASH =0xFF
|
||||||
|
|
||||||
/* Constructor/Destructor tables */
|
/* Constructor/Destructor tables */
|
||||||
.preinit_array :
|
.preinit_array : ALIGN(4)
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
KEEP (*(.preinit_array*))
|
KEEP (*(.preinit_array*))
|
||||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
} >FLASH
|
. = ALIGN(4);
|
||||||
|
} >FLASH =0xFF
|
||||||
|
|
||||||
.init_array :
|
.init_array : ALIGN(4)
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN (__init_array_start = .);
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
KEEP (*(SORT(.init_array.*)))
|
KEEP (*(SORT(.init_array.*)))
|
||||||
KEEP (*(.init_array*))
|
KEEP (*(.init_array*))
|
||||||
PROVIDE_HIDDEN (__init_array_end = .);
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
} >FLASH
|
. = ALIGN(4);
|
||||||
|
} >FLASH =0xFF
|
||||||
|
|
||||||
.fini_array :
|
.fini_array : ALIGN(4)
|
||||||
{
|
{
|
||||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
KEEP (*(.fini_array*))
|
KEEP (*(.fini_array*))
|
||||||
KEEP (*(SORT(.fini_array.*)))
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
} >FLASH
|
. = ALIGN(4);
|
||||||
|
} >FLASH =0xFF
|
||||||
|
|
||||||
/* Initialized Data */
|
/* Initialized Data */
|
||||||
__ld_load_data = LOADADDR(.data);
|
__ld_load_data = LOADADDR(.data);
|
||||||
.data :
|
.data : ALIGN(4)
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
|
||||||
__ld_sdata = .;
|
__ld_sdata = .;
|
||||||
*(.data)
|
*(.data)
|
||||||
*(.data*)
|
*(.data*)
|
||||||
@ -108,9 +111,8 @@ SECTIONS
|
|||||||
} >RAM AT> FLASH
|
} >RAM AT> FLASH
|
||||||
|
|
||||||
/* Uninitialized static data */
|
/* Uninitialized static data */
|
||||||
.bss :
|
.bss : ALIGN(4)
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
|
||||||
__ld_sbss = .;
|
__ld_sbss = .;
|
||||||
*(.bss)
|
*(.bss)
|
||||||
*(.bss*)
|
*(.bss*)
|
||||||
@ -119,9 +121,8 @@ SECTIONS
|
|||||||
__ld_ebss = .;
|
__ld_ebss = .;
|
||||||
} >RAM
|
} >RAM
|
||||||
|
|
||||||
.heap_stack (NOLOAD) :
|
.heap_stack (NOLOAD) : ALIGN(4)
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
|
||||||
__ld_sheap = .;
|
__ld_sheap = .;
|
||||||
. = . + __ld_heap_size;
|
. = . + __ld_heap_size;
|
||||||
__ld_eheap = .;
|
__ld_eheap = .;
|
||||||
|
@ -54,6 +54,8 @@ int32_t temperature_adc_get_temp(void)
|
|||||||
temp = ((temp_lf_s23_8 / 16) * vdd_lf_s23_8 / FLOAT_TO_S23_8(3.3)) * 16;
|
temp = ((temp_lf_s23_8 / 16) * vdd_lf_s23_8 / FLOAT_TO_S23_8(3.3)) * 16;
|
||||||
temp = (get_temp_sensor_cal() << 10) - temp;
|
temp = (get_temp_sensor_cal() << 10) - temp;
|
||||||
temp = (temp * 10 / slope) + 300;
|
temp = (temp * 10 / slope) + 300;
|
||||||
|
|
||||||
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t get_vrefint_cal(void)
|
static uint32_t get_vrefint_cal(void)
|
||||||
@ -94,9 +96,9 @@ void DMA_CH1_IRQHandler(void)
|
|||||||
uint32_t isr;
|
uint32_t isr;
|
||||||
|
|
||||||
isr = DMA1->ISR;
|
isr = DMA1->ISR;
|
||||||
DMA1->IFCR = isr;
|
DMA1->IFCR = isr & 0xF;
|
||||||
|
|
||||||
if (isr & DMA_ISR_TCIF1) {
|
if (isr & DMA_ISR_TCIF1) {
|
||||||
process_adc_samples();
|
process_adc_samples();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
housing/.gitignore
vendored
1
housing/.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
*.FCStd?
|
*.FCStd?
|
||||||
|
*.stl
|
||||||
|
Binary file not shown.
@ -929,9 +929,11 @@ Wire Wire Line
|
|||||||
Text Notes 3250 2100 0 50 ~ 0
|
Text Notes 3250 2100 0 50 ~ 0
|
||||||
22 uH
|
22 uH
|
||||||
Text Notes 2150 4650 0 50 ~ 0
|
Text Notes 2150 4650 0 50 ~ 0
|
||||||
Max Current = 60 mA
|
Max Current = 60 mA\nYou may use 27k for 88mA. This turned out to be fine.
|
||||||
Text Notes 850 3900 0 50 ~ 0
|
Text Notes 850 3900 0 50 ~ 0
|
||||||
f = 1.08 MHz
|
f = 1.08 MHz
|
||||||
Text Notes 1650 1850 0 50 ~ 0
|
Text Notes 1650 1850 0 50 ~ 0
|
||||||
For the calculation of the component values see 'lp8867-calc.py'
|
For the calculation of the component values see 'lp8867-calc.py'
|
||||||
|
Text Notes 6050 2800 0 50 ~ 0
|
||||||
|
(15pF)
|
||||||
$EndSCHEMATC
|
$EndSCHEMATC
|
||||||
|
2
pcb/lp8867-calc.py
Normal file → Executable file
2
pcb/lp8867-calc.py
Normal file → Executable file
@ -35,7 +35,7 @@ switching_freq = 1.1e6
|
|||||||
output_voltage_nom = 24 + 0.9
|
output_voltage_nom = 24 + 0.9
|
||||||
inductor_value = 22e-6
|
inductor_value = 22e-6
|
||||||
input_voltage = 12
|
input_voltage = 12
|
||||||
output_current_per_lane = 60e-3
|
output_current_per_lane = 110e-3
|
||||||
desired_e_series = es.E12
|
desired_e_series = es.E12
|
||||||
r1 = 560e3
|
r1 = 560e3
|
||||||
r2 = 100e3
|
r2 = 100e3
|
||||||
|
@ -1058,7 +1058,7 @@ P 1950 1200
|
|||||||
F 0 "SW1" H 1950 875 50 0000 C CNN
|
F 0 "SW1" H 1950 875 50 0000 C CNN
|
||||||
F 1 "5FS1S102M6QE " H 1950 966 50 0000 C CNN
|
F 1 "5FS1S102M6QE " H 1950 966 50 0000 C CNN
|
||||||
F 2 "shimatta_switch:NINIGI-5FS1S102M6QE" H 1950 1200 50 0001 C CNN
|
F 2 "shimatta_switch:NINIGI-5FS1S102M6QE" H 1950 1200 50 0001 C CNN
|
||||||
F 3 "~" H 1950 1200 50 0001 C CNN
|
F 3 "https://www.tme.eu/Document/d3fdab2d1ef2b3e44d3477e847fc8839/slide_switch_5F.PDF" H 1950 1200 50 0001 C CNN
|
||||||
1 1950 1200
|
1 1950 1200
|
||||||
1 0 0 1
|
1 0 0 1
|
||||||
$EndComp
|
$EndComp
|
||||||
|
Loading…
Reference in New Issue
Block a user