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