Merge pull request #11190 from mathiasvr/pr-arraylen
[betaflight.git] / src / test / unit / ledstrip_unittest.cc
blob4cd6db9fa460a29b8721b8c0752786dab22fad7f
1 /*
2 * This file is part of Cleanflight.
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.
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.
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/>.
17 #include <stdint.h>
18 #include <stdlib.h>
20 #include <limits.h>
22 //#define DEBUG_LEDSTRIP
24 extern "C" {
25 #include "platform.h"
26 #include "build/build_config.h"
28 #include "common/axis.h"
29 #include "common/color.h"
30 #include "common/utils.h"
32 #include "pg/pg.h"
33 #include "pg/pg_ids.h"
34 #include "pg/rx.h"
36 #include "drivers/io.h"
37 #include "drivers/light_ws2811strip.h"
38 #include "drivers/timer.h"
39 #include "drivers/timer_def.h"
41 #include "config/config.h"
42 #include "fc/rc_controls.h"
43 #include "fc/rc_modes.h"
44 #include "fc/runtime_config.h"
46 #include "io/gps.h"
47 #include "io/ledstrip.h"
49 #include "rx/rx.h"
51 #include "sensors/battery.h"
53 #include "target.h"
56 #include "unittest_macros.h"
57 #include "gtest/gtest.h"
59 extern "C" {
60 extern uint8_t highestYValueForNorth;
61 extern uint8_t lowestYValueForSouth;
62 extern uint8_t highestXValueForWest;
63 extern uint8_t lowestXValueForEast;
65 extern uint8_t ledGridRows;
67 extern ledCounts_t ledCounts;
69 void reevaluateLedConfig();
71 PG_REGISTER(batteryConfig_t, batteryConfig, PG_BATTERY_CONFIG, 0);
74 TEST(LedStripTest, parseLedStripConfig)
76 // given
77 memset(&ledStripStatusModeConfigMutable()->ledConfigs, 0, LED_MAX_STRIP_LENGTH);
79 // and
80 static const ledConfig_t expectedLedStripConfig[WS2811_LED_STRIP_LENGTH] = {
81 DEFINE_LED(9, 9, 0, LD(SOUTH), LF(FLIGHT_MODE), LO(WARNING), 0),
82 DEFINE_LED(10, 10, 0, LD(SOUTH), LF(FLIGHT_MODE), LO(WARNING), 0),
83 DEFINE_LED(11, 11, 0, LD(SOUTH), LF(ARM_STATE), LO(INDICATOR), 0),
84 DEFINE_LED(11, 11, 0, LD(EAST), LF(ARM_STATE), LO(INDICATOR), 0),
85 DEFINE_LED(10, 10, 0, LD(EAST), LF(FLIGHT_MODE), 0, 0),
87 DEFINE_LED(10, 5, 0, LD(SOUTH), LF(FLIGHT_MODE), 0, 0),
88 DEFINE_LED(11, 4, 0, LD(SOUTH), LF(FLIGHT_MODE), 0, 0),
89 DEFINE_LED(12, 3, 0, LD(SOUTH), LF(ARM_STATE), LO(INDICATOR), 0),
90 DEFINE_LED(12, 2, 0, LD(NORTH), LF(ARM_STATE), LO(INDICATOR), 0),
91 DEFINE_LED(11, 1, 0, LD(NORTH), LF(FLIGHT_MODE), 0, 0),
92 DEFINE_LED(10, 0, 0, LD(NORTH), LF(FLIGHT_MODE), 0, 0),
94 DEFINE_LED(7, 0, 0, LD(NORTH), LF(FLIGHT_MODE), LO(WARNING), 0),
95 DEFINE_LED(6, 0, 1, LD(NORTH), LF(COLOR), LO(WARNING), 0),
96 DEFINE_LED(5, 0, 1, LD(NORTH), LF(COLOR), LO(WARNING), 0),
97 DEFINE_LED(4, 0, 0, LD(NORTH), LF(FLIGHT_MODE), LO(WARNING), 0),
99 DEFINE_LED(2, 0, 0, LD(NORTH), LF(FLIGHT_MODE), 0, 0),
100 DEFINE_LED(1, 1, 0, LD(NORTH), LF(FLIGHT_MODE), 0, 0),
101 DEFINE_LED(0, 2, 0, LD(NORTH), LF(ARM_STATE), LO(INDICATOR), 0),
102 DEFINE_LED(0, 3, 0, LD(WEST), LF(ARM_STATE), LO(INDICATOR), 0),
103 DEFINE_LED(1, 4, 0, LD(WEST), LF(FLIGHT_MODE), 0, 0),
104 DEFINE_LED(2, 5, 0, LD(WEST), LF(FLIGHT_MODE), 0, 0),
106 DEFINE_LED(1, 10, 0, LD(WEST), LF(FLIGHT_MODE), 0, 0),
107 DEFINE_LED(0, 11, 0, LD(WEST), LF(ARM_STATE), LO(INDICATOR), 0),
108 DEFINE_LED(0, 11, 0, LD(SOUTH), LF(ARM_STATE), LO(INDICATOR), 0),
109 DEFINE_LED(1, 10, 0, LD(SOUTH), LF(FLIGHT_MODE), LO(WARNING), 0),
110 DEFINE_LED(2, 9, 0, LD(SOUTH), LF(FLIGHT_MODE), LO(WARNING), 0),
112 DEFINE_LED(7, 7, 14, 0, LF(THRUST_RING), 0, 0),
113 DEFINE_LED(8, 7, 15, 0, LF(THRUST_RING), 0, 0),
114 DEFINE_LED(8, 8, 14, 0, LF(THRUST_RING), 0, 0),
115 DEFINE_LED(7, 8, 15, 0, LF(THRUST_RING), 0, 0),
121 // and
122 const char *ledStripConfigCommands[] = {
123 // Spider quad
125 // right rear cluster
126 "9,9:S:FW:0",
127 "10,10:S:FW:0",
128 "11,11:S:IA:0",
129 "11,11:E:IA:0",
130 "10,10:E:F:0",
132 // right front cluster
133 "10,5:S:F:0",
134 "11,4:S:F:0",
135 "12,3:S:IA:0",
136 "12,2:N:IA:0",
137 "11,1:N:F:0",
138 "10,0:N:F:0",
140 // center front cluster
141 "7,0:N:FW:0",
142 "6,0:N:CW:1",
143 "5,0:N:CW:1",
144 "4,0:N:FW:0",
146 // left front cluster
147 "2,0:N:F:0",
148 "1,1:N:F:0",
149 "0,2:N:IA:0",
150 "0,3:W:IA:0",
151 "1,4:W:F:0",
152 "2,5:W:F:0",
154 // left rear cluster
155 "1,10:W:F:0",
156 "0,11:W:IA:0",
157 "0,11:S:IA:0",
158 "1,10:S:FW:0",
159 "2,9:S:FW:0",
161 // thrust ring
162 "7,7::R:14",
163 "8,7::R:15",
164 "8,8::R:14",
165 "7,8::R:15"
168 // when
169 for (uint8_t index = 0; index < ARRAYLEN(ledStripConfigCommands); index++) {
170 EXPECT_TRUE(parseLedStripConfig(index, ledStripConfigCommands[index]));
173 // then
174 EXPECT_EQ(30, ledCounts.count);
175 EXPECT_EQ(4, ledCounts.ring);
177 // and
178 for (uint8_t index = 0; index < WS2811_LED_STRIP_LENGTH; index++) {
179 #ifdef DEBUG_LEDSTRIP
180 printf("iteration: %d\n", index);
181 #endif
182 EXPECT_EQ(expectedLedStripConfig[index], ledStripStatusModeConfig()->ledConfigs[index]);
185 // then
186 EXPECT_EQ(12, ledGridRows);
188 // then
189 EXPECT_EQ(5, highestXValueForWest);
190 EXPECT_EQ(7, lowestXValueForEast);
191 EXPECT_EQ(5, highestYValueForNorth);
192 EXPECT_EQ(6, lowestYValueForSouth);
195 TEST(LedStripTest, smallestGridWithCenter)
197 // given
198 memset(&ledStripStatusModeConfigMutable()->ledConfigs, 0, LED_MAX_STRIP_LENGTH);
200 // and
201 static const ledConfig_t testLedConfigs[] = {
202 DEFINE_LED(2, 2, 0, LD(EAST), LF(ARM_STATE), LO(INDICATOR), 0),
203 DEFINE_LED(2, 1, 0, LD(NORTH) | LD(EAST), LF(FLIGHT_MODE), LO(WARNING), 0),
204 DEFINE_LED(2, 0, 0, LD(NORTH), LF(ARM_STATE), LO(INDICATOR), 0),
205 DEFINE_LED(1, 0, 0, LD(NORTH) | LD(WEST), LF(FLIGHT_MODE), LO(WARNING), 0),
206 DEFINE_LED(0, 0, 0, LD(WEST), LF(ARM_STATE), LO(INDICATOR), 0),
207 DEFINE_LED(0, 1, 0, LD(SOUTH) | LD(WEST), LF(FLIGHT_MODE), LO(WARNING), 0),
208 DEFINE_LED(0, 2, 0, LD(SOUTH), LF(ARM_STATE), LO(INDICATOR), 0)
210 memcpy(&ledStripStatusModeConfigMutable()->ledConfigs, &testLedConfigs, sizeof(testLedConfigs));
212 // when
213 reevaluateLedConfig();
215 // then
216 EXPECT_EQ(3, ledGridRows);
217 EXPECT_EQ(0, highestXValueForWest);
218 EXPECT_EQ(2, lowestXValueForEast);
219 EXPECT_EQ(0, highestYValueForNorth);
220 EXPECT_EQ(2, lowestYValueForSouth);
223 TEST(LedStripTest, smallestGrid)
225 // given
226 memset(&ledStripStatusModeConfigMutable()->ledConfigs, 0, LED_MAX_STRIP_LENGTH);
228 // and
229 static const ledConfig_t testLedConfigs[] = {
230 DEFINE_LED(1, 1, 0, LD(SOUTH) | LD(EAST), LF(FLIGHT_MODE), LO(INDICATOR), 0),
231 DEFINE_LED(1, 0, 0, LD(NORTH) | LD(EAST), LF(FLIGHT_MODE), LO(INDICATOR), 0),
232 DEFINE_LED(0, 0, 0, LD(NORTH) | LD(WEST), LF(FLIGHT_MODE), LO(INDICATOR), 0),
233 DEFINE_LED(0, 1, 0, LD(SOUTH) | LD(WEST), LF(FLIGHT_MODE), LO(INDICATOR), 0)
235 memcpy(&ledStripStatusModeConfigMutable()->ledConfigs, &testLedConfigs, sizeof(testLedConfigs));
237 // when
238 reevaluateLedConfig();
240 // then
241 EXPECT_EQ(2, ledGridRows);
242 EXPECT_EQ(0, highestXValueForWest);
243 EXPECT_EQ(1, lowestXValueForEast);
244 EXPECT_EQ(0, highestYValueForNorth);
245 EXPECT_EQ(1, lowestYValueForSouth);
248 hsvColor_t testColors[LED_CONFIGURABLE_COLOR_COUNT];
250 extern hsvColor_t *colors;
252 #define TEST_COLOR_COUNT 4
254 TEST(ColorTest, parseColor)
256 // given
257 memset(ledStripStatusModeConfigMutable()->colors, 0, sizeof(hsvColor_t) * LED_CONFIGURABLE_COLOR_COUNT);
259 // and
260 const hsvColor_t expectedColors[TEST_COLOR_COUNT] = {
261 // H S V
262 { 0, 0, 0 },
263 { 1, 1, 1 },
264 { 359, 255, 255 },
265 { 333, 22, 1 }
268 const char *testColors[TEST_COLOR_COUNT] = {
269 "0,0,0",
270 "1,1,1",
271 "359,255,255",
272 "333,22,1"
275 // when
276 for (uint8_t index = 0; index < TEST_COLOR_COUNT; index++) {
277 #ifdef DEBUG_LEDSTRIP
278 printf("parse iteration: %d\n", index);
279 #endif
281 parseColor(index, testColors[index]);
284 // then
286 for (uint8_t index = 0; index < TEST_COLOR_COUNT; index++) {
287 #ifdef DEBUG_LEDSTRIP
288 printf("iteration: %d\n", index);
289 #endif
291 EXPECT_EQ(expectedColors[index].h, ledStripStatusModeConfig()->colors[index].h);
292 EXPECT_EQ(expectedColors[index].s, ledStripStatusModeConfig()->colors[index].s);
293 EXPECT_EQ(expectedColors[index].v, ledStripStatusModeConfig()->colors[index].v);
297 extern "C" {
299 uint8_t armingFlags = 0;
300 uint8_t stateFlags = 0;
301 uint16_t flightModeFlags = 0;
302 float rcCommand[4];
303 float rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT];
304 boxBitmask_t rcModeActivationMask;
305 gpsSolutionData_t gpsSol;
307 batteryState_e getBatteryState(void)
309 return BATTERY_OK;
312 void ws2811LedStripInit(ioTag_t ioTag)
314 UNUSED(ioTag);
317 void ws2811UpdateStrip(ledStripFormatRGB_e, uint8_t) {}
319 void setLedValue(uint16_t index, const uint8_t value)
321 UNUSED(index);
322 UNUSED(value);
325 void setLedHsv(uint16_t index, const hsvColor_t *color)
327 UNUSED(index);
328 UNUSED(color);
331 void getLedHsv(uint16_t index, hsvColor_t *color)
333 UNUSED(index);
334 UNUSED(color);
338 void scaleLedValue(uint16_t index, const uint8_t scalePercent)
340 UNUSED(index);
341 UNUSED(scalePercent);
344 void setStripColor(const hsvColor_t *color)
346 UNUSED(color);
349 void setStripColors(const hsvColor_t *colors)
351 UNUSED(colors);
354 bool isWS2811LedStripReady(void) { return false; }
356 void delay(uint32_t ms)
358 UNUSED(ms);
359 return;
362 uint32_t micros(void) { return 0; }
364 uint32_t millis(void) { return 0; }
366 bool shouldSoundBatteryAlarm(void) { return false; }
367 bool featureIsEnabled(uint32_t mask)
369 UNUSED(mask);
370 return false;
373 void tfp_sprintf(char *, char*, ...) { }
375 int scaleRange(int x, int srcMin, int srcMax, int destMin, int destMax)
377 UNUSED(x);
378 UNUSED(srcMin);
379 UNUSED(srcMax);
380 UNUSED(destMin);
381 UNUSED(destMax);
383 return 0;
386 bool failsafeIsActive() { return false; }
387 bool rxIsReceivingSignal() { return true; }
389 bool isBeeperOn() { return false; };
391 uint8_t calculateBatteryPercentageRemaining() { return 0; }
393 bool sensors(uint32_t mask)
395 UNUSED(mask);
396 return false;
399 const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = {};
401 bool isArmingDisabled(void) { return false; }
403 uint8_t getRssiPercent(void) { return 0; }
405 bool isFlipOverAfterCrashActive(void) { return false; }
407 void ws2811LedStripEnable(void) { }
409 void setUsedLedCount(unsigned) { }
410 void pinioBoxTaskControl(void) {}
411 void schedulerIgnoreTaskExecTime(void) {}
412 bool schedulerGetIgnoreTaskExecTime() { return false; }
413 void schedulerSetNextStateTime(timeDelta_t) {}