diff --git a/libraries/SondeLib/DFM.cpp b/libraries/SondeLib/DFM.cpp index 1396fc9..69113a7 100644 --- a/libraries/SondeLib/DFM.cpp +++ b/libraries/SondeLib/DFM.cpp @@ -71,6 +71,8 @@ int DFM::setup(int inverse) } int DFM::setFrequency(float frequency) { + Serial.print("DFM: setting RX frequency to "); + Serial.println(frequency); return sx1278.setFrequency(frequency); } diff --git a/libraries/SondeLib/RS41.cpp b/libraries/SondeLib/RS41.cpp index 082e1d8..4feaa55 100644 --- a/libraries/SondeLib/RS41.cpp +++ b/libraries/SondeLib/RS41.cpp @@ -133,6 +133,8 @@ int RS41::setup() } int RS41::setFrequency(float frequency) { + Serial.print("RS41: setting RX frequency to "); + Serial.println(frequency); return sx1278.setFrequency(frequency); } @@ -311,11 +313,11 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p) z = (double)getint32(b, b_len, p+8UL)*0.01; wgs84r(x, y, z, &lat, &long0, &heig); Serial.print(" "); - si.lat = (float)(X2C_DIVL(lat,1.7453292519943E-2)); - Serial.print(si.lat); + sonde.si()->lat = (float)(X2C_DIVL(lat,1.7453292519943E-2)); + Serial.print(sonde.si()->lat); Serial.print(" "); - si.lon = (float)(X2C_DIVL(long0,1.7453292519943E-2)); - Serial.print(si.lon); + sonde.si()->lon = (float)(X2C_DIVL(long0,1.7453292519943E-2)); + Serial.print(sonde.si()->lon); if (heig<1.E+5 && heig>(-1.E+5)) { Serial.print(" "); Serial.print((uint32_t)heig); @@ -338,18 +340,18 @@ static void posrs41(const byte b[], uint32_t b_len, uint32_t p) dir = X2C_DIVL(atang2(vn, ve),1.7453292519943E-2); if (dir<0.0) dir = 360.0+dir; Serial.print(" "); - si.hs = sqrt((float)(vn*vn+ve*ve))*3.6f; - Serial.print(si.hs); + sonde.si()->hs = sqrt((float)(vn*vn+ve*ve))*3.6f; + Serial.print(sonde.si()->hs); Serial.print("km/h "); Serial.print(dir); Serial.print("deg "); Serial.print((float)vu); - si.vs = vu; + sonde.si()->vs = vu; Serial.print("m/s "); Serial.print(getcard16(b, b_len, p+18UL)&255UL); Serial.print("Sats"); - si.hei = heig; - si.validPos = true; + sonde.si()->hei = heig; + sonde.si()->validPos = true; } /* end posrs41() */ @@ -400,10 +402,10 @@ void RS41::decode41(byte *data, int MAXLEN) Serial.print("; RS41 ID "); snprintf(buf, 10, "%.8s ", data+p+2); Serial.print(buf); - strcpy(si.type, "RS41"); - strncpy(si.id, (const char *)(data+p+2), 8); - si.id[8]=0; - si.validID=true; + sonde.si()->type=STYPE_RS41; + strncpy(sonde.si()->id, (const char *)(data+p+2), 8); + sonde.si()->id[8]=0; + sonde.si()->validID=true; } // TODO: some more data break; @@ -463,14 +465,15 @@ int RS41::receiveFrame() { sx1278.setPayloadLength(MAXLEN-8); // Expect 320-8 bytes or 518-8 bytes (8 byte header) sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE); - int e = sx1278.receivePacketTimeout(3000, data+8); - if(e) { Serial.println("TIMEOUT"); return 1; } //if timeout... return 1 + int e = sx1278.receivePacketTimeout(1000, data+8); + if(e) { Serial.println("TIMEOUT"); return RX_TIMEOUT; } //if timeout... return 1 for(int i=0; i #include "Sonde.h" +#include "RS41.h" +#include "DFM.h" extern U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8; -SondeInfo si = { "RS41", 403.450, "P1234567", true, 48.1234, 14.9876, 543, 3.97, -0.5, true, 120 }; +//SondeInfo si = { STYPE_RS41, 403.450, "P1234567", true, 48.1234, 14.9876, 543, 3.97, -0.5, true, 120 }; +const char *sondeTypeStr[5] = { "DFM6", "DFM9", "RS41" }; static unsigned char kmh_tiles[] U8X8_PROGMEM = { 0x1F, 0x04, 0x0A, 0x11, 0x00, 0x1F, 0x02, 0x04, 0x42, 0x3F, 0x10, 0x08, 0xFC, 0x22, 0x20, 0xF8 @@ -13,14 +16,104 @@ static unsigned char kmh_tiles[] U8X8_PROGMEM = { static unsigned char ms_tiles[] U8X8_PROGMEM = { 0x1F, 0x02, 0x04, 0x02, 0x1F, 0x40, 0x20, 0x10, 0x08, 0x04, 0x12, 0xA4, 0xA4, 0xA4, 0x40, 0x00 }; +static unsigned char stattiles[4][4] = { + 0x00, 0x00, 0x00, 0x00 , + 0x00, 0x10, 0x10, 0x00 , + 0x1F, 0x15, 0x15, 0x00 , + 0x00, 0x1F, 0x00, 0x00 }; + +byte myIP_tiles[8*10]; + +static const uint8_t font[10][5]={ + 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 + 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 + 0x42, 0x61, 0x51, 0x49, 0x46, // 2 + 0x21, 0x41, 0x45, 0x4B, 0x31, // 3 + 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 + 0x27, 0x45, 0x45, 0x45, 0x39, // 5 + 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 + 0x01, 0x01, 0x79, 0x05, 0x03, // 7 + 0x36, 0x49, 0x49, 0x49, 0x36, // 8 + 0x06, 0x49, 0x39, 0x29, 0x1E }; // 9; .=0x40 + +void Sonde::setIP(const char *ip) { + int tp = 0; + int len = strlen(ip); + for(int i=0; i=MAXSONDE) { + Serial.println("Cannot add another sonde, MAXSONDE reached"); + return; + } + sondeList[nSonde].type = type; + sondeList[nSonde].freq = frequency; + memcpy(sondeList[nSonde].rxStat, "\x00\x01\x2\x3\x2\x1\x1\x2\x0\x3\x0\x0\x1\x2\x3\x1\x0", 18); + nSonde++; +} +void Sonde::nextConfig() { + currentSonde++; + if(currentSonde>=nSonde) { + currentSonde=0; + } + setup(); +} +SondeInfo *Sonde::si() { + return &sondeList[currentSonde]; +} + +void Sonde::setup() { + // Test only: setIP("123.456.789.012"); + // update receiver config: TODO + Serial.print("Setting up receiver on channel "); + Serial.println(currentSonde); + switch(sondeList[currentSonde].type) { + case STYPE_RS41: + rs41.setup(); + rs41.setFrequency(sondeList[currentSonde].freq * 1000000); + break; + case STYPE_DFM06: + case STYPE_DFM09: + dfm.setup( sondeList[currentSonde].type==STYPE_DFM06?0:1 ); + dfm.setFrequency(sondeList[currentSonde].freq * 1000000); + break; + } + // Update display + //updateDisplayRXConfig(); + //updateDisplay(); +} +int Sonde::receiveFrame() { + int ret; + if(sondeList[currentSonde].type == STYPE_RS41) { + ret = rs41.receiveFrame(); + } else { + ret = dfm.receiveFrame(); + } + memmove(sonde.si()->rxStat+1, sonde.si()->rxStat, 17); + sonde.si()->rxStat[0] = ret==0 ? 3 : 1; // OK or Timeout; TODO: add error (2) + return ret; // 0: OK, 1: Timeuot, 2: Other error (TODO) +} void Sonde::updateDisplayPos() { char buf[16]; u8x8.setFont(u8x8_font_7x14_1x2_r); - if(si.validPos) { - snprintf(buf, 16, "%2.5f", si.lat); + if(si()->validPos) { + snprintf(buf, 16, "%2.5f", si()->lat); u8x8.drawString(0,2,buf); - snprintf(buf, 16, "%2.5f", si.lon); + snprintf(buf, 16, "%2.5f", si()->lon); u8x8.drawString(0,4,buf); } else { u8x8.drawString(0,2," "); @@ -31,17 +124,17 @@ void Sonde::updateDisplayPos() { void Sonde::updateDisplayPos2() { char buf[16]; u8x8.setFont(u8x8_font_chroma48medium8_r); - if(!si.validPos) { + if(!si()->validPos) { u8x8.drawString(10,2," "); u8x8.drawString(10,3," "); u8x8.drawString(10,4," "); return; } - snprintf(buf, 16, si.hei>999?"%5.0fm":"%3.1fm", si.hei); + snprintf(buf, 16, si()->hei>999?"%5.0fm":"%3.1fm", si()->hei); u8x8.drawString((10+6-strlen(buf)),2,buf); - snprintf(buf, 16, si.hs>99?"%3.0f":"%2.1f", si.hs); + snprintf(buf, 16, si()->hs>99?"%3.0f":"%2.1f", si()->hs); u8x8.drawString((10+4-strlen(buf)),3,buf); - snprintf(buf, 16, "%+2.1f", si.vs); + snprintf(buf, 16, "%+2.1f", si()->vs); u8x8.drawString((10+4-strlen(buf)),4,buf); u8x8.drawTile(14,3,2,kmh_tiles); u8x8.drawTile(14,4,2,ms_tiles); @@ -49,8 +142,8 @@ void Sonde::updateDisplayPos2() { void Sonde::updateDisplayID() { u8x8.setFont(u8x8_font_chroma48medium8_r); - if(si.validID) { - u8x8.drawString(0,1, si.id); + if(si()->validID) { + u8x8.drawString(0,1, si()->id); } else { u8x8.drawString(0,1, "nnnnnnnn "); } @@ -59,19 +152,45 @@ void Sonde::updateDisplayID() { void Sonde::updateDisplayRSSI() { char buf[16]; u8x8.setFont(u8x8_font_7x14_1x2_r); - snprintf(buf, 16, "%ddB ", si.rssi); + snprintf(buf, 16, "%ddB ", sonde.si()->rssi); u8x8.drawString(0,6,buf); } +void Sonde::updateStat() { + uint8_t *stat = si()->rxStat; + for(int i=0; i<18; i+=2) { + uint8_t tile[8]; + *(uint32_t *)(&tile[0]) = *(uint32_t *)(&(stattiles[stat[i]])); + *(uint32_t *)(&tile[4]) = *(uint32_t *)(&(stattiles[stat[i+1]])); + u8x8.drawTile(7+i/2, 6, 1, tile); + } +} + void Sonde::updateDisplayRXConfig() { char buf[16]; u8x8.setFont(u8x8_font_chroma48medium8_r); - u8x8.drawString(0,0, si.type); - snprintf(buf, 16, "%3.3f MHz", si.freq); + u8x8.drawString(0,0, sondeTypeStr[si()->type]); + snprintf(buf, 16, "%3.3f MHz", si()->freq); u8x8.drawString(5,0, buf); } +void Sonde::updateDisplayIP() { + u8x8.drawTile(6, 7, 10, myIP_tiles); +} + +// Probing RS41 +// 40x.xxx MHz +void Sonde::updateDisplayScanner() { + char buf[16]; + u8x8.setFont(u8x8_font_7x14_1x2_r); + u8x8.drawString(0, 0, "Probing"); + u8x8.drawString(8, 0, sondeTypeStr[si()->type]); + snprintf(buf, 16, "%3.3f MHz", si()->freq); + u8x8.drawString(0,3, buf); + updateDisplayIP(); +} + void Sonde::updateDisplay() { char buf[16]; @@ -80,6 +199,12 @@ void Sonde::updateDisplay() updateDisplayPos(); updateDisplayPos2(); updateDisplayRSSI(); + updateStat(); + updateDisplayIP(); +} + +void Sonde::clearDisplay() { + u8x8.clearDisplay(); } Sonde sonde = Sonde(); diff --git a/libraries/SondeLib/Sonde.h b/libraries/SondeLib/Sonde.h index 18a9510..de3e80a 100644 --- a/libraries/SondeLib/Sonde.h +++ b/libraries/SondeLib/Sonde.h @@ -1,11 +1,18 @@ - #ifndef Sonde_h #define Sonde_H +// RX_TIMEOUT: no header detected +// RX_ERROR: header detected, but data not decoded (crc error, etc.) +// RX_OK: header and data ok +enum RxResult { RX_OK, RX_TIMEOUT, RX_ERROR }; + +enum SondeType { STYPE_DFM06, STYPE_DFM09, STYPE_RS41 }; +extern const char *sondeTypeStr[5]; + typedef struct st_sondeinfo { // receiver configuration - char type[5]; + SondeType type; float freq; // decoded ID char id[10]; @@ -19,20 +26,39 @@ typedef struct st_sondeinfo { bool validPos; // RSSI from receiver int rssi; + uint8_t rxStat[20]; } SondeInfo; +// rxState: 0=undef[empty] 1=timeout[.] 2=errro[E] 3=ok[1] -extern SondeInfo si; + +#define MAXSONDE 10 class Sonde { private: + int nSonde; + int currentSonde = 0; + SondeInfo sondeList[MAXSONDE+1]; public: + void clearSonde(); + void addSonde(float frequency, SondeType type); + void nextConfig(); + void setup(); + + int receiveFrame(); + SondeInfo *si(); + void updateDisplayPos(); void updateDisplayPos2(); void updateDisplayID(); void updateDisplayRSSI(); void updateDisplayRXConfig(); + void updateStat(); + void updateDisplayIP(); void updateDisplay(); + void updateDisplayScanner(); + void clearDisplay(); + void setIP(const char *ip); }; extern Sonde sonde;