0.1.2 Fletcher

This commit is contained in:
rob tillaart 2022-01-27 10:11:25 +01:00
parent b55e305e59
commit 6eccb2f585
19 changed files with 823 additions and 11 deletions

View File

@ -2,7 +2,7 @@
//
// FILE: Fletcher.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.1
// VERSION: 0.1.2
// DATE: 2022-01-25
// PURPOSE: Arduino Library for calculating Fletcher's checksum
// URL: https://github.com/RobTillaart/Fletcher
@ -11,12 +11,13 @@
// HISTORY
// 0.1.0 2022-01-25 initial version, straightforward implementation
// 0.1.1 2022-01-26 optimize % math variation based upon to Anastase Nakassis (wikipedia)
// 0.1.2 2022-01-26 add class implementation e.g. for streaming
#include "Arduino.h"
#define FLETCHER_LIB_VERSION (F("0.1.1"))
#define FLETCHER_LIB_VERSION (F("0.1.2"))
#define FLETCHER_16 255
#define FLETCHER_32 65535UL

View File

@ -0,0 +1,47 @@
//
// FILE: Fletcher16.cpp
// AUTHOR: Rob Tillaart
// PURPOSE: Arduino class for Fletcher16
// URL: https://github.com/RobTillaart/Fletcher
#include "Fletcher16.h"
#define FLETCHER_16 255
Fletcher16::Fletcher16()
{
begin();
}
void Fletcher16::begin(uint8_t s1, uint8_t s2)
{
_s1 = s1;
_s2 = s2;
_count = 0;
}
void Fletcher16::add(uint8_t value)
{
_count++;
_s1 += value;
if (_s1 >= FLETCHER_16) _s1 -= FLETCHER_16;
_s2 += _s1;
if (_s2 >= FLETCHER_16) _s2 -= FLETCHER_16;
}
void Fletcher16::add(const uint8_t * array, uint16_t length)
{
while (length--)
{
add(*array++);
}
}
// -- END OF FILE --

View File

@ -0,0 +1,34 @@
#pragma once
//
// FILE: Fletcher16.h
// AUTHOR: Rob Tillaart
// PURPOSE: Arduino class for Fletcher16
// URL: https://github.com/RobTillaart/Fletcher
#include "Arduino.h"
class Fletcher16
{
public:
Fletcher16();
// set parameters to default
void begin(uint8_t s1 = 0, uint8_t s2 = 0);
void add(uint8_t value);
void add(const uint8_t * array, uint16_t length);
uint16_t getFletcher() { return (_s2 << 8) | _s1; };
uint32_t count() { return _count; };
private:
uint16_t _s1;
uint16_t _s2;
uint32_t _count;
};
// -- END OF FILE --

View File

@ -0,0 +1,49 @@
//
// FILE: Fletcher32.cpp
// AUTHOR: Rob Tillaart
// PURPOSE: Arduino class for Fletcher32
// URL: https://github.com/RobTillaart/Fletcher
#include "Fletcher32.h"
#define FLETCHER_32 65535UL
Fletcher32::Fletcher32()
{
begin();
}
void Fletcher32::begin(uint16_t s1, uint16_t s2)
{
_s1 = s1;
_s2 = s2;
_count = 0;
}
void Fletcher32::add(uint16_t value)
{
_count++;
_s1 += value;
if (_s1 >= FLETCHER_32) _s1 -= FLETCHER_32;
_s2 += _s1;
if (_s2 >= FLETCHER_32) _s2 -= FLETCHER_32;
}
// NOTE: padding with zero's error
//
void Fletcher32::add(const uint16_t * array, uint16_t length)
{
while (length--)
{
add(*array++);
}
}
// -- END OF FILE --

View File

@ -0,0 +1,34 @@
#pragma once
//
// FILE: Fletcher32.h
// AUTHOR: Rob Tillaart
// PURPOSE: Arduino class for Fletcher32
// URL: https://github.com/RobTillaart/Fletcher
#include "Arduino.h"
class Fletcher32
{
public:
Fletcher32();
// set parameters to default
void begin(uint16_t s1 = 0, uint16_t s2 = 0);
void add(uint16_t value);
void add(const uint16_t * array, uint16_t length);
uint32_t getFletcher() { return (_s2 << 16) | _s1; };
uint32_t count() { return _count; };
private:
uint32_t _s1;
uint32_t _s2;
uint32_t _count;
};
// -- END OF FILE --

View File

@ -0,0 +1,48 @@
//
// FILE: Fletcher64.cpp
// AUTHOR: Rob Tillaart
// PURPOSE: Arduino class for Fletcher32
// URL: https://github.com/RobTillaart/Fletcher
#include "Fletcher64.h"
#define FLETCHER_64 4294967295ULL
Fletcher64::Fletcher64()
{
begin();
}
void Fletcher64::begin(uint32_t s1, uint32_t s2)
{
_s1 = s1;
_s2 = s2;
_count = 0;
}
void Fletcher64::add(uint32_t value)
{
_count++;
_s1 += value;
if (_s1 >= FLETCHER_64) _s1 -= FLETCHER_64;
_s2 += _s1;
if (_s2 >= FLETCHER_64) _s2 -= FLETCHER_64;
}
void Fletcher64::add(const uint32_t * array, uint16_t length)
{
while (length--)
{
add(*array++);
}
}
// -- END OF FILE --

View File

@ -0,0 +1,34 @@
#pragma once
//
// FILE: Fletcher64.h
// AUTHOR: Rob Tillaart
// PURPOSE: Arduino class for Fletcher64
// URL: https://github.com/RobTillaart/Fletcher
#include "Arduino.h"
class Fletcher64
{
public:
Fletcher64();
// set parameters to default
void begin(uint32_t s1 = 0, uint32_t s2 = 0);
void add(uint32_t value);
void add(const uint32_t * array, uint16_t length);
uint64_t getFletcher() { return (_s2 << 32) | _s1; };
uint32_t count() { return _count; };
private:
uint64_t _s1;
uint64_t _s2;
uint32_t _count;
};
// -- END OF FILE --

View File

@ -28,16 +28,68 @@ Tested on Arduino UNO only.
## Interface
## Fletcher16
These interfaces are very similar for Fletcher16, Fletcher32 and Fletcher64 class.
Use **\#include "Fletcher16.h"**
- **Fletcher16()** Constructor, initializes internals.
- **void begin(uint8_t s1 = 0, uint8_t s2 = 0)** resets the internals.
optional setting start values for s1 and s2. Note this is not part of the standard.
- **void add(uint8_t value)** add a single value to the checksum.
- **void add(const uint8_t \* array, uint8_t length)** add an array of values to the checksum.
- **uint16_t getFletcher()** get the current checksum.
- **uint32_t count()** get the number of items added. Merely a debugging feature, can overflow without affecting checksum.
The checksum from **getFletcher()** can be split into a high and a low part
to be used to "feed" **begin()** again. See restart example.
#### Performance
Not tested ESP32 (and many other platforms) yet.
First numbers of **.add(value)** measured with test sketch shows the following timing.
| Checksum | UNO 16 MHz | ESP32 240 MHz |
|:------------|:-----------:|:-------------:|
| Fletcher16 | 3.8 us | |
| Fletcher32 | 5.6 us | |
| Fletcher64 | 10.1 us | |
| Average | 6.5 us | |
## Interface static functions
The functions are straightforward, however one should define **length**
in terms of the data type and optional pad it with zeros.
A string "abcdef" has length 2 for **fletcher64()** as it needs 2x4 bytes.
Use **\#include "Fletcher.h"**
- **uint16_t fletcher16(uint8_t \*data, uint16_t length)** length in units of 1 byte = 8 bits.
- **uint32_t fletcher32(uint16_t \*data, uint16_t length)** length in units of 2 bytes = 16 bits.
- **uint64_t fletcher64(uint32_t \*data, uint16_t length)** length in units of 4 bytes = 32 bits.
TODO - class version.
#### Performance
Not tested extensively, first numbers of **.add(array, length)**
measured with **Fletcher_performance.ino** sketch shows the following timing.
Lorem Ipsum text = 868 bytes.
| Checksum | UNO 16 MHz | ESP32 240 MHz |
|:------------|:-----------:|:-------------:|
| Fletcher16 | 1120 us | |
| Fletcher32 | 728 us | |
| Fletcher64 | 1952 us | |
| Average | 1267 us | |
Average 1267 / 868 = ~1.5 us per byte.
## Operation
@ -49,9 +101,13 @@ See examples.
- improve documentation
- test other platforms
- Class versions
- incremental calculate e.g. for a stream.
- similar to CRC classes
- Fletcher24 ? and others?
- others e.g. Fletcher24?
- generic FletcherN(). for N = 1..32
- add Print interface
- or Printable() ?
- Stream ??
- add getters for S1 and S2 in the classes
- add parameter for start values for F in static functions
- would allow to use them in a stream too.

View File

@ -0,0 +1,37 @@
//
// FILE: Fletcher16_echo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: echo's Fletcher checksum after every character.
#include "Arduino.h"
#include "Fletcher16.h"
Fletcher16 fl;
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Fletcher16_echo");
fl.begin();
}
void loop()
{
if (Serial.available())
{
uint8_t c = Serial.read();
fl.add(c);
Serial.print(c);
Serial.print("\t");
Serial.println(fl.getFletcher());
}
}
// -- END OF FILE --

View File

@ -0,0 +1,59 @@
//
// FILE: Fletcher16_performance.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Fletcher16.h"
#include "printHelpers.h" // https://github.com/RobTillaart/printHelpers
Fletcher16 fl;
volatile uint8_t z;
uint32_t start, stop, randomtime;
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Fletcher16_performance");
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
}
stop = micros();
randomtime = stop - start;
Serial.print("randomtime: ");
Serial.println(randomtime);
delay(100);
fl.begin();
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
fl.add(z);
}
stop = micros();
Serial.print(" total: ");
Serial.println(stop - start);
Serial.print(" 1e4 x add: ");
Serial.println(stop - start - randomtime);
delay(100);
Serial.print(" checksum: ");
Serial.println(fl.getFletcher());
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,58 @@
//
// FILE: Fletcher16_restart.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Fletcher16.h"
#include "printHelpers.h" // https://github.com/RobTillaart/printHelpers
// expected output
// Fletcher16_restart
// 51440
// 51440
// 8279
// 8279
// 1575
// 1575
Fletcher16 fl;
char str[32] = "abcdefghijklmnopqrstuvwxyz";
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Fletcher16_restart");
Serial.println("\n add array 0..4");
fl.begin();
fl.add((uint8_t *)str, 5);
uint16_t x = fl.getFletcher();
Serial.println(x);
Serial.println("\n add array 5..9");
fl.add((uint8_t *)&str[5], 5);
Serial.println(fl.getFletcher());
Serial.println("\n array 0..9");
fl.begin();
fl.add((uint8_t *)str, 10);
Serial.println(fl.getFletcher());
Serial.println("\nrestart from position 5");
fl.begin(x & 0xFF, x >> 8); // split into s1 and s2;
fl.add((uint8_t *)&str[5], 5);
Serial.println(fl.getFletcher());
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,65 @@
//
// FILE: Fletcher16_test.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Fletcher16.h"
#include "printHelpers.h" // https://github.com/RobTillaart/printHelpers
// expected output
// Fletcher16_test
// 51440
// 51440
// 8279
// 8279
// 1575
// 1575
Fletcher16 fl;
char str1[24] = "abcde";
char str2[24] = "abcdef";
char str3[24] = "abcdefgh";
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Fletcher16_test");
fl.begin();
fl.add((uint8_t *)str1, 5);
Serial.println(fl.getFletcher());
fl.begin();
for (int i = 0; i < 5; i++) fl.add((uint8_t)str1[i]);
Serial.println(fl.getFletcher());
fl.begin();
fl.add((uint8_t *)str2, 6);
Serial.println(fl.getFletcher());
fl.begin();
for (int i = 0; i < 6; i++) fl.add((uint8_t)str2[i]);
Serial.println(fl.getFletcher());
fl.begin();
fl.add((uint8_t *)str3, 8);
Serial.println(fl.getFletcher());
fl.begin();
for (int i = 0; i < 8; i++) fl.add((uint8_t)str3[i]);
Serial.println(fl.getFletcher());
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,59 @@
//
// FILE: Fletcher32_performance.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Fletcher32.h"
#include "printHelpers.h" // https://github.com/RobTillaart/printHelpers
Fletcher32 fl;
volatile uint8_t z;
uint32_t start, stop, randomtime;
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Fletcher32_performance");
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
}
stop = micros();
randomtime = stop - start;
Serial.print("randomtime: ");
Serial.println(randomtime);
delay(100);
fl.begin();
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
fl.add(z);
}
stop = micros();
Serial.print(" total: ");
Serial.println(stop - start);
Serial.print(" 1e4 x add: ");
Serial.println(stop - start - randomtime);
delay(100);
Serial.print(" checksum: ");
Serial.println(fl.getFletcher());
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,81 @@
//
// FILE: Fletcher32_test.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Fletcher32.h"
#include "printHelpers.h" // https://github.com/RobTillaart/printHelpers
// expected output
// Fletcher32_test
// 4031760169
// 4031760169
// 116654705
// 116654705
// 116982386
// 116982386
// 116720242
// 116720242
Fletcher32 fl;
char str1[24] = "abcde";
uint16_t arr1[5] = { 100, 120, 130, 135, 140 };
uint16_t arr2[5] = { 101, 120, 130, 135, 140 }; // minimal diff.
uint16_t arr3[5] = { 100, 120, 130, 135, 141 }; // minimal diff.
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Fletcher32_test");
fl.begin();
fl.add((uint16_t *)str1, 3);
Serial.println(fl.getFletcher());
// Note adding per byte element is tricky
fl.begin();
fl.add((uint16_t)((str1[1] << 8) + str1[0])); // note order dependency
fl.add((uint16_t)((str1[3] << 8) + str1[2]));
fl.add((uint16_t)( 0 + str1[4]));
Serial.println(fl.getFletcher());
//////////////////////////////////////////////////
fl.begin();
fl.add(arr1, 5);
Serial.println(fl.getFletcher());
fl.begin();
for (int i = 0; i < 5; i++) fl.add(arr1[i]);
Serial.println(fl.getFletcher());
fl.begin();
fl.add(arr2, 5);
Serial.println(fl.getFletcher());
fl.begin();
for (int i = 0; i < 5; i++) fl.add(arr2[i]);
Serial.println(fl.getFletcher());
fl.begin();
fl.add(arr3, 5);
Serial.println(fl.getFletcher());
fl.begin();
for (int i = 0; i < 5; i++) fl.add(arr3[i]);
Serial.println(fl.getFletcher());
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,59 @@
//
// FILE: Fletcher64_performance.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Fletcher64.h"
#include "printHelpers.h" // https://github.com/RobTillaart/printHelpers
Fletcher64 fl;
volatile uint8_t z;
uint32_t start, stop, randomtime;
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Fletcher64_performance");
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
}
stop = micros();
randomtime = stop - start;
Serial.print("randomtime: ");
Serial.println(randomtime);
delay(100);
fl.begin();
start = micros();
for (uint16_t x = 0; x < 10000; x++)
{
z = random(255);
fl.add(z);
}
stop = micros();
Serial.print(" total: ");
Serial.println(stop - start);
Serial.print(" 1e4 x add: ");
Serial.println(stop - start - randomtime);
delay(100);
Serial.print(" checksum: ");
Serial.println(print64(fl.getFletcher()));
}
void loop()
{
}
// -- END OF FILE --

View File

@ -0,0 +1,88 @@
//
// FILE: Fletcher64_test.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
#include "Arduino.h"
#include "Fletcher64.h"
#include "printHelpers.h" // https://github.com/RobTillaart/printHelpers
// expected output
// Fletcher64_test
// 14467467625952928454
// 14467467625952928454
// 7645041787505
// 7645041787505
// 7666516623986
// 7666516623986
// 7649336754802
// 7649336754802
Fletcher64 fl;
char str1[24] = "abcde";
uint32_t arr1[5] = { 100, 120, 130, 135, 140 };
uint32_t arr2[5] = { 101, 120, 130, 135, 140 }; // minimal diff.
uint32_t arr3[5] = { 100, 120, 130, 135, 141 }; // minimal diff.
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println();
Serial.println("Fletcher64_test");
fl.begin();
fl.add((uint32_t *)str1, 2);
Serial.println(print64(fl.getFletcher()));
// Note adding per byte element is tricky => order dependency
fl.begin();
uint32_t t = str1[3];
t <<= 8;
t += str1[2];
t <<= 8;
t += str1[1];
t <<= 8;
t += str1[0];
fl.add(t);
fl.add(str1[4]);
Serial.println(print64(fl.getFletcher()));
//////////////////////////////////////////////////
fl.begin();
fl.add(arr1, 5);
Serial.println(print64(fl.getFletcher()));
fl.begin();
for (int i = 0; i < 5; i++) fl.add(arr1[i]);
Serial.println(print64(fl.getFletcher()));
fl.begin();
fl.add(arr2, 5);
Serial.println(print64(fl.getFletcher()));
fl.begin();
for (int i = 0; i < 5; i++) fl.add(arr2[i]);
Serial.println(print64(fl.getFletcher()));
fl.begin();
fl.add(arr3, 5);
Serial.println(print64(fl.getFletcher()));
fl.begin();
for (int i = 0; i < 5; i++) fl.add(arr3[i]);
Serial.println(print64(fl.getFletcher()));
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,7 +1,10 @@
# Syntax Colouring Map For FLETCHER
# Data types (KEYWORD1)
Fletcher KEYWORD1
Fletcher16 KEYWORD1
Fletcher32 KEYWORD1
Fletcher64 KEYWORD1
# Methods and Functions (KEYWORD2)
fletcher16 KEYWORD2

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/Fletcher.git"
},
"version": "0.1.1",
"version": "0.1.2",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=Fletcher
version=0.1.1
version=0.1.2
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence="Arduino Library for calculating Fletcher's checksum.
@ -7,5 +7,5 @@ paragraph=
category=Signal Input/Output
url=https://github.com/RobTillaart/Fletcher
architectures=*
includes=Fletcher.h
includes=Fletcher.h,Fletcher16.h,Fletcher32.h,Fletcher64.h
depends=