0.2.0 GAMMA

This commit is contained in:
rob tillaart 2021-11-02 15:15:11 +01:00
parent ef7e288adf
commit 0832418993
12 changed files with 176 additions and 74 deletions

View File

@ -2,6 +2,10 @@ compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
- leonardo
- due
- zero
# - due
# - zero
# - leonardo
- m4
- esp32
# - esp8266
# - mega2560

View File

@ -4,10 +4,14 @@ name: Arduino CI
on: [push, pull_request]
jobs:
arduino_ci:
runTest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: Arduino-CI/action@master
# Arduino-CI/action@v0.1.1
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- run: |
gem install arduino_ci
arduino_ci.rb

View File

@ -1,12 +1,16 @@
[![Arduino CI](https://github.com/RobTillaart/GAMMA/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/GAMMA/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/GAMMA/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/GAMMA/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/GAMMA/actions/workflows/jsoncheck.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/GAMMA/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/GAMMA.svg?maxAge=3600)](https://github.com/RobTillaart/GAMMA/releases)
# GAMMA
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
@ -23,41 +27,50 @@ 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()** function that allows an application to change
the gamma value runtime. This allows adjustments that a fixed table does not have.
The library has a **setGamma(float gamma)** function that allows an application
to change the gamma value runtime.
This allows adjustments that a fixed table does not have.
The class can be used to dump the internal table e.g. to place in PROGMEM.
Note: tested on UNO and ESP32 only.
## Interface
### Core functions
- **GAMMA(size = 32)** constructor, gets the size of the internal
array as parameter. The array is initialized with a gamma == 2.8 which
is an often used value.
The default for size = 32 as this is a good balance between performance
and size ot the internal array.
The size parameter must be in {2, 4, 8, 16, 32, 64, 128, 256 }
- **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. The size parameter must be in {2, 4, 8, 16, 32, 64, 128, 256 }.
- **begin()** The array is initialized with a gamma == 2.8 which is an often used value.
**begin()** must be called before any other function.
- **setGamma(float gamma)** calculates and fills the array with new values.
This can be done runtime so runtime adjustment of gamma mapping.
This function relative quite some time.
This function takes relative quite some time.
The parameter **gamma** must be > 0. The value 1 gives an 1:1 mapping.
- **getGamma()** returns the set gamma value.
- **operator \[\]** allows the GAMMA object to be accessed as an array.
like ```x = G[40];``` Makes it easy to switch with a real array.
### Development functions
- **size()** returns size of the internal array.
- **distinct()** returns the number of distinct values in the table.
- **distinct()** returns the number of distinct values in the table. Especially with larger internal tables this will happen.
- **dump()** dumps the internal table to Serial. Can be useful to create
a direct usable array in RAM, PROGMEM or wherever.
an array in RAM, PROGMEM or wherever.
## Future ideas
- look for optimizations
- uint16 version?
-
## Operation
See example
## Future ideas
- test other platforms
- improve documentation
- look for optimizations
- uint16 version?
-

View File

@ -1,13 +1,14 @@
//
// FILE: GammaErrorAnalysis.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.2.0
// PURPOSE: demo
// DATE: 2020-08-08
#include "gamma.h"
GAMMA gt1(256);
GAMMA gt2(128);
GAMMA gt3(64);
@ -20,11 +21,21 @@ GAMMA gt8(2);
uint32_t start, d1;
volatile int x;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
gt1.begin();
gt2.begin();
gt3.begin();
gt4.begin();
gt5.begin();
gt6.begin();
gt7.begin();
gt8.begin();
Serial.println("\nError Analysis 256 elements = reference\n");
Serial.println("Size\tErrors\tMaximum");
test_error(gt1);
@ -40,6 +51,7 @@ void setup()
Serial.println("\ndone...\n");
}
void test_error(GAMMA gt)
{
int count = 0;
@ -59,8 +71,11 @@ void test_error(GAMMA gt)
Serial.println(maxdiff);
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,13 +1,14 @@
//
// FILE: gammaPerformance.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.2.0
// PURPOSE: demo
// DATE: 2020-08-08
#include "gamma.h"
GAMMA gt1(256);
GAMMA gt2(128);
GAMMA gt3(64);
@ -17,13 +18,19 @@ GAMMA gt5(16);
uint32_t start, d1;
volatile int x;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.println("\ntiming in microseconds\n");
gt1.begin();
gt2.begin();
gt3.begin();
gt4.begin();
gt5.begin();
Serial.println("\ntiming in microseconds\n");
Serial.println("SETGAMMA");
Serial.println("SIZE\tTIME\tTIME per element");
@ -34,7 +41,6 @@ void setup()
test_setGamma(gt5);
Serial.println();
Serial.println("SETGAMMA II");
Serial.println("SIZE\tTIME\tTIME per element");
test_setGamma(gt1);
@ -44,7 +50,6 @@ void setup()
test_setGamma(gt5);
Serial.println();
Serial.println("GET[]");
Serial.println("SIZE\tTIME\tTIME per element");
test_index(gt1);
@ -54,10 +59,10 @@ void setup()
test_index(gt5);
Serial.println();
Serial.println("\ndone...");
}
void test_setGamma(GAMMA & gt)
{
start = micros();
@ -71,6 +76,7 @@ void test_setGamma(GAMMA & gt)
delay(10);
}
void test_index(GAMMA & gt)
{
start = micros();
@ -92,4 +98,5 @@ void loop()
{
}
// -- END OF FILE --

View File

@ -1,26 +1,39 @@
//
// FILE: gamma_test.ino
// FILE: gammaFast.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.2.0
// PURPOSE: demo
// DATE: 2020-08-08
#include "gamma.h"
GAMMA gt1(256);
// fastGamma is based upon values found with GAMMA(8).setGamma(2.8);
// it is however not that fast...
// it is however not fast enough...
// binary search
int fastGamma(uint8_t idx)
{
if (idx < 32) return map(idx, 0, 31, 0, 1);
if (idx < 64) return map(idx, 32, 63, 1, 5);
if (idx < 96) return map(idx, 64, 31, 5, 17);
if (idx < 128) return map(idx, 96, 127, 17, 37);
if (idx < 160) return map(idx, 128, 159, 37, 69);
if (idx < 192) return map(idx, 160, 191, 69, 115);
if (idx < 128)
{
if (idx < 64)
{
if (idx < 32) return map(idx, 0, 31, 0, 1);
return map(idx, 32, 63, 1, 5);
}
else
{
if (idx < 96) return map(idx, 64, 95, 5, 17);
return map(idx, 96, 127, 17, 37);
}
}
if (idx < 192)
{
if (idx < 160) return map(idx, 128, 159, 37, 69);
return map(idx, 160, 191, 69, 115);
}
if (idx < 224) return map(idx, 192, 223, 115, 177);
return map(idx, 224, 255, 177, 255);
}
@ -30,32 +43,46 @@ void setup()
{
Serial.begin(115200);
gt1.begin();
gt1.setGamma(2.8);
for (int i = 0; i < 256; i++)
Serial.println("\n\ttest fastGamma()");
Serial.println("\ti \tgt1[] \tfast \tdelta");
for (int i = 0; i < 256; i ++ )
{
Serial.print('\t');
Serial.print(i);
Serial.print('\t');
Serial.print(gt1[i]);
Serial.print('\t');
Serial.print(fastGamma(i));
Serial.print(fastGamma(i));
Serial.print('\t');
Serial.print(gt1[i] - fastGamma(i));
Serial.println();
}
volatile int x;
volatile uint32_t x = 0;
uint32_t start = micros();
for (int i = 0; i < 256; i++) x += gt1[i];
uint32_t d1 = micros() - start;
Serial.println();
Serial.print(" 256 x gt1[i] : ");
Serial.println(d1);
Serial.print(" x : ");
Serial.println(x);
delay(10);
x = 0;
start = micros();
for (int i = 0; i < 256; i++) x += fastGamma(i);
d1 = micros() - start;
Serial.print(" 256 x fast : ");
Serial.println(d1);
Serial.print(" x : ");
Serial.println(x);
delay(10);
Serial.println(x);
Serial.println("\ndone...");
}
@ -63,4 +90,5 @@ void loop()
{
}
// -- END OF FILE --

View File

@ -1,23 +1,31 @@
//
// FILE: gamma_test.ino
// FILE: gammaTest.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.2.0
// PURPOSE: demo
// DATE: 2020-08-08
#include "gamma.h"
GAMMA gt1(256);
GAMMA gt2(128);
GAMMA gt3(64);
GAMMA gt4(32); // default
GAMMA gt5(16);
void setup()
{
Serial.begin(115200);
gt1.begin();
gt2.begin();
gt3.begin();
gt4.begin();
gt5.begin();
gt1.setGamma(2.8);
gt2.setGamma(2.8);
gt3.setGamma(2.8);
@ -39,12 +47,15 @@ void setup()
Serial.print(gt5[i]);
Serial.println();
}
Serial.println("\ndone...\n");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -1,25 +1,30 @@
//
// FILE: gamma_test.ino
// FILE: gammaTest2.ino
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// VERSION: 0.2.0
// PURPOSE: demo setGamma
// DATE: 2020-08-08
// Use Arduino Plotter to see the different curves.
#include "gamma.h"
GAMMA gt; // uses default 32 size
void setup()
{
Serial.begin(115200);
Serial.println("hello");
Serial.println("gammaTest2.ino");
gt.begin();
for (int i = 0; i < 256; i++)
{
for (int gam = 1; gam < 10; gam += 1)
for (float gamma = 0.1; gamma < 10; gamma *= 2)
{
gt.setGamma(gam);
gt.setGamma(gamma);
Serial.print(gt[i]);
Serial.print('\t');
}
@ -32,4 +37,6 @@ void loop()
{
}
// -- END OF FILE --

View File

@ -2,23 +2,21 @@
//
// FILE: gamma.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.1
// VERSION: 0.2.0
// DATE: 2020-08-08
// PURPOSE: Arduino Library to efficiently hold a gamma lookup table
// 0.1.0 2020-08-08 initial release
// 0.1.1 2020-12-24 arduino-ci + unit test
// 0.2.0 2021-11-02 update build-CI, badges
// add begin() - fixes ESP32 crash.
#include "Arduino.h"
#define GAMMA_LIB_VERSION (F("0.1.1"))
#define GAMMA_LIB_VERSION (F("0.2.0"))
#if defined(ESP8266) || defined(ESP32)
#include "types.h"
#endif
class GAMMA
{
@ -39,15 +37,26 @@ public:
}
_mask = (1 << _shift) - 1;
_interval = 256 / _size;
_table = (uint8_t *)malloc(_size + 1);
setGamma(2.8);
// removed malloc from constructor for ESP32
}
~GAMMA()
{
if (_table) free(_table);
}
void begin()
{
if (_table == NULL)
{
_table = (uint8_t *)malloc(_size + 1);
}
setGamma(2.8);
}
void setGamma(float gamma)
{
if (_gamma != gamma)
@ -62,11 +71,13 @@ public:
}
}
float getGamma()
{
return _gamma;
};
uint8_t operator[] (uint8_t idx)
{
if (_interval == 1) return _table[idx];
@ -81,11 +92,13 @@ public:
return _table[i] + delta;
}
uint16_t size()
{
return _size + 1;
};
int distinct()
{
int last = _table[0];
@ -99,6 +112,7 @@ public:
return cnt;
}
void dump()
{
for (uint16_t i = 0; i < _size; i++)
@ -114,8 +128,9 @@ private:
uint16_t _size = 0;
uint8_t _interval = 0;
float _gamma = 0;
uint8_t * _table;
uint8_t * _table = NULL;
};
// -- END OF FILE --

View File

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

View File

@ -1,5 +1,5 @@
name=GAMMA
version=0.1.1
version=0.2.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino Library for the GAMMA function

View File

@ -37,61 +37,58 @@ unittest_teardown()
{
}
/*
unittest(test_new_operator)
{
assertEqualINF(exp(800));
assertEqualINF(0.0/0.0);
assertEqualINF(42);
assertEqualNAN(INFINITY - INFINITY);
assertEqualNAN(0.0/0.0);
assertEqualNAN(42);
}
*/
unittest(test_constructor)
{
GAMMA gt0; // uses default 32 size
gt0.begin();
assertEqual(33, gt0.size());
assertEqualFloat(2.8, gt0.getGamma(), 0.0001);
assertEqual(28, gt0.distinct());
GAMMA gt1(256);
gt1.begin();
assertEqual(257, gt1.size());
assertEqualFloat(2.8, gt1.getGamma(), 0.0001);
assertEqual(163, gt1.distinct());
GAMMA gt2(128);
gt2.begin();
assertEqual(129, gt2.size());
assertEqualFloat(2.8, gt2.getGamma(), 0.0001);
assertEqual(97, gt2.distinct());
GAMMA gt3(64);
gt3.begin();
assertEqual(65, gt3.size());
assertEqualFloat(2.8, gt3.getGamma(), 0.0001);
assertEqual(53, gt3.distinct());
GAMMA gt4(32); // default
gt4.begin();
assertEqual(33, gt4.size());
assertEqualFloat(2.8, gt4.getGamma(), 0.0001);
assertEqual(28, gt4.distinct());
GAMMA gt5(16);
gt5.begin();
assertEqual(17, gt5.size());
assertEqualFloat(2.8, gt5.getGamma(), 0.0001);
assertEqual(15, gt5.distinct());
GAMMA gt6(8);
gt6.begin();
assertEqual(9, gt6.size());
assertEqualFloat(2.8, gt6.getGamma(), 0.0001);
assertEqual(8, gt6.distinct());
}
unittest(test_get_set)
{
GAMMA gt; // uses default 32 size
gt.begin();
for (int i = 1; i < 20; i++)
{
gt.setGamma(i * 0.1);
@ -99,6 +96,7 @@ unittest(test_get_set)
}
}
unittest_main()
// --------