GY-63_MS5611/libraries/GAMMA/gamma.cpp

189 lines
3.5 KiB
C++
Raw Normal View History

2022-07-25 09:25:14 -04:00
//
// FILE: gamma.cpp
// AUTHOR: Rob Tillaart
2023-01-26 13:56:10 -05:00
// VERSION: 0.4.0
2022-07-25 09:25:14 -04:00
// DATE: 2020-08-08
// PURPOSE: Arduino Library to efficiently hold a gamma lookup table
#include "gamma.h"
GAMMA::GAMMA(uint16_t size)
{
_shift = 7;
2022-11-08 11:03:54 -05:00
// force power of 2; get shift & mask right
2022-07-25 09:25:14 -04:00
for (uint16_t s = 2; s <= GAMMA_MAX_SIZE; s <<= 1)
{
if (size <= s)
{
_size = s;
break;
}
_shift--;
}
_mask = (1 << _shift) - 1;
_interval = GAMMA_MAX_SIZE / _size;
};
GAMMA::~GAMMA()
{
if (_table) free(_table);
};
2022-07-26 07:16:03 -04:00
bool GAMMA::begin()
2022-07-25 09:25:14 -04:00
{
if (_table == NULL)
{
2023-01-26 13:56:10 -05:00
_table = (uint8_t *) malloc(_size + 1);
2022-07-25 09:25:14 -04:00
}
2022-07-26 07:16:03 -04:00
if (_table == NULL) return false;
2022-07-25 09:25:14 -04:00
setGamma(2.8);
2022-07-26 07:16:03 -04:00
return true;
2022-07-25 09:25:14 -04:00
};
2022-07-26 07:16:03 -04:00
bool GAMMA::setGamma(float gamma)
2022-07-25 09:25:14 -04:00
{
2022-07-26 07:16:03 -04:00
if (_table == NULL) return false;
if (gamma <= 0) return false;
2022-07-25 09:25:14 -04:00
if (_gamma != gamma)
{
2023-01-26 13:56:10 -05:00
yield(); // try to keep ESP happy
2022-07-25 09:25:14 -04:00
_gamma = gamma;
2023-01-26 13:56:10 -05:00
#if defined(ESP32)
// confirmed faster for ESP32.
float tmp = log(_interval / 255.0);
for (uint16_t i = 1; i < _size; i++)
{
float x = log(i) + tmp;
_table[i] = exp(x * _gamma) * 255 + 0.444;
}
#else
2022-07-25 09:25:14 -04:00
// REFERENCE
2022-07-26 07:16:03 -04:00
// rounding factor 0.444 optimized with error example.
2023-01-26 13:56:10 -05:00
float tmp = (_interval / 255.0);
2022-07-26 07:16:03 -04:00
for (uint16_t i = 1; i < _size; i++)
2022-07-25 09:25:14 -04:00
{
2023-01-26 13:56:10 -05:00
_table[i] = pow(i * tmp, _gamma) * 255 + 0.444;
2022-07-25 09:25:14 -04:00
}
2023-01-26 13:56:10 -05:00
#endif
2022-07-26 07:16:03 -04:00
_table[0] = 0;
2023-01-26 13:56:10 -05:00
_table[_size] = 255; // anchor for interpolation.
2022-07-25 09:25:14 -04:00
}
2022-07-26 07:16:03 -04:00
return true;
2022-07-25 09:25:14 -04:00
};
float GAMMA::getGamma()
{
return _gamma;
};
uint8_t GAMMA::operator[] (uint8_t index)
{
2022-07-26 07:16:03 -04:00
// 0.3.0 _table test slows performance ~0.4 us.
if (_table == NULL) return 0;
2022-07-25 09:25:14 -04:00
if (_interval == 1) return _table[index];
2023-01-26 13:56:10 -05:00
// 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
2022-07-25 09:25:14 -04:00
if ( m == 0 ) return _table[i];
2023-01-26 13:56:10 -05:00
2022-07-26 07:16:03 -04:00
// interpolation
// delta must be uint16_t to prevent overflow. (small tables)
// delta * m can be > 8 bit.
2022-07-25 09:25:14 -04:00
uint16_t delta = _table[i+1] - _table[i];
2023-01-26 13:56:10 -05:00
// for AVR UNO this speeds up
if (delta != 0)
{
// delta = ( delta * m + _interval/2 ) >> _shift; // == /_interval;
delta += m;
delta +=_interval/2;
delta >>= _shift; // == /_interval;
}
2022-07-25 09:25:14 -04:00
return _table[i] + delta;
2023-01-26 13:56:10 -05:00
#endif
2022-07-25 09:25:14 -04:00
};
uint16_t GAMMA::size()
{
return _size + 1;
};
uint16_t GAMMA::distinct()
{
uint8_t last = _table[0];
uint16_t count = 1;
for (uint16_t i = 1; i <= _size; i++)
{
if (_table[i] == last) continue;
last = _table[i];
count++;
}
return count;
};
2022-07-26 07:16:03 -04:00
bool GAMMA::dump(Stream *str)
2022-07-25 09:25:14 -04:00
{
2022-07-26 07:16:03 -04:00
if (_table == NULL) return false;
2022-07-25 09:25:14 -04:00
for (uint16_t i = 0; i <= _size; i++)
{
str->println(_table[i]);
}
2022-07-26 07:16:03 -04:00
return true;
2022-07-25 09:25:14 -04:00
};
2022-07-26 07:16:03 -04:00
bool GAMMA::dumpArray(Stream *str)
2022-07-25 09:25:14 -04:00
{
2022-07-26 07:16:03 -04:00
if (_table == NULL) return false;
2022-07-25 09:25:14 -04:00
str->println();
str->print("uint8_t gamma[");
str->print(_size + 1);
str->print("] = {");
2023-01-26 13:56:10 -05:00
2022-07-25 09:25:14 -04:00
for (uint16_t i = 0; i <= _size; i++)
{
if (i % 8 == 0) str->print("\n ");
str->print(_table[i]);
if (i < _size) str->print(", ");
}
str->print("\n };\n\n");
2022-07-26 07:16:03 -04:00
return true;
2022-07-25 09:25:14 -04:00
};
2022-07-26 07:16:03 -04:00
// performance investigation
inline float GAMMA::fastPow(float a, float b)
{
// reference
return pow(a, b);
}
2023-01-26 13:56:10 -05:00
// -- END OF FILE --
2022-07-25 09:25:14 -04:00