From d13cd04dac9bf975ebd779429e22b9051410fdf8 Mon Sep 17 00:00:00 2001 From: rob tillaart Date: Fri, 27 Nov 2020 11:16:22 +0100 Subject: [PATCH] update libraries E-I --- libraries/FRAM/FRAM.cpp | 102 +++--- libraries/FRAM/FRAM.h | 33 +- libraries/FRAM/LICENSE | 21 ++ libraries/FRAM/README.md | 23 ++ libraries/FRAM/examples/testFRAM/testFRAM.ino | 3 +- .../testFRAMPerformance.ino | 23 +- libraries/FRAM/keywords.txt | 25 +- libraries/FRAM/library.json | 13 +- libraries/FRAM/library.properties | 10 +- libraries/FastMap/FastMap.cpp | 55 ++- libraries/FastMap/FastMap.h | 38 +- libraries/FastMap/LICENSE | 21 ++ .../constrainedMapDemo/constrainedMapDemo.ino | 7 +- .../examples/fastMapDemo/fastMapDemo.ino | 5 +- .../examples/fastMapDemo2/fastMapDemo2.ino | 5 +- .../examples/fastMapDemo3/fastMapDemo3.ino | 6 +- .../examples/fastMapDemo4/fastMapDemo4.ino | 9 +- .../examples/fastMapDouble/fastMapDouble.ino | 66 ++++ libraries/FastMap/keywords..txt | 15 + libraries/FastMap/library.json | 9 +- libraries/FastMap/library.properties | 8 +- libraries/FastMap/readme.md | 62 +++- libraries/FastShiftIn/FastShiftIn.cpp | 135 +++++--- libraries/FastShiftIn/FastShiftIn.h | 44 +-- libraries/FastShiftIn/LICENSE | 21 ++ .../fastShiftIn_readLSBFIRST.ino | 77 +++++ .../fastShiftIn_readMSBFIRST.ino | 77 +++++ .../fastShiftIn_test/fastShiftIn_test.ino | 147 ++++++++ libraries/FastShiftIn/library.json | 13 +- libraries/FastShiftIn/library.properties | 12 +- libraries/FastShiftIn/performance.txt | 119 +++++++ libraries/FastShiftIn/readme.md | 43 ++- .../FastShiftOut_test/FastShiftOut_test.ino | 119 +++++++ libraries/FastShiftOut/FastShiftOut.cpp | 172 +++++---- libraries/FastShiftOut/FastShiftOut.h | 43 +-- libraries/FastShiftOut/LICENSE | 21 ++ libraries/FastShiftOut/PerformanceNotes.txt | 179 ++++++++++ libraries/FastShiftOut/README.md | 48 +++ libraries/FastShiftOut/library.json | 13 +- libraries/FastShiftOut/library.properties | 10 +- libraries/Fraction/LICENSE | 21 ++ .../FractionFindSum/FractionFindSum.ino | 12 +- .../FractionMediant/FractionMediant.ino | 108 ++++++ .../fractionExerciser/fractionExerciser.ino | 8 +- .../fractionTest01/fractionTest01.ino | 12 +- libraries/Fraction/fraction.cpp | 225 ++++-------- libraries/Fraction/fraction.h | 23 +- libraries/Fraction/keywords..txt | 18 + libraries/Fraction/library.json | 13 +- libraries/Fraction/library.properties | 12 +- libraries/Fraction/readme.md | 24 +- .../FunctionGenerator/FunctionGenerator.h | 327 +++--------------- libraries/FunctionGenerator/LICENSE | 21 ++ .../functionGenerator/functionGenerator.ino | 48 ++- .../functionGeneratorDuoPlot.ino | 47 +++ .../functionGeneratorPerformance.ino | 136 ++++++-- .../functionGeneratorPlotter.ino | 46 +++ .../FunctionGenerator/functionGenerator.cpp | 300 ++++++++++++++++ libraries/FunctionGenerator/keywords.txt | 28 ++ libraries/FunctionGenerator/library.json | 11 +- .../FunctionGenerator/library.properties | 10 +- libraries/FunctionGenerator/readme.md | 44 ++- libraries/HT16K33/HT16K33.cpp | 122 +++++-- libraries/HT16K33/HT16K33.h | 35 +- libraries/HT16K33/README.md | 83 +++-- libraries/HT16K33/examples/demo1/demo1.ino | 55 ++- .../HT16K33/examples/demo_VU/demo_VU.ino | 136 ++++++++ .../examples/demo_cache/demo_cache.ino | 73 ++++ .../demo_displayInt/demo_displayInt.ino | 78 +++++ .../demo_displayRaw/demo_displayRaw.ino | 82 +++++ .../demo_displayTime/demo_displayTime.ino | 42 +++ .../examples/demo_dual1/demo_dual1.ino | 37 +- .../test_printfloat/test_printfloat.ino | 8 +- libraries/HT16K33/keywords.txt | 7 + libraries/HT16K33/library.json | 2 +- libraries/HT16K33/library.properties | 2 +- libraries/Histogram/LICENSE | 21 ++ libraries/Histogram/histogram.cpp | 10 +- libraries/Histogram/histogram.h | 20 +- libraries/Histogram/keywords.txt | 8 - libraries/Histogram/library.json | 11 +- libraries/Histogram/library.properties | 10 +- libraries/Histogram/readme.md | 7 +- libraries/I2C_EEPROM/I2C_eeprom.cpp | 266 +++++++------- libraries/I2C_EEPROM/I2C_eeprom.h | 65 ++-- libraries/I2C_EEPROM/LICENSE | 21 ++ .../examples/I2C_eeprom_test/new 2.txt | 128 +++++++ .../I2C_small_eeprom_test.ino | 22 +- libraries/I2C_EEPROM/keywords.txt | 24 +- libraries/I2C_EEPROM/library.json | 11 +- libraries/I2C_EEPROM/library.properties | 8 +- libraries/I2C_EEPROM/readme.md | 29 ++ libraries/IEEE754tools/IEEE754tools.h | 64 ++-- libraries/IEEE754tools/LICENSE | 21 ++ .../examples/FastNegate/FastNegate.ino | 172 +++++++++ .../examples/float2double/float2double.ino | 93 +++++ libraries/IEEE754tools/library.json | 11 +- libraries/IEEE754tools/library.properties | 10 +- libraries/IEEE754tools/readme.md | 34 +- libraries/hmc6352/LICENSE | 21 ++ libraries/hmc6352/README.md | 18 + .../continuousDemo/continuousDemo.ino | 49 ++- .../examples/hmc6352Config/hmc6352Config.ino | 154 ++++----- .../hmc6352/examples/queryDemo/queryDemo.ino | 39 ++- .../set2continuous/set2continuous.ino | 47 +-- .../hmc6352/examples/set2query/set2query.ino | 49 +-- .../examples/set2standby/set2standby.ino | 47 +-- .../examples/standbyDemo/standbyDemo.ino | 34 +- libraries/hmc6352/hmc6352.cpp | 91 ++--- libraries/hmc6352/hmc6352.h | 58 ++-- libraries/hmc6352/keywords.txt | 34 ++ libraries/hmc6352/library.json | 11 +- libraries/hmc6352/library.properties | 12 +- 113 files changed, 4239 insertions(+), 1599 deletions(-) create mode 100644 libraries/FRAM/LICENSE create mode 100644 libraries/FRAM/README.md create mode 100644 libraries/FastMap/LICENSE create mode 100644 libraries/FastMap/examples/fastMapDouble/fastMapDouble.ino create mode 100644 libraries/FastMap/keywords..txt create mode 100644 libraries/FastShiftIn/LICENSE create mode 100644 libraries/FastShiftIn/examples/fastShiftIn_readLSBFIRST/fastShiftIn_readLSBFIRST.ino create mode 100644 libraries/FastShiftIn/examples/fastShiftIn_readMSBFIRST/fastShiftIn_readMSBFIRST.ino create mode 100644 libraries/FastShiftIn/examples/fastShiftIn_test/fastShiftIn_test.ino create mode 100644 libraries/FastShiftIn/performance.txt create mode 100644 libraries/FastShiftOut/Examples/FastShiftOut_test/FastShiftOut_test.ino create mode 100644 libraries/FastShiftOut/LICENSE create mode 100644 libraries/FastShiftOut/PerformanceNotes.txt create mode 100644 libraries/FastShiftOut/README.md create mode 100644 libraries/Fraction/LICENSE create mode 100644 libraries/Fraction/examples/FractionMediant/FractionMediant.ino create mode 100644 libraries/Fraction/keywords..txt create mode 100644 libraries/FunctionGenerator/LICENSE create mode 100644 libraries/FunctionGenerator/examples/functionGeneratorDuoPlot/functionGeneratorDuoPlot.ino create mode 100644 libraries/FunctionGenerator/examples/functionGeneratorPlotter/functionGeneratorPlotter.ino create mode 100644 libraries/FunctionGenerator/functionGenerator.cpp create mode 100644 libraries/FunctionGenerator/keywords.txt create mode 100644 libraries/HT16K33/examples/demo_VU/demo_VU.ino create mode 100644 libraries/HT16K33/examples/demo_cache/demo_cache.ino create mode 100644 libraries/HT16K33/examples/demo_displayInt/demo_displayInt.ino create mode 100644 libraries/HT16K33/examples/demo_displayRaw/demo_displayRaw.ino create mode 100644 libraries/HT16K33/examples/demo_displayTime/demo_displayTime.ino create mode 100644 libraries/Histogram/LICENSE create mode 100644 libraries/I2C_EEPROM/LICENSE create mode 100644 libraries/I2C_EEPROM/examples/I2C_eeprom_test/new 2.txt create mode 100644 libraries/IEEE754tools/LICENSE create mode 100644 libraries/IEEE754tools/examples/FastNegate/FastNegate.ino create mode 100644 libraries/IEEE754tools/examples/float2double/float2double.ino create mode 100644 libraries/hmc6352/LICENSE create mode 100644 libraries/hmc6352/README.md create mode 100644 libraries/hmc6352/keywords.txt diff --git a/libraries/FRAM/FRAM.cpp b/libraries/FRAM/FRAM.cpp index 40d91df2..d7bdf830 100644 --- a/libraries/FRAM/FRAM.cpp +++ b/libraries/FRAM/FRAM.cpp @@ -1,17 +1,20 @@ // // FILE: FRAM.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 -// PURPOSE: Class for FRAM memory -// URL: +// VERSION: 0.2.1 +// DATE: 2018-01-24 +// PURPOSE: Arduino library for I2C FRAM +// URL: https://github.com/RobTillaart/FRAM_I2C // // HISTORY: -// 0.1.0 initial version -// 0.1.1 added suppport for Fujitsu 64Kbit MB85RC64T (kudos ysoyipek) +// 0.1.0 2018-01-24 initial version +// 0.1.1 2019-07-31 added suppport for Fujitsu 64Kbit MB85RC64T (kudos ysoyipek) +// 0.2.0 2020-04-30 refactor, add writeProtectPin code +// 0.2.1 2020-06-10 fix library.json #include "FRAM.h" -#define FRAM_SLAVE_ID_ 0x7C +const uint8_t FRAM_SLAVE_ID_= 0x7C; ///////////////////////////////////////////////////// // @@ -20,7 +23,7 @@ FRAM::FRAM() {} -int FRAM::begin(int address = 0X50) +int FRAM::begin(uint8_t address, int8_t writeProtectPin) { if (address < 0x50 || address > 0x57) { @@ -30,18 +33,11 @@ int FRAM::begin(int address = 0X50) _address = address; Wire.begin(); - uint16_t mid = getManufacturerID(); - uint16_t pid = getProductID(); - _size = 0; // UNKNOWN - if (mid == 0x000A) // fujitsu + if (writeProtectPin > -1) { - // note pid's are from fujitsu SIZE TYPE - if (pid == 0x0358) _size = 8; // 8KB MB85RC64T - if (pid == 0x0510) _size = 32; // 32KB MB85RC256V - if (pid == 0x0658) _size = 64; // 64KB MB85RC512T - if (pid == 0x0758) _size = 128; // 128KB MB85RC1MT + _writeProtectPin = writeProtectPin; + pinMode(_writeProtectPin, OUTPUT); } - return FRAM_OK; } @@ -104,7 +100,7 @@ uint32_t FRAM::read32(uint16_t memaddr) void FRAM::read(uint16_t memaddr, uint8_t * obj, uint16_t size) { - const int blocksize = 24; + const uint8_t blocksize = 24; uint8_t * p = obj; while (size >= blocksize) { @@ -113,44 +109,70 @@ void FRAM::read(uint16_t memaddr, uint8_t * obj, uint16_t size) p += blocksize; size -= blocksize; } + // remainder if (size > 0) { readBlock(memaddr, p, size); } } +bool FRAM::setWriteProtect(bool b) +{ + if (_writeProtectPin == -1) return false; + digitalWrite(_writeProtectPin, b ? HIGH : LOW); + return true; +} + uint16_t FRAM::getManufacturerID() { - uint16_t value = 0; - Wire.beginTransmission(FRAM_SLAVE_ID_); - Wire.write(_address << 1); - Wire.endTransmission(false); - int x = Wire.requestFrom(FRAM_SLAVE_ID_, 2); - if (x != 2) return -1; - value = Wire.read() << 4; - value |= Wire.read() >> 4; - return value; + return getMetaData(0); } uint16_t FRAM::getProductID() { - uint16_t value = 0; - Wire.beginTransmission(FRAM_SLAVE_ID_); - Wire.write(_address << 1); - Wire.endTransmission(false); - int x = Wire.requestFrom(FRAM_SLAVE_ID_, 3); - if (x != 3) return -1; - Wire.read(); - value = (Wire.read() & 0x0F) << 8; - value |= Wire.read(); - return value; + return getMetaData(1); +} + +uint16_t FRAM::getSize() +{ + uint16_t val = getMetaData(2); // density bits + if (val > 0) return 1 << val; + return 0; } /////////////////////////////////////////////////////////// // // PRIVATE // -void FRAM::writeBlock(uint16_t memaddr, uint8_t * obj, uint16_t size) + +// metadata is packed as [....MMMM][MMMMDDDD][PPPPPPPP] +// M = manufacturerID +// D = density => memsize = 2^D KB +// P = product ID (together with D) +uint16_t FRAM::getMetaData(uint8_t field) +{ + if (field > 2) return 0; + + Wire.beginTransmission(FRAM_SLAVE_ID_); + Wire.write(_address << 1); + Wire.endTransmission(false); + int x = Wire.requestFrom(FRAM_SLAVE_ID_, (uint8_t)3); + if (x != 3) return -1; + + uint32_t value = 0; + value = Wire.read(); + value |= Wire.read(); + value |= Wire.read(); + // MANUFACTURER + if (field == 0) return (value >> 12) & 0xFF; + // PRODUCT ID + if (field == 1) return value & 0x0FFF; + // DENSITY + if (field == 2) return (value >> 8) & 0x0F; + return 0; +} + +void FRAM::writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size) { // TODO constrain size < 30 ?? Wire.beginTransmission(_address); @@ -164,7 +186,7 @@ void FRAM::writeBlock(uint16_t memaddr, uint8_t * obj, uint16_t size) Wire.endTransmission(); } -void FRAM::readBlock(uint16_t memaddr, uint8_t * obj, uint16_t size) +void FRAM::readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size) { Wire.beginTransmission(_address); Wire.write(memaddr >> 8); @@ -178,4 +200,4 @@ void FRAM::readBlock(uint16_t memaddr, uint8_t * obj, uint16_t size) } } -// END OF FILE +// -- END OF FILE -- diff --git a/libraries/FRAM/FRAM.h b/libraries/FRAM/FRAM.h index 1fa5ab11..5ea5c373 100644 --- a/libraries/FRAM/FRAM.h +++ b/libraries/FRAM/FRAM.h @@ -1,21 +1,20 @@ +#pragma once // // FILE: FRAM.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 -// PURPOSE: Class for FRAM memory -// URL: +// VERSION: 0.2.1 +// DATE: 2018-01-24 +// PURPOSE: Arduino library for I2C FRAM +// URL: https://github.com/RobTillaart/FRAM_I2C // // HISTORY: // see FRAM.cpp file // -#ifndef FRAM_H -#define FRAM_H - #include "Arduino.h" #include "Wire.h" -#define FRAM_LIB_VERSION (F("0.1.1")) +#define FRAM_LIB_VERSION (F("0.2.1")) #define FRAM_OK 0 #define FRAM_ERROR_ADDR -10 @@ -25,7 +24,8 @@ class FRAM public: FRAM(); - int begin(const int address); // defaults to 0x50 + // writeProtectPin is optional + int begin(const uint8_t address = 0x50, int8_t writeProtectPin = -1); void write8(uint16_t memaddr, uint8_t value); void write16(uint16_t memaddr, uint16_t value); @@ -37,18 +37,19 @@ public: uint32_t read32(uint16_t memaddr); void read(uint16_t memaddr, uint8_t * obj, uint16_t size); + bool setWriteProtect(bool b); + uint16_t getManufacturerID(); uint16_t getProductID(); - uint16_t getSize() { return _size; }; + uint16_t getSize(); private: - int8_t _address; - uint16_t _size; // unknown + uint8_t _address; + int8_t _writeProtectPin = -1; // default no pin ==> no write protect. - void writeBlock(uint16_t memaddr, uint8_t * obj, uint16_t size); - void readBlock(uint16_t memaddr, uint8_t * obj, uint16_t size); + uint16_t getMetaData(uint8_t id); + void writeBlock(uint16_t memaddr, uint8_t * obj, uint8_t size); + void readBlock(uint16_t memaddr, uint8_t * obj, uint8_t size); }; -#endif - -// END OF FILE \ No newline at end of file +// -- END OF FILE -- diff --git a/libraries/FRAM/LICENSE b/libraries/FRAM/LICENSE new file mode 100644 index 00000000..a1f64de6 --- /dev/null +++ b/libraries/FRAM/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/FRAM/README.md b/libraries/FRAM/README.md new file mode 100644 index 00000000..1c4046f7 --- /dev/null +++ b/libraries/FRAM/README.md @@ -0,0 +1,23 @@ +# FRAM_I2C + +Arduino library for I2C FRAM + +# Description + +FRAM is a library to read and write (over I2C) to an FRAM module. +FRAM is much faster than EEPROM and almost as fast as Arduino UNO RAM. +Another imaportant feature is that FRAM keeps its content after a reboot (non-volatile) + +Types of FRAM it should work with + +| SIZE | TYPE | +|:---:|:---:| +| 8KB | MB85RC64T | +| 32KB | MB85RC256V | +| 64KB | MB85RC512T | +| 128KB | MB85RC1MT | + + +# Operational + + See examples \ No newline at end of file diff --git a/libraries/FRAM/examples/testFRAM/testFRAM.ino b/libraries/FRAM/examples/testFRAM/testFRAM.ino index f80297b4..125324ca 100644 --- a/libraries/FRAM/examples/testFRAM/testFRAM.ino +++ b/libraries/FRAM/examples/testFRAM/testFRAM.ino @@ -3,7 +3,7 @@ // AUTHOR: Rob Tillaart // VERSION: 0.1.0 // PURPOSE: test for FRAM library for Arduino -// URL: +// URL: https://github.com/RobTillaart/FRAM_I2C // // Released to the public domain // @@ -171,7 +171,6 @@ void testReadWriteLarge() Serial.println(); } - void testWriteText() { char str[10][20] = diff --git a/libraries/FRAM/examples/testFRAMPerformance/testFRAMPerformance.ino b/libraries/FRAM/examples/testFRAMPerformance/testFRAMPerformance.ino index dde2912a..6640e0d8 100644 --- a/libraries/FRAM/examples/testFRAMPerformance/testFRAMPerformance.ino +++ b/libraries/FRAM/examples/testFRAMPerformance/testFRAMPerformance.ino @@ -3,9 +3,7 @@ // AUTHOR: Rob Tillaart // VERSION: 0.1.0 // PURPOSE: test for FRAM library for Arduino -// URL: -// -// Released to the public domain +// URL: https://github.com/RobTillaart/FRAM_I2C // #include "FRAM.h" @@ -15,6 +13,8 @@ FRAM fram; uint32_t start; uint32_t stop; +int ar[600]; + void setup() { Serial.begin(115200); @@ -55,30 +55,31 @@ void testReadWriteLarge() Serial.println(); Serial.println(__FUNCTION__); - uint8_t ar[100]; - for (int i = 0; i < 100; i++) ar[i] = i; + for (int i = 0; i < 600; i++) ar[i] = i; start = millis(); - fram.write(1000, ar, 100); + fram.write(1000, (uint8_t*)ar, 1200); stop = millis(); - Serial.print("WRITE 100 bytes TIME:\t"); + Serial.print("WRITE 1200 bytes TIME:\t"); Serial.print(stop - start); Serial.println(" ms"); - for (int i = 0; i < 100; i++) ar[i] = 0; + for (int i = 0; i < 600; i++) ar[i] = 0; start = millis(); - fram.read(1000, ar, 100); + fram.read(1000, (uint8_t*)ar, 1200); stop = millis(); - Serial.print("READ 100 bytes TIME:\t"); + Serial.print("READ 1200 bytes TIME:\t"); Serial.print(stop - start); Serial.println(" ms"); - for (int i = 0; i < 100; i++) + for (int i = 0; i < 600; i++) { if (ar[i] != i) { Serial.print("FAIL: \t"); + Serial.print(ar[i]); + Serial.print('\t'); Serial.println(i); } } diff --git a/libraries/FRAM/keywords.txt b/libraries/FRAM/keywords.txt index a225893a..568ba65d 100644 --- a/libraries/FRAM/keywords.txt +++ b/libraries/FRAM/keywords.txt @@ -1,22 +1,25 @@ -####################################### # Syntax Coloring Map for FRAM -####################################### -####################################### # Datatypes (KEYWORD1) -####################################### - FRAM KEYWORD1 -####################################### # Methods and Functions (KEYWORD2) -####################################### +begin KEYWORD2 + +write8 KEYWORD2 +write16 KEYWORD2 +write32 KEYWORD2 +write KEYWORD2 + +read8 KEYWORD2 +read16 KEYWORD2 +read32 KEYWORD2 +read KEYWORD2 getManufacturerID KEYWORD2 getProductID KEYWORD2 +getSize KEYWORD2 -####################################### # Constants (LITERAL1) -####################################### - -unknown LITERAL1 +FRAM_OK LITERAL1 +FRAM_ERROR_ADDR LITERAL1 diff --git a/libraries/FRAM/library.json b/libraries/FRAM/library.json index 11a29c4b..85af57c8 100644 --- a/libraries/FRAM/library.json +++ b/libraries/FRAM/library.json @@ -1,6 +1,6 @@ { - "name": "FRAM", - "keywords": "FRAM,storage", + "name": "FRAM_I2C", + "keywords": "FRAM, storage", "description": "Library for FRAM for Arduino.", "authors": [ @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/FRAM_I2C.git" }, - "version":"0.1.1", + "version":"0.2.1", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/FRAM" - } + "platforms": "*" } diff --git a/libraries/FRAM/library.properties b/libraries/FRAM/library.properties index 1f7298fe..e5fbab5c 100644 --- a/libraries/FRAM/library.properties +++ b/libraries/FRAM/library.properties @@ -1,9 +1,11 @@ -name=FRAM -version=0.1.1 +name=FRAM_I2C +version=0.2.1 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Library for FRAM for Arduino. +sentence=Arduino library for I2C FRAM. paragraph= category=Data Storage -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ +url=https://github.com/RobTillaart/FRAM_I2C.git architectures=* +includes=Wire.h,FRAM.h +depends=Wire.h diff --git a/libraries/FastMap/FastMap.cpp b/libraries/FastMap/FastMap.cpp index 16396be8..937af29e 100644 --- a/libraries/FastMap/FastMap.cpp +++ b/libraries/FastMap/FastMap.cpp @@ -1,14 +1,19 @@ // // FILE: FastMap.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.8 +// VERSION: 0.3.1 // PURPOSE: class with fast map function - library for Arduino -// URL: http://forum.arduino.cc/index.php?topic=276194 +// URL: https://github.com/RobTillaart/FastMap // // HISTORY: +// 0.3.1 2020-08-31 updated documentation +// 0.3.0 2020-07-04 added fastMapDouble + test sketch. +// 0.2.1 2020-06-10 fix library.json; rename license +// 0.2.0 2020-03-21 #pragma once; readme.md; license.md +// // 0.1.8 2017-07-27 revert double to float (issue 33) // 0.1.7 2017-04-28 cleaned up, get examples working again -// 0.1.06 2015-03-08 replaced float by float (support ARM) +// 0.1.06 2015-03-08 replaced float by double (support ARM) // 0.1.05 2014-11-02 stripped of bit mask experimental code // 0.1.04 add back() - the inverse map // tested with bit mask for constrain code (Perfomance was killed) @@ -20,10 +25,6 @@ #include "FastMap.h" -///////////////////////////////////////////////////// -// -// PUBLIC -// FastMap::FastMap() { init(0, 1, 0, 1); @@ -62,4 +63,42 @@ float FastMap::upperConstrainedMap(float value) return this->map(value); } -// END OF FILE \ No newline at end of file +FastMapDouble::FastMapDouble() +{ + init(0, 1, 0, 1); +} + +void FastMapDouble::init(double in_min, double in_max, double out_min, double out_max) +{ + _in_min = in_min; + _in_max = in_max; + _out_min = out_min; + _out_max = out_max; + + _factor = (out_max - out_min)/(in_max - in_min); + _base = out_min - in_min * _factor; + + _backfactor = 1/_factor; + _backbase = in_min - out_min * _backfactor; +} + +double FastMapDouble::constrainedMap(double value) +{ + if (value <= _in_min) return _out_min; + if (value >= _in_max) return _out_max; + return this->map(value); +} + +double FastMapDouble::lowerConstrainedMap(double value) +{ + if (value <= _in_min) return _out_min; + return this->map(value); +} + +double FastMapDouble::upperConstrainedMap(double value) +{ + if (value >= _in_max) return _out_max; + return this->map(value); +} + +// END OF FILE diff --git a/libraries/FastMap/FastMap.h b/libraries/FastMap/FastMap.h index 021efa3a..d48d88d2 100644 --- a/libraries/FastMap/FastMap.h +++ b/libraries/FastMap/FastMap.h @@ -1,24 +1,18 @@ +#pragma once // // FILE: FastMap.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.8 +// VERSION: 0.3.1 // PURPOSE: class with fast map function - library for Arduino -// URL: http://forum.arduino.cc/index.php?topic=276194 +// URL: https://github.com/RobTillaart/FastMap // // HISTORY: // see FastMap.cpp file // -#ifndef FastMap_h -#define FastMap_h - -#if ARDUINO < 100 -#include -#else #include -#endif -#define FASTMAP_LIB_VERSION (F("0.1.8")) +#define FASTMAP_LIB_VERSION (F("0.3.1")) class FastMap { @@ -40,6 +34,26 @@ private: float _backfactor, _backbase; }; -#endif -// END OF FILE \ No newline at end of file +class FastMapDouble +{ +public: + FastMapDouble(); + void init(const double in_min, const double in_max, const double out_min, const double out_max); + + double inline map (const double value) { return _base + value * _factor; } + double inline back (const double value) { return _backbase + value * _backfactor; } + + double constrainedMap(const double value); + double lowerConstrainedMap(const double value); + double upperConstrainedMap(const double value); + +private: + double _in_min, _in_max, _out_min, _out_max; + double _factor, _base; + double _backfactor, _backbase; +}; + + + +// -- END OF FILE -- diff --git a/libraries/FastMap/LICENSE b/libraries/FastMap/LICENSE new file mode 100644 index 00000000..fbd4df5b --- /dev/null +++ b/libraries/FastMap/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2010-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/FastMap/examples/constrainedMapDemo/constrainedMapDemo.ino b/libraries/FastMap/examples/constrainedMapDemo/constrainedMapDemo.ino index a103a750..857b995a 100644 --- a/libraries/FastMap/examples/constrainedMapDemo/constrainedMapDemo.ino +++ b/libraries/FastMap/examples/constrainedMapDemo/constrainedMapDemo.ino @@ -1,13 +1,10 @@ // // FILE: constrainedMap.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.01 +// VERSION: 0.1.1 // PURPOSE: demo of FastMap class ==> merge map and constrain functions // DATE: 2014-11-02 -// URL: -// -// Released to the public domain -// +// URL: https://github.com/RobTillaart/FastMap #include "FastMap.h" diff --git a/libraries/FastMap/examples/fastMapDemo/fastMapDemo.ino b/libraries/FastMap/examples/fastMapDemo/fastMapDemo.ino index d7c3820b..483650c6 100644 --- a/libraries/FastMap/examples/fastMapDemo/fastMapDemo.ino +++ b/libraries/FastMap/examples/fastMapDemo/fastMapDemo.ino @@ -4,10 +4,7 @@ // VERSION: 0.1.02 // PURPOSE: demo of FastMap class ==> a faster map function // DATE: 2014-11-02 -// URL: -// -// Released to the public domain -// +// URL: https://github.com/RobTillaart/FastMap #include "FastMap.h" diff --git a/libraries/FastMap/examples/fastMapDemo2/fastMapDemo2.ino b/libraries/FastMap/examples/fastMapDemo2/fastMapDemo2.ino index f84d850b..3a9bf312 100644 --- a/libraries/FastMap/examples/fastMapDemo2/fastMapDemo2.ino +++ b/libraries/FastMap/examples/fastMapDemo2/fastMapDemo2.ino @@ -4,10 +4,7 @@ // VERSION: 0.1.02 // PURPOSE: demo of FastMap class ==> a faster map function // DATE: 2014-11-02 -// URL: -// -// Released to the public domain -// +// URL: https://github.com/RobTillaart/FastMap #include "FastMap.h" diff --git a/libraries/FastMap/examples/fastMapDemo3/fastMapDemo3.ino b/libraries/FastMap/examples/fastMapDemo3/fastMapDemo3.ino index d4a11d10..7628c41d 100644 --- a/libraries/FastMap/examples/fastMapDemo3/fastMapDemo3.ino +++ b/libraries/FastMap/examples/fastMapDemo3/fastMapDemo3.ino @@ -3,10 +3,8 @@ // VERSION: 0.1.1 // PURPOSE: demo of FastMap class ==> a faster map function // DATE: 2014-11-02 -// URL: http://forum.arduino.cc/index.php?topic=276194 -// -// Released to the public domain -// +// URL: https://github.com/RobTillaart/FastMap +// http://forum.arduino.cc/index.php?topic=276194 #include "FastMap.h" diff --git a/libraries/FastMap/examples/fastMapDemo4/fastMapDemo4.ino b/libraries/FastMap/examples/fastMapDemo4/fastMapDemo4.ino index e83f0d01..38199548 100644 --- a/libraries/FastMap/examples/fastMapDemo4/fastMapDemo4.ino +++ b/libraries/FastMap/examples/fastMapDemo4/fastMapDemo4.ino @@ -1,15 +1,10 @@ // // FILE: fastMapDemo4.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.00 +// VERSION: 0.1.0 // PURPOSE: demo of FastMap class ==> a faster map function // DATE: 2014-11-02 -// URL: -// -// Released to the public domain -// - -// works only with 0.1.04 +// URL: https://github.com/RobTillaart/FastMap #include "FastMap.h" diff --git a/libraries/FastMap/examples/fastMapDouble/fastMapDouble.ino b/libraries/FastMap/examples/fastMapDouble/fastMapDouble.ino new file mode 100644 index 00000000..04f82315 --- /dev/null +++ b/libraries/FastMap/examples/fastMapDouble/fastMapDouble.ino @@ -0,0 +1,66 @@ +// +// FILE: fastMapDouble.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: demo of FastMapDouble class +// DATE: 2020-07-04 +// URL: https://github.com/RobTillaart/FastMap + +// Note: the mapping used in the example cannot be done +// with the normal map function. + + +#include "FastMap.h" + +#include "printHelpers.h" // https://github.com/RobTillaart/printHelpers + +uint32_t start, stop; +volatile double x; + +FastMapDouble mapper; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.print("lib version: "); + Serial.println(FASTMAP_LIB_VERSION); + Serial.println(); + + // Get a non optimizable value; + volatile double pie = PI; + + // FASTMAP + // map 0 .. 100% to lightspeed in km/hr + mapper.init(0, 100, 0, 1.0792528488E+12); + start = micros(); + for (int i = 0; i < 10000; i++) + { + x = mapper.map(pie); + } + stop = micros(); + Serial.print("10000 calls map:\t"); + Serial.print(pie, 5); + Serial.print(" -> "); + Serial.println(sci(x, 5)); + Serial.print(" time:\t"); + Serial.println(stop - start); + Serial.println(); + + Serial.println("PERC\tSpeed in Km/h"); + for (float p = 80; p < 100; p += 0.25) + { + x = mapper.map(p); + Serial.print(p, 2); + Serial.print('\t'); + Serial.print(sci(x, 4)); + Serial.println(); + } + Serial.println("\nDone..."); +} + +void loop() +{ +} + +// -- END OF FILE -- diff --git a/libraries/FastMap/keywords..txt b/libraries/FastMap/keywords..txt new file mode 100644 index 00000000..2ee6da52 --- /dev/null +++ b/libraries/FastMap/keywords..txt @@ -0,0 +1,15 @@ +# Syntax Coloring Map For FastMap + +# Datatypes (KEYWORD1) +FastMap KEYWORD1 +FastMapDouble KEYWORD1 + +# Methods and Functions (KEYWORD2) +map KEYWORD2 +back KEYWORD2 +constrainedMap KEYWORD2 +lowerConstrainedMap KEYWORD2 +upperConstrainedMap KEYWORD2 + +# Constants (LITERAL1) + diff --git a/libraries/FastMap/library.json b/libraries/FastMap/library.json index 868231af..d5cdb1e3 100644 --- a/libraries/FastMap/library.json +++ b/libraries/FastMap/library.json @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/FastMap" }, - "version":"0.1.8", + "version":"0.3.1", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/FastMap" - } + "platforms": "*" } diff --git a/libraries/FastMap/library.properties b/libraries/FastMap/library.properties index ccdf2bae..94939c5c 100644 --- a/libraries/FastMap/library.properties +++ b/libraries/FastMap/library.properties @@ -1,9 +1,11 @@ name=FastMap -version=0.1.8 +version=0.3.1 author=Rob Tillaart maintainer=Rob Tillaart sentence=Library with fast map function for Arduino. paragraph= category=Data Processing -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/FastMap +architectures=* +includes=FastMap.h +depends= \ No newline at end of file diff --git a/libraries/FastMap/readme.md b/libraries/FastMap/readme.md index 13b3865a..3cbf8fdd 100644 --- a/libraries/FastMap/readme.md +++ b/libraries/FastMap/readme.md @@ -1,2 +1,62 @@ +# FastMap -https://github.com/RobTillaart/FastMap +Fast mapping and constraining + +## Description + +FastMap is an object that precalculates (internal) floats to make a mapping function especially for floats. +The Fastmap also provides a **back()** function to reverse the mapping. +This only works well with floats, so use with care. + +An important difference with the traditional **map()** function is that both **init()** and **map()** +accepts floats as parameters, allowing mapping that would be hard to achieve with the normal **map()** +function. + +## Performance notes + +(based upon tests https://github.com/RobTillaart/FastMap/issues/4 ) +- On AVR (UNO and MEGA) no gain is made mapping integers with fastMap, 130% slower = substantial +- On AVR the gain for float is limited, 10% faster +- On ESP32 the gain for integers and float is both in the order of 25% + +To see the actual gain in your project on your hardware you should test and compare. + +FastMap is faster when mapping floats as it uses less float operations than the standard map formula does. +The perfomance results from precalculating values in the **init()** function so actual mapping needs only +one multiply and add, where the standard **map()** function uses four adds, a multiplication and a division. +The precalculation in **init()** should be taken in account and if every **map()** call needs an **init()** +there will be no gain, on contrary. + +The implementation uses floats (typical 32 bits) which might result in more memory usage and loss of precision +for mapping of larger values, especially 32 and 64 bit integers. This is caused by the limits of the mantissa +(~23 bits) of the standard 4 byte float. + +## Interface + +- **void init(in_min, in_max, out_min, out_max);** defines the linear mapping parameters. +The **init()** function calculates all needed values for the **map()**, the **back()** call and the **constrainXX()** functions. +The **init()** function can be called again with new values when needed to do other mapping, +although it will give less overhead if you create an fastMap object per conversion needed. +Note: **init()** does not check for a divide by zero (out_max == out_min) or (in_max == in_min) +- **float map(float value)** maps the parameter. +- **float back(float value)** does the inverse mapping + +FastMap supports three versions of constraining the map function, based upon the parameters of **init()** +- **float constrainedMap(float value);** returns a value between outMin .. outMax +- **float lowerConstrainedMap(float value);** returns a value between outMin .. inf (No upper limit) +- **float upperConstrainedMap(float value);** returns a value between -inf .. outMax + +To change the constrain values call **init()** with new limits, or call **constrain()** + +Note there are **NO** constrain-versions for **back(value)** function. + + +## FastMapDouble + +Version 3.0 adds **fastMapDouble** which has the same interface. +This class is meant to support 8 bytes doubles in their native accuracy and precision. +To display doubles one might need the **sci()** function of my **printHelpers** class. + +## Usage + +See examples. diff --git a/libraries/FastShiftIn/FastShiftIn.cpp b/libraries/FastShiftIn/FastShiftIn.cpp index e3e22d25..aac1c32f 100644 --- a/libraries/FastShiftIn/FastShiftIn.cpp +++ b/libraries/FastShiftIn/FastShiftIn.cpp @@ -1,58 +1,113 @@ // // FILE: FastShiftIn.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.3 -// PURPOSE: shiftin +// VERSION: 0.2.1 +// PURPOSE: Fast ShiftIn for 74HC165 register, AVR optimized // DATE: 2013-09-29 -// URL: -// -// Released to the public domain +// URL: https://github.com/RobTillaart/FastShiftIn // #include "FastShiftIn.h" FastShiftIn::FastShiftIn(const uint8_t datapin, const uint8_t clockpin, const uint8_t bitOrder) { - _bitorder = bitOrder; - _value = FASTSHIFTIN_NOVALUE; + _bitorder = bitOrder; - pinMode(datapin, INPUT); - pinMode(clockpin, INPUT); + pinMode(datapin, INPUT); + pinMode(clockpin, OUTPUT); - // uint8_t _datatimer = digitalPinToTimer(datapin); - // if (_datatimer != NOT_ON_TIMER) turnOffPWM(_datatimer); TODO - uint8_t _dataport = digitalPinToPort(datapin); - _datain = portOutputRegister(_dataport); - _databit = digitalPinToBitMask(datapin); +#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) - // uint8_t _clocktimer = digitalPinToTimer(clockpin); - // if (_clocktimer != NOT_ON_TIMER) turnOffPWM(_clocktimer); - uint8_t _clockport = digitalPinToPort(clockpin); - _clockin = portOutputRegister(_clockport); - _clockbit = digitalPinToBitMask(clockpin); + // uint8_t _datatimer = digitalPinToTimer(datapin); + // if (_datatimer != NOT_ON_TIMER) turnOffPWM(_datatimer); TODO + uint8_t _dataport = digitalPinToPort(datapin); + _datain = portOutputRegister(_dataport); + _databit = digitalPinToBitMask(datapin); + + // uint8_t _clocktimer = digitalPinToTimer(clockpin); + // if (_clocktimer != NOT_ON_TIMER) turnOffPWM(_clocktimer); + uint8_t _clockport = digitalPinToPort(clockpin); + _clockin = portOutputRegister(_clockport); + _clockbit = digitalPinToBitMask(clockpin); + +#else // reference implementation + + // reuse these vars as pin to save some space + _databit = datapin; + _clockbit = clockpin; + +#endif } - int FastShiftIn::read() { - _value = 0; - - for (uint8_t i = 0, m = 1, n = 128; i < 8; i++, m <<=1, n >>= 1) - { - uint8_t oldSREG = SREG; - cli(); - *_clockin |= _clockbit; - - if ((*_datain & _databit) > 0) - { - if (_bitorder == LSBFIRST) - _value |= m; - else - _value |= n; - } - *_clockin &= ~_clockbit; - SREG = oldSREG; - } - return _value; + if (_bitorder == LSBFIRST) + { + return readLSBFIRST(); + } + return readMSBFIRST(); } -// -- END OF FILE -- \ No newline at end of file + +#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) + +int FastShiftIn::readLSBFIRST() +{ + uint8_t value = 0; + uint8_t cbmask1 = _clockbit; + uint8_t cbmask2 = ~_clockbit; + uint8_t dbmask = _databit; + + for (uint8_t m = 1; m > 0; m <<= 1) + { + uint8_t oldSREG = SREG; + cli(); + *_clockin |= cbmask1; + if ((*_datain & dbmask) > 0) + { + value |= m; + } + *_clockin &= cbmask2; + SREG = oldSREG; + } + _value = value; + return _value; +} + +int FastShiftIn::readMSBFIRST() +{ + uint8_t value = 0; + uint8_t cbmask1 = _clockbit; + uint8_t cbmask2 = ~cbmask1; + uint8_t dbmask = _databit; + + for (uint8_t n = 128; n > 0; n >>= 1) + { + uint8_t oldSREG = SREG; + cli(); + *_clockin |= cbmask1; + if ((*_datain & dbmask) > 0) + { + value |= n; + } + *_clockin &= cbmask2; + SREG = oldSREG; + } + _value = value; + return _value; +} + +#else // reference implementation - note this has no cli() + +int FastShiftIn::readLSBFIRST() +{ + return shiftIn(_databit, _clockbit, LSBFIRST); +} + +int FastShiftIn::readMSBFIRST() +{ + return shiftIn(_databit, _clockbit, MSBFIRST); +} + +#endif + +// -- END OF FILE -- diff --git a/libraries/FastShiftIn/FastShiftIn.h b/libraries/FastShiftIn/FastShiftIn.h index 2b163bfe..5832a485 100644 --- a/libraries/FastShiftIn/FastShiftIn.h +++ b/libraries/FastShiftIn/FastShiftIn.h @@ -1,43 +1,37 @@ +#pragma once // // FILE: FastShiftIn.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.3 -// PURPOSE: shiftin +// VERSION: 0.2.1 +// PURPOSE: Fast ShiftIn for 74HC165 register, AVR optimized // DATE: 2013-09-29 -// URL: -// -// Released to the public domain +// URL: https://github.com/RobTillaart/FastShiftIn // -#ifndef FastShiftIn_h -#define FastShiftIn_h - -#if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" -#else -#include "WProgram.h" -#endif -#define FASTSHIFTIN_LIB_VERSION "0.1.3" - -#define FASTSHIFTIN_NOVALUE -1 +#define FASTSHIFTIN_LIB_VERSION (F("0.2.1")) class FastShiftIn { public: - FastShiftIn(const uint8_t, const uint8_t, const uint8_t); - int read(void); + // bitorder = { LSBFIRST, MSBFIRST }; + FastShiftIn(const uint8_t datapin, const uint8_t clockpin, const uint8_t bitOrder = LSBFIRST); + int read(void); + + // overrule bitorder (most optimized). + int readLSBFIRST(void); + int readMSBFIRST(void); private: - uint8_t _bitorder; - int _value; + uint8_t _bitorder; + int _value; - uint8_t _databit; - volatile uint8_t *_datain; + uint8_t _databit; + volatile uint8_t *_datain; - uint8_t _clockbit; - volatile uint8_t *_clockin; + uint8_t _clockbit; + volatile uint8_t *_clockin; }; -#endif -// -- END OF FILE -- \ No newline at end of file +// -- END OF FILE -- diff --git a/libraries/FastShiftIn/LICENSE b/libraries/FastShiftIn/LICENSE new file mode 100644 index 00000000..2fc1cc50 --- /dev/null +++ b/libraries/FastShiftIn/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/FastShiftIn/examples/fastShiftIn_readLSBFIRST/fastShiftIn_readLSBFIRST.ino b/libraries/FastShiftIn/examples/fastShiftIn_readLSBFIRST/fastShiftIn_readLSBFIRST.ino new file mode 100644 index 00000000..7d499036 --- /dev/null +++ b/libraries/FastShiftIn/examples/fastShiftIn_readLSBFIRST/fastShiftIn_readLSBFIRST.ino @@ -0,0 +1,77 @@ +// +// FILE: fastShiftIn_readLSBFIRST.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: test sketch +// URL: https://github.com/RobTillaart/FastShiftIn +// + +#include "FastShiftIn.h" + +FastShiftIn FSI(12, 13); + +volatile int x = 0; + +void setup() +{ + Serial.begin(115200); + Serial.print("example fastShiftIn: "); + Serial.println(FASTSHIFTIN_LIB_VERSION); + + digitalWrite(12, HIGH); + Serial.println("\n 8 bits HIGH - readLSBFIRST\n"); + + Serial.println("\nPerformance - time in us"); + uint32_t start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.readLSBFIRST(); + } + uint32_t duration1 = micros() - start; + Serial.print("FastShiftIn1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.readLSBFIRST(); + x = FSI.readLSBFIRST(); + } + uint32_t duration2 = micros() - start; + Serial.print("FastShiftIn2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = shiftIn(12, 13, LSBFIRST); + } + duration1 = micros() - start; + Serial.print("Standard shiftIn1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = shiftIn(12, 13, LSBFIRST); + x = shiftIn(12, 13, LSBFIRST); + } + duration2 = micros() - start; + Serial.print("Standard shiftIn2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + + Serial.println("done..."); +} + +void loop() +{ +} + +// -- END OF FILE -- diff --git a/libraries/FastShiftIn/examples/fastShiftIn_readMSBFIRST/fastShiftIn_readMSBFIRST.ino b/libraries/FastShiftIn/examples/fastShiftIn_readMSBFIRST/fastShiftIn_readMSBFIRST.ino new file mode 100644 index 00000000..cbff0e5f --- /dev/null +++ b/libraries/FastShiftIn/examples/fastShiftIn_readMSBFIRST/fastShiftIn_readMSBFIRST.ino @@ -0,0 +1,77 @@ +// +// FILE: fastShiftIn_readMSBFIRST.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: test sketch +// URL: https://github.com/RobTillaart/FastShiftIn +// + +#include "FastShiftIn.h" + +FastShiftIn FSI(12, 13); + +volatile int x = 0; + +void setup() +{ + Serial.begin(115200); + Serial.print("example fastShiftIn: "); + Serial.println(FASTSHIFTIN_LIB_VERSION); + + digitalWrite(12, HIGH); + Serial.println("\n 8 bits HIGH\n"); + + Serial.println("\nPerformance - time in us"); + uint32_t start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.readMSBFIRST(); + } + uint32_t duration1 = micros() - start; + Serial.print("FastShiftIn1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.readMSBFIRST(); + x = FSI.readMSBFIRST(); + } + uint32_t duration2 = micros() - start; + Serial.print("FastShiftIn2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = shiftIn(12, 13, MSBFIRST); + } + duration1 = micros() - start; + Serial.print("Standard shiftIn1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = shiftIn(12, 13, MSBFIRST); + x = shiftIn(12, 13, MSBFIRST); + } + duration2 = micros() - start; + Serial.print("Standard shiftIn2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + + Serial.println("done..."); +} + +void loop() +{ +} + +// -- END OF FILE -- diff --git a/libraries/FastShiftIn/examples/fastShiftIn_test/fastShiftIn_test.ino b/libraries/FastShiftIn/examples/fastShiftIn_test/fastShiftIn_test.ino new file mode 100644 index 00000000..8d6ad3a7 --- /dev/null +++ b/libraries/FastShiftIn/examples/fastShiftIn_test/fastShiftIn_test.ino @@ -0,0 +1,147 @@ +// +// FILE: fastShiftIn_test.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: test sketch +// URL: https://github.com/RobTillaart/FastShiftIn +// + +#include "FastShiftIn.h" + +FastShiftIn FSI(12, 13); + +volatile int x = 0; + +uint32_t start, duration1, duration2; + +void setup() +{ + Serial.begin(115200); + Serial.print("example fastShiftIn: "); + Serial.println(FASTSHIFTIN_LIB_VERSION); + + digitalWrite(12, HIGH); + Serial.println("\n 8 bits HIGH\n"); + + Serial.println("\nPerformance - time in us : read()"); + test_read(); + + Serial.println("\nPerformance - time in us : readLSBFIRST()"); + test_readLSBFIRST(); + + Serial.println("\nPerformance - time in us : readMSBFIRST()"); + test_readMSBFIRST(); + + Serial.println("\nPerformance - time in us : reference shiftIn()"); + test_reference(); + + Serial.println("done..."); +} + +void test_read() +{ + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.read(); + } + duration1 = micros() - start; + Serial.print("FastShiftIn1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.read(); + x = FSI.read(); + } + duration2 = micros() - start; + Serial.print("FastShiftIn2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + delay(100); +} + +void test_readLSBFIRST() +{ + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.readLSBFIRST(); + } + duration1 = micros() - start; + Serial.print("FastShiftIn1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.readLSBFIRST(); + x = FSI.readLSBFIRST(); + } + duration2 = micros() - start; + Serial.print("FastShiftIn2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + delay(100); +} + +void test_readMSBFIRST() +{ + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.readMSBFIRST(); + } + duration1 = micros() - start; + Serial.print("FastShiftIn1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = FSI.readMSBFIRST(); + x = FSI.readMSBFIRST(); + } + duration2 = micros() - start; + Serial.print("FastShiftIn2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + delay(100); +} + +void test_reference() +{ + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = shiftIn(12, 13, LSBFIRST); + } + duration1 = micros() - start; + Serial.print("Standard shiftIn1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + x = shiftIn(12, 13, LSBFIRST); + x = shiftIn(12, 13, LSBFIRST); + } + duration2 = micros() - start; + Serial.print("Standard shiftIn2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + +} + +void loop() +{ +} \ No newline at end of file diff --git a/libraries/FastShiftIn/library.json b/libraries/FastShiftIn/library.json index b3c6e981..85c5a0a1 100644 --- a/libraries/FastShiftIn/library.json +++ b/libraries/FastShiftIn/library.json @@ -1,7 +1,7 @@ { "name": "FastShiftIn", - "keywords": "Shift,shiftin,in,serial,fast", - "description": "Class for up to 3x faster shift in.", + "keywords": "Shift, shiftIn, in, serial, fast, 74HC165", + "description": "Arduino library for (AVR) optimized shiftIn - e.g. for 74HC165", "authors": [ { @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/FastShiftIn.git" }, - "version":"0.1.3", + "version":"0.2.1", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/FastShiftIn" - } + "platforms": "AVR" } diff --git a/libraries/FastShiftIn/library.properties b/libraries/FastShiftIn/library.properties index 5f1608f4..112acd1a 100644 --- a/libraries/FastShiftIn/library.properties +++ b/libraries/FastShiftIn/library.properties @@ -1,9 +1,11 @@ name=FastShiftIn -version=0.1.3 +version=0.2.1 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Class for up to 3x faster shift in. -paragraph= +sentence=Arduino library for (AVR) optimized shiftIn - e.g. for 74HC165 +paragraph= category=Signal Input/Output -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/FastShiftIn +architectures=avr +includes=FastShiftIn.h +depends= diff --git a/libraries/FastShiftIn/performance.txt b/libraries/FastShiftIn/performance.txt new file mode 100644 index 00000000..8aa81bbb --- /dev/null +++ b/libraries/FastShiftIn/performance.txt @@ -0,0 +1,119 @@ + + +============================== + +2020-04-14 - tested IDE 1.8.12 + factor 5+ faster +----------------------------- + +example fastShiftIn: 0.2.0 + + 8 bits HIGH + + +Performance - time in us : read() +FastShiftIn1: 20.43 +FastShiftIn2: 39.72 + Delta: 19.29 + + +Performance - time in us : readLSBFIRST() +FastShiftIn1: 19.80 +FastShiftIn2: 38.84 + Delta: 19.04 + + +Performance - time in us : readMSBFIRST() +FastShiftIn1: 19.80 +FastShiftIn2: 38.84 + Delta: 19.04 + + +Performance - time in us : reference shiftIn() +Standard shiftIn1: 108.61 +Standard shiftIn2: 216.43 + Delta: 107.82 + +done... + +============================== + +tested IDE 1.8.12 + +2020-04-14 + +example fastShiftIn: 0.1.5 + + 8 bits HIGH + + +Performance - time in us +FastShiftIn1: 25.15 +FastShiftIn2: 49.15 + Delta: 24.00 + +Standard shiftIn1: 108.51 +Standard shiftIn2: 216.43 + Delta: 107.92 + +done... + +============================== + +tested IDE 1.8.1 + +20-08-2017 +example fastShiftIn: 0.1.4 + + 8 bits HIGH + + +Performance - time in us +FastShiftIn1: 25.64 +FastShiftIn2: 50.16 + Delta: 24.52 + +Standard shiftIn1: 110.53 +Standard shiftIn2: 220.48 + Delta: 109.95 + +done... + +============================== + +2017-4-27 +example fastShiftIn: 0.1.3 + + 8 bits HIGH + + +Performance - time in us +FastShiftIn1: 31.31 +FastShiftIn2: 61.48 + Delta: 30.18 + +Standard shiftIn1: 110.54 +Standard shiftIn2: 220.48 + Delta: 109.94 + +done... + +============================== + +example fastShiftIn: 0.1.01 + + 8 bits HIGH + + +Performance - time in us +FastShiftIn1: 44.83 +FastShiftIn2: 88.52 + Delta: 43.70 + +Standard shiftIn1: 110.54 +Standard shiftIn2: 220.49 + Delta: 109.95 + +done... + + diff --git a/libraries/FastShiftIn/readme.md b/libraries/FastShiftIn/readme.md index efe6ab8b..2f029d3f 100644 --- a/libraries/FastShiftIn/readme.md +++ b/libraries/FastShiftIn/readme.md @@ -1,6 +1,41 @@ +# FastShiftIn -FastShiftIn is a class that speeds up the shifting by using predetermined posts and masks. -Its performance is about twice as fast as the normal Arduino shiftIn. +Arduino library for (AVR) optimized shiftIn - e.g. for 74HC165 + +A library for FastShiftOut also exist. + +## Description + +FastShiftIn is a class that has optimized code (AVR only) to shift in data faster +than the normal shiftIn() function. +It speeds up the shift using low level ports and masks. These are predetermined +in the constructor of the FastShiftIn object. + +If not an **ARDUINO_ARCH_AVR** or **ARDUINO_ARCH_MEGAAVR** the class falls back +to the default shiftIn() implementation. + +## Performance + +The performance of **read()** is substantially faster than the default Arduino +**shiftIn()**, but not as fast as HW SPI. +Exact how big the performance gain is can be seen with the example sketch. +It does a comparison and shows how the class is to be used. + +## Interface + +The interface exists of the following functions: + +- **int read(void);** +- **int readLSBFIRST(void);** most optimized +- **int readMSBFIRST(void);** most optimized + +## Notes + +- The optimizations are AVR only for now, other platforms may follow. +- The 74HC165 needs 0.1uF caps and the data and clock lines may need +pull up resistors, especially if wires are exceeding 10 cm (4"). + +## Operation + +See examples -There is a thread on the forum here - http://forum.arduino.cc/index.php?topic=184002.0 - -This thread also discusses a FastShiftOut \ No newline at end of file diff --git a/libraries/FastShiftOut/Examples/FastShiftOut_test/FastShiftOut_test.ino b/libraries/FastShiftOut/Examples/FastShiftOut_test/FastShiftOut_test.ino new file mode 100644 index 00000000..7464ccad --- /dev/null +++ b/libraries/FastShiftOut/Examples/FastShiftOut_test/FastShiftOut_test.ino @@ -0,0 +1,119 @@ +// +// FILE: FastShiftOut_test.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: test sketch +// URL: https://github.com/RobTillaart/FastSHiftOut +// + +#include "FastShiftOut.h" + +FastShiftOut FSO(12, 13, LSBFIRST); + +uint32_t start, duration1, duration2; + +void setup() +{ + Serial.begin(115200); + Serial.print("example fastShiftOut: "); + Serial.println(FASTSHIFTOUT_LIB_VERSION); + + Serial.println("\nPerformance - time in us"); + test1(); + test2(); + test3(); + + Serial.println("\ndone ...\n"); +} + +void test1() +{ + start = micros(); + for (int i = 0; i < 1000; i++) + { + FSO.write(0x55); + } + duration1 = micros() - start; + Serial.print("FastShiftOut1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + FSO.write(0x55); + FSO.write(0x55); + } + duration2 = micros() - start; + Serial.print("FastShiftOut2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + delay(100); +} + + +void test2() +{ + start = micros(); + for (int i = 0; i < 1000; i++) + { + shiftOut(12, 13, 0x55, LSBFIRST); + } + duration1 = micros() - start; + Serial.print("Standard shiftOut1: "); + Serial.println(duration1 * 0.001); + + start = micros(); + for (int i = 0; i < 1000; i++) + { + shiftOut(12, 13, 0x55, LSBFIRST); + shiftOut(12, 13, 0x55, LSBFIRST); + } + duration2 = micros() - start; + Serial.print("Standard shiftOut2: "); + Serial.println(duration2 * 0.001); + Serial.print(" Delta: "); + Serial.println((duration2 - duration1) * 0.001); + Serial.println(); + delay(100); +} + +void test3() +{ + Serial.println("\nTest print interface"); + start = micros(); + for (int i = 0; i < 100; i++) + { + FSO.println("Hello world"); + } + duration1 = micros() - start; + Serial.print("println(\"Hello world\"): \t"); + Serial.println(duration1 * 0.01); + + start = micros(); + for (int i = 0; i < 100; i++) + { + FSO.println(1357); + } + duration1 = micros() - start; + Serial.print("println(1357): \t\t\t"); + Serial.println(duration1 * 0.01); + + + start = micros(); + for (int i = 0; i < 100; i++) + { + FSO.println(3.14159265, 4); + } + duration1 = micros() - start; + Serial.print("println(3.14159265, 4): \t"); + Serial.println(duration1 * 0.01); + delay(100); +} + +void loop() +{ +} + +// -- END OF FILE -- diff --git a/libraries/FastShiftOut/FastShiftOut.cpp b/libraries/FastShiftOut/FastShiftOut.cpp index 0bfe495c..0778995c 100644 --- a/libraries/FastShiftOut/FastShiftOut.cpp +++ b/libraries/FastShiftOut/FastShiftOut.cpp @@ -1,112 +1,110 @@ // // FILE: FastShiftOut.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.5 +// VERSION: 0.2.1 // PURPOSE: shiftout that implements the Print interface // DATE: 2013-08-22 -// URL: -// -// Released to the public domain -// -// HISTORY -// 0.1.5 - changed masking in inner loop +// URL: https://github.com/RobTillaart/FastShiftOut // #include "FastShiftOut.h" -// -// Constructor -// prepares the digitalWrite() FastShiftOut::FastShiftOut(const uint8_t datapin, const uint8_t clockpin, const uint8_t bitOrder) { - _bitorder = bitOrder; - _value = -1; - pinMode(datapin, OUTPUT); - pinMode(clockpin, OUTPUT); + _bitorder = bitOrder; + pinMode(datapin, OUTPUT); + pinMode(clockpin, OUTPUT); - // uint8_t _datatimer = digitalPinToTimer(datapin); - // if (_datatimer != NOT_ON_TIMER) turnOffPWM(_datatimer); TODO - uint8_t _dataport = digitalPinToPort(datapin); - _dataout = portOutputRegister(_dataport); - _databit = digitalPinToBitMask(datapin); +#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) - // uint8_t _clocktimer = digitalPinToTimer(clockpin); - // if (_clocktimer != NOT_ON_TIMER) turnOffPWM(_clocktimer); - uint8_t _clockport = digitalPinToPort(clockpin); - _clockout = portOutputRegister(_clockport); - _clockbit = digitalPinToBitMask(clockpin); + // uint8_t _datatimer = digitalPinToTimer(datapin); + // if (_datatimer != NOT_ON_TIMER) turnOffPWM(_datatimer); TODO + uint8_t _dataport = digitalPinToPort(datapin); + _dataout = portOutputRegister(_dataport); + _databit = digitalPinToBitMask(datapin); + + // uint8_t _clocktimer = digitalPinToTimer(clockpin); + // if (_clocktimer != NOT_ON_TIMER) turnOffPWM(_clocktimer); + uint8_t _clockport = digitalPinToPort(clockpin); + _clockout = portOutputRegister(_clockport); + _clockbit = digitalPinToBitMask(clockpin); + +#else // reference implementation + + // reuse these vars as pin to save some space + _databit = datapin; + _clockbit = clockpin; + +#endif } -// -// write() must implement the virtual write of Print class -// -// approx 30 us/byte size_t FastShiftOut::write(const uint8_t data) { - _value = data; - for (uint8_t i = 0, m = 1, n = 128; i < 8; i++, m <<= 1, n >>= 1) - { - uint8_t v; - if (_bitorder == LSBFIRST) v = (_value & m); - else v = (_value & n); + if (_bitorder == LSBFIRST) + { + return writeLSBFIRST(data); + } + return writeMSBFIRST(data); +} - uint8_t oldSREG = SREG; - cli(); - if (v == 0) *_dataout &= ~_databit; - else *_dataout |= _databit; - *_clockout |= _clockbit; - *_clockout &= ~_clockbit; - SREG = oldSREG; - } +#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) + +size_t FastShiftOut::writeLSBFIRST(const uint8_t data) +{ + uint8_t cbmask1 = _clockbit; + uint8_t cbmask2 = ~_clockbit; + uint8_t dbmask1 = _databit; + uint8_t dbmask2 = ~_databit; + + for (uint8_t i = 0, m = 1; i < 8; i++) + { + uint8_t oldSREG = SREG; + cli(); + if ((data & m) == 0) *_dataout &= dbmask2; + else *_dataout |= dbmask1; + *_clockout |= cbmask1; + *_clockout &= cbmask2; + SREG = oldSREG; + m <<= 1; + } + return 1; +} + +size_t FastShiftOut::writeMSBFIRST(const uint8_t data) +{ + uint8_t cbmask1 = _clockbit; + uint8_t cbmask2 = ~_clockbit; + uint8_t dbmask1 = _databit; + uint8_t dbmask2 = ~_databit; + + for (uint8_t i = 0, n = 128; i < 8; i++) + { + uint8_t oldSREG = SREG; + cli(); + if ((data & n) == 0) *_dataout &= dbmask2; + else *_dataout |= dbmask1; + *_clockout |= cbmask1; + *_clockout &= cbmask2; + SREG = oldSREG; + n >>= 1; + } + return 1; +} + +#else // reference implementation // note this has no cli() + +size_t FastShiftOut::writeLSBFIRST(const uint8_t data) +{ + shiftOut(_databit, _clockbit, LSBFIRST, data); return 1; } -// -// this version is twice as fast, -// but it is in CLI() mode -// approx 32us / byte -// size_t FastShiftOut::write(uint8_t data) -// { -// _value = data; -// // prep masks -// uint8_t dm1 = *_dataout | _databit; -// uint8_t dm0 = *_dataout & ~_databit; -// uint8_t cm1 = *_clockout | _clockbit; -// uint8_t cm0 = *_clockout & ~_clockbit; - -// uint8_t oldSREG = SREG; -// cli(); -// if (_bitorder == LSBFIRST) -// { -// for (uint8_t m = 0x01; m != 0x80; m <<= 1) -// { -// if (_value & m) *_dataout = dm1; -// else *_dataout = dm0; -// *_clockout = cm1; -// *_clockout = cm0; -// } -// } -// else -// { -// for (uint8_t m = 0x80; m > 0; m >>= 1) -// { -// if (_value & m) *_dataout = dm1; -// else *_dataout = dm0; -// *_clockout = cm1; -// *_clockout = cm0; -// } -// } -// SREG = oldSREG; -// return 1; -// } - - -// -// reads back the last value written. -// -int FastShiftOut::read() +size_t FastShiftOut::writeMSBFIRST(const uint8_t data) { - return _value; + shiftOut(_databit, _clockbit, MSBFIRST, data); + return 1; } +#endif + // -- END OF FILE -- \ No newline at end of file diff --git a/libraries/FastShiftOut/FastShiftOut.h b/libraries/FastShiftOut/FastShiftOut.h index ef9246ca..70ed949b 100644 --- a/libraries/FastShiftOut/FastShiftOut.h +++ b/libraries/FastShiftOut/FastShiftOut.h @@ -1,44 +1,37 @@ +#pragma once // // FILE: FastShiftOut.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.5 +// VERSION: 0.2.1 // PURPOSE: shiftout that implements the Print interface // DATE: 2013-08-22 -// URL: -// -// Released to the public domain +// URL: https://github.com/RobTillaart/FastShiftOut // -#ifndef FastShiftOut_h -#define FastShiftOut_h - -#if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" -#else -#include "WProgram.h" -#endif - -#define FASTSHIFTOUT_LIB_VERSION (F("0.1.5")) - #include "Print.h" +#define FASTSHIFTOUT_LIB_VERSION (F("0.2.1")) + class FastShiftOut : public Print { public: - FastShiftOut(const uint8_t, const uint8_t, const uint8_t); - size_t write(const uint8_t); - int read(void); + // bitorder = { LSBFIRST, MSBFIRST }; + FastShiftOut(const uint8_t datapin, const uint8_t clockpin, const uint8_t bitOrder = LSBFIRST); + size_t write(const uint8_t data); + + // overrule bitorder (most optimized). + size_t writeLSBFIRST(const uint8_t data); + size_t writeMSBFIRST(const uint8_t data); private: - uint8_t _bitorder; - int _value; + uint8_t _bitorder; - uint8_t _databit; - volatile uint8_t *_dataout; + uint8_t _databit; + volatile uint8_t *_dataout; - uint8_t _clockbit; - volatile uint8_t *_clockout; + uint8_t _clockbit; + volatile uint8_t *_clockout; }; -#endif -// -- END OF FILE -- \ No newline at end of file +// -- END OF FILE -- diff --git a/libraries/FastShiftOut/LICENSE b/libraries/FastShiftOut/LICENSE new file mode 100644 index 00000000..2fc1cc50 --- /dev/null +++ b/libraries/FastShiftOut/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/FastShiftOut/PerformanceNotes.txt b/libraries/FastShiftOut/PerformanceNotes.txt new file mode 100644 index 00000000..2175feec --- /dev/null +++ b/libraries/FastShiftOut/PerformanceNotes.txt @@ -0,0 +1,179 @@ + +============================== + +tests IDE 1.8.12 - 20-08-2017 + +example fastShiftOut: 0.2.0 + +Performance - time in us +FastShiftOut1: 21.95 +FastShiftOut2: 43.00 + Delta: 21.04 + +Standard shiftOut1: 88.27 +Standard shiftOut2: 175.94 + Delta: 87.68 + + +Test print interface +println("Hello world"): 313.16 +println(1357): 304.68 +println(3.14159265, 4): 705.60 + +done ... + +============================== + +tests IDE 1.8.12 - 20-08-2017 + + +example fastShiftOut: 0.1.6 + +Performance - time in us +FastShiftOut1: 27.68 +FastShiftOut2: 54.44 + Delta: 26.76 + +Standard shiftOut1: 88.27 +Standard shiftOut2: 175.94 + Delta: 87.67 + + +Test print interface +println("Hello world"): 387.92 +println(1357): 339.44 +println(3.14159265, 4): 751.96 + +done ... + +============================== +tests IDE 1.8.1 + +20-08-2017 +example fastShiftOut: 0.1.6 + +Performance - time in us +FastShiftOut1: 28.69 +FastShiftOut2: 56.46 + Delta: 27.76 + +Standard shiftOut1: 90.79 +Standard shiftOut2: 181.00 + Delta: 90.21 + + +Test print interface +println("Hello world"): 403.20 +println(1357): 346.64 +println(3.14159265, 4): 757.72 + +done ... + +20-08-2017 +example fastShiftOut: 0.1.5 + +Performance - time in us +FastShiftOut1: 29.76 +FastShiftOut2: 58.59 + Delta: 28.83 + +Standard shiftOut1: 90.80 +Standard shiftOut2: 181.00 + Delta: 90.20 + + +Test print interface +println("Hello world"): 417.08 +println(1357): 353.00 +println(3.14159265, 4): 766.28 + +done ... + +example fastShiftOut: 0.1.04 + +Performance - time in us +FastShiftOut1: 43.66 +FastShiftOut2: 86.38 + Delta: 42.72 + +Standard shiftOut1: 90.79 +Standard shiftOut2: 181.00 + Delta: 90.21 + + +Test print interface +println("Hello world"): 597.68 +println(1357): 436.44 +println(3.14159265, 4): 877.48 + +done ... + +================================== + +example fastShiftOut: 0.1.03 + +Performance - time in us +FastShiftOut1: 63.9 +FastShiftOut2: 123.0 +Standard shiftOut1: 115.7 +Standard shiftOut2: 230.4 + +Test print interface +println("Hello world"): 822.2 +println(1357): 561.2 +println(3.14159265, 4): 1068.6 +done + +example fastShiftOut: 0.1.03 + +Performance - time in us +FastShiftOut1: 31.9 +FastShiftOut2: 60.8 +Standard shiftOut1: 115.7 +Standard shiftOut2: 230.4 + +Test print interface +println("Hello world"): 412.9 +println(1357): 372.0 +println(3.14159265, 4): 815.9 + +done + + +1.04 - fast print version + normal fastSHiftOut +example fastShiftOut: 0.1.03 + +Performance - time in us +FastShiftOut1: 64.0 +FastShiftOut2: 123.4 +Standard shiftOut1: 115.8 +Standard shiftOut2: 230.5 + +Test print interface +println("Hello world"): 816.6 +println(1357): 405.9 +println(3.14159265, 4): 579.8 + +done +======================================= +example fastShiftIn: 0.1.00 + +Performance - time in us +FastShiftIn1: 42.8 // 8 bits LOW +FastShiftIn2: 80.8 // 8 bits LOW +Standard shiftIn1: 114248.4 +Standard shiftIn2: 228004.8 + +example fastShiftIn: 0.1.00 + +Performance - time in us +FastShiftIn1: 67.7 // 8 bits HIGH +FastShiftIn2: 130.6 // 8 bits HIGH +Standard shiftIn1: 114442.4 +Standard shiftIn2: 228440.4 + + + + + + diff --git a/libraries/FastShiftOut/README.md b/libraries/FastShiftOut/README.md new file mode 100644 index 00000000..e6e46374 --- /dev/null +++ b/libraries/FastShiftOut/README.md @@ -0,0 +1,48 @@ +# FastShiftOut + +Arduino library for (AVR) optimized shiftOut - e.g. 74HC595 + +A library for FastShiftOut also exist. + +## Description + +FastShiftOut is a class that has optimized code for AVR to shift out data faster +than the normal shiftOut() function. +It speeds up the shift using low level ports and masks. These are predetermined +in the constructor of the FastShiftOut object. + +If not an **ARDUINO_ARCH_AVR** or **ARDUINO_ARCH_MEGAAVR** the class falls back +to the default shiftOut() implementation. + +## Performance + +The performance of **write()** is substantially faster than the default Arduino +**shiftIn()**, but not as fast as HW SPI. +Exact how big the performance gain is can be seen with the example sketch. +It does a comparison and shows how the class is to be used. + +## Interface + +The interface exists of the following functions: + +- **size_t write(const uint8_t data);** +- **size_t writeLSBFIRST(const uint8_t data);** most optimized +- **size_t writeMSBFIRST(const uint8_t data);** most optimized + +Furthermore an FastShiftOut object implements the Print interface +so one can also call +- **FSO.print(any type);** or +- **FSO.println(any type);** + +to send e.g. a float with 4 digits over the line. + +## Notes + +- The optimizations are AVR only for now, other platforms may follow. +- The 74HC595 needs 0.1uF caps and the data and clock lines may need +pull up resistors, especially if wires are exceeding 10 cm (4"). + +## Operation + +See examples + diff --git a/libraries/FastShiftOut/library.json b/libraries/FastShiftOut/library.json index 15b76c46..105dcb13 100644 --- a/libraries/FastShiftOut/library.json +++ b/libraries/FastShiftOut/library.json @@ -1,7 +1,7 @@ { "name": "FastShiftOut", - "keywords": "Shift,shiftout,out,serial,fast", - "description": "Class for up to 3x faster shift out. Implements print() interface.", + "keywords": "Shift, shiftout, out, serial, fast", + "description": "Arduino library for (AVR) optimized shiftOut - e.g. 74HC595", "authors": [ { @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/FastShiftOut.git" }, - "version":"0.1.5", + "version":"0.2.1", "frameworks": "arduino", - "platforms": "atmelavr", - "export": { - "include": "libraries/FastShiftOut" - } + "platforms": "atmelavr" } diff --git a/libraries/FastShiftOut/library.properties b/libraries/FastShiftOut/library.properties index 1e04ffc3..1f1a3e6b 100644 --- a/libraries/FastShiftOut/library.properties +++ b/libraries/FastShiftOut/library.properties @@ -1,9 +1,11 @@ name=FastShiftOut -version=0.1.5 +version=0.2.1 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Class for up to 3x faster shift out. +sentence=Arduino library for (AVR) optimized shiftOut - e.g. 74HC595 paragraph=Implements print() interface. category=Signal Input/Output -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/FastSHiftOut +architectures=* +includes=FastShiftOut.h +depends= diff --git a/libraries/Fraction/LICENSE b/libraries/Fraction/LICENSE new file mode 100644 index 00000000..e563929f --- /dev/null +++ b/libraries/Fraction/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2015-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/Fraction/examples/FractionFindSum/FractionFindSum.ino b/libraries/Fraction/examples/FractionFindSum/FractionFindSum.ino index 5f60a1eb..5ef29539 100644 --- a/libraries/Fraction/examples/FractionFindSum/FractionFindSum.ino +++ b/libraries/Fraction/examples/FractionFindSum/FractionFindSum.ino @@ -1,12 +1,10 @@ // // FILE: FractionFindSum.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.00 +// VERSION: 0.1.1 // PURPOSE: demo // DATE: 13-feb-2015 -// URL: -// -// Released to the public domain +// URL: https://github.com/RobTillaart/Fraction // #include "fraction.h" @@ -50,7 +48,7 @@ void findSum(Fraction f) Serial.print(g); Serial.print(" + "); } - if (f == 0) + if (f == Fraction(0)) { break; } @@ -59,8 +57,10 @@ void findSum(Fraction f) Serial.println(z); Serial.println(); } + + void loop() { } - +// -- END OF FILE -- diff --git a/libraries/Fraction/examples/FractionMediant/FractionMediant.ino b/libraries/Fraction/examples/FractionMediant/FractionMediant.ino new file mode 100644 index 00000000..88c6eac3 --- /dev/null +++ b/libraries/Fraction/examples/FractionMediant/FractionMediant.ino @@ -0,0 +1,108 @@ +// +// FILE: FractionMediant.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: Find fraction by binary search with mediant. +// DATE: 2020-04-21 +// + +// this method is not that fast but it shows a nice application for +// the mediant. + +#include "fraction.h" + +uint32_t start, stop; + +void setup() +{ + Serial.begin(115200); + Serial.print(__FILE__); + Serial.println(); + Serial.println(); + + float f = PI; + start = micros(); + Fraction x = fractionize(f); + stop = micros(); + Serial.println(stop - start); + Serial.println(x); + Serial.println(x.toDouble(), 10); + Serial.println(); + + f = EULER; + start = micros(); + Fraction y = fractionize(f); + stop = micros(); + Serial.println(stop - start); + Serial.println(y); + Serial.println(y.toDouble(), 10); + Serial.println(); + + Serial.println("done...\n"); + +} + + +void loop() +{ + float f = random(1000000) * 0.000001; + + // reference + start = micros(); + Fraction y(f); + stop = micros(); + + Serial.println(); + Serial.print(stop - start); + Serial.print("\t"); + Serial.print(y); + Serial.print("\t"); + Serial.print(f, 10); + Serial.print("\t"); + Serial.print(y.toDouble(), 10); + Serial.print("\t"); + Serial.println(f - y.toDouble(), 10); + + // mediant method. + start = micros(); + y = fractionize(f); + stop = micros(); + + Serial.print(stop - start); + Serial.print("\t"); + Serial.print(y); + Serial.print("\t"); + Serial.print(f, 10); + Serial.print("\t"); + Serial.print(y.toDouble(), 10); + Serial.print("\t"); + Serial.println(f - y.toDouble(), 10); +} + + +Fraction fractionize(float f) +{ + float acc = 1e-6; + float d1 = 0; + float d2 = 0; + Fraction a(0, 1); + Fraction b(9999, 1); + Fraction q(f); + + for (int i = 0; i < 500; i++) + { + Fraction c = Fraction::mediant(a, b); // NOTE middle(a,b) is slower and worse! + if ( c.toDouble() < f) a = c; + else b = c; + + d1 = abs(f - a.toDouble()); + d2 = abs(f - b.toDouble()); + if (d1 < acc && d2 < acc) break; + } + if (d1 < d2) return a; + return b; +} + + + +// -- END OF FILE -- \ No newline at end of file diff --git a/libraries/Fraction/examples/fractionExerciser/fractionExerciser.ino b/libraries/Fraction/examples/fractionExerciser/fractionExerciser.ino index 35410ae9..a20cfcf5 100644 --- a/libraries/Fraction/examples/fractionExerciser/fractionExerciser.ino +++ b/libraries/Fraction/examples/fractionExerciser/fractionExerciser.ino @@ -1,12 +1,10 @@ // // FILE: fractionExerciser.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.00 +// VERSION: 0.1.1 // PURPOSE: demo sketch for fraction math -// DATE: -// URL: -// -// Released to the public domain +// DATE: 2015-03-29 +// URL: https://github.com/RobTillaart/Fraction // #include "fraction.h" diff --git a/libraries/Fraction/examples/fractionTest01/fractionTest01.ino b/libraries/Fraction/examples/fractionTest01/fractionTest01.ino index c621eecc..b786c963 100644 --- a/libraries/Fraction/examples/fractionTest01/fractionTest01.ino +++ b/libraries/Fraction/examples/fractionTest01/fractionTest01.ino @@ -1,12 +1,10 @@ // // FILE: fractionTest01.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.00 +// VERSION: 0.1.1 // PURPOSE: test sketch for fraction math -// DATE: -// URL: -// -// Released to the public domain +// DATE: 2015-01-25 +// URL: https://github.com/RobTillaart/Fraction // #include "fraction.h" @@ -18,6 +16,7 @@ Fraction b(1, 4); Fraction n(0, 5); Fraction p(5); Fraction pi(PI); +Fraction e(EULER); void setup() { @@ -33,6 +32,9 @@ void setup() Serial.println(p); Serial.println(q); Serial.println(pi); + Serial.println(e); + Serial.println(Fraction::middle(pi, e)); + Serial.println(Fraction::mediant(pi, e)); Serial.println(); testPlus(); diff --git a/libraries/Fraction/fraction.cpp b/libraries/Fraction/fraction.cpp index 1a719dc4..7e39535f 100644 --- a/libraries/Fraction/fraction.cpp +++ b/libraries/Fraction/fraction.cpp @@ -1,16 +1,17 @@ // // FILE: fraction.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.8 -// PURPOSE: library for fractions for Arduino -// URL: https://github.com/RobTillaart/Arduino +// VERSION: 0.1.10 +// PURPOSE: Arduino library to implement a Fraction datatype +// URL: https://github.com/RobTillaart/Fraction // -// Released to the public domain // // TODO // - divide by zero errors // - test extensively // +// 0.1.10 2020-06-10 fix library.json +// 0.1.9 refactor // 0.1.8 - refactor made constructors explicit; fix issue #33 double --> float // 0.1.07 - major refactoring by Chris-A // 0.1.06 - added proper(), mediant(), angle(); @@ -24,8 +25,10 @@ #include "fraction.h" +////////////////////////////////////// +// // CONSTRUCTORS - +// Fraction::Fraction(double d) { Fraction::split(float(d)); @@ -45,16 +48,29 @@ void Fraction::split(float f) // EULER = 2721/1001; // 1.1e-7 // EULER = 1264/465; // 2.2e-6 - // get robust for small values. + // get robust for small values. (effectively zero) if (abs(f) < 0.00001) { n = 0; d = 1; return; } + if (int32_t(f) == f) + { + n = int32_t(f); + d = 1; + return; + } // Normalize to 0.0 ... 1.0 bool negative = f < 0; if (negative) f = -f; + + // TODO investigate different strategy: + // intpart = int32_t(f); // strip of the integer part. + // f = f - intpart; // determine remainder + // determine n, d + // n += intpart * d; // add integer part * denominator to fraction. + bool reciproke = f > 1; if (reciproke) f = 1/f; @@ -79,10 +95,16 @@ Fraction::Fraction(int32_t p, int32_t q) : n(p), d(q) simplify(); } + +////////////////////////////////////// +// // PRINTING +// size_t Fraction::printTo(Print& p) const { size_t s = 0; + // TODO split of sign first + // // vs 22/7 => 3_1/7 // if (n >= d) // { @@ -96,12 +118,21 @@ size_t Fraction::printTo(Print& p) const return s; }; +////////////////////////////////////// +// // EQUALITIES +// bool Fraction::operator == (const Fraction &c) { return (n * c.d) == (d * c.n); } +// bool Fraction::operator == (const float &f) +// { + // Fraction c(f); + // return (n * c.d) == (d * c.n); +// } + bool Fraction::operator != (const Fraction &c) { return (n * c.d) != (d * c.n); @@ -127,13 +158,19 @@ bool Fraction::operator <= (const Fraction &c) return (n * c.d) <= (d * c.n); } +////////////////////////////////////// +// // NEGATE +// Fraction Fraction::operator - () { return Fraction(-n, d); } +////////////////////////////////////// +// // BASIC MATH +// Fraction Fraction::operator + (const Fraction &c) { if (d == c.d) @@ -215,7 +252,6 @@ float Fraction::toDouble() return (1.0 * n) / d; } -// wikipedia // fraction is proper if abs(fraction) < 1 bool Fraction::isProper() { @@ -229,15 +265,18 @@ float Fraction::toAngle() } -//////////////////////////////////////////////////////////// +////////////////////////////////////// +// // STATIC +// // Mediant - http://www.cut-the-knot.org/Curriculum/Arithmetic/FCExercise.shtml // void Fraction::mediant(Fraction c) // { -// n += c.n; -// d += c.d; -// simplify(); +// n += c.n; +// d += c.d; +// simplify(); // } +// // the mediant is a fraction that is always between 2 fractions // at least if within precission. @@ -246,6 +285,13 @@ Fraction Fraction::mediant(const Fraction &a, const Fraction &b) return Fraction(a.n + b.n, a.d + b.d); } +// the middle is a fraction that is between 2 fractions +// at least if within precission. +Fraction Fraction::middle(const Fraction &a, const Fraction &b) +{ + return Fraction(a.n*b.d + b.n*a.d, 2 * a.d * b.d); +} + // approximate a fraction with defined denominator // sort of setDenominator(uint16_t den); Fraction Fraction::setDenominator(const Fraction &a, uint16_t b) @@ -256,9 +302,11 @@ Fraction Fraction::setDenominator(const Fraction &a, uint16_t b) } -//////////////////////////////////////////////////////////////// +////////////////////////////////////// +// // PRIVATE // http://en.wikipedia.org/wiki/Binary_GCD_algorithm +// int32_t Fraction::gcd(int32_t a , int32_t b) { while ( a != 0 ) @@ -282,8 +330,8 @@ void Fraction::simplify() int32_t p = abs(n); int32_t q = abs(d); int32_t x = gcd(p,q); - p = p/x; - q = q/x; + p = p / x; + q = q / x; // denominator max 4 digits keeps mul and div simple // in preventing overflow @@ -293,14 +341,15 @@ void Fraction::simplify() p = (p + 5)/10; q = (q + 5)/10; x = gcd(p, q); - p = p/x; - q = q/x; + p = p / x; + q = q / x; } - n = (neg)?-p:p; + n = (neg) ? -p : p; d = q; } ////////////////////////////////////////////////////////////////////////////// +// // fractionize() - finds the fraction representation of a float // PRE: 0 <= f < 1.0 // @@ -312,106 +361,14 @@ void Fraction::simplify() // -// MINIMALISTIC -// (100x) micros()=51484 -/* -float Fraction::fractionize(float f) // simple, small, 2nd fastest -{ - n = round(f * 10000); // why not 1000000 ? - d = 10000; - simplify(); - return 0; // abs(f - this.toDouble()); -} -*/ - -// LINEAR SEARCH -// (100x) micros()=18873064 -// slow not stable -/* -float Fraction::fractionize(float f) -{ - long nn = 1, dd = 1; - - float r = 1 / f; - float delta = f * dd - nn; - while (abs(delta) > 0.00001 && (dd < 10000)) - { - dd++; - if (delta < 0) - { - nn++; - dd = nn * r; - } - delta = f * dd - nn; - } - n = nn; - d = dd; - return delta; -} -*/ - -/* -// LINEAR SEARCH (mirror optimized) -// (100x) micros()= -// slow but stable version -float Fraction::fractionize(float f) -{ - long nn = 1, dd = 1; - bool inverse = false; - - if (f > 0.5) - { - f = 1-f; - inverse = true; - } - - float r = 1 / f; - float delta = f * dd - nn; - while (abs(delta) > 0.00001 && (dd < 10000)) - { - dd++; - if (delta < 0) - { - nn++; - dd = nn * r; - } - delta = f * dd - nn; - } - n = inverse?(dd - nn):nn; - d = dd; - return delta; -} -*/ - - -// ADD BY DIGIT -// - does not find "magic fractions" e.g. pi = 355/113 -// (100x) micros()=392620 -/* -float Fraction::fractionize(float f) // divide and conquer, simple, small, 2nd fastest -{ - Fraction t((long)0); - for (long dd = 10; dd < 1000001; dd *= 10) - { - f *= 10; - int ff = f; - t += Fraction(ff, dd); - f -= ff; - } - n = t.n; - d = t.d; - return f; -} -*/ - - // Dr. Peterson // - http://mathforum.org/library/drmath/view/51886.html // (100x) micros()=96048 // showed errors for very small values around 0 void Fraction::fractionize(float val) -{ // find nearest fraction - float Precision = 0.000001; +{ + // find nearest fraction + float Precision = 0.0000001; Fraction low(0, 1); // "A" = 0/1 Fraction high(1, 1); // "B" = 1/1 for (int i = 0; i < 100; ++i) @@ -456,46 +413,4 @@ void Fraction::fractionize(float val) d = high.d; } - -// BINARY SEARCH -// - http://www.gamedev.net/topic/354209-how-do-i-convert-a-decimal-to-a-fraction-in-c/ -// (100x) micros()=1292452 -// slower -/* -float Fraction::fractionize(float value) // size ok, too slow. -{ - int max_denominator = 10000; - - int low_n = 0; - int low_d = 1; - int high_n = 1; - int high_d = 1; - int mid_n; - int mid_d; - - do - { - mid_n = low_n + high_n; - mid_d = low_d + high_d; - if ( mid_n < value * mid_d ) - { - low_n = mid_n; - low_d = mid_d; - n = high_n; - d = high_d; - } - else - { - high_n = mid_n; - high_d = mid_d; - n = low_n; - d = low_d; - } - } while ( mid_d <= max_denominator ); - return 0; -} -*/ - -// -// END OF FILE -// \ No newline at end of file +// -- END OF FILE -- diff --git a/libraries/Fraction/fraction.h b/libraries/Fraction/fraction.h index 14f6bd0f..70da254e 100644 --- a/libraries/Fraction/fraction.h +++ b/libraries/Fraction/fraction.h @@ -1,19 +1,15 @@ +#pragma once // // FILE: fraction.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.8 -// PURPOSE: demo library for fractions for Arduino -// URL: +// VERSION: 0.1.10 +// PURPOSE: Arduino library to implement a Fraction datatype +// URL: https://github.com/RobTillaart/Fraction // -// Released to the public domain -// - -#ifndef Fraction_h -#define Fraction_h #include "Arduino.h" -#define FRACTIONLIBVERSION "0.1.8" +#define FRACTIONLIBVERSION "0.1.10" class Fraction: public Printable { @@ -33,6 +29,7 @@ public: // equalities bool operator == (const Fraction&); + // bool operator == (const float&); bool operator != (const Fraction&); bool operator > (const Fraction&); bool operator >= (const Fraction&); @@ -58,7 +55,12 @@ public: bool isProper(); // abs(f) < 1 float toAngle(); + int32_t nominator() { return n; }; + int32_t denominator() { return d; }; + static Fraction mediant(const Fraction&, const Fraction&); + static Fraction middle(const Fraction&, const Fraction&); + // approximate a fraction with defined denominator static Fraction setDenominator(const Fraction&, uint16_t); @@ -73,7 +75,4 @@ protected: int32_t d; }; -#endif -// // -- END OF FILE -- -// \ No newline at end of file diff --git a/libraries/Fraction/keywords..txt b/libraries/Fraction/keywords..txt new file mode 100644 index 00000000..46cc6e95 --- /dev/null +++ b/libraries/Fraction/keywords..txt @@ -0,0 +1,18 @@ +# Syntax Coloring Map For Fraction + +# Datatypes (KEYWORD1) +Fraction KEYWORD1 + +# Methods and Functions (KEYWORD2) +toDouble KEYWORD2 +toFloat KEYWORD2 +isProper KEYWORD2 +toAngle KEYWORD2 +nominator KEYWORD2 +denominator KEYWORD2 +mediant KEYWORD2 +middle KEYWORD2 +setDenominator KEYWORD2 + +# Constants (LITERAL1) + diff --git a/libraries/Fraction/library.json b/libraries/Fraction/library.json index e78a057f..e45bf5c2 100644 --- a/libraries/Fraction/library.json +++ b/libraries/Fraction/library.json @@ -1,7 +1,7 @@ { "name": "Fraction", - "keywords": "Fraction,quotient,math,nominator,denominator", - "description": "Library for using fractions.", + "keywords": "Fraction, quotient, math, nominator, denominator", + "description": "Arduino library to implement a Fraction datatype. Nominator and denominator are limited to 4 digits. Experimental.", "authors": [ { @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/Fraction.git" }, - "version":"0.1.8", + "version":"0.1.10", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/Fraction" - } + "platforms": "*" } diff --git a/libraries/Fraction/library.properties b/libraries/Fraction/library.properties index 624cfb8a..b279b72e 100644 --- a/libraries/Fraction/library.properties +++ b/libraries/Fraction/library.properties @@ -1,9 +1,11 @@ name=Fraction -version=0.1.8 +version=0.1.10 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Library for using fractions. -paragraph= +sentence=Arduino library to implement a Fraction datatype +paragraph=Nominator and denominator are limited to 4 digits. Experimental. category=Data Processing -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/Fraction +architectures=* +includes=fraction.h +depends= diff --git a/libraries/Fraction/readme.md b/libraries/Fraction/readme.md index 0c557acb..5246bc96 100644 --- a/libraries/Fraction/readme.md +++ b/libraries/Fraction/readme.md @@ -1,12 +1,30 @@ +# Fraction + +Arduino library to implement a Fraction datatype (experimental) + +## Description + +The fraction library implements fractional numbers a.k.a. Q, +(integers are Z and floats/doubles are R), +and the conversion to floats. -Fraction is an experimental fraction library for the Arduino. The code is working with a number of limitations among others: - denominator is max 4 digits to keep code for multiply and divide simple -- therefore not all fractions are exact +- Fractions are not exact (even floats are not exact) - the range of numbers supported is limited. +- code is experimental still. That said, the library is useful e.g. to display float numbers as a fraction. From programming point of view the fractionize function, converting a double into a fraction is a nice programming problem, fast with a minimal error. -In short, use fractions with care otherwise your sketch might get broken ;) \ No newline at end of file +In short, use fractions with care otherwise your sketch might get broken ;) + +## Operations + +See examples + +## Use with care + +The library is reasonably tested, and if problems arise please let me know. + diff --git a/libraries/FunctionGenerator/FunctionGenerator.h b/libraries/FunctionGenerator/FunctionGenerator.h index 4531fa7e..424b6a2c 100644 --- a/libraries/FunctionGenerator/FunctionGenerator.h +++ b/libraries/FunctionGenerator/FunctionGenerator.h @@ -1,300 +1,59 @@ +#pragma once // // FILE: functionGenerator.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.04 -// PURPOSE: functionGenerator functions (use with care) -// URL: -// -// HISTORY: -// 0.1.00 - 2015-01-01 - initial version -// 0.1.01 - 2015-01-01 - initial class version -// 0.1.02 - 2015-01-01 - refactor and research -// 0.1.03 - 2015-01-02 - added stair, more refactoring -// 0.1.04 - 2015-01-03 - added integer versions - to be used with 8 bit DAC +// VERSION: 0.2.0 +// PURPOSE: wave form generating functions (use with care) +// URL: https://github.com/RobTillaart/FunctionGenerator // -#ifndef functiongenerator_h -#define functiongenerator_h +#include "Arduino.h" - -#if ARDUINO < 100 -#include -#else -#include -#endif - -#define FUNCTIONGENERATOR_LIB_VERSION "0.1.04" +#define FUNCTIONGENERATOR_LIB_VERSION "0.2.0" class funcgen { public: - funcgen(double period = 1.0, double amplitude = 1.0, double phase = 0.0, double yShift = 0.0) - { - begin(period, amplitude, phase, yShift); - } - - void begin(double period = 1.0, double amplitude = 1.0, double phase = 0.0, double yShift = 0.0) - { - _period = period; - _freq1 = 1 / period; - _freq2 = 2 * _freq1; - _freq4 = 4 * _freq1; - _freq0 = TWO_PI * _freq1; - _amplitude = amplitude; - _phase = phase; - _yShift = yShift; - } - - double sawtooth(double t) - { - double rv; - t += _phase; - if (t >= 0.0) - { - if (t >= _period) t = fmod(t, _period); - rv = _amplitude * (-1.0 + t *_freq2); - } - else - { - t = -t; - if (t >= _period) t = fmod(t, _period); - rv = _amplitude * ( 1.0 - t * _freq2); - } - rv += _yShift; - return rv; - } - - double triangle(double t) - { - double rv; - t += _phase; - if (t < 0.0) - { - t = -t; - } - if (t >= _period) t = fmod(t, _period); - if ( t * 2 < _period) - { - rv = _amplitude * (-1.0 + t * _freq4); - } - else - { - rv = _amplitude * (3.0 - t * _freq4); - } - rv += _yShift; - return rv; - } - - double square(double t) - { - double rv; - t += _phase; - if (t >= 0) - { - if (t >= _period) t = fmod(t, _period); - if ((t + t) < _period) rv = _amplitude; - else rv = -_amplitude; - } - else - { - t = -t; - if (t >= _period) t = fmod(t, _period); - if ( t * 2 < _period) rv = -_amplitude; - else rv = _amplitude; - } - rv += _yShift; - return rv; - } - - double sinus(double t) - { - double rv; - t += _phase; - rv = _amplitude * sin(t * _freq0); - rv += _yShift; - return rv; - } - - double stair(double t, uint16_t steps = 8) - { - t += _phase; - if (t >= 0) - { - if (t >= _period) t = fmod(t, _period); - int level = steps * t / _period; - return _yShift + _amplitude * (-1.0 + 2.0 * level / (steps - 1)); - } - - t = -t; - if (t >= _period) t = fmod(t, _period); - int level = steps * t / _period; - return _yShift + _amplitude * (1.0 - 2.0 * level / (steps - 1)); - } + funcgen(float period = 1.0, float amplitude = 1.0, float phase = 0.0, float yShift = 0.0); + // configuration + void setPeriod(float period = 1.0); + float getPeriod() { return _period; }; + void setFrequency(float freq = 1.0) { setPeriod(1/freq); }; + float getFrequency() { return _freq1; }; + void setAmplitude(float ampl = 1.0) { _amplitude = ampl; }; + float getAmplitude() { return _amplitude; }; + void setPhase(float phase = 0.0) { _phase = phase; }; + float getPhase() { return _phase; }; + void setYShift(float yShift = 0.0) { _yShift = yShift; }; + float getYShift() { return _yShift; }; + + // constant amplitude + float line(); + // constant zero for calibration + float zero(); + + // standard wave forms + float sawtooth(float t); + float triangle(float t); + float square(float t); + float sinus(float t); + float stair(float t, uint16_t steps = 8); + float random(); private: - double _period; - double _freq0; - double _freq1; - double _freq2; - double _freq4; - double _amplitude; - double _phase; - double _yShift; + float _period; + float _freq0; + float _freq1; + float _freq2; + float _freq4; + float _amplitude; + float _phase; + float _yShift; + // Marsaglia 'constants' + uint32_t _m_w = 1; + uint32_t _m_z = 2; + uint32_t _random(); }; -// -// INTEGER VERSIONS FOR 8 BIT DAC -// -// 8 bits version -// t = 0..9999 period 10000 in millis, returns 0..255 - -/* -uint8_t ifgsaw(uint16_t t, uint16_t period = 1000) -{ - return 255L * t / period; -} - -uint8_t ifgtri(uint16_t t, uint16_t period = 1000) -{ - if (t * 2 < period) return 510L * t / period; - return 255L - 510L * t / period; -} - -uint8_t ifgsqr(uint16_t t, uint16_t period = 1000) -{ - if (t * 2 < period) return 510L * t / period; - return 255L - 510L * t / period; -} - -uint8_t ifgsin(uint16_t t, uint16_t period = 1000) -{ - return sin(355L * t / period / 113); // LUT -} - -uint8_t ifgstr(uint16_t t, uint16_t period = 1000, uint16_t steps = 8) -{ - int level = 1L * steps * t / period; - return 255L * level / (steps - 1); -} -*/ - -// -// SIMPLE DOUBLE ONES -// -// t = 0..period -// period = 0.001 ... 10000 ? -/* -double fgsaw(double t, double period = 1.0) -{ - if (t >= 0) return -1.0 + 2 * t / period; - return 1.0 + 2 * t / period; -} - -double fgtri(double t, double period = 1.0) -{ - if (t < 0) t = -t; - if (t * 2 < period) return -1.0 + 4 * t / period; - return 3.0 - 4 * t / period; -} - -double fgsqr(double t, double period = 1.0) -{ - if (t >= 0) - { - if ( 2 * t < period) return 1.0; - return -1.0; - } - t = -t; - if (2 * t < period) return -1.0; - return 1.0; -} - -double fgsin(double t, double period = 1.0) -{ - return sin(TWO_PI * t / period); -} - -double fgstr(double t, double period = 1.0, uint16_t steps = 8) -{ - if (t >= 0) - { - int level = steps * t / period; - return -1.0 + 2.0 * level / (steps - 1); - } - t = -t; - int level = steps * t / period; - return 1.0 - 2.0 * level / (steps - 1); -} -*/ - -// -// FULL DOUBLES ONES -// -double fgsaw(double t, double period = 1.0, double amplitude = 1.0, double phase = 0.0, double yShift = 0.0) -{ - t += phase; - if (t >= 0) - { - if (t >= period) t = fmod(t, period); - return yShift + amplitude * (-1.0 + 2 * t / period); - } - t = -t; - if (t >= period) t = fmod(t, period); - return yShift + amplitude * ( 1.0 - 2 * t / period); -} - -double fgtri(double t, double period = 1.0, double amplitude = 1.0, double phase = 0.0, double yShift = 0.0, double dutyCycle = 0.50) -{ - t += phase; - if (t < 0) t = -t; - if (t >= period) t = fmod(t, period); - // 50 % dutyCycle = faster - // if (t * 2 < period) return yShift + amplitude * (-1.0 + 4 * t / period); - // return yShift + amplitude * (3.0 - 4 * t / period); - if (t < dutyCycle * period) return yShift + amplitude * (-1.0 + 2 * t / (dutyCycle * period)); - // return yShift + amplitude * (-1.0 + 2 / (1 - dutyCycle) - 2 * t / ((1 - dutyCycle) * period)); - return yShift + amplitude * (-1.0 + 2 / (1 - dutyCycle) * ( 1 - t / period)); -} - -double fgsqr(double t, double period = 1.0, double amplitude = 1.0, double phase = 0.0, double yShift = 0.0, double dutyCycle = 0.50) -{ - t += phase; - if (t >= 0) - { - if (t >= period) t = fmod(t, period); - if (t < dutyCycle * period) return yShift + amplitude; - return yShift - amplitude; - } - t = -t; - if (t >= period) t = fmod(t, period); - if (t < dutyCycle * period) return yShift - amplitude; - return yShift + amplitude; -} - -double fgsin(double t, double period = 1.0, double amplitude = 1.0, double phase = 0.0, double yShift = 0.0) -{ - t += phase; - double rv = yShift + amplitude * sin(TWO_PI * t / period); - return rv; -} - -double fgstr(double t, double period = 1.0, double amplitude = 1.0, double phase = 0.0, double yShift = 0.0, uint16_t steps = 8) -{ - t += phase; - if (t >= 0) - { - if (t >= period) t = fmod(t, period); - int level = steps * t / period; - return yShift + amplitude * (-1.0 + 2.0 * level / (steps - 1)); - } - t = -t; - if (t >= period) t = fmod(t, period); - int level = steps * t / period; - return yShift + amplitude * (1.0 - 2.0 * level / (steps - 1)); -} - -#endif -// // END OF FILE -// \ No newline at end of file diff --git a/libraries/FunctionGenerator/LICENSE b/libraries/FunctionGenerator/LICENSE new file mode 100644 index 00000000..e563929f --- /dev/null +++ b/libraries/FunctionGenerator/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2015-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/FunctionGenerator/examples/functionGenerator/functionGenerator.ino b/libraries/FunctionGenerator/examples/functionGenerator/functionGenerator.ino index e83f5241..0a5e13aa 100644 --- a/libraries/FunctionGenerator/examples/functionGenerator/functionGenerator.ino +++ b/libraries/FunctionGenerator/examples/functionGenerator/functionGenerator.ino @@ -1,44 +1,54 @@ // // FILE: functionGenerator.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.02 +// VERSION: 0.2.0 // PURPOSE: demo function generators // DATE: 2015-01-03 -// URL: -// -// Released to the public domain +// URL: https://github.com/RobTillaart/FunctionGenerator // #include "functionGenerator.h" +funcgen gen; + uint32_t lastTime = 0; +char choice = '0'; void setup() { - Serial.begin(115200); + Serial.begin(500000); + Serial.println(__FILE__); Serial.println("Start "); + gen.setFrequency(4); + gen.setAmplitude(50); } void loop() { - uint32_t now = millis(); - int choice = analogRead(A0) / 200; // signal selection potMeter - - int period = 1000; // in milliseconds - float val; - - if (now != lastTime) + if (Serial.available()) { - lastTime = now; - int p = now % period; + choice = Serial.read(); + } + // wave selection by potMeter + // int choice = analogRead(A0) / 200; + + float val; + // wait for next millisecond; + if (millis() - lastTime > 0) + { + lastTime = millis(); + float t = lastTime * 0.001; switch (choice) { - case 0: val = fgsqr(p, period); break; - case 1: val = fgsaw(p, period); break; - case 2: val = fgtri(p, period); break; - case 3: val = fgstr(p, period); break; - default: val = fgsin(p, period); break; + case '0': val = gen.square(t); break; + case '1': val = gen.sawtooth(t); break; + case '2': val = gen.triangle(t); break; + case '3': val = gen.stair(t); break; + case '4': val = gen.sinus(t); break; + case '5': val = gen.line(); break; + case '6': val = gen.random(); break; + default: val = gen.zero(); break; } Serial.println(val); } diff --git a/libraries/FunctionGenerator/examples/functionGeneratorDuoPlot/functionGeneratorDuoPlot.ino b/libraries/FunctionGenerator/examples/functionGeneratorDuoPlot/functionGeneratorDuoPlot.ino new file mode 100644 index 00000000..7b0666f9 --- /dev/null +++ b/libraries/FunctionGenerator/examples/functionGeneratorDuoPlot/functionGeneratorDuoPlot.ino @@ -0,0 +1,47 @@ +// +// FILE: functionGeneratorDuoPlot.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: demo function generators +// DATE: 2020-06-10 +// URL: https://github.com/RobTillaart/FunctionGenerator +// +// use a Serial plotter to show the data + + +#include "functionGenerator.h" + +funcgen gen1; +funcgen gen2; + +void setup() +{ + Serial.begin(115200); + // Serial.print("Start functionGeneratorPerformance - LIB VERSION: "); + // Serial.println(FUNCTIONGENERATOR_LIB_VERSION); + + gen1.setFrequency(13); + gen1.setAmplitude(50); + gen1.setPhase(0); + gen1.setYShift(0); + + gen2.setFrequency(17); + gen2.setAmplitude(25); + gen2.setPhase(0.25); + gen2.setYShift(25); +} + +void loop() +{ + float t = millis() * 0.001; + float x = gen1.sinus(t); + float y = gen2.sinus(t); + Serial.print(x); + Serial.print("\t"); + Serial.print(y); + Serial.print("\t"); + Serial.print(x + y); + Serial.println(); +} + +// END OF FILE diff --git a/libraries/FunctionGenerator/examples/functionGeneratorPerformance/functionGeneratorPerformance.ino b/libraries/FunctionGenerator/examples/functionGeneratorPerformance/functionGeneratorPerformance.ino index 1331e6fa..bfe7e5ce 100644 --- a/libraries/FunctionGenerator/examples/functionGeneratorPerformance/functionGeneratorPerformance.ino +++ b/libraries/FunctionGenerator/examples/functionGeneratorPerformance/functionGeneratorPerformance.ino @@ -1,12 +1,10 @@ // // FILE: functionGeneratorPerformance.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.00 +// VERSION: 0.2.0 // PURPOSE: demo function generators // DATE: 2015-01-01 -// URL: -// -// Released to the public domain +// URL: https://github.com/RobTillaart/FunctionGenerator // #include "functionGenerator.h" @@ -14,46 +12,58 @@ uint32_t start; uint32_t stop; -volatile double t; -volatile double y; +volatile float t; +volatile float y; + +funcgen gen; void setup() { Serial.begin(115200); - Serial.println("Start functionGeneratorPerformance - LIB VERSION: "); + Serial.print("Start functionGeneratorPerformance - LIB VERSION: "); Serial.println(FUNCTIONGENERATOR_LIB_VERSION); - Serial.println("func \t usec\t max calls/sec"); + Serial.println("func \t\tusec\tmax calls/sec"); y = analogRead(A0) / 1024; - test_fgsqr(); + test_square(); delay(10); - test_fgsaw(); + test_sawtooth(); delay(10); - test_fgtri(); + test_triangle(); delay(10); - test_fgsin(); + test_sinus(); delay(10); - test_fgstr(); + test_stair(); + delay(10); + test_random(); + delay(10); + test_line(); + delay(10); + test_zero(); delay(10); Serial.println(); - Serial.println("t \t sqr\t saw\t tri\t sin\t str"); + Serial.println("t \t sqr\t saw\t tri\t sin\t str\t rnd\t line\t zero"); for (int i = -400; i < 400; i += 2) { - // func(double t, double period = 1.0, double amplitude = 1.0, double phase = 0.0, double yShift = 0.0) - double t = i * 0.01; + float t = i * 0.01; Serial.print(t); Serial.print("\t"); - Serial.print(fgsqr(t)); + Serial.print(gen.square(t)); Serial.print("\t"); - Serial.print(fgsaw(t)); //, 2.0, 1.0, 0.5)); + Serial.print(gen.sawtooth(t)); Serial.print("\t"); - Serial.print(fgtri(t)); //, 1.0, 0.5, 1.0)); + Serial.print(gen.triangle(t)); Serial.print("\t"); - Serial.print(fgsin(t)); // , TWO_PI, 1.0, PI / 4)); // period 2PI, phase = 45° - // Serial.print(fgsin(t, 1.0, 0.5, -0.5, 0.5)); + Serial.print(gen.sinus(t)); Serial.print("\t"); - Serial.print(fgstr(t)); + Serial.print(gen.stair(t)); + Serial.print("\t"); + Serial.print(gen.random()); + Serial.print("\t"); + Serial.print(gen.line()); + Serial.print("\t"); + Serial.print(gen.zero()); Serial.println(); } Serial.println("\ndone..."); @@ -62,71 +72,121 @@ void setup() /******************************************************************/ -void test_fgsqr() +void test_square() { start = micros(); for (int i = 0; i < 10000; i++) { - t = fgsqr(i); + t = gen.square(i); } stop = micros(); - Serial.print("fsqr:\t"); + Serial.print(__FUNCTION__); + Serial.print(":\t"); Serial.print((stop - start) / 10000.0); Serial.print("\t"); Serial.println(1000000.0 / ((stop - start) / 10000.0)); } -void test_fgsaw() +void test_sawtooth() { start = micros(); for (int i = 0; i < 10000; i++) { - t = fgsaw(i); + t = gen.sawtooth(i); } stop = micros(); - Serial.print("fsaw:\t"); + Serial.print(__FUNCTION__); + Serial.print(":\t"); Serial.print((stop - start) / 10000.0); Serial.print("\t"); Serial.println(1000000.0 / ((stop - start) / 10000.0)); } -void test_fgtri() +void test_triangle() { start = micros(); for (int i = 0; i < 10000; i++) { - t = fgtri(i); + t = gen.triangle(i); } stop = micros(); - Serial.print("ftri:\t"); + Serial.print(__FUNCTION__); + Serial.print(":\t"); Serial.print((stop - start) / 10000.0); Serial.print("\t"); Serial.println(1000000.0 / ((stop - start) / 10000.0)); } -void test_fgsin() +void test_sinus() { start = micros(); for (int i = 0; i < 10000; i++) { - t = fgsin(i); + t = gen.sinus(i); } stop = micros(); - Serial.print("fsin:\t"); + Serial.print(__FUNCTION__); + Serial.print(":\t"); Serial.print((stop - start) / 10000.0); Serial.print("\t"); Serial.println(1000000.0 / ((stop - start) / 10000.0)); } -void test_fgstr() +void test_stair() { start = micros(); for (int i = 0; i < 10000; i++) { - t = fgstr(i); + t = gen.stair(i); } stop = micros(); - Serial.print("fstr:\t"); + Serial.print(__FUNCTION__); + Serial.print(":\t"); + Serial.print((stop - start) / 10000.0); + Serial.print("\t"); + Serial.println(1000000.0 / ((stop - start) / 10000.0)); +} + +void test_random() +{ + start = micros(); + for (int i = 0; i < 10000; i++) + { + t = gen.random(); + } + stop = micros(); + Serial.print(__FUNCTION__); + Serial.print(":\t"); + Serial.print((stop - start) / 10000.0); + Serial.print("\t"); + Serial.println(1000000.0 / ((stop - start) / 10000.0)); +} + +void test_line() +{ + start = micros(); + for (int i = 0; i < 10000; i++) + { + t = gen.line(); + } + stop = micros(); + Serial.print(__FUNCTION__); + Serial.print(":\t"); + Serial.print((stop - start) / 10000.0); + Serial.print("\t"); + Serial.println(1000000.0 / ((stop - start) / 10000.0)); +} + +void test_zero() +{ + start = micros(); + for (int i = 0; i < 10000; i++) + { + t = gen.zero(); + } + stop = micros(); + Serial.print(__FUNCTION__); + Serial.print(":\t"); Serial.print((stop - start) / 10000.0); Serial.print("\t"); Serial.println(1000000.0 / ((stop - start) / 10000.0)); @@ -136,4 +196,4 @@ void loop() { } -// END OF FILE \ No newline at end of file +// END OF FILE diff --git a/libraries/FunctionGenerator/examples/functionGeneratorPlotter/functionGeneratorPlotter.ino b/libraries/FunctionGenerator/examples/functionGeneratorPlotter/functionGeneratorPlotter.ino new file mode 100644 index 00000000..3c66b6f1 --- /dev/null +++ b/libraries/FunctionGenerator/examples/functionGeneratorPlotter/functionGeneratorPlotter.ino @@ -0,0 +1,46 @@ +// +// FILE: functionGeneratorPlotter.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: demo function generators +// DATE: 2020-06-10 +// URL: https://github.com/RobTillaart/FunctionGenerator +// +// use a Serial plotter to show the data + + +#include "functionGenerator.h" + +funcgen gen; + +void setup() +{ + Serial.begin(115200); + // Serial.print("Start functionGeneratorPerformance - LIB VERSION: "); + // Serial.println(FUNCTIONGENERATOR_LIB_VERSION); + + gen.setAmplitude(50); +} + +void loop() +{ + float t = millis() * 0.001; + Serial.print(gen.square(t)); + Serial.print("\t"); + Serial.print(gen.sawtooth(t)); + Serial.print("\t"); + Serial.print(gen.triangle(t)); + Serial.print("\t"); + Serial.print(gen.sinus(t)); + Serial.print("\t"); + Serial.print(gen.stair(t)); + Serial.print("\t"); + Serial.print(gen.random()); + Serial.print("\t"); + Serial.print(gen.line()); + Serial.print("\t"); + Serial.print(gen.zero()); + Serial.println(); +} + +// END OF FILE diff --git a/libraries/FunctionGenerator/functionGenerator.cpp b/libraries/FunctionGenerator/functionGenerator.cpp new file mode 100644 index 00000000..c08fc292 --- /dev/null +++ b/libraries/FunctionGenerator/functionGenerator.cpp @@ -0,0 +1,300 @@ +// +// FILE: functionGenerator.cpp +// AUTHOR: Rob Tillaart +// VERSION: 0.2.0 +// PURPOSE: wave form generating functions (use with care) +// URL: https://github.com/RobTillaart/FunctionGenerator +// +// HISTORY: +// 0.1.00 2015-01-01 initial version +// 0.1.01 2015-01-01 initial class version +// 0.1.02 2015-01-01 refactor and research +// 0.1.03 2015-01-02 added stair, more refactoring +// 0.1.04 2015-01-03 added integer versions - to be used with 8 bit DAC +// 0.1.5 2017-07-29 Fix issue #33 (dbl -> float) +// 0.2.0 2020-06-10 main refactoring and cleanup + +#include "functionGenerator.h" + +funcgen::funcgen(float period, float amplitude, float phase, float yShift) +{ + setPeriod(period); + setAmplitude(amplitude); + setPhase(phase); + setYShift(yShift); +} + +void funcgen::setPeriod(float period) +{ + _period = period; + _freq1 = 1 / period; + _freq2 = 2 * _freq1; + _freq4 = 4 * _freq1; + _freq0 = TWO_PI * _freq1; +} + +float funcgen::line() +{ + return _yShift + _amplitude; +} + +float funcgen::zero() +{ + return 0; +} + +float funcgen::sawtooth(float t) +{ + float rv; + t += _phase; + if (t >= 0.0) + { + if (t >= _period) t = fmod(t, _period); + rv = _amplitude * (-1.0 + t *_freq2); + } + else + { + t = -t; + if (t >= _period) t = fmod(t, _period); + rv = _amplitude * ( 1.0 - t * _freq2); + } + rv += _yShift; + return rv; +} + +float funcgen::triangle(float t) +{ + float rv; + t += _phase; + if (t < 0.0) + { + t = -t; + } + if (t >= _period) t = fmod(t, _period); + if ( t * 2 < _period) + { + rv = _amplitude * (-1.0 + t * _freq4); + } + else + { + rv = _amplitude * (3.0 - t * _freq4); + } + rv += _yShift; + return rv; +} + +float funcgen::square(float t) +{ + float rv; + t += _phase; + if (t >= 0) + { + if (t >= _period) t = fmod(t, _period); + if ((t + t) < _period) rv = _amplitude; + else rv = -_amplitude; + } + else + { + t = -t; + if (t >= _period) t = fmod(t, _period); + if ( t * 2 < _period) rv = -_amplitude; + else rv = _amplitude; + } + rv += _yShift; + return rv; +} + +float funcgen::sinus(float t) +{ + float rv; + t += _phase; + rv = _amplitude * sin(t * _freq0); + rv += _yShift; + return rv; +} + +float funcgen::stair(float t, uint16_t steps) +{ + t += _phase; + if (t >= 0) + { + if (t >= _period) t = fmod(t, _period); + int level = steps * t / _period; + return _yShift + _amplitude * (-1.0 + 2.0 * level / (steps - 1)); + } + t = -t; + if (t >= _period) t = fmod(t, _period); + int level = steps * t / _period; + return _yShift + _amplitude * (1.0 - 2.0 * level / (steps - 1)); +} + +float funcgen::random() +{ + // TODO smart reseed needed + float rv = _yShift + _amplitude * _random() * 0.2328306436E-9; // div 0xFFFFFFFF + return rv; +} + +// An example of a simple pseudo-random number generator is the +// Multiply-with-carry method invented by George Marsaglia. +// two initializers (not null) +uint32_t funcgen::_random() +{ + _m_z = 36969L * (_m_z & 65535L) + (_m_z >> 16); + _m_w = 18000L * (_m_w & 65535L) + (_m_w >> 16); + return (_m_z << 16) + _m_w; /* 32-bit result */ +} + + +// +// INTEGER VERSIONS FOR 8 BIT DAC +// +// 8 bits version +// t = 0..9999 period 10000 in millis, returns 0..255 + +/* +uint8_t ifgsaw(uint16_t t, uint16_t period = 1000) +{ + return 255L * t / period; +} + +uint8_t ifgtri(uint16_t t, uint16_t period = 1000) +{ + if (t * 2 < period) return 510L * t / period; + return 255L - 510L * t / period; +} + +uint8_t ifgsqr(uint16_t t, uint16_t period = 1000) +{ + if (t * 2 < period) return 510L * t / period; + return 255L - 510L * t / period; +} + +uint8_t ifgsin(uint16_t t, uint16_t period = 1000) +{ + return sin(355L * t / period / 113); // LUT +} + +uint8_t ifgstr(uint16_t t, uint16_t period = 1000, uint16_t steps = 8) +{ + int level = 1L * steps * t / period; + return 255L * level / (steps - 1); +} +*/ + +// +// SIMPLE float ONES +// +// t = 0..period +// period = 0.001 ... 10000 ? +/* +float fgsaw(float t, float period = 1.0) +{ + if (t >= 0) return -1.0 + 2 * t / period; + return 1.0 + 2 * t / period; +} + +float fgtri(float t, float period = 1.0) +{ + if (t < 0) t = -t; + if (t * 2 < period) return -1.0 + 4 * t / period; + return 3.0 - 4 * t / period; +} + +float fgsqr(float t, float period = 1.0) +{ + if (t >= 0) + { + if ( 2 * t < period) return 1.0; + return -1.0; + } + t = -t; + if (2 * t < period) return -1.0; + return 1.0; +} + +float fgsin(float t, float period = 1.0) +{ + return sin(TWO_PI * t / period); +} + +float fgstr(float t, float period = 1.0, uint16_t steps = 8) +{ + if (t >= 0) + { + int level = steps * t / period; + return -1.0 + 2.0 * level / (steps - 1); + } + t = -t; + int level = steps * t / period; + return 1.0 - 2.0 * level / (steps - 1); +} +*/ + +// +// FULL floatS ONES +// +float fgsaw(float t, float period = 1.0, float amplitude = 1.0, float phase = 0.0, float yShift = 0.0) +{ + t += phase; + if (t >= 0) + { + if (t >= period) t = fmod(t, period); + return yShift + amplitude * (-1.0 + 2 * t / period); + } + t = -t; + if (t >= period) t = fmod(t, period); + return yShift + amplitude * ( 1.0 - 2 * t / period); +} + +float fgtri(float t, float period = 1.0, float amplitude = 1.0, float phase = 0.0, float yShift = 0.0, float dutyCycle = 0.50) +{ + t += phase; + if (t < 0) t = -t; + if (t >= period) t = fmod(t, period); + // 50 % dutyCycle = faster + // if (t * 2 < period) return yShift + amplitude * (-1.0 + 4 * t / period); + // return yShift + amplitude * (3.0 - 4 * t / period); + if (t < dutyCycle * period) return yShift + amplitude * (-1.0 + 2 * t / (dutyCycle * period)); + // return yShift + amplitude * (-1.0 + 2 / (1 - dutyCycle) - 2 * t / ((1 - dutyCycle) * period)); + return yShift + amplitude * (-1.0 + 2 / (1 - dutyCycle) * ( 1 - t / period)); +} + +float fgsqr(float t, float period = 1.0, float amplitude = 1.0, float phase = 0.0, float yShift = 0.0, float dutyCycle = 0.50) +{ + t += phase; + if (t >= 0) + { + if (t >= period) t = fmod(t, period); + if (t < dutyCycle * period) return yShift + amplitude; + return yShift - amplitude; + } + t = -t; + if (t >= period) t = fmod(t, period); + if (t < dutyCycle * period) return yShift - amplitude; + return yShift + amplitude; +} + +float fgsin(float t, float period = 1.0, float amplitude = 1.0, float phase = 0.0, float yShift = 0.0) +{ + t += phase; + float rv = yShift + amplitude * sin(TWO_PI * t / period); + return rv; +} + +float fgstr(float t, float period = 1.0, float amplitude = 1.0, float phase = 0.0, float yShift = 0.0, uint16_t steps = 8) +{ + t += phase; + if (t >= 0) + { + if (t >= period) t = fmod(t, period); + int level = steps * t / period; + return yShift + amplitude * (-1.0 + 2.0 * level / (steps - 1)); + } + t = -t; + if (t >= period) t = fmod(t, period); + int level = steps * t / period; + return yShift + amplitude * (1.0 - 2.0 * level / (steps - 1)); +} + +// END OF FILE diff --git a/libraries/FunctionGenerator/keywords.txt b/libraries/FunctionGenerator/keywords.txt new file mode 100644 index 00000000..53259d13 --- /dev/null +++ b/libraries/FunctionGenerator/keywords.txt @@ -0,0 +1,28 @@ +# Syntax Coloring Map for funcgen + +# Datatypes (KEYWORD1) +funcgen KEYWORD1 + +# Methods and Functions (KEYWORD2) +setPeriod KEYWORD2 +getPeriod KEYWORD2 +setFrequency KEYWORD2 +getFrequency KEYWORD2 +setAmplitude KEYWORD2 +getAmplitude KEYWORD2 +setPhase KEYWORD2 +getPhase KEYWORD2 +setYShift KEYWORD2 +getYShift KEYWORD2 + +sawtooth KEYWORD2 +triangle KEYWORD2 +square KEYWORD2 +sinus KEYWORD2 +stair KEYWORD2 +random KEYWORD2 +line KEYWORD2 +zero KEYWORD2 + +# Constants (LITERAL1) + diff --git a/libraries/FunctionGenerator/library.json b/libraries/FunctionGenerator/library.json index f0eadcbe..c2139f93 100644 --- a/libraries/FunctionGenerator/library.json +++ b/libraries/FunctionGenerator/library.json @@ -1,7 +1,7 @@ { "name": "FunctionGenerator", "keywords": "Function,wave,generator,sawtooth,sinus,square,stair,triangle", - "description": "Experimental library for waveform generation (SW).", + "description": "Arduino library to generate wave forms (nummeric) for a DAC", "authors": [ { @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/FunctionGenerator" }, - "version":"0.1.4", + "version":"0.2.0", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/FunctionGenerator" - } + "platforms": "*" } diff --git a/libraries/FunctionGenerator/library.properties b/libraries/FunctionGenerator/library.properties index bd0454bf..e5b395c2 100644 --- a/libraries/FunctionGenerator/library.properties +++ b/libraries/FunctionGenerator/library.properties @@ -1,9 +1,11 @@ name=FunctionGenerator -version=0.1.4 +version=0.2.0 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Experimental library for waveform generation (SW). +sentence=Arduino library to generate wave forms (nummeric) for a DAC paragraph=a.k.a. FunctionGenerator category=Data Processing -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/FunctionGenerator +architectures=* +includes=functionGenerator.h +depends= diff --git a/libraries/FunctionGenerator/readme.md b/libraries/FunctionGenerator/readme.md index a4d68986..bb129c2f 100644 --- a/libraries/FunctionGenerator/readme.md +++ b/libraries/FunctionGenerator/readme.md @@ -1,2 +1,44 @@ +# FunctionGenerator + +Arduino library to generate wave forms (nummeric) for a DAC + +## Description + +**Constructor** +* funcgen(float period = 1.0, float amplitude = 1.0, float phase = 0.0, float yShift = 0.0); +All parameters can be set in the constructor but also later in configuration. + +**Configuration** +* void setPeriod(float period = 1.0); // seconds +* float getPeriod(); +* void setFrequency(float freq = 1.0); // Hertz +* float getFrequency(); +* void setAmplitude(float ampl = 1.0); // - +* float getAmplitude(); +* void setPhase(float phase = 0.0); // phase of period +* float getPhase(); +* void setYShift(float yShift = 0.0); // shift in amplitude, zero point. +* float getYShift(); + +**Wave forms** +t is time in seconds +* float sawtooth(float t); +* float triangle(float t); +* float square(float t); +* float sinus(float t); +* float stair(float t, uint16_t steps = 8); +* float random(); +* float line(); +* float zero(); + +Line() and zero() are functions that can be used +to drive a constant voltage from a DAC and can be +used to calibrate the generator / DAC combination. + +## Operational + +See examples. + +TODO example with DAC. 8 12 16 bit. +TODO example with potmeters for 4 parameters -experimental diff --git a/libraries/HT16K33/HT16K33.cpp b/libraries/HT16K33/HT16K33.cpp index c781a8a0..f7a455ef 100644 --- a/libraries/HT16K33/HT16K33.cpp +++ b/libraries/HT16K33/HT16K33.cpp @@ -1,7 +1,7 @@ // // FILE: HT16K33.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.2.1 +// VERSION: 0.3.0 // DATE: 2019-02-07 // PURPOSE: Arduino Library for HT16K33 4x7segment display // URL: https://github.com/RobTillaart/HT16K33 @@ -15,6 +15,10 @@ // 0.1.5 2019-11-30 refactor, // 0.2.0 2020-06-13 ESP32 support; fix brightness bug; // 0.2.1 2020-07-15 fix #160 - decimal point +// 0.2.2 2020-10-04 added displayDate() thanks to bepitama +// 0.2.3 2020-10-09 issue #4 add negative values for displayInt() +// 0.2.4 2020-10-10 refactor #5 setDigits() iso suppressLeadingZeroPlaces() +// 0.3.0 2020-10-12 negative float, cache control, extend displayRaw() #include "HT16K33.h" @@ -97,19 +101,24 @@ void HT16K33::reset() { displayOn(); displayClear(); - suppressLeadingZeroPlaces(3); + setDigits(1); + clearCache(); + brightness(8); +} + +void HT16K33::clearCache() +{ for (uint8_t i = 0; i < 5; i++) { _displayCache[i] = HT16K33_NONE; } - brightness(8); } void HT16K33::displayOn() { writeCmd(HT16K33_ON); writeCmd(HT16K33_DISPLAYON); - brightness(_bright); // TODO needed? + brightness(_bright); } void HT16K33::displayOff() @@ -120,7 +129,6 @@ void HT16K33::displayOff() void HT16K33::blink(uint8_t val) { - // TODO cache blink state too? if (val > 0x03) val = 0x00; writeCmd(HT16K33_BLINKOFF | (val << 1) ); } @@ -133,10 +141,16 @@ void HT16K33::brightness(uint8_t val) writeCmd(HT16K33_BRIGHTNESS | _bright); } +void HT16K33::setDigits(uint8_t val) +{ + _digits = val > 4 ? 4 : val; +} + void HT16K33::suppressLeadingZeroPlaces(uint8_t val) { - _leadingZeroPlaces = val > 4 ? 4 : val; + _digits = val > 4 ? 0 : 4 - val; } + ////////////////////////////////////////// // // display functions @@ -148,18 +162,37 @@ void HT16K33::displayClear() displayColon(false); } -// 0000..9999 -// TODO negative numbers +// -999..9999 // DIV10 & DIV100 optimize? void HT16K33::displayInt(int n) { uint8_t x[4], h, l; + bool neg = (n < 0); + if (neg) n = -n; h = n / 100; l = n - h * 100; x[0] = h / 10; x[1] = h - x[0] * 10; x[2] = l / 10; x[3] = l - x[2] * 10; + + if (neg) + { + if (_digits >= 3) + { + x[0] = HT16K33_MINUS; + } + else + { + int i = 0; + for (i = 0; i < (4 - _digits); i++) + { + if (x[i] != 0) break; + x[i] = HT16K33_SPACE; + } + x[i-1] = HT16K33_MINUS; + } + } display(x); } @@ -176,6 +209,18 @@ void HT16K33::displayHex(uint16_t n) display(x); } +// 00.00 .. 99.99 +void HT16K33::displayDate(uint8_t left, uint8_t right) +{ + uint8_t x[4]; + x[0] = left / 10; + x[1] = left - x[0] * 10; + x[2] = right / 10; + x[3] = right - x[2] * 10; + display(x, 1); + displayColon(false); +} + // 00:00 .. 99:99 void HT16K33::displayTime(uint8_t left, uint8_t right) { @@ -189,13 +234,16 @@ void HT16K33::displayTime(uint8_t left, uint8_t right) } // only 0.000 .. 9999. -// TODO -999..-0.00 // TODO x.yEz void HT16K33::displayFloat(float f) { - // uint8_t neg = 0; - // if (f < 0) { neg = -1; f = -f; } - if (f > 9999 || f < 0 ) return; + if (f > 9999 || f < -999 ) + { + // display overflow ? + return; + } + bool neg = (f < 0); + if (neg) f = -f; int w = f; int pt = 3; @@ -220,6 +268,14 @@ void HT16K33::displayFloat(float f) x[1] = h - x[0] * 10; x[2] = l / 10; x[3] = l - x[2] * 10; + if (neg) // corrections for neg => all shift one position + { + x[3] = x[2]; + x[2] = x[1]; + x[1] = x[0]; + x[0] = HT16K33_MINUS; + pt++; + } display(x, pt); } @@ -236,12 +292,13 @@ void HT16K33::displayTest(uint8_t del) } } -void HT16K33::displayRaw(uint8_t *arr) +void HT16K33::displayRaw(uint8_t *arr, bool colon) { writePos(0, arr[0]); writePos(1, arr[1]); writePos(3, arr[2]); writePos(4, arr[3]); + writePos(2, colon ? 255 : 0); } void HT16K33::displayVULeft(uint8_t val) @@ -286,29 +343,24 @@ void HT16K33::displayVURight(uint8_t val) void HT16K33::display(uint8_t *arr) { - if (_leadingZeroPlaces) + for (uint8_t i = 0; i < (4 - _digits); i++) { - for (uint8_t i = 0; i < _leadingZeroPlaces; i++) - { - if (arr[i] != 0) break; - arr[i] = HT16K33_SPACE; - } + if (arr[i] != 0) break; + arr[i] = HT16K33_SPACE; } writePos(0, charmap[arr[0]]); writePos(1, charmap[arr[1]]); writePos(3, charmap[arr[2]]); writePos(4, charmap[arr[3]]); + + // debug to Serial + // dumpSerial(arr, 0); } void HT16K33::display(uint8_t *arr, uint8_t pnt) { - // to debug without display - // Serial.print(arr[0]); - // Serial.print(arr[1]); - // Serial.print(arr[2]); - // Serial.print(arr[3]); - // Serial.print(" "); - // Serial.println(pnt); + // debug to Serial + // dumpSerial(arr, pnt); writePos(0, charmap[arr[0]], pnt == 0); writePos(1, charmap[arr[1]], pnt == 1); @@ -321,6 +373,19 @@ void HT16K33::displayColon(uint8_t on) writePos(2, on ? 2 : 0); } +void HT16K33::dumpSerial(uint8_t *arr, uint8_t pnt) +{ + // to debug without display + for (int i = 0; i < 4; i++) + { + if (arr[i] == HT16K33_SPACE) Serial.print(" "); + else if (arr[i] == HT16K33_MINUS) Serial.print("-"); + else Serial.print(arr[i]); + } + Serial.print(" "); + Serial.println(pnt); +} + ////////////////////////////////////////////////////////// // // PRIVATE @@ -334,17 +399,18 @@ void HT16K33::writeCmd(uint8_t cmd) void HT16K33::writePos(uint8_t pos, uint8_t mask) { - if (_displayCache[pos] == mask) return; + if (_cache && (_displayCache[pos] == mask)) return; Wire.beginTransmission(_addr); Wire.write(pos * 2); Wire.write(mask); Wire.endTransmission(); - _displayCache[pos] = mask; + _displayCache[pos] = _cache ? mask : HT16K33_NONE; } void HT16K33::writePos(uint8_t pos, uint8_t mask, bool pnt) { if (pnt) mask |= 0x80; + else mask &= 0x7F; writePos(pos, mask); } diff --git a/libraries/HT16K33/HT16K33.h b/libraries/HT16K33/HT16K33.h index 87fe7a5d..90d91bdc 100644 --- a/libraries/HT16K33/HT16K33.h +++ b/libraries/HT16K33/HT16K33.h @@ -2,7 +2,7 @@ // // FILE: HT16K33.h // AUTHOR: Rob Tillaart -// VERSION: 0.2.1 +// VERSION: 0.3.0 // DATE: 2019-02-07 // PURPOSE: Arduino Library for HT16K33 4x7segment display // http://www.adafruit.com/products/1002 @@ -12,7 +12,7 @@ #include "Arduino.h" #include "Wire.h" -#define HT16K33_LIB_VERSION "0.2.1" +#define HT16K33_LIB_VERSION "0.3.0" class HT16K33 { @@ -25,30 +25,48 @@ public: void begin(); void reset(); + // default _cache is true as it is ~3x faster but if one has noise + // on the I2C and wants to force refresh one can disable caching + // for one or more calls. + void clearCache(); + void cacheOn() { _cache = true; }; + void cacheOff() { _cache = false; }; + void displayOn(); void displayOff(); void brightness(uint8_t val); // 0 .. 15 void blink(uint8_t val); // 0 .. 3 0 = off + // 0,1,2,3,4 digits - will replace suppressLeadingZeroPlaces + void setDigits(uint8_t val); // 0 = off, 1,2,3,4 digits space iso 0 - void suppressLeadingZeroPlaces(uint8_t val); + void suppressLeadingZeroPlaces(uint8_t val); // will be obsolete void displayClear(); - void displayInt(int n); // 0000 .. 9999 + void displayInt(int n); // -999 .. 9999 void displayHex(uint16_t n); // 0000 .. FFFF + + // Date could be {month.day} or {day.hour} . as separator + // Time could be hh:mm or mm:ss or ss:uu (hundreds : as separator + // + void displayDate(uint8_t left, uint8_t right); // 00.00 .. 99.99 void displayTime(uint8_t left, uint8_t right); // 00:00 .. 99:99 - void displayFloat(float f); // 0.000 .. 9999 + + void displayFloat(float f); // -999 .. 0.000 .. 9999 void display(uint8_t *arr); // array with 4 elements void display(uint8_t *arr, uint8_t pt); // pt = digit with . (0..3) void displayColon(uint8_t on); // 0 = off + void displayRaw(uint8_t *arr, bool colon = false); // max control - void displayTest(uint8_t del); // debug - void displayRaw(uint8_t *arr); // max control void displayVULeft(uint8_t val); // 0..8 void displayVURight(uint8_t val); // 0..8 + // DEBUG + void displayTest(uint8_t del); + void dumpSerial(uint8_t *arr, uint8_t pnt); + private: void writeCmd(uint8_t cmd); @@ -57,7 +75,8 @@ private: uint8_t _addr; uint8_t _displayCache[5]; // for performance - uint8_t _leadingZeroPlaces; + bool _cache = true; + uint8_t _digits = 0; uint8_t _bright; }; diff --git a/libraries/HT16K33/README.md b/libraries/HT16K33/README.md index 597b236a..e2d22056 100644 --- a/libraries/HT16K33/README.md +++ b/libraries/HT16K33/README.md @@ -7,10 +7,22 @@ Arduino Library for HT16K33 I2C 4x7segment display This library is for the Adafruit 4x7segment display with HT16K33 driver, http://www.adafruit.com/products/1002 -This library is functionally less capable than Adafruits especially -it has no support for negative numbers. -However it is much faster for writing an int / hex to the display. +This library is functionally less capable than Adafruits. +However as it caches the values written to the display per position +it is faster for writing on average. The actual gain depends on the +application and of course the values. + + +## Perfomance + +Version 0.3.0 allows one to switch the caching on/off to enforce +writing all positions e.g. in case of noisy I2C bus. + +The example **demo_cache.ino** measures the performance gain of caching +for different I2C bus speeds. + +``` Test on UNO, I2C.setClock(100000); // version 0.1.2 0-9999 integers 3.960 sec 0-65535 hexadecimal 23.685 sec @@ -19,33 +31,56 @@ Test on UNO, I2C.setClock(800000); // version 0.1.2 0-9999 integers 1.223 sec 0-65535 hexadecimal 6.350 sec -Substantial part of this performance gain is due to an internal -cache of the digits displayed, so other tests and real live -usage may result in different gain. +Test on UNO, I2C.setClock(100000); // version 0.3.0 +0-9999 integers 4.092 sec // ~3% slower due to robustness & cache control +0-65535 hexadecimal 24.336 sec +``` -## Release notes +## Multiple display -* 0.1.3 -**suppressLeadingZeroPlaces(val)** replaces leading zero with space. -Works only correctly for integers (for now). -If you have two (or multiple) displays to display long integers -you can suppress 4 zero's in the left display and 3 zero's in the right display. +The library supports only one display. Using multiple displays (cascading) e.g. to +display more than 4 digits must done by the user - see **demo_dual1.ino**. +With dual display it is important to **setDigits()** for the displays correctly to +get leading/railing zero's correctly. -* 0.1.4 -**displayRaw(ar[4])** added, to be able to display any pattern possible -**displayVULeft(val)** and **displayVURight(val)** added, shows 0..8 vertical bars, -uses **displayRaw()**. +## Interface -* 0.1.5 -refactor -added minus sign in the char map. +#### setup behaviour +- **HT16K33(address)** address is 0x70..0x77 depending on the jumpers A0..A2. **0x70** is default +- **void begin(sda, scl)** for ESP32, select I2C pins, initialize I2C and calls **reset()** +- **void begin()** initialize I2C and calls **reset()** +- **void reset()** resets display +- **void clearCache()** forced clearing of the cache, to be used to switch the cache off just for one write. +- **void cacheOn()** enable caching, this is default behavior +- **void cacheOff()** disable caching, will force writing to every position +- **void displayOn()** enable display +- **void displayOff()** disable display, fast way to darken display e.g. for energy consumption +- **void brightness(val)** values (dim) 0..15 (bright) +- **void blink(val)** values 0..3 0 = off +- **void setDigits(val)** values 0..4, minimal number of digits shown, mandatory for large numbers on dual display. +- **void suppressLeadingZeroPlaces(val)** obsolete, replaced by setDigits -* 0.2.0 -fix brightness bug -ESP32 support +#### datatypes +- **void displayClear()** empty display +- **void displayInt(n)** values -999 .. 9999 +- **void displayHex(n)** values 0000 .. FFFF +- **void displayDate(left, right)** values 00.00..99.99 Date could be {month.day} or {day.hour} . as separator +- **void displayTime(left, right)** values 00:00..99:99 Time could be hh:mm or mm:ss or ss:uu (hundreds) : as separator +- **void displayFloat(f)** values -999..0.000..9999, no overflow indication! -* 0.2.1 -fix decimal point in **printFloat()** +#### special +- **void displayVULeft(val)** display used as sort VU meter, values 0..8 +- **void displayVURight(val)** display used as sort VU meter, values 0..8 + +#### lower level workers +- **void display(uint8_t \*arr)** array of 4 bytes to control one 7seg display +- **void display(uint8_t \*arr, uint8_t pt)** idem + pt = position of the digit with point (0..3) +- **void displayColon(on)** 0 = off, all values other are on. +- **void displayRaw(uint8_t \*arr, colon)** array of 4 bytes to control one 7seg display + colon flag + +#### debugging +- **void displayTest(uint8_t del)** debugging / test function +- **void dumpSerial(uint8_t \*arr, uint8_t pt)** debugging equivalent of display. ## Operation diff --git a/libraries/HT16K33/examples/demo1/demo1.ino b/libraries/HT16K33/examples/demo1/demo1.ino index f906066c..284ba14f 100644 --- a/libraries/HT16K33/examples/demo1/demo1.ino +++ b/libraries/HT16K33/examples/demo1/demo1.ino @@ -1,5 +1,5 @@ // -// FILE: 4x7segmentI2C.ino +// FILE: demo1.ino // AUTHOR: Rob Tillaart // VERSION: 0.1.0 // PURPOSE: demo @@ -10,9 +10,7 @@ HT16K33 seg(0x70); -uint32_t start; -uint32_t stop; - +uint32_t start, stop; void setup() { @@ -43,14 +41,17 @@ void loop() Serial.println("dim()"); for (int i = 0; i < 16; i++) { + seg.displayHex(0xABC0 + i); seg.brightness(i); delay(500); } - for (int i = 15; i > 0; i--) + for (int i = 15; i >= 0; i--) { + seg.displayHex(0xABC0 + i); seg.brightness(i); delay(500); } + delay(1000); seg.brightness(2); Serial.println("displayClear()"); @@ -67,6 +68,26 @@ void loop() delay(500); } + Serial.println("displayDate()"); + uint8_t dpm[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 32, 30, 31 }; + for (uint8_t mo = 0; mo < 12; mo++) + { + for (uint8_t da = 1; da <= dpm[mo]; da++) + { + seg.displayDate(mo + 1, da); + delay(200); + } + } + + seg.displayTime(13, 25); + for (int i = 50; i < 60; i++) + { + seg.displayTime(13, i); + delay(500); + seg.displayColon(true); + delay(500); + } + Serial.println("float"); seg.displayClear(); delay(500); @@ -103,6 +124,7 @@ void loop() Serial.println("blink()"); for (uint8_t i = 0; i < 3; i++) { + seg.displayHex(0xABC0 + i); seg.blink(i); delay(4000); } @@ -110,7 +132,7 @@ void loop() Serial.print("INT TEST:\t"); start = millis(); - for (uint16_t counter = 0; counter < 9999; counter++) + for (int16_t counter = -999; counter < 9999; counter++) { seg.displayInt(counter); } @@ -126,6 +148,27 @@ void loop() } stop = millis(); Serial.println(stop - start); + + // Serial.print("SUPRESS ZERO TEST:\t"); + // for (uint8_t nlz = 0; nlz < 5; nlz++) + // { + // Serial.print(nlz); + // seg.suppressLeadingZeroPlaces(nlz); + // seg.displayInt(0); + // delay(1000); + // } + // seg.suppressLeadingZeroPlaces(0); + + Serial.print("SET DIGITS TEST:\t"); + for (uint8_t dig = 0; dig < 5; dig++) + { + Serial.print(dig); + seg.setDigits(dig); + seg.displayInt(0); + delay(1000); + } + seg.setDigits(1); + } // -- END OF FILE -- diff --git a/libraries/HT16K33/examples/demo_VU/demo_VU.ino b/libraries/HT16K33/examples/demo_VU/demo_VU.ino new file mode 100644 index 00000000..299ef6e9 --- /dev/null +++ b/libraries/HT16K33/examples/demo_VU/demo_VU.ino @@ -0,0 +1,136 @@ +// +// FILE: demo_VU.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: demo +// URL: http://www.adafruit.com/products/1002 +// URL: https://github.com/RobTillaart/HT16K33 + +// connect potmeter or so to A0 and A1 for the VU tests + +#include "HT16K33.h" + +HT16K33 seg(0x70); +uint32_t start, stop; +uint8_t ar[4]; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + + seg.begin(); + Wire.setClock(100000); + + seg.displayOn(); + seg.setDigits(4); + + Serial.println("displayTest()"); + seg.displayTest(10); + seg.displayOff(); + delay(1000); + seg.displayOn(); + seg.displayColon(false); +} + +void loop() +{ + test_VULeft(); + delay(1000); + test_VURight(); + delay(1000); + test_VUStereo(); + delay(1000); +} + +void test_VULeft() +{ + for (uint8_t run = 0; run < 50; run++) + { + int val = abs((sin(run * PI/ 50)) * 8); + seg.displayVULeft(val); + delay(100); + } +} + +void test_VURight() +{ + for (uint8_t run = 0; run < 50; run++) + { + int val = analogRead(A0); + val = val / 120; // 0..8 + seg.displayVURight(val); + delay(100); + } +} + +void test_VUStereo() +{ + for (uint8_t run = 0; run < 50; run++) + { + uint8_t left = analogRead(A0) / 240; // 0..4 + uint8_t right = analogRead(A1) / 240; // 0..4 + displayVUStereo(left, right); + delay(100); + } +} + +void displayVUStereo(uint8_t left, uint8_t right) +{ + switch (left) + { + case 0: + ar[0] = 0x00; + ar[1] = 0x00; + break; + case 1: + ar[0] = 0x00; + ar[1] = 0x06; + break; + case 2: + ar[0] = 0x00; + ar[1] = 0x36; + break; + case 3: + ar[0] = 0x06; + ar[1] = 0x36; + break; + case 4: + default: + ar[0] = 0x36; + ar[1] = 0x36; + break; + } + switch (right) + { + case 0: + ar[2] = 0x00; + ar[3] = 0x00; + break; + case 1: + ar[2] = 0x30; + ar[3] = 0x00; + break; + case 2: + ar[2] = 0x36; + ar[3] = 0x00; + break; + case 3: + ar[2] = 0x36; + ar[3] = 0x30; + break; + case 4: + default: + ar[2] = 0x36; + ar[3] = 0x36; + break; + } + seg.displayRaw(ar); + + // sort of heartbeat + static bool hb = false; + seg.displayColon(hb); + hb = !hb; +} + +// -- END OF FILE -- diff --git a/libraries/HT16K33/examples/demo_cache/demo_cache.ino b/libraries/HT16K33/examples/demo_cache/demo_cache.ino new file mode 100644 index 00000000..99b62e3b --- /dev/null +++ b/libraries/HT16K33/examples/demo_cache/demo_cache.ino @@ -0,0 +1,73 @@ +// +// FILE: demo_cache.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.1 +// PURPOSE: demo +// URL: http://www.adafruit.com/products/1002 +// URL: https://github.com/RobTillaart/HT16K33 + +#include "HT16K33.h" + +HT16K33 seg(0x70); + +uint32_t start, stop, d1, d2; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + + seg.begin(); + Wire.setClock(100000); + seg.displayOn(); + seg.brightness(2); + seg.displayClear(); + seg.blink(0); +} + +void loop() +{ + // Note: UNO fails for speed above 850K + // UNO 750K and 800K are using same clock divider + Serial.println("\nSPEED \tNOCACHE \tms/call \tCACHE\t\tms/call \tRATIO"); + for (uint32_t sp = 100000; sp < 900000; sp += 50000) + { + test_cache(sp); + } + Serial.println(); +} + +void test_cache(uint32_t speed) +{ + Wire.setClock(speed); + Serial.print(speed); + Serial.print("\t"); + seg.cacheOff(); + start = millis(); + for (int16_t counter = -999; counter < 10000; counter+=10) + { + seg.displayInt(counter); + } + d1 = millis() - start; + Serial.print(d1); + Serial.print("\t\t"); + Serial.print(d1 / 1100.0, 3); + Serial.print("\t\t"); + delay(100); + + seg.cacheOn(); + start = millis(); + for (int16_t counter = -999; counter < 10000; counter+=10) + { + seg.displayInt(counter); + } + d2 = millis() - start; + Serial.print(d2); + Serial.print("\t\t"); + Serial.print(d2 / 1100.0, 3); + Serial.print("\t\t"); + Serial.println(1.0 * d1 / d2, 3); + delay(1000); +} + +// -- END OF FILE -- diff --git a/libraries/HT16K33/examples/demo_displayInt/demo_displayInt.ino b/libraries/HT16K33/examples/demo_displayInt/demo_displayInt.ino new file mode 100644 index 00000000..1f85faa9 --- /dev/null +++ b/libraries/HT16K33/examples/demo_displayInt/demo_displayInt.ino @@ -0,0 +1,78 @@ +// +// FILE: demo_displayInt.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: demo +// URL: http://www.adafruit.com/products/1002 +// URL: https://github.com/RobTillaart/HT16K33 + +#include "HT16K33.h" + +HT16K33 seg(0x70); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + + seg.begin(); + Wire.setClock(100000); + seg.displayOn(); + seg.brightness(2); + seg.displayClear(); + seg.blink(0); +} + +void loop() +{ + Serial.print("INT TEST 0:\t"); + for (int16_t d = 4; d >= 0; d--) + { + seg.setDigits(d); + seg.displayInt(0); + delay(1000); + seg.setDigits(d); + seg.displayInt(8); + delay(1000); + seg.setDigits(d); + seg.displayInt(-8); + delay(1000); + } + for (int16_t d = 0; d <= 4; d++) + { + seg.setDigits(d); + seg.displayInt(0); + delay(1000); + seg.setDigits(d); + seg.displayInt(8); + delay(1000); + seg.setDigits(d); + seg.displayInt(-8); + delay(1000); + } + Serial.println(); + delay(1000); + + Serial.print("INT TEST 1:\t"); + seg.setDigits(1); + for (int16_t counter = -200; counter < 1001; counter += 7) + { + seg.displayInt(counter); + delay(100); + } + Serial.println(); + delay(1000); + + Serial.print("INT TEST 2:\t"); + seg.setDigits(4); + for (int16_t counter = -200; counter < 1001; counter += 7) + { + seg.displayInt(counter); + delay(100); + } + Serial.println(); + delay(1000); + +} + +// -- END OF FILE -- diff --git a/libraries/HT16K33/examples/demo_displayRaw/demo_displayRaw.ino b/libraries/HT16K33/examples/demo_displayRaw/demo_displayRaw.ino new file mode 100644 index 00000000..6d6935e2 --- /dev/null +++ b/libraries/HT16K33/examples/demo_displayRaw/demo_displayRaw.ino @@ -0,0 +1,82 @@ +// +// FILE: demo_displayRaw.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.1.0 +// PURPOSE: demo +// URL: http://www.adafruit.com/products/1002 +// URL: https://github.com/RobTillaart/HT16K33 + +#include "HT16K33.h" + +HT16K33 seg(0x70); + +uint32_t start, stop, d1, d2; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + + seg.begin(); + Wire.setClock(100000); + seg.displayOn(); + seg.brightness(2); + seg.displayClear(); + seg.blink(0); + + seg.cacheOff(); + start = millis(); + seg.displayTest(0); + Serial.println(millis() - start); + + seg.cacheOn(); + start = millis(); + seg.displayTest(0); + Serial.println(millis() - start); +} + +void loop() +{ + uint8_t x[4] = { 255, 255, 255, 255 }; + seg.displayClear(); + delay(1000); + seg.displayRaw(x); + delay(1000); + seg.displayRaw(x, true); + delay(1000); + seg.displayRaw(x, false); + delay(1000); + + test_elsa(); // limited text possible + delay(1000); + test_random(); + delay(1000); +} + +void test_elsa() +{ + uint8_t ar[4]; + ar[0] = 0x79; + ar[1] = 0x38; + ar[2] = 0x6D; + ar[3] = 0x77; + seg.displayRaw(ar); +} + +void test_random() +{ + uint8_t ar[4]; + for (uint8_t run = 0; run < 50; run++) + { + for (uint8_t i = 0; i < 4; i++) + { + ar[i] = random(256); + } + seg.displayRaw(ar, random(2)); + delay(100); + } +} + + + +// -- END OF FILE -- diff --git a/libraries/HT16K33/examples/demo_displayTime/demo_displayTime.ino b/libraries/HT16K33/examples/demo_displayTime/demo_displayTime.ino new file mode 100644 index 00000000..feb49e5f --- /dev/null +++ b/libraries/HT16K33/examples/demo_displayTime/demo_displayTime.ino @@ -0,0 +1,42 @@ +// +// FILE: demo_displayTime.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.2.0 +// PURPOSE: demo +// URL: http://www.adafruit.com/products/1002 +// URL: https://github.com/RobTillaart/HT16K33 + + +// sketch will work correctly up to 99:99 + +#include "HT16K33.h" + +HT16K33 seg(0x70); + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + + seg.begin(); + Wire.setClock(100000); + seg.displayOn(); + seg.setDigits(4); +} + +void loop() +{ + static uint32_t last = 0; + uint32_t now = millis(); + if (now != last) + { + last = now; + uint32_t s = now / 1000; + uint32_t t = (now - s * 1000) / 10; + s = s % 100; + seg.displayTime(s, t); + seg.displayColon(1); + } +} + +// -- END OF FILE -- diff --git a/libraries/HT16K33/examples/demo_dual1/demo_dual1.ino b/libraries/HT16K33/examples/demo_dual1/demo_dual1.ino index 6e856873..84bc0ec2 100644 --- a/libraries/HT16K33/examples/demo_dual1/demo_dual1.ino +++ b/libraries/HT16K33/examples/demo_dual1/demo_dual1.ino @@ -1,15 +1,15 @@ // // FILE: demo_dual1.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.0 +// VERSION: 0.2.0 // PURPOSE: demo 2 I2C 4x7segment displays one uint32_t unsigned long // URL: http://www.adafruit.com/products/1002 // URL: https://github.com/RobTillaart/HT16K33 #include "HT16K33.h" -HT16K33 left(0x70); -HT16K33 right(0x71); +HT16K33 left(0x71); +HT16K33 right(0x70); uint32_t counter = 0; @@ -20,28 +20,35 @@ void setup() left.begin(); right.begin(); - + Wire.setClock(100000); left.displayOn(); right.displayOn(); - left.suppressLeadingZeroPlaces(4); // show no digit if not needed - right.suppressLeadingZeroPlaces(3); // show at least 1 digit if zero (0) - + Serial.println("dual displayTest"); } void loop() { - uint16_t lval = counter / 10000; - uint16_t rval = counter % 10000; - - right.suppressLeadingZeroPlaces(lval == 0 ? 3 : 0); - left.displayInt(lval); - right.displayInt(rval); + display_ulong(counter); - delay(1); + delay(1); counter++; } -// -- END OF FILE -- +void display_ulong(uint32_t value) +{ + uint16_t lval = value / 10000; + uint16_t rval = value % 10000; + + // left show no digit if not needed + left.setDigits(0); + // right show at least 1 digit if value < 10000, otherwise leading zero's needed + right.setDigits(lval > 0 ? 4 : 0); + + left.displayInt(lval); + right.displayInt(rval); +} + +// -- END OF FILE -- diff --git a/libraries/HT16K33/examples/test_printfloat/test_printfloat.ino b/libraries/HT16K33/examples/test_printfloat/test_printfloat.ino index 17d0051f..a4ddb71b 100644 --- a/libraries/HT16K33/examples/test_printfloat/test_printfloat.ino +++ b/libraries/HT16K33/examples/test_printfloat/test_printfloat.ino @@ -1,7 +1,7 @@ // // FILE: test_printfloat.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.0 +// VERSION: 0.2.0 // PURPOSE: test decimal point for floats. // URL: http://www.adafruit.com/products/1002 // URL: https://github.com/RobTillaart/HT16K33 @@ -30,6 +30,12 @@ void loop() void test_printfloat() { + for (int i = -2000; i < 2000; i++) + { + float f = i * 0.001; + seg.displayFloat(f); + delay(10); + } for (int i = 9990; i < 10005; i++) { float f = i * 0.001; diff --git a/libraries/HT16K33/keywords.txt b/libraries/HT16K33/keywords.txt index d574a24d..e482099f 100644 --- a/libraries/HT16K33/keywords.txt +++ b/libraries/HT16K33/keywords.txt @@ -7,15 +7,22 @@ HT16K33 KEYWORD1 HT16K33 KEYWORD2 begin KEYWORD2 +reset KEYWORD2 +clearCache KEYWORD2 +cacheOn KEYWORD2 +cacheOff KEYWORD2 displayOn KEYWORD2 displayOff KEYWORD2 brightness KEYWORD2 blink KEYWORD2 + +setDigits KEYWORD2 suppressLeadingZeroPlaces KEYWORD2 displayClear KEYWORD2 displayInt KEYWORD2 displayHex KEYWORD2 +displayDate KEYWORD2 displayTime KEYWORD2 displayFloat KEYWORD2 display KEYWORD2 diff --git a/libraries/HT16K33/library.json b/libraries/HT16K33/library.json index 9a09b30c..e5958b9e 100644 --- a/libraries/HT16K33/library.json +++ b/libraries/HT16K33/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/HT16K33.git" }, - "version":"0.2.1", + "version":"0.3.0", "frameworks": "arduino", "platforms": "*" } diff --git a/libraries/HT16K33/library.properties b/libraries/HT16K33/library.properties index 9d4521e2..ae97ef0d 100644 --- a/libraries/HT16K33/library.properties +++ b/libraries/HT16K33/library.properties @@ -1,5 +1,5 @@ name=HT16K33 -version=0.2.1 +version=0.3.0 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino Library for HT16K33 diff --git a/libraries/Histogram/LICENSE b/libraries/Histogram/LICENSE new file mode 100644 index 00000000..4c3eaf9b --- /dev/null +++ b/libraries/Histogram/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2012-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/Histogram/histogram.cpp b/libraries/Histogram/histogram.cpp index 741f2ad0..7bfe0e9b 100644 --- a/libraries/Histogram/histogram.cpp +++ b/libraries/Histogram/histogram.cpp @@ -1,12 +1,10 @@ // // FILE: Histogram.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.6 +// VERSION: 0.2.0 // PURPOSE: Histogram library for Arduino // DATE: 2012-11-10 // -// Released to the public domain -// // HISTORY: // 0.1.0 - 2012-11-10 initial version // 0.1.1 - 2012-11-10 added PMF() and CDF() @@ -15,9 +13,7 @@ // 0.1.4 - 2015-03-06 stricter interface // 0.1.5 - 2017-07-16 refactor, support for > 256 buckets; prevent alloc errors // 0.1.6 - 2017-07-27 revert double to float (issue #33) -// -// Released to the public domain -// +// 0.2.0 2020-06-12 #pragma once, removed pre 1.0 support #include "histogram.h" @@ -140,4 +136,4 @@ int16_t Histogram::find(const float val) // return i; } -// END OF FILE \ No newline at end of file +// -- END OF FILE -- diff --git a/libraries/Histogram/histogram.h b/libraries/Histogram/histogram.h index 6cc3b52d..80da8051 100644 --- a/libraries/Histogram/histogram.h +++ b/libraries/Histogram/histogram.h @@ -1,26 +1,15 @@ -#ifndef Histogram_h -#define Histogram_h +#pragma once // // FILE: Histogram.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.5 +// VERSION: 0.2.0 // PURPOSE: Histogram library for Arduino // DATE: 2012-11-10 // -// Released to the public domain -// -#include -#include -#include - -#if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" -#else -#include "WProgram.h" -#endif -#define HISTOGRAM_LIB_VERSION "0.1.6" +#define HISTOGRAM_LIB_VERSION "0.2.0" class Histogram { @@ -53,5 +42,4 @@ protected: uint32_t _cnt; }; -#endif -// END OF FILE \ No newline at end of file +// -- END OF FILE -- diff --git a/libraries/Histogram/keywords.txt b/libraries/Histogram/keywords.txt index 227ff28b..1ee2437e 100644 --- a/libraries/Histogram/keywords.txt +++ b/libraries/Histogram/keywords.txt @@ -1,15 +1,9 @@ -####################################### # Syntax Coloring Map For Histogram -####################################### -####################################### # Datatypes (KEYWORD1) -####################################### Histogram KEYWORD1 -####################################### # Methods and Functions (KEYWORD2) -####################################### clear KEYWORD2 add KEYWORD2 sub KEYWORD2 @@ -22,7 +16,5 @@ CDF KEYWORD2 VAL KEYWORD2 find KEYWORD2 -####################################### # Constants (LITERAL1) -####################################### HISTOGRAM_LIB_VERSION LITERAL1 diff --git a/libraries/Histogram/library.json b/libraries/Histogram/library.json index 91afeee0..a17b6d4c 100644 --- a/libraries/Histogram/library.json +++ b/libraries/Histogram/library.json @@ -1,7 +1,7 @@ { "name": "Histogram", "keywords": "Histogram,VAL,CDF,PMF,frequency", - "description": "Library for creating histogram math.", + "description": "Arduino library for creating histograms math.", "authors": [ { @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/Histogram.git" }, - "version":"0.1.6", + "version":"0.2.0", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/Histogram" - } + "platforms": "*" } diff --git a/libraries/Histogram/library.properties b/libraries/Histogram/library.properties index a5606ada..62f99a56 100644 --- a/libraries/Histogram/library.properties +++ b/libraries/Histogram/library.properties @@ -1,9 +1,11 @@ name=Histogram -version=0.1.6 +version=0.2.0 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Library for creating histogram math. +sentence=Arduino library for creating histograms math. paragraph= category=Data Processing -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/Histogram +architectures=* +includes=histogram.h +depends= diff --git a/libraries/Histogram/readme.md b/libraries/Histogram/readme.md index c858935f..b9f449ed 100644 --- a/libraries/Histogram/readme.md +++ b/libraries/Histogram/readme.md @@ -1,5 +1,7 @@ # Histogram Library +Arduino library for creating histograms math. + ## Description One of the main applications for the Arduino board is reading and logging of sensor data. @@ -28,7 +30,6 @@ The interface consists of: * float PMF(float val); // Probability Mass Function * float CDF(float val); // Cumulative Distribution Function * float VAL(float prob); // Value -(:sourceend:) When the class is initialized an array of the boundaries to define the borders of the buckets is passed to the constructor. This array should be declared global as the @@ -42,8 +43,8 @@ and the buckets counter is increased. The sub() function is used to decrease the count of a bucket and it can cause the count to become below zero. ALthough seldom used but still depending on the application it can be useful. E.g. when you want to compare two value generating streams, you let one stream -add() and the other sub(). If the histogram is similar they should cancel each other out -(more or less), and the count of all the buckets should be around 0. [not tried]. +add() and the other sub(). If the histogram of both streams is similar they should cancel +each other out (more or less), and the value of all buckets should be around 0. [not tried]. Frequency() may be removed to reduce footprint as it can be calculated quite easily with the formula (1.0* bucket(i))/count(). diff --git a/libraries/I2C_EEPROM/I2C_eeprom.cpp b/libraries/I2C_EEPROM/I2C_eeprom.cpp index 316249ec..f64c3078 100644 --- a/libraries/I2C_EEPROM/I2C_eeprom.cpp +++ b/libraries/I2C_EEPROM/I2C_eeprom.cpp @@ -1,8 +1,9 @@ // // FILE: I2C_eeprom.cpp // AUTHOR: Rob Tillaart -// VERSION: 1.2.7 -// PURPOSE: I2C_eeprom library for Arduino with EEPROM 24LC256 et al. +// VERSION: 1.3.0 +// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al. +// URL: https://github.com/RobTillaart/I2C_EEPROM.git // // HISTORY: // 0.1.00 - 2011-01-21 initial version @@ -24,24 +25,15 @@ // 1.2.01 - 2014-05-21 Refactoring // 1.2.02 - 2015-03-06 stricter interface // 1.2.03 - 2015-05-15 bugfix in _pageBlock & example (thanks ifreislich ) -// 1.2.4 - 2017-04-19 remove timeout - issue #63 -// 1.2.5 - 2017-04-20 refactor the removed timeout (Thanks to Koepel) -// 1.2.6 - 2019-02-01 fix issue #121 -// 1.2.7 - 2019-09-03 fix issue #113 and #128 -// -// Released to the public domain +// 1.2.4 2017-04-19 remove timeout - issue #63 +// 1.2.5 2017-04-20 refactor the removed timeout (Thanks to Koepel) +// 1.2.6 2019-02-01 fix issue #121 +// 1.2.7 2019-09-03 fix issue #113 and #128 +// 1.3.0 2020-06-19 refactor; removed pre 1.0 support; added ESP32 support. // #include -#if defined(ARDUINO) && ARDUINO >= 100 - #define WIRE_WRITE Wire.write - #define WIRE_READ Wire.read -#else - #define WIRE_WRITE Wire.send - #define WIRE_READ Wire.receive -#endif - I2C_eeprom::I2C_eeprom(const uint8_t deviceAddress) { @@ -71,113 +63,108 @@ I2C_eeprom::I2C_eeprom(const uint8_t deviceAddress, const unsigned int deviceSiz } } +#if defined (ESP8266) || defined(ESP32) +void I2C_eeprom::begin(uint8_t sda, uint8_t scl) +{ + Wire.begin(sda, scl); + _lastWrite = 0; +} +#endif + void I2C_eeprom::begin() { - Wire.begin(); - _lastWrite = 0; - -// TWBR is not available on Arduino Due -#ifdef TWBR - TWBR = 72; - // 0=1000 1=888 2=800 8=500 - // 12=400KHz 24=250 32=200 72=100 152=50 - // F_CPU/16+(2*TWBR) // TWBR is a uint8_t -#endif + Wire.begin(); + _lastWrite = 0; } - - int I2C_eeprom::writeByte(const uint16_t memoryAddress, const uint8_t data) { - int rv = _WriteBlock(memoryAddress, &data, 1); - return rv; + int rv = _WriteBlock(memoryAddress, &data, 1); + return rv; } int I2C_eeprom::setBlock(const uint16_t memoryAddress, const uint8_t data, const uint16_t length) { - uint8_t buffer[I2C_TWIBUFFERSIZE]; - for (uint8_t i = 0; i < I2C_TWIBUFFERSIZE; i++) buffer[i] = data; - - int rv = _pageBlock(memoryAddress, buffer, length, false); - return rv; + uint8_t buffer[I2C_TWIBUFFERSIZE]; + for (uint8_t i = 0; i < I2C_TWIBUFFERSIZE; i++) + { + buffer[i] = data; + } + int rv = _pageBlock(memoryAddress, buffer, length, false); + return rv; } int I2C_eeprom::writeBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint16_t length) { - int rv = _pageBlock(memoryAddress, buffer, length, true); - return rv; + int rv = _pageBlock(memoryAddress, buffer, length, true); + return rv; } uint8_t I2C_eeprom::readByte(const uint16_t memoryAddress) { - uint8_t rdata; - _ReadBlock(memoryAddress, &rdata, 1); - return rdata; + uint8_t rdata; + _ReadBlock(memoryAddress, &rdata, 1); + return rdata; } uint16_t I2C_eeprom::readBlock(const uint16_t memoryAddress, uint8_t* buffer, const uint16_t length) { - uint16_t addr = memoryAddress; - uint16_t len = length; - uint16_t rv = 0; - while (len > 0) - { -#if defined(ESP8266) || defined(ESP32) // || defined(...) - uint8_t cnt = _min(len, I2C_TWIBUFFERSIZE); -#else - uint8_t cnt = min(len, I2C_TWIBUFFERSIZE); -#endif - rv += _ReadBlock(addr, buffer, cnt); - addr += cnt; - buffer += cnt; - len -= cnt; - } - return rv; + uint16_t addr = memoryAddress; + uint16_t len = length; + uint16_t rv = 0; + while (len > 0) + { + uint8_t cnt = I2C_TWIBUFFERSIZE; + if (cnt > len) cnt = len; + rv += _ReadBlock(addr, buffer, cnt); + addr += cnt; + buffer += cnt; + len -= cnt; + } + return rv; } -#ifdef I2C_EEPROM_EXTENDED // returns 64, 32, 16, 8, 4, 2, 1, 0 // 0 is smaller than 1K int I2C_eeprom::determineSize() { - int rv = 0; // unknown - uint8_t orgValues[8]; - uint16_t addr; + int rv = 0; // unknown + uint8_t orgValues[8]; + uint16_t addr; - // try to read a byte to see if connected - rv += _ReadBlock(0x00, orgValues, 1); - if (rv == 0) return -1; + // try to read a byte to see if connected + rv += _ReadBlock(0x00, orgValues, 1); + if (rv == 0) return -1; - // remember old values, non destructive - for (uint8_t i=0; i<8; i++) + // remember old values, non destructive + for (uint8_t i = 0; i < 8; i++) + { + addr = (512 << i) + 1; + orgValues[i] = readByte(addr); + } + + // scan page folding + for (uint8_t i = 0; i < 8; i++) + { + rv = i; + uint16_t addr1 = (512 << i) + 1; + uint16_t addr2 = (512 << (i+1)) + 1; + writeByte(addr1, 0xAA); + writeByte(addr2, 0x55); + if (readByte(addr1) == 0x55) // folded! { - addr = (512 << i) + 1; - orgValues[i] = readByte(addr); + break; } + } - // scan page folding - for (uint8_t i=0; i<8; i++) - { - rv = i; - uint16_t addr1 = (512 << i) + 1; - uint16_t addr2 = (512 << (i+1)) + 1; - writeByte(addr1, 0xAA); - writeByte(addr2, 0x55); - if (readByte(addr1) == 0x55) // folded! - { - break; - } - } - - // restore original values - for (uint8_t i=0; i<8; i++) - { - uint16_t addr = (512 << i) + 1; - writeByte(addr, orgValues[i]); - } - return 0x01 << (rv-1); + // restore original values + for (uint8_t i = 0; i < 8; i++) + { + uint16_t addr = (512 << i) + 1; + writeByte(addr, orgValues[i]); + } + return 0x01 << (rv - 1); } -#endif //////////////////////////////////////////////////////////////////// // @@ -189,28 +176,24 @@ int I2C_eeprom::determineSize() // returns 0 = OK otherwise error int I2C_eeprom::_pageBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint16_t length, const bool incrBuffer) { - uint16_t addr = memoryAddress; - uint16_t len = length; - while (len > 0) - { - uint8_t bytesUntilPageBoundary = this->_pageSize - addr % this->_pageSize; + uint16_t addr = memoryAddress; + uint16_t len = length; + while (len > 0) + { + uint8_t bytesUntilPageBoundary = this->_pageSize - addr % this->_pageSize; -#if defined(ESP8266) || defined(ESP32) // || defined(...) - uint8_t cnt = _min(len, bytesUntilPageBoundary); - cnt = _min(cnt, I2C_TWIBUFFERSIZE); -#else - uint8_t cnt = min(len, bytesUntilPageBoundary); - cnt = min(cnt, I2C_TWIBUFFERSIZE); -#endif + uint8_t cnt = I2C_TWIBUFFERSIZE; + if (cnt > len) cnt = len; + if (cnt > bytesUntilPageBoundary) cnt = bytesUntilPageBoundary; - int rv = _WriteBlock(addr, buffer, cnt); - if (rv != 0) return rv; + int rv = _WriteBlock(addr, buffer, cnt); + if (rv != 0) return rv; - addr += cnt; - if (incrBuffer) buffer += cnt; - len -= cnt; - } - return 0; + addr += cnt; + if (incrBuffer) buffer += cnt; + len -= cnt; + } + return 0; } // supports one and 2 bytes addresses @@ -220,61 +203,62 @@ void I2C_eeprom::_beginTransmission(const uint16_t memoryAddress) if (this->_isAddressSizeTwoWords) { - WIRE_WRITE((memoryAddress >> 8)); // Address High Byte + // Address High Byte + Wire.write((memoryAddress >> 8)); } - WIRE_WRITE((memoryAddress & 0xFF)); // Address Low Byte (or only byte for chips 16K or smaller that only have one-word addresses) + // Address Low Byte (or only byte for chips 16K or smaller that only have one-word addresses) + Wire.write((memoryAddress & 0xFF)); } // pre: length <= this->_pageSize && length <= I2C_TWIBUFFERSIZE; // returns 0 = OK otherwise error int I2C_eeprom::_WriteBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint8_t length) { - waitEEReady(); + _waitEEReady(); - this->_beginTransmission(memoryAddress); - WIRE_WRITE(buffer, length); - int rv = Wire.endTransmission(); + this->_beginTransmission(memoryAddress); + Wire.write(buffer, length); + int rv = Wire.endTransmission(); - - _lastWrite = micros(); - return rv; + _lastWrite = micros(); + return rv; } // pre: buffer is large enough to hold length bytes // returns bytes read uint8_t I2C_eeprom::_ReadBlock(const uint16_t memoryAddress, uint8_t* buffer, const uint8_t length) { - waitEEReady(); + _waitEEReady(); - this->_beginTransmission(memoryAddress); + this->_beginTransmission(memoryAddress); + int rv = Wire.endTransmission(); + if (rv != 0) return 0; // error - int rv = Wire.endTransmission(); - if (rv != 0) return 0; // error - - // readbytes will always be equal or smaller to length - uint8_t readBytes = Wire.requestFrom(_deviceAddress, length); - uint8_t cnt = 0; - while (cnt < readBytes) - { - buffer[cnt++] = WIRE_READ(); - } - return readBytes; + // readbytes will always be equal or smaller to length + uint8_t readBytes = Wire.requestFrom(_deviceAddress, length); + uint8_t cnt = 0; + while (cnt < readBytes) + { + buffer[cnt++] = Wire.read(); + } + return readBytes; } -void I2C_eeprom::waitEEReady() +void I2C_eeprom::_waitEEReady() { #define I2C_WRITEDELAY 5000 - // Wait until EEPROM gives ACK again. - // this is a bit faster than the hardcoded 5 milliSeconds - while ((micros() - _lastWrite) <= I2C_WRITEDELAY) - { - Wire.beginTransmission(_deviceAddress); - int x = Wire.endTransmission(); - if (x == 0) break; - yield(); - } + // Wait until EEPROM gives ACK again. + // this is a bit faster than the hardcoded 5 milliSeconds + while ((micros() - _lastWrite) <= I2C_WRITEDELAY) + { + Wire.beginTransmission(_deviceAddress); + int x = Wire.endTransmission(); + if (x == 0) return; + yield(); + } + return; } -// END OF FILE +// -- END OF FILE -- diff --git a/libraries/I2C_EEPROM/I2C_eeprom.h b/libraries/I2C_EEPROM/I2C_eeprom.h index ad4981e4..8b91959a 100644 --- a/libraries/I2C_EEPROM/I2C_eeprom.h +++ b/libraries/I2C_EEPROM/I2C_eeprom.h @@ -1,27 +1,18 @@ -#ifndef I2C_EEPROM_H -#define I2C_EEPROM_H +#pragma once // // FILE: I2C_eeprom.h // AUTHOR: Rob Tillaart -// PURPOSE: I2C_eeprom library for Arduino with EEPROM 24LC256 et al. -// VERSION: 1.2.7 +// VERSION: 1.3.0 +// PURPOSE: Arduino Library for external I2C EEPROM 24LC256 et al. +// URL: https://github.com/RobTillaart/I2C_EEPROM.git +// // HISTORY: See I2C_eeprom.cpp -// URL: http://arduino.cc/playground/Main/LibraryForI2CEEPROM -// -// Released to the public domain -// + #include "Wire.h" - -#if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" -#else -#include "WProgram.h" -#include "Wstring.h" -#include "Wiring.h" -#endif -#define I2C_EEPROM_VERSION "1.2.7" +#define I2C_EEPROM_VERSION "1.3.0" // The DEFAULT page size. This is overriden if you use the second constructor. // I2C_EEPROM_PAGESIZE must be multiple of 2 e.g. 16, 32 or 64 @@ -32,9 +23,6 @@ // 1 byte for eeprom register address is available in txbuffer #define I2C_TWIBUFFERSIZE 30 -// comment next line to keep lib small (idea a read only lib?) -#define I2C_EEPROM_EXTENDED - class I2C_eeprom { public: @@ -47,45 +35,52 @@ public: * Initializes the EEPROM for the given device address. * * It will try to guess page size and address word size based on the size of the device. - * + * * @param deviceAddress Byte address of the device. * @param deviceSize Max size in bytes of the device (divide your device size in Kbits by 8) */ I2C_eeprom(const uint8_t deviceAddress, const unsigned int deviceSize); +#if defined (ESP8266) || defined(ESP32) + void begin(uint8_t sda, uint8_t scl); +#endif void begin(); + + // writes a byte to memaddr int writeByte(const uint16_t memoryAddress, const uint8_t value); + // writes length bytes from buffer to EEPROM int writeBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint16_t length); + // set length bytes in the EEPROM to the same value. int setBlock(const uint16_t memoryAddress, const uint8_t value, const uint16_t length); - uint8_t readByte(const uint16_t memoryAddress); + // returns the value stored in memaddr + uint8_t readByte(const uint16_t memoryAddress); + // reads length bytes into buffer uint16_t readBlock(const uint16_t memoryAddress, uint8_t* buffer, const uint16_t length); -#ifdef I2C_EEPROM_EXTENDED - int determineSize(); -#endif + int determineSize(); + private: - uint8_t _deviceAddress; + uint8_t _deviceAddress; uint32_t _lastWrite; // for waitEEReady - uint8_t _pageSize; + uint8_t _pageSize; // for some smaller chips that use one-word addresses - bool _isAddressSizeTwoWords; + bool _isAddressSizeTwoWords; /** * Begins wire transmission and selects the given address to write/read. - * + * * @param memoryAddress Address to write/read */ - void _beginTransmission(const uint16_t memoryAddress); + void _beginTransmission(const uint16_t memoryAddress); - int _pageBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint16_t length, const bool incrBuffer); - int _WriteBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint8_t length); - uint8_t _ReadBlock(const uint16_t memoryAddress, uint8_t* buffer, const uint8_t length); + int _pageBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint16_t length, const bool incrBuffer); + int _WriteBlock(const uint16_t memoryAddress, const uint8_t* buffer, const uint8_t length); + uint8_t _ReadBlock(const uint16_t memoryAddress, uint8_t* buffer, const uint8_t length); - void waitEEReady(); + void _waitEEReady(); }; -#endif -// END OF FILE \ No newline at end of file +// -- END OF FILE -- diff --git a/libraries/I2C_EEPROM/LICENSE b/libraries/I2C_EEPROM/LICENSE new file mode 100644 index 00000000..95ba2177 --- /dev/null +++ b/libraries/I2C_EEPROM/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2011-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/I2C_EEPROM/examples/I2C_eeprom_test/new 2.txt b/libraries/I2C_EEPROM/examples/I2C_eeprom_test/new 2.txt new file mode 100644 index 00000000..3e580895 --- /dev/null +++ b/libraries/I2C_EEPROM/examples/I2C_eeprom_test/new 2.txt @@ -0,0 +1,128 @@ + +Try this (not tested) +[code] +//#include +#include +#include +#include +#include + +#define SD_CS 9 + + +//UTFT(byte model, int RS, int WR, int RD, int CS) +//UTFT myGLCD(ITDB32S,A2,A1,A0,10); // Remember to change the model parameter to suit your display module! +//ArduCAM(byte model,int RS, int WR, int RD, int REG_CS, int FIFO_CS) +ArduCAM myCAM(OV2640,A2,A1,A0,A3,10); // Remember to change the model parameter to suit your canera module! + +void setup() +{ + Serial.begin(115200); // <<<<<<<<<<<<<<<<<<<<<<< + Serial.println("Start arducam test"); + + //Initialize I2C Bus + Wire.begin(); + //Switch to FIFO Mode + myCAM.write_reg(ARDUCHIP_TIM, MODE_MASK); + //Set sensor to JPEG mode. Note don't all the camera modules support JPEG mode + myCAM.OV2640_set_format(JPEG); + //Initialize Camera Module + myCAM.InitCAM(); + myCAM.OV2640_set_JPEG_size(OV2640_320x240); + + Serial.println("SD.begin"); + //Initialize SD Card + if (!SD.begin(SD_CS)) + { + Serial.println("SD card failed"); + //while (1); //If failed, stop here + } + Serial.println("SD card success"); + Serial.println("End setup"); +} + +void loop() +{ + Serial.print(millis()); + Serial.println("\tstart loop"); + + char str[8]; + File outFile; + static int k = 0; + uint8_t temp,temp_last; + uint8_t start_capture = 0; + + Serial.print(millis()); + Serial.println("\tWait trigger from shutter buttom"); + + //Wait trigger from shutter buttom + if(myCAM.read_reg(ARDUCHIP_TRIG) & SHUTTER_MASK) + { + //Wait until buttom released + while(myCAM.read_reg(ARDUCHIP_TRIG) & SHUTTER_MASK); + start_capture = 1; + } + + + Serial.print(millis()); + Serial.println("\tStart capture I"); + //Start capture when detect a valid shutter press + if(start_capture) + { + //Flush the FIFO + myCAM.flush_fifo(); + //Start capture + myCAM.start_capture(); + } + + if(myCAM.read_reg(ARDUCHIP_TRIG) & CAP_DONE_MASK) + { + //Construct a file name + k = k + 1; + itoa(k, str, 10); + strcat(str,".jpg"); + //Open the new file + outFile = SD.open(str,FILE_WRITE); + if (! outFile) + { + Serial.print(millis()); + Serial.println("\tfailure outfile"); + return; + } + + Serial.print(millis()); + Serial.println("\toutfile succes"); + + //Enable FIFO + myCAM.enable_fifo(); + + uint32_t bytecounter = 0; + //Read the first dummy byte from FIFO + temp = myCAM.read_fifo(); + + //Read JPEG data from FIFO + while( (temp != 0xD9) | (temp_last != 0xFF) ) + { + bytecounter++; + if (bytecounter % 32 == 0) Serial.print('.'); + if (bytecounter % 1024 == 0) Serial.println; + temp_last = temp; + temp = myCAM.read_fifo(); + //Write image data to file + outFile.write(temp); + } + Serial.println(); + + //Disable FIFO when all the image data is saved to the file + myCAM.disable_fifo(); + //Close the file + outFile.close(); + + //Clear the capture done flag + myCAM.clear_fifo_flag(); + //Clear the start capture flag + start_capture = 0; + } +} + +[/code] \ No newline at end of file diff --git a/libraries/I2C_EEPROM/examples/I2C_small_eeprom_test/I2C_small_eeprom_test.ino b/libraries/I2C_EEPROM/examples/I2C_small_eeprom_test/I2C_small_eeprom_test.ino index 57e235ab..6622601e 100644 --- a/libraries/I2C_EEPROM/examples/I2C_small_eeprom_test/I2C_small_eeprom_test.ino +++ b/libraries/I2C_EEPROM/examples/I2C_small_eeprom_test/I2C_small_eeprom_test.ino @@ -1,9 +1,12 @@ // // FILE: I2C_small_eeprom_test.ino -// AUTHOR: -// VERSION: 0.1.00 +// AUTHOR: Tyler Freeman +// VERSION: 0.1.1 // PURPOSE: show/test I2C_EEPROM library with small EEPROMS -// +// HISTORY +// 0.1.0 2014-05-xx initial version +// 0.1.1 2020-07-14 fix #1 compile for ESP; fix author + #include #include @@ -30,7 +33,8 @@ #define UNALIGNED_BUFFER_LEN 35 #define UNALIGNED_TEST_PAGE_ADDR (LONG_TEST_PAGE_ADDR + LONG_BUFFER_LEN + 5) -#define SERIAL_DEBUG SerialUSB +// #define SERIAL_DEBUG SerialUSB +#define SERIAL_DEBUG Serial I2C_eeprom eeprom(DEVICEADDRESS, EE24LC01MAXBYTES); @@ -64,7 +68,7 @@ void readAndWritePage(unsigned int pageAddress, int bufferLen) { byte testBuffer[LONG_BUFFER_LEN + 1]; // null-terminate for printing! - testBuffer[bufferLen] = NULL; + testBuffer[bufferLen] = '\0'; eeprom.readBlock(pageAddress, testBuffer, bufferLen); @@ -74,7 +78,9 @@ void readAndWritePage(unsigned int pageAddress, int bufferLen) { for (int i = 0; i < bufferLen; i++) { // use max to init to all AAAA's on first run. - testBuffer[i] = max('A', (testBuffer[i] + ((i % 4) + 1) % 'z')); + testBuffer[i] = 'A'; + char c = (testBuffer[i] + ((i % 4) + 1) % 'z'); + if (testBuffer[i] < c) testBuffer[i] = c; } eeprom.writeBlock(pageAddress, testBuffer, bufferLen); @@ -128,9 +134,11 @@ void setup() SERIAL_DEBUG.println("----------------------------------------------"); readAndWritePage(UNALIGNED_TEST_PAGE_ADDR, UNALIGNED_BUFFER_LEN); + + SERIAL_DEBUG.println("\nDone..."); } void loop() { // Nothing to do during loop -} \ No newline at end of file +} diff --git a/libraries/I2C_EEPROM/keywords.txt b/libraries/I2C_EEPROM/keywords.txt index 95797450..58f8f4bb 100644 --- a/libraries/I2C_EEPROM/keywords.txt +++ b/libraries/I2C_EEPROM/keywords.txt @@ -1,24 +1,14 @@ -####################################### # Syntax Coloring Map For I2C_EEPROM -####################################### -####################################### # Datatypes (KEYWORD1) -####################################### +I2C_eeprom KEYWORD1 -I2C_eeprom KEYWORD1 - -####################################### # Methods and Functions (KEYWORD2) -####################################### +readByte KEYWORD2 +writeByte KEYWORD2 +setBlock KEYWORD2 +readBlock KEYWORD2 +writeBlock KEYWORD2 +determineSize KEYWORD2 -readByte KEYWORD2 -writeByte KEYWORD2 -setBlock KEYWORD2 -readBlock KEYWORD2 -writeBlock KEYWORD2 -determineSize KEYWORD2 - -####################################### # Constants (LITERAL1) -####################################### \ No newline at end of file diff --git a/libraries/I2C_EEPROM/library.json b/libraries/I2C_EEPROM/library.json index 1dc8ac2e..59d01368 100644 --- a/libraries/I2C_EEPROM/library.json +++ b/libraries/I2C_EEPROM/library.json @@ -1,6 +1,6 @@ { "name": "I2C_EEPROM", - "keywords": "EEPROM,24LC256", + "keywords": "EEPROM, 24LC256, 24LC64", "description": "Library for I2C EEPROMS.", "authors": [ @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/I2C_EEPROM.git" }, - "version":"1.2.7", + "version":"1.3.0", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/I2C_EEPROM" - } + "platforms": "*" } diff --git a/libraries/I2C_EEPROM/library.properties b/libraries/I2C_EEPROM/library.properties index f2123177..f2487e80 100644 --- a/libraries/I2C_EEPROM/library.properties +++ b/libraries/I2C_EEPROM/library.properties @@ -1,9 +1,11 @@ name=I2C_EEPROM -version=1.2.7 +version=1.3.0 author=Rob Tillaart maintainer=Rob Tillaart sentence=Library for I2C EEPROMS. paragraph=24LC256 et al category=Data Storage -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/I2C_EEPROM.git +architectures=* +includes=I2C_eeprom.h +depends= \ No newline at end of file diff --git a/libraries/I2C_EEPROM/readme.md b/libraries/I2C_EEPROM/readme.md index e69de29b..455f10b9 100644 --- a/libraries/I2C_EEPROM/readme.md +++ b/libraries/I2C_EEPROM/readme.md @@ -0,0 +1,29 @@ +# I2C_EEPROM + +Arduino Library for external I2C EEPROM - 24LC256, 24LC64 + +## Description + +Library to access external I2C EEPROM. + +The interface is pretty straightforward + +* readByte - read a single byte from a given address +* writeByte +* setBlock +* readBlock +* writeBlock +* determineSize + + + +## Limitation + +The library does not offer multiple EEPROMS as one +continuous storage device. + + +## Operational + +See examples + diff --git a/libraries/IEEE754tools/IEEE754tools.h b/libraries/IEEE754tools/IEEE754tools.h index 330d5490..6a6683ba 100644 --- a/libraries/IEEE754tools/IEEE754tools.h +++ b/libraries/IEEE754tools/IEEE754tools.h @@ -1,34 +1,28 @@ +#pragma once // // FILE: IEEE754tools.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.03 -// PURPOSE: IEEE754 tools +// VERSION: 0.2.0 +// PURPOSE: manipulate IEEE754 float numbers fast +// URL: https://github.com/RobTillaart/IEEE754tools.git // -// http://playground.arduino.cc//Main/IEEE754tools +// EXPERIMENTAL ==> USE WITH CARE +// not tested extensively, // -// Released to the public domain -// not tested, use with care -// -// 0.1.03 renamed IEEE_Sign IEEE_Exponent -// 0.1.02 added SHIFT_POW2 -// 0.1.01 added IEEE_NAN, IEEE_INF tests + version string -// 0.1.00 initial version +// 0.1.00 2013-09-08 initial version +// 0.1.01 2013-09-08 added IEEE_NAN, IEEE_INF tests + version string +// 0.1.02 2013-09-08 added SHIFT_POW2 +// 0.1.03 2013-09-10 renamed IEEE_Sign IEEE_Exponent +// 0.2.0 2020-06-30 own repo + some refactor... +// -#ifndef IEEE754tools_h -#define IEEE754tools_h - - -#if defined(ARDUINO) && ARDUINO >= 100 #include "Arduino.h" -#else -#include "WProgram.h" -#endif -#define IEEE754_VERSION "0.1.03" +#define IEEE754_VERSION "0.2.0" // (un)comment lines to configure functionality / size //#define IEEE754_ENABLE_MSB // +78 bytes -#define IEEE754_ENABLE_DUMP + // IEEE754 float layout; struct IEEEfloat @@ -74,10 +68,10 @@ union _DBLCONV byte b[8]; }; + // // DEBUG FUNCTIONS // -#ifdef IEEE754_ENABLE_DUMP // print float components void dumpFloat(float number) { @@ -102,7 +96,6 @@ void dumpDBL(struct _DBL dbl) Serial.print("\t"); Serial.println(dbl.m, HEX); } -#endif // // mapping to/from 64bit double - best effort @@ -111,11 +104,12 @@ void dumpDBL(struct _DBL dbl) // converts a float to a packed array of 8 bytes representing a 64 bit double // restriction exponent and mantisse. // float; array of 8 bytes; LSBFIRST; MSBFIRST -void float2DoublePacked(float number, byte* bar, int byteOrder=LSBFIRST) +void float2DoublePacked(float number, byte* bar, int byteOrder = LSBFIRST) { _FLOATCONV fl; fl.f = number; _DBLCONV dbl; + dbl.p.filler = 0; dbl.p.s = fl.p.s; dbl.p.e = fl.p.e-127 +1023; // exponent adjust dbl.p.m = fl.p.m; @@ -124,7 +118,7 @@ void float2DoublePacked(float number, byte* bar, int byteOrder=LSBFIRST) if (byteOrder == LSBFIRST) { #endif - for (int i=0; i<8; i++) + for (int i = 0; i < 8; i++) { bar[i] = dbl.b[i]; } @@ -132,7 +126,7 @@ void float2DoublePacked(float number, byte* bar, int byteOrder=LSBFIRST) } else { - for (int i=0; i<8; i++) + for (int i = 0; i < 8; i++) { bar[i] = dbl.b[7-i]; } @@ -143,7 +137,7 @@ void float2DoublePacked(float number, byte* bar, int byteOrder=LSBFIRST) // converts a packed array of bytes into a 32bit float. // there can be an exponent overflow // the mantisse is truncated to 23 bits. -float doublePacked2Float(byte* bar, int byteOrder=LSBFIRST) +float doublePacked2Float(byte* bar, int byteOrder = LSBFIRST) { _FLOATCONV fl; _DBLCONV dbl; @@ -152,7 +146,7 @@ float doublePacked2Float(byte* bar, int byteOrder=LSBFIRST) if (byteOrder == LSBFIRST) { #endif - for (int i=0; i<8; i++) + for (int i = 0; i < 8; i++) { dbl.b[i] = bar[i]; } @@ -160,14 +154,14 @@ float doublePacked2Float(byte* bar, int byteOrder=LSBFIRST) } else { - for (int i=0; i<8; i++) + for (int i = 0; i < 8; i++) { dbl.b[i] = bar[7-i]; } } #endif - int e = dbl.p.e-1023 +127; // exponent adjust + int e = dbl.p.e - 1023 + 127; // exponent adjust // TODO check exponent overflow. if (e >=0 || e <= 255) { @@ -281,7 +275,7 @@ void doublePacked2Float2(byte* bar, int byteOrder, float* value, float* error) if (byteOrder == LSBFIRST) { #endif - for (int i=0; i<8; i++) + for (int i = 0; i < 8; i++) { dbl.b[i] = bar[i]; } @@ -289,14 +283,14 @@ void doublePacked2Float2(byte* bar, int byteOrder, float* value, float* error) } else { - for (int i=0; i<8; i++) + for (int i = 0; i < 8; i++) { - dbl.b[i] = bar[7-i]; + dbl.b[i] = bar[7 - i]; } } #endif - int e = dbl.p.e-1023 +127; // exponent adjust + int e = dbl.p.e - 1023 + 127; // exponent adjust // TODO check exponent overflow. if (e >=0 || e <= 255) { @@ -381,5 +375,5 @@ bool IEEE_EQ(float f, float g) } */ -#endif -// END OF FILE \ No newline at end of file + +// -- END OF FILE -- diff --git a/libraries/IEEE754tools/LICENSE b/libraries/IEEE754tools/LICENSE new file mode 100644 index 00000000..2fc1cc50 --- /dev/null +++ b/libraries/IEEE754tools/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/IEEE754tools/examples/FastNegate/FastNegate.ino b/libraries/IEEE754tools/examples/FastNegate/FastNegate.ino new file mode 100644 index 00000000..52be2910 --- /dev/null +++ b/libraries/IEEE754tools/examples/FastNegate/FastNegate.ino @@ -0,0 +1,172 @@ +// +// FILE: FastNegate.ino +// AUTHOR: Rob dot Tillaart at gmail dot com +// VERSION: 0.2.0 +// PURPOSE: Fast negate for floating points +// +// HISTORY: +// 0.2.0 2020-06-30 main refactor +// 0.1.01 - 2013-09-08 added Gain: +// 0.1.00 - 2011-08-21 initial version +// + +volatile float zz = 100; +volatile int x = 3; + +uint32_t start, duration1, duration2; + +void setup() +{ + Serial.begin(115200); + Serial.println(__FILE__); + Serial.println(); + + test_negfabs(); + test_fabs(); + test_negate(); + test_less_zero(); + test5(); +} + +void test_negfabs() +{ + Serial.println(__FUNCTION__); + Serial.println("zz = -fabs(zz)"); + start = micros(); + for (int i = 0; i < 30000; i++) + { + *(((byte*) &zz) + 3) |= 0x80; // Force negative == -fabs(zz); + } + duration1 = micros() - start; + Serial.println(duration1 / 30000.0); + Serial.println(zz); + delay(10); + + zz = 100; + start = micros(); + for (int i = 0; i < 30000; i++) + { + zz = -fabs(zz); + } + duration2 = micros() - start; + Serial.println(duration2 / 30000.0); + Serial.print("Gain:\t"); + Serial.println(1.0 * duration2 / duration1); + Serial.println(zz); + Serial.println(); + delay(10); +} + +void test_fabs() +{ + Serial.println(__FUNCTION__); + Serial.println("zz = fabs(zz)"); + start = micros(); + for (int i = 0; i < 30000; i++) + { + *(((byte*) &zz) + 3) &= 0x7F; // force positive == fabs(zz); + } + duration1 = micros() - start; + Serial.println(duration1 / 30000.0); + Serial.println(zz); + delay(10); + + start = micros(); + for (int i = 0; i < 30000; i++) + { + zz = fabs(zz); + } + duration2 = micros() - start; + Serial.println(duration2 / 30000.0); + Serial.print("Gain:\t"); + Serial.println(1.0 * duration2 / duration1); + Serial.println(zz); + Serial.println(); + delay(10); +} + +void test_negate() +{ + Serial.println(__FUNCTION__); + Serial.println("zz = -zz"); + start = micros(); + for (int i = 0; i < 30000; i++) + { + *(((byte*) &zz) + 3) ^= 0x80; + } + duration1 = micros() - start; + Serial.println(duration1 / 30000.0); + Serial.println(zz); + + start = micros(); + for (int i = 0; i < 30000; i++) + { + zz = -zz; + } + duration2 = micros() - start; + Serial.println(duration2 / 30000.0); + Serial.print("Gain:\t"); + Serial.println(1.0 * duration2 / duration1); + Serial.println(zz); + Serial.println(); + delay(10); +} + +void test_less_zero() +{ + Serial.println(__FUNCTION__); + Serial.println("if (zz < 0) "); + start = micros(); + for (int i = 0; i < 30000; i++) + { + if ( *(((byte*) &zz) + 3) & 0x80) x = 2; // equals if (zz < 0); + } + duration1 = micros() - start; + Serial.println(duration1 / 30000.0); + Serial.println(zz); + + start = micros(); + for (int i = 0; i < 30000; i++) + { + if (zz < 0) x = 2; + } + duration2 = micros() - start; + Serial.println(duration2 / 30000.0); + Serial.print("Gain:\t"); + Serial.println(1.0 * duration2 / duration1); + Serial.println(zz); + + start = micros(); + for (int i = 0; i < 30000; i++) + { + x = 2; + } + Serial.println((micros() - start) / 30000.0, 4); + Serial.println(zz); + Serial.println(); + delay(10); +} + +void test5() +{ + Serial.println(__FUNCTION__); + zz = -100; + if (zz < 0) Serial.println("N"); + else Serial.println("P"); + zz = 100; + if (zz < 0) Serial.println("N"); + else Serial.println("P"); + + zz = -100; + if (*(((byte*) &zz) + 3) & 0x80) Serial.println("N"); + else Serial.println("P"); + zz = 100; + if (*(((byte*) &zz) + 3) & 0x80) Serial.println("N"); + else Serial.println("P"); +} + +void loop() +{ +} + +// -- END OF FILE -- diff --git a/libraries/IEEE754tools/examples/float2double/float2double.ino b/libraries/IEEE754tools/examples/float2double/float2double.ino new file mode 100644 index 00000000..14bd1d32 --- /dev/null +++ b/libraries/IEEE754tools/examples/float2double/float2double.ino @@ -0,0 +1,93 @@ +// +// FILE: float2double.ino +// AUTHOR: Rob Tillaart +// VERSION: 0.2.0 +// PURPOSE: experimental expands a float in a IEEE 754 double to be printed to PC. +// + +#include + +byte x[8]; + +void setup() +{ + Serial.begin(115200); + + test1(); + test2(); + test3(); + test4(); + + Serial.println("done"); +} + +void test1() +{ + Serial.println(); + for (float f = -50.0; f < 50.0; f += 10.0) + { + dumpFloat(f); + float2DoublePacked(f, x, LSBFIRST); + dumpByteArray(x); + float g = doublePacked2Float(x, LSBFIRST); + Serial.println(g, 10); + if (f != g) Serial.println("-- FAIL --"); + Serial.println(); + } +} + +void test2() +{ + Serial.println("\n0.15625"); + dumpFloat(0.15625); + // sign = 0 + // exponent = 7C + // mantissa = 0020 0000 +} + +void test3() +{ + Serial.println("\nPI-check"); + Serial.println(PI, 20); + float2DoublePacked(PI, x); + dumpByteArray(x); + float f = doublePacked2Float(x, LSBFIRST); + Serial.println(f, 20); + Serial.println(); +} + +void test4() +{ + Serial.println("\nBIG-check"); + Serial.println(1.23456789e38, 20); + dumpFloat(1.23456789e38); + float2DoublePacked(1.23456789e38, x); + dumpByteArray(x); + float f = doublePacked2Float(x, LSBFIRST); + Serial.println(f / 1e38, 20); // divide prevents ovf in output + dumpFloat(f); + Serial.println(); +} + + +void loop() +{ +} + + + + + + + + +void dumpByteArray(byte *ar) +{ + for (int i = 0; i < 8; i++) + { + if (ar[i] < 0x10) Serial.print('0'); + Serial.print(ar[i], HEX); + Serial.print('\t'); + } + Serial.println(); +} diff --git a/libraries/IEEE754tools/library.json b/libraries/IEEE754tools/library.json index 31c6a926..f61e8473 100644 --- a/libraries/IEEE754tools/library.json +++ b/libraries/IEEE754tools/library.json @@ -1,7 +1,7 @@ { "name": "IEEE754tools", "keywords": "IEEE,754,float,double,algorithms", - "description": "Helper functions for IEEE 754 floating point format.", + "description": "Fast helper functions for IEEE 754 floats.", "authors": [ { @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/IEEE754tools.git" }, - "version":"0.1.3", + "version":"0.2.0", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/IEEE754tools" - } + "platforms": "*" } diff --git a/libraries/IEEE754tools/library.properties b/libraries/IEEE754tools/library.properties index b503bf95..77d5a6b4 100644 --- a/libraries/IEEE754tools/library.properties +++ b/libraries/IEEE754tools/library.properties @@ -1,9 +1,11 @@ name=IEEE754tools -version=0.1.3 +version=0.2.0 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Helper functions for IEEE 754 floating point format. +sentence=Fast helper functions for IEEE754 floats. paragraph= category=Data Processing -url=https://github.com/RobTillaart/Arduino/tree/master/libraries/ -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/IEEE754tools +architectures=* +includes=IEEE754tools.h +depends= diff --git a/libraries/IEEE754tools/readme.md b/libraries/IEEE754tools/readme.md index b5dcc0d1..019bd8a1 100644 --- a/libraries/IEEE754tools/readme.md +++ b/libraries/IEEE754tools/readme.md @@ -1,4 +1,32 @@ -IEEE754_tools.h contains a collection of bit-hacks to speed up a number of operations on floating pointnumbers on the Arduino. -If you don't need micro-second speedups do not use these code snippets. -in short: USE WITH CARE +# IEEE754_tools + +Arduino library to manipulate IEEE754 float numbers fast. + +## Description + +IEEE754tools.h contains a collection of bit-hacks to speed up a number +of operations on floating point numbers on the Arduino. These bit-hacks +started in 2010 (oldest code found) or maybe even earlier. + +http://en.wikipedia.org/wiki/Double_precision + +http://en.wikipedia.org/wiki/Single-precision_floating-point_format + + +## WARNING +* If you don't need micro-second speedups **do not use** these code snippets. +* code is experimental, so use with care. +* only tested on UNO + +## Future + +* include https://playground.arduino.cc/Main/IEEE754tools/ +* write examples +* test on ESP32 +* binary transfer over serial (see playground) + +## Operations + +See examples + diff --git a/libraries/hmc6352/LICENSE b/libraries/hmc6352/LICENSE new file mode 100644 index 00000000..95ba2177 --- /dev/null +++ b/libraries/hmc6352/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2011-2020 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/hmc6352/README.md b/libraries/hmc6352/README.md new file mode 100644 index 00000000..4bed2593 --- /dev/null +++ b/libraries/hmc6352/README.md @@ -0,0 +1,18 @@ +# HMC6352 + +Arduino library for HMC6352 compass sensor + +## Description + +BETA: WARNING: BETA: WARNING: BETA: WARNING: BETA: + +This library is BETA, only tested partially and not thoroughly +No guarantees, use at own risk, all disclaimers apply +The example sketch can be used to config the compass. +For switching operational mode one must reboot the system. + +WARNING: BETA: WARNING: BETA: WARNING: BETA: WARNING: + +## Operation + +See examples diff --git a/libraries/hmc6352/examples/continuousDemo/continuousDemo.ino b/libraries/hmc6352/examples/continuousDemo/continuousDemo.ino index 22d1a3b3..dd298f85 100644 --- a/libraries/hmc6352/examples/continuousDemo/continuousDemo.ino +++ b/libraries/hmc6352/examples/continuousDemo/continuousDemo.ino @@ -1,54 +1,47 @@ -// +// // FILE: continuousDemo.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 +// VERSION: 0.2.0 // PURPOSE: demo app HMC6352 library - continuous mode for Arduino // -// HISTORY: +// HISTORY: // 0.1.0 - 2011-04-12 initial version // 0.1.1 - 2017-09-13 renamed to .ino -// -// Released to the public domain -// -// All disclaimers apply use at own risk +// 0.2.0 2020-06-13 match 0.2.0 version of lib // -#include #include hmc6352 Compass(0x21); // 0x21 <==> 33 <==> 66 >> 1 +int heading; + void setup() { - Serial.begin(19200); - Serial.println("HMC6352: Version "); - Serial.println(HMC_LIB_VERSION); - Serial.print("current output modus"); - Serial.println(Compass.getOutputModus()); + Serial.begin(115200); + Serial.println(__FILE__); + Serial.println("LIB: "); + Serial.println(HMC6352_LIB_VERSION); + + Compass.begin(); - int x = Compass.askHeading(); - //Serial.print("Ask returns: "); - //Serial.println(x); + Serial.print("Output modus: "); + Serial.println(Compass.getOutputModus()); + + heading = Compass.askHeading(); + Serial.print("Ask returns: "); + Serial.println(heading); } -int x; void loop() { // in continuous mode it is not needed to ask for a new reading every time // as it will do a new reading continuously even when not asked for // Try making a fast turn and see the difference with the query mode - x = Compass.readHeading(); + heading = Compass.readHeading(); Serial.print("Degree : "); - Serial.println(x); + Serial.println(heading); delay(1000); } + // END OF FILE - - - - - - - - - diff --git a/libraries/hmc6352/examples/hmc6352Config/hmc6352Config.ino b/libraries/hmc6352/examples/hmc6352Config/hmc6352Config.ino index bc3b0394..3f1918ce 100644 --- a/libraries/hmc6352/examples/hmc6352Config/hmc6352Config.ino +++ b/libraries/hmc6352/examples/hmc6352Config/hmc6352Config.ino @@ -1,30 +1,30 @@ // // FILE: hmc6352Config.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 -// PURPOSE: test app HMC6352 library for Arduino +// VERSION: 0.2.0 +// PURPOSE: test HMC6352 library for Arduino // // HISTORY: // 0.1.0 - 2011-04-12 initial version // 0.1.1 - 2017-09-13 renamed to .ino; -// -// Released to the public domain +// 0.2.0 2020-06-13 match lib version 0.2.0 // -#include #include hmc6352 Compass(33); void setup() { - Serial.begin(19200); - Serial.println("HMC6352: Config"); - Serial.println(HMC_LIB_VERSION); + Serial.begin(115200); + Serial.println(__FILE__); + Serial.println("LIB: "); + Serial.println(HMC6352_LIB_VERSION); + + Compass.begin(); dumpEEPROM(); } -int x; void loop() { @@ -60,73 +60,71 @@ void loop() char cmd = Serial.read(); // EXECUTE COMMAND - switch(cmd) + switch (cmd) { - case 'F': - factoryReset(); - break; - case 'E': - dumpEEPROM(); - break; - case 'R': - dumpRAM(); - break; - case 'A': - askHeading(); - break; - case 'Q': - readHeading(); - break; - case 'W': - x = Compass.wakeUp(); - Serial.println(x, DEC); - break; - case 'S': - x = Compass.sleep(); - Serial.println(x, DEC); - break; - case 'O': - OutPutModusMenu(); - break; - case '7': - // mode , freq , reset - Compass.setOperationalModus(STANDBY, 1, true); // 10 default val - Serial.println("Reboot Arduino"); - break; - case '8': - Compass.setOperationalModus(QUERY, 1, true); // 10 default val - Serial.println("Reboot Arduino"); - break; - case '9': - Compass.setOperationalModus(CONT, 20, true); // 10 default val - Serial.println("Reboot Arduino"); - break; - case 'U': - Compass.callibrationOn(); - break; - case 'X': - Compass.callibrationOff(); - break; - case 'I': - setI2Caddress(); - break; - case '@': - Compass.updateOffsets(); - break; - case 'Z': - while (1) - { + case 'F': + factoryReset(); + break; + case 'E': + dumpEEPROM(); + break; + case 'R': + dumpRAM(); + break; + case 'A': + askHeading(); + break; + case 'Q': readHeading(); - if (Serial.available()>0) + break; + case 'W': + Serial.println(Compass.wakeUp(), DEC); + break; + case 'S': + Serial.println(Compass.sleep(), DEC); + break; + case 'O': + OutPutModusMenu(); + break; + case '7': + // mode , freq , reset + Compass.setOperationalModus(STANDBY, 1, true); // 10 default val + Serial.println("Reboot Arduino"); + break; + case '8': + Compass.setOperationalModus(QUERY, 1, true); // 10 default val + Serial.println("Reboot Arduino"); + break; + case '9': + Compass.setOperationalModus(CONT, 20, true); // 10 default val + Serial.println("Reboot Arduino"); + break; + case 'U': + Compass.callibrationOn(); + break; + case 'X': + Compass.callibrationOff(); + break; + case 'I': + setI2Caddress(); + break; + case '@': + Compass.updateOffsets(); + break; + case 'Z': + while (1) { - Serial.read(); - break; + readHeading(); + if (Serial.available() > 0) + { + Serial.read(); + break; + } + delay(50); // 20 Hz } - delay(50); // 20 Hz - } - break; - default: - break; + break; + default: + break; } } @@ -157,9 +155,9 @@ void askHeading() void readHeading() { - int x = Compass.readHeading(); + int heading = Compass.readHeading(); Serial.print("DEGREE: "); - Serial.println(x); + Serial.println(heading); } void factoryReset() @@ -172,15 +170,17 @@ void dumpRAM() { Serial.println("\nDUMP RAM: (decimal values)"); Serial.println("Size 256 bytes (?) meaning mostly unknown"); - for (int i = 0; i< 256; i++) + for (int i = 0; i < 256; i++) { if (i % 16 == 0) { Serial.println(); Serial.print(i, HEX); - Serial.print(" : "); + Serial.print("\t: "); } - Serial.print(Compass.readRAM(i), HEX); + int val = Compass.readRAM(i); + if (val < 0x10) Serial.print('0'); + Serial.print(val, HEX); Serial.print("\t "); } Serial.println(); diff --git a/libraries/hmc6352/examples/queryDemo/queryDemo.ino b/libraries/hmc6352/examples/queryDemo/queryDemo.ino index be7ae8b9..f89e829c 100644 --- a/libraries/hmc6352/examples/queryDemo/queryDemo.ino +++ b/libraries/hmc6352/examples/queryDemo/queryDemo.ino @@ -1,36 +1,37 @@ // // FILE: queryDemo.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 -// PURPOSE: demo app HMC6352 library - query mode for Arduino +// VERSION: 0.2.0 +// PURPOSE: demo HMC6352 library - query mode for Arduino // // HISTORY: // 0.1.00 - 2011-04-12 initial version // 0.1.1 - 2017-09-13 renamed to .ino -// -// Released to the public domain -// -// All disclaimers apply use at own risk +// 0.2.0 2020-06-13 match lib version 0.2.0 // -#include #include -hmc6352 Compass(0x21); // 0x21 <==> 33 <==> 66 >> 1 +hmc6352 Compass(0x21); + +int heading; void setup() { - Serial.begin(19200); - Serial.println("HMC6352: Version "); - Serial.println(HMC_LIB_VERSION); - Serial.print("current output modus"); + Serial.begin(115200); + Serial.println(__FILE__); + Serial.println("LIB: "); + Serial.println(HMC6352_LIB_VERSION); + + Compass.begin(); + + Serial.print("Output modus: "); Serial.println(Compass.getOutputModus()); - int x = Compass.askHeading(); - //Serial.print("Ask returns: "); - //Serial.println(x); + heading = Compass.askHeading(); + Serial.print("Ask returns: "); + Serial.println(heading); } -int x; void loop() { @@ -38,10 +39,10 @@ void loop() // as it will do a new reading directly after the chip is read // and waits until it is asked for. // Try making a fast turn and smile ... - x = Compass.readHeading(); + heading = Compass.readHeading(); Serial.print("Degree : "); - Serial.println(x); + Serial.println(heading); delay(1000); } -// END OF FILE \ No newline at end of file +// END OF FILE diff --git a/libraries/hmc6352/examples/set2continuous/set2continuous.ino b/libraries/hmc6352/examples/set2continuous/set2continuous.ino index 8c1769c6..96095468 100644 --- a/libraries/hmc6352/examples/set2continuous/set2continuous.ino +++ b/libraries/hmc6352/examples/set2continuous/set2continuous.ino @@ -1,43 +1,32 @@ // // FILE: set2continuous.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 -// PURPOSE: Reset HMC6352 to continuous mode +// VERSION: 0.2.0 +// PURPOSE: Reset HMC6352 to continuous mode without library // // HISTORY: // 0.1.0 - 2011-04-12 initial version // 0.1.1 - 2017-09-13 renamed to .ino; fix wire.receive -// -// Released to the public domain -// -// All disclaimers apply use at own risk +// 0.2.0 2020-06-13 refactor // #include -#if defined(ARDUINO) && ARDUINO >= 100 -#define WIRE_WRITE Wire.write -#define WIRE_READ Wire.read -#else -#define WIRE_WRITE Wire.send -#define WIRE_READ Wire.receive -#endif - int HMC = 0x21; int ledPin = 13; boolean ledState = LOW; -byte value; -int x; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.print("HMC6352 : start - "); Serial.println(HMC, HEX); pinMode(ledPin, OUTPUT); + digitalWrite(ledPin, ledState); Wire.begin(); + delay(1000); // give all things time to start } @@ -50,31 +39,31 @@ void loop() // write continuous mode to RAM 0x74 and do an L command immediately after it // pull out 5 volt if it reads back 0x72 Wire.beginTransmission(HMC); - WIRE_WRITE('G'); - WIRE_WRITE(0x74); - WIRE_WRITE(0x72); // 20 Hz | Reset = True | CONT - WIRE_WRITE('L'); - // WIRE_WRITE('O'); optional reset - x = Wire.endTransmission(); + Wire.write('G'); + Wire.write(0x74); + Wire.write(0x72); // 20 Hz | Reset = True | CONT + Wire.write('L'); + // Wire.write('O'); optional reset + Wire.endTransmission(); delay(10); // Read the EEPROM value for feedback as this is the next startup value Wire.beginTransmission(HMC); - WIRE_WRITE('r'); - WIRE_WRITE(0x07); - x = Wire.endTransmission(); + Wire.write('r'); + Wire.write(0x07); + Wire.endTransmission(); delay(10); int cnt = Wire.requestFrom(HMC, 1); if (cnt == 1) { - value = WIRE_READ(); Serial.print("Current Mode: "); - Serial.println((int)value, BIN); + Serial.println((int)Wire.read(), BIN); } else { - Serial.println("Error..."); + Serial.print("Error... : "); + Serial.println(cnt); } } diff --git a/libraries/hmc6352/examples/set2query/set2query.ino b/libraries/hmc6352/examples/set2query/set2query.ino index 7029e6a6..b7e1f216 100644 --- a/libraries/hmc6352/examples/set2query/set2query.ino +++ b/libraries/hmc6352/examples/set2query/set2query.ino @@ -1,43 +1,32 @@ // // FILE: Set2query.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 -// PURPOSE: Reset HMC6352 to query mode +// VERSION: 0.2.0 +// PURPOSE: Reset HMC6352 to query mode without library // // HISTORY: // 0.1.00 - 2011-04-12 initial version // 0.1.1 - 2017-09-13 renamed to .ino; fix receive -// -// Released to the public domain -// -// All disclaimers apply use at own risk +// 0.2.0 2020-06-13 refactor // #include -#if defined(ARDUINO) && ARDUINO >= 100 -#define WIRE_WRITE Wire.write -#define WIRE_READ Wire.read -#else -#define WIRE_WRITE Wire.send -#define WIRE_READ Wire.receive -#endif - int HMC = 0x21; int ledPin = 13; boolean ledState = LOW; -byte value; -int x; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.print("HMC6352 : start - "); Serial.println(HMC, HEX); pinMode(ledPin, OUTPUT); + digitalWrite(ledPin, ledState); Wire.begin(); + delay(1000); // give all things time to start } @@ -51,32 +40,32 @@ void loop() // this is done to "break through" the continuous mode if needed // pull out 5 volt if it reads back 0x50 Wire.beginTransmission(HMC); - WIRE_WRITE('G'); - WIRE_WRITE(0x74); - WIRE_WRITE(0x51); // 10 Hz | Reset = True | QUERY - WIRE_WRITE('L'); - // WIRE_WRITE('O'); optional reset - x = Wire.endTransmission(); + Wire.write('G'); + Wire.write(0x74); + Wire.write(0x51); // 10 Hz | Reset = True | QUERY + Wire.write('L'); + // Wire.write('O'); optional reset + Wire.endTransmission(); delay(10); // Read the EEPROM value for feedback as this is the next startup value Wire.beginTransmission(HMC); - WIRE_WRITE('r'); - WIRE_WRITE(0x07); - x = Wire.endTransmission(); + Wire.write('r'); + Wire.write(0x07); + Wire.endTransmission(); delay(10); int cnt = Wire.requestFrom(HMC, 1); if (cnt == 1) { - value = WIRE_READ(); Serial.print("Current Mode: "); - Serial.println((int)value, BIN); + Serial.println((int)Wire.read(), BIN); } else { - Serial.println("Error..."); + Serial.print("Error... : "); + Serial.println(cnt); } } -// END OF FILE \ No newline at end of file +// END OF FILE diff --git a/libraries/hmc6352/examples/set2standby/set2standby.ino b/libraries/hmc6352/examples/set2standby/set2standby.ino index bb531317..19b46ead 100644 --- a/libraries/hmc6352/examples/set2standby/set2standby.ino +++ b/libraries/hmc6352/examples/set2standby/set2standby.ino @@ -1,44 +1,33 @@ // // FILE: set2standby.pde // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 -// PURPOSE: Reset HMC6352 to standby mode +// VERSION: 0.2.0 +// PURPOSE: Reset HMC6352 to standby mode without library // (esp if it is struck in continuous mode - Arduino) // // HISTORY: // 0.1.00 - 2011-04-12 initial version // 0.1.1 - 2017-09-13 renamed to .ino; fix wire.receive -// -// Released to the public domain -// -// All disclaimers apply use at own risk +// 0.2.0 2020-06-13 refactor // #include -#if defined(ARDUINO) && ARDUINO >= 100 -#define WIRE_WRITE Wire.write -#define WIRE_READ Wire.read -#else -#define WIRE_WRITE Wire.send -#define WIRE_READ Wire.receive -#endif - int HMC = 0x21; int ledPin = 13; boolean ledState = LOW; -byte value; -int x; void setup() { - Serial.begin(9600); + Serial.begin(115200); Serial.print("HMC6352 : start - "); Serial.println(HMC, HEX); pinMode(ledPin, OUTPUT); + digitalWrite(ledPin, ledState); Wire.begin(); + delay(1000); // give all things time to start } @@ -52,31 +41,31 @@ void loop() // this is done to "break through" the continuous mode // pull out 5 volt if it reads back 0x50 Wire.beginTransmission(HMC); - WIRE_WRITE('G'); - WIRE_WRITE(0x74); - WIRE_WRITE(0x50); - WIRE_WRITE('L'); - // WIRE_WRITE('O'); optional reset - x = Wire.endTransmission(); + Wire.write('G'); + Wire.write(0x74); + Wire.write(0x50); + Wire.write('L'); + // Wire.write('O'); optional reset + Wire.endTransmission(); delay(10); // Read the EEPROM value for feedback as this is the next startup value Wire.beginTransmission(HMC); - WIRE_WRITE('r'); - WIRE_WRITE(0x07); - x = Wire.endTransmission(); + Wire.write('r'); + Wire.write(0x07); + Wire.endTransmission(); delay(10); int cnt = Wire.requestFrom(HMC, 1); if (cnt == 1) { - value = WIRE_READ(); Serial.print("Current Mode: "); - Serial.println((int)value, BIN); + Serial.println((int)Wire.read(), BIN); } else { - Serial.println("Error..."); + Serial.print("Error... : "); + Serial.println(cnt); } } diff --git a/libraries/hmc6352/examples/standbyDemo/standbyDemo.ino b/libraries/hmc6352/examples/standbyDemo/standbyDemo.ino index 70ff2c04..143a5424 100644 --- a/libraries/hmc6352/examples/standbyDemo/standbyDemo.ino +++ b/libraries/hmc6352/examples/standbyDemo/standbyDemo.ino @@ -1,31 +1,31 @@ // // FILE: standbyDemo.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 +// VERSION: 0.2.0 // PURPOSE: demo app HMC6352 library - standby mode for Arduino // // HISTORY: // 0.1.00 - 2011-04-12 initial version // 0.1.1 - 2017-09-13 renamed to .ino; -// -// Released to the public domain -// -// All disclaimers apply use at own risk +// 0.2.0 2020-06-13 refactor // -#include #include -hmc6352 Compass(0x21); // 0x21 <==> 33 <==> 66 >> 1 -int x; +hmc6352 Compass(0x21); +int heading; void setup() { - Serial.begin(19200); - Serial.println("HMC6352: Version "); - Serial.println(HMC_LIB_VERSION); - Serial.print("current output modus"); + Serial.begin(115200); + Serial.println(__FILE__); + Serial.println("LIB: "); + Serial.println(HMC6352_LIB_VERSION); + + Compass.begin(); + + Serial.print("Output modus"); Serial.println(Compass.getOutputModus()); } @@ -38,13 +38,13 @@ void loop() // without impact on the footprint of the lib. // this way one can ask a make a reading and fetch it a bit later. // TODO is it fast enough for IRQ ? - x = Compass.askHeading(); + int x = Compass.askHeading(); //Serial.print("Ask returns: "); //Serial.println(x); - x = Compass.readHeading(); - Serial.print("ask & read : Degree : "); - Serial.println(x); + heading = Compass.readHeading(); + Serial.print("ask & read : "); + Serial.println(heading); Compass.sleep(); // low energy mode delay(500); @@ -52,7 +52,7 @@ void loop() // this is the simplest mode to use the library // suitable for 99.9% of all robots :) Compass.wakeUp(); - Serial.print("getHeading : Degree : "); + Serial.print("getHeading : "); Serial.println(Compass.getHeading()); Compass.sleep(); delay(500); diff --git a/libraries/hmc6352/hmc6352.cpp b/libraries/hmc6352/hmc6352.cpp index 81310287..d74aae04 100644 --- a/libraries/hmc6352/hmc6352.cpp +++ b/libraries/hmc6352/hmc6352.cpp @@ -1,8 +1,8 @@ // // FILE: hmc6352.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.03 -// PURPOSE: HMC6352 library for Arduino +// VERSION: 0.2.0 +// PURPOSE: Arduino library for HMC6352 digital compass sensor // // HISTORY: // 0.1.00 - 2011-04-07 initial version @@ -10,20 +10,22 @@ // 0.1.02 - 2011-04-12 added timing, fixed a bug // 0.1.03 - 2011-04-13 fixed small things; added getHeading() // 0.1.4 - 2017-09-13 minor refactor -// -// Released to the public domain +// 0.2.0 2020-06-12 remove pre1.0 support, main refactor // -#include -#include +#include "hmc6352.h" -#if defined(ARDUINO) && ARDUINO >= 100 -#define WIRE_WRITE Wire.write -#define WIRE_READ Wire.read -#else -#define WIRE_WRITE Wire.send -#define WIRE_READ Wire.receive -#endif +#define HMC_GET_DATA 0x41 +#define HMC_WAKE 0x57 +#define HMC_SLEEP 0x53 +#define HMC_SAVE_OP_MODE 0x4C +#define HMC_CALLIBRATE_ON 0x43 +#define HMC_CALLIBRATE_OFF 0x45 +#define HMC_UPDATE_OFFSETS 0x4F +#define HMC_WRITE_RAM 0x47 +#define HMC_READ_RAM 0x67 +#define HMC_WRITE_EEPROM 0x77 +#define HMC_READ_EEPROM 0x72 /* ERROR CODES ALL FUNCTIONS // @@ -47,10 +49,21 @@ hmc6352::hmc6352(uint8_t device) { - Wire.begin(); _device = constrain(device, 0x10, 0xF6); } +#if defined (ESP8266) || defined(ESP32) +void hmc6352::begin(uint8_t sda, uint8_t scl) +{ + Wire.begin(sda, scl); +} +#endif + +void hmc6352::begin() +{ + Wire.begin(); +} + int hmc6352::getHeading() { int rv = askHeading(); @@ -67,13 +80,13 @@ int hmc6352::askHeading() return rv; } -// read the last value from the +// read the last value from the sensor int hmc6352::readHeading() { int rv = Wire.requestFrom(_device, (uint8_t)2); // remove ambiguity if (rv != 2) return -10; - rv = WIRE_READ() * 256; // MSB - rv += WIRE_READ(); // LSB + rv = Wire.read() * 256; // MSB + rv += Wire.read(); // LSB return rv; } @@ -118,26 +131,24 @@ int hmc6352::setOperationalModus(hmcMode m, uint8_t freq, bool periodicReset) byte omcb = 0; // Operational Mode Control Byte switch(freq) { - case 1: break; - case 5: omcb |= 0x20; break; - case 10: omcb |= 0x40; break; - case 20: omcb |= 0x60; break; - default: return -21; + case 1: break; + case 5: omcb |= 0x20; break; + case 10: omcb |= 0x40; break; + case 20: omcb |= 0x60; break; + default: return -21; } if (periodicReset) omcb |= 0x10; switch(m) { - case STANDBY: break; // omcb |= 0x00; - case QUERY: omcb |= 0x01; break; - case CONT: omcb |= 0x02; break; - default: return -20; + case STANDBY: omcb |= 0x00; break; + case QUERY: omcb |= 0x01; break; + case CONT: omcb |= 0x02; break; + default: return -20; } - writeCmd(HMC_WRITE_RAM, 0x74, omcb); - cmd(HMC_SAVE_OP_MODE); - delayMicroseconds(125); + saveOpMode(omcb); return omcb; } @@ -199,7 +210,6 @@ int hmc6352::getI2CAddress() // NOT TESTED // meaning time delay unknown -// therefore removed from lib for now int hmc6352::setTimeDelay(uint8_t msec) { return writeCmd(HMC_WRITE_EEPROM, 5, msec); @@ -212,7 +222,6 @@ int hmc6352::getTimeDelay() // NOT TESTED // meaning measurement summing unknown -// therefore removed from lib for now int hmc6352::setMeasurementSumming(uint8_t ms) { if (ms > 16 ) ms = 16; @@ -224,10 +233,10 @@ int hmc6352::getMeasurementSumming() return readCmd(HMC_READ_EEPROM, 6); } -// Makes only sense in setOperationalModus() -// therefore removed from lib for now -int hmc6352::saveOpMode() +// used by setOperationalModus() +int hmc6352::saveOpMode(byte OpMode) { + writeCmd(HMC_WRITE_RAM, 0x74, OpMode); int rv = cmd(HMC_SAVE_OP_MODE); delayMicroseconds(125); return rv; @@ -277,7 +286,7 @@ int hmc6352::readRAM(uint8_t address) int hmc6352::cmd(uint8_t c) { Wire.beginTransmission(_device); - WIRE_WRITE(c); + Wire.write(c); int rv = Wire.endTransmission(); delay(10); return rv; @@ -286,8 +295,8 @@ int hmc6352::cmd(uint8_t c) int hmc6352::readCmd(uint8_t c, uint8_t address) { Wire.beginTransmission(_device); - WIRE_WRITE(c); - WIRE_WRITE(address); + Wire.write(c); + Wire.write(address); int rv = Wire.endTransmission(); if (rv != 0) return -rv; @@ -295,16 +304,16 @@ int hmc6352::readCmd(uint8_t c, uint8_t address) rv = Wire.requestFrom(_device, (uint8_t)1); if (rv != 1) return -10; - rv = WIRE_READ(); + rv = Wire.read(); return rv; } int hmc6352::writeCmd(uint8_t c, uint8_t address, uint8_t data) { Wire.beginTransmission(_device); - WIRE_WRITE(c); - WIRE_WRITE(address); - WIRE_WRITE(data); + Wire.write(c); + Wire.write(address); + Wire.write(data); int rv = Wire.endTransmission(); delayMicroseconds(70); return rv; diff --git a/libraries/hmc6352/hmc6352.h b/libraries/hmc6352/hmc6352.h index b809ff5f..c570ee2f 100644 --- a/libraries/hmc6352/hmc6352.h +++ b/libraries/hmc6352/hmc6352.h @@ -1,35 +1,36 @@ -#ifndef HMC6352_H -#define HMC6352_H +#pragma once // // FILE: hmc6352.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.4 +// VERSION: 0.2.0 // PURPOSE: HMC6352 library for Arduino // -// DETAILS: see cpp file -// -// Released to the public domain -// +// HISTORY: see cpp file -#if ARDUINO >= 100 +#include "Wire.h" #include "Arduino.h" -#else -#include "WProgram.h" -#endif -#define HMC_LIB_VERSION "0.1.4" +#define HMC6352_LIB_VERSION "0.2.0" -#define HMC_GET_DATA 0x41 -#define HMC_WAKE 0x57 -#define HMC_SLEEP 0x53 -#define HMC_SAVE_OP_MODE 0x4C -#define HMC_CALLIBRATE_ON 0x43 -#define HMC_CALLIBRATE_OFF 0x45 -#define HMC_UPDATE_OFFSETS 0x4F -#define HMC_WRITE_RAM 0x47 -#define HMC_READ_RAM 0x67 -#define HMC_WRITE_EEPROM 0x77 -#define HMC_READ_EEPROM 0x72 +/* ERROR CODES ALL FUNCTIONS +// +// * twi_writeTo codes (== endTransmission commands) +// 0 .. OK +// -1 .. length to long for buffer +// -2 .. address send, NACK received +// -3 .. data send, NACK received +// -4 .. other twi error (lost bus arbitration, bus error, ..) +// +// * requestFrom +// -10 .. not enough values returned +// +// * function calls +// 0 .. OK +// -20 .. error param1 +// -21 .. error param2 +// -22 .. error param3 +// +*/ enum hmcMode { STANDBY=0, QUERY=1, CONT=2, ERROR}; @@ -38,6 +39,11 @@ class hmc6352 public: hmc6352(uint8_t device); +#if defined (ESP8266) || defined(ESP32) + void begin(uint8_t sda, uint8_t scl); +#endif + void begin(); + // BASIC CALLS FOR STANDBY MODE int getHeading(void); // just a merge of ask & read int askHeading(void); @@ -67,12 +73,14 @@ public: int writeRAM(uint8_t address, uint8_t data); int readRAM(uint8_t address); + // allow power users to set operational mode flags + int saveOpMode(byte OpMode); + // NOT TESTED / UNKNOWN int setTimeDelay(uint8_t msec); int getTimeDelay(); int setMeasurementSumming(uint8_t ms); int getMeasurementSumming(); - int saveOpMode(void); int updateOffsets(void); private: @@ -83,4 +91,4 @@ private: uint8_t _device; }; -#endif +// -- END OF FILE -- diff --git a/libraries/hmc6352/keywords.txt b/libraries/hmc6352/keywords.txt new file mode 100644 index 00000000..66946c39 --- /dev/null +++ b/libraries/hmc6352/keywords.txt @@ -0,0 +1,34 @@ +# Syntax Coloring Map For HMC6352 + +# Datatypes (KEYWORD1) +HMC6352 KEYWORD1 + +# Methods and Functions (KEYWORD2) +getHeading KEYWORD2 +askHeading KEYWORD2 +readHeading KEYWORD2 +wakeUp KEYWORD2 +sleep KEYWORD2 +factoryReset KEYWORD2 +setOperationalModus KEYWORD2 +getOperationalModus KEYWORD2 +setOutputModus KEYWORD2 +getOutputModus KEYWORD2 +callibrationOn KEYWORD2 +callibrationOff KEYWORD2 +setI2CAddress KEYWORD2 +getI2CAddress KEYWORD2 +writeEEPROM KEYWORD2 +readEEPROM KEYWORD2 +writeRAM KEYWORD2 +readRAM KEYWORD2 + +setTimeDelay KEYWORD2 +getTimeDelay KEYWORD2 +setMeasurementSumming KEYWORD2 +getMeasurementSumming KEYWORD2 +saveOpMode KEYWORD2 +updateOffsets KEYWORD2 + +# Constants (LITERAL1) +HMC6352_LIB_VERSION LITERAL1 diff --git a/libraries/hmc6352/library.json b/libraries/hmc6352/library.json index 9aa1f6dd..3a64a80a 100644 --- a/libraries/hmc6352/library.json +++ b/libraries/hmc6352/library.json @@ -1,7 +1,7 @@ { "name": "HMC6352", "keywords": "Compass,heading", - "description": "Experimental library for digital compass sensor", + "description": "Experimental Arduino library for HMC6352 digital compass sensor", "authors": [ { @@ -13,12 +13,9 @@ "repository": { "type": "git", - "url": "https://github.com/RobTillaart/Arduino.git" + "url": "https://github.com/RobTillaart/HMC6352" }, - "version":"0.1.4", + "version":"0.2.0", "frameworks": "arduino", - "platforms": "*", - "export": { - "include": "libraries/hmc6352" - } + "platforms": "*" } diff --git a/libraries/hmc6352/library.properties b/libraries/hmc6352/library.properties index 6367a69a..fa8a5f84 100644 --- a/libraries/hmc6352/library.properties +++ b/libraries/hmc6352/library.properties @@ -1,9 +1,11 @@ -name=HMC6532 -version=0.1.4 +name=HMC6352 +version=0.2.0 author=Rob Tillaart maintainer=Rob Tillaart -sentence=Experimental library for digital compass sensor +sentence=Experimental Arduino library for HMC6352 digital compass sensor paragraph= category=Sensors -url=https://github.com/RobTillaart/Arduino/tree/master/libraries -architectures=* \ No newline at end of file +url=https://github.com/RobTillaart/HMC6352 +architectures=* +includes=hmc6352.h +depends=*