Updated and Validated
[betaflight.git] / src / test / unit / ledstrip_unittest.cc
blob81f0918b0d6e5cdccdf5e6ae33cac452babf8df6
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"
31 #include "pg/pg.h"
32 #include "pg/pg_ids.h"
33 #include "pg/rx.h"
35 #include "drivers/io.h"
36 #include "drivers/light_ws2811strip.h"
37 #include "drivers/timer.h"
38 #include "drivers/timer_def.h"
40 #include "config/config.h"
41 #include "fc/rc_controls.h"
42 #include "fc/rc_modes.h"
43 #include "fc/runtime_config.h"
45 #include "io/gps.h"
46 #include "io/ledstrip.h"
48 #include "rx/rx.h"
50 #include "sensors/battery.h"
52 #include "target.h"
55 #include "unittest_macros.h"
56 #include "gtest/gtest.h"
58 extern "C" {
59 extern uint8_t highestYValueForNorth;
60 extern uint8_t lowestYValueForSouth;
61 extern uint8_t highestXValueForWest;
62 extern uint8_t lowestXValueForEast;
64 extern uint8_t ledGridRows;
66 extern ledCounts_t ledCounts;
68 void reevaluateLedConfig();
70 PG_REGISTER(batteryConfig_t, batteryConfig, PG_BATTERY_CONFIG, 0);
73 TEST(LedStripTest, parseLedStripConfig)
75 // given
76 memset(&ledStripStatusModeConfigMutable()->ledConfigs, 0, LED_MAX_STRIP_LENGTH);
78 // and
79 static const ledConfig_t expectedLedStripConfig[WS2811_LED_STRIP_LENGTH] = {
80 DEFINE_LED(9, 9, 0, LD(SOUTH), LF(FLIGHT_MODE), LO(WARNING), 0),
81 DEFINE_LED(10, 10, 0, LD(SOUTH), LF(FLIGHT_MODE), LO(WARNING), 0),
82 DEFINE_LED(11, 11, 0, LD(SOUTH), LF(ARM_STATE), LO(INDICATOR), 0),
83 DEFINE_LED(11, 11, 0, LD(EAST), LF(ARM_STATE), LO(INDICATOR), 0),
84 DEFINE_LED(10, 10, 0, LD(EAST), LF(FLIGHT_MODE), 0, 0),
86 DEFINE_LED(10, 5, 0, LD(SOUTH), LF(FLIGHT_MODE), 0, 0),
87 DEFINE_LED(11, 4, 0, LD(SOUTH), LF(FLIGHT_MODE), 0, 0),
88 DEFINE_LED(12, 3, 0, LD(SOUTH), LF(ARM_STATE), LO(INDICATOR), 0),
89 DEFINE_LED(12, 2, 0, LD(NORTH), LF(ARM_STATE), LO(INDICATOR), 0),
90 DEFINE_LED(11, 1, 0, LD(NORTH), LF(FLIGHT_MODE), 0, 0),
91 DEFINE_LED(10, 0, 0, LD(NORTH), LF(FLIGHT_MODE), 0, 0),
93 DEFINE_LED(7, 0, 0, LD(NORTH), LF(FLIGHT_MODE), LO(WARNING), 0),
94 DEFINE_LED(6, 0, 1, LD(NORTH), LF(COLOR), LO(WARNING), 0),
95 DEFINE_LED(5, 0, 1, LD(NORTH), LF(COLOR), LO(WARNING), 0),
96 DEFINE_LED(4, 0, 0, LD(NORTH), LF(FLIGHT_MODE), LO(WARNING), 0),
98 DEFINE_LED(2, 0, 0, LD(NORTH), LF(FLIGHT_MODE), 0, 0),
99 DEFINE_LED(1, 1, 0, LD(NORTH), LF(FLIGHT_MODE), 0, 0),
100 DEFINE_LED(0, 2, 0, LD(NORTH), LF(ARM_STATE), LO(INDICATOR), 0),
101 DEFINE_LED(0, 3, 0, LD(WEST), LF(ARM_STATE), LO(INDICATOR), 0),
102 DEFINE_LED(1, 4, 0, LD(WEST), LF(FLIGHT_MODE), 0, 0),
103 DEFINE_LED(2, 5, 0, LD(WEST), LF(FLIGHT_MODE), 0, 0),
105 DEFINE_LED(1, 10, 0, LD(WEST), LF(FLIGHT_MODE), 0, 0),
106 DEFINE_LED(0, 11, 0, LD(WEST), LF(ARM_STATE), LO(INDICATOR), 0),
107 DEFINE_LED(0, 11, 0, LD(SOUTH), LF(ARM_STATE), LO(INDICATOR), 0),
108 DEFINE_LED(1, 10, 0, LD(SOUTH), LF(FLIGHT_MODE), LO(WARNING), 0),
109 DEFINE_LED(2, 9, 0, LD(SOUTH), LF(FLIGHT_MODE), LO(WARNING), 0),
111 DEFINE_LED(7, 7, 14, 0, LF(THRUST_RING), 0, 0),
112 DEFINE_LED(8, 7, 15, 0, LF(THRUST_RING), 0, 0),
113 DEFINE_LED(8, 8, 14, 0, LF(THRUST_RING), 0, 0),
114 DEFINE_LED(7, 8, 15, 0, LF(THRUST_RING), 0, 0),
120 // and
121 const char *ledStripConfigCommands[] = {
122 // Spider quad
124 // right rear cluster
125 "9,9:S:FW:0",
126 "10,10:S:FW:0",
127 "11,11:S:IA:0",
128 "11,11:E:IA:0",
129 "10,10:E:F:0",
131 // right front cluster
132 "10,5:S:F:0",
133 "11,4:S:F:0",
134 "12,3:S:IA:0",
135 "12,2:N:IA:0",
136 "11,1:N:F:0",
137 "10,0:N:F:0",
139 // center front cluster
140 "7,0:N:FW:0",
141 "6,0:N:CW:1",
142 "5,0:N:CW:1",
143 "4,0:N:FW:0",
145 // left front cluster
146 "2,0:N:F:0",
147 "1,1:N:F:0",
148 "0,2:N:IA:0",
149 "0,3:W:IA:0",
150 "1,4:W:F:0",
151 "2,5:W:F:0",
153 // left rear cluster
154 "1,10:W:F:0",
155 "0,11:W:IA:0",
156 "0,11:S:IA:0",
157 "1,10:S:FW:0",
158 "2,9:S:FW:0",
160 // thrust ring
161 "7,7::R:14",
162 "8,7::R:15",
163 "8,8::R:14",
164 "7,8::R:15"
167 // when
168 for (uint8_t index = 0; index < (sizeof(ledStripConfigCommands) / sizeof(ledStripConfigCommands[0])); index++) {
169 EXPECT_TRUE(parseLedStripConfig(index, ledStripConfigCommands[index]));
172 // then
173 EXPECT_EQ(30, ledCounts.count);
174 EXPECT_EQ(4, ledCounts.ring);
176 // and
177 for (uint8_t index = 0; index < WS2811_LED_STRIP_LENGTH; index++) {
178 #ifdef DEBUG_LEDSTRIP
179 printf("iteration: %d\n", index);
180 #endif
181 EXPECT_EQ(expectedLedStripConfig[index], ledStripStatusModeConfig()->ledConfigs[index]);
184 // then
185 EXPECT_EQ(12, ledGridRows);
187 // then
188 EXPECT_EQ(5, highestXValueForWest);
189 EXPECT_EQ(7, lowestXValueForEast);
190 EXPECT_EQ(5, highestYValueForNorth);
191 EXPECT_EQ(6, lowestYValueForSouth);
194 TEST(LedStripTest, smallestGridWithCenter)
196 // given
197 memset(&ledStripStatusModeConfigMutable()->ledConfigs, 0, LED_MAX_STRIP_LENGTH);
199 // and
200 static const ledConfig_t testLedConfigs[] = {
201 DEFINE_LED(2, 2, 0, LD(EAST), LF(ARM_STATE), LO(INDICATOR), 0),
202 DEFINE_LED(2, 1, 0, LD(NORTH) | LD(EAST), LF(FLIGHT_MODE), LO(WARNING), 0),
203 DEFINE_LED(2, 0, 0, LD(NORTH), LF(ARM_STATE), LO(INDICATOR), 0),
204 DEFINE_LED(1, 0, 0, LD(NORTH) | LD(WEST), LF(FLIGHT_MODE), LO(WARNING), 0),
205 DEFINE_LED(0, 0, 0, LD(WEST), LF(ARM_STATE), LO(INDICATOR), 0),
206 DEFINE_LED(0, 1, 0, LD(SOUTH) | LD(WEST), LF(FLIGHT_MODE), LO(WARNING), 0),
207 DEFINE_LED(0, 2, 0, LD(SOUTH), LF(ARM_STATE), LO(INDICATOR), 0)
209 memcpy(&ledStripStatusModeConfigMutable()->ledConfigs, &testLedConfigs, sizeof(testLedConfigs));
211 // when
212 reevaluateLedConfig();
214 // then
215 EXPECT_EQ(3, ledGridRows);
216 EXPECT_EQ(0, highestXValueForWest);
217 EXPECT_EQ(2, lowestXValueForEast);
218 EXPECT_EQ(0, highestYValueForNorth);
219 EXPECT_EQ(2, lowestYValueForSouth);
222 TEST(LedStripTest, smallestGrid)
224 // given
225 memset(&ledStripStatusModeConfigMutable()->ledConfigs, 0, LED_MAX_STRIP_LENGTH);
227 // and
228 static const ledConfig_t testLedConfigs[] = {
229 DEFINE_LED(1, 1, 0, LD(SOUTH) | LD(EAST), LF(FLIGHT_MODE), LO(INDICATOR), 0),
230 DEFINE_LED(1, 0, 0, LD(NORTH) | LD(EAST), LF(FLIGHT_MODE), LO(INDICATOR), 0),
231 DEFINE_LED(0, 0, 0, LD(NORTH) | LD(WEST), LF(FLIGHT_MODE), LO(INDICATOR), 0),
232 DEFINE_LED(0, 1, 0, LD(SOUTH) | LD(WEST), LF(FLIGHT_MODE), LO(INDICATOR), 0)
234 memcpy(&ledStripStatusModeConfigMutable()->ledConfigs, &testLedConfigs, sizeof(testLedConfigs));
236 // when
237 reevaluateLedConfig();
239 // then
240 EXPECT_EQ(2, ledGridRows);
241 EXPECT_EQ(0, highestXValueForWest);
242 EXPECT_EQ(1, lowestXValueForEast);
243 EXPECT_EQ(0, highestYValueForNorth);
244 EXPECT_EQ(1, lowestYValueForSouth);
247 hsvColor_t testColors[LED_CONFIGURABLE_COLOR_COUNT];
249 extern hsvColor_t *colors;
251 #define TEST_COLOR_COUNT 4
253 TEST(ColorTest, parseColor)
255 // given
256 memset(ledStripStatusModeConfigMutable()->colors, 0, sizeof(hsvColor_t) * LED_CONFIGURABLE_COLOR_COUNT);
258 // and
259 const hsvColor_t expectedColors[TEST_COLOR_COUNT] = {
260 // H S V
261 { 0, 0, 0 },
262 { 1, 1, 1 },
263 { 359, 255, 255 },
264 { 333, 22, 1 }
267 const char *testColors[TEST_COLOR_COUNT] = {
268 "0,0,0",
269 "1,1,1",
270 "359,255,255",
271 "333,22,1"
274 // when
275 for (uint8_t index = 0; index < TEST_COLOR_COUNT; index++) {
276 #ifdef DEBUG_LEDSTRIP
277 printf("parse iteration: %d\n", index);
278 #endif
280 parseColor(index, testColors[index]);
283 // then
285 for (uint8_t index = 0; index < TEST_COLOR_COUNT; index++) {
286 #ifdef DEBUG_LEDSTRIP
287 printf("iteration: %d\n", index);
288 #endif
290 EXPECT_EQ(expectedColors[index].h, ledStripStatusModeConfig()->colors[index].h);
291 EXPECT_EQ(expectedColors[index].s, ledStripStatusModeConfig()->colors[index].s);
292 EXPECT_EQ(expectedColors[index].v, ledStripStatusModeConfig()->colors[index].v);
296 extern "C" {
298 uint8_t armingFlags = 0;
299 uint8_t stateFlags = 0;
300 uint16_t flightModeFlags = 0;
301 float rcCommand[4];
302 float rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT];
303 boxBitmask_t rcModeActivationMask;
304 gpsSolutionData_t gpsSol;
306 batteryState_e getBatteryState(void) {
307 return BATTERY_OK;
310 void ws2811LedStripInit(ioTag_t ioTag) {
311 UNUSED(ioTag);
314 void ws2811UpdateStrip(ledStripFormatRGB_e, uint8_t) {}
316 void setLedValue(uint16_t index, const uint8_t value) {
317 UNUSED(index);
318 UNUSED(value);
321 void setLedHsv(uint16_t index, const hsvColor_t *color) {
322 UNUSED(index);
323 UNUSED(color);
326 void getLedHsv(uint16_t index, hsvColor_t *color) {
327 UNUSED(index);
328 UNUSED(color);
332 void scaleLedValue(uint16_t index, const uint8_t scalePercent) {
333 UNUSED(index);
334 UNUSED(scalePercent);
337 void setStripColor(const hsvColor_t *color) {
338 UNUSED(color);
341 void setStripColors(const hsvColor_t *colors) {
342 UNUSED(colors);
345 bool isWS2811LedStripReady(void) { return false; }
347 void delay(uint32_t ms)
349 UNUSED(ms);
350 return;
353 uint32_t micros(void) { return 0; }
355 uint32_t millis(void) { return 0; }
357 bool shouldSoundBatteryAlarm(void) { return false; }
358 bool featureIsEnabled(uint32_t mask) {
359 UNUSED(mask);
360 return false;
363 void tfp_sprintf(char *, char*, ...) { }
365 int scaleRange(int x, int srcMin, int srcMax, int destMin, int destMax) {
366 UNUSED(x);
367 UNUSED(srcMin);
368 UNUSED(srcMax);
369 UNUSED(destMin);
370 UNUSED(destMax);
372 return 0;
375 bool failsafeIsActive() { return false; }
376 bool rxIsReceivingSignal() { return true; }
378 bool isBeeperOn() { return false; };
380 uint8_t calculateBatteryPercentageRemaining() { return 0; }
382 bool sensors(uint32_t mask)
384 UNUSED(mask);
385 return false;
388 const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = {};
390 bool isArmingDisabled(void) { return false; }
392 uint8_t getRssiPercent(void) { return 0; }
394 bool isFlipOverAfterCrashActive(void) { return false; }
396 void ws2811LedStripEnable(void) { }
398 void setUsedLedCount(unsigned) { }
399 void pinioBoxTaskControl(void) {}
400 void schedulerIgnoreTaskExecTime(void) {}
401 bool schedulerGetIgnoreTaskExecTime() { return false; }
402 void schedulerSetNextStateTime(timeDelta_t) {}