mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
0.4.0 GAMMA
This commit is contained in:
parent
9d0c5e722c
commit
6472ef20d9
@ -6,7 +6,7 @@ jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: arduino/arduino-lint-action@v1
|
||||
with:
|
||||
library-manager: update
|
||||
|
@ -8,7 +8,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.6
|
||||
|
@ -10,7 +10,7 @@ jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: json-syntax-check
|
||||
uses: limitusus/json-syntax-check@v1
|
||||
with:
|
||||
|
@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.4.0] - 2023-01-26
|
||||
- optimize **setGamma()** especially for ESP32
|
||||
- optimize **get[]** especially for ESP32
|
||||
- update GitHub actions
|
||||
- update license 2023
|
||||
- update readme.md
|
||||
|
||||
----
|
||||
|
||||
## [0.3.1] - 2022-11-08
|
||||
- add changelog.md
|
||||
- add rp2040 to build-CI
|
||||
@ -28,7 +37,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- fix distinct()
|
||||
|
||||
## [0.2.1 2021-12-18
|
||||
- update library.json, license,
|
||||
- update library.json, license,
|
||||
- add constants, minor edits.
|
||||
|
||||
## [0.2.0 2021-11-02
|
||||
|
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-2022 Rob Tillaart
|
||||
Copyright (c) 2020-2023 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
|
||||
|
@ -13,25 +13,25 @@ Arduino Library for the GAMMA function to adjust brightness of LED's etc.
|
||||
|
||||
## Description
|
||||
|
||||
This library is provides a gamma lookup class. It is typical used to
|
||||
This library is provides a gamma lookup class. It is typical used to
|
||||
change the intensity / brightness of a LED to match the human eye.
|
||||
When a LED is given 50% PWM it looks far brighter for the eye.
|
||||
|
||||
This lib provides a balance between an expensive math function and the speed
|
||||
of a lookup table.
|
||||
of a lookup table.
|
||||
|
||||
The accuracy of the library depends on the size of the internal array.
|
||||
A size of 256 is the reference. Smaller arrays use interpolation and
|
||||
these interpolated values are good (< 1%) down to internal array size 16.
|
||||
A size of 256 is the reference. Smaller arrays use interpolation and
|
||||
these interpolated values are good (< 1%) down to internal array size 16.
|
||||
The size can be as small as 2 which is pretty inaccurate.
|
||||
In this latter case the curve is approximated by only two linear interpolations.
|
||||
In short, choose the size that fits your application.
|
||||
|
||||
The library has a **setGamma(float gamma)** function that allows an application
|
||||
to change the gamma value runtime.
|
||||
The library has a **setGamma(float gamma)** function that allows an application
|
||||
to change the gamma value runtime.
|
||||
This allows adjustments that are not possible with a fixed table.
|
||||
|
||||
The class provides **dump()** to create a table e.g. to place in PROGMEM.
|
||||
The class provides **dump()** to create a table e.g. to place in PROGMEM.
|
||||
Since 0.2.2 the library also has **dumpArray()** to generate a C-style array.
|
||||
|
||||
Note: tested on UNO and ESP32 only.
|
||||
@ -39,11 +39,15 @@ Note: tested on UNO and ESP32 only.
|
||||
|
||||
## Interface
|
||||
|
||||
```cpp
|
||||
#include "gamma.h"
|
||||
```
|
||||
|
||||
### Core functions
|
||||
|
||||
- **GAMMA(uint16_t size = 32)** constructor, gets the size of the internal
|
||||
array as parameter. The default for size = 32 as this is a good balance between performance
|
||||
and size of the internal array.
|
||||
and size of the internal array.
|
||||
The size parameter must be in {2, 4, 8, 16, 32, 64, 128, 256 }.
|
||||
- **~GAMMA()** destructor.
|
||||
- **bool begin()** The internal array is allocated and initialized with a gamma == 2.8.
|
||||
@ -51,26 +55,26 @@ This is an often used value to adjust light to human eye responses.
|
||||
Note that **begin()** must be called before any other function.
|
||||
Returns false if allocation fails.
|
||||
- **void setGamma(float gamma)** calculates and fills the array with new values.
|
||||
This can be done runtime so runtime adjustment of gamma mapping is possible.
|
||||
This can be done runtime so runtime adjustment of gamma mapping is possible.
|
||||
This calculation are relative expensive and takes quite some time (depending on size).
|
||||
If the array already is calculated for gamma, the calculation will be skipped.
|
||||
The parameter **gamma** must be > 0. The value 1 gives an 1:1 mapping.
|
||||
Returns false if gamma <= 0 or if no table is allocated.
|
||||
- **float getGamma()** returns the set gamma value.
|
||||
- **uint8_t operator \[uint8_t index\]** allows the GAMMA object to be accessed as an array.
|
||||
like ```x = G[40];``` Makes it easy to switch with a real array.
|
||||
like ```x = G[40];``` Makes it easy to switch with a real array.
|
||||
The value returned is in the range 0 .. 255, so the user may need to scale it e.g. to 0.0 - 1.0.
|
||||
Note: if internal table not allocated the function returns 0.
|
||||
Note: if internal table not allocated the function returns 0.
|
||||
As this is a legitimate value the user should take care.
|
||||
|
||||
|
||||
### Development functions
|
||||
|
||||
- **uint16_t size()** returns size of the internal array.
|
||||
- **uint16_t size()** returns the size of the internal array.
|
||||
This is always a power of 2.
|
||||
- **uint16_t distinct()** returns the number of distinct values in the table.
|
||||
- **uint16_t distinct()** returns the number of distinct values in the table.
|
||||
Especially with larger internal tables there will be duplicate numbers in the table.
|
||||
- **bool dump(Stream \*str = &Serial)** dumps the internal table to a stream, default Serial.
|
||||
- **bool dump(Stream \*str = &Serial)** dumps the internal table to a stream, default Serial.
|
||||
Useful to create an array in RAM, PROGMEM, EEPROM, in a file or wherever.
|
||||
Returns false if no table is allocated.
|
||||
- **void dumpArray(Stream \*str = &Serial)** dumps the internal table to a stream, default Serial, as a C-style array. See example.
|
||||
@ -84,18 +88,25 @@ See example.
|
||||
|
||||
## Future ideas
|
||||
|
||||
#### must
|
||||
#### Must
|
||||
|
||||
- improve documentation
|
||||
|
||||
#### should
|
||||
- test other platforms
|
||||
- look for optimizations
|
||||
- getter \[\]
|
||||
- setGamma -> pow() is expensive
|
||||
#### Should
|
||||
|
||||
- test other platforms
|
||||
|
||||
#### Could
|
||||
|
||||
#### could
|
||||
- uint16 version?
|
||||
- GAMMA16, GAMMA32,
|
||||
- GAMMA16,
|
||||
- GAMMA32,
|
||||
- GAMMA_RGB ?
|
||||
|
||||
#### Wont
|
||||
|
||||
- look for optimizations (done in 0.4.0)
|
||||
- getter \[\]
|
||||
- setGamma -> pow() is expensive
|
||||
- setGamma(gamma) gamma = 1.0 is linear, less math (too specific?)
|
||||
|
||||
|
@ -0,0 +1,62 @@
|
||||
Arduino UNO
|
||||
IDE 1.8.19
|
||||
|
||||
GammaPerformance.ino
|
||||
GAMMA_LIB_VERSION: 0.3.2 (not released)
|
||||
|
||||
timing in microseconds
|
||||
|
||||
SETGAMMA
|
||||
SIZE TIME TIME per element
|
||||
257 85744 333.63
|
||||
129 42692 330.95
|
||||
65 21208 326.28
|
||||
33 10464 317.09
|
||||
17 5096 299.76
|
||||
|
||||
SETGAMMA II
|
||||
SIZE TIME TIME per element
|
||||
257 8 0.03
|
||||
129 8 0.06
|
||||
65 8 0.12
|
||||
33 8 0.24
|
||||
17 8 0.47
|
||||
|
||||
GET[]
|
||||
SIZE TIME TIME per element
|
||||
257 460 1.80
|
||||
129 956 3.73
|
||||
65 1196 4.67
|
||||
33 1412 5.52
|
||||
17 1600 6.25
|
||||
|
||||
======================================
|
||||
|
||||
GAMMA_LIB_VERSION: 0.3.2 (not released)
|
||||
|
||||
timing in microseconds
|
||||
|
||||
SETGAMMA
|
||||
SIZE TIME TIME per element
|
||||
257 9675 37.65
|
||||
129 4835 37.48
|
||||
65 2406 37.02
|
||||
33 1191 36.09
|
||||
17 578 34.00
|
||||
|
||||
SETGAMMA II
|
||||
SIZE TIME TIME per element
|
||||
257 1 0.00
|
||||
129 1 0.01
|
||||
65 1 0.02
|
||||
33 1 0.03
|
||||
17 1 0.06
|
||||
|
||||
GET[]
|
||||
SIZE TIME TIME per element
|
||||
257 44 0.17
|
||||
129 58 0.23
|
||||
65 60 0.23
|
||||
33 61 0.24
|
||||
17 62 0.24
|
||||
|
@ -0,0 +1,66 @@
|
||||
Arduino UNO
|
||||
IDE 1.8.19
|
||||
|
||||
GammaPerformance.ino
|
||||
GAMMA_LIB_VERSION: 0.4.0
|
||||
|
||||
timing in microseconds
|
||||
|
||||
SETGAMMA
|
||||
SIZE TIME TIME per element
|
||||
257 85744 333.63
|
||||
129 42692 330.95
|
||||
65 21208 326.28
|
||||
33 10464 317.09
|
||||
17 5096 299.76
|
||||
|
||||
SETGAMMA II
|
||||
SIZE TIME TIME per element
|
||||
257 8 0.03
|
||||
129 8 0.06
|
||||
65 8 0.12
|
||||
33 8 0.24
|
||||
17 8 0.47
|
||||
|
||||
GET[]
|
||||
SIZE TIME TIME per element
|
||||
257 460 1.80
|
||||
129 904 3.53
|
||||
65 1128 4.41
|
||||
33 1336 5.22
|
||||
17 1544 6.03
|
||||
|
||||
|
||||
======================================
|
||||
|
||||
ESP32
|
||||
|
||||
GAMMA_LIB_VERSION: 0.4.0
|
||||
|
||||
timing in microseconds
|
||||
|
||||
SETGAMMA
|
||||
SIZE TIME TIME per element
|
||||
257 6009 23.38
|
||||
129 2966 22.99
|
||||
65 1457 22.42
|
||||
33 703 21.30
|
||||
17 336 19.76
|
||||
|
||||
SETGAMMA II
|
||||
SIZE TIME TIME per element
|
||||
257 1 0.00
|
||||
129 1 0.01
|
||||
65 1 0.02
|
||||
33 1 0.03
|
||||
17 1 0.06
|
||||
|
||||
GET[]
|
||||
SIZE TIME TIME per element
|
||||
257 44 0.17
|
||||
129 55 0.21
|
||||
65 58 0.23
|
||||
33 59 0.23
|
||||
17 60 0.23
|
||||
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
GAMMA gt1(256);
|
||||
|
||||
// fastGamma is based upon values found with GAMMA(8).setGamma(2.8);
|
||||
// it is however not fast enough...
|
||||
// binary search
|
||||
// fastGamma is based upon values found with GAMMA(8).setGamma(2.8);
|
||||
// it is however not fast enough...
|
||||
// binary search
|
||||
int fastGamma(uint8_t idx)
|
||||
{
|
||||
if (idx < 128)
|
||||
@ -93,4 +93,4 @@ void loop()
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
// -- END OF FILE --
|
||||
|
@ -1,11 +1,9 @@
|
||||
//
|
||||
// FILE: gamma.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.1
|
||||
// VERSION: 0.4.0
|
||||
// DATE: 2020-08-08
|
||||
// PURPOSE: Arduino Library to efficiently hold a gamma lookup table
|
||||
//
|
||||
// HISTORY: see changelog.md
|
||||
|
||||
|
||||
#include "gamma.h"
|
||||
@ -39,7 +37,7 @@ bool GAMMA::begin()
|
||||
{
|
||||
if (_table == NULL)
|
||||
{
|
||||
_table = (uint8_t *)malloc(_size + 1);
|
||||
_table = (uint8_t *) malloc(_size + 1);
|
||||
}
|
||||
if (_table == NULL) return false;
|
||||
setGamma(2.8);
|
||||
@ -53,24 +51,27 @@ bool GAMMA::setGamma(float gamma)
|
||||
if (gamma <= 0) return false;
|
||||
if (_gamma != gamma)
|
||||
{
|
||||
yield(); // try to keep ESP happy
|
||||
yield(); // try to keep ESP happy
|
||||
_gamma = gamma;
|
||||
// marginally faster
|
||||
// uint16_t iv = _interval;
|
||||
// _table[0] = 0;
|
||||
// for (uint16_t i = 1; i < _size; i++)
|
||||
// {
|
||||
// float x = log(i * iv) + log(1.0 / 255);
|
||||
// _table[i] = exp(x * _gamma) * 255 + 0.5;
|
||||
// }
|
||||
// REFERENCE
|
||||
// rounding factor 0.444 optimized with error example.
|
||||
#if defined(ESP32)
|
||||
// confirmed faster for ESP32.
|
||||
float tmp = log(_interval / 255.0);
|
||||
for (uint16_t i = 1; i < _size; i++)
|
||||
{
|
||||
_table[i] = pow(i * _interval * (1.0/ 255.0), _gamma) * 255 + 0.444;
|
||||
float x = log(i) + tmp;
|
||||
_table[i] = exp(x * _gamma) * 255 + 0.444;
|
||||
}
|
||||
#else
|
||||
// REFERENCE
|
||||
// rounding factor 0.444 optimized with error example.
|
||||
float tmp = (_interval / 255.0);
|
||||
for (uint16_t i = 1; i < _size; i++)
|
||||
{
|
||||
_table[i] = pow(i * tmp, _gamma) * 255 + 0.444;
|
||||
}
|
||||
#endif
|
||||
_table[0] = 0;
|
||||
_table[_size] = 255; // anchor for interpolation.
|
||||
_table[_size] = 255; // anchor for interpolation.
|
||||
}
|
||||
return true;
|
||||
};
|
||||
@ -87,17 +88,41 @@ uint8_t GAMMA::operator[] (uint8_t index)
|
||||
// 0.3.0 _table test slows performance ~0.4 us.
|
||||
if (_table == NULL) return 0;
|
||||
if (_interval == 1) return _table[index];
|
||||
// else interpolate
|
||||
uint8_t i = index >> _shift;
|
||||
uint8_t m = index & _mask;
|
||||
// exact element shortcut
|
||||
|
||||
// else interpolate
|
||||
#if defined(ESP32)
|
||||
uint32_t i = index >> _shift;
|
||||
uint32_t m = index & _mask;
|
||||
// exact element shortcut
|
||||
if ( m == 0 ) return _table[i];
|
||||
|
||||
// interpolation
|
||||
// delta must be uint16_t to prevent overflow. (small tables)
|
||||
// delta * m can be > 8 bit.
|
||||
uint32_t delta = _table[i+1] - _table[i];
|
||||
delta = ( delta * m + _interval/2 ) >> _shift; // == /_interval;
|
||||
return _table[i] + delta;
|
||||
|
||||
#else
|
||||
uint16_t i = index >> _shift;
|
||||
uint16_t m = index & _mask;
|
||||
// exact element shortcut
|
||||
if ( m == 0 ) return _table[i];
|
||||
|
||||
// interpolation
|
||||
// delta must be uint16_t to prevent overflow. (small tables)
|
||||
// delta * m can be > 8 bit.
|
||||
uint16_t delta = _table[i+1] - _table[i];
|
||||
delta = (delta * m + _interval/2) >> _shift; // == /_interval;
|
||||
// for AVR UNO this speeds up
|
||||
if (delta != 0)
|
||||
{
|
||||
// delta = ( delta * m + _interval/2 ) >> _shift; // == /_interval;
|
||||
delta += m;
|
||||
delta +=_interval/2;
|
||||
delta >>= _shift; // == /_interval;
|
||||
}
|
||||
return _table[i] + delta;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -139,7 +164,7 @@ bool GAMMA::dumpArray(Stream *str)
|
||||
str->print("uint8_t gamma[");
|
||||
str->print(_size + 1);
|
||||
str->print("] = {");
|
||||
|
||||
|
||||
for (uint16_t i = 0; i <= _size; i++)
|
||||
{
|
||||
if (i % 8 == 0) str->print("\n ");
|
||||
@ -152,7 +177,6 @@ bool GAMMA::dumpArray(Stream *str)
|
||||
|
||||
|
||||
// performance investigation
|
||||
// https://stackoverflow.com/questions/43429238/using-boost-cpp-int-for-functions-like-pow-and-rand
|
||||
inline float GAMMA::fastPow(float a, float b)
|
||||
{
|
||||
// reference
|
||||
@ -160,5 +184,5 @@ inline float GAMMA::fastPow(float a, float b)
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -2,14 +2,14 @@
|
||||
//
|
||||
// FILE: gamma.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// VERSION: 0.3.1
|
||||
// VERSION: 0.4.0
|
||||
// DATE: 2020-08-08
|
||||
// PURPOSE: Arduino Library to efficiently hold a gamma lookup table
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define GAMMA_LIB_VERSION (F("0.3.1"))
|
||||
#define GAMMA_LIB_VERSION (F("0.4.0"))
|
||||
|
||||
#define GAMMA_DEFAULT_SIZE 32
|
||||
#define GAMMA_MAX_SIZE 256
|
||||
@ -57,5 +57,5 @@ private:
|
||||
};
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
// -- END OF FILE --
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/GAMMA.git"
|
||||
},
|
||||
"version": "0.3.1",
|
||||
"version": "0.4.0",
|
||||
"license": "MIT",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=GAMMA
|
||||
version=0.3.1
|
||||
version=0.4.0
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino Library for the GAMMA function
|
||||
|
Loading…
Reference in New Issue
Block a user