Skip to content

Commit fdb321e

Browse files
committed
0.3.0 SHEX
1 parent 2e0ef7f commit fdb321e

File tree

10 files changed

+356
-84
lines changed

10 files changed

+356
-84
lines changed

libraries/SHEX/README.md

Lines changed: 92 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,18 @@ Arduino library to generate hex dump over Serial (any stream).
1313

1414
## Description
1515

16-
SHEX is a simple library that wraps the Serial output side (by default) and
16+
### SHEX
17+
18+
**SHEX** is a simple library that wraps the Serial output side (by default) and
1719
generates an hex dump of all data that is printed. 16 bytes per row.
1820

19-
The default output format is
21+
The default output format is (changed since 0.3.0)
2022
```
21-
0xABCDABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
22-
0xABCDABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
23-
0xABCDABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
23+
ABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
24+
ABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
25+
ABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
2426
25-
0xABCDABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
27+
ABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
2628
```
2729
with a separator line after each 8th line.
2830

@@ -35,38 +37,92 @@ This makes it possible to switch between the modes e.g. between 'debugging' and
3537
One can toggle the character count at the start of the line.
3638

3739

40+
### SHEXA
41+
42+
**SHEXA** (Serial HEX Ascii) is a derived class from **SHEX** that also
43+
displays a column with printable characters.
44+
45+
46+
The default output format is
47+
```
48+
ABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx abcdefgh ijklmnop
49+
ABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx abcdefgh ijklmnop
50+
ABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx abcdefgh ijklmnop
51+
52+
ABCD xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
53+
```
54+
55+
To print this ASCII column extra RAM and code is used.
56+
Therefore this is made a derived class from **SHEX**.
57+
58+
Furthermore **SHEXA** has a function **flushASCII()** to flush the ASCII column to output.
59+
This is might be needed when HEX output is restarted.
60+
61+
3862
## Interface
3963

64+
The **SHEX** and **SHEXA** share most of their interface.
65+
4066
### Defines
4167

4268
To be adjusted via command line (or in SHEX.h file)
4369

44-
- **SHEX_DEFAULT_LENGTH 16**
45-
- **SHEX_MAX_LENGTH 32**
70+
- **SHEX_DEFAULT_LENGTH 16**
71+
- **SHEX_MAX_LENGTH 32**
72+
- **SHEX_MIN_LENGTH 4**
73+
- **SHEX_COUNTER_DIGITS 4**
74+
- **SHEX_DEFAULT_VTAB 8**
4675

4776

4877
### Constructor + Core
4978

50-
- **SHEX(Print \* stream = &Serial, uint8_t length = SHEX_DEFAULT_LENGTH)** Constructor, optional set the number of bytes per line.
79+
- **SHEX(Print \* stream = &Serial, uint8_t length = SHEX_DEFAULT_LENGTH)** Constructor,
80+
optional set the number of bytes per line.
5181
default 16 bytes per line, forced multiple of 4, max SHEX_MAX_LENGTH = 32.
5282
- **size_t write(uint8_t c)** implements the Print interface.
5383

5484

55-
### Modifiers
85+
### Output Modifiers
5686

5787
- **void setHEX(bool hexOutput = true)** switch between modi, HEX (true) or pass through (false).
5888
- **bool getHEX()** returns mode set above.
59-
- **void setBytesPerLine(uint8_t length = SHEX_DEFAULT_LENGTH)** idem, default 16 bytes per line, forced multiple of 4, max SHEX_MAX_LENGTH = 32.
89+
- **void setBytesPerLine(uint8_t length = SHEX_DEFAULT_LENGTH)** idem, default 16 bytes per line,
90+
forced multiple of 4, max SHEX_MAX_LENGTH = 32.
6091
- **uint8_t getBytesPerLine()** returns number of bytes per line.
92+
93+
94+
### Separator
95+
6196
- **void setSeparator(char c = ' ')** set the separator character, default a space.
6297
Some people like a dot '.', or a tab '\t'. Feel free to experiment.
6398
- **char getSeparator()** return the separator character set.
64-
- **void setCountFlag(bool flag = true)** show the character count at begin of every line.
65-
- **bool getCountFlag()** return flag set.
99+
100+
101+
### Counter
102+
103+
- **void setCountDigits(uint8_t digits)** set the length of the counter, 8 or 6 or 4 (default).
104+
Other numbers will be rounded up to 4, 6 or 8.
105+
- **uint8_t getCountDigits()** returns idem.
106+
- **void restartOutput()** restarts the counter from 0 and a new line.
107+
Is automatically called if a setting is modified like **bytesPerLine**
108+
**setVTAB** or **setCountDigits**
109+
- **uint32_t getCounter()** return internal counter.
110+
111+
112+
### VTAB
113+
66114
- **void setVTAB(uint8_t vtab = SHEX_DEFAULT_VTAB)** set the vertical separator line.
67115
- **uint8_t getVTAB()** return the current vertical separator line.
68116

69117

118+
### SHEXA specific
119+
120+
- **void flushASCII()** allows the user to flush the ASCII column to output.
121+
This is typically used after a setting is changed, which causes a restart of
122+
the HEX output. Best if followed by a **restartOutput()**.
123+
_Note: it is not ideal but workable. This might change in the future._
124+
125+
70126
## Operational
71127

72128
See examples.
@@ -77,19 +133,29 @@ See examples.
77133
Although no follow up release is planned, some ideas are kept here
78134
so they won't get lost.
79135

80-
- Optional ASCII column in the output format ( . if not printable) e.g.
81-
```
82-
0xABCDABCD xx xx xx xx xx xx xx xx xx c.cc c..c
83-
```
84-
needs a line buffer to do that (double loop)
136+
### Must
85137

86-
- line buffering for faster output (e.g Ethernet and SD card)
87-
could it support **write(array, length)** call ?
88-
- header line: runtime configurable; optional combined with separator
89-
and after how many lines the header should repeat)
90-
**header(str, lines)**; ???
91-
- HEX reader: converts dump format to a normal stream again.
92-
- better name for the class? - streamHex
93-
- **showByteCount(bool)** is a better name than **setCountFlag()**
138+
- optimize code
139+
- print vs write
140+
- more testing
141+
- performance measurement
142+
- different platforms.
143+
- different streams incl SW Serial
144+
145+
### Could
94146

147+
- investigate **flushASCII()** for better solutions.
148+
- HEX reader: **RHEX** converts dump format to a normal stream again.
149+
- separate library.
95150

151+
### Wont
152+
153+
- line buffering for faster output (e.g Ethernet and SD card)
154+
could it support **write(array, length)** call.
155+
needs quite a rewrite..
156+
Needs a big buffer: ~150 bytes. (counter 8 + hex 96 + printable 32 + extra sep)
157+
- header line: runtime configurable;
158+
optional combined with separator
159+
and after how many lines the header should repeat
160+
**header(str, lines)** ?
161+
Can also be done by just calling Serial.print.

libraries/SHEX/SHEX.cpp

Lines changed: 124 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// FILE: SHEX.cpp
33
// AUTHOR: Rob Tillaart
4-
// VERSION: 0.2.3
4+
// VERSION: 0.3.0
55
// PURPOSE: Arduino library to generate hex dump over Serial
66
// DATE: 2020-05-24
77
// URL: https://github.com/RobTillaart/SHEX
@@ -13,8 +13,17 @@
1313
// 0.2.1 2021-12-28 update library.json, readme, license, minor edits
1414
// 0.2.2 2022-05-27 fix #6 set default length
1515
// add defines SHEX_DEFAULT_LENGTH + SHEX_MAX_LENGTH
16-
// 0.2.3 2022-5-28 add setVTAB(vtab) getVTAB()
16+
// 0.2.3 2022-05-28 add setVTAB(vtab) getVTAB()
1717
// add define SHEX_DEFAULT_VTAB
18+
// 0.3.0 2022-05-28 breaking!
19+
// change default HEX output instead of pass through.
20+
// add get / setCountDigits() =>
21+
// #digits of count 4, 6 or 8 (4 = default)
22+
// replaces get / setCounterFlag()
23+
// add define SHEX_COUNTER_DIGITS + SHEX_MIN_LENGTH
24+
// add restartOutput() and getCounter()
25+
// add SHEXA class for ASCII column output
26+
// add SHEXA::flushASCII().
1827

1928

2029
#include "SHEX.h"
@@ -30,16 +39,20 @@ SHEX::SHEX(Print* stream, uint8_t length)
3039
{
3140
_length = SHEX_MAX_LENGTH;
3241
}
42+
if (_length < SHEX_MIN_LENGTH)
43+
{
44+
_length = SHEX_MIN_LENGTH;
45+
}
3346
};
3447

3548

3649
void SHEX::reset()
3750
{
38-
_hexOutput = false;
51+
_hexOutput = true;
3952
_length = SHEX_DEFAULT_LENGTH;
4053
_charCount = 0;
4154
_separator = ' ';
42-
_countFlag = true;
55+
_digits = SHEX_COUNTER_DIGITS;
4356
_vtab = SHEX_DEFAULT_VTAB;
4457
}
4558

@@ -50,24 +63,28 @@ void SHEX::reset()
5063
//
5164
size_t SHEX::write(uint8_t c)
5265
{
53-
// PASS THROUGH MODE
66+
// PASS THROUGH MODE
5467
if (_hexOutput == false) return _stream->write(c);
5568

56-
// HEX MODE
57-
// handle end of line and position number
69+
// HEX MODE
70+
// handle end of line and position number
5871
if ((_charCount % _length) == 0)
5972
{
73+
// insert ASCII array here
74+
6075
_stream->println();
61-
// separator line every _vtab lines
76+
// separator line every _vtab (default 8) lines
6277
if ((_charCount % (_length * _vtab)) == 0)
6378
{
6479
_stream->println();
6580
}
6681

67-
// next line
68-
if (_countFlag)
82+
// next line
83+
if (_digits > 0)
6984
{
70-
uint32_t mask = 0xF0000000;
85+
uint32_t mask = 0xF000;
86+
if (_digits > 4) mask = 0xF00000;
87+
if (_digits > 6) mask = 0xF0000000;
7188
while((mask > 0xF) && (mask & _charCount) == 0)
7289
{
7390
_stream->print('0');
@@ -78,7 +95,7 @@ size_t SHEX::write(uint8_t c)
7895
}
7996
}
8097

81-
// Print char as HEX
98+
// Print char as HEX
8299
if (c < 0x10) _stream->print('0');
83100
_stream->print(c, HEX);
84101
_stream->print(_separator);
@@ -92,9 +109,7 @@ size_t SHEX::write(uint8_t c)
92109
void SHEX::setHEX(bool hexOutput)
93110
{
94111
_hexOutput = hexOutput;
95-
_charCount = 0;
96-
// prevent change in middle of line
97-
_stream->println();
112+
restartOutput();
98113
};
99114

100115

@@ -106,20 +121,109 @@ void SHEX::setBytesPerLine(const uint8_t length)
106121
{
107122
_length = SHEX_MAX_LENGTH;
108123
}
109-
_charCount = 0;
110-
// prevent change in middle of line
111-
_stream->println();
124+
if (_length < SHEX_MIN_LENGTH)
125+
{
126+
_length = SHEX_MIN_LENGTH;
127+
}
128+
restartOutput();
112129
}
113130

114131

115132
void SHEX::setVTAB(uint8_t vtab)
116133
{
117134
_vtab = vtab;
118-
_charCount = 0;
135+
restartOutput();
136+
};
137+
138+
139+
void SHEX::setCountDigits(uint8_t digits)
140+
{
141+
_digits = digits;
142+
if (_digits == 0) return;
143+
if (_digits < 4) _digits = 4;
144+
if (_digits > 8) _digits = 8;
145+
restartOutput();
146+
};
147+
148+
149+
void SHEX::restartOutput()
150+
{
119151
// prevent change in middle of line
152+
_charCount = 0;
120153
_stream->println();
121-
};
154+
}
155+
156+
157+
///////////////////////////////////////////////////
158+
//
159+
// SHEXA
160+
//
161+
SHEXA::SHEXA(Print* stream, uint8_t length) : SHEX(stream, length)
162+
{
163+
}
164+
165+
166+
size_t SHEXA::write(uint8_t c)
167+
{
168+
// PASS THROUGH MODE
169+
if (_hexOutput == false) return _stream->write(c);
170+
171+
// HEX MODE
172+
// handle end of line and position number
173+
if ((_charCount % _length) == 0)
174+
{
175+
// printable ASCII column
176+
if (_charCount != 0) flushASCII();
122177

178+
_stream->println();
179+
// separator line every _vtab (default 8) lines
180+
if ((_charCount % (_length * _vtab)) == 0)
181+
{
182+
_stream->println();
183+
}
184+
185+
// next line
186+
if (_digits > 0)
187+
{
188+
uint32_t mask = 0xF000;
189+
if (_digits > 4) mask = 0xF00000;
190+
if (_digits > 6) mask = 0xF0000000;
191+
while((mask > 0xF) && (mask & _charCount) == 0)
192+
{
193+
_stream->print('0');
194+
mask >>= 4;
195+
}
196+
_stream->print(_charCount, HEX);
197+
_stream->print('\t');
198+
}
199+
}
200+
201+
// Print char as HEX
202+
if (c < 0x10) _stream->print('0');
203+
_stream->print(c, HEX);
204+
_stream->print(_separator);
205+
206+
// Store in _txtbuf
207+
_txtbuf[_charCount % _length] = isPrintable(c) ? c : '.';
208+
209+
_charCount++;
210+
if ((_charCount % 4) == 0) _stream->print(_separator);
211+
212+
return 1;
213+
}
214+
215+
216+
void SHEXA::flushASCII()
217+
{
218+
int len = _charCount % _length;
219+
if (len == 0) len = _length;
220+
// else print about (_length - len) * 3 of spaces ...
221+
for (uint8_t i = 0; i < len;)
222+
{
223+
_stream->write(_txtbuf[i++]);
224+
if ((i % 8) == 0)_stream->print(" ");
225+
}
226+
}
123227

124228
// -- END OF FILE --
125229

0 commit comments

Comments
 (0)