diff options
author | xengineering <mail2xengineering@protonmail.com> | 2020-10-25 13:07:54 +0100 |
---|---|---|
committer | xengineering <mail2xengineering@protonmail.com> | 2020-10-25 13:07:54 +0100 |
commit | 58d3787ca563b7d6a2cb4e0a1ab7fdde67fd5557 (patch) | |
tree | 42115a58b60bdd7fa027b8b37cac7e76e7b74fab | |
parent | 9435a85605d7efc75642491c85b0942bd558fcec (diff) | |
download | stm32f103c8-examples-58d3787ca563b7d6a2cb4e0a1ab7fdde67fd5557.tar stm32f103c8-examples-58d3787ca563b7d6a2cb4e0a1ab7fdde67fd5557.tar.zst stm32f103c8-examples-58d3787ca563b7d6a2cb4e0a1ab7fdde67fd5557.zip |
Add ws2812 Code
-rw-r--r-- | libraries/ws2812.c | 125 | ||||
-rw-r--r-- | libraries/ws2812.h | 38 | ||||
-rw-r--r-- | ws2812/Makefile | 34 | ||||
-rw-r--r-- | ws2812/main.c | 76 |
4 files changed, 273 insertions, 0 deletions
diff --git a/libraries/ws2812.c b/libraries/ws2812.c new file mode 100644 index 0000000..41d4fb5 --- /dev/null +++ b/libraries/ws2812.c @@ -0,0 +1,125 @@ + + +/* + +# WS2812 Library for libopencm3 + +Please mind these restrictions: + +- Only usable with libopencm3 +- Newer versions of libopencm3 may be not compatibel (libopencm3 api is not stable yet) +- Just usable with a clock frequency of 80 MHz +- You have to setup the clock and gpio yourself + +*/ + + +#include "ws2812.h" + +#define NUMBER_NOPS_RESET 1080 // > 50 µs --> 60 µs (to be sure) = 4320 cycles @ 72 MHz = 1080 nops +#define NUMBER_NOPS_LONG 16 // 0.9 µs = 64.8 cycles @ 72 MHz = 16.2 nops --> 11.1 ns timing error +#define NUMBER_NOPS_SHORT 6 // 0.35 µs = 25.2 cycles @ 72 MHz = 6.3 nops --> 16.7 ns timing error + + +void ws2812_init(ws2812_init_typedef *control_struct, uint32_t port, uint16_t pin, uint32_t array_length, uint32_t matrix_width) +{ + control_struct->gpio_port = port; + control_struct->gpio_pin = pin; + control_struct->array_length = array_length; + control_struct->matrix_width = matrix_width; + control_struct->led_array = malloc(sizeof(uint8_t[array_length][3])); + ws2812_clear_buffer(control_struct); + ws2812_send_reset(control_struct); +} + + +void ws2812_send_reset(ws2812_init_typedef *control_struct) +{ + gpio_clear(control_struct->gpio_port, control_struct->gpio_pin); + for (int i = 0; i < NUMBER_NOPS_RESET; i++) { + __asm__("nop"); + } +} + + +void ws2812_send_zero(ws2812_init_typedef *control_struct) +{ + gpio_set(control_struct->gpio_port, control_struct->gpio_pin); + for (int i = 0; i < NUMBER_NOPS_SHORT; i++) { + __asm__("nop"); + } + gpio_clear(control_struct->gpio_port, control_struct->gpio_pin); + for (int i = 0; i < NUMBER_NOPS_LONG; i++) { + __asm__("nop"); + } +} + + +void ws2812_send_one(ws2812_init_typedef *control_struct) +{ + gpio_set(control_struct->gpio_port, control_struct->gpio_pin); + for (int i = 0; i < NUMBER_NOPS_LONG; i++) { + __asm__("nop"); + } + gpio_clear(control_struct->gpio_port, control_struct->gpio_pin); + for (int i = 0; i < NUMBER_NOPS_SHORT; i++) { + __asm__("nop"); + } +} + + +void ws2812_send_byte(ws2812_init_typedef *control_struct, uint8_t data) +{ + for (int i=7; i>=0; i--){ + if ( (data >> i) & 0x01 ){ + ws2812_send_one(control_struct); + } + else { + ws2812_send_zero(control_struct); + } + } +} + + +void ws2812_send_led(ws2812_init_typedef *control_struct, uint8_t red, uint8_t green, uint8_t blue) +{ + ws2812_send_byte(control_struct, green); + ws2812_send_byte(control_struct, red); + ws2812_send_byte(control_struct, blue); +} + + +void ws2812_write_leds(ws2812_init_typedef *control_struct) +{ + for(uint32_t i=0; i<(control_struct->array_length); i++){ + ws2812_send_led( + control_struct, + control_struct->led_array[i][0], // red + control_struct->led_array[i][1], // green + control_struct->led_array[i][2] // blue + ); + } + ws2812_send_reset(control_struct); +} + + +void ws2812_set_array_led(ws2812_init_typedef *control_struct, uint32_t index, uint8_t red, uint8_t green, uint8_t blue) +{ + control_struct->led_array[index][0] = red; + control_struct->led_array[index][1] = green; + control_struct->led_array[index][2] = blue; +} + + +void ws2812_set_matrix_led(ws2812_init_typedef *control_struct, uint32_t x, uint32_t y, uint8_t red, uint8_t green, uint8_t blue) +{ + ws2812_set_array_led(control_struct, (x + y * (control_struct->matrix_width)), red, green, blue); +} + + +void ws2812_clear_buffer(ws2812_init_typedef *control_struct) +{ + for (uint32_t i=0; i<control_struct->array_length; i++){ + ws2812_set_array_led(control_struct, i, 0, 0, 0); + } +} diff --git a/libraries/ws2812.h b/libraries/ws2812.h new file mode 100644 index 0000000..e4f0754 --- /dev/null +++ b/libraries/ws2812.h @@ -0,0 +1,38 @@ + + +#ifndef WS2812_H +#define WS2812_H + + +#include <stdlib.h> +#include <libopencm3/stm32/gpio.h> + + +typedef struct ws2812_init_typedef{ + + uint32_t gpio_port; + uint16_t gpio_pin; + uint32_t array_length; + uint32_t matrix_width; + uint8_t (*led_array)[3]; + +}ws2812_init_typedef; + + +void ws2812_init(ws2812_init_typedef *control_struct, uint32_t port, uint16_t pin, uint32_t array_length, uint32_t matrix_width); + +void ws2812_send_reset(ws2812_init_typedef *control_struct); +void ws2812_send_zero(ws2812_init_typedef *control_struct); +void ws2812_send_one(ws2812_init_typedef *control_struct); + +void ws2812_send_byte(ws2812_init_typedef *control_struct, uint8_t data); +void ws2812_send_led(ws2812_init_typedef *control_struct, uint8_t red, uint8_t green, uint8_t blue); +void ws2812_write_leds(ws2812_init_typedef *control_struct); + +void ws2812_set_array_led(ws2812_init_typedef *control_struct, uint32_t index, uint8_t red, uint8_t green, uint8_t blue); +void ws2812_set_matrix_led(ws2812_init_typedef *control_struct, uint32_t x, uint32_t y, uint8_t red, uint8_t green, uint8_t blue); + +void ws2812_clear_buffer(ws2812_init_typedef *control_struct); + + +#endif /* WS2812_H */ diff --git a/ws2812/Makefile b/ws2812/Makefile new file mode 100644 index 0000000..8973ef6 --- /dev/null +++ b/ws2812/Makefile @@ -0,0 +1,34 @@ +PROJECT = ws2812 +BUILD_DIR = bin + +SHARED_DIR = ../libraries +CFILES = main.c +CFILES += ws2812.c +#AFILES += api-asm.S + +# TODO - you will need to edit these two lines! +DEVICE=stm32f103c8 +#OOCD_FILE = board/stm32f4discovery.cfg + +# You shouldn't have to edit anything below here. +VPATH += $(SHARED_DIR) +INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR)) +OPENCM3_DIR=../libopencm3 + +include $(OPENCM3_DIR)/mk/genlink-config.mk +include ../rules.mk +include $(OPENCM3_DIR)/mk/genlink-rules.mk + + +# Black Magic Probe: + +GDB=/usr/bin/arm-none-eabi-gdb +BMP_DEVICE=/dev/ttyACM0 + +bmp: $(PROJECT).elf + $(GDB) $(PROJECT).elf \ + -ex 'set confirm off' \ + -ex 'target extended-remote $(BMP_DEVICE)' \ + -ex 'monitor swdp_scan' \ + -ex 'attach 1' + diff --git a/ws2812/main.c b/ws2812/main.c new file mode 100644 index 0000000..926cd68 --- /dev/null +++ b/ws2812/main.c @@ -0,0 +1,76 @@ + + +#include <libopencm3/stm32/rcc.h> +#include <libopencm3/stm32/gpio.h> + +#include "ws2812.h" + + +#define DELAY 30000 // 18,000,000 nops are one second +#define BRIGHTNESS 100 + + +void clock_init(void); +void gpio_init(void); +void delay(void); + + +ws2812_init_typedef ws2812; + + +int main(void) +{ + clock_init(); + gpio_init(); + ws2812_init(&ws2812, GPIOB, GPIO13, 1, 1); + + while(1){ + /*ws2812_send_led(&ws2812, BRIGHTNESS, 0, 0); + delay(); + ws2812_send_led(&ws2812, 0, BRIGHTNESS, 0); + delay(); + ws2812_send_led(&ws2812, 0, 0, BRIGHTNESS); + delay(); + ws2812_send_led(&ws2812, BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); + delay();*/ + + for (uint16_t i=0; i<=255; i++){ + ws2812_send_led(&ws2812, i, 0, 0); + delay(); + } + for (uint16_t i=255; i>0; i--){ + ws2812_send_led(&ws2812, i, 0, 0); + delay(); + } + } + + return 0; +} + + +void clock_init(void) +{ + rcc_clock_setup_in_hse_12mhz_out_72mhz(); + rcc_periph_clock_enable(RCC_GPIOB); // for ws2812 + rcc_periph_clock_enable(RCC_GPIOC); // for PC13 blinking +} + + +void gpio_init(void) +{ + // on board led blinking + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_set(GPIOC, GPIO13); + + // ws2812 output pin + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_set(GPIOB, GPIO13); +} + + +void delay(void) +{ + for (int i = 0; i < DELAY; i++) { + __asm__("nop"); + } +} |