mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
update libraries E-I
This commit is contained in:
parent
a19ec7f025
commit
d13cd04dac
@ -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 --
|
||||
|
@ -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
|
||||
// -- END OF FILE --
|
||||
|
21
libraries/FRAM/LICENSE
Normal file
21
libraries/FRAM/LICENSE
Normal file
@ -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.
|
23
libraries/FRAM/README.md
Normal file
23
libraries/FRAM/README.md
Normal file
@ -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
|
@ -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] =
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=FRAM
|
||||
version=0.1.1
|
||||
name=FRAM_I2C
|
||||
version=0.2.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
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
|
||||
|
@ -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
|
||||
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
|
||||
|
@ -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 <WProgram.h>
|
||||
#else
|
||||
#include <Arduino.h>
|
||||
#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
|
||||
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 --
|
||||
|
21
libraries/FastMap/LICENSE
Normal file
21
libraries/FastMap/LICENSE
Normal file
@ -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.
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
66
libraries/FastMap/examples/fastMapDouble/fastMapDouble.ino
Normal file
66
libraries/FastMap/examples/fastMapDouble/fastMapDouble.ino
Normal file
@ -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 --
|
15
libraries/FastMap/keywords..txt
Normal file
15
libraries/FastMap/keywords..txt
Normal file
@ -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)
|
||||
|
@ -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": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=FastMap
|
||||
version=0.1.8
|
||||
version=0.3.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library with fast map function for Arduino.
|
||||
paragraph=
|
||||
category=Data Processing
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
|
||||
architectures=*
|
||||
url=https://github.com/RobTillaart/FastMap
|
||||
architectures=*
|
||||
includes=FastMap.h
|
||||
depends=
|
@ -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.
|
||||
|
@ -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 --
|
||||
|
||||
#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 --
|
||||
|
@ -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 --
|
||||
// -- END OF FILE --
|
||||
|
21
libraries/FastShiftIn/LICENSE
Normal file
21
libraries/FastShiftIn/LICENSE
Normal file
@ -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.
|
@ -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 --
|
@ -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 --
|
@ -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()
|
||||
{
|
||||
}
|
@ -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"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=FastShiftIn
|
||||
version=0.1.3
|
||||
version=0.2.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
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=*
|
||||
url=https://github.com/RobTillaart/FastShiftIn
|
||||
architectures=avr
|
||||
includes=FastShiftIn.h
|
||||
depends=
|
||||
|
119
libraries/FastShiftIn/performance.txt
Normal file
119
libraries/FastShiftIn/performance.txt
Normal file
@ -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...
|
||||
|
||||
|
@ -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
|
@ -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 --
|
@ -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 --
|
@ -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 --
|
||||
// -- END OF FILE --
|
||||
|
21
libraries/FastShiftOut/LICENSE
Normal file
21
libraries/FastShiftOut/LICENSE
Normal file
@ -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.
|
179
libraries/FastShiftOut/PerformanceNotes.txt
Normal file
179
libraries/FastShiftOut/PerformanceNotes.txt
Normal file
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
48
libraries/FastShiftOut/README.md
Normal file
48
libraries/FastShiftOut/README.md
Normal file
@ -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
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=FastShiftOut
|
||||
version=0.1.5
|
||||
version=0.2.1
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
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=*
|
||||
url=https://github.com/RobTillaart/FastSHiftOut
|
||||
architectures=*
|
||||
includes=FastShiftOut.h
|
||||
depends=
|
||||
|
21
libraries/Fraction/LICENSE
Normal file
21
libraries/Fraction/LICENSE
Normal file
@ -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.
|
@ -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 --
|
||||
|
108
libraries/Fraction/examples/FractionMediant/FractionMediant.ino
Normal file
108
libraries/Fraction/examples/FractionMediant/FractionMediant.ino
Normal file
@ -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 --
|
@ -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"
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
//
|
||||
// -- END OF FILE --
|
||||
|
@ -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 --
|
||||
//
|
18
libraries/Fraction/keywords..txt
Normal file
18
libraries/Fraction/keywords..txt
Normal file
@ -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)
|
||||
|
@ -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": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=Fraction
|
||||
version=0.1.8
|
||||
version=0.1.10
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
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=*
|
||||
url=https://github.com/RobTillaart/Fraction
|
||||
architectures=*
|
||||
includes=fraction.h
|
||||
depends=
|
||||
|
@ -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 ;)
|
||||
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.
|
||||
|
||||
|
@ -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 <WProgram.h>
|
||||
#else
|
||||
#include <Arduino.h>
|
||||
#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
|
||||
//
|
21
libraries/FunctionGenerator/LICENSE
Normal file
21
libraries/FunctionGenerator/LICENSE
Normal file
@ -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.
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
// END OF FILE
|
||||
|
@ -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
|
300
libraries/FunctionGenerator/functionGenerator.cpp
Normal file
300
libraries/FunctionGenerator/functionGenerator.cpp
Normal file
@ -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
|
28
libraries/FunctionGenerator/keywords.txt
Normal file
28
libraries/FunctionGenerator/keywords.txt
Normal file
@ -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)
|
||||
|
@ -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": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=FunctionGenerator
|
||||
version=0.1.4
|
||||
version=0.2.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
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=*
|
||||
url=https://github.com/RobTillaart/FunctionGenerator
|
||||
architectures=*
|
||||
includes=functionGenerator.h
|
||||
depends=
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 --
|
||||
|
136
libraries/HT16K33/examples/demo_VU/demo_VU.ino
Normal file
136
libraries/HT16K33/examples/demo_VU/demo_VU.ino
Normal file
@ -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 --
|
73
libraries/HT16K33/examples/demo_cache/demo_cache.ino
Normal file
73
libraries/HT16K33/examples/demo_cache/demo_cache.ino
Normal file
@ -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 --
|
@ -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 --
|
@ -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 --
|
@ -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 --
|
@ -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 --
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/HT16K33.git"
|
||||
},
|
||||
"version":"0.2.1",
|
||||
"version":"0.3.0",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=HT16K33
|
||||
version=0.2.1
|
||||
version=0.3.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino Library for HT16K33
|
||||
|
21
libraries/Histogram/LICENSE
Normal file
21
libraries/Histogram/LICENSE
Normal file
@ -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.
|
@ -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
|
||||
// -- END OF FILE --
|
||||
|
@ -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 <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#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
|
||||
// -- END OF FILE --
|
||||
|
@ -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
|
||||
|
@ -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": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=Histogram
|
||||
version=0.1.6
|
||||
version=0.2.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
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=*
|
||||
url=https://github.com/RobTillaart/Histogram
|
||||
architectures=*
|
||||
includes=histogram.h
|
||||
depends=
|
||||
|
@ -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().
|
||||
|
@ -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 <I2C_eeprom.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
|
||||
|
||||
|
||||
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 --
|
||||
|
@ -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
|
||||
// -- END OF FILE --
|
||||
|
21
libraries/I2C_EEPROM/LICENSE
Normal file
21
libraries/I2C_EEPROM/LICENSE
Normal file
@ -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.
|
128
libraries/I2C_EEPROM/examples/I2C_eeprom_test/new 2.txt
Normal file
128
libraries/I2C_EEPROM/examples/I2C_eeprom_test/new 2.txt
Normal file
@ -0,0 +1,128 @@
|
||||
|
||||
Try this (not tested)
|
||||
[code]
|
||||
//#include <UTFT.h>
|
||||
#include <SD.h>
|
||||
#include <Wire.h>
|
||||
#include <ArduCAM.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#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]
|
@ -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 <Wire.h>
|
||||
#include <I2C_eeprom.h>
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
#######################################
|
@ -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": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=I2C_EEPROM
|
||||
version=1.2.7
|
||||
version=1.3.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Library for I2C EEPROMS.
|
||||
paragraph=24LC256 et al
|
||||
category=Data Storage
|
||||
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
|
||||
architectures=*
|
||||
url=https://github.com/RobTillaart/I2C_EEPROM.git
|
||||
architectures=*
|
||||
includes=I2C_eeprom.h
|
||||
depends=
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
// -- END OF FILE --
|
||||
|
21
libraries/IEEE754tools/LICENSE
Normal file
21
libraries/IEEE754tools/LICENSE
Normal file
@ -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.
|
172
libraries/IEEE754tools/examples/FastNegate/FastNegate.ino
Normal file
172
libraries/IEEE754tools/examples/FastNegate/FastNegate.ino
Normal file
@ -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 --
|
@ -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 <IEEE754tools.h>
|
||||
|
||||
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();
|
||||
}
|
@ -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": "*"
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
name=IEEE754tools
|
||||
version=0.1.3
|
||||
version=0.2.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
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=*
|
||||
url=https://github.com/RobTillaart/IEEE754tools
|
||||
architectures=*
|
||||
includes=IEEE754tools.h
|
||||
depends=
|
||||
|
@ -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
|
||||
|
||||
|
21
libraries/hmc6352/LICENSE
Normal file
21
libraries/hmc6352/LICENSE
Normal file
@ -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.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user