/* * Authors (alphabetical order) * - Andre Bernet * - Andreas Weitl * - Bertrand Songis * - Bryan J. Rentoul (Gruvin) * - Cameron Weeks * - Erez Raviv * - Gabriel Birkus * - Jean-Pierre Parisy * - Karl Szmutny * - Michael Blandford * - Michal Hlavinka * - Pat Mackenzie * - Philip Moss * - Rob Thomson * - Romolo Manfredini * - Thomas Husterer * * opentx is based on code named * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, * er9x by Erez Raviv: http://code.google.com/p/er9x/, * and the original (and ongoing) project by * Thomas Husterer, th9x: http://code.google.com/p/th9x/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include #include #include "opentx.h" #define CHANNEL_MAX (1024*256) void doMixerCalculations(); #define MODEL_RESET() memset(&g_model, 0, sizeof(g_model)) #define MIXER_RESET() \ memset(channelOutputs, 0, sizeof(channelOutputs)); \ memset(ex_chans, 0, sizeof(ex_chans)); \ memset(act, 0, sizeof(act)); \ memset(swOn, 0, sizeof(swOn)); \ int32_t lastAct = 0; lastAct = lastAct; /* to avoid a warning */ uint16_t anaInValues[NUM_STICKS+NUM_POTS] = { 0 }; uint16_t anaIn(uint8_t chan) { if (chan < NUM_STICKS+NUM_POTS) return anaInValues[chan]; else return 0; } TEST(Trims, greaterTrimLink) { MODEL_RESET(); setTrimValue(1, 0, TRIM_EXTENDED_MAX+3); // link to FP3 trim setTrimValue(3, 0, 32); EXPECT_EQ(getRawTrimValue(getTrimFlightPhase(1, 0), 0), 32); } TEST(Trims, chainedTrims) { MODEL_RESET(); setTrimValue(0, 0, 32); setTrimValue(1, 0, TRIM_EXTENDED_MAX+1); // link to FP0 trim setTrimValue(2, 0, TRIM_EXTENDED_MAX+2); // link to FP1 trim EXPECT_EQ(getRawTrimValue(getTrimFlightPhase(0, 2), 0), 32); } TEST(Trims, infiniteChainedTrims) { MODEL_RESET(); setTrimValue(0, 0, 32); setTrimValue(1, 0, TRIM_EXTENDED_MAX+3); // link to FP3 trim setTrimValue(2, 0, TRIM_EXTENDED_MAX+2); // link to FP1 trim setTrimValue(3, 0, TRIM_EXTENDED_MAX+3); // link to FP2 trim EXPECT_EQ(getRawTrimValue(getTrimFlightPhase(0, 2), 0), 32); } TEST(outdezNAtt, test_unsigned) { uint16_t altitude = 65530; uint8_t refBuf[sizeof(displayBuf)]; memset(displayBuf, 0, sizeof(displayBuf)); lcd_putc(0*FWNUM, 0, '6'); lcd_putc(1*FWNUM, 0, '5'); lcd_putc(2*FWNUM, 0, '5'); lcd_putc(3*FWNUM, 0, '3'); lcd_putc(4*FWNUM, 0, '0'); memcpy(refBuf, displayBuf, sizeof(displayBuf)); memset(displayBuf, 0, sizeof(displayBuf)); lcd_outdezNAtt(1, 0, altitude, LEFT|UNSIGN); EXPECT_EQ(memcmp(refBuf, displayBuf, sizeof(displayBuf)), 0) << "Unsigned numbers will be bad displayed"; } TEST(EEPROM, 1000_random_writes) { eepromFile = NULL; // in memory RlcFile f; uint8_t buf[1000]; uint8_t buf2[1000]; EeFsFormat(); for(int i=0; i<1000; i++) { int size = rand()%800; for(int j=0; j> 8)); \ } \ } while (0) #define CHECK_DELAY(channel, duration) \ do { \ int32_t value = chans[(channel)]; \ for (int i=1; i<=(duration); i++) { \ perOut(e_perout_mode_normal, 1); \ EXPECT_EQ(chans[(channel)], value); \ } \ } while (0) TEST(Mixer, SlowOnSwitch) { MODEL_RESET(); MIXER_RESET(); g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; g_model.mixData[0].weight = 100; g_model.mixData[0].swtch = SWSRC_THR; g_model.mixData[0].speedUp = 10; g_model.mixData[0].speedDown = 10; perOut(e_perout_mode_normal, 0); EXPECT_EQ(chans[0], 0); simuSetSwitch(0, 1); CHECK_SLOW_MOVEMENT(0, +1, 250); simuSetSwitch(0, 0); CHECK_SLOW_MOVEMENT(0, -1, 250); } TEST(Mixer, SlowOnPhase) { MODEL_RESET(); MIXER_RESET(); g_model.phaseData[1].swtch = SWSRC_THR; g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; g_model.mixData[0].weight = 100; g_model.mixData[0].phases = 0x2 + 0x4 + 0x8 + 0x10 /*only enabled in phase 0*/; g_model.mixData[0].speedUp = 10; g_model.mixData[0].speedDown = 10; s_perout_flight_phase = 0; perOut(e_perout_mode_normal, 0); EXPECT_EQ(chans[0], 0); CHECK_SLOW_MOVEMENT(0, +1, 250); s_perout_flight_phase = 1; CHECK_SLOW_MOVEMENT(0, -1, 250); } TEST(Mixer, SlowOnSwitchAndPhase) { MODEL_RESET(); MIXER_RESET(); g_model.phaseData[1].swtch = SWSRC_THR; g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_MAX; g_model.mixData[0].weight = 100; g_model.mixData[0].swtch = SWSRC_THR; g_model.mixData[0].phases = 0x2 + 0x4 + 0x8 + 0x10 /*only enabled in phase 0*/; g_model.mixData[0].speedUp = 10; g_model.mixData[0].speedDown = 10; perOut(e_perout_mode_normal, 0); EXPECT_EQ(chans[0], 0); simuSetSwitch(0, 1); s_perout_flight_phase = 0; CHECK_SLOW_MOVEMENT(0, +1, 250); simuSetSwitch(0, 0); s_perout_flight_phase = 1; CHECK_SLOW_MOVEMENT(0, -1, 250); } TEST(Mixer, SlowOnSwitchSource) { MODEL_RESET(); MIXER_RESET(); g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_THR; g_model.mixData[0].weight = 100; g_model.mixData[0].speedUp = 10; g_model.mixData[0].speedDown = 10; simuSetSwitch(0, 0); CHECK_SLOW_MOVEMENT(0, -1, 250); EXPECT_EQ(chans[0], -CHANNEL_MAX); simuSetSwitch(0, 1); CHECK_SLOW_MOVEMENT(0, +1, 500); } TEST(Mixer, SlowAndDelayOnReplace3POSSource) { MODEL_RESET(); MIXER_RESET(); g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_REP; g_model.mixData[0].srcRaw = MIXSRC_3POS; g_model.mixData[0].weight = 100; g_model.mixData[0].delayUp = 10; g_model.mixData[0].speedUp = 10; g_model.mixData[0].speedDown = 10; simuSetSwitch(3, -1); CHECK_SLOW_MOVEMENT(0, -1, 250); EXPECT_EQ(chans[0], -CHANNEL_MAX); simuSetSwitch(3, 0); CHECK_DELAY(0, 500); CHECK_SLOW_MOVEMENT(0, +1, 250/*half course*/); EXPECT_EQ(chans[0], 0); simuSetSwitch(3, 1); CHECK_DELAY(0, 500); CHECK_SLOW_MOVEMENT(0, +1, 250); } TEST(Mixer, NoTrimOnInactiveMix) { MODEL_RESET(); MIXER_RESET(); g_model.mixData[0].destCh = 0; g_model.mixData[0].mltpx = MLTPX_ADD; g_model.mixData[0].srcRaw = MIXSRC_Thr; g_model.mixData[0].weight = 100; g_model.mixData[0].swtch = SWSRC_THR; g_model.mixData[0].speedUp = 10; g_model.mixData[0].speedDown = 10; setTrimValue(0, 2, 256); simuSetSwitch(0, 1); CHECK_SLOW_MOVEMENT(0, 1, 100); simuSetSwitch(0, 0); CHECK_SLOW_MOVEMENT(0, -1, 100); } TEST(Curves, LinearIntpol) { MODEL_RESET(); for (int8_t i=-2; i<=2; i++) { g_model.points[2+i] = 50*i; } EXPECT_EQ(intpol(-1024, 0), -1024); EXPECT_EQ(intpol(0, 0), 0); EXPECT_EQ(intpol(1024, 0), 1024); EXPECT_EQ(intpol(-192, 0), -192); } int main(int argc, char **argv) { StartEepromThread(NULL); g_menuStackPtr = 0; g_menuStack[0] = menuMainView; ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }