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/>.
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"
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"
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
)
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
},
103 const char *ledStripConfigCommands
[] = {
106 // right rear cluster
113 // right front cluster
121 // center front cluster
127 // left front cluster
149 memset(&systemLedConfigs
, 0, sizeof(systemLedConfigs
));
150 ledConfigs
= systemLedConfigs
;
156 for (uint8_t index
= 0; index
< (sizeof(ledStripConfigCommands
) / sizeof(ledStripConfigCommands
[0])); index
++) {
157 ok
|= parseLedStripConfig(index
, ledStripConfigCommands
[index
]);
162 EXPECT_EQ(30, ledCount
);
163 EXPECT_EQ(4, ledsInRingCount
);
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
);
176 EXPECT_EQ(13, ledGridWidth
);
177 EXPECT_EQ(12, ledGridHeight
);
180 EXPECT_EQ(5, highestXValueForWest
);
181 EXPECT_EQ(7, lowestXValueForEast
);
182 EXPECT_EQ(5, highestYValueForNorth
);
183 EXPECT_EQ(6, lowestYValueForSouth
);
186 TEST(LedStripTest
, smallestGridWithCenter
)
189 memset(&systemLedConfigs
, 0, sizeof(systemLedConfigs
));
190 ledConfigs
= systemLedConfigs
;
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
));
206 determineLedStripDimensions();
209 EXPECT_EQ(3, ledGridWidth
);
210 EXPECT_EQ(3, ledGridHeight
);
213 determineOrientationLimits();
216 EXPECT_EQ(0, highestXValueForWest
);
217 EXPECT_EQ(2, lowestXValueForEast
);
218 EXPECT_EQ(0, highestYValueForNorth
);
219 EXPECT_EQ(2, lowestYValueForSouth
);
222 TEST(LedStripTest
, smallestGrid
)
225 memset(&systemLedConfigs
, 0, sizeof(systemLedConfigs
));
226 ledConfigs
= systemLedConfigs
;
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
));
238 determineLedStripDimensions();
241 EXPECT_EQ(2, ledGridWidth
);
242 EXPECT_EQ(2, ledGridHeight
);
245 determineOrientationLimits();
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
)
307 memset(colors
, 0, sizeof(colors
) * CONFIGURABLE_COLOR_COUNT
);
310 const hsvColor_t expectedColors
[TEST_COLOR_COUNT
] = {
318 const char *testColors
[TEST_COLOR_COUNT
] = {
326 for (uint8_t index
= 0; index
< TEST_COLOR_COUNT
; index
++) {
327 printf("parse iteration: %d\n", index
);
328 parseColor(index
, testColors
[index
]);
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
);
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) {
354 void ws2811LedStripInit(void) {}
355 void ws2811UpdateStrip(void) {}
357 void setLedValue(uint16_t index
, const uint8_t value
) {
362 void setLedHsv(uint16_t index
, const hsvColor_t
*color
) {
367 void getLedHsv(uint16_t index
, hsvColor_t
*color
) {
373 void scaleLedValue(uint16_t index
, const uint8_t scalePercent
) {
375 UNUSED(scalePercent
);
378 void setStripColor(const hsvColor_t
*color
) {
382 void setStripColors(const hsvColor_t
*colors
) {
386 bool isWS2811LedStripReady(void) { return false; }
388 void delay(uint32_t ms
)
394 uint32_t micros(void) { return 0; }
395 bool shouldSoundBatteryAlarm(void) { return false; }
396 bool feature(uint32_t mask
) {
401 void tfp_sprintf(char *, char*, ...) { }
403 int scaleRange(int x
, int srcMin
, int srcMax
, int destMin
, int destMax
) {