From: Martin Mares Date: Sun, 24 Mar 2024 12:13:23 +0000 (+0100) Subject: test-neopixel-square: init X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=23b70744999e99b0b58bd8bad7402988561c0a48;p=home-hw.git test-neopixel-square: init --- diff --git a/test-neopixel-square/Makefile b/test-neopixel-square/Makefile new file mode 100644 index 0000000..fdc81f8 --- /dev/null +++ b/test-neopixel-square/Makefile @@ -0,0 +1,6 @@ +ROOT=.. +BINARY=test +OBJS=main.o +LIB_OBJS=util-debug.o + +include $(ROOT)/mk/bluepill.mk diff --git a/test-neopixel-square/README b/test-neopixel-square/README new file mode 100644 index 0000000..2d42d67 --- /dev/null +++ b/test-neopixel-square/README @@ -0,0 +1,30 @@ +Assignment of peripherals and pins +================================== + +USART1 debugging +TIM4 Neopixel control + + + Blue Pill pinout + +--------------------+ + | VBATT 3.3V | +BluePill LED | PC13 GND | Neopixel ground + | PC14 5V | Neopixel power + | PC15 PB9 | + | PA0 PB8 | TIM4_CH3 - Neopixel data (pull up to +5V) + | PA1 PB7 | + | PA2 PB6 | + | PA3 PB5 | + | PA4 PB4 | + | PA5 PB3 | + | PA6 PA15 | + | PA7 PA12 | + | PB0 PA11 | + | PB1 PA10 | RXD1 - debugging console + | PB10 PA9 | TXD1 - debugging console + | PB11 PA8 | + | RESET PB15 | + | 3.3 V PB14 | + | GND PB13 | + | GND PB12 | + +--------------------+ diff --git a/test-neopixel-square/config.h b/test-neopixel-square/config.h new file mode 100644 index 0000000..312c7be --- /dev/null +++ b/test-neopixel-square/config.h @@ -0,0 +1,14 @@ +/* + * Test Gadget -- Configuration + * + * (c) 2020 Martin Mareš + */ + +// Processor clock + +#define CPU_CLOCK_MHZ 72 + +// Debugging port + +#define DEBUG_USART USART1 +#define DEBUG_LED_BLUEPILL diff --git a/test-neopixel-square/main.c b/test-neopixel-square/main.c new file mode 100644 index 0000000..fdfe0ab --- /dev/null +++ b/test-neopixel-square/main.c @@ -0,0 +1,447 @@ +/* + * Neopixel (WS2812B) Test + * + * (c) 2022 Martin Mareš + */ + +#include "util.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/*** Hardware init ***/ + +static void clock_init(void) +{ + rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); + + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_USART1); + rcc_periph_clock_enable(RCC_TIM4); + rcc_periph_clock_enable(RCC_DMA1); + + rcc_periph_reset_pulse(RST_GPIOA); + rcc_periph_reset_pulse(RST_GPIOB); + rcc_periph_reset_pulse(RST_GPIOC); + rcc_periph_reset_pulse(RST_USART1); + rcc_periph_reset_pulse(RST_TIM4); +} + +static void gpio_init(void) +{ + // PA9 = TXD1 for debugging console + // PA10 = RXD1 for debugging console + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO9); + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO10); + + // PC13 = BluePill LED + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_clear(GPIOC, GPIO13); + + // PB8 = data for Neopixel + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, GPIO8); +} + +static void usart_init(void) +{ + usart_set_baudrate(USART1, 115200); + usart_set_databits(USART1, 8); + usart_set_stopbits(USART1, USART_STOPBITS_1); + usart_set_mode(USART1, USART_MODE_TX); + usart_set_parity(USART1, USART_PARITY_NONE); + usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + + usart_enable(USART1); +} + +/*** System ticks ***/ + +static volatile u32 ms_ticks; + +void sys_tick_handler(void) +{ + ms_ticks++; +} + +static void tick_init(void) +{ + systick_set_frequency(1000, CPU_CLOCK_MHZ * 1000000); + systick_counter_enable(); + systick_interrupt_enable(); +} + +static void delay_ms(uint ms) +{ + u32 start_ticks = ms_ticks; + while (ms_ticks - start_ticks < ms) + ; +} + +/*** Neopixels ***/ + +#define NPIX_PERIOD 90 // timer runs on 72 MHz, so 90 periods = 1250 ns +#define B0 30 +#define B1 60 + +byte neopixel_buf[] = { + // 128 cycles low: reset (has to be longer than in the datasheet) + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + // G7 G6 G5 G4 G3 G2 G1 G0 + // R7 R6 R5 R4 R3 R2 R1 R0 + // B7 B6 B5 B4 B3 B2 B1 B0 + + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B1, B1, B1, B1, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B1, B1, B1, B1, + + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B1, B1, B1, B1, + + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B1, B1, B1, B1, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B1, B1, B1, B1, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B1, B1, B1, B1, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B1, B1, B1, B1, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B1, B1, B1, B1, + + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + B0, B0, B0, B0, B0, B0, B0, B0, + + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B1, B1, B1, B1, + B0, B0, B0, B0, B1, B1, B1, B1, +}; + +static void neopixel_init(void) +{ + // TIM4 update is connected to DMA1 channel 7 + + // FIXME: Strange programming sequence as specified in manual + + dma_channel_reset(DMA1, 7); + + dma_set_peripheral_address(DMA1, 7, (u32) &TIM_CCR3(TIM4)); + dma_set_memory_address(DMA1, 7, (u32) neopixel_buf); + dma_set_number_of_data(DMA1, 7, ARRAY_SIZE(neopixel_buf)); + dma_set_priority(DMA1, 7, DMA_CCR_PL_VERY_HIGH); + + dma_set_read_from_memory(DMA1, 7); + dma_enable_circular_mode(DMA1, 7); + + dma_set_memory_size(DMA1, 7, DMA_CCR_MSIZE_8BIT); + dma_enable_memory_increment_mode(DMA1, 7); + + dma_set_peripheral_size(DMA1, 7, DMA_CCR_PSIZE_16BIT); + dma_disable_peripheral_increment_mode(DMA1, 7); + + dma_enable_channel(DMA1, 7); + + timer_set_prescaler(TIM4, 0); + timer_set_mode(TIM4, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_disable_preload(TIM4); + timer_set_period(TIM4, NPIX_PERIOD - 1); + + timer_set_oc_mode(TIM4, TIM_OC3, TIM_OCM_PWM1); + timer_set_oc_value(TIM4, TIM_OC3, 0); + timer_set_oc_polarity_high(TIM4, TIM_OC3); + timer_enable_oc_output(TIM4, TIM_OC3); + + timer_set_dma_on_update_event(TIM4); + TIM_DIER(TIM4) |= TIM_DIER_UDE; + + timer_enable_counter(TIM4); +} + +/*** Main ***/ + +int main(void) +{ + clock_init(); + gpio_init(); + usart_init(); + tick_init(); + neopixel_init(); + + debug_printf("Hello, world!\n"); + +#if 0 + for (int i=0; i<24*64; i++) + neopixel_buf[128+i] = B1; +#endif + + for (;;) { + // wait_for_interrupt(); + debug_led(1); + for (int i=4; i<8; i++) + neopixel_buf[128+24*63+i] = B1; + delay_ms(100); + debug_led(0); + for (int i=4; i<8; i++) + neopixel_buf[128+24*63+i] = B0; + delay_ms(500); + } + + return 0; +} diff --git a/test-neopixel/README b/test-neopixel/README index bad9e94..2d42d67 100644 --- a/test-neopixel/README +++ b/test-neopixel/README @@ -11,7 +11,7 @@ TIM4 Neopixel control BluePill LED | PC13 GND | Neopixel ground | PC14 5V | Neopixel power | PC15 PB9 | - | PA0 PB8 | TIM4_CH3 - Neopixel data + | PA0 PB8 | TIM4_CH3 - Neopixel data (pull up to +5V) | PA1 PB7 | | PA2 PB6 | | PA3 PB5 |