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 "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"
53 #include "scheduler/scheduler.h"
58 #include "unittest_macros.h"
59 #include "gtest/gtest.h"
62 extern uint8_t highestYValueForNorth
;
63 extern uint8_t lowestYValueForSouth
;
64 extern uint8_t highestXValueForWest
;
65 extern uint8_t lowestXValueForEast
;
67 extern uint8_t ledGridRows
;
69 extern ledCounts_t ledCounts
;
71 void reevaluateLedConfig();
73 PG_REGISTER(batteryConfig_t
, batteryConfig
, PG_BATTERY_CONFIG
, 0);
76 TEST(LedStripTest
, parseLedStripConfig
)
79 memset(&ledStripStatusModeConfigMutable()->ledConfigs
, 0, sizeof(ledStripStatusModeConfigMutable()->ledConfigs
));
82 static const ledConfig_t expectedLedStripConfig
[WS2811_LED_STRIP_LENGTH
] = {
83 DEFINE_LED(9, 9, 0, LD(SOUTH
), LF(FLIGHT_MODE
), LO(WARNING
)),
84 DEFINE_LED(10, 10, 0, LD(SOUTH
), LF(FLIGHT_MODE
), LO(WARNING
)),
85 DEFINE_LED(11, 11, 0, LD(SOUTH
), LF(ARM_STATE
), LO(INDICATOR
)),
86 DEFINE_LED(11, 11, 0, LD(EAST
), LF(ARM_STATE
), LO(INDICATOR
)),
87 DEFINE_LED(10, 10, 0, LD(EAST
), LF(FLIGHT_MODE
), 0),
89 DEFINE_LED(10, 5, 0, LD(SOUTH
), LF(FLIGHT_MODE
), 0),
90 DEFINE_LED(11, 4, 0, LD(SOUTH
), LF(FLIGHT_MODE
), 0),
91 DEFINE_LED(12, 3, 0, LD(SOUTH
), LF(ARM_STATE
), LO(INDICATOR
)),
92 DEFINE_LED(12, 2, 0, LD(NORTH
), LF(ARM_STATE
), LO(INDICATOR
)),
93 DEFINE_LED(11, 1, 0, LD(NORTH
), LF(FLIGHT_MODE
), 0),
94 DEFINE_LED(10, 0, 0, LD(NORTH
), LF(FLIGHT_MODE
), 0),
96 DEFINE_LED(7, 0, 0, LD(NORTH
), LF(FLIGHT_MODE
), LO(WARNING
)),
97 DEFINE_LED(6, 0, 1, LD(NORTH
), LF(COLOR
), LO(WARNING
)),
98 DEFINE_LED(5, 0, 1, LD(NORTH
), LF(COLOR
), LO(WARNING
)),
99 DEFINE_LED(4, 0, 0, LD(NORTH
), LF(FLIGHT_MODE
), LO(WARNING
)),
101 DEFINE_LED(2, 0, 0, LD(NORTH
), LF(FLIGHT_MODE
), 0),
102 DEFINE_LED(1, 1, 0, LD(NORTH
), LF(FLIGHT_MODE
), 0),
103 DEFINE_LED(0, 2, 0, LD(NORTH
), LF(ARM_STATE
), LO(INDICATOR
)),
104 DEFINE_LED(0, 3, 0, LD(WEST
), LF(ARM_STATE
), LO(INDICATOR
)),
105 DEFINE_LED(1, 4, 0, LD(WEST
), LF(FLIGHT_MODE
), 0),
106 DEFINE_LED(2, 5, 0, LD(WEST
), LF(FLIGHT_MODE
), 0),
108 DEFINE_LED(1, 10, 0, LD(WEST
), LF(FLIGHT_MODE
), 0),
109 DEFINE_LED(0, 11, 0, LD(WEST
), LF(ARM_STATE
), LO(INDICATOR
)),
110 DEFINE_LED(0, 11, 0, LD(SOUTH
), LF(ARM_STATE
), LO(INDICATOR
)),
111 DEFINE_LED(1, 10, 0, LD(SOUTH
), LF(FLIGHT_MODE
), LO(WARNING
)),
112 DEFINE_LED(2, 9, 0, LD(SOUTH
), LF(FLIGHT_MODE
), LO(WARNING
)),
114 DEFINE_LED(7, 7, 14, 0, LF(THRUST_RING
), 0),
115 DEFINE_LED(8, 7, 15, 0, LF(THRUST_RING
), 0),
116 DEFINE_LED(8, 8, 14, 0, LF(THRUST_RING
), 0),
117 DEFINE_LED(7, 8, 15, 0, LF(THRUST_RING
), 0),
124 const char *ledStripConfigCommands
[] = {
127 // right rear cluster
134 // right front cluster
142 // center front cluster
148 // left front cluster
171 for (uint8_t index
= 0; index
< ARRAYLEN(ledStripConfigCommands
); index
++) {
172 EXPECT_TRUE(parseLedStripConfig(index
, ledStripConfigCommands
[index
]));
176 EXPECT_EQ(30, ledCounts
.count
);
177 EXPECT_EQ(4, ledCounts
.ring
);
180 for (uint8_t index
= 0; index
< WS2811_LED_STRIP_LENGTH
; index
++) {
181 #ifdef DEBUG_LEDSTRIP
182 printf("iteration: %d\n", index
);
184 EXPECT_EQ(expectedLedStripConfig
[index
], ledStripStatusModeConfig()->ledConfigs
[index
]);
188 EXPECT_EQ(12, ledGridRows
);
191 EXPECT_EQ(5, highestXValueForWest
);
192 EXPECT_EQ(7, lowestXValueForEast
);
193 EXPECT_EQ(5, highestYValueForNorth
);
194 EXPECT_EQ(6, lowestYValueForSouth
);
197 TEST(LedStripTest
, smallestGridWithCenter
)
200 memset(&ledStripStatusModeConfigMutable()->ledConfigs
, 0, sizeof(ledStripStatusModeConfigMutable()->ledConfigs
));
203 static const ledConfig_t testLedConfigs
[] = {
204 DEFINE_LED(2, 2, 0, LD(EAST
), LF(ARM_STATE
), LO(INDICATOR
)),
205 DEFINE_LED(2, 1, 0, LD(NORTH
) | LD(EAST
), LF(FLIGHT_MODE
), LO(WARNING
)),
206 DEFINE_LED(2, 0, 0, LD(NORTH
), LF(ARM_STATE
), LO(INDICATOR
)),
207 DEFINE_LED(1, 0, 0, LD(NORTH
) | LD(WEST
), LF(FLIGHT_MODE
), LO(WARNING
)),
208 DEFINE_LED(0, 0, 0, LD(WEST
), LF(ARM_STATE
), LO(INDICATOR
)),
209 DEFINE_LED(0, 1, 0, LD(SOUTH
) | LD(WEST
), LF(FLIGHT_MODE
), LO(WARNING
)),
210 DEFINE_LED(0, 2, 0, LD(SOUTH
), LF(ARM_STATE
), LO(INDICATOR
))
212 memcpy(&ledStripStatusModeConfigMutable()->ledConfigs
, &testLedConfigs
, sizeof(testLedConfigs
));
215 reevaluateLedConfig();
218 EXPECT_EQ(3, ledGridRows
);
219 EXPECT_EQ(0, highestXValueForWest
);
220 EXPECT_EQ(2, lowestXValueForEast
);
221 EXPECT_EQ(0, highestYValueForNorth
);
222 EXPECT_EQ(2, lowestYValueForSouth
);
225 TEST(LedStripTest
, smallestGrid
)
228 memset(&ledStripStatusModeConfigMutable()->ledConfigs
, 0, sizeof(ledStripStatusModeConfigMutable()->ledConfigs
));
231 static const ledConfig_t testLedConfigs
[] = {
232 DEFINE_LED(1, 1, 0, LD(SOUTH
) | LD(EAST
), LF(FLIGHT_MODE
), LO(INDICATOR
)),
233 DEFINE_LED(1, 0, 0, LD(NORTH
) | LD(EAST
), LF(FLIGHT_MODE
), LO(INDICATOR
)),
234 DEFINE_LED(0, 0, 0, LD(NORTH
) | LD(WEST
), LF(FLIGHT_MODE
), LO(INDICATOR
)),
235 DEFINE_LED(0, 1, 0, LD(SOUTH
) | LD(WEST
), LF(FLIGHT_MODE
), LO(INDICATOR
))
237 memcpy(&ledStripStatusModeConfigMutable()->ledConfigs
, &testLedConfigs
, sizeof(testLedConfigs
));
240 reevaluateLedConfig();
243 EXPECT_EQ(2, ledGridRows
);
244 EXPECT_EQ(0, highestXValueForWest
);
245 EXPECT_EQ(1, lowestXValueForEast
);
246 EXPECT_EQ(0, highestYValueForNorth
);
247 EXPECT_EQ(1, lowestYValueForSouth
);
250 hsvColor_t testColors
[LED_CONFIGURABLE_COLOR_COUNT
];
252 extern hsvColor_t
*colors
;
254 #define TEST_COLOR_COUNT 4
256 TEST(ColorTest
, parseColor
)
259 memset(ledStripStatusModeConfigMutable()->colors
, 0, sizeof(hsvColor_t
) * LED_CONFIGURABLE_COLOR_COUNT
);
262 const hsvColor_t expectedColors
[TEST_COLOR_COUNT
] = {
270 const char *testColors
[TEST_COLOR_COUNT
] = {
278 for (uint8_t index
= 0; index
< TEST_COLOR_COUNT
; index
++) {
279 #ifdef DEBUG_LEDSTRIP
280 printf("parse iteration: %d\n", index
);
283 parseColor(index
, testColors
[index
]);
288 for (uint8_t index
= 0; index
< TEST_COLOR_COUNT
; index
++) {
289 #ifdef DEBUG_LEDSTRIP
290 printf("iteration: %d\n", index
);
293 EXPECT_EQ(expectedColors
[index
].h
, ledStripStatusModeConfig()->colors
[index
].h
);
294 EXPECT_EQ(expectedColors
[index
].s
, ledStripStatusModeConfig()->colors
[index
].s
);
295 EXPECT_EQ(expectedColors
[index
].v
, ledStripStatusModeConfig()->colors
[index
].v
);
301 uint8_t armingFlags
= 0;
302 uint8_t stateFlags
= 0;
303 uint16_t flightModeFlags
= 0;
305 float rcData
[MAX_SUPPORTED_RC_CHANNEL_COUNT
];
306 extern boxBitmask_t rcModeActivationMask
;
307 gpsSolutionData_t gpsSol
;
309 batteryState_e
getBatteryState(void)
314 void ws2811LedStripInit(ioTag_t ioTag
)
319 bool ws2811UpdateStrip(ledStripFormatRGB_e
, uint8_t) {return true;}
321 void setLedValue(uint16_t index
, const uint8_t value
)
327 void setLedHsv(uint16_t index
, const hsvColor_t
*color
)
333 void getLedHsv(uint16_t index
, hsvColor_t
*color
)
340 void scaleLedValue(uint16_t index
, const uint8_t scalePercent
)
343 UNUSED(scalePercent
);
346 void setStripColor(const hsvColor_t
*color
)
351 void setStripColors(const hsvColor_t
*colors
)
356 bool isWS2811LedStripReady(void) { return false; }
358 void delay(uint32_t ms
)
364 uint32_t micros(void) { return 0; }
366 uint32_t millis(void) { return 0; }
368 bool shouldSoundBatteryAlarm(void) { return false; }
369 bool featureIsEnabled(uint32_t mask
)
375 void tfp_sprintf(char *, char*, ...) { }
377 int scaleRange(int x
, int srcMin
, int srcMax
, int destMin
, int destMax
)
388 bool failsafeIsActive() { return false; }
389 bool isRxReceivingSignal() { return true; }
391 bool isBeeperOn() { return false; };
393 uint8_t calculateBatteryPercentageRemaining() { return 0; }
394 uint32_t getEstimatedAltitudeCm() { return 0; }
396 bool sensors(uint32_t mask
)
402 bool isArmingDisabled(void) { return false; }
404 uint8_t getRssiPercent(void) { return 0; }
406 bool isCrashFlipModeActive(void) { return false; }
408 void ws2811LedStripEnable(void) { }
410 void setUsedLedCount(unsigned) { }
411 void pinioBoxTaskControl(void) {}
412 void rescheduleTask(taskId_e
, timeDelta_t
){}
413 void schedulerIgnoreTaskExecTime(void) {}
414 void schedulerIgnoreTaskExecRate(void) {}
415 bool schedulerGetIgnoreTaskExecTime() { return false; }
416 void schedulerSetNextStateTime(timeDelta_t
) {}