added stream system & improved LCD string handling (crlf)

This commit is contained in:
2015-04-30 15:22:39 +02:00
parent 256e96afc3
commit f0f216469b
17 changed files with 2948 additions and 306 deletions
+68 -6
View File
@@ -13,6 +13,12 @@
// Start address of rows
const uint8_t LCD_ROW_ADDR[] = {0x00, 0x40, 0x14, 0x54};
// Shared stream instance
static STREAM _lcd_singleton;
STREAM* lcd;
// Internal prototypes
void _lcd_mode_r();
void _lcd_mode_w();
@@ -36,6 +42,16 @@ uint8_t _lcd_read_byte();
// 0 W, 1 R
bool _lcd_mode;
struct {
uint8_t x;
uint8_t y;
} _pos;
enum {
TEXT = 0,
CG = 1
} _addrtype;
/** Initialize the display */
void lcd_init()
@@ -68,6 +84,16 @@ void lcd_init()
// mark as enabled
lcd_enable();
_lcd_singleton.tx = &lcd_write;
_lcd_singleton.rx = &lcd_read;
// Stream
lcd = &_lcd_singleton;
_pos.x = 0;
_pos.y = 0;
_addrtype = TEXT;
}
@@ -75,7 +101,7 @@ void lcd_init()
void _lcd_clk()
{
pin_up(LCD_E);
delay_ns(420);
delay_ns(450);
pin_down(LCD_E);
}
@@ -141,6 +167,24 @@ void lcd_command(uint8_t bb)
/** Write a data byte */
void lcd_write(uint8_t bb)
{
if (_addrtype == TEXT) {
if (bb == '\r') {
// CR
_pos.x = 0;
lcd_xy(_pos.x, _pos.y);
return;
}
if (bb == '\n') {
// LF
_pos.y++;
lcd_xy(_pos.x, _pos.y);
return;
}
_pos.x++;
}
_lcd_wait_bf();
pin_up(LCD_RS); // select data register
_lcd_write_byte(bb); // send data byte
@@ -158,12 +202,14 @@ uint8_t lcd_read_bf_addr()
/** Read CGRAM or DDRAM */
uint8_t lcd_read()
{
if (_addrtype == TEXT) _pos.x++;
pin_up(LCD_RS);
return _lcd_read_byte();
}
/** Write a byte using the 8-bit interface */
/** Write a byte using the 4-bit interface */
void _lcd_write_byte(uint8_t bb)
{
_lcd_mode_w(); // enter W mode
@@ -189,13 +235,14 @@ void _lcd_wait_bf()
/** Send a string to LCD */
void lcd_puts(char* str_p)
{
while (*str_p)
lcd_putc(*str_p++);
char c;
while ((c = *str_p++))
lcd_putc(c);
}
/** Print from progmem */
void lcd_puts_pgm(const char* str_p)
void lcd_puts_P(const char* str_p)
{
char c;
while ((c = pgm_read_byte(str_p++)))
@@ -213,6 +260,8 @@ void lcd_putc(const char c)
/** Set cursor position */
void lcd_xy(const uint8_t x, const uint8_t y)
{
_pos.x = x;
_pos.y = y;
lcd_addr(LCD_ROW_ADDR[y] + (x));
}
@@ -249,6 +298,9 @@ void lcd_enable()
void lcd_home()
{
lcd_command(LCD_HOME);
_pos.x = 0;
_pos.y = 0;
_addrtype = TEXT;
}
@@ -266,22 +318,31 @@ void lcd_glyph(const uint8_t index, const uint8_t* array)
for (uint8_t i = 0; i < 8; ++i) {
lcd_write(array[i]);
}
// restore previous position
lcd_xy(_pos.x, _pos.y);
_addrtype = TEXT;
}
/** Define a glyph */
void lcd_glyph_pgm(const uint8_t index, const uint8_t* array)
void lcd_glyph_P(const uint8_t index, const uint8_t* array)
{
lcd_addr_cg(index * 8);
for (uint8_t i = 0; i < 8; ++i) {
lcd_write(pgm_read_byte(&array[i]));
}
// restore previous position
lcd_xy(_pos.x, _pos.y);
_addrtype = TEXT;
}
/** Set address in CGRAM */
void lcd_addr_cg(const uint8_t acg)
{
_addrtype = CG;
lcd_command(0b01000000 | ((acg) & 0b00111111));
}
@@ -289,5 +350,6 @@ void lcd_addr_cg(const uint8_t acg)
/** Set address in DDRAM */
void lcd_addr(const uint8_t add)
{
_addrtype = TEXT;
lcd_command(0b10000000 | ((add) & 0b01111111));
}
+12 -3
View File
@@ -21,9 +21,18 @@
#include <stdint.h>
#include <stdbool.h>
#include "stream.h"
// File with configs
#include "lcd_config.h"
// Shared LCD stream object
// Can be used with functions from stream.h once LCD is initialized
extern STREAM* lcd;
// --- Commands ---
// Clear screen (reset)
@@ -88,7 +97,7 @@ uint8_t lcd_read();
void lcd_puts(char* str_p);
/** Send a string to LCD from program memory */
void lcd_puts_pgm(const char* str_p);
void lcd_puts_P(const char* str_p);
/** Sedn a char to LCD */
void lcd_putc(const char c);
@@ -97,7 +106,7 @@ void lcd_putc(const char c);
#define lcd_puts_xy(x, y, str_p) do { lcd_xy((x), (y)); lcd_puts((str_p)); } while(0)
/** Show string at X, Y */
#define lcd_puts_xy_pgm(x, y, str_p) do { lcd_xy((x), (y)); lcd_puts_pgm((str_p)); } while(0)
#define lcd_puts_xy_P(x, y, str_p) do { lcd_xy((x), (y)); lcd_puts_P((str_p)); } while(0)
/** Show char at X, Y */
#define lcd_putc_xy(x, y, c) do { lcd_xy((x), (y)); lcd_putc((c)); } while(0)
@@ -128,7 +137,7 @@ void lcd_clear();
void lcd_glyph(const uint8_t index, const uint8_t* array);
/** Define a glyph that's in PROGMEM */
void lcd_glyph_pgm(const uint8_t index, const uint8_t* array);
void lcd_glyph_P(const uint8_t index, const uint8_t* array);
/** Set address in CGRAM */
void lcd_addr_cg(const uint8_t acg);
+13 -25
View File
@@ -7,13 +7,13 @@
#include "sonar.h"
// Currently measured sonar
volatile sonar_t *_sonar_active_so;
sonar_t* _sonar_active_so;
// Flag that measurement is in progress
volatile bool _busy;
volatile bool sonar_busy;
// Result of last measurement, in millimeters
volatile int16_t _result = 0xFFFF;
volatile int16_t sonar_result;
void _sonar_init_do(sonar_t* so, PORT_P port, uint8_t ntx, PORT_P pin, uint8_t nrx)
@@ -45,11 +45,11 @@ void _sonar_init_do(sonar_t* so, PORT_P port, uint8_t ntx, PORT_P pin, uint8_t n
*/
bool sonar_start(sonar_t* so)
{
if (_busy) return false;
if (sonar_busy) return false;
_sonar_active_so = so;
_busy = true;
sonar_busy = true;
// make sure the timer is stopped (set clock to NONE)
TCCR1B = 0;
@@ -114,16 +114,16 @@ void _sonar_stop()
// Disable timer1 overflow interrupt
TIMSK1 &= ~(1 << TOIE1);
_busy = false;
sonar_busy = false;
}
/** Handle TIMER1_OVF (returns true if consumed) */
bool sonar_handle_t1ovf()
inline bool sonar_handle_t1ovf()
{
if (!_busy) return false; // nothing
if (!sonar_busy) return false; // nothing
_result = -1;
sonar_result = -1;
_sonar_stop();
return true;
@@ -131,9 +131,9 @@ bool sonar_handle_t1ovf()
/** Handle pin change interrupt (returns true if consumed) */
bool sonar_handle_pci()
inline bool sonar_handle_pci()
{
if (!_busy) {
if (!sonar_busy) {
return false; // nothing
}
@@ -146,24 +146,12 @@ bool sonar_handle_pci()
x /= _SNR_DIV_CONST;
x *= 100000000L;
x /= F_CPU;
_result = (int16_t) x;
sonar_result = (int16_t) x;
// no obstacle
if (_result > _SNR_MAX_DIST) _result = -1;
if (sonar_result > _SNR_MAX_DIST) sonar_result = -1;
_sonar_stop();
return true;
}
bool sonar_busy()
{
return _busy;
}
int16_t sonar_result()
{
return _result;
}
+4 -8
View File
@@ -34,6 +34,10 @@ typedef struct {
} sonar_t;
extern volatile bool sonar_busy;
extern volatile int16_t sonar_result;
// Create a Sonar port
// Args: sonar_t* so, Trig pin, Echo pin
#define sonar_init(so, trig, echo) do { \
@@ -46,14 +50,6 @@ typedef struct {
void _sonar_init_do(sonar_t* so, PORT_P port, uint8_t ntx, PORT_P pin, uint8_t nrx);
/** Check if sonar is busy */
bool sonar_busy();
/** Get result of last measurement, in millimeters. Returns -1 if no obstacle detected */
int16_t sonar_result();
/**
* Start sonar measurement
* Interrupts must be enabled
+162
View File
@@ -0,0 +1,162 @@
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "stream.h"
static char tmpstr[20]; // buffer for number rendering
void put_str(const STREAM *p, char* str)
{
char c;
while ((c = *str++))
p->tx(c);
}
void put_str_P(const STREAM *p, const char* str)
{
char c;
while ((c = pgm_read_byte(str++)))
p->tx(c);
}
static void _putnf(const STREAM *p, const uint8_t places);
/** Send signed int8 */
void put_u8(const STREAM *p, const uint8_t num)
{
utoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send unsigned int8 */
void put_i8(const STREAM *p, const int8_t num)
{
itoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send unsigned int */
void put_u16(const STREAM *p, const uint16_t num)
{
utoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send signed int */
void put_i16(const STREAM *p, const int16_t num)
{
itoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send unsigned long */
void put_u32(const STREAM *p, const uint32_t num)
{
ultoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send signed long */
void put_i32(const STREAM *p, const int32_t num)
{
ltoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
// float variant doesn't make sense for 8-bit int
/** Send unsigned int as float */
void put_u16f(const STREAM *p, const uint16_t num, const uint8_t places)
{
utoa(num, tmpstr, 10);
_putnf(p, places);
}
/** Send signed int as float */
void put_i16f(const STREAM *p, const int16_t num, const uint8_t places)
{
if (num < 0) {
p->tx('-');
itoa(-num, tmpstr, 10);
} else {
itoa(num, tmpstr, 10);
}
_putnf(p, places);
}
/** Send unsigned long as float */
void put_u32f(const STREAM *p, const uint32_t num, const uint8_t places)
{
ultoa(num, tmpstr, 10);
_putnf(p, places);
}
/** Send signed long as float */
void put_i32f(const STREAM *p, const int32_t num, const uint8_t places)
{
if (num < 0) {
p->tx('-');
ltoa(-num, tmpstr, 10);
} else {
ltoa(num, tmpstr, 10);
}
_putnf(p, places);
}
/** Print number in tmp string as float with given decimal point position */
void _putnf(const STREAM *p, const uint8_t places)
{
// measure text length
uint8_t len = 0;
while(tmpstr[len] != 0) len++;
int8_t at = len - places;
// print virtual zeros
if (at <= 0) {
p->tx('0');
p->tx('.');
while(at <= -1) {
p->tx('0');
at++;
}
at = -1;
}
// print the number
uint8_t i = 0;
while(i < len) {
if (at-- == 0) {
p->tx('.');
}
p->tx(tmpstr[i++]);
}
}
/** Print CR LF */
void put_nl(const STREAM *p)
{
p->tx(13);
p->tx(10);
}
+71
View File
@@ -0,0 +1,71 @@
#pragma once
//
// Stream utilities - printing abstraction
// Works with eg. UART
//
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <avr/pgmspace.h>
/** Stream structure */
typedef struct {
void (*tx) (uint8_t b);
uint8_t (*rx) (void);
} STREAM;
/** Print string into a stream */
void put_str(const STREAM *p, char* str);
/** Print a programspace string into a stream */
void put_str_P(const STREAM *p, const char* str);
/** Send signed int8 */
void put_u8(const STREAM *p, const uint8_t num);
/** Send unsigned int8 */
void put_i8(const STREAM *p, const int8_t num);
/** Send unsigned int */
void put_u16(const STREAM *p, const uint16_t num);
/** Send signed int */
void put_i16(const STREAM *p, const int16_t num);
/** Send unsigned long */
void put_u32(const STREAM *p, const uint32_t num);
/** Send signed long */
void put_i32(const STREAM *p, const int32_t num);
// float variant doesn't make sense for 8-bit int
/** Send unsigned int as float */
void put_u16f(const STREAM *p, const uint16_t num, const uint8_t places);
/** Send signed int as float */
void put_i16f(const STREAM *p, const int16_t num, const uint8_t places);
/** Send unsigned long as float */
void put_u32f(const STREAM *p, const uint32_t num, const uint8_t places);
/** Send signed long as float */
void put_i32f(const STREAM *p, const int32_t num, const uint8_t places);
/** Print CR LF */
void put_nl(const STREAM *p);
+11 -127
View File
@@ -6,6 +6,11 @@
#include <stdlib.h>
#include "uart.h"
#include "stream.h"
// Shared stream instance
static STREAM _uart_singleton;
STREAM* uart;
void _uart_init_do(uint16_t ubrr) {
@@ -18,6 +23,11 @@ void _uart_init_do(uint16_t ubrr) {
// 8-bit data, 1 stop bit
UCSR0C = (0b11 << UCSZ00);
_uart_singleton.tx = &uart_tx;
_uart_singleton.rx = &uart_rx;
uart = &_uart_singleton;
}
@@ -84,7 +94,7 @@ void uart_puts(const char* str)
/** Send progmem string over UART */
void uart_puts_pgm(const char* str)
void uart_puts_P(const char* str)
{
char c;
while ((c = pgm_read_byte(str++))) {
@@ -100,129 +110,3 @@ void uart_flush()
while (UCSR0A & (1 << RXC0))
dummy = UDR0;
}
/** Send CRLF */
void uart_nl()
{
uart_tx(13);
uart_tx(10);
}
char tmpstr[12]; // buffer for number rendering
void _uart_putnf(const uint8_t places);
/** Send signed int8 */
void uart_putu(const uint8_t num)
{
utoa(num, tmpstr, 10);
uart_puts(tmpstr);
}
/** Send unsigned int8 */
void uart_putn(const int8_t num)
{
itoa(num, tmpstr, 10);
uart_puts(tmpstr);
}
/** Send unsigned int as float */
void uart_putiu(const uint16_t num, const uint8_t places)
{
if (!places) {
utoa(num, tmpstr, 10);
uart_puts(tmpstr);
} else {
utoa(num, tmpstr, 10);
_uart_putnf(places);
}
}
/** Send signed int as float */
void uart_puti(const int16_t num, const uint8_t places)
{
if (!places) {
itoa(num, tmpstr, 10);
uart_puts(tmpstr);
} else {
if (num < 0) {
uart_tx('-');
itoa(-num, tmpstr, 10);
} else {
itoa(num, tmpstr, 10);
}
_uart_putnf(places);
}
}
/** Send unsigned long as float */
void uart_putlu(const uint32_t num, const uint8_t places)
{
if (!places) {
ultoa(num, tmpstr, 10);
uart_puts(tmpstr);
} else {
ultoa(num, tmpstr, 10);
_uart_putnf(places);
}
}
/** Send signed long as float */
void uart_putl(const int32_t num, const uint8_t places)
{
if (!places) {
ltoa(num, tmpstr, 10);
uart_puts(tmpstr);
} else {
if (num < 0) {
uart_tx('-');
ltoa(-num, tmpstr, 10);
} else {
ltoa(num, tmpstr, 10);
}
_uart_putnf(places);
}
}
/** Print number in tmp string as float with given decimal point position */
void _uart_putnf(const uint8_t places)
{
// measure text length
uint8_t len = 0;
while(tmpstr[len] != 0) len++;
int8_t at = len - places;
// print virtual zeros
if (at <= 0) {
uart_tx('0');
uart_tx('.');
while(at <= -1) {
uart_tx('0');
at++;
}
at = -1;
}
// print the number
uint8_t i = 0;
while(i < len) {
if (at-- == 0) {
uart_tx('.');
}
uart_tx(tmpstr[i++]);
}
}
+6 -26
View File
@@ -13,6 +13,11 @@
#include <stdbool.h>
#include <stdint.h>
#include "stream.h"
// Shared UART stream object
// Can be used with functions from stream.h once UART is initialized
extern STREAM* uart;
/** Init UART for given baudrate */
void _uart_init_do(uint16_t ubrr); // internal, needed for the macro.
@@ -59,30 +64,5 @@ void uart_flush();
void uart_puts(const char* str);
/** Send progmem string over UART */
void uart_puts_pgm(const char* str);
void uart_puts_P(const char* str);
// Numbers
/** Send unsigned int */
void uart_putu(const uint8_t num);
/** Send signed int */
void uart_putn(const int8_t num);
/** Send unsigned int */
void uart_puti(const int16_t num, const uint8_t places);
/** Send signed int */
void uart_putiu(const uint16_t num, const uint8_t places);
/** Send signed long */
void uart_putl(const int32_t num, const uint8_t places);
/** Send unsigned long */
void uart_putlu(const uint32_t num, const uint8_t places);
// Extras
/** Send CRLF */
void uart_nl();
+82 -81
View File
@@ -6,6 +6,7 @@
#include "uart.h"
#include "uart_ansi.h"
#include "stream.h"
void _vt_apply_style();
void _vt_reset_attribs_do();
@@ -15,30 +16,30 @@ void _vt_color_do();
void vt_goto(uint8_t x, uint8_t y)
{
uart_putc(27);
uart_putc('[');
uart_putu(y+1); // one-based !
uart_putc(';');
uart_putu(x+1);
uart_putc('H');
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_putc(27);
uart_putc('[');
uart_putu(x+1);
uart_putc('`');
uart_tx(27);
uart_tx('[');
put_u8(uart, x+1);
uart_tx('`');
}
void vt_goto_y(uint8_t y)
{
uart_putc(27);
uart_putc('[');
uart_putu(y+1);
uart_putc('d');
uart_tx(27);
uart_tx('[');
put_u8(uart, y+1);
uart_tx('d');
}
@@ -72,54 +73,54 @@ void vt_move_y(int8_t y)
void vt_up(uint8_t y)
{
if (y == 0) return;
uart_putc(27);
uart_putc('[');
uart_putu(y);
uart_putc('A');
uart_tx(27);
uart_tx('[');
put_u8(uart, y);
uart_tx('A');
}
void vt_down(uint8_t y)
{
if (y == 0) return;
uart_putc(27);
uart_putc('[');
uart_putu(y);
uart_putc('B');
uart_tx(27);
uart_tx('[');
put_u8(uart, y);
uart_tx('B');
}
void vt_left(uint8_t x)
{
if (x == 0) return;
uart_putc(27);
uart_putc('[');
uart_putu(x);
uart_putc('D');
uart_tx(27);
uart_tx('[');
put_u8(uart, x);
uart_tx('D');
}
void vt_right(uint8_t x)
{
if (x == 0) return;
uart_putc(27);
uart_putc('[');
uart_putu(x);
uart_putc('C');
uart_tx(27);
uart_tx('[');
put_u8(uart, x);
uart_tx('C');
}
void vt_scroll(int8_t y)
{
while (y < 0) {
uart_putc(27);
uart_putc('D'); // up
uart_tx(27);
uart_tx('D'); // up
y++;
}
while (y > 0) {
uart_putc(27);
uart_putc('M'); // down
uart_tx(27);
uart_tx('M'); // down
y--;
}
}
@@ -127,20 +128,20 @@ void vt_scroll(int8_t y)
void vt_scroll_set(uint8_t from, uint8_t to)
{
uart_putc(27);
uart_putc('[');
uart_putu(from);
uart_putc(';');
uart_putu(to);
uart_putc('r');
uart_tx(27);
uart_tx('[');
put_u8(uart, from);
uart_tx(';');
put_u8(uart, to);
uart_tx('r');
}
void vt_scroll_reset()
{
uart_putc(27);
uart_putc('[');
uart_putc('r');
uart_tx(27);
uart_tx('[');
uart_tx('r');
}
@@ -156,7 +157,7 @@ vt_style_t current_style;
void vt_save()
{
uart_puts_pgm(PSTR("\x1B[s"));
uart_puts_P(PSTR("\x1B[s"));
saved_style = current_style;
}
@@ -164,7 +165,7 @@ void vt_save()
void vt_restore()
{
uart_puts_pgm(PSTR("\x1B[u"));
uart_puts_P(PSTR("\x1B[u"));
current_style = saved_style;
}
@@ -246,7 +247,7 @@ void vt_color_bg(uint8_t bg)
/** Send reset command */
inline void _vt_reset_attribs_do()
{
uart_puts_pgm(PSTR("\x1B[m")); // reset
uart_puts_P(PSTR("\x1B[m")); // reset
}
@@ -254,27 +255,27 @@ inline void _vt_reset_attribs_do()
void _vt_style_do()
{
if (current_style.flags & VT_BOLD) {
uart_puts_pgm(PSTR("\x1B[1m"));
uart_puts_P(PSTR("\x1B[1m"));
}
if (current_style.flags & VT_FAINT) {
uart_puts_pgm(PSTR("\x1B[2m"));
uart_puts_P(PSTR("\x1B[2m"));
}
if (current_style.flags & VT_ITALIC) {
uart_puts_pgm(PSTR("\x1B[3m"));
uart_puts_P(PSTR("\x1B[3m"));
}
if (current_style.flags & VT_UNDERLINE) {
uart_puts_pgm(PSTR("\x1B[4m"));
uart_puts_P(PSTR("\x1B[4m"));
}
if (current_style.flags & VT_BLINK) {
uart_puts_pgm(PSTR("\x1B[5m"));
uart_puts_P(PSTR("\x1B[5m"));
}
if (current_style.flags & VT_REVERSE) {
uart_puts_pgm(PSTR("\x1B[7m"));
uart_puts_P(PSTR("\x1B[7m"));
}
}
@@ -282,93 +283,93 @@ void _vt_style_do()
/** Send commands for xolor */
void _vt_color_do()
{
uart_putc(27);
uart_putc('[');
uart_putu(30 + current_style.fg);
uart_putc(';');
uart_putu(40 + current_style.bg);
uart_putc('m');
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_putc(27);
uart_putc('[');
uart_putu(count);
uart_putc('L');
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_putc(27);
uart_putc('[');
uart_putu(count);
uart_putc('M');
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_putc(27);
uart_putc('[');
uart_putu(count);
uart_putc('@');
uart_tx(27);
uart_tx('[');
put_u8(uart, count);
uart_tx('@');
}
/** Delete characters at cursor */
void vt_delete_chars(uint8_t count)
{
uart_putc(27);
uart_putc('[');
uart_putu(count);
uart_putc('P');
uart_tx(27);
uart_tx('[');
put_u8(uart, count);
uart_tx('P');
}
void vt_clear()
{
uart_puts_pgm(PSTR("\x1B[2J"));
uart_puts_P(PSTR("\x1B[2J"));
}
void vt_erase_forth()
{
uart_puts_pgm(PSTR("\x1B[K"));
uart_puts_P(PSTR("\x1B[K"));
}
void vt_erase_back()
{
uart_puts_pgm(PSTR("\x1B[1K"));
uart_puts_P(PSTR("\x1B[1K"));
}
void vt_erase_line()
{
uart_puts_pgm(PSTR("\x1B[2K"));
uart_puts_P(PSTR("\x1B[2K"));
}
void vt_erase_above()
{
uart_puts_pgm(PSTR("\x1B[1J"));
uart_puts_P(PSTR("\x1B[1J"));
}
void vt_erase_below()
{
uart_puts_pgm(PSTR("\x1B[J"));
uart_puts_P(PSTR("\x1B[J"));
}
void vt_home()
{
uart_puts_pgm(PSTR("\x1B[H"));
uart_puts_P(PSTR("\x1B[H"));
}