Bonjour,
dans le cadre d'une librairie servant à piloter des LED par une arduino, j'ai réalisé une nouvelle fonctionnalité qui a comme objectif de corriger les couleurs demandées aux LED pour qu'elles émettent les bonnes couleurs.
Par exemple, quand je demande du blanc (255,255,255) je dois transformer la couleur demandée pour envoyer 255,182,81 aux leds à la place.

La fonctionnalité à l'air de fonctionner mais elle est beaucoup trop lente (d'un facteur 20) pour être utilisable. En effet, la lenteur du calcul va provoquer des scintillements chez les LEDs.
Comme je n'ai plus programmé en C depuis 10 ans, je sollicite votre aide pour savoir si mon objectif en terme de vitesse est atteignable sur une arduino ou sur un PC courant.

Le code fait une centaine de ligne est consultable sur github.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
 
struct LUTCoord {
	union {
		struct {
			uint8_t redIndex;
			uint8_t greenIndex;
			uint8_t blueIndex;
		};
		uint8_t raw[3];
	};
 
	inline LUTCoord() __attribute__((always_inline))
    {
    }
 
    inline LUTCoord( uint8_t ir, uint8_t ig, uint8_t ib)  __attribute__((always_inline))
        : redIndex(ir), greenIndex(ig), blueIndex(ib)
    {
    }
};
 
/// 8 vertices of a cube
struct LUTSubcube {
	CRGB n000;
	CRGB n001;
	CRGB n010;
	CRGB n011;
	CRGB n100;
	CRGB n101;
	CRGB n110;
	CRGB n111;
};
 
/// This 3D LUT can be used provided that the space between entries is the same for all dimensions.
class Array3DLUT {
public:
	CRGB *entries;
	uint8_t size;
	float step;
	uint8_t maxSubcubeIndex;
 
	Array3DLUT(CRGB *entries, uint8_t size);
	virtual ~Array3DLUT();
 
	/// Retrieve an entry in the table.
	/// @param indexes - 3D index of entry
	/// @returns Entry value
	CRGB lookup(LUTCoord indexes);
 
	/// Returns the values of the 8 vertices of the target sub-cube.
	/// The given coordinates must be those of the lowest point.
	/// @param subcubeOriginCoord - lowest point coordinates of the desired subcube
	/// @returns Each (8) subcube values
	struct LUTSubcube lookup_subcube(LUTCoord subcubeOriginCoord);
 
	/// Similar to lookup but instead of a coordinate in the LUT,
	/// we pass a point and the result will be interpolated.
	/// @param input - RGB coordinates of a point in the LUT
	/// @returns Interpolated value in the LUT
	struct CRGB lookup3DTetrahedral(CRGB &input);
};
 
Array3DLUT::Array3DLUT(CRGB *entries, uint8_t size) {
	this->entries = entries;
	this->size = size;
	this->step = 255. / (size - 1);
	this->maxSubcubeIndex = size - 2;
}
 
Array3DLUT::~Array3DLUT() {
	// TODO Auto-generated destructor stub
}
 
CRGB Array3DLUT::lookup(LUTCoord indexes) {
	uint8_t offset =
			  (indexes.redIndex * this->size * this->size)
			+ (indexes.greenIndex * this->size)
			+ indexes.blueIndex;
	return this->entries[offset];
}
 
 
struct LUTSubcube Array3DLUT::lookup_subcube(LUTCoord subcubeOriginCoord) {
	struct LUTSubcube result;
 
	result.n000 = this->lookup(subcubeOriginCoord);
	result.n001 = this->lookup(LUTCoord(subcubeOriginCoord.redIndex, subcubeOriginCoord.greenIndex, subcubeOriginCoord.blueIndex+1));
	result.n010 = this->lookup(LUTCoord(subcubeOriginCoord.redIndex, subcubeOriginCoord.greenIndex+1, subcubeOriginCoord.blueIndex));
	result.n011 = this->lookup(LUTCoord(subcubeOriginCoord.redIndex, subcubeOriginCoord.greenIndex+1, subcubeOriginCoord.blueIndex+1));
	result.n100 = this->lookup(LUTCoord(subcubeOriginCoord.redIndex+1, subcubeOriginCoord.greenIndex, subcubeOriginCoord.blueIndex));
	result.n101 = this->lookup(LUTCoord(subcubeOriginCoord.redIndex+1, subcubeOriginCoord.greenIndex, subcubeOriginCoord.blueIndex+1));
	result.n110 = this->lookup(LUTCoord(subcubeOriginCoord.redIndex+1, subcubeOriginCoord.greenIndex+1, subcubeOriginCoord.blueIndex));
	result.n111 = this->lookup(LUTCoord(subcubeOriginCoord.redIndex+1, subcubeOriginCoord.greenIndex+1, subcubeOriginCoord.blueIndex+1));
 
	return result;
}
 
// Ref implem: https://github.com/ampas/CLF/blob/master/python/aces/clf/Array.py
struct CRGB Array3DLUT::lookup3DTetrahedral(CRGB &input) {
	LUTCoord subcubeOrigin; // Store the subcube's origin coordinates
	float dimensionalDistances[3]; // Distance for each dimensions
 
	for (int i = 0; i < 3; i++) { // for each rgb channel
		dimensionalDistances[i] = input.raw[i] / this->step; // Not yet valid. We should remove int part
		subcubeOrigin.raw[i] = uint8_t(dimensionalDistances[i]); // we put a guessed coordinate
		if (subcubeOrigin.raw[i] > maxSubcubeIndex) {
			// But, if we are on an upper border then we must take the
			// inner border or the subcube will not exist.
			subcubeOrigin.raw[i] = maxSubcubeIndex;
		}
 
		dimensionalDistances[i] -= subcubeOrigin.raw[i]; // Remove the int part
	}
 
	// Rebind for consistency with Truelight paper
	#define fx dimensionalDistances[0]
	#define fy dimensionalDistances[1]
	#define fz dimensionalDistances[2]
 
	struct CRGB result;
	struct LUTSubcube cube = this->lookup_subcube(subcubeOrigin);
	if (fx > fy) {
		if (fy > fz) {
			for (int i=0; i < 3; i++) {
				result.raw[i] = (
						(1-fx)  * cube.n000.raw[i] +
						(fx-fy) * cube.n100.raw[i] +
						(fy-fz) * cube.n110.raw[i] +
						(fz)    * cube.n111.raw[i] );
			}
		} else {
			if (fx > fz) {
				for (int i=0; i < 3; i++) {
					result.raw[i] = (
							(1-fx)  * cube.n000.raw[i] +
							(fx-fz) * cube.n100.raw[i] +
							(fz-fy) * cube.n101.raw[i] +
							(fy)    * cube.n111.raw[i] );
				}
			} else {
				for (int i=0; i < 3; i++) {
					result.raw[i] = (
							(1-fz)  * cube.n000.raw[i] +
							(fz-fx) * cube.n001.raw[i] +
							(fx-fy) * cube.n101.raw[i] +
							(fy)    * cube.n111.raw[i] );
				}
			}
		}
	} else {
		if (fz > fy) {
			for (int i=0; i < 3; i++) {
				result.raw[i] = (
						(1-fz)  * cube.n000.raw[i] +
						(fz-fy) * cube.n001.raw[i] +
						(fy-fx) * cube.n011.raw[i] +
						(fx)    * cube.n111.raw[i] );
			}
		} else {
			if (fz > fx) {
				for (int i=0; i < 3; i++) {
					result.raw[i] = (
							(1-fy)  * cube.n000.raw[i] +
							(fy-fz) * cube.n010.raw[i] +
							(fz-fx) * cube.n011.raw[i] +
							(fx)    * cube.n111.raw[i] );
				}
			} else {
				for (int i=0; i < 3; i++) {
					result.raw[i] = (
							(1-fy)  * cube.n000.raw[i] +
							(fy-fx) * cube.n010.raw[i] +
							(fx-fz) * cube.n011.raw[i] +
							(fz)    * cube.n111.raw[i] );
				}
			}
		}
	}
 
	return result;
}
(si c'est codé comme un cochon, n'hésitez à le faire savoir ^^ )

Edit 1: Ajout des sources dans le post