]> mj.ucw.cz Git - home-hw.git/commitdiff
Indicators: Started from test-neopixel
authorMartin Mares <mj@ucw.cz>
Sun, 20 Feb 2022 12:58:29 +0000 (13:58 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 20 Feb 2022 12:58:29 +0000 (13:58 +0100)
USB-IDS
indicators/README [new file with mode: 0644]
indicators/bootloader/Makefile [new file with mode: 0644]
indicators/bootloader/config.h [new file with mode: 0644]
indicators/firmware/Makefile [new file with mode: 0644]
indicators/firmware/config.h [new file with mode: 0644]
indicators/firmware/main.c [new file with mode: 0644]

diff --git a/USB-IDS b/USB-IDS
index 2e3b4bc19975679f88940181c58db602dfecfd54..591f21be547bbab0bf5fe9022fc78362318e6a39 100644 (file)
--- a/USB-IDS
+++ b/USB-IDS
@@ -8,5 +8,7 @@ USB IDs used by our gadgets
 4242:0006      DMX512 interface bootloader
 4242:0007      Test gadget
 4242:0008      Test gadget bootloader
+4242:0009      Neopixel indicators
+4242:000a      Neopixel indicators bootloader
 cafe:cafe      KSP Space Alert thermometer
 cafe:caff      KSP Space Alert accelerometer
diff --git a/indicators/README b/indicators/README
new file mode 100644 (file)
index 0000000..203357f
--- /dev/null
@@ -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 (needs pull-up)
+                       | 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/indicators/bootloader/Makefile b/indicators/bootloader/Makefile
new file mode 100644 (file)
index 0000000..9ba9617
--- /dev/null
@@ -0,0 +1,7 @@
+ROOT=../..
+BINARY=bootloader
+OBJS=
+LIB_OBJS=util-debug.o dfu-bootloader.o
+MAX_SIZE=8192
+
+include $(ROOT)/mk/bluepill.mk
diff --git a/indicators/bootloader/config.h b/indicators/bootloader/config.h
new file mode 100644 (file)
index 0000000..bd6d9b2
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ *     Neopixel Indicators Bootloader -- Configuration
+ *
+ *     (c) 2022 Martin Mareš <mj@ucw.cz>
+ */
+
+// Processor clock
+
+#define CPU_CLOCK_MHZ 48
+
+// Debugging port
+
+#define DEBUG_USART USART1
+#define DEBUG_LED_BLUEPILL
+
+// Bootloader settings
+
+#undef BOOTLOADER_DEBUG
+#define BOOTLOADER_APP_START 0x08002000
+#define BOOTLOADER_MFG_ID 0x4242
+#define BOOTLOADER_PROD_ID 0x000a
+#define BOOTLOADER_PROD_VERSION 0x0100
+#define BOOTLOADER_MFG_NAME "United Computer Wizards"
+#define BOOTLOADER_PROD_NAME "Neopixel Indicators (boot-loader)"
diff --git a/indicators/firmware/Makefile b/indicators/firmware/Makefile
new file mode 100644 (file)
index 0000000..7b9a622
--- /dev/null
@@ -0,0 +1,10 @@
+ROOT=../..
+BINARY=firmware
+OBJS=main.o
+LIB_OBJS=util-debug.o
+
+WITH_BOOT_LOADER=1
+WITH_DFU_FLASH=1
+DFU_ARGS=-d 4242:000a
+
+include $(ROOT)/mk/bluepill.mk
diff --git a/indicators/firmware/config.h b/indicators/firmware/config.h
new file mode 100644 (file)
index 0000000..312c7be
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ *     Test Gadget -- Configuration
+ *
+ *     (c) 2020 Martin Mareš <mj@ucw.cz>
+ */
+
+// Processor clock
+
+#define CPU_CLOCK_MHZ 72
+
+// Debugging port
+
+#define DEBUG_USART USART1
+#define DEBUG_LED_BLUEPILL
diff --git a/indicators/firmware/main.c b/indicators/firmware/main.c
new file mode 100644 (file)
index 0000000..b677dec
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ *     Neopixel (WS2812B) Test
+ *
+ *     (c) 2022 Martin Mareš <mj@ucw.cz>
+ */
+
+#include "util.h"
+
+#include <libopencm3/cm3/cortex.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/cm3/systick.h>
+#include <libopencm3/cm3/scb.h>
+#include <libopencm3/stm32/dma.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/timer.h>
+#include <libopencm3/stm32/usart.h>
+
+#include <string.h>
+
+/*** 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[] = {
+       // 64 cycles low: reset
+       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,
+};
+
+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");
+
+       for (;;) {
+               // wait_for_interrupt();
+               debug_led(1);
+               for (int i=4; i<8; i++)
+                       neopixel_buf[64+i] = B1;
+               delay_ms(100);
+               debug_led(0);
+               for (int i=4; i<8; i++)
+                       neopixel_buf[64+i] = B0;
+               delay_ms(500);
+       }
+
+       return 0;
+}