From 3700047d2cd67d4259ad71629b7159dac4676bd6 Mon Sep 17 00:00:00 2001 From: Damjan Adamic Date: Wed, 9 Jul 2014 14:18:39 +0200 Subject: [PATCH] Re #1409 and #1444: * added support for two FLVSS * added gtests for FLVSS --- radio/src/telemetry/frsky_sport.cpp | 19 +- radio/src/tests/frsky.cpp | 234 +++++++++++++++++- .../one_sensor_votages_screen_212x64.png | Bin 0 -> 640 bytes .../two_sensor_votages_screen_212x64.png | Bin 0 -> 706 bytes 4 files changed, 239 insertions(+), 14 deletions(-) create mode 100644 radio/src/tests/one_sensor_votages_screen_212x64.png create mode 100644 radio/src/tests/two_sensor_votages_screen_212x64.png diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp index 7ad91b634..daa63d50d 100644 --- a/radio/src/telemetry/frsky_sport.cpp +++ b/radio/src/telemetry/frsky_sport.cpp @@ -279,6 +279,8 @@ bool checkSportPacket(uint8_t *packet) #define SPORT_DATA_U32(packet) (*((uint32_t *)(packet+4))) #define HUB_DATA_U16(packet) (*((uint16_t *)(packet+4))) +uint8_t noCellsSensor[2]; + void frskySportProcessPacket(uint8_t *packet) { uint8_t dataId = packet[0]; @@ -463,9 +465,18 @@ void frskySportProcessPacket(uint8_t *packet) uint32_t data = SPORT_DATA_U32(packet); uint8_t battnumber = data & 0xF; uint8_t cells = (data & 0xF0) >> 4; + bool useSecondCell = (battnumber+1 < cells); - if (dataId != DATA_ID_FLVSS) { - // TODO second sensor connected + if (dataId == DATA_ID_FLVSS) { + // first sensor, remember its cell count + noCellsSensor[0] = cells; + cells += noCellsSensor[1]; + } + else { + // second sensor connected + noCellsSensor[1] = cells; + cells += noCellsSensor[0]; + battnumber += noCellsSensor[0]; } if (cells != frskyData.hub.cellsCount) { @@ -473,7 +484,9 @@ void frskySportProcessPacket(uint8_t *packet) } frskySetCellVoltage(battnumber, (frskyCellVoltage_t) ((data & 0x000FFF00) >> 8) / 5); - frskySetCellVoltage(battnumber+1, (frskyCellVoltage_t) ((data & 0xFFF00000) >> 20) / 5); + if (useSecondCell) { + frskySetCellVoltage(battnumber+1, (frskyCellVoltage_t) ((data & 0xFFF00000) >> 20) / 5); + } } break; } diff --git a/radio/src/tests/frsky.cpp b/radio/src/tests/frsky.cpp index f6ae8e873..11e482b73 100644 --- a/radio/src/tests/frsky.cpp +++ b/radio/src/tests/frsky.cpp @@ -44,6 +44,7 @@ #define SWAP_DEFINED #include "opentx.h" +extern bool checkScreenshot(QString test); #if defined(FRSKY) && !defined(FRSKY_SPORT) extern void frskyDProcessPacket(uint8_t *packet); @@ -93,17 +94,6 @@ TEST(FrSky, dateNtime) } #endif -#if defined(FRSKY_SPORT) -extern bool checkSportPacket(uint8_t *packet); -TEST(FrSkySPORT, checkCrc) -{ - // uint8_t pkt[] = { 0x7E, 0x98, 0x10, 0x10, 0x00, 0x7D, 0x5E, 0x02, 0x00, 0x00, 0x5F }; - uint8_t pkt[] = { 0x7E, 0x98, 0x10, 0x10, 0x00, 0x7E, 0x02, 0x00, 0x00, 0x5F }; - EXPECT_EQ(checkSportPacket(pkt+1), true); -} -#endif - - #if defined(FRSKY) && defined(CPUARM) TEST(FrSky, FrskyValueWithMinAveraging) { @@ -131,3 +121,225 @@ TEST(FrSky, FrskyValueWithMinAveraging) } } #endif + + + +#if defined(FRSKY_SPORT) +extern bool checkSportPacket(uint8_t *packet); +TEST(FrSkySPORT, checkCrc) +{ + // uint8_t pkt[] = { 0x7E, 0x98, 0x10, 0x10, 0x00, 0x7D, 0x5E, 0x02, 0x00, 0x00, 0x5F }; + uint8_t pkt[] = { 0x7E, 0x98, 0x10, 0x10, 0x00, 0x7E, 0x02, 0x00, 0x00, 0x5F }; + EXPECT_EQ(checkSportPacket(pkt+1), true); +} + +extern void frskySportProcessPacket(uint8_t *packet); +extern bool checkSportPacket(uint8_t *packet); +extern void frskyCalculateCellStats(void); +extern void displayVoltagesScreen(); + +void setSportPacketCrc(uint8_t * packet) +{ + short crc = 0; + for (int i=1; i> 8; //0-100 + crc &= 0x00ff; + crc += crc >> 8; //0-0FF + crc &= 0x00ff; + } + packet[FRSKY_SPORT_PACKET_SIZE-1] = 0xFF - (crc & 0x00ff); + //TRACE("crc set: %x", packet[FRSKY_SPORT_PACKET_SIZE-1]); +} + +void generateSportCellPacket(uint8_t * packet, uint8_t cells, uint8_t battnumber, uint16_t cell1, uint16_t cell2) +{ + if (battnumber < 6) { + packet[0] = 0xA1; //DATA_ID_FLVSS; + } + else { + packet[0] = 0xA1+1; //DATA_ID_FLVSS+1; + battnumber -= 6; + } + packet[1] = 0x10; //DATA_FRAME + *((uint16_t *)(packet+2)) = 0x0300; //CELLS_FIRST_ID + uint32_t data = 0; + data += (cells << 4) + battnumber; + data += ((cell1 * 5) & 0xFFF) << 8; + data += ((cell2 * 5) & 0xFFF) << 20; + *((int32_t *)(packet+4)) = data; + setSportPacketCrc(packet); +} + +#define _V(volts) (volts/TELEMETRY_CELL_VOLTAGE_MUTLIPLIER) + +TEST(FrSkySPORT, frskySetCellVoltage) +{ + memclear(&frskyData, sizeof(frskyData)); + uint8_t packet[FRSKY_SPORT_PACKET_SIZE]; + + //test that simulates 3 cell battery + generateSportCellPacket(packet, 3, 0, _V(410), _V(420)); frskySportProcessPacket(packet); + EXPECT_EQ(checkSportPacket(packet), true) << "Bad CRC generation in setSportPacketCrc()"; + generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); frskySportProcessPacket(packet); + + generateSportCellPacket(packet, 3, 0, _V(405), _V(300)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); frskySportProcessPacket(packet); + + EXPECT_EQ(frskyData.hub.cellsCount, 3); + EXPECT_EQ(frskyData.hub.cellVolts[0], _V(405)); + EXPECT_EQ(frskyData.hub.cellVolts[1], _V(300)); + EXPECT_EQ(frskyData.hub.cellVolts[2], _V(430)); + EXPECT_EQ(frskyData.hub.cellVolts[4], _V( 0)); + EXPECT_EQ(frskyData.hub.minCellVolts, _V(300)); //current minimum cell voltage + EXPECT_EQ(frskyData.hub.minCell, _V(300)); //all time minimum cell voltage + EXPECT_EQ(frskyData.hub.minCells, _V(113)); //all time cells sum minimum + EXPECT_EQ(frskyData.hub.cellsSum, _V(113)); //current cells sum + + generateSportCellPacket(packet, 3, 0, _V(405), _V(250)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); frskySportProcessPacket(packet); + + generateSportCellPacket(packet, 3, 0, _V(410), _V(420)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 3, 2, _V(430), _V( 0)); frskySportProcessPacket(packet); + + EXPECT_EQ(frskyData.hub.cellsCount, 3); + EXPECT_EQ(frskyData.hub.cellVolts[0], _V(410)); + EXPECT_EQ(frskyData.hub.cellVolts[1], _V(420)); + EXPECT_EQ(frskyData.hub.cellVolts[2], _V(430)); + EXPECT_EQ(frskyData.hub.cellVolts[4], _V( 0)); + EXPECT_EQ(frskyData.hub.minCellVolts, _V(410)); //current minimum cell voltage + EXPECT_EQ(frskyData.hub.minCell, _V(250)); //all time minimum cell voltage + EXPECT_EQ(frskyData.hub.minCells, _V(108)); //all time cells sum minimum + EXPECT_EQ(frskyData.hub.cellsSum, _V(126)); //current cells sum + + //add another two cells - 5 cell battery + generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 5, 2, _V(415), _V(420)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); frskySportProcessPacket(packet); + + EXPECT_EQ(frskyData.hub.cellsCount, 5); + EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418)); + EXPECT_EQ(frskyData.hub.cellVolts[1], _V(408)); + EXPECT_EQ(frskyData.hub.cellVolts[2], _V(415)); + EXPECT_EQ(frskyData.hub.cellVolts[3], _V(420)); + EXPECT_EQ(frskyData.hub.cellVolts[4], _V(410)); + EXPECT_EQ(frskyData.hub.cellVolts[5], _V( 0)); + EXPECT_EQ(frskyData.hub.minCellVolts, _V(408)); //current minimum cell voltage + EXPECT_EQ(frskyData.hub.minCell, _V(408)); //all time minimum cell voltage + EXPECT_EQ(frskyData.hub.minCells, _V(207)); //all time cells sum minimum + EXPECT_EQ(frskyData.hub.cellsSum, _V(207)); //current cells sum + + //simulate very low voltage for cell 3 + generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 5, 2, _V(100), _V(420)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); frskySportProcessPacket(packet); + + EXPECT_EQ(frskyData.hub.cellsCount, 5); + EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418)); + EXPECT_EQ(frskyData.hub.cellVolts[1], _V(408)); + EXPECT_EQ(frskyData.hub.cellVolts[2], _V(100)); + EXPECT_EQ(frskyData.hub.cellVolts[3], _V(420)); + EXPECT_EQ(frskyData.hub.cellVolts[4], _V(410)); + EXPECT_EQ(frskyData.hub.cellVolts[5], _V( 0)); + EXPECT_EQ(frskyData.hub.minCellVolts, _V(100)); //current minimum cell voltage + EXPECT_EQ(frskyData.hub.minCell, _V(100)); //all time minimum cell voltage + EXPECT_EQ(frskyData.hub.minCells, _V(175)); //all time cells sum minimum + EXPECT_EQ(frskyData.hub.cellsSum, _V(175)); //current cells sum + + //back to normal (but with reversed order of packets) + generateSportCellPacket(packet, 5, 4, _V(410), _V( 0)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 5, 0, _V(418), _V(408)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 5, 2, _V(412), _V(420)); frskySportProcessPacket(packet); + + EXPECT_EQ(frskyData.hub.cellsCount, 5); + EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418)); + EXPECT_EQ(frskyData.hub.cellVolts[1], _V(408)); + EXPECT_EQ(frskyData.hub.cellVolts[2], _V(412)); + EXPECT_EQ(frskyData.hub.cellVolts[3], _V(420)); + EXPECT_EQ(frskyData.hub.cellVolts[4], _V(410)); + EXPECT_EQ(frskyData.hub.cellVolts[5], _V( 0)); + EXPECT_EQ(frskyData.hub.minCellVolts, _V(408)); //current minimum cell voltage + EXPECT_EQ(frskyData.hub.minCell, _V(100)); //all time minimum cell voltage + EXPECT_EQ(frskyData.hub.minCells, _V(175)); //all time cells sum minimum + EXPECT_EQ(frskyData.hub.cellsSum, _V(206)); //current cells sum + + //display test + lcd_clear(); + g_model.frsky.voltsSource = FRSKY_VOLTS_SOURCE_A1; + displayVoltagesScreen(); + EXPECT_TRUE(checkScreenshot("one_sensor_votages_screen")); +} + +TEST(FrSkySPORT, frskySetCellVoltageTwoSensors) +{ + //telemetryReset(); + memclear(&frskyData, sizeof(frskyData)); + uint8_t packet[FRSKY_SPORT_PACKET_SIZE]; + + //sensor 1: 3 cell battery + generateSportCellPacket(packet, 3, 0, _V(418), _V(416)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); frskySportProcessPacket(packet); + + EXPECT_EQ(frskyData.hub.cellsCount, 3); + EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418)); + EXPECT_EQ(frskyData.hub.cellVolts[1], _V(416)); + EXPECT_EQ(frskyData.hub.cellVolts[2], _V(415)); + EXPECT_EQ(frskyData.hub.cellVolts[3], _V( 0)); + EXPECT_EQ(frskyData.hub.minCellVolts, _V(415)); //current minimum cell voltage + EXPECT_EQ(frskyData.hub.minCell, _V(415)); //all time minimum cell voltage + EXPECT_EQ(frskyData.hub.minCells, _V(124)); //all time cells sum minimum + EXPECT_EQ(frskyData.hub.cellsSum, _V(124)); //current cells sum + + //sensor 2: 4 cell battery + generateSportCellPacket(packet, 4, 6, _V(410), _V(420)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 4, 8, _V(400), _V(405)); frskySportProcessPacket(packet); + + //we need to send all cells from first battery before a new calculation will be made + generateSportCellPacket(packet, 3, 0, _V(418), _V(416)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); frskySportProcessPacket(packet); + + EXPECT_EQ(frskyData.hub.cellsCount, 7); + EXPECT_EQ(frskyData.hub.cellVolts[0], _V(418)); + EXPECT_EQ(frskyData.hub.cellVolts[1], _V(416)); + EXPECT_EQ(frskyData.hub.cellVolts[2], _V(415)); + EXPECT_EQ(frskyData.hub.cellVolts[3], _V(410)); + EXPECT_EQ(frskyData.hub.cellVolts[4], _V(420)); + EXPECT_EQ(frskyData.hub.cellVolts[5], _V(400)); + EXPECT_EQ(frskyData.hub.cellVolts[6], _V(405)); + EXPECT_EQ(frskyData.hub.cellVolts[7], _V( 0)); + EXPECT_EQ(frskyData.hub.cellVolts[8], _V( 0)); + EXPECT_EQ(frskyData.hub.minCellVolts, _V(400)); //current minimum cell voltage + EXPECT_EQ(frskyData.hub.minCell, _V(400)); //all time minimum cell voltage + EXPECT_EQ(frskyData.hub.minCells, _V(288)); //all time cells sum minimum + EXPECT_EQ(frskyData.hub.cellsSum, _V(288)); //current cells sum + + //now change some voltages + generateSportCellPacket(packet, 3, 2, _V(415), _V( 0)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 4, 8, _V(390), _V(370)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 3, 0, _V(420), _V(410)); frskySportProcessPacket(packet); + generateSportCellPacket(packet, 4, 6, _V(410), _V(420)); frskySportProcessPacket(packet); + + EXPECT_EQ(frskyData.hub.cellsCount, 7); + EXPECT_EQ(frskyData.hub.cellVolts[0], _V(420)); + EXPECT_EQ(frskyData.hub.cellVolts[1], _V(410)); + EXPECT_EQ(frskyData.hub.cellVolts[2], _V(415)); + EXPECT_EQ(frskyData.hub.cellVolts[3], _V(410)); + EXPECT_EQ(frskyData.hub.cellVolts[4], _V(420)); + EXPECT_EQ(frskyData.hub.cellVolts[5], _V(390)); + EXPECT_EQ(frskyData.hub.cellVolts[6], _V(370)); + EXPECT_EQ(frskyData.hub.cellVolts[7],_V( 0)); + EXPECT_EQ(frskyData.hub.cellVolts[8],_V( 0)); + EXPECT_EQ(frskyData.hub.minCellVolts, _V(370)); //current minimum cell voltage + EXPECT_EQ(frskyData.hub.minCell, _V(370)); //all time minimum cell voltage + EXPECT_EQ(frskyData.hub.minCells, _V(283)); //all time cells sum minimum + EXPECT_EQ(frskyData.hub.cellsSum, _V(283)); //current cells sum + + //display test + lcd_clear(); + g_model.frsky.voltsSource = FRSKY_VOLTS_SOURCE_A1; + displayVoltagesScreen(); + EXPECT_TRUE(checkScreenshot("two_sensor_votages_screen")); +} +#endif //#if defined(FRSKY_SPORT) + + diff --git a/radio/src/tests/one_sensor_votages_screen_212x64.png b/radio/src/tests/one_sensor_votages_screen_212x64.png new file mode 100644 index 0000000000000000000000000000000000000000..e394794ab566537c2793ef849549be537cc74fdf GIT binary patch literal 640 zcmV-`0)PF9P)kH|>H6 zLqWzEMAU}=TRD!K@!|~_MWjav!2uRt);EBC5k8n9d@w`!V21F)4B>+r!Ur>i4^zDN zkIs1S(@Vk!O}EJlA%qa(Nx}y;Fb#kgJ1qRp&eNU_oM$h3B6 zAEr>}!ynS$&qw&6N$lrKg+1zgSf!qV+cPrZgO0|--_=``TA)TOvNS?T_@G0q^R?H) zgbz#9o6+*62K{_cpucao-o^`b>hI?h_U#tCJU(*6_!2$+eCa?awGcRrx$WmGT<+Ut z*ux_Ofsyy^k~|D}x=s*EEhG;EH23YY;KdBFpO1aJ&_q8U{w2Z(GlUOj2p`N4KA0hV zFhlrYhB_aB{T$XeU?4SfyXyDRUG>$Zc)mDU%pUCz#MbIxjBEUcTzXj_3>+i3>4IY* z5H$O!+jRF@+AuKo=RGMTskb%_pPL)W@<+y*Yc{v(v>QDd`DR8+i1r=%a>W+D;$8j| a=ORB=Z-DreJo*X%0000%=U42EIS;hvn0n|9%; zBV_p(1$W~2Sp^4DFTSxs82UQTa|34hncV@bi|}C@!iQ-HAEqIEn1=9S8p4NZ_Sqf4 ze8+Kwa_?~*p+#1IV`FR&Ex8JD{55%aY>}IU4{tIe@w3W}Olq1xnbdS=waK)LCT7&C z`;-r1%>5MMgAa9T7(W+6O!)Aou6E7ngzJW_c0Olb zL91h5EUCiSBzxaa_}hW%(DS{)7f6$%CgQlc%habsCD5gsyn3CFxfla-=ZLxe_lB*`-@pPz;aEQmFIA37R?|rq=lYM}=z3A#9xU z!B@G?w_PhQjC^p@Qs=we;drQD_;xKPj_O_-;e(sr@(9x|e4Kv@`>1phK70gqJ~W}u zhcD5-o{#XsQ_Fh3xR{>s!APPUsR)2RG|SemK@ zm@VmM`eEQRq(!fG2Li!jA9ssh?Z&%3V~4k-kfc^E8ouq`NY=9CjAdz6i%z>i*T{Eg oq=aeRkxx