diff --git a/examples/Makefile b/examples/Makefile index c36a52e..abf7935 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -11,14 +11,14 @@ EFUSE = 0x05 ## === Source files === # Main C file -MAIN = uart_isr.c +MAIN = sonar_to_lcd.c # Extra C files in this folder LOCAL_SOURCE = # Library directory (with C files) EXTRA_SOURCE_DIR = lib/ # C files in the library directory -EXTRA_SOURCE_FILES = uart.c lcd.c sonar.c uart_ansi.c stream.c +EXTRA_SOURCE_FILES = uart.c lcd.c sonar.c stream.c ## === Programmer === diff --git a/examples/lcd_config.h b/examples/lcd_config.h index 594b506..68473b6 100644 --- a/examples/lcd_config.h +++ b/examples/lcd_config.h @@ -2,12 +2,10 @@ // Pin config file for LCD. -#include "lib/arduino_pins.h" - -#define LCD_RS D2 -#define LCD_RW D3 -#define LCD_E D4 -#define LCD_D4 D5 -#define LCD_D5 D6 -#define LCD_D6 D7 -#define LCD_D7 D8 +#define LCD_RS 2 +#define LCD_RW 3 +#define LCD_E 4 +#define LCD_D4 5 +#define LCD_D5 6 +#define LCD_D6 7 +#define LCD_D7 8 diff --git a/examples/sonar_to_lcd.c b/examples/sonar_to_lcd.c index 6432182..81c9bc4 100644 --- a/examples/sonar_to_lcd.c +++ b/examples/sonar_to_lcd.c @@ -8,7 +8,7 @@ #include #include -#include "lib/arduino_pins.h" +#include "lib/iopins.h" #include "lib/sonar.h" #include "lib/stream.h" #include "lib/lcd.h" diff --git a/examples/uart_keyhandler.c b/examples/uart_keyhandler.c index 5c12346..337b3b1 100644 --- a/examples/uart_keyhandler.c +++ b/examples/uart_keyhandler.c @@ -4,7 +4,6 @@ #include #include "lib/uart.h" -#include "lib/uart_ansi.h" #include "lib/stream.h" // diff --git a/lib/hsl.c b/lib/color.c similarity index 91% rename from lib/hsl.c rename to lib/color.c index 7b96c86..101613e 100644 --- a/lib/hsl.c +++ b/lib/color.c @@ -1,7 +1,13 @@ -#include +#include +#include #include -#include "colors.h" -#include "hsl.h" + +#include "iopins.h" +#include "nsdelay.h" +#include "color.h" + + +// --- HSL --- #ifdef HSL_LINEAR const uint8_t FADE_128[] = { @@ -17,7 +23,7 @@ #endif // based on: https://github.com/lewisd32/avr-hsl2rgb -xrgb_t hsl2xrgb(const hsl_t cc) +xrgb_t hsl_xrgb(const hsl_t cc) { // 0 .. 256*3 const uint16_t hh = (uint16_t) cc.h * 3; diff --git a/lib/colors.h b/lib/color.h similarity index 50% rename from lib/colors.h rename to lib/color.h index e3e40f0..716f738 100644 --- a/lib/colors.h +++ b/lib/color.h @@ -1,15 +1,15 @@ #pragma once -// -// Some useful utilities for RGB color manipulation +// --- color types --- // // The XXXc macros don't use cast, so they can be used in array initializers. // // xrgb ... 3-byte true-color RGB (8 bits per component) -// rgbXX ... XX-bit color value, with equal nr of bits per component +// rgb24 ... 24-bit color value, with equal nr of bits per component // // XX_r (_g, _b) ... extract component from the color, and convert it to 0..255 -// + +// Define HSL_LINEAR to get more linear brightness in hsl->rgb conversion typedef struct { @@ -18,11 +18,8 @@ typedef struct { uint8_t b; } xrgb_t; -typedef uint32_t rgb24_t; -typedef uint16_t rgb15_t; -typedef uint16_t rgb12_t; -typedef uint8_t rgb6_t; +typedef uint32_t rgb24_t; #define xrgb(rr, gg, bb) ((xrgb_t)xrgbc(rr, gg, bb)) // xrgb for constant array declarations @@ -35,7 +32,6 @@ typedef uint8_t rgb6_t; #define xrgb_rgb12(c) (((((rgb12_t)c.r) & 0xF0) << 4) | ((((rgb12_t)c.g) & 0xF0)) | ((((rgb12_t)c.b) & 0xF0) >> 4)) #define xrgb_rgb6(c) (((((rgb6_t)c.r) & 0xC0) >> 2) | ((((rgb6_t)c.g) & 0xC0) >> 4) | ((((rgb6_t)c.b) & 0xC0) >> 6)) - #define rgb24c(r,g,b) (((((rgb24_t)r) & 0xFF) << 16) | ((((rgb24_t)g) & 0xFF) << 8) | (((rgb24_t)b) & 0xFF)) #define rgb24(r,g,b) ((rgb24_t) rgb24(r,g,b)) @@ -45,40 +41,15 @@ typedef uint8_t rgb6_t; #define rgb24_xrgb(c) xrgb(rgb24_r(c), rgb24_g(c), rgb24_b(c)) #define rgb24_xrgbc(c) xrgbc(rgb24_r(c), rgb24_g(c), rgb24_b(c)) +#define add_xrgb(x, y) ((xrgb_t) { (((y).r > (255 - (x).r)) ? 255 : ((x).r + (y).r)), (((y).g > (255 - (x).g)) ? 255 : ((x).g + (y).g)), (((y).b > 255 - (x).b) ? 255 : ((x).b + (y).b)) }) -#define rgb15(r,g,b) ((rgb15_t) rgb15c(r,g,b)) -#define rgb15c(r,g,b) (((r & 0x1F) << 10) | ((g & 0x1F) << 5) | (b & 0x1F)) - -#define rgb15_r(c) ((((rgb15_t) (c)) & 0x7C00) >> 7) -#define rgb15_g(c) ((((rgb15_t) (c)) & 0x3E0) >> 2) -#define rgb15_b(c) ((((rgb15_t) (c)) & 0x1F) << 3) -#define rgb15_xrgb(c) xrgb(rgb15_r(c), rgb15_g(c), rgb15_b(c)) -#define rgb15_rgb24(c) rgb24(rgb15_r(c), rgb15_g(c), rgb15_b(c)) -#define rgb15_rgb24c(c) rgb24c(rgb15_r(c), rgb15_g(c), rgb15_b(c)) - - -#define rgb12(r,g,b) ((rgb12_t) rgb12c(r,g,b)) -#define rgb12c(r,g,b) (((r & 0xF) << 8) | ((g & 0xF) << 4) | (b & 0xF)) - -#define rgb12_r(c) ((((rgb12_t) (c)) & 0xF00) >> 4) -#define rgb12_g(c) (((rgb12_t) (c)) & 0xF0) -#define rgb12_b(c) (((r(rgb12_t) (c)gb) & 0x0F) << 4) -#define rgb12_xrgb(c) xrgb(rgb12_r(c), rgb12_g(c), rgb12_b(c)) -#define rgb12_xrgbc(c) xrgbc(rgb12_r(c), rgb12_g(c), rgb12_b(c)) -#define rgb12_rgb24(c) rgb24(rgb12_r(c), rgb12_g(c), rgb12_b(c)) -#define rgb12_rgb24c(c) rgb24c(rgb12_r(c), rgb12_g(c), rgb12_b(c)) - - -#define rgb6(r,g,b) ((rgb6_t) rgb6c(r,g,b)) -#define rgb6c(r,g,b) (((r & 3) << 4) | ((g & 3) << 2) | (b & 3)) - -#define rgb6_r(c) ((((rgb6_t) (c)) & 0x30) << 2) -#define rgb6_g(c) ((((rgb6_t) (c)) & 0xC) << 4) -#define rgb6_b(c) ((((rgb6_t) (c)) & 0x3) << 6) -#define rgb6_xrgb(c) xrgb(rgb6_r(c), rgb6_g(c), rgb6_b(c)) -#define rgb6_xrgbc(c) xrgbc(rgb6_r(c), rgb6_g(c), rgb6_b(c)) -#define rgb6_rgb24(c) rgb24(rgb6_r(c), rgb6_g(c), rgb6_b(c)) -#define rgb6_rgb24c(c) rgb24c(rgb6_r(c), rgb6_g(c), rgb6_b(c)) -#define add_xrgb(x, y) ((xrgb_t) { (((y).r > (255 - (x).r)) ? 255 : ((x).r + (y).r)), (((y).g > (255 - (x).g)) ? 255 : ((x).g + (y).g)), (((y).b > 255 - (x).b) ? 255 : ((x).b + (y).b)) }) +// HSL data structure +typedef struct { + uint8_t h; + uint8_t s; + uint8_t l; +} hsl_t; +/* Convert HSL to XRGB */ +xrgb_t hsl_xrgb(const hsl_t color); diff --git a/lib/debounce.h b/lib/debounce.h index 89ac266..918111d 100644 --- a/lib/debounce.h +++ b/lib/debounce.h @@ -7,13 +7,6 @@ // // You must provide a config file debo_config.h (next to your main.c) // -// Example: -// #pragma once -// #define DEBO_CHANNELS 2 -// #define DDEBO_TICKS 5 -// -// ---- -// // A pin is registered like this: // // #define BTN1 12 // pin D12 @@ -39,7 +32,14 @@ #include "calc.h" #include "pins.h" + +// Your config file #include "debo_config.h" +/* + #define DEBO_CHANNELS 2 + #define DDEBO_TICKS 5 +*/ + /* Internal deboucer entry */ typedef struct { diff --git a/lib/hsl.h b/lib/hsl.h deleted file mode 100644 index b2d89cf..0000000 --- a/lib/hsl.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -// -// HSL support (addition to colors.h) -// - -#include "colors.h" - -// Define HSL_LINEAR to get more linear brightness in hsl->rgb conversion - -// HSL data structure -typedef struct { - uint8_t h; - uint8_t s; - uint8_t l; -} hsl_t; - -/* Convert HSL to XRGB */ -xrgb_t hsl2xrgb(const hsl_t color); diff --git a/lib/lcd.c b/lib/lcd.c index cf5fb1e..4332e5a 100644 --- a/lib/lcd.c +++ b/lib/lcd.c @@ -5,7 +5,7 @@ #include #include "calc.h" -#include "pins.h" +#include "iopins.h" #include "nsdelay.h" #include "lcd.h" #include "lcd_config.h" diff --git a/lib/lcd.h b/lib/lcd.h index cff8943..7f48d16 100644 --- a/lib/lcd.h +++ b/lib/lcd.h @@ -7,15 +7,6 @@ // // Content can be something like this: // -// #pragma once -// #include "lib/arduino_pins.h" -// #define LCD_RS D10 -// #define LCD_RW D11 -// #define LCD_E D12 -// #define LCD_D4 D13 -// #define LCD_D5 D14 -// #define LCD_D6 D15 -// #define LCD_D7 D16 // #include @@ -23,8 +14,17 @@ #include "stream.h" -// File with configs +// Your file with configs #include "lcd_config.h" +/* + #define LCD_RS 10 + #define LCD_RW 11 + #define LCD_E 12 + #define LCD_D4 13 + #define LCD_D5 14 + #define LCD_D6 15 + #define LCD_D7 16 +*/ diff --git a/lib/uart.c b/lib/uart.c index 566517d..e2a477b 100644 --- a/lib/uart.c +++ b/lib/uart.c @@ -100,3 +100,579 @@ void uart_flush() dummy = UDR0; } } + + +// ------------- VT100 extension -------------- + + +void _vt_apply_style(); +void _vt_reset_attribs_do(); +void _vt_style_do(); +void _vt_color_do(); + + +void vt_goto(uint8_t x, uint8_t y) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, y+1); // one-based ! + uart_tx(';'); + put_u8(uart, x+1); + uart_tx('H'); +} + + +void vt_goto_x(uint8_t x) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, x+1); + uart_tx('`'); +} + + +void vt_goto_y(uint8_t y) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, y+1); + uart_tx('d'); +} + + +void vt_move(int8_t x, int8_t y) +{ + vt_move_x(x); + vt_move_y(y); +} + + +void vt_move_x(int8_t x) +{ + if (x < 0) { + vt_left(-x); + } else { + vt_right(x); + } +} + + +void vt_move_y(int8_t y) +{ + if (y < 0) { + vt_up(-y); + } else { + vt_down(y); + } +} + + +void vt_up(uint8_t y) +{ + if (y == 0) return; + uart_tx(27); + uart_tx('['); + put_u8(uart, y); + uart_tx('A'); +} + + +void vt_down(uint8_t y) +{ + if (y == 0) return; + uart_tx(27); + uart_tx('['); + put_u8(uart, y); + uart_tx('B'); +} + + +void vt_left(uint8_t x) +{ + if (x == 0) return; + uart_tx(27); + uart_tx('['); + put_u8(uart, x); + uart_tx('D'); +} + + +void vt_right(uint8_t x) +{ + if (x == 0) return; + uart_tx(27); + uart_tx('['); + put_u8(uart, x); + uart_tx('C'); +} + + +void vt_scroll(int8_t y) +{ + while (y < 0) { + uart_tx(27); + uart_tx('D'); // up + y++; + } + + while (y > 0) { + uart_tx(27); + uart_tx('M'); // down + y--; + } +} + + +void vt_scroll_set(uint8_t from, uint8_t to) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, from); + uart_tx(';'); + put_u8(uart, to); + uart_tx('r'); +} + + +void vt_scroll_reset() +{ + uart_tx(27); + uart_tx('['); + uart_tx('r'); +} + + + +typedef struct { + uint8_t flags; + uint8_t fg; + uint8_t bg; +} vt_style_t; + +vt_style_t saved_style; +vt_style_t current_style; + +void vt_save() +{ + uart_puts_P(PSTR("\x1B[s")); + + saved_style = current_style; +} + + +void vt_restore() +{ + uart_puts_P(PSTR("\x1B[u")); + + current_style = saved_style; +} + + +/** Disable all text attributes (excluding color) */ +void vt_attr_reset() +{ + current_style.flags = 0; + + _vt_reset_attribs_do(); + _vt_apply_style(); +} + + +/** Set color to white on black */ +void vt_color_reset() +{ + current_style.fg = VT_WHITE; + current_style.bg = VT_BLACK; + + _vt_color_do(); +} + + +/** Enable or disable a text attribute */ +void vt_attr(uint8_t attribute, bool on) +{ + // flags are powers of two + // so this can handle multiple OR'd flags + for(uint8_t c = 1; c <= VT_FAINT; c *= 2) { + if (attribute & c) { + if (on) { + current_style.flags |= c; + } else { + current_style.flags &= ~c; + } + } + } + + _vt_apply_style(); +} + + +/** Send style and color commands */ +void _vt_apply_style() +{ + _vt_reset_attribs_do(); + _vt_style_do(); + _vt_color_do(); +} + + +/** Set color 0..7 */ +void vt_color(uint8_t fg, uint8_t bg) +{ + current_style.fg = fg; + current_style.bg = bg; + _vt_color_do(); +} + + +/** Set FG color 0..7 */ +void vt_color_fg(uint8_t fg) +{ + current_style.fg = fg; + _vt_color_do(); +} + + +/** Set BG color 0..7 */ +void vt_color_bg(uint8_t bg) +{ + current_style.bg = bg; + _vt_color_do(); +} + + +/** Send reset command */ +inline void _vt_reset_attribs_do() +{ + uart_puts_P(PSTR("\x1B[m")); // reset +} + + +/** Send commands for text attribs */ +void _vt_style_do() +{ + if (current_style.flags & VT_BOLD) { + uart_puts_P(PSTR("\x1B[1m")); + } + + if (current_style.flags & VT_FAINT) { + uart_puts_P(PSTR("\x1B[2m")); + } + + if (current_style.flags & VT_ITALIC) { + uart_puts_P(PSTR("\x1B[3m")); + } + + if (current_style.flags & VT_UNDERLINE) { + uart_puts_P(PSTR("\x1B[4m")); + } + + if (current_style.flags & VT_BLINK) { + uart_puts_P(PSTR("\x1B[5m")); + } + + if (current_style.flags & VT_REVERSE) { + uart_puts_P(PSTR("\x1B[7m")); + } +} + + +/** Send commands for xolor */ +void _vt_color_do() +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, 30 + current_style.fg); + uart_tx(';'); + put_u8(uart, 40 + current_style.bg); + uart_tx('m'); +} + + +/** Insert blank lines febore the current line */ +void vt_insert_lines(uint8_t count) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, count); + uart_tx('L'); +} + + +/** Delete lines from the current line down */ +void vt_delete_lines(uint8_t count) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, count); + uart_tx('M'); +} + + +/** Insert empty characters at cursor */ +void vt_insert_chars(uint8_t count) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, count); + uart_tx('@'); +} + + +/** Delete characters at cursor */ +void vt_delete_chars(uint8_t count) +{ + uart_tx(27); + uart_tx('['); + put_u8(uart, count); + uart_tx('P'); +} + + +void vt_clear() +{ + uart_puts_P(PSTR("\x1B[2J")); +} + + +void vt_erase_forth() +{ + uart_puts_P(PSTR("\x1B[K")); +} + + +void vt_erase_back() +{ + uart_puts_P(PSTR("\x1B[1K")); +} + + +void vt_erase_line() +{ + uart_puts_P(PSTR("\x1B[2K")); +} + + +void vt_erase_above() +{ + uart_puts_P(PSTR("\x1B[1J")); +} + +void vt_erase_below() +{ + uart_puts_P(PSTR("\x1B[J")); +} + + +void vt_home() +{ + uart_puts_P(PSTR("\x1B[H")); +} + + +/** Initialize helper variables */ +void vt_init() +{ + vt_reset(); +} + + +/** Reset state and clear screen */ +void vt_reset() +{ + // reset color and attributes + vt_color_reset(); + vt_attr_reset(); + vt_scroll_reset(); + + // clear screen + vt_clear(); + + // go to top left + vt_home(); + + // overwrite saved state + vt_save(); +} + + + +// Assigned keyhandler +void (*_vt_kh)(uint8_t, bool) = NULL; + +/** Assign a key handler (later used with vt_handle_key) */ +void vt_set_key_handler(void (*handler)(uint8_t, bool)) +{ + _vt_kh = handler; +} + + +// state machine states +typedef enum { + GROUND = 0, + ESC = 1, + BR = 2, + O = 3, + WAITING_TILDE = 4 +} KSTATE; + +// code received before started to wait for a tilde +uint8_t _before_wtilde; +// current state +KSTATE _kstate = GROUND; + + + +void _vt_kh_abort() +{ + switch (_kstate) { + case ESC: + _vt_kh(VK_ESC, true); + break; + + case BR: + _vt_kh(VK_ESC, true); + _vt_kh('[', false); + break; + + case O: + _vt_kh(VK_ESC, true); + _vt_kh('O', false); + break; + + case WAITING_TILDE: + _vt_kh(VK_ESC, true); + _vt_kh('[', false); + vt_handle_key(_before_wtilde); + break; + + case GROUND: + // nop + break; + } + + _kstate = GROUND; +} + + +/** + * Handle a key received over UART + * Takes care of multi-byte keys and translates them to special + * constants. + */ +void vt_handle_key(uint8_t c) +{ + if (_vt_kh == NULL) return; + + switch (_kstate) { + case GROUND: + switch (c) { + case 27: + _kstate = ESC; + break; + + case VK_ENTER: + case VK_TAB: + case VK_BACKSPACE: + _vt_kh(c, true); + return; + + default: + _vt_kh(c, false); + return; + } + + break; // continue to next char + + case ESC: + switch (c) { + case '[': + _kstate = BR; + break; // continue to next char + + case 'O': + _kstate = O; + break; // continue to next char + + default: + // bad code + _vt_kh_abort(); + vt_handle_key(c); + return; + } + break; + + case BR: + switch (c) { + // arrows + case 65: + case 66: + case 67: + case 68: + _vt_kh(c, true); + _kstate = GROUND; + return; + + // ins del pgup pgdn + case 50: + case 51: + case 53: + case 54: + // wait for terminating tilde + _before_wtilde = c; + _kstate = WAITING_TILDE; + break; // continue to next char + + // bad key + default: + _vt_kh_abort(); + vt_handle_key(c); + return; + } + break; + + case O: + switch (c) { + // F keys + case 80: + case 81: + case 82: + case 83: + // home, end + case 72: + case 70: + _vt_kh(c, true); + _kstate = GROUND; + return; + + // bad key + default: + _vt_kh_abort(); + vt_handle_key(c); + return; + } + + case WAITING_TILDE: + if (c != '~') { + _vt_kh_abort(); + vt_handle_key(c); + return; + } else { + _vt_kh(_before_wtilde, true); + _kstate = GROUND; + return; + } + } + + // wait for next key + if (_kstate != GROUND) { + _delay_ms(2); + if (!uart_rx_ready()) { + // abort receiving + _vt_kh_abort(); + + } else { + vt_handle_key(uart_rx()); + } + } +} diff --git a/lib/uart.h b/lib/uart.h index 5813803..13b0775 100644 --- a/lib/uart.h +++ b/lib/uart.h @@ -66,3 +66,188 @@ void uart_puts(const char* str); /** Send progmem string over UART */ void uart_puts_P(const char* str); + + +// +// ANSI / VT100 utilities for UART +// +// To use this, first call uart_init(baud) and vt_init() +// To print stuff on the screen, use uart_puts() etc from uart.h +// + + +// INIT + +/** Initialize helper variables */ +void vt_init(); + +/** Reset state and clear screen */ +void vt_reset(); + + + +// CURSOR MOVE + +/** Move cursor to top left corner */ +void vt_home(); + +/** Jump to a location on the screen */ +void vt_goto(uint8_t x, uint8_t y); + +/** Jump to given X, keep Y */ +void vt_goto_x(uint8_t x); + +/** Jump to given Y, keep X */ +void vt_goto_y(uint8_t y); + +/** Move cursor relative to current location */ +void vt_move(int8_t x, int8_t y); + +/** Move cursor horizontally */ +void vt_move_x(int8_t x); + +/** Move cursor vertically */ +void vt_move_y(int8_t y); + +/** Move cursor up y cells */ +void vt_up(uint8_t y); + +/** Move cursor down y cells */ +void vt_down(uint8_t y); + +/** Move cursor left x cells */ +void vt_left(uint8_t x); + +/** Move cursor right x cells */ +void vt_right(uint8_t x); + + + +// SCROLLING + +/** Scroll y lines down (like up/down, but moves window if needed) */ +void vt_scroll(int8_t down); + +/** Set scrolling region (lines) */ +void vt_scroll_set(uint8_t from, uint8_t to); + + +/** Sets scrolling region to the entire screen. */ +void vt_scroll_reset(); + + +// COLOR + +#define VT_BLACK 0 +#define VT_RED 1 +#define VT_GREEN 2 +#define VT_YELLOW 3 +#define VT_BLUE 4 +#define VT_MAGENTA 5 +#define VT_CYAN 6 +#define VT_WHITE 7 + +/** Set color 0..7 */ +void vt_color(uint8_t fg, uint8_t bg); + +/** Set FG color 0..7 */ +void vt_color_fg(uint8_t fg); + +/** Set BG color 0..7 */ +void vt_color_bg(uint8_t bg); + +/** Set color to white on black */ +void vt_color_reset(); + + + +// STYLES + +#define VT_BOLD 1 +#define VT_UNDERLINE 2 +#define VT_BLINK 4 +#define VT_REVERSE 8 +#define VT_ITALIC 16 +#define VT_FAINT 32 + +/** Enable or disable a text attribute */ +void vt_attr(uint8_t attribute, bool on); + +/** Disable all text attributes (excluding color) */ +void vt_attr_reset(); + + + +// SAVE & RESTORE + +/** Save cursor position & text attributes */ +void vt_save(); + +/** Restore cursor to saved values */ +void vt_restore(); + + + +// MODIFY + + +/** Insert blank lines febore the current line */ +void vt_insert_lines(uint8_t count); + +/** Delete lines from the current line down */ +void vt_delete_lines(uint8_t count); + +/** Insert empty characters at cursor */ +void vt_insert_chars(uint8_t count); + +/** Delete characters at cursor */ +void vt_delete_chars(uint8_t count); + + + +// ERASING + +/** Clear the screen */ +void vt_clear(); + +/** Erase to the end of line */ +void vt_erase_forth(); + +/** Erase line to cursor */ +void vt_erase_back(); + +/** Erase entire line */ +void vt_erase_line(); + +/** Erase screen below the line */ +void vt_erase_above(); + +/** Erase screen above the line */ +void vt_erase_below(); + + + +// KEY HANDLER + +// Special keys from key handler +#define VK_LEFT 68 +#define VK_RIGHT 67 +#define VK_UP 65 +#define VK_DOWN 66 +#define VK_DELETE 51 +#define VK_INSERT 50 +#define VK_PGUP 53 +#define VK_PGDN 54 +#define VK_HOME 72 +#define VK_END 70 +#define VK_F1 80 +#define VK_F2 81 +#define VK_F3 82 +#define VK_F4 83 +#define VK_BACKSPACE 8 +#define VK_TAB 9 +#define VK_ENTER 13 +#define VK_ESC 27 + +void vt_handle_key(uint8_t c); +void vt_set_key_handler(void (*handler)(uint8_t, bool)); diff --git a/lib/uart_ansi.c b/lib/uart_ansi.c deleted file mode 100644 index 4f696a2..0000000 --- a/lib/uart_ansi.c +++ /dev/null @@ -1,581 +0,0 @@ -#include -#include -#include -#include -#include - -#include "uart.h" -#include "uart_ansi.h" -#include "stream.h" - -void _vt_apply_style(); -void _vt_reset_attribs_do(); -void _vt_style_do(); -void _vt_color_do(); - - -void vt_goto(uint8_t x, uint8_t y) -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, y+1); // one-based ! - uart_tx(';'); - put_u8(uart, x+1); - uart_tx('H'); -} - - -void vt_goto_x(uint8_t x) -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, x+1); - uart_tx('`'); -} - - -void vt_goto_y(uint8_t y) -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, y+1); - uart_tx('d'); -} - - -void vt_move(int8_t x, int8_t y) -{ - vt_move_x(x); - vt_move_y(y); -} - - -void vt_move_x(int8_t x) -{ - if (x < 0) { - vt_left(-x); - } else { - vt_right(x); - } -} - - -void vt_move_y(int8_t y) -{ - if (y < 0) { - vt_up(-y); - } else { - vt_down(y); - } -} - - -void vt_up(uint8_t y) -{ - if (y == 0) return; - uart_tx(27); - uart_tx('['); - put_u8(uart, y); - uart_tx('A'); -} - - -void vt_down(uint8_t y) -{ - if (y == 0) return; - uart_tx(27); - uart_tx('['); - put_u8(uart, y); - uart_tx('B'); -} - - -void vt_left(uint8_t x) -{ - if (x == 0) return; - uart_tx(27); - uart_tx('['); - put_u8(uart, x); - uart_tx('D'); -} - - -void vt_right(uint8_t x) -{ - if (x == 0) return; - uart_tx(27); - uart_tx('['); - put_u8(uart, x); - uart_tx('C'); -} - - -void vt_scroll(int8_t y) -{ - while (y < 0) { - uart_tx(27); - uart_tx('D'); // up - y++; - } - - while (y > 0) { - uart_tx(27); - uart_tx('M'); // down - y--; - } -} - - -void vt_scroll_set(uint8_t from, uint8_t to) -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, from); - uart_tx(';'); - put_u8(uart, to); - uart_tx('r'); -} - - -void vt_scroll_reset() -{ - uart_tx(27); - uart_tx('['); - uart_tx('r'); -} - - - -typedef struct { - uint8_t flags; - uint8_t fg; - uint8_t bg; -} vt_style_t; - -vt_style_t saved_style; -vt_style_t current_style; - -void vt_save() -{ - uart_puts_P(PSTR("\x1B[s")); - - saved_style = current_style; -} - - -void vt_restore() -{ - uart_puts_P(PSTR("\x1B[u")); - - current_style = saved_style; -} - - -/** Disable all text attributes (excluding color) */ -void vt_attr_reset() -{ - current_style.flags = 0; - - _vt_reset_attribs_do(); - _vt_apply_style(); -} - - -/** Set color to white on black */ -void vt_color_reset() -{ - current_style.fg = VT_WHITE; - current_style.bg = VT_BLACK; - - _vt_color_do(); -} - - -/** Enable or disable a text attribute */ -void vt_attr(uint8_t attribute, bool on) -{ - // flags are powers of two - // so this can handle multiple OR'd flags - for(uint8_t c = 1; c <= VT_FAINT; c *= 2) { - if (attribute & c) { - if (on) { - current_style.flags |= c; - } else { - current_style.flags &= ~c; - } - } - } - - _vt_apply_style(); -} - - -/** Send style and color commands */ -void _vt_apply_style() -{ - _vt_reset_attribs_do(); - _vt_style_do(); - _vt_color_do(); -} - - -/** Set color 0..7 */ -void vt_color(uint8_t fg, uint8_t bg) -{ - current_style.fg = fg; - current_style.bg = bg; - _vt_color_do(); -} - - -/** Set FG color 0..7 */ -void vt_color_fg(uint8_t fg) -{ - current_style.fg = fg; - _vt_color_do(); -} - - -/** Set BG color 0..7 */ -void vt_color_bg(uint8_t bg) -{ - current_style.bg = bg; - _vt_color_do(); -} - - -/** Send reset command */ -inline void _vt_reset_attribs_do() -{ - uart_puts_P(PSTR("\x1B[m")); // reset -} - - -/** Send commands for text attribs */ -void _vt_style_do() -{ - if (current_style.flags & VT_BOLD) { - uart_puts_P(PSTR("\x1B[1m")); - } - - if (current_style.flags & VT_FAINT) { - uart_puts_P(PSTR("\x1B[2m")); - } - - if (current_style.flags & VT_ITALIC) { - uart_puts_P(PSTR("\x1B[3m")); - } - - if (current_style.flags & VT_UNDERLINE) { - uart_puts_P(PSTR("\x1B[4m")); - } - - if (current_style.flags & VT_BLINK) { - uart_puts_P(PSTR("\x1B[5m")); - } - - if (current_style.flags & VT_REVERSE) { - uart_puts_P(PSTR("\x1B[7m")); - } -} - - -/** Send commands for xolor */ -void _vt_color_do() -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, 30 + current_style.fg); - uart_tx(';'); - put_u8(uart, 40 + current_style.bg); - uart_tx('m'); -} - - -/** Insert blank lines febore the current line */ -void vt_insert_lines(uint8_t count) -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, count); - uart_tx('L'); -} - - -/** Delete lines from the current line down */ -void vt_delete_lines(uint8_t count) -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, count); - uart_tx('M'); -} - - -/** Insert empty characters at cursor */ -void vt_insert_chars(uint8_t count) -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, count); - uart_tx('@'); -} - - -/** Delete characters at cursor */ -void vt_delete_chars(uint8_t count) -{ - uart_tx(27); - uart_tx('['); - put_u8(uart, count); - uart_tx('P'); -} - - -void vt_clear() -{ - uart_puts_P(PSTR("\x1B[2J")); -} - - -void vt_erase_forth() -{ - uart_puts_P(PSTR("\x1B[K")); -} - - -void vt_erase_back() -{ - uart_puts_P(PSTR("\x1B[1K")); -} - - -void vt_erase_line() -{ - uart_puts_P(PSTR("\x1B[2K")); -} - - -void vt_erase_above() -{ - uart_puts_P(PSTR("\x1B[1J")); -} - -void vt_erase_below() -{ - uart_puts_P(PSTR("\x1B[J")); -} - - -void vt_home() -{ - uart_puts_P(PSTR("\x1B[H")); -} - - -/** Initialize helper variables */ -void vt_init() -{ - vt_reset(); -} - - -/** Reset state and clear screen */ -void vt_reset() -{ - // reset color and attributes - vt_color_reset(); - vt_attr_reset(); - vt_scroll_reset(); - - // clear screen - vt_clear(); - - // go to top left - vt_home(); - - // overwrite saved state - vt_save(); -} - - - -// Assigned keyhandler -void (*_vt_kh)(uint8_t, bool) = NULL; - -/** Assign a key handler (later used with vt_handle_key) */ -void vt_set_key_handler(void (*handler)(uint8_t, bool)) -{ - _vt_kh = handler; -} - - -// state machine states -typedef enum { - GROUND = 0, - ESC = 1, - BR = 2, - O = 3, - WAITING_TILDE = 4 -} KSTATE; - -// code received before started to wait for a tilde -uint8_t _before_wtilde; -// current state -KSTATE _kstate = GROUND; - - - -void _vt_kh_abort() -{ - switch (_kstate) { - case ESC: - _vt_kh(VK_ESC, true); - break; - - case BR: - _vt_kh(VK_ESC, true); - _vt_kh('[', false); - break; - - case O: - _vt_kh(VK_ESC, true); - _vt_kh('O', false); - break; - - case WAITING_TILDE: - _vt_kh(VK_ESC, true); - _vt_kh('[', false); - vt_handle_key(_before_wtilde); - break; - - case GROUND: - // nop - break; - } - - _kstate = GROUND; -} - - -/** - * Handle a key received over UART - * Takes care of multi-byte keys and translates them to special - * constants. - */ -void vt_handle_key(uint8_t c) -{ - if (_vt_kh == NULL) return; - - switch (_kstate) { - case GROUND: - switch (c) { - case 27: - _kstate = ESC; - break; - - case VK_ENTER: - case VK_TAB: - case VK_BACKSPACE: - _vt_kh(c, true); - return; - - default: - _vt_kh(c, false); - return; - } - - break; // continue to next char - - case ESC: - switch (c) { - case '[': - _kstate = BR; - break; // continue to next char - - case 'O': - _kstate = O; - break; // continue to next char - - default: - // bad code - _vt_kh_abort(); - vt_handle_key(c); - return; - } - break; - - case BR: - switch (c) { - // arrows - case 65: - case 66: - case 67: - case 68: - _vt_kh(c, true); - _kstate = GROUND; - return; - - // ins del pgup pgdn - case 50: - case 51: - case 53: - case 54: - // wait for terminating tilde - _before_wtilde = c; - _kstate = WAITING_TILDE; - break; // continue to next char - - // bad key - default: - _vt_kh_abort(); - vt_handle_key(c); - return; - } - break; - - case O: - switch (c) { - // F keys - case 80: - case 81: - case 82: - case 83: - // home, end - case 72: - case 70: - _vt_kh(c, true); - _kstate = GROUND; - return; - - // bad key - default: - _vt_kh_abort(); - vt_handle_key(c); - return; - } - - case WAITING_TILDE: - if (c != '~') { - _vt_kh_abort(); - vt_handle_key(c); - return; - } else { - _vt_kh(_before_wtilde, true); - _kstate = GROUND; - return; - } - } - - // wait for next key - if (_kstate != GROUND) { - _delay_ms(2); - if (!uart_rx_ready()) { - // abort receiving - _vt_kh_abort(); - - } else { - vt_handle_key(uart_rx()); - } - } -} diff --git a/lib/uart_ansi.h b/lib/uart_ansi.h deleted file mode 100644 index f780758..0000000 --- a/lib/uart_ansi.h +++ /dev/null @@ -1,192 +0,0 @@ -#pragma once - -// -// ANSI / VT100 utilities for UART -// -// To use this, first call uart_init(baud) and vt_init() -// To print stuff on the screen, use uart_puts() etc from uart.h -// - -#include -#include -#include -#include -#include "uart.h" - - - -// INIT - -/** Initialize helper variables */ -void vt_init(); - -/** Reset state and clear screen */ -void vt_reset(); - - - -// CURSOR MOVE - -/** Move cursor to top left corner */ -void vt_home(); - -/** Jump to a location on the screen */ -void vt_goto(uint8_t x, uint8_t y); - -/** Jump to given X, keep Y */ -void vt_goto_x(uint8_t x); - -/** Jump to given Y, keep X */ -void vt_goto_y(uint8_t y); - -/** Move cursor relative to current location */ -void vt_move(int8_t x, int8_t y); - -/** Move cursor horizontally */ -void vt_move_x(int8_t x); - -/** Move cursor vertically */ -void vt_move_y(int8_t y); - -/** Move cursor up y cells */ -void vt_up(uint8_t y); - -/** Move cursor down y cells */ -void vt_down(uint8_t y); - -/** Move cursor left x cells */ -void vt_left(uint8_t x); - -/** Move cursor right x cells */ -void vt_right(uint8_t x); - - - -// SCROLLING - -/** Scroll y lines down (like up/down, but moves window if needed) */ -void vt_scroll(int8_t down); - -/** Set scrolling region (lines) */ -void vt_scroll_set(uint8_t from, uint8_t to); - - -/** Sets scrolling region to the entire screen. */ -void vt_scroll_reset(); - - -// COLOR - -#define VT_BLACK 0 -#define VT_RED 1 -#define VT_GREEN 2 -#define VT_YELLOW 3 -#define VT_BLUE 4 -#define VT_MAGENTA 5 -#define VT_CYAN 6 -#define VT_WHITE 7 - -/** Set color 0..7 */ -void vt_color(uint8_t fg, uint8_t bg); - -/** Set FG color 0..7 */ -void vt_color_fg(uint8_t fg); - -/** Set BG color 0..7 */ -void vt_color_bg(uint8_t bg); - -/** Set color to white on black */ -void vt_color_reset(); - - - -// STYLES - -#define VT_BOLD 1 -#define VT_UNDERLINE 2 -#define VT_BLINK 4 -#define VT_REVERSE 8 -#define VT_ITALIC 16 -#define VT_FAINT 32 - -/** Enable or disable a text attribute */ -void vt_attr(uint8_t attribute, bool on); - -/** Disable all text attributes (excluding color) */ -void vt_attr_reset(); - - - -// SAVE & RESTORE - -/** Save cursor position & text attributes */ -void vt_save(); - -/** Restore cursor to saved values */ -void vt_restore(); - - - -// MODIFY - - -/** Insert blank lines febore the current line */ -void vt_insert_lines(uint8_t count); - -/** Delete lines from the current line down */ -void vt_delete_lines(uint8_t count); - -/** Insert empty characters at cursor */ -void vt_insert_chars(uint8_t count); - -/** Delete characters at cursor */ -void vt_delete_chars(uint8_t count); - - - -// ERASING - -/** Clear the screen */ -void vt_clear(); - -/** Erase to the end of line */ -void vt_erase_forth(); - -/** Erase line to cursor */ -void vt_erase_back(); - -/** Erase entire line */ -void vt_erase_line(); - -/** Erase screen below the line */ -void vt_erase_above(); - -/** Erase screen above the line */ -void vt_erase_below(); - - - -// KEY HANDLER - -// Special keys from key handler -#define VK_LEFT 68 -#define VK_RIGHT 67 -#define VK_UP 65 -#define VK_DOWN 66 -#define VK_DELETE 51 -#define VK_INSERT 50 -#define VK_PGUP 53 -#define VK_PGDN 54 -#define VK_HOME 72 -#define VK_END 70 -#define VK_F1 80 -#define VK_F2 81 -#define VK_F3 82 -#define VK_F4 83 -#define VK_BACKSPACE 8 -#define VK_TAB 9 -#define VK_ENTER 13 -#define VK_ESC 27 - -void vt_handle_key(uint8_t c); -void vt_set_key_handler(void (*handler)(uint8_t, bool)); diff --git a/lib/ws_rgb.h b/lib/ws_rgb.h deleted file mode 100644 index b58a28f..0000000 --- a/lib/ws_rgb.h +++ /dev/null @@ -1,126 +0,0 @@ -#pragma once - -// -// Utils for driving a WS28xx (tested on WS2812B) RGB LED strips. -// -// It's implemented as macros to avoid overhead when passing values, and to -// enable driving multiple strips at once. -// -// To avoid bloating your code, try to reduce the number of invocations - -// compute color and then send it. -// -// [IMPORTANT] -// -// Some seemingly random influences can ruin the communication. -// If you have enough memory, consider preparing the colors in array, -// and sending this array using one of the "ws_send_XXX_array" macros. -// - -#include - -#include "iopins.h" -#include "nsdelay.h" -#include "colors.h" - -/* Driver code for WS2812B */ - -// --- timing constraints (NS) --- - -#ifndef WS_T_1H -# define WS_T_1H 700 -#endif - -#ifndef WS_T_1L -# define WS_T_1L 150 -#endif - -#ifndef WS_T_0H -# define WS_T_0H 150 -#endif - -#ifndef WS_T_0L -# define WS_T_0L 700 -#endif - -#ifndef WS_T_LATCH -# define WS_T_LATCH 7000 -#endif - - -/** Wait long enough for the colors to show */ -#define ws_show() do {delay_ns_c(WS_T_LATCH, 0); } while(0) - - -/** Send one byte to the RGB strip */ -#define ws_send_byte(io, bb) do { \ - for (volatile int8_t __ws_tmp = 7; __ws_tmp >= 0; --__ws_tmp) { \ - if ((bb) & (1 << __ws_tmp)) { \ - set_high(io); delay_ns_c(WS_T_1H, -2); \ - set_low(io); delay_ns_c(WS_T_1L, -10); \ - } else { \ - set_high(io); delay_ns_c(WS_T_0H, -2); \ - set_low(io); delay_ns_c(WS_T_0L, -10); \ - } \ - } \ -} while(0) - - -/** Send R,G,B color to the strip */ -#define ws_send_rgb(io, r, g, b) do { \ - ws_send_byte(io, g); \ - ws_send_byte(io, r); \ - ws_send_byte(io, b); \ -} while(0) - -/** Send a RGB struct */ -#define ws_send_xrgb(io, xrgb) ws_send_rgb(io, (xrgb).r, (xrgb).g, (xrgb).b) - -/** Send color hex */ -#define ws_send_rgb24(io, rgb) ws_send_rgb(io, rgb24_r(rgb), rgb24_g(rgb), rgb24_b(rgb)) -#define ws_send_rgb15(io, rgb) ws_send_rgb(io, rgb15_r(rgb), rgb15_g(rgb), rgb15_b(rgb)) -#define ws_send_rgb12(io, rgb) ws_send_rgb(io, rgb12_r(rgb), rgb12_g(rgb), rgb12_b(rgb)) -#define ws_send_rgb6(io, rgb) ws_send_rgb(io, rgb6_r(rgb), rgb6_g(rgb), rgb6_b(rgb)) - -/** Send array of colors */ -#define ws_send_xrgb_array(io, rgbs, length) __ws_send_array_proto(io, (rgbs), (length), xrgb) -#define ws_send_rgb24_array(io, rgbs, length) __ws_send_array_proto(io, (rgbs), (length), rgb24) -#define ws_send_rgb15_array(io, rgbs, length) __ws_send_array_proto(io, (rgbs), (length), rgb15) -#define ws_send_rgb12_array(io, rgbs, length) __ws_send_array_proto(io, (rgbs), (length), rgb12) -#define ws_send_rgb6_array(io, rgbs, length) __ws_send_array_proto(io, (rgbs), (length), rgb6) - -// prototype for sending array. it's ugly, sorry. -#define __ws_send_array_proto(io, rgbs, length, style) do { \ - for (uint8_t __ws_sap_i = 0; __ws_sap_i < length; __ws_sap_i++) { \ - style ## _t __ws_sap2 = (rgbs)[__ws_sap_i]; \ - ws_send_ ## style(io, __ws_sap2); \ - } \ -} while(0) - -/** Send a 2D array to a zig-zag display */ -#define ws_send_xrgb_array_zigzag(io, rgbs, width, height) do { \ - int8_t __ws_sxaz_y, __ws_sxaz_x; \ - for(__ws_sxaz_y = 0; __ws_sxaz_y < (height); __ws_sxaz_y ++) { \ - for(__ws_sxaz_x = 0; __ws_sxaz_x < (width); __ws_sxaz_x++) { \ - ws_send_xrgb(io, (rgbs)[__ws_sxaz_y][__ws_sxaz_x]); \ - } \ - __ws_sxaz_y++; \ - for(__ws_sxaz_x = (width) - 1; __ws_sxaz_x >= 0; __ws_sxaz_x--) { \ - ws_send_xrgb(io, (rgbs)[__ws_sxaz_y][__ws_sxaz_x]); \ - } \ - } \ -} while(0) - - -/** Send a linear array to a zig-zag display as a n*m board (row-by-row) */ -#define ws_send_xrgb_array_zigzag_linear(io, rgbs, width, height) do { \ - int8_t __ws_sxazl_x, __ws_sxazl_y; \ - for(__ws_sxazl_y = 0; __ws_sxazl_y < (height); __ws_sxazl_y++) { \ - for(__ws_sxazl_x = 0; __ws_sxazl_x < (width); __ws_sxazl_x++) { \ - ws_send_xrgb(io, (rgbs)[__ws_sxazl_y * (width) + __ws_sxazl_x]); \ - } \ - __ws_sxazl_y++; \ - for(__ws_sxazl_x = width-1; __ws_sxazl_x >=0; __ws_sxazl_x--) { \ - ws_send_xrgb(io, (rgbs)[__ws_sxazl_y * (width) + __ws_sxazl_x]); \ - } \ - } \ -} while(0) diff --git a/lib/wsrgb.c b/lib/wsrgb.c new file mode 100644 index 0000000..f0c27cd --- /dev/null +++ b/lib/wsrgb.c @@ -0,0 +1,132 @@ +#include +#include +#include + +#include "iopins.h" +#include "nsdelay.h" + +#include "wsrgb.h" +#include "color.h" +#include "ws_config.h" + + +/* Driver code for WS2812B */ + +void ws_init() +{ + as_output(WS_PIN); +} + +/** Wait long enough for the colors to show */ +void ws_show() { + delay_ns_c(WS_T_LATCH, 0); +} + +/** Send one byte to the RGB strip */ +void ws_send_byte(const uint8_t bb) +{ + for (volatile int8_t i = 7; i >= 0; --i) { + if ((bb) & (1 << i)) { + set_high(WS_PIN); + delay_ns_c(WS_T_1H, -2); + + set_low(WS_PIN); + delay_ns_c(WS_T_1L, -10); + } else { + set_high(WS_PIN); + delay_ns_c(WS_T_0H, -2); + + set_low(WS_PIN); + delay_ns_c(WS_T_0L, -10); + } + } +} + + +/** Send R,G,B color to the strip */ +void ws_send_rgb(const uint8_t r, const uint8_t g, const uint8_t b) +{ + ws_send_byte(g); + ws_send_byte(r); + ws_send_byte(b); +} + + +/** Send a RGB struct */ +void ws_send_xrgb(xrgb_t xrgb) +{ + ws_send_byte(xrgb.g); + ws_send_byte(xrgb.r); + ws_send_byte(xrgb.b); +} + + +/** Send color hex */ +void ws_send_rgb24(rgb24_t rgb) +{ + ws_send_byte(rgb24_g(rgb)); + ws_send_byte(rgb24_r(rgb)); + ws_send_byte(rgb24_b(rgb)); +} + +/** Send array of colors */ +void ws_send_xrgb_array(const xrgb_t rgbs[], const uint8_t length) +{ + for (uint8_t i = 0; i < length; i++) { + const xrgb_t c = rgbs[i]; + ws_send_byte(c.g); + ws_send_byte(c.r); + ws_send_byte(c.b); + } +} + +/** Send array of colors */ +void ws_send_rgb24_array(const rgb24_t rgbs[], const uint8_t length) +{ + for (uint8_t i = 0; i < length; i++) { + const rgb24_t c = rgbs[i]; + ws_send_byte(rgb24_g(c)); + ws_send_byte(rgb24_r(c)); + ws_send_byte(rgb24_b(c)); + } +} + +//#define ws_send_rgb24_array(rgbs, length) __ws_send_array_proto((rgbs), (length), rgb24) + +// prototype for sending array. it's ugly, sorry. +/*#define __ws_send_array_proto(rgbs, length, style) { \ + for (uint8_t __rgb_sap_i = 0; __rgb_sap_i < length; __rgb_sap_i++) { \ + style ## _t __rgb_sap2 = (rgbs)[__rgb_sap_i]; \ + ws_send_ ## style(__rgb_sap2); \ + } \ +}*/ + + +// /** Send a 2D array to a zig-zag display */ +// #define ws_send_xrgb_array_zigzag(rgbs, width, height) { \ +// int8_t __rgb_sxaz_y, __rgb_sxaz_x; \ +// for(__rgb_sxaz_y = 0; __rgb_sxaz_y < (height); __rgb_sxaz_y ++) { \ +// for(__rgb_sxaz_x = 0; __rgb_sxaz_x < (width); __rgb_sxaz_x++) { \ +// ws_send_xrgb((rgbs)[__rgb_sxaz_y][__rgb_sxaz_x]); \ +// } \ +// __rgb_sxaz_y++; \ +// for(__rgb_sxaz_x = (width) - 1; __rgb_sxaz_x >= 0; __rgb_sxaz_x--) { \ +// ws_send_xrgb((rgbs)[__rgb_sxaz_y][__rgb_sxaz_x]); \ +// } \ +// } \ +// } + + +// /* Send a linear array to a zig-zag display as a n*m board (row-by-row) +// #define ws_send_xrgb_array_zigzag_linear(rgbs, width, height) { \ +// int8_t __rgb_sxazl_x, __rgb_sxazl_y; \ +// for(__rgb_sxazl_y = 0; __rgb_sxazl_y < (height); __rgb_sxazl_y++) { \ +// for(__rgb_sxazl_x = 0; __rgb_sxazl_x < (width); __rgb_sxazl_x++) { \ +// ws_send_xrgb((rgbs)[__rgb_sxazl_y * (width) + __rgb_sxazl_x]); \ +// } \ +// __rgb_sxazl_y++; \ +// for(__rgb_sxazl_x = width-1; __rgb_sxazl_x >=0; __rgb_sxazl_x--) { \ +// ws_send_xrgb((rgbs)[__rgb_sxazl_y * (width) + __rgb_sxazl_x]); \ +// } \ +// } \ +// } diff --git a/lib/wsrgb.h b/lib/wsrgb.h new file mode 100644 index 0000000..391bd1f --- /dev/null +++ b/lib/wsrgb.h @@ -0,0 +1,51 @@ +#pragma once + +// +// Utils for driving a WS2812 RGB LED strips, and color manipulation in general. +// +// Timing is critical! +// +// Create a config file rgb_config.h next to your main.c +// + +#include "iopins.h" +#include "color.h" + +// Your config file +#include "ws_config.h" + +/* + #define WS_T_1H 700 + #define WS_T_1L 150 + #define WS_T_0H 150 + #define WS_T_0L 700 + #define WS_T_LATCH 7000 + #define WS_PIN 2 +*/ + + +// --- functions for RGB strips --- + +/** Initialize OI */ +void ws_init(); + +/** Wait long enough for the colors to show */ +void ws_show(); + +/** Send one byte to the RGB strip */ +void ws_send_byte(const uint8_t bb); + +/** Send R,G,B color to the strip */ +void ws_send_rgb(const uint8_t r, const uint8_t g, const uint8_t b); + +/** Send a RGB struct */ +void ws_send_xrgb(xrgb_t xrgb); + +/** Send color hex */ +void ws_send_rgb24(rgb24_t rgb); + +/** Send array of colors */ +void ws_send_xrgb_array(const xrgb_t rgbs[], const uint8_t length); + +/** Send array of colors */ +void ws_send_rgb24_array(const rgb24_t rgbs[], const uint8_t length);