Merge pull request #10285 from flywoo/master
[inav.git] / src / test / unit / ledstrip_unittest.cc.txt
blob1dfb5bcd7d4360409457b36045beb0afffe0cf74
1 /*
2  * This file is part of Cleanflight.
3  *
4  * Cleanflight is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Cleanflight is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Cleanflight.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 #include <stdint.h>
18 #include <stdlib.h>
20 #include <limits.h>
22 //#define DEBUG_LEDSTRIP
24 extern "C" {
25     #include "build_config.h"
27     #include "common/color.h"
28     #include "common/axis.h"
29     #include "common/utils.h"
31     #include "sensors/battery.h"
32     #include "config/runtime_config.h"
33     #include "config/config.h"
35     #include "rx/rx.h"
37     #include "io/rc_controls.h"
39     #include "drivers/light_ws2811strip.h"
40     #include "io/ledstrip.h"
43 #include "unittest_macros.h"
44 #include "gtest/gtest.h"
46 extern "C" {
47     extern uint8_t highestYValueForNorth;
48     extern uint8_t lowestYValueForSouth;
49     extern uint8_t highestXValueForWest;
50     extern uint8_t lowestXValueForEast;
51     extern uint8_t ledGridWidth;
52     extern uint8_t ledGridHeight;
53     extern ledCounts_t ledCounts;
55     void updateLedCount(void);
56     void determineLedStripDimensions(void);
57     void determineOrientationLimits(void);
60 // utility macros
61 #define LF(name) LED_FUNCTION_ ## name
62 #define LO(name) LED_FLAG_OVERLAY(LED_OVERLAY_ ## name)
63 #define LD(name) LED_FLAG_DIRECTION(LED_DIRECTION_ ## name)
65 TEST(LedStripTest, parseLedStripConfig)
67     // given
68     static const ledConfig_t expectedLedStripConfig[WS2811_LED_STRIP_LENGTH] = {
69             DEFINE_LED( 9,  9, 0, LD(SOUTH) , LF(FLIGHT_MODE) , LO(WARNING) , 0),
70             DEFINE_LED(10, 10, 0, LD(SOUTH) , LF(FLIGHT_MODE) , LO(WARNING) , 0),
71             DEFINE_LED(11, 11, 0, LD(SOUTH) , LF(ARM_STATE) , LO(INDICATOR) , 0),
72             DEFINE_LED(11, 11, 0, LD(EAST)  , LF(ARM_STATE) , LO(INDICATOR) , 0),
73             DEFINE_LED(10, 10, 0, LD(EAST)  , LF(FLIGHT_MODE) , 0, 0),
75             DEFINE_LED(10,  5, 0, LD(SOUTH) , LF(FLIGHT_MODE) , 0, 0),
76             DEFINE_LED(11,  4, 0, LD(SOUTH) , LF(FLIGHT_MODE) , 0, 0),
77             DEFINE_LED(12,  3, 0, LD(SOUTH) , LF(ARM_STATE) , LO(INDICATOR) , 0),
78             DEFINE_LED(12,  2, 0, LD(NORTH) , LF(ARM_STATE) , LO(INDICATOR) , 0),
79             DEFINE_LED(11,  1, 0, LD(NORTH) , LF(FLIGHT_MODE) , 0, 0),
80             DEFINE_LED(10,  0, 0, LD(NORTH) , LF(FLIGHT_MODE) , 0, 0),
82             DEFINE_LED( 7,  0, 0, LD(NORTH) , LF(FLIGHT_MODE) , LO(WARNING) , 0),
83             DEFINE_LED( 6,  0, 1, LD(NORTH) , LF(COLOR) , LO(WARNING) , 0),
84             DEFINE_LED( 5,  0, 1, LD(NORTH) , LF(COLOR) , LO(WARNING) , 0),
85             DEFINE_LED( 4,  0, 0, LD(NORTH) , LF(FLIGHT_MODE) , LO(WARNING) , 0),
87             DEFINE_LED( 2,  0, 0, LD(NORTH) , LF(FLIGHT_MODE) , 0, 0),
88             DEFINE_LED( 1,  1, 0, LD(NORTH) , LF(FLIGHT_MODE) , 0, 0),
89             DEFINE_LED( 0,  2, 0, LD(NORTH) , LF(ARM_STATE) , LO(INDICATOR) , 0),
90             DEFINE_LED( 0,  3, 0, LD(WEST)  , LF(ARM_STATE) , LO(INDICATOR) , 0),
91             DEFINE_LED( 1,  4, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0, 0),
92             DEFINE_LED( 2,  5, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0, 0),
94             DEFINE_LED( 1, 10, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0, 0),
95             DEFINE_LED( 0, 11, 0, LD(WEST)  , LF(ARM_STATE) , LO(INDICATOR) , 0),
96             DEFINE_LED( 0, 11, 0, LD(SOUTH) , LF(ARM_STATE) , LO(INDICATOR) , 0),
97             DEFINE_LED( 1, 10, 0, LD(SOUTH) , LF(FLIGHT_MODE) , LO(WARNING) , 0),
98             DEFINE_LED( 2,  9, 0, LD(SOUTH) , LF(FLIGHT_MODE) , LO(WARNING) , 0),
100             DEFINE_LED( 7,  7, 14, 0, LF(THRUST_RING) , 0 , 0),
101             DEFINE_LED( 8,  7, 15, 0, LF(THRUST_RING) , 0 , 0),
102             DEFINE_LED( 8,  8, 14, 0, LF(THRUST_RING) , 0 , 0),
103             DEFINE_LED( 7,  8, 15, 0, LF(THRUST_RING) , 0 , 0),
105             DEFINE_LED( 0, 0, 0, 0 , 0 , 0 , 0),
106             DEFINE_LED( 0, 0, 0, 0 , 0 , 0 , 0),
107     };
109     // and
110     const char *ledStripConfigCommands[] = {
111             // Spider quad
113             // right rear cluster
114             "9,9:S:FW:0",
115             "10,10:S:FW:0",
116             "11,11:S:AI:0",
117             "11,11:E:AI:0",
118             "10,10:E:F:0",
120             // right front cluster
121             "10,5:S:F:0",
122             "11,4:S:F:0",
123             "12,3:S:AI:0",
124             "12,2:N:AI:0",
125             "11,1:N:F:0",
126             "10,0:N:F:0",
128             // center front cluster
129             "7,0:N:FW:0",
130             "6,0:N:CW:1",
131             "5,0:N:CW:1",
132             "4,0:N:FW:0",
134             // left front cluster
135             "2,0:N:F:0",
136             "1,1:N:F:0",
137             "0,2:N:AI:0",
138             "0,3:W:AI:0",
139             "1,4:W:F:0",
140             "2,5:W:F:0",
142             // left rear cluster
143             "1,10:W:F:0",
144             "0,11:W:AI:0",
145             "0,11:S:AI:0",
146             "1,10:S:FW:0",
147             "2,9:S:FW:0",
149             // thrust ring
150             "7,7::R:14",
151             "8,7::R:15",
152             "8,8::R:14",
153             "7,8::R:15"
154     };
155     // and
156     memset(ledConfigs_arr(), 0, sizeof(*ledConfigs_arr()));
158     // and
159     bool result = true;
161     // when
162     for (unsigned index = 0; index < ARRAYLEN(ledStripConfigCommands); index++) {
163         result = result && parseLedStripConfig(index, ledStripConfigCommands[index]);
164     }
166     // then
167     EXPECT_EQ(true, result);
168     EXPECT_EQ(30, ledCounts.count);
169     EXPECT_EQ(4, ledCounts.ring);
172     // and
173     for (int index = 0; index < WS2811_LED_STRIP_LENGTH; index++) {
174 #ifdef DEBUG_LEDSTRIP
175         printf("iteration: %d\n", index);
176 #endif
177         EXPECT_EQ(ledGetXY(&expectedLedStripConfig[index]), ledGetXY(ledConfigs(index)));
178         EXPECT_EQ(ledGetFunction(&expectedLedStripConfig[index]), ledGetFunction(ledConfigs(index)));
179         EXPECT_EQ(ledGetOverlay(&expectedLedStripConfig[index]), ledGetOverlay(ledConfigs(index)));
180         EXPECT_EQ(ledGetColor(&expectedLedStripConfig[index]), ledGetColor(ledConfigs(index)));
181         EXPECT_EQ(ledGetDirection(&expectedLedStripConfig[index]), ledGetDirection(ledConfigs(index)));
182         EXPECT_EQ(ledGetParams(&expectedLedStripConfig[index]), ledGetParams(ledConfigs(index)));
183     }
185     // then
186     EXPECT_EQ(13, ledGridWidth);
187     EXPECT_EQ(12, ledGridHeight);
189     // then
190     EXPECT_EQ(5, highestXValueForWest);
191     EXPECT_EQ(7, lowestXValueForEast);
192     EXPECT_EQ(5, highestYValueForNorth);
193     EXPECT_EQ(6, lowestYValueForSouth);
196 TEST(LedStripTest, smallestGridWithCenter)
198     // given
199     memset(ledConfigs_arr(), 0, sizeof(*ledConfigs_arr()));
201     // and
202     static const ledConfig_t testLedConfigs[] = {
203         DEFINE_LED( 2,  2, 0, LD(SOUTH) | LD(EAST) , LF(ARM_STATE)   , LO(INDICATOR), 0),
204         DEFINE_LED( 2,  1, 0, LD(EAST)             , LF(FLIGHT_MODE) , LO(WARNING)  , 0),
205         DEFINE_LED( 2,  0, 0, LD(NORTH) | LD(EAST) , LF(ARM_STATE)   , LO(INDICATOR), 0),
206         DEFINE_LED( 1,  0, 0, LD(NORTH)            , LF(FLIGHT_MODE) , LO(WARNING)  , 0),
207         DEFINE_LED( 0,  0, 0, LD(NORTH) | LD(WEST) , LF(ARM_STATE)   , LO(INDICATOR), 0),
208         DEFINE_LED( 0,  1, 0, LD(WEST)             , LF(FLIGHT_MODE) , LO(WARNING)  , 0),
209         DEFINE_LED( 0,  2, 0, LD(SOUTH) | LD(WEST) , LF(ARM_STATE)   , LO(INDICATOR), 0),
210         DEFINE_LED( 1,  2, 0, LD(SOUTH)            , LF(FLIGHT_MODE) , LO(WARNING)  , 0),
211     };
212     memcpy(ledConfigs_arr(), &testLedConfigs, sizeof(testLedConfigs));
214     // when
215     updateLedCount();
216     determineLedStripDimensions();
218     // then
219     EXPECT_EQ(8, ledCounts.count);
220     EXPECT_EQ(3, ledGridWidth);
221     EXPECT_EQ(3, ledGridHeight);
223     // when
224     determineOrientationLimits();
226     // then
227     EXPECT_EQ(0, highestXValueForWest);
228     EXPECT_EQ(2, lowestXValueForEast);
229     EXPECT_EQ(0, highestYValueForNorth);
230     EXPECT_EQ(2, lowestYValueForSouth);
233 TEST(LedStripTest, smallestGrid)
235     // given
236     memset(ledConfigs_arr(), 0, sizeof(*ledConfigs_arr()));
238     // and
239     static const ledConfig_t testLedConfigs[] = {
240         DEFINE_LED( 1,  1, 0, LD(SOUTH) | LD(EAST) , LF(FLIGHT_MODE) , LO(INDICATOR), 0),
241         DEFINE_LED( 1,  0, 0, LD(NORTH) | LD(EAST) , LF(FLIGHT_MODE) , LO(INDICATOR), 0),
242         DEFINE_LED( 0,  0, 0, LD(NORTH) | LD(WEST) , LF(FLIGHT_MODE) , LO(INDICATOR), 0),
243         DEFINE_LED( 0,  1, 0, LD(SOUTH) | LD(WEST) , LF(FLIGHT_MODE) , LO(INDICATOR), 0),
244     };
245     memcpy(ledConfigs_arr(), &testLedConfigs, sizeof(testLedConfigs));
247     // when
248     updateLedCount();
249     determineLedStripDimensions();
251     // then
252     EXPECT_EQ(4, ledCounts.count);
253     EXPECT_EQ(2, ledGridWidth);
254     EXPECT_EQ(2, ledGridHeight);
256     // when
257     determineOrientationLimits();
259     // then
260     EXPECT_EQ(0, highestXValueForWest);
261     EXPECT_EQ(1, lowestXValueForEast);
262     EXPECT_EQ(0, highestYValueForNorth);
263     EXPECT_EQ(1, lowestYValueForSouth);
267         LED( 1, 14, 0, LD(SOUTH) , LF(FLIGHT_MODE) , LO(INDICATOR) , 0 ),
269         LED( 0, 13, 0, LD(WEST)  , LF(ARM_STATE) , LO(INDICATOR)  , 0 ),
270         LED( 0, 12, 0, LD(WEST)  , LF(ARM_STATE) , LO(INDICATOR)  , 0 ),
272         LED( 0, 11, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0 , 0 ),
273         LED( 0, 10, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0 , 0 ),
274         LED( 0,  9, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0 , 0 ),
275         LED( 0,  8, 0, LD(WEST)  , LF(FLIGHT_MODE) , LO(WARNING) , 0 ),
276         LED( 0,  7, 0, LD(WEST)  , LF(FLIGHT_MODE) , LO(WARNING) , 0 ),
277         LED( 0,  6, 0, LD(WEST)  , LF(FLIGHT_MODE) , LO(WARNING) , 0 ),
278         LED( 0,  5, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0 , 0 ),
279         LED( 0,  4, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0 , 0 ),
280         LED( 0,  3, 0, LD(WEST)  , LF(FLIGHT_MODE) , 0 , 0 ),
282         LED( 0,  2, 0, LD(WEST)  , LF(ARM_STATE) , LO(INDICATOR)  , 0 ),
283         LED( 0,  1, 0, LD(WEST)  , LF(ARM_STATE) , LO(INDICATOR)  , 0 ),
285         LED( 1,  0, 0, LD(NORTH) , LF(FLIGHT_MODE) , LO(INDICATOR)  , 0 ),
286         LED( 2,  0, 0, LD(NORTH) , LF(FLIGHT_MODE) , 0 , 0 ),
287         LED( 3,  0, 0, LD(NORTH) , LF(FLIGHT_MODE) , LO(INDICATOR) , 0 ),
289         LED( 4,  1, 0, LD(EAST)  , LF(ARM_STATE) , LO(INDICATOR)  , 0 ),
290         LED( 4,  2, 0, LD(EAST)  , LF(ARM_STATE) , LO(INDICATOR)  , 0 ),
292         LED( 4,  3, 0, LD(EAST)  , LF(FLIGHT_MODE) , 0 , 0 ),
293         LED( 4,  4, 0, LD(EAST)  , LF(FLIGHT_MODE) , 0 , 0 ),
294         LED( 4,  5, 0, LD(EAST)  , LF(FLIGHT_MODE) , 0 , 0 ),
295         LED( 4,  6, 0, LD(EAST)  , LF(FLIGHT_MODE) , LO(WARNING) , 0 ),
296         LED( 4,  7, 0, LD(EAST)  , LF(FLIGHT_MODE) , LO(WARNING) , 0 ),
297         LED( 4,  8, 0, LD(EAST)  , LF(FLIGHT_MODE) , LO(WARNING) , 0 ),
298         LED( 4,  9, 0, LD(EAST)  , LF(FLIGHT_MODE) , 0 , 0 ),
299         LED( 4, 10, 0, LD(EAST)  , LF(FLIGHT_MODE) , 0 , 0 ),
300         LED( 4, 11, 0, LD(EAST)  , LF(FLIGHT_MODE) , 0 , 0 ),
302         LED( 4, 12, 0, LD(EAST)  , LF(ARM_STATE) , LO(INDICATOR)  , 0 ),
303         LED( 4, 13, 0, LD(EAST)  , LF(ARM_STATE) , LO(INDICATOR)  , 0 ),
305         LED( 3, 14, 0, LD(SOUTH) , LF(FLIGHT_MODE) , LO(INDICATOR) , 0 ),
307  */
309 hsvColor_t testColors[LED_CONFIGURABLE_COLOR_COUNT];
311 #define TEST_COLOR_COUNT 4
313 TEST(ColorTest, parseColor)
315     // given
316     memset(colors_arr(), 0, sizeof(*colors_arr()));
318     // and
319     const hsvColor_t expectedColors[TEST_COLOR_COUNT] = {
320             //  H    S    V
321             {   0,   0,   0 },
322             {   1,   1,   1 },
323             { 359, 255, 255 },
324             { 333,  22,   1 }
325     };
327     const char *testColors[TEST_COLOR_COUNT] = {
328             "0,0,0",
329             "1,1,1",
330             "359,255,255",
331             "333,22,1"
332     };
334     // when
335     for (int index = 0; index < TEST_COLOR_COUNT; index++) {
336 #ifdef DEBUG_LEDSTRIP
337         printf("parse iteration: %d\n", index);
338 #endif
340         parseColor(index, testColors[index]);
341     }
343     // then
345     for (int index = 0; index < TEST_COLOR_COUNT; index++) {
346 #ifdef DEBUG_LEDSTRIP
347         printf("iteration: %d\n", index);
348 #endif
350         EXPECT_EQ(expectedColors[index].h, colors(index)->h);
351         EXPECT_EQ(expectedColors[index].s, colors(index)->s);
352         EXPECT_EQ(expectedColors[index].v, colors(index)->v);
353     }
356 extern "C" {
358 uint8_t armingFlags = 0;
359 uint16_t flightModeFlags = 0;
360 int16_t rcCommand[4];
361 int16_t rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT];
362 uint32_t rcModeActivationMask;
364 batteryState_e getBatteryState(void) {
365     return BATTERY_OK;
368 void ws2811LedStripInit(void) {}
369 void ws2811UpdateStrip(void) {}
371 void setLedValue(int index, const uint8_t value) {
372     UNUSED(index);
373     UNUSED(value);
376 void setLedHsv(int index, const hsvColor_t *color) {
377     UNUSED(index);
378     UNUSED(color);
381 void getLedHsv(int index, hsvColor_t *color) {
382     UNUSED(index);
383     UNUSED(color);
387 void scaleLedValue(int index, const uint8_t scalePercent) {
388     UNUSED(index);
389     UNUSED(scalePercent);
392 void setStripColor(const hsvColor_t *color) {
393     UNUSED(color);
396 void setStripColors(const hsvColor_t *colors) {
397     UNUSED(colors);
400 bool isWS2811LedStripReady(void) { return false; }
402 void delay(uint32_t ms)
404     UNUSED(ms);
405     return;
408 uint32_t micros(void) { return 0; }
409 bool shouldSoundBatteryAlarm(void) { return false; }
410 bool feature(uint32_t mask) {
411     UNUSED(mask);
412     return false;
415 void tfp_sprintf(char *, char*, ...) { }
417 int scaleRange(int x, int srcMin, int srcMax, int destMin, int destMax) {
418     UNUSED(x);
419     UNUSED(srcMin);
420     UNUSED(srcMax);
421     UNUSED(destMin);
422     UNUSED(destMax);
424     return 0;
427 bool rcModeIsActive(boxId_e modeId) { return rcModeActivationMask & (1 << modeId); }
428 bool failsafeIsActive() { return false; }
429 bool rxIsReceivingSignal() { return true; }
430 bool sensors(uint32_t mask) { UNUSED(mask); return true; }
431 uint8_t calculateBatteryCapacityRemainingPercentage(void) { return 40; }
433 uint8_t GPS_numSat;
434 uint8_t stateFlags;
435 uint16_t rssi;