Initial pass on implementing ANSI escape sequences
Signed-off-by: Collin J. Doering <collin.doering@rekahsoft.ca>
This commit is contained in:
parent
f7893b7f88
commit
d63c250630
187
lcdLib.c
187
lcdLib.c
@ -249,9 +249,112 @@ void writeCharToLCD(char c) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Given a character string, and a uint8_t pointer, reads the character string until a
|
||||
non-numerical ASCII character, returning the integer representation of the number read. At
|
||||
the end of the functions execution, the found_num uint8_t pointer will indicate how many
|
||||
digits were read.
|
||||
*/
|
||||
uint8_t readASCIINumber(const char* str, uint8_t* found_num) {
|
||||
const uint8_t num_digits = 4;
|
||||
uint8_t nums[num_digits];
|
||||
|
||||
while (*str != '\0' && *found_num < num_digits - 1) {
|
||||
if (*str >= 0x30 && *str <= 0x39) {
|
||||
// Use *str as a number (specified in ASCII)
|
||||
nums[*(found_num++)] = *str - 0x30;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
str++;
|
||||
}
|
||||
|
||||
uint8_t ret = 0;
|
||||
for (uint8_t i = 0; i < num_digits; i++)
|
||||
ret += nums[num_digits - i] * pow(10, i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void writeStringToLCD(const char* str) {
|
||||
while (*str != '\0') {
|
||||
writeCharToLCD(*str);
|
||||
// Check for ANSI CSI (Control Sequence Introducer)
|
||||
if (*str == '\e') {
|
||||
if (*(++str) != '\0' && *str == '[') {
|
||||
// Read optional variable length number in ASCII (0x30 - 0x3f) where 0x3a - 0x3f are
|
||||
// ignored (they are used as flags by some terminals
|
||||
uint8_t fnd0;
|
||||
uint8_t num0 = readASCIINumber(str++, &fnd0);
|
||||
|
||||
// Read optional (semicolon followed by optional variable length number)
|
||||
uint8_t fnd1;
|
||||
uint8_t num1;
|
||||
if (*(++str) != '\0' && *str == ';') {
|
||||
num1 = readASCIINumber(str++, &fnd1);
|
||||
|
||||
// Read control character (between 0x40 - 0x7e) for two argument sequences
|
||||
switch (*str) {
|
||||
case 'f': // HVP - Horizontal and vertical position
|
||||
case 'H': // CUP - Cursor position
|
||||
num0 = fnd0 ? num0 : 1;
|
||||
num1 = fnd1 ? num1 : 1;
|
||||
setCursorPosition(num0, num1);
|
||||
break;
|
||||
;;
|
||||
default: // Invalid control character
|
||||
break;
|
||||
;;
|
||||
}
|
||||
} else if (*str != '\0') {
|
||||
// Read control character (between 0x40 - 0x7e) for single argument sequences
|
||||
switch (*str) {
|
||||
case 'A': // CUU - Cursor up
|
||||
num0 = fnd0 ? num0 : 1;
|
||||
moveCursorUp(num0);
|
||||
break;
|
||||
;;
|
||||
case 'B': // CUD - Cursor down
|
||||
num0 = fnd0 ? num0 : 1;
|
||||
moveCursorDown(num0);
|
||||
break;
|
||||
;;
|
||||
case 'C': // CUF - Cursor forward
|
||||
num0 = fnd0 ? num0 : 1;
|
||||
moveCursorForward(num0);
|
||||
break;
|
||||
;;
|
||||
case 'D': // CUB - Cursor back
|
||||
num0 = fnd0 ? num0 : 1;
|
||||
moveCursorBackward(num0);
|
||||
break;
|
||||
;;
|
||||
case 'E': // CNL - Cursor next line
|
||||
num0 = fnd0 ? num0 : 1;
|
||||
moveCursorNextLine(num0);
|
||||
break;
|
||||
;;
|
||||
case 'F': // CPL - Cursor previous line
|
||||
num0 = fnd0 ? num0 : 1;
|
||||
moveCursorPreviousLine(num0);
|
||||
break;
|
||||
;;
|
||||
case 'G': // CHA - Cursor horizontal absolute
|
||||
num0 = fnd0 ? num0 : 1;
|
||||
moveCursorToColumn(num0);
|
||||
break;
|
||||
;;
|
||||
default: // Invalid control character
|
||||
break;
|
||||
;;
|
||||
}
|
||||
} else {
|
||||
return; // Invalid escape sequence (terminated early)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeCharToLCD(*str);
|
||||
}
|
||||
|
||||
str++;
|
||||
}
|
||||
}
|
||||
@ -280,6 +383,88 @@ void returnHome(void) {
|
||||
currentLineChars = 0;
|
||||
}
|
||||
|
||||
void getCursorPosition(uint8_t* row, uint8_t* column) {
|
||||
*row = currentLineNum + 1;
|
||||
*column = currentLineChars + 1;
|
||||
}
|
||||
|
||||
void setCursorPosition(uint8_t row, uint8_t column) {
|
||||
// Set currentLineNum and currentLineChars
|
||||
currentLineNum = row ? row - 1 : 0;
|
||||
currentLineChars = column ? column - 1 : 0;
|
||||
|
||||
writeLCDInstr(INSTR_DDRAM_ADDR | (lineBeginnings[currentLineNum] + currentLineChars));
|
||||
}
|
||||
|
||||
void moveCursorUp(uint8_t n) {
|
||||
if (n < currentLineNum + 1) {
|
||||
currentLineNum -= n;
|
||||
} else {
|
||||
currentLineNum = 0;
|
||||
}
|
||||
|
||||
writeLCDInstr(INSTR_DDRAM_ADDR | (lineBeginnings[currentLineNum] + currentLineChars));
|
||||
}
|
||||
|
||||
void moveCursorDown(uint8_t n) {
|
||||
if (n + currentLineNum > LCD_NUMBER_OF_LINES - 1) {
|
||||
currentLineNum += n;
|
||||
} else {
|
||||
currentLineNum = LCD_NUMBER_OF_LINES - 1;
|
||||
}
|
||||
|
||||
writeLCDInstr(INSTR_DDRAM_ADDR | (lineBeginnings[currentLineNum] + currentLineChars));
|
||||
}
|
||||
|
||||
void moveCursorForward(uint8_t n) {
|
||||
if (n + currentLineChars > LCD_CHARACTERS_PER_LINE - 1) {
|
||||
currentLineChars += n;
|
||||
} else {
|
||||
currentLineChars = LCD_CHARACTERS_PER_LINE - 1;
|
||||
}
|
||||
|
||||
writeLCDInstr(INSTR_DDRAM_ADDR | (lineBeginnings[currentLineNum] + currentLineChars));
|
||||
}
|
||||
|
||||
void moveCursorBackward(uint8_t n) {
|
||||
if (n < currentLineChars + 1) {
|
||||
currentLineChars += n;
|
||||
} else {
|
||||
currentLineChars = 0;
|
||||
}
|
||||
|
||||
writeLCDInstr(INSTR_DDRAM_ADDR | (lineBeginnings[currentLineNum] + currentLineChars));
|
||||
}
|
||||
|
||||
void moveCursorNextLine(uint8_t n) {
|
||||
if (n + currentLineNum > LCD_NUMBER_OF_LINES - 1) {
|
||||
currentLineNum += n;
|
||||
} else {
|
||||
currentLineNum = LCD_NUMBER_OF_LINES - 1;
|
||||
}
|
||||
|
||||
writeLCDInstr(INSTR_DDRAM_ADDR | (lineBeginnings[currentLineNum] + currentLineChars));
|
||||
}
|
||||
|
||||
void moveCursorPreviousLine(uint8_t n) {
|
||||
if (n < currentLineNum + 1) {
|
||||
currentLineNum -= n;
|
||||
} else {
|
||||
currentLineNum = 0;
|
||||
}
|
||||
|
||||
writeLCDInstr(INSTR_DDRAM_ADDR | (lineBeginnings[currentLineNum] + currentLineChars));
|
||||
}
|
||||
|
||||
void moveCursorToColumn(uint8_t n) {
|
||||
if (n < LCD_CHARACTERS_PER_LINE) {
|
||||
currentLineChars = n ? n - 1 : 0;
|
||||
writeLCDInstr(INSTR_DDRAM_ADDR | (lineBeginnings[currentLineNum] + currentLineChars));
|
||||
} // else index out of range (off screen column)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
/* char readCharFromLCD(void) { */
|
||||
/* loop_until_LCD_BF_clear(); // Wait until LCD is ready for new instructions */
|
||||
|
||||
|
58
lcdLib.h
58
lcdLib.h
@ -25,6 +25,7 @@
|
||||
// Includes -------------------------------------------------------------------------------
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <math.h>
|
||||
#include "lcdLibConfig.h"
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
@ -65,6 +66,11 @@
|
||||
// Set DD RAM address instruction
|
||||
#define INSTR_DDRAM_ADDR 0x80
|
||||
|
||||
//-------------------------------------
|
||||
|
||||
|
||||
#define LCD_CHARACTERS_PER_SCREEN (LCD_CHARACTERS_PER_LINE * LCD_NUMBER_OF_LINES)
|
||||
|
||||
|
||||
//------------------------------------
|
||||
// Function definitions
|
||||
@ -133,6 +139,9 @@ void writeCharToLCD(char);
|
||||
*/
|
||||
void writeStringToLCD(const char*);
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// LCD command functions
|
||||
|
||||
/**
|
||||
Clears the display and positions the cursor in the top left of the LCD screen.
|
||||
*/
|
||||
@ -143,11 +152,60 @@ void clearDisplay(void);
|
||||
*/
|
||||
void returnHome(void);
|
||||
|
||||
/**
|
||||
Gets the current row and column of the LCD cursor.
|
||||
*/
|
||||
void getCursorPosition(uint8_t* row, uint8_t* column);
|
||||
|
||||
/**
|
||||
Sets given pointers row and column to the current row and column occupied by the LCD cursor.
|
||||
*/
|
||||
void setCursorPosition(uint8_t row, uint8_t column);
|
||||
|
||||
/**
|
||||
Moves the cursor n positions up. If the cursor is at the edge of the screen this has no effect.
|
||||
*/
|
||||
void moveCursorUp(uint8_t n);
|
||||
|
||||
/**
|
||||
Moves the cursor n positions down. If the cursor is at the edge of the screen this has no effect.
|
||||
*/
|
||||
void moveCursorDown(uint8_t n);
|
||||
|
||||
/**
|
||||
Moves the cursor n positions forward. If the cursor is at the edge of the screen this has no effect.
|
||||
*/
|
||||
void moveCursorForward(uint8_t n);
|
||||
|
||||
/**
|
||||
Moves the cursor n positions backwards. If the cursor is at the edge of the screen this has no effect.
|
||||
*/
|
||||
void moveCursorBackward(uint8_t n);
|
||||
|
||||
/**
|
||||
Moves the cursor to the beginning of the line n lines down.
|
||||
*/
|
||||
void moveCursorNextLine(uint8_t n);
|
||||
|
||||
/**
|
||||
Moves the cursor to the beginning of the line n lines up.
|
||||
*/
|
||||
void moveCursorPreviousLine(uint8_t n);
|
||||
|
||||
/**
|
||||
Moves the cursor to column n. If n is off screen go to the last line.
|
||||
*/
|
||||
void moveCursorToColumn(uint8_t n);
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
UNIMPLEMENTED
|
||||
*/
|
||||
char readCharFromLCD(void);
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
Initialize the LCD display via software initialization as specified by the datasheet.
|
||||
*/
|
||||
|
57
lcdOutput.c
57
lcdOutput.c
@ -29,6 +29,7 @@
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/power.h>
|
||||
#include <util/delay.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lcdLib.h"
|
||||
#include "ansi_escapes.h"
|
||||
@ -38,6 +39,8 @@
|
||||
#define STATUS_LED_DDR DDRC
|
||||
#define STATUS_LED PC5
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
void flashLED(uint8_t times) {
|
||||
while (times > 0) {
|
||||
STATUS_LED_PORT |= 1 << STATUS_LED; // turn on status LED
|
||||
@ -47,12 +50,27 @@ void flashLED(uint8_t times) {
|
||||
times--;
|
||||
}
|
||||
}
|
||||
//--------------------------------------------------
|
||||
|
||||
/*
|
||||
Initialize previous, current, and next screen variables to spaces
|
||||
*/
|
||||
char* initScreenMem(const uint8_t len) {
|
||||
char *scrn = (char*) malloc(len * sizeof(char));
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
scrn[i] = ' ';
|
||||
}
|
||||
return scrn;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
clock_prescale_set(clock_div_1);
|
||||
|
||||
STATUS_LED_DDR |= 1 << STATUS_LED; // DEBUG
|
||||
|
||||
// Allocate and init first block of heap for storing LCD data
|
||||
char* scrn = initScreenMem(LCD_CHARACTERS_PER_SCREEN);
|
||||
|
||||
initUSART();
|
||||
char serialChar;
|
||||
|
||||
@ -60,6 +78,45 @@ int main(void) {
|
||||
//initLCDByInternalReset();
|
||||
flashLED(5); // DEBUG
|
||||
|
||||
|
||||
writeStringToLCD("Backwards 4" CUB(4));
|
||||
_delay_ms(5000);
|
||||
|
||||
clearDisplay();
|
||||
writeStringToLCD("Backwards 3" CUB(3));
|
||||
_delay_ms(5000);
|
||||
|
||||
clearDisplay();
|
||||
writeStringToLCD("Backwards 2" CUB(2));
|
||||
_delay_ms(5000);
|
||||
|
||||
clearDisplay();
|
||||
writeStringToLCD("Backwards 1" CUB(1));
|
||||
_delay_ms(5000);
|
||||
|
||||
clearDisplay();
|
||||
writeStringToLCD("Forwards 4" CUF(4));
|
||||
_delay_ms(5000);
|
||||
|
||||
/* writeStringToLCD(CNL(1)); */
|
||||
/* _delay_ms(5000); */
|
||||
|
||||
/* writeStringToLCD(CUF(10)); */
|
||||
/* _delay_ms(5000); */
|
||||
|
||||
/* writeStringToLCD(CPL(1)); */
|
||||
/* _delay_ms(5000); */
|
||||
|
||||
/* writeStringToLCD(CHA(20)); */
|
||||
/* _delay_ms(5000); */
|
||||
|
||||
/* writeStringToLCD(CUP(20,20)); */
|
||||
/* _delay_ms(5000); */
|
||||
|
||||
/* writeStringToLCD(CUP(1,1)); */
|
||||
/* _delay_ms(5000); */
|
||||
|
||||
|
||||
while (1) {
|
||||
serialChar = receiveByte();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user