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/>.
22 //#define DEBUG_LEDSTRIP
26 #include "build/build_config.h"
28 #include "common/axis.h"
29 #include "common/color.h"
30 #include "common/utils.h"
33 #include "pg/pg_ids.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"
47 #include "io/ledstrip.h"
51 #include "sensors/battery.h"
56 #include "unittest_macros.h"
57 #include "gtest/gtest.h"
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
)
77 memset(&ledStripStatusModeConfigMutable()->ledConfigs
, 0, LED_MAX_STRIP_LENGTH
);
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),
122 const char *ledStripConfigCommands
[] = {
125 // right rear cluster
132 // right front cluster
140 // center front cluster
146 // left front cluster
169 for (uint8_t index
= 0; index
< ARRAYLEN(ledStripConfigCommands
); index
++) {
170 EXPECT_TRUE(parseLedStripConfig(index
, ledStripConfigCommands
[index
]));
174 EXPECT_EQ(30, ledCounts
.count
);
175 EXPECT_EQ(4, ledCounts
.ring
);
178 for (uint8_t index
= 0; index
< WS2811_LED_STRIP_LENGTH
; index
++) {
179 #ifdef DEBUG_LEDSTRIP
180 printf("iteration: %d\n", index
);
182 EXPECT_EQ(expectedLedStripConfig
[index
], ledStripStatusModeConfig()->ledConfigs
[index
]);
186 EXPECT_EQ(12, ledGridRows
);
189 EXPECT_EQ(5, highestXValueForWest
);
190 EXPECT_EQ(7, lowestXValueForEast
);
191 EXPECT_EQ(5, highestYValueForNorth
);
192 EXPECT_EQ(6, lowestYValueForSouth
);
195 TEST(LedStripTest
, smallestGridWithCenter
)
198 memset(&ledStripStatusModeConfigMutable()->ledConfigs
, 0, LED_MAX_STRIP_LENGTH
);
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
));
213 reevaluateLedConfig();
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
)
226 memset(&ledStripStatusModeConfigMutable()->ledConfigs
, 0, LED_MAX_STRIP_LENGTH
);
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
));
238 reevaluateLedConfig();
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
)
257 memset(ledStripStatusModeConfigMutable()->colors
, 0, sizeof(hsvColor_t
) * LED_CONFIGURABLE_COLOR_COUNT
);
260 const hsvColor_t expectedColors
[TEST_COLOR_COUNT
] = {
268 const char *testColors
[TEST_COLOR_COUNT
] = {
276 for (uint8_t index
= 0; index
< TEST_COLOR_COUNT
; index
++) {
277 #ifdef DEBUG_LEDSTRIP
278 printf("parse iteration: %d\n", index
);
281 parseColor(index
, testColors
[index
]);
286 for (uint8_t index
= 0; index
< TEST_COLOR_COUNT
; index
++) {
287 #ifdef DEBUG_LEDSTRIP
288 printf("iteration: %d\n", index
);
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
);
299 uint8_t armingFlags
= 0;
300 uint8_t stateFlags
= 0;
301 uint16_t flightModeFlags
= 0;
303 float rcData
[MAX_SUPPORTED_RC_CHANNEL_COUNT
];
304 boxBitmask_t rcModeActivationMask
;
305 gpsSolutionData_t gpsSol
;
307 batteryState_e
getBatteryState(void)
312 void ws2811LedStripInit(ioTag_t ioTag
)
317 void ws2811UpdateStrip(ledStripFormatRGB_e
, uint8_t) {}
319 void setLedValue(uint16_t index
, const uint8_t value
)
325 void setLedHsv(uint16_t index
, const hsvColor_t
*color
)
331 void getLedHsv(uint16_t index
, hsvColor_t
*color
)
338 void scaleLedValue(uint16_t index
, const uint8_t scalePercent
)
341 UNUSED(scalePercent
);
344 void setStripColor(const hsvColor_t
*color
)
349 void setStripColors(const hsvColor_t
*colors
)
354 bool isWS2811LedStripReady(void) { return false; }
356 void delay(uint32_t ms
)
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
)
373 void tfp_sprintf(char *, char*, ...) { }
375 int scaleRange(int x
, int srcMin
, int srcMax
, int destMin
, int destMax
)
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
)
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
) {}