Finally rename flight.c/.h to pid.c/.h. Cleanup some dependencies.
[betaflight.git] / src / test / unit / ledstrip_unittest.cc
blob6cd1bf9dcfb9baa7f70d18d9c86eafdb1b2b5704
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 extern "C" {
23 #include "build_config.h"
25 #include "common/color.h"
26 #include "common/axis.h"
28 #include "sensors/battery.h"
29 #include "config/runtime_config.h"
30 #include "config/config.h"
32 #include "rx/rx.h"
34 #include "io/rc_controls.h"
36 #include "drivers/light_ws2811strip.h"
37 #include "io/ledstrip.h"
40 #include "unittest_macros.h"
41 #include "gtest/gtest.h"
43 extern "C" {
44 extern ledConfig_t *ledConfigs;
45 extern uint8_t highestYValueForNorth;
46 extern uint8_t lowestYValueForSouth;
47 extern uint8_t highestXValueForWest;
48 extern uint8_t lowestXValueForEast;
49 extern uint8_t ledGridWidth;
50 extern uint8_t ledGridHeight;
52 void determineLedStripDimensions(void);
53 void determineOrientationLimits(void);
55 ledConfig_t systemLedConfigs[MAX_LED_STRIP_LENGTH];
58 TEST(LedStripTest, parseLedStripConfig)
60 // given
61 static const ledConfig_t expectedLedStripConfig[WS2811_LED_STRIP_LENGTH] = {
62 { CALCULATE_LED_XY( 9, 9), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
63 { CALCULATE_LED_XY(10, 10), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
64 { CALCULATE_LED_XY(11, 11), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
65 { CALCULATE_LED_XY(11, 11), 0, LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
66 { CALCULATE_LED_XY(10, 10), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
68 { CALCULATE_LED_XY(10, 5), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE },
69 { CALCULATE_LED_XY(11, 4), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE },
70 { CALCULATE_LED_XY(12, 3), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
71 { CALCULATE_LED_XY(12, 2), 0, LED_DIRECTION_NORTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
72 { CALCULATE_LED_XY(11, 1), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
73 { CALCULATE_LED_XY(10, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
75 { CALCULATE_LED_XY( 7, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
76 { CALCULATE_LED_XY( 6, 0), 1, LED_DIRECTION_NORTH | LED_FUNCTION_COLOR | LED_FUNCTION_WARNING },
77 { CALCULATE_LED_XY( 5, 0), 1, LED_DIRECTION_NORTH | LED_FUNCTION_COLOR | LED_FUNCTION_WARNING },
78 { CALCULATE_LED_XY( 4, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
80 { CALCULATE_LED_XY( 2, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
81 { CALCULATE_LED_XY( 1, 1), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE },
82 { CALCULATE_LED_XY( 0, 2), 0, LED_DIRECTION_NORTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
83 { CALCULATE_LED_XY( 0, 3), 0, LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
84 { CALCULATE_LED_XY( 1, 4), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
85 { CALCULATE_LED_XY( 2, 5), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
87 { CALCULATE_LED_XY( 1, 10), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
88 { CALCULATE_LED_XY( 0, 11), 0, LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
89 { CALCULATE_LED_XY( 0, 11), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
90 { CALCULATE_LED_XY( 1, 10), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
91 { CALCULATE_LED_XY( 2, 9), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
93 { CALCULATE_LED_XY( 7, 7), 14, LED_FUNCTION_THRUST_RING },
94 { CALCULATE_LED_XY( 8, 7), 15, LED_FUNCTION_THRUST_RING },
95 { CALCULATE_LED_XY( 8, 8), 14, LED_FUNCTION_THRUST_RING },
96 { CALCULATE_LED_XY( 7, 8), 15, LED_FUNCTION_THRUST_RING },
98 { 0, 0, 0 },
99 { 0, 0, 0 },
102 // and
103 const char *ledStripConfigCommands[] = {
104 // Spider quad
106 // right rear cluster
107 "9,9:S:FW:0",
108 "10,10:S:FW:0",
109 "11,11:S:IA:0",
110 "11,11:E:IA:0",
111 "10,10:E:F:0",
113 // right front cluster
114 "10,5:S:F:0",
115 "11,4:S:F:0",
116 "12,3:S:IA:0",
117 "12,2:N:IA:0",
118 "11,1:N:F:0",
119 "10,0:N:F:0",
121 // center front cluster
122 "7,0:N:FW:0",
123 "6,0:N:CW:1",
124 "5,0:N:CW:1",
125 "4,0:N:FW:0",
127 // left front cluster
128 "2,0:N:F:0",
129 "1,1:N:F:0",
130 "0,2:N:IA:0",
131 "0,3:W:IA:0",
132 "1,4:W:F:0",
133 "2,5:W:F:0",
135 // left rear cluster
136 "1,10:W:F:0",
137 "0,11:W:IA:0",
138 "0,11:S:IA:0",
139 "1,10:S:FW:0",
140 "2,9:S:FW:0",
142 // thrust ring
143 "7,7::R:14",
144 "8,7::R:15",
145 "8,8::R:14",
146 "7,8::R:15"
148 // and
149 memset(&systemLedConfigs, 0, sizeof(systemLedConfigs));
150 ledConfigs = systemLedConfigs;
152 // and
153 bool ok = false;
155 // when
156 for (uint8_t index = 0; index < (sizeof(ledStripConfigCommands) / sizeof(ledStripConfigCommands[0])); index++) {
157 ok |= parseLedStripConfig(index, ledStripConfigCommands[index]);
160 // then
161 EXPECT_EQ(true, ok);
162 EXPECT_EQ(30, ledCount);
163 EXPECT_EQ(4, ledsInRingCount);
166 // and
167 for (uint8_t index = 0; index < WS2811_LED_STRIP_LENGTH; index++) {
168 printf("iteration: %d\n", index);
170 EXPECT_EQ(expectedLedStripConfig[index].xy, ledConfigs[index].xy);
171 EXPECT_EQ(expectedLedStripConfig[index].flags, ledConfigs[index].flags);
172 EXPECT_EQ(expectedLedStripConfig[index].color, ledConfigs[index].color);
175 // then
176 EXPECT_EQ(13, ledGridWidth);
177 EXPECT_EQ(12, ledGridHeight);
179 // then
180 EXPECT_EQ(5, highestXValueForWest);
181 EXPECT_EQ(7, lowestXValueForEast);
182 EXPECT_EQ(5, highestYValueForNorth);
183 EXPECT_EQ(6, lowestYValueForSouth);
186 TEST(LedStripTest, smallestGridWithCenter)
188 // given
189 memset(&systemLedConfigs, 0, sizeof(systemLedConfigs));
190 ledConfigs = systemLedConfigs;
192 // and
193 static const ledConfig_t testLedConfigs[] = {
194 { CALCULATE_LED_XY( 2, 2), 0, LED_DIRECTION_SOUTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
195 { CALCULATE_LED_XY( 2, 1), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
196 { CALCULATE_LED_XY( 2, 0), 0, LED_DIRECTION_NORTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
197 { CALCULATE_LED_XY( 1, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
198 { CALCULATE_LED_XY( 0, 0), 0, LED_DIRECTION_NORTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
199 { CALCULATE_LED_XY( 0, 1), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
200 { CALCULATE_LED_XY( 0, 2), 0, LED_DIRECTION_SOUTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
201 { CALCULATE_LED_XY( 1, 2), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING }
203 memcpy(&systemLedConfigs, &testLedConfigs, sizeof(testLedConfigs));
205 // when
206 determineLedStripDimensions();
208 // then
209 EXPECT_EQ(3, ledGridWidth);
210 EXPECT_EQ(3, ledGridHeight);
212 // when
213 determineOrientationLimits();
215 // then
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(&systemLedConfigs, 0, sizeof(systemLedConfigs));
226 ledConfigs = systemLedConfigs;
228 // and
229 static const ledConfig_t testLedConfigs[] = {
230 { CALCULATE_LED_XY( 1, 1), 0, LED_DIRECTION_SOUTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_FLIGHT_MODE },
231 { CALCULATE_LED_XY( 1, 0), 0, LED_DIRECTION_NORTH | LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_FLIGHT_MODE },
232 { CALCULATE_LED_XY( 0, 0), 0, LED_DIRECTION_NORTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_FLIGHT_MODE },
233 { CALCULATE_LED_XY( 0, 1), 0, LED_DIRECTION_SOUTH | LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_FLIGHT_MODE },
235 memcpy(&systemLedConfigs, &testLedConfigs, sizeof(testLedConfigs));
237 // when
238 determineLedStripDimensions();
240 // then
241 EXPECT_EQ(2, ledGridWidth);
242 EXPECT_EQ(2, ledGridHeight);
244 // when
245 determineOrientationLimits();
247 // then
248 EXPECT_EQ(0, highestXValueForWest);
249 EXPECT_EQ(1, lowestXValueForEast);
250 EXPECT_EQ(0, highestYValueForNorth);
251 EXPECT_EQ(1, lowestYValueForSouth);
255 { CALCULATE_LED_XY( 1, 14), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_INDICATOR | LED_FUNCTION_FLIGHT_MODE },
257 { CALCULATE_LED_XY( 0, 13), 0, LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
258 { CALCULATE_LED_XY( 0, 12), 0, LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
260 { CALCULATE_LED_XY( 0, 11), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
261 { CALCULATE_LED_XY( 0, 10), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
262 { CALCULATE_LED_XY( 0, 9), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
263 { CALCULATE_LED_XY( 0, 8), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
264 { CALCULATE_LED_XY( 0, 7), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
265 { CALCULATE_LED_XY( 0, 6), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
266 { CALCULATE_LED_XY( 0, 5), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
267 { CALCULATE_LED_XY( 0, 4), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
268 { CALCULATE_LED_XY( 0, 3), 0, LED_DIRECTION_WEST | LED_FUNCTION_FLIGHT_MODE },
270 { CALCULATE_LED_XY( 0, 2), 0, LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
271 { CALCULATE_LED_XY( 0, 1), 0, LED_DIRECTION_WEST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
273 { CALCULATE_LED_XY( 1, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
274 { CALCULATE_LED_XY( 2, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_ARM_STATE },
275 { CALCULATE_LED_XY( 3, 0), 0, LED_DIRECTION_NORTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
277 { CALCULATE_LED_XY( 4, 1), 0, LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
278 { CALCULATE_LED_XY( 4, 2), 0, LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
280 { CALCULATE_LED_XY( 4, 3), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
281 { CALCULATE_LED_XY( 4, 4), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
282 { CALCULATE_LED_XY( 4, 5), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
283 { CALCULATE_LED_XY( 4, 6), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
284 { CALCULATE_LED_XY( 4, 7), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
285 { CALCULATE_LED_XY( 4, 8), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_WARNING },
286 { CALCULATE_LED_XY( 4, 9), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
287 { CALCULATE_LED_XY( 4, 10), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
288 { CALCULATE_LED_XY( 4, 11), 0, LED_DIRECTION_EAST | LED_FUNCTION_FLIGHT_MODE },
290 { CALCULATE_LED_XY( 4, 12), 0, LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
291 { CALCULATE_LED_XY( 4, 13), 0, LED_DIRECTION_EAST | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
293 { CALCULATE_LED_XY( 3, 14), 0, LED_DIRECTION_SOUTH | LED_FUNCTION_FLIGHT_MODE | LED_FUNCTION_INDICATOR | LED_FUNCTION_ARM_STATE },
297 hsvColor_t testColors[CONFIGURABLE_COLOR_COUNT];
299 extern hsvColor_t *colors;
301 #define TEST_COLOR_COUNT 4
303 TEST(ColorTest, parseColor)
305 // given
306 colors = testColors;
307 memset(colors, 0, sizeof(colors) * CONFIGURABLE_COLOR_COUNT);
309 // and
310 const hsvColor_t expectedColors[TEST_COLOR_COUNT] = {
311 // H S V
312 { 0, 0, 0 },
313 { 1, 1, 1 },
314 { 359, 255, 255 },
315 { 333, 22, 1 }
318 const char *testColors[TEST_COLOR_COUNT] = {
319 "0,0,0",
320 "1,1,1",
321 "359,255,255",
322 "333,22,1"
325 // when
326 for (uint8_t index = 0; index < TEST_COLOR_COUNT; index++) {
327 printf("parse iteration: %d\n", index);
328 parseColor(index, testColors[index]);
331 // then
333 for (uint8_t index = 0; index < TEST_COLOR_COUNT; index++) {
334 printf("iteration: %d\n", index);
336 EXPECT_EQ(expectedColors[index].h, colors[index].h);
337 EXPECT_EQ(expectedColors[index].s, colors[index].s);
338 EXPECT_EQ(expectedColors[index].v, colors[index].v);
342 extern "C" {
344 uint8_t armingFlags = 0;
345 uint16_t flightModeFlags = 0;
346 int16_t rcCommand[4];
347 int16_t rcData[MAX_SUPPORTED_RC_CHANNEL_COUNT];
348 uint32_t rcModeActivationMask;
350 batteryState_e calculateBatteryState(void) {
351 return BATTERY_OK;
354 void ws2811LedStripInit(void) {}
355 void ws2811UpdateStrip(void) {}
357 void setLedValue(uint16_t index, const uint8_t value) {
358 UNUSED(index);
359 UNUSED(value);
362 void setLedHsv(uint16_t index, const hsvColor_t *color) {
363 UNUSED(index);
364 UNUSED(color);
367 void getLedHsv(uint16_t index, hsvColor_t *color) {
368 UNUSED(index);
369 UNUSED(color);
373 void scaleLedValue(uint16_t index, const uint8_t scalePercent) {
374 UNUSED(index);
375 UNUSED(scalePercent);
378 void setStripColor(const hsvColor_t *color) {
379 UNUSED(color);
382 void setStripColors(const hsvColor_t *colors) {
383 UNUSED(colors);
386 bool isWS2811LedStripReady(void) { return false; }
388 void delay(uint32_t ms)
390 UNUSED(ms);
391 return;
394 uint32_t micros(void) { return 0; }
395 bool shouldSoundBatteryAlarm(void) { return false; }
396 bool feature(uint32_t mask) {
397 UNUSED(mask);
398 return false;
401 void tfp_sprintf(char *, char*, ...) { }
403 int scaleRange(int x, int srcMin, int srcMax, int destMin, int destMax) {
404 UNUSED(x);
405 UNUSED(srcMin);
406 UNUSED(srcMax);
407 UNUSED(destMin);
408 UNUSED(destMax);
410 return 0;