2021-01-29 06:31:58 -05:00
|
|
|
//
|
|
|
|
// FILE: SHEX.cpp
|
|
|
|
// AUTHOR: Rob Tillaart
|
2022-11-24 06:47:19 -05:00
|
|
|
// VERSION: 0.3.1
|
2021-01-29 06:31:58 -05:00
|
|
|
// PURPOSE: Arduino library to generate hex dump over Serial
|
|
|
|
// DATE: 2020-05-24
|
|
|
|
// URL: https://github.com/RobTillaart/SHEX
|
|
|
|
|
|
|
|
|
|
|
|
#include "SHEX.h"
|
|
|
|
|
|
|
|
|
2021-12-28 05:19:54 -05:00
|
|
|
SHEX::SHEX(Print* stream, uint8_t length)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2021-12-28 05:19:54 -05:00
|
|
|
_stream = stream;
|
2021-01-29 06:31:58 -05:00
|
|
|
reset();
|
|
|
|
// force multiple of 4; max 32
|
2021-12-28 05:19:54 -05:00
|
|
|
_length = ((length + 3) / 4) * 4;
|
2022-05-27 04:43:49 -04:00
|
|
|
if (_length > SHEX_MAX_LENGTH)
|
|
|
|
{
|
|
|
|
_length = SHEX_MAX_LENGTH;
|
|
|
|
}
|
2022-05-31 11:39:54 -04:00
|
|
|
if (_length < SHEX_MIN_LENGTH)
|
|
|
|
{
|
|
|
|
_length = SHEX_MIN_LENGTH;
|
|
|
|
}
|
2021-01-29 06:31:58 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void SHEX::reset()
|
|
|
|
{
|
2022-05-31 11:39:54 -04:00
|
|
|
_hexOutput = true;
|
2022-05-27 04:43:49 -04:00
|
|
|
_length = SHEX_DEFAULT_LENGTH;
|
2021-01-29 06:31:58 -05:00
|
|
|
_charCount = 0;
|
|
|
|
_separator = ' ';
|
2022-05-31 11:39:54 -04:00
|
|
|
_digits = SHEX_COUNTER_DIGITS;
|
2022-05-28 05:28:52 -04:00
|
|
|
_vtab = SHEX_DEFAULT_VTAB;
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////
|
|
|
|
//
|
2022-11-24 06:47:19 -05:00
|
|
|
// WRITE - the core
|
2021-01-29 06:31:58 -05:00
|
|
|
//
|
|
|
|
size_t SHEX::write(uint8_t c)
|
|
|
|
{
|
2022-05-31 11:39:54 -04:00
|
|
|
// PASS THROUGH MODE
|
2021-01-29 06:31:58 -05:00
|
|
|
if (_hexOutput == false) return _stream->write(c);
|
|
|
|
|
2022-05-31 11:39:54 -04:00
|
|
|
// HEX MODE
|
|
|
|
// handle end of line and position number
|
2021-01-29 06:31:58 -05:00
|
|
|
if ((_charCount % _length) == 0)
|
|
|
|
{
|
2022-05-31 11:39:54 -04:00
|
|
|
// insert ASCII array here
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
_stream->println();
|
2022-05-31 11:39:54 -04:00
|
|
|
// separator line every _vtab (default 8) lines
|
2022-05-28 05:28:52 -04:00
|
|
|
if ((_charCount % (_length * _vtab)) == 0)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
|
|
|
_stream->println();
|
|
|
|
}
|
|
|
|
|
2022-05-31 11:39:54 -04:00
|
|
|
// next line
|
|
|
|
if (_digits > 0)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2022-05-31 11:39:54 -04:00
|
|
|
uint32_t mask = 0xF000;
|
|
|
|
if (_digits > 4) mask = 0xF00000;
|
|
|
|
if (_digits > 6) mask = 0xF0000000;
|
2021-01-29 06:31:58 -05:00
|
|
|
while((mask > 0xF) && (mask & _charCount) == 0)
|
|
|
|
{
|
|
|
|
_stream->print('0');
|
|
|
|
mask >>= 4;
|
|
|
|
}
|
|
|
|
_stream->print(_charCount, HEX);
|
|
|
|
_stream->print('\t');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-31 11:39:54 -04:00
|
|
|
// Print char as HEX
|
2021-01-29 06:31:58 -05:00
|
|
|
if (c < 0x10) _stream->print('0');
|
|
|
|
_stream->print(c, HEX);
|
|
|
|
_stream->print(_separator);
|
|
|
|
_charCount++;
|
|
|
|
if ((_charCount % 4) == 0) _stream->print(_separator);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SHEX::setHEX(bool hexOutput)
|
|
|
|
{
|
|
|
|
_hexOutput = hexOutput;
|
2022-05-31 11:39:54 -04:00
|
|
|
restartOutput();
|
2021-01-29 06:31:58 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-12-28 05:19:54 -05:00
|
|
|
void SHEX::setBytesPerLine(const uint8_t length)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2022-11-24 06:47:19 -05:00
|
|
|
// force multiple of 4; max 32
|
2021-12-28 05:19:54 -05:00
|
|
|
_length = ((length + 3) / 4) * 4;
|
2022-05-27 04:43:49 -04:00
|
|
|
if (_length > SHEX_MAX_LENGTH)
|
|
|
|
{
|
|
|
|
_length = SHEX_MAX_LENGTH;
|
|
|
|
}
|
2022-05-31 11:39:54 -04:00
|
|
|
if (_length < SHEX_MIN_LENGTH)
|
|
|
|
{
|
|
|
|
_length = SHEX_MIN_LENGTH;
|
|
|
|
}
|
|
|
|
restartOutput();
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-05-28 05:28:52 -04:00
|
|
|
void SHEX::setVTAB(uint8_t vtab)
|
|
|
|
{
|
|
|
|
_vtab = vtab;
|
2022-05-31 11:39:54 -04:00
|
|
|
restartOutput();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void SHEX::setCountDigits(uint8_t digits)
|
|
|
|
{
|
|
|
|
_digits = digits;
|
|
|
|
if (_digits == 0) return;
|
|
|
|
if (_digits < 4) _digits = 4;
|
|
|
|
if (_digits > 8) _digits = 8;
|
|
|
|
restartOutput();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void SHEX::restartOutput()
|
|
|
|
{
|
2022-05-28 05:28:52 -04:00
|
|
|
// prevent change in middle of line
|
2022-05-31 11:39:54 -04:00
|
|
|
_charCount = 0;
|
2022-05-28 05:28:52 -04:00
|
|
|
_stream->println();
|
2022-05-31 11:39:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// SHEXA
|
|
|
|
//
|
|
|
|
SHEXA::SHEXA(Print* stream, uint8_t length) : SHEX(stream, length)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
size_t SHEXA::write(uint8_t c)
|
|
|
|
{
|
2022-11-24 06:47:19 -05:00
|
|
|
// PASS THROUGH MODE
|
2022-05-31 11:39:54 -04:00
|
|
|
if (_hexOutput == false) return _stream->write(c);
|
|
|
|
|
|
|
|
// HEX MODE
|
|
|
|
// handle end of line and position number
|
|
|
|
if ((_charCount % _length) == 0)
|
|
|
|
{
|
|
|
|
// printable ASCII column
|
|
|
|
if (_charCount != 0) flushASCII();
|
2022-05-28 05:28:52 -04:00
|
|
|
|
2022-05-31 11:39:54 -04:00
|
|
|
_stream->println();
|
|
|
|
// separator line every _vtab (default 8) lines
|
|
|
|
if ((_charCount % (_length * _vtab)) == 0)
|
|
|
|
{
|
|
|
|
_stream->println();
|
|
|
|
}
|
|
|
|
|
|
|
|
// next line
|
|
|
|
if (_digits > 0)
|
|
|
|
{
|
|
|
|
uint32_t mask = 0xF000;
|
|
|
|
if (_digits > 4) mask = 0xF00000;
|
|
|
|
if (_digits > 6) mask = 0xF0000000;
|
|
|
|
while((mask > 0xF) && (mask & _charCount) == 0)
|
|
|
|
{
|
|
|
|
_stream->print('0');
|
|
|
|
mask >>= 4;
|
|
|
|
}
|
|
|
|
_stream->print(_charCount, HEX);
|
|
|
|
_stream->print('\t');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Print char as HEX
|
|
|
|
if (c < 0x10) _stream->print('0');
|
|
|
|
_stream->print(c, HEX);
|
|
|
|
_stream->print(_separator);
|
|
|
|
|
|
|
|
// Store in _txtbuf
|
|
|
|
_txtbuf[_charCount % _length] = isPrintable(c) ? c : '.';
|
|
|
|
|
|
|
|
_charCount++;
|
|
|
|
if ((_charCount % 4) == 0) _stream->print(_separator);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SHEXA::flushASCII()
|
|
|
|
{
|
|
|
|
int len = _charCount % _length;
|
|
|
|
if (len == 0) len = _length;
|
|
|
|
// else print about (_length - len) * 3 of spaces ...
|
|
|
|
for (uint8_t i = 0; i < len;)
|
|
|
|
{
|
|
|
|
_stream->write(_txtbuf[i++]);
|
|
|
|
if ((i % 8) == 0)_stream->print(" ");
|
|
|
|
}
|
|
|
|
}
|
2022-05-28 05:28:52 -04:00
|
|
|
|
2022-11-24 06:47:19 -05:00
|
|
|
|
|
|
|
// -- END OF FILE --
|
2021-12-28 05:19:54 -05:00
|
|
|
|