Skip to content

Commit

Permalink
refactor getScreenSize() (#18)
Browse files Browse the repository at this point in the history
- fix missing 0 in normal (#19, Kudos to d0m1n1qu3)
- fix basic escape strings write length (normal, bold etc  eating one char).
- add **getScreenSize()** (#16, Kudos to chlordk)
- add **readCursorPosition()** (#16, Kudos to chlordk)
- add example, (#16, Kudos to chlordk)
- add **screenWidth()** call getScreenSize() before use
- add **screenHeight()** call getScreenSize() before use
- refactor **deviceType()** size.
- add **blinkFast()**
- update readme.md
- update keywords.txt
  • Loading branch information
RobTillaart committed Nov 11, 2023
1 parent c9aa711 commit bf27f1c
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 73 deletions.
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,27 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## [0.3.0] - 2023-11-09
- fix missing 0 in normal (#19, Kudos to d0m1n1qu3)
- fix basic escape strings write length (normal, bold etc eating one char).
- add **getScreenSize()** (#16, Kudos to chlordk)
- add **readCursorPosition()** (#16, Kudos to chlordk)
- add example, (#16, Kudos to chlordk)
- add **screenWidth()** call getScreenSize() before use
- add **screenHeight()** call getScreenSize() before use
- refactor **deviceType()** size.
- add **blinkFast()**
- update readme.md
- update keywords.txt

----

## [0.2.1] - 2023-10-17
- update readme.md (badges)
- fix version in ansi.cpp
- add a derived VT100 class (wrapper for now).
- minor edits


## [0.2.0] - 2023-02-26
- fix #13 gotoXY(column, row)
- add ansi_gotoXY example.
Expand Down
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,14 @@ Stream interface also includes print(), println(), write().

#### Character modi

Most of these are supported (more or less) in terminal apps.

- **void normal()** normal intensity.
- **void bold()** bold or high intensity.
- **void low()** low intensity.
- **void underline()** idem.
- **void blink()** idem.
- **void blinkFast()** idem.
- **void reverse()** idem.


Expand Down Expand Up @@ -121,7 +124,23 @@ Some are working with Teraterm, others are unclear of fail.
The user can uncomment these and verify if these work with their terminal.


##### Experimental device type
##### Experimental getScreenSize()

Added in 0.2.2 (From PR #16 refactored) use with care.

- **bool readCursorPosition(uint16_t &w, uint16_t &h, uint32_t timeout = 100)**
returns true if width and height are reported.
Be sure to test the return value!
- **bool getScreenSize(uint16_t &w, uint16_t &h, uint32_t timeout = 100)**
returns true if width and height are reported.
Be sure to test the return value!
- **inline uint16_t screenWidth()** used after successful
call of getScreenSize();
- **inline uint16_t screenHeight()** used after successful
call of getScreenSize();


##### Experimental deviceType()

The **int deviceType()** function needs more testing.

Expand Down
107 changes: 70 additions & 37 deletions ansi.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// FILE: ansi.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.1
// VERSION: 0.3.0
// PURPOSE: Arduino library to send ANSI escape sequences
// DATE: 2020-04-28
// URL: https://github.com/RobTillaart/ANSI
Expand Down Expand Up @@ -50,32 +50,37 @@ void ANSI::flush()
//
void ANSI::normal()
{
_stream->write("\033[m", 3);
_stream->write("\033[0m", 4);
}

void ANSI::bold()
{
_stream->write("\033[1m", 3);
_stream->write("\033[1m", 4);
}

void ANSI::low()
{
_stream->write("\033[2m", 3);
_stream->write("\033[2m", 4);
}

void ANSI::underline()
{
_stream->write("\033[4m", 3);
_stream->write("\033[4m", 4);
}

void ANSI::blink()
{
_stream->write("\033[5m", 3);
_stream->write("\033[5m", 4);
}

void ANSI::blinkFast()
{
_stream->write("\033[6m", 4);
}

void ANSI::reverse()
{
_stream->write("\033[7m", 3);
_stream->write("\033[7m", 4);
}


Expand Down Expand Up @@ -202,58 +207,86 @@ int ANSI::deviceType(uint32_t timeout)
int type = -1; // -1 = unknown
print("\033[0c");

char buffer[4];
int len = 0;
char c;
uint32_t start = millis();
int read_len = 0;
char buffer[8];
while ((read_len != 3) && ((millis() - start) < timeout))
while ((len < 3) && ((millis() - start) < timeout))
{
delay(1);
read_len = Serial.readBytes(buffer, 3);
if ((buffer[0] == '1') && (buffer[1] == ';'))
if (_stream->available())
{
type = buffer[2] - '0';
c = _stream->read();
buffer[len++] = c;
buffer[len] = 0;
}
// Serial.write(buffer, 3);
// Serial.println();
}

if ((buffer[0] == '1') && (buffer[1] == ';'))
{
type = buffer[2] - '0';
}
return type;
}

int ANSI::readCursorPosition(struct screen_t *screen, uint32_t timeout)

bool ANSI::readCursorPosition(uint16_t &w, uint16_t &h, uint32_t timeout)
{
print("\033[6n");

Serial.setTimeout(timeout);
String buffer = Serial.readStringUntil('R');
if (buffer.length() < 7) { // 8 = \e[24;80R
return 0;
}
unsigned int number[2];
unsigned char n = 0;
unsigned char i = 0;
while (n < 2) {
number[n] = 0;
while (i < buffer.length() && !isdigit(buffer.charAt(i))) {
++i;
char buffer[16];
int len = 0;
char c;
uint32_t start = millis();
while (millis() - start < timeout)
{
if (_stream->available())
{
c = _stream->read();
buffer[len++] = c;
buffer[len] = 0;
if (c == 'R') break;
}
while (i < buffer.length() && isdigit(buffer.charAt(i))) {
}
// do we have enough chars
// typical (8) = \e[24;80R
// minimal (6) = \e[1;1R
if (len < 6) return false;
// last char must be R to have them all.
if (c != 'R') return false;

// parse the buffer
int number[2] = {0, 0};
int i = 0;
// read digits.
for (int n = 0; n < 2; n++)
{
// skip until digits
while ((i < len) && !isdigit(buffer[i])) i++;
// read number
while ((i < len) && isdigit(buffer[i]))
{
number[n] *= 10;
number[n] += buffer[i] - '0';
++i;
i++;
}
++n;
}
screen->x = number[1];
screen->y = number[0];
return buffer.length();
w = number[1];
h = number[0];
return ((w > 0) && (h > 0));
}

int ANSI::getScreensize(uint32_t timeout)

bool ANSI::getScreenSize(uint16_t &w, uint16_t &h, uint32_t timeout)
{
// gotoXY(9999,9999);
print("\033[9999;9999H");
return readCursorPosition(&screen, timeout);
bool rv = readCursorPosition(w, h, timeout);
_width = w;
_height = h;
return rv;
}


//////////////////////////////////////////////////
//
// PROTECTED
Expand Down
44 changes: 27 additions & 17 deletions ansi.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
//
// FILE: ansi.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.1
// VERSION: 0.3.0
// PURPOSE: Arduino library to send ANSI escape sequences
// DATE: 2020-04-28
// URL: https://github.com/RobTillaart/ANSI


#include "Arduino.h"

#define ANSI_LIB_VERSION (F("0.2.1"))
#define ANSI_LIB_VERSION (F("0.3.0"))


class ANSI : public Stream
Expand All @@ -31,6 +31,7 @@ class ANSI : public Stream
void low();
void underline();
void blink();
void blinkFast();
void reverse();


Expand Down Expand Up @@ -92,25 +93,31 @@ class ANSI : public Stream


// EXPERIMENTAL SECTION
// use at own risk
// META
// deviceType is discussed
// - https://github.com/RobTillaart/ANSI/issues/9
// use at own risk

// TERMINAL TYPE
// - https://github.com/RobTillaart/ANSI/issues/9
// timeout in milliseconds.
// note this function blocks for timeout or less.
// -1 = unknown;
// 1 = VT52, 2 = VT100, 3 = VT220,
enum {
UNKNOWN = -1,
// known types
VT52 = 1,
VT100 = 2,
VT220 = 3,
// add others if needed.
};
int deviceType(uint32_t timeout = 100);

struct screen_t {
uint16_t x;
uint16_t y;
} screen = {
.x = 0,
.y = 0
};
int readCursorPosition(struct screen_t *screen, uint32_t timeout = 100);
int getScreensize(uint32_t timeout = 100);

// SCREENSIZE
// - https://github.com/RobTillaart/ANSI/pull/16
bool readCursorPosition(uint16_t &w, uint16_t &h, uint32_t timeout = 100);
bool getScreenSize(uint16_t &w, uint16_t &h, uint32_t timeout = 100);
// to be used after successful call of getScreenSize();
inline uint16_t screenWidth() { return _width; };
inline uint16_t screenHeight() { return _height; };


// check if it works on your terminal
// TERATERM
Expand Down Expand Up @@ -157,6 +164,9 @@ class ANSI : public Stream

Stream * _stream;

// screen size parameters
uint16_t _width = 0;
uint16_t _height = 0;
};


Expand Down
3 changes: 3 additions & 0 deletions examples/ansiDemo01/ansiDemo01.ino
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ void setup()
Serial.begin(115200);

ansi.clearScreen();
ansi.println("Hello world");
ansi.bold();
ansi.println("Hello world");
ansi.blink();
ansi.println("Hello world");
ansi.blinkFast();
ansi.println("Hello world");
ansi.underline();
ansi.println("Hello world");
ansi.low();
Expand Down
16 changes: 16 additions & 0 deletions examples/ansi_performance/performance_0.3.0.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
IDE: 1.8.19
Board: UNO

ansi_performance.ino
0.3.0

PERFORMANCE TEST ANSI TERMINAL PRINT
ANSITERM: 352
PERFORMANCE TEST ANSI TERMINAL PRINT
SERIAL: 300

(cleaned output of clearScreen(); test)
ANSITERM: 52
SERIAL: 56

done...
Loading

0 comments on commit bf27f1c

Please sign in to comment.