0.4.0 GAMMA

This commit is contained in:
rob tillaart 2023-01-26 19:56:10 +01:00
parent 9d0c5e722c
commit 6472ef20d9
13 changed files with 233 additions and 61 deletions

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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?)

View File

@ -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

View File

@ -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

View File

@ -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 --

View 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 --

View 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 --

View 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": "*",

View File

@ -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