GY-63_MS5611/libraries/map2colour/map2colour.cpp

247 lines
5.3 KiB
C++
Raw Normal View History

2021-12-04 15:32:57 -05:00
//
// FILE: map2colour.cpp
// AUTHOR: Rob Tillaart
2023-04-26 03:26:03 -04:00
// VERSION: 0.2.0
2021-12-04 15:32:57 -05:00
// PURPOSE: Arduino library for mapping a float to colour spectrum
// URL: https://github.com/RobTillaart/map2colour
#include "map2colour.h"
2023-04-26 03:26:03 -04:00
#define M2C_MIN_SIZE 7
2021-12-04 15:32:57 -05:00
2023-04-26 03:26:03 -04:00
map2colour::map2colour(uint8_t size)
2021-12-04 15:32:57 -05:00
{
2023-04-26 03:26:03 -04:00
_size = size;
if (_size < M2C_MIN_SIZE) _size = M2C_MIN_SIZE;
_Red = (uint8_t *)malloc(_size);
_Green = (uint8_t *)malloc(_size);
_Blue = (uint8_t *)malloc(_size);
// for backwards compatibility
uint8_t r[7] = { 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF };
uint8_t g[7] = { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF };
uint8_t b[7] = { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF };
memcpy(_Red, r, 7);
memcpy(_Green, g, 7);
memcpy(_Blue, b, 7);
}
map2colour::~map2colour()
{
if (_Red) free(_Red);
if (_Green) free(_Green);
if (_Blue) free(_Blue);
2021-12-04 15:32:57 -05:00
}
2021-12-09 09:05:02 -05:00
bool map2colour::begin(float * values, uint32_t * colourMap)
2021-12-04 15:32:57 -05:00
{
2023-04-26 03:26:03 -04:00
if ((_Red == NULL) || (_Green == NULL) || (_Blue == NULL))
{
// need error codes?
return false;
}
2023-02-21 11:01:58 -05:00
// split colour map in channels to allow interpolation per channel
2021-12-09 09:05:02 -05:00
if (colourMap != NULL)
{
2023-04-26 03:26:03 -04:00
for (int i = 0; i < _size; i++)
2021-12-09 09:05:02 -05:00
{
uint32_t val = colourMap[i];
_Blue[i] = val & 0xFF;
val >>= 8;
_Green[i] = val & 0xFF;
val >>= 8;
_Red[i] = val & 0xFF;
}
}
2021-12-04 15:32:57 -05:00
_values = values;
2023-04-26 03:26:03 -04:00
for (int index = 1; index < _size; index++)
2021-12-09 09:05:02 -05:00
{
float den = _values[index] - _values[index - 1];
2023-04-26 03:26:03 -04:00
if (den < 0.0) return false;
2021-12-09 09:05:02 -05:00
}
2021-12-04 15:32:57 -05:00
return true;
}
2023-04-26 03:26:03 -04:00
uint8_t map2colour::size()
{
return _size;
}
2021-12-04 15:32:57 -05:00
uint32_t map2colour::map2RGB(float value)
{
2023-02-21 11:01:58 -05:00
uint8_t index = 1;
2021-12-09 09:05:02 -05:00
// default values + out of lower range
uint8_t R = _Red[0];
uint8_t G = _Green[0];
uint8_t B = _Blue[0];
2022-10-20 05:58:00 -04:00
if (_values[0] < value)
2021-12-09 09:05:02 -05:00
{
2023-04-26 03:26:03 -04:00
if (value < _values[_size-1] )
2021-12-09 09:05:02 -05:00
{
// search the interval
while (_values[index] < value) index++;
// base value
R = _Red[index];
G = _Green[index];
B = _Blue[index];
2023-02-21 11:01:58 -05:00
2021-12-09 09:05:02 -05:00
// calculate the interpolation factor
2022-10-20 05:58:00 -04:00
// map2colourFast uses pre calculated dividers (costs 24 bytes extra RAM).
2021-12-09 09:05:02 -05:00
float factor = (_values[index] - value) / (_values[index] - _values[index - 1]);
2022-10-20 05:58:00 -04:00
// interpolate only if delta != 0
2021-12-09 09:05:02 -05:00
int delta = _Red[index] - _Red[index - 1];
if (delta != 0 ) R -= factor * delta;
delta = _Green[index] - _Green[index - 1];
if (delta != 0 ) G -= factor * delta;
delta = _Blue[index] - _Blue[index - 1];
if (delta != 0 ) B -= factor * delta;
}
else
{
// out of upper range
2023-04-26 03:26:03 -04:00
R = _Red[_size-1];
G = _Green[_size-1];
B = _Blue[_size-1];
2021-12-09 09:05:02 -05:00
}
}
uint32_t colour = R;
colour <<= 8;
colour |= G;
colour <<= 8;
colour |= B;
return colour;
}
uint16_t map2colour::map2_565(float value)
{
uint32_t RGB = map2RGB(value);
uint16_t colour = 0x0000;
RGB >>= 3;
2023-02-21 11:01:58 -05:00
colour |= (RGB & 0x001F); // B channel 5 bits
2021-12-09 09:05:02 -05:00
RGB >>= 2;
2023-02-21 11:01:58 -05:00
colour |= (RGB & 0x07E0); // G channel 6 bits
2021-12-09 09:05:02 -05:00
RGB >>= 3;
2023-02-21 11:01:58 -05:00
colour |= (RGB & 0xF800); // R channel 5 bits
2021-12-09 09:05:02 -05:00
return colour;
}
/////////////////////////////////////////////////////////////////////////
//
2023-02-21 11:01:58 -05:00
// DERIVED CLASS
2021-12-09 09:05:02 -05:00
//
2023-04-26 03:26:03 -04:00
map2colourFast::map2colourFast(uint8_t size) : map2colour(size)
2021-12-09 09:05:02 -05:00
{
2023-04-26 03:26:03 -04:00
divFactor = (float *) malloc(size * sizeof(float));
2021-12-09 09:05:02 -05:00
}
2023-04-26 03:26:03 -04:00
map2colourFast::~map2colourFast()
{
if (divFactor) free(divFactor);
}
2021-12-09 09:05:02 -05:00
bool map2colourFast::begin(float * values, uint32_t * colourMap)
{
2022-10-20 05:58:00 -04:00
// load the colour-map and check non-decreasing order.
bool OK = map2colour::begin(values, colourMap);
// pre-calculate dividers
2023-04-26 03:26:03 -04:00
for (int index = 1; index < _size; index++)
2021-12-09 09:05:02 -05:00
{
2022-10-20 05:58:00 -04:00
float divider = _values[index] - _values[index - 1];
if (divider > 0)
{
divFactor[index - 1] = 1.0 / divider;
}
else
{
divFactor[index - 1] = 0;
}
2021-12-09 09:05:02 -05:00
}
2022-10-20 05:58:00 -04:00
return OK;
2021-12-09 09:05:02 -05:00
}
uint32_t map2colourFast::map2RGB(float value)
{
int index = 1;
// default values + out of lower range
2021-12-04 15:32:57 -05:00
uint8_t R = _Red[0];
uint8_t G = _Green[0];
uint8_t B = _Blue[0];
2022-10-20 05:58:00 -04:00
if (_values[0] < value)
2021-12-04 15:32:57 -05:00
{
2023-04-26 03:26:03 -04:00
if (value < _values[_size-1] )
2021-12-09 09:05:02 -05:00
{
// search the interval
while (_values[index] < value) index++;
// base value
R = _Red[index];
G = _Green[index];
B = _Blue[index];
// calculate the interpolation factor
float factor = (_values[index] - value) * divFactor[index - 1];
// interpolate if delta <> 0
int delta = _Red[index] - _Red[index - 1];
if (delta != 0 ) R -= factor * delta;
delta = _Green[index] - _Green[index - 1];
if (delta != 0 ) G -= factor * delta;
delta = _Blue[index] - _Blue[index - 1];
if (delta != 0 ) B -= factor * delta;
}
else
{
2023-02-21 11:01:58 -05:00
// out of upper range
2023-04-26 03:26:03 -04:00
R = _Red[_size-1];
G = _Green[_size-1];
B = _Blue[_size-1];
2021-12-09 09:05:02 -05:00
}
2021-12-04 15:32:57 -05:00
}
uint32_t colour = R;
colour <<= 8;
colour |= G;
colour <<= 8;
colour |= B;
return colour;
}
2023-02-21 11:01:58 -05:00
// could be slightly faster (~0.4 us) for AVR by
// - split of R = RGB >> 16 (one third could be 16 bit math.
2021-12-09 09:05:02 -05:00
uint16_t map2colourFast::map2_565(float value)
{
uint32_t RGB = map2RGB(value);
uint16_t colour = 0x0000;
RGB >>= 3;
2023-02-21 11:01:58 -05:00
colour |= (RGB & 0x001F); // B channel 5 bits
2021-12-09 09:05:02 -05:00
RGB >>= 2;
2023-02-21 11:01:58 -05:00
colour |= (RGB & 0x07E0); // G channel 6 bits
2021-12-09 09:05:02 -05:00
RGB >>= 3;
2023-02-21 11:01:58 -05:00
colour |= (RGB & 0xF800); // R channel 5 bits
2021-12-09 09:05:02 -05:00
return colour;
}
2023-02-21 11:01:58 -05:00
// -- END OF FILE --
2021-12-04 15:32:57 -05:00