parent
32c1be7e54
commit
72964684e4
@ -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); |
@ -1,581 +0,0 @@ |
||||
#include <avr/io.h> |
||||
#include <avr/pgmspace.h> |
||||
#include <avr/interrupt.h> |
||||
#include <stdbool.h> |
||||
#include <stdint.h> |
||||
|
||||
#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()); |
||||
} |
||||
} |
||||
} |
@ -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 <avr/io.h> |
||||
#include <stdlib.h> |
||||
#include <stdbool.h> |
||||
#include <stdint.h> |
||||
#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)); |
@ -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 <avr/io.h> |
||||
|
||||
#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) |
@ -0,0 +1,132 @@ |
||||
#include <avr/io.h> |
||||
#include <util/delay.h> |
||||
#include <stdint.h> |
||||
|
||||
#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]); \
|
||||
// } \
|
||||
// } \
|
||||
// }
|
@ -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); |
Loading…
Reference in new issue