diff options
| author | xengineering <mail2xengineering@protonmail.com> | 2021-01-26 16:05:27 +0100 | 
|---|---|---|
| committer | xengineering <mail2xengineering@protonmail.com> | 2021-01-26 16:05:27 +0100 | 
| commit | 60849a62e04769aff854781e6cafa67b7025ed73 (patch) | |
| tree | abe07c2472e3b43795fb7dec611f36d5df23f95f /libraries | |
| parent | 17857f69f675141a814c80975545afb7c13dc675 (diff) | |
| download | stm32f103c8-examples-60849a62e04769aff854781e6cafa67b7025ed73.tar stm32f103c8-examples-60849a62e04769aff854781e6cafa67b7025ed73.tar.zst stm32f103c8-examples-60849a62e04769aff854781e6cafa67b7025ed73.zip | |
Diffstat (limited to 'libraries')
| -rw-r--r-- | libraries/ws2812.c | 88 | ||||
| -rw-r--r-- | libraries/ws2812.h | 52 | 
2 files changed, 77 insertions, 63 deletions
| diff --git a/libraries/ws2812.c b/libraries/ws2812.c index aa64031..5fbdf6c 100644 --- a/libraries/ws2812.c +++ b/libraries/ws2812.c @@ -1,16 +1,8 @@ +// vim: tabstop=4 shiftwidth=4 noexpandtab  /* - -# 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 72 MHz -- You have to setup the clock and gpio yourself - +    Documentation is in ws2812.h  */ @@ -21,6 +13,8 @@ Please mind these restrictions:  #define NUMBER_NOPS_SHORT 6  // 0.35 µs = 25.2 cycles @ 72 MHz = 6.3 nops --> 16.7 ns timing error +// public API functions: +  void ws2812_init(WS2812_ARRAY *control_struct, uint32_t port, uint16_t pin, uint8_t *buffer_ptr, uint32_t array_length)  {  	control_struct->gpio_port = port; @@ -29,47 +23,65 @@ void ws2812_init(WS2812_ARRAY *control_struct, uint32_t port, uint16_t pin, uint  	control_struct->array_length = array_length;  	ws2812_clear_buffer(control_struct);  	ws2812_send_reset(control_struct); +    ws2812_write_buffer_to_leds(control_struct);  } +void ws2812_clear_buffer(WS2812_ARRAY *control_struct) +{ +	for (uint32_t i=0; i<(control_struct->array_length*3); i++){ +		control_struct->array_buffer[i] = 0x00; +	} +} + +void ws2812_write_buffer_to_leds(WS2812_ARRAY *control_struct) +{ +    for (uint32_t i=0; i<(control_struct->array_length); i++) +	{ +		ws2812_send_byte(control_struct, control_struct->array_buffer[i*3+1]);  // green first +		ws2812_send_byte(control_struct, control_struct->array_buffer[i*3+0]);  // red second +		ws2812_send_byte(control_struct, control_struct->array_buffer[i*3+2]);  // blue third +	} +    ws2812_send_reset(control_struct); +} + + +// internal functions:  void ws2812_send_reset(WS2812_ARRAY *control_struct)  {  	gpio_clear(control_struct->gpio_port, control_struct->gpio_pin); -	for (int i = 0; i < NUMBER_NOPS_RESET; i++) { +	for (uint16_t i = 0; i < NUMBER_NOPS_RESET; i++) {  		__asm__("nop");  	}  } -  void ws2812_send_zero(WS2812_ARRAY *control_struct)  {  	gpio_set(control_struct->gpio_port, control_struct->gpio_pin); -	for (int i = 0; i < NUMBER_NOPS_SHORT; i++) { +	for (uint8_t 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++) { +	for (uint8_t i = 0; i < NUMBER_NOPS_LONG; i++) {  		__asm__("nop");  	}  } -  void ws2812_send_one(WS2812_ARRAY *control_struct)  {  	gpio_set(control_struct->gpio_port, control_struct->gpio_pin); -	for (int i = 0; i < NUMBER_NOPS_LONG; i++) { +	for (uint8_t 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++) { +	for (uint8_t i = 0; i < NUMBER_NOPS_SHORT; i++) {  		__asm__("nop");  	}  } -  void ws2812_send_byte(WS2812_ARRAY *control_struct, uint8_t data)  { -	for (int i=7; i>=0; i--){ +	for (int8_t i=7; i>=0; i--){  		if ( (data >> i) & 0x01 ){  			ws2812_send_one(control_struct);  		} @@ -78,41 +90,3 @@ void ws2812_send_byte(WS2812_ARRAY *control_struct, uint8_t data)  		}  	}  } - - -void ws2812_send_led(WS2812_ARRAY *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_ARRAY *control_struct) -{ -	for(uint32_t i=0; i<(control_struct->array_length); i++){ -		ws2812_send_led( -			control_struct, -			control_struct->array_buffer[i * WS2812_NUMBER_OF_COLORS + 0],  // red -			control_struct->array_buffer[i * WS2812_NUMBER_OF_COLORS + 1],  // green -			control_struct->array_buffer[i * WS2812_NUMBER_OF_COLORS + 2]   // blue -		); -	} -	ws2812_send_reset(control_struct); -} - - -void ws2812_set_array_led(WS2812_ARRAY *control_struct, uint32_t index, uint8_t red, uint8_t green, uint8_t blue) -{ -	control_struct->array_buffer[index * WS2812_NUMBER_OF_COLORS + 0] = red; -	control_struct->array_buffer[index * WS2812_NUMBER_OF_COLORS + 1] = green; -	control_struct->array_buffer[index * WS2812_NUMBER_OF_COLORS + 2] = blue; -} - - -void ws2812_clear_buffer(WS2812_ARRAY *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 index c6c85d9..f738137 100644 --- a/libraries/ws2812.h +++ b/libraries/ws2812.h @@ -1,3 +1,42 @@ +// vim: tabstop=4 shiftwidth=4 noexpandtab + + +/* +	ws2812 + +	This low-level library gives you access to ws2812 LEDs and +	LED strips via libopencm3. Please use it like this: + +	- connect the data pin (DIN) of the ws2812 to a GPIO of +	  your MCU +	- initialize clock to a sysclock speed of 72 MHz +	- initialize the GPIO pin with GPIO_MODE_OUTPUT_50_MHZ and +	  GPIO_CNF_OUTPUT_PUSHPULL +	- create a WS2812_ARRAY control struct +	- create a uint8_t[ARRAY_LENGTH * 3] buffer +	- call ws2812_init() with your control struct and buffer +	- adjust values on the buffer +	- use ws2812_write_buffer_to_leds() to set the LEDs + +	The uint8_t buffer has the following structure: + +	 -----------------------------------------------------  ... +	|     |     |     |     |     |     |     |     |     | ... +	|  R  |  G  |  B  |  R  |  G  |  B  |  R  |  G  |  B  | ... +	|     |     |     |     |     |     |     |     |     | ... +	 -----------------------------------------------------  ... +	     first led         second led        third led      ... + +	Please mention that this library will never have features +	to make fancy animations and so on. It is designed just to +	access the LEDs on a physical layer. To avoid bad code +	quality due to unnecessary features it will never do more +	than this ... + +	Technical note: This library is based on delays. This is not +	the best way. Maybe it will change to interrupt or DMA use in +	the future. +*/  #ifndef WS2812_H @@ -20,18 +59,19 @@ typedef struct WS2812_ARRAY{  }WS2812_ARRAY; +// public API functions: +  void ws2812_init(WS2812_ARRAY *control_struct, uint32_t port, uint16_t pin, uint8_t *buffer_ptr, uint32_t array_length); +void ws2812_clear_buffer(WS2812_ARRAY *control_struct); +void ws2812_write_buffer_to_leds(WS2812_ARRAY *control_struct); + + +// internal functions:  void ws2812_send_reset(WS2812_ARRAY *control_struct);  void ws2812_send_zero(WS2812_ARRAY *control_struct);  void ws2812_send_one(WS2812_ARRAY *control_struct); -  void ws2812_send_byte(WS2812_ARRAY *control_struct, uint8_t data); -void ws2812_send_led(WS2812_ARRAY *control_struct, uint8_t red, uint8_t green, uint8_t blue); - -void ws2812_write_leds(WS2812_ARRAY *control_struct); -void ws2812_set_array_led(WS2812_ARRAY *control_struct, uint32_t index, uint8_t red, uint8_t green, uint8_t blue); -void ws2812_clear_buffer(WS2812_ARRAY *control_struct);  #endif  /* WS2812_H */ | 
