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/>.
28 #include "build/version.h"
31 #include "cli/settings.h"
32 #include "common/printf.h"
33 #include "common/maths.h"
34 #include "common/gps_conversion.h"
35 #include "config/feature.h"
36 #include "drivers/buf_writer.h"
37 #include "drivers/vtx_common.h"
38 #include "config/config.h"
39 #include "fc/rc_adjustments.h"
40 #include "fc/runtime_config.h"
41 #include "flight/mixer.h"
42 #include "flight/pid.h"
43 #include "flight/servos.h"
44 #include "io/beeper.h"
45 #include "io/ledstrip.h"
46 #include "io/serial.h"
49 #include "msp/msp_box.h"
52 #include "pg/gps_rescue.h"
53 #include "pg/pg_ids.h"
54 #include "pg/beeper.h"
59 #include "scheduler/scheduler.h"
60 #include "sensors/battery.h"
61 #include "sensors/gyro.h"
63 void cliSet(const char *cmdName
, char *cmdline
);
64 int cliGetSettingIndex(char *name
, uint8_t length
);
65 void *cliGetValuePointer(const clivalue_t
*value
);
67 const clivalue_t valueTable
[] = {
68 { .name
= "array_unit_test", .type
= VAR_INT8
| MODE_ARRAY
| MASTER_VALUE
, .config
= { .array
= { .length
= 3}}, .pgn
= PG_RESERVED_FOR_TESTING_1
, .offset
= 0 },
69 { .name
= "str_unit_test", .type
= VAR_UINT8
| MODE_STRING
| MASTER_VALUE
, .config
= { .string
= { 0, 16, 0 }}, .pgn
= PG_RESERVED_FOR_TESTING_1
, .offset
= 0 },
70 { .name
= "wos_unit_test", .type
= VAR_UINT8
| MODE_STRING
| MASTER_VALUE
, .config
= { .string
= { 0, 16, STRING_FLAGS_WRITEONCE
}}, .pgn
= PG_RESERVED_FOR_TESTING_1
, .offset
= 0 },
72 const uint16_t valueTableEntryCount
= ARRAYLEN(valueTable
);
73 const lookupTableEntry_t lookupTables
[] = {};
74 const char * const lookupTableOsdDisplayPortDevice
[] = {};
75 const char * const buildKey
= NULL
;
76 const char * const releaseName
= NULL
;
79 PG_REGISTER(osdConfig_t
, osdConfig
, PG_OSD_CONFIG
, 0);
80 PG_REGISTER(batteryConfig_t
, batteryConfig
, PG_BATTERY_CONFIG
, 0);
81 PG_REGISTER(ledStripConfig_t
, ledStripConfig
, PG_LED_STRIP_CONFIG
, 0);
82 PG_REGISTER(ledStripStatusModeConfig_t
, ledStripStatusModeConfig
, PG_LED_STRIP_STATUS_MODE_CONFIG
, 0);
83 PG_REGISTER(systemConfig_t
, systemConfig
, PG_SYSTEM_CONFIG
, 0);
84 PG_REGISTER(pilotConfig_t
, pilotConfig
, PG_PILOT_CONFIG
, 0);
85 PG_REGISTER_ARRAY(adjustmentRange_t
, MAX_ADJUSTMENT_RANGE_COUNT
, adjustmentRanges
, PG_ADJUSTMENT_RANGE_CONFIG
, 0);
86 PG_REGISTER_ARRAY(modeActivationCondition_t
, MAX_MODE_ACTIVATION_CONDITION_COUNT
, modeActivationConditions
, PG_MODE_ACTIVATION_PROFILE
, 0);
87 PG_REGISTER(mixerConfig_t
, mixerConfig
, PG_MIXER_CONFIG
, 0);
88 PG_REGISTER_ARRAY(motorMixer_t
, MAX_SUPPORTED_MOTORS
, customMotorMixer
, PG_MOTOR_MIXER
, 0);
89 PG_REGISTER_ARRAY(servoParam_t
, MAX_SUPPORTED_SERVOS
, servoParams
, PG_SERVO_PARAMS
, 0);
90 PG_REGISTER_ARRAY(servoMixer_t
, MAX_SERVO_RULES
, customServoMixers
, PG_SERVO_MIXER
, 0);
91 PG_REGISTER(beeperConfig_t
, beeperConfig
, PG_BEEPER_CONFIG
, 0);
92 PG_REGISTER(rxConfig_t
, rxConfig
, PG_RX_CONFIG
, 0);
93 PG_REGISTER(serialConfig_t
, serialConfig
, PG_SERIAL_CONFIG
, 0);
94 PG_REGISTER_ARRAY(rxChannelRangeConfig_t
, NON_AUX_CHANNEL_COUNT
, rxChannelRangeConfigs
, PG_RX_CHANNEL_RANGE_CONFIG
, 0);
95 PG_REGISTER_ARRAY(rxFailsafeChannelConfig_t
, MAX_SUPPORTED_RC_CHANNEL_COUNT
, rxFailsafeChannelConfigs
, PG_RX_FAILSAFE_CHANNEL_CONFIG
, 0);
96 PG_REGISTER(pidConfig_t
, pidConfig
, PG_PID_CONFIG
, 0);
97 PG_REGISTER(gyroConfig_t
, gyroConfig
, PG_GYRO_CONFIG
, 0);
98 PG_REGISTER(gpsConfig_t
, gpsConfig
, PG_GPS_CONFIG
, 0);
99 PG_REGISTER(gpsRescueConfig_t
, gpsRescueConfig
, PG_GPS_RESCUE
, 0);
101 PG_REGISTER_WITH_RESET_FN(int8_t, unitTestData
, PG_RESERVED_FOR_TESTING_1
, 0);
104 #include "unittest_macros.h"
105 #include "gtest/gtest.h"
107 const bool PRINT_TEST_DATA
= false;
109 TEST(CLIUnittest
, TestCliSetArray
)
111 char *str
= (char *)"array_unit_test = 123, -3 , 1";
114 const uint16_t index
= cliGetSettingIndex(str
, 15);
115 EXPECT_LT(index
, valueTableEntryCount
);
117 const clivalue_t val
= valueTable
[index
];
118 int8_t *data
= (int8_t *)cliGetValuePointer(&val
);
120 if (PRINT_TEST_DATA
) {
121 printf("\n===============================\n");
122 for(int i
= 0; i
< val
.config
.array
.length
; i
++){
123 printf("data[%d] = %d\n", i
, data
[i
]);
125 printf("\n===============================\n");
128 EXPECT_EQ(123, data
[0]);
129 EXPECT_EQ( -3, data
[1]);
130 EXPECT_EQ( 1, data
[2]);
133 TEST(CLIUnittest
, TestCliSetStringNoFlags
)
135 char *str
= (char *)"str_unit_test = SAMPLE";
138 const uint16_t index
= cliGetSettingIndex(str
, 13);
139 EXPECT_LT(index
, valueTableEntryCount
);
141 const clivalue_t val
= valueTable
[index
];
142 uint8_t *data
= (uint8_t *)cliGetValuePointer(&val
);
144 if (PRINT_TEST_DATA
) {
145 printf("\n===============================\n");
146 for(int i
= 0; i
< val
.config
.string
.maxlength
&& data
[i
] != 0; i
++){
147 printf("data[%d] = %d (%c)\n", i
, data
[i
], data
[i
]);
149 printf("\n===============================\n");
152 EXPECT_EQ('S', data
[0]);
153 EXPECT_EQ('A', data
[1]);
154 EXPECT_EQ('M', data
[2]);
155 EXPECT_EQ('P', data
[3]);
156 EXPECT_EQ('L', data
[4]);
157 EXPECT_EQ('E', data
[5]);
158 EXPECT_EQ(0, data
[6]);
161 TEST(CLIUnittest
, TestCliSetStringWriteOnce
)
163 char *str1
= (char *)"wos_unit_test = SAMPLE";
164 char *str2
= (char *)"wos_unit_test = ELPMAS";
167 const uint16_t index
= cliGetSettingIndex(str1
, 13);
168 EXPECT_LT(index
, valueTableEntryCount
);
170 const clivalue_t val
= valueTable
[index
];
172 uint8_t *data
= (uint8_t *)cliGetValuePointer(&val
);
173 if (PRINT_TEST_DATA
) {
174 printf("\n===============================\n");
175 for(int i
= 0; i
< val
.config
.string
.maxlength
&& data
[i
] != 0; i
++){
176 printf("data[%d] = %d (%c)\n", i
, data
[i
], data
[i
]);
178 printf("\n===============================\n");
180 EXPECT_EQ('S', data
[0]);
181 EXPECT_EQ('A', data
[1]);
182 EXPECT_EQ('M', data
[2]);
183 EXPECT_EQ('P', data
[3]);
184 EXPECT_EQ('L', data
[4]);
185 EXPECT_EQ('E', data
[5]);
186 EXPECT_EQ(0, data
[6]);
190 EXPECT_EQ('S', data
[0]);
191 EXPECT_EQ('A', data
[1]);
192 EXPECT_EQ('M', data
[2]);
193 EXPECT_EQ('P', data
[3]);
194 EXPECT_EQ('L', data
[4]);
195 EXPECT_EQ('E', data
[5]);
196 EXPECT_EQ(0, data
[6]);
200 EXPECT_EQ('S', data
[0]);
201 EXPECT_EQ('A', data
[1]);
202 EXPECT_EQ('M', data
[2]);
203 EXPECT_EQ('P', data
[3]);
204 EXPECT_EQ('L', data
[4]);
205 EXPECT_EQ('E', data
[5]);
206 EXPECT_EQ(0, data
[6]);
213 float motor_disarmed
[MAX_SUPPORTED_MOTORS
];
215 uint16_t batteryWarningVoltage
;
216 uint8_t useHottAlarmSoundPeriod (void) { return 0; }
217 const uint32_t baudRates
[] = {0, 9600, 19200, 38400, 57600, 115200, 230400, 250000, 400000}; // see baudRate_e
220 int32_t schedLoopStartCycles
;
221 int32_t taskGuardCycles
;
223 uint32_t micros(void) {return 0;}
225 int32_t getAmperage(void)
230 uint16_t getBatteryVoltage(void)
235 batteryState_e
getBatteryState(void)
240 uint8_t calculateBatteryPercentageRemaining(void)
245 uint8_t getMotorCount()
250 size_t getEEPROMStorageSize()
256 void setPrintfSerialPort(struct serialPort_s
) {}
258 static const box_t boxes
[] = { { "DUMMYBOX", 0, 0 } };
259 const box_t
*findBoxByPermanentId(uint8_t) { return &boxes
[0]; }
260 const box_t
*findBoxByBoxId(boxId_e
) { return &boxes
[0]; }
262 int8_t unitTestDataArray
[3];
264 void pgResetFn_unitTestData(int8_t *)
267 uint32_t getBeeperOffMask(void) { return 0; }
268 uint32_t getPreferredBeeperOffMask(void) { return 0; }
270 void beeper(beeperMode_e
) {}
271 void beeperSilence(void) {}
272 void beeperConfirmationBeeps(uint8_t) {}
273 void beeperWarningBeeps(uint8_t) {}
274 void beeperUpdate(timeUs_t
) {}
275 uint32_t getArmingBeepTimeMicros(void) {return 0;}
276 beeperMode_e
beeperModeForTableIndex(int) {return BEEPER_SILENCE
;}
277 uint32_t beeperModeMaskForTableIndex(int idx
) {UNUSED(idx
); return 0;}
278 const char *beeperNameForTableIndex(int) {return NULL
;}
279 int beeperTableEntryCount(void) {return 0;}
280 bool isBeeperOn(void) {return false;}
281 void beeperOffSetAll(uint8_t) {}
282 void setBeeperOffMask(uint32_t) {}
283 void setPreferredBeeperOffMask(uint32_t) {}
285 void beeperOffSet(uint32_t) {}
286 void beeperOffClear(uint32_t) {}
287 void beeperOffClearAll(void) {}
288 bool parseColor(int, const char *) {return false; }
289 bool resetEEPROM(void) { return true; }
290 void bufWriterFlush(bufWriter_t
*) {}
291 void mixerResetDisarmedMotors(void) {}
297 void dashboardShowFixedPage(pageId_e
){}
298 void dashboardUpdate(timeUs_t
) {}
300 bool parseLedStripConfig(int, const char *){return false; }
301 const char rcChannelLetters
[] = "AERT12345678abcdefgh";
303 void parseRcChannels(const char *, rxConfig_t
*){}
304 void mixerLoadMix(int, motorMixer_t
*) {}
305 bool setModeColor(ledModeIndex_e
, int, int) { return false; }
306 float motorConvertFromExternal(uint16_t) { return 1.0; }
307 void motorShutdown(void) { }
308 uint8_t getCurrentPidProfileIndex(void){ return 1; }
309 uint8_t getCurrentControlRateProfileIndex(void){ return 1; }
310 void changeControlRateProfile(uint8_t) {}
311 void resetAllRxChannelRangeConfigurations(rxChannelRangeConfig_t
*) {}
312 void writeEEPROM() {}
313 serialPortConfig_t
*serialFindPortConfigurationMutable(serialPortIdentifier_e
) {return NULL
; }
314 baudRate_e
lookupBaudRateIndex(uint32_t){return BAUD_9600
; }
315 serialPortUsage_t
*findSerialPortUsageByIdentifier(serialPortIdentifier_e
){ return NULL
; }
316 serialPort_t
*openSerialPort(serialPortIdentifier_e
, serialPortFunction_e
, serialReceiveCallbackPtr
, void *, uint32_t, portMode_e
, portOptions_e
) { return NULL
; }
317 const serialPortConfig_t
*findSerialPortConfig(serialPortFunction_e
) { return NULL
; }
318 void serialPassthrough(serialPort_t
*, serialPort_t
*, serialConsumer
*, serialConsumer
*) {}
319 uint32_t millis(void) { return 0; }
320 uint8_t getBatteryCellCount(void) { return 1; }
321 void servoMixerLoadMix(int) {}
322 const char * getBatteryStateString(void){ return "_getBatteryStateString_"; }
324 uint32_t stackTotalSize(void) { return 0x4000; }
325 uint32_t stackHighMem(void) { return 0x80000000; }
326 uint16_t getEEPROMConfigSize(void) { return 1024; }
328 uint8_t __config_start
= 0x00;
329 uint8_t __config_end
= 0x10;
330 uint16_t averageSystemLoadPercent
= 0;
332 timeDelta_t
getTaskDeltaTimeUs(taskId_e
){ return 0; }
333 uint16_t currentRxIntervalUs
= 9000;
335 /*const char *armingDisableFlagNames[]= {
336 "DUMMYDISABLEFLAGNAME"
339 void getTaskInfo(taskId_e
, taskInfo_t
*) {}
340 void getCheckFuncInfo(cfCheckFuncInfo_t
*) {}
341 void schedulerResetTaskMaxExecutionTime(taskId_e
) {}
342 void schedulerResetCheckFunctionMaxExecutionTime(void) {}
344 const char * const targetName
= "UNITTEST";
345 const char* const buildDate
= "Jan 01 2017";
346 const char * const buildTime
= "00:00:00";
347 const char * const shortGitRevision
= "MASTER";
349 //uint32_t serialRxBytesWaiting(const serialPort_t *) {return 0;}
350 //uint8_t serialRead(serialPort_t *){return 0;}
352 void bufWriterAppend(bufWriter_t
*, uint8_t ch
){ printf("%c", ch
); }
353 //void serialWriteBufShim(void *, const uint8_t *, int) {}
354 void bufWriterInit(bufWriter_t
*, uint8_t *, int, bufWrite_t
, void *) { }
355 //void setArmingDisabled(armingDisableFlags_e) {}
357 void waitForSerialPortToFinishTransmitting(serialPort_t
*) {}
358 void systemResetToBootloader(void) {}
359 void resetConfig(void) {}
360 void systemReset(void) {}
361 void writeUnmodifiedConfigToEEPROM(void) {}
363 void changePidProfile(uint8_t) {}
364 bool serialIsPortAvailable(serialPortIdentifier_e
) { return false; }
365 void generateLedConfig(ledConfig_t
*, char *, size_t) {}
366 //bool isSerialTransmitBufferEmpty(const serialPort_t *) {return true; }
367 //void serialWrite(serialPort_t *, uint8_t ch) { printf("%c", ch);}
369 //void serialSetCtrlLineStateCb(serialPort_t *, void (*)(void *, uint16_t ), void *) {}
370 void serialSetCtrlLineStateDtrPin(serialPort_t
*, ioTag_t
) {}
371 void serialSetCtrlLineState(serialPort_t
*, uint16_t ) {}
373 serialPortIdentifier_e
findSerialPortByName(const char* portName
, int (*cmp
)(const char *portName
, const char *candidate
))
377 return SERIAL_PORT_NONE
;
380 const char* serialName(serialPortIdentifier_e identifier
, const char* notFound
)
386 //void serialSetBaudRateCb(serialPort_t *, void (*)(serialPort_t *context, uint32_t baud), serialPort_t *) {}
387 void rescheduleTask(taskId_e
, timeDelta_t
){}
388 void schedulerSetNextStateTime(timeDelta_t
){}
389 char *getBoardName(void) { return NULL
; }
390 char *getManufacturerId(void) { return NULL
; }
391 bool boardInformationIsSet(void) { return true; }
393 bool setBoardName(char *newBoardName
) { UNUSED(newBoardName
); return true; };
394 bool setManufacturerId(char *newManufacturerId
) { UNUSED(newManufacturerId
); return true; };
395 bool persistBoardInformation(void) { return true; };
397 void activeAdjustmentRangeReset(void) {}
398 void analyzeModeActivationConditions(void) {}
399 bool isModeActivationConditionConfigured(const modeActivationCondition_t
*, const modeActivationCondition_t
*) { return false; }
401 void delay(uint32_t) {}
402 displayPort_t
*osdGetDisplayPort(osdDisplayPortDevice_e
*) { return NULL
; }
403 mcuTypeId_e
getMcuTypeId(void) { return MCU_TYPE_UNKNOWN
; }
404 uint16_t getCurrentRxRateHz(void) { return 0; }
405 uint16_t getAverageSystemLoadPercent(void) { return 0; }
406 bool getRxRateValid(void) { return false; }