From 59b2787c24c75325b985e5c794284cca5c6b0967 Mon Sep 17 00:00:00 2001 From: "Hansi, dl9rdz" Date: Fri, 2 Apr 2021 23:02:12 +0200 Subject: [PATCH] partial mp3h1 --- RX_FSK/RX_FSK.ino | 7 +- RX_FSK/data/rdz.js | 1 + RX_FSK/version.h | 4 +- libraries/SondeLib/Display.cpp | 6 +- libraries/SondeLib/MP3H.cpp | 511 +++++++++++++++++++++++++++++++++ libraries/SondeLib/MP3H.h | 35 +++ libraries/SondeLib/RS41.cpp | 5 +- libraries/SondeLib/Sonde.cpp | 16 ++ libraries/SondeLib/Sonde.h | 9 +- 9 files changed, 584 insertions(+), 10 deletions(-) create mode 100644 libraries/SondeLib/MP3H.cpp create mode 100644 libraries/SondeLib/MP3H.h diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 72201ec..eaf745f 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -199,6 +199,9 @@ void setupChannelList() { else if (space[1] == '2') { type = STYPE_M20; } + else if (space[1] == '3') { + type = STYPE_MP3H; + } else continue; int active = space[3] == '+' ? 1 : 0; if (space[4] == ' ') { @@ -439,7 +442,7 @@ void addSondeStatus(char *ptr, int i) strcat(ptr, ""); sprintf(ptr + strlen(ptr), "\n", s->lat, s->lon, s->alt); @@ -525,6 +528,8 @@ struct st_configitems config_list[] = { {"dfm.rxbw", "DFM RX bandwidth", 0, &sonde.config.dfm.rxbw}, {"m10m20.agcbw", "M10/M20 AGC bandwidth", 0, &sonde.config.m10m20.agcbw}, {"m10m20.rxbw", "M10/M20 RX bandwidth", 0, &sonde.config.m10m20.rxbw}, + {"mp3h.agcbw", "MP3H AGC bandwidth", 0, &sonde.config.mp3h.agcbw}, + {"mp3h.rxbw", "MP3H RX bandwidth", 0, &sonde.config.mp3h.rxbw}, {"ephftp", "FTP for eph (RS92)", 39, &sonde.config.ephftp}, {"", "Data feed configuration", -5, NULL}, /* APRS settings */ diff --git a/RX_FSK/data/rdz.js b/RX_FSK/data/rdz.js index e041dec..396bd53 100644 --- a/RX_FSK/data/rdz.js +++ b/RX_FSK/data/rdz.js @@ -6,6 +6,7 @@ stypes.set('6', 'DFM6 (old)'); stypes.set('D', 'DFM'); stypes.set('M', 'M10'); stypes.set('2', 'M20'); +stypes.set('3', 'MP3H'); /* Used by qrg.html in RX_FSK.ino */ function prep() { diff --git a/RX_FSK/version.h b/RX_FSK/version.h index 3590246..4712a0f 100644 --- a/RX_FSK/version.h +++ b/RX_FSK/version.h @@ -1,4 +1,4 @@ const char *version_name = "rdzTTGOsonde"; -const char *version_id = "devel20210316"; +const char *version_id = "devel20210402"; const int SPIFFS_MAJOR=2; -const int SPIFFS_MINOR=10; +const int SPIFFS_MINOR=11; diff --git a/libraries/SondeLib/Display.cpp b/libraries/SondeLib/Display.cpp index f4cbb40..985eca4 100644 --- a/libraries/SondeLib/Display.cpp +++ b/libraries/SondeLib/Display.cpp @@ -27,9 +27,9 @@ struct GpsPos gpsPos; SPIClass spiDisp(HSPI); -const char *sondeTypeStr[NSondeTypes] = { "DFM ", "DFM9", "RS41", "RS92", "M10 ", "M20 ", "DFM6" }; -const char *sondeTypeLongStr[NSondeTypes] = { "DFM (all)", "DFM9 (old)", "RS41", "RS92", "M10 ", "M20 ", "DFM6 (old)" }; -const char sondeTypeChar[NSondeTypes] = { 'D', '9', '4', 'R', 'M', '2', '6' }; +const char *sondeTypeStr[NSondeTypes] = { "DFM ", "DFM9", "RS41", "RS92", "M10 ", "M20 ", "DFM6", "MP3H" }; +const char *sondeTypeLongStr[NSondeTypes] = { "DFM (all)", "DFM9 (old)", "RS41", "RS92", "M10 ", "M20 ", "DFM6 (old)", "MP3H" }; +const char sondeTypeChar[NSondeTypes] = { 'D', '9', '4', 'R', 'M', '2', '6', '3' }; byte myIP_tiles[8*11]; static uint8_t ap_tile[8]={0x00,0x04,0x22,0x92, 0x92, 0x22, 0x04, 0x00}; diff --git a/libraries/SondeLib/MP3H.cpp b/libraries/SondeLib/MP3H.cpp new file mode 100644 index 0000000..a516d50 --- /dev/null +++ b/libraries/SondeLib/MP3H.cpp @@ -0,0 +1,511 @@ + +/* MP3H decoder functions */ + +#include "MP3H.h" +#include "SX1278FSK.h" +#include "rsc.h" +#include "Sonde.h" +#include + +#define MP3H_DEBUG 1 + +#if MP3H_DEBUG +#define MP3H_DBG(x) x +#else +#define MP3H_DBG(x) +#endif + +static struct st_mp3hstate { + uint32_t id1, id2; + uint8_t idok; + uint32_t gpsdate; + bool dateok; +} mp3hstate; + +static byte data1[512]; +static byte *dataptr=data1; + +static uint8_t rxbitc; +static uint16_t rxbyte; +static int rxp=0; +static int haveNewFrame = 0; +//static int lastFrame = 0; +static int headerDetected = 0; + +int MP3H::setup(float frequency) +{ + MP3H_DBG(Serial.println("Setup sx1278 for MP3H sonde"));; + if(sx1278.ON()!=0) { + MP3H_DBG(Serial.println("Setting SX1278 power on FAILED")); + return 1; + } + // setFSK: switches to FSK standby mode + if(sx1278.setFSK()!=0) { + MP3H_DBG(Serial.println("Setting FSK mode FAILED")); + return 1; + } + Serial.print("MP3H: setting RX frequency to "); + Serial.println(frequency); + int res = sx1278.setFrequency(frequency); + // Test: maybe fix issue after spectrum display? + sx1278.writeRegister(REG_PLL_HOP, 0); + + if(sx1278.setAFCBandwidth(sonde.config.mp3h.agcbw)!=0) { + MP3H_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.mp3h.agcbw)); + return 1; + } + if(sx1278.setRxBandwidth(sonde.config.mp3h.rxbw)!=0) { + MP3H_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.mp3h.rxbw)); + return 1; + } + +#if 0 +/// TODO: Maybe do this conditionally? -- maybe skip if afc if agcbw set to 0 or -1? +//// Step 1: Tentative AFC mode + sx1278.clearIRQFlags(); + // preamble detector + AFC + AGC on + // wait for preamble interrupt within 2sec + sx1278.setBitrate(4800); + // DetectorOn=1, Preamble detector size 01, preamble tol 0x0A (10) + sx1278.setPreambleDetect(0x80 | 0x20 | 0x0A); + // Manual start RX, Enable Auto-AFC, Auto-AGC, RX Trigger (AGC+AFC)by preamble + sx1278.setRxConf(0x20 | 0x10 | 0x08 | 0x06); + // Packet config 1: fixed len, no mancecer, no crc, no address filter + // Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0) + if(sx1278.setPacketConfig(0x08, 0x40)!=0) { + MP3H_DBG(Serial.println("Setting Packet config FAILED")); + return 1; + } + // enable RX + sx1278.setPayloadLength(0); + sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE); + unsigned long t0 = millis(); + MP3H_DBG(Serial.printf("MP3H::setup() AFC preamble search start at %ld\n",t0)); + while( millis() - t0 < 1000 ) { + uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS1); + if(value & 2) { + int32_t afc = sx1278.getAFC(); + int16_t rssi = sx1278.getRSSI(); + Serial.printf("MP3H::setup: preamble: AFC is %d, RSSI is %.1f\n", afc, rssi/2.0); + sonde.sondeList[rxtask.currentSonde].rssi = rssi; + sonde.sondeList[rxtask.currentSonde].afc = afc; + break; + } + yield(); + } + if( millis() - t0 >= 1000) { + Serial.println("Preamble scan for AFC: TIMEOUT\n"); + return 1; // no preamble, so we may fail fast.... + } +#endif + +//// Step 2: Real reception + // FSK standby mode, seems like otherweise baudrate cannot be changed? + sx1278.setFSK(); + if(sx1278.setBitrate(2400)!=0) { + MP3H_DBG(Serial.println("Setting bitrate 2400bit/s FAILED")); + return 1; + } + MP3H_DBG(Serial.printf("Exact bitrate is %f\n", sx1278.getBitrate())); + // Probably not necessary, as this was set before + if(sx1278.setAFCBandwidth(sonde.config.mp3h.agcbw)!=0) { + MP3H_DBG(Serial.printf("Setting AFC bandwidth %d Hz FAILED", sonde.config.mp3h.agcbw)); + return 1; + } + if(sx1278.setRxBandwidth(sonde.config.mp3h.rxbw)!=0) { + MP3H_DBG(Serial.printf("Setting RX bandwidth to %d Hz FAILED", sonde.config.mp3h.rxbw)); + return 1; + } + + ///// Enable auto-AFC, auto-AGC, RX Trigger by preamble + //if(sx1278.setRxConf(0x1E)!=0) { + // Disable auto-AFC, auto-AGC, RX Trigger by preamble + if(sx1278.setRxConf(0x00)!=0) { + MP3H_DBG(Serial.println("Setting RX Config FAILED")); + return 1; + } + // version 1, working with continuous RX + const char *SYNC="\x66\x66"; + if(sx1278.setSyncConf(0x70, 1, (const uint8_t *)SYNC)!=0) { + MP3H_DBG(Serial.println("Setting SYNC Config FAILED")); + return 1; + } + // Preamble detection off (+ size 1 byte, maximum tolerance; should not matter for "off"?) + if(sx1278.setPreambleDetect(0x00 | 0x00 | 0x1F)!=0) { + MP3H_DBG(Serial.println("Setting PreambleDetect FAILED")); + return 1; + } + + // Packet config 1: fixed len, no mancecer, no crc, no address filter + // Packet config 2: packet mode, no home ctrl, no beackn, msb(packetlen)=0) + if(sx1278.setPacketConfig(0x08, 0x40)!=0) { + MP3H_DBG(Serial.println("Setting Packet config FAILED")); + return 1; + } + + // enable RX + sx1278.setPayloadLength(0); // infinite for now... + //sx1278.setRxConf(0x20); + uint16_t afc = sx1278.getRawAFC(); + sx1278.writeRegister(REG_OP_MODE, FSK_RX_MODE); + delay(50); + sx1278.setRawAFC(afc); + delay(50); + Serial.printf("after RX_MODE: AFC is %d\n", sx1278.getAFC()); + + memset((void *)&mp3hstate, 0, sizeof(mp3hstate)); +#if MP3H_DEBUG + MP3H_DBG(Serial.println("Setting SX1278 config for MP3H finished\n"); Serial.println()); +#endif + return res; +} + + +MP3H::MP3H() { +} + +#define MP3H_FRAMELEN 49 + +// offsets from zilog +// https://github.com/rs1729/RS/blob/master/demod/mod/mp3h1mod.c +#define OFS -3 +#define pos_CNT1 (OFS+ 3) // 1 nibble (0x80..0x8F ?) +#define pos_TIME (OFS+ 4) // 3*1 byte +#define pos_GPSecefX (OFS+ 8) // 4 byte +#define pos_GPSecefY (OFS+12) // 4 byte +#define pos_GPSecefZ (OFS+16) // 4 byte +#define pos_GPSecefV (OFS+20) // 3*2 byte +#define pos_GPSnSats (OFS+26) // 1 byte (num Sats ?) +#define pos_PTU1 (OFS+35) // 4 byte +#define pos_PTU2 (OFS+39) // 4 byte +#define pos_CNT2 (OFS+43) // 1 byte (0x01..0x10 ?) +#define pos_CFG (OFS+44) // 2/4 byte +#define pos_CRC (OFS+48) // 2 byte + + +#define crc16poly 0xA001 +static bool checkMP3CRC(uint8_t *data) +{ + int start = pos_CNT1; + int len = 45; + uint16_t rem = 0xffff; + for(int i=0; i>1) ^ crc16poly; + else rem = rem>>1; + } + } + uint16_t crcdat = data[pos_CRC] | (data[pos_CRC+1]<<8); + return rem == crcdat ? true : false; +} + +void MP3H::printRaw(uint8_t *data, int len) +{ + char buf[3]; + int i; + for(i=0; ilat = (float)(lat*DEG); + si->lon = (float)(lng*DEG); + si->alt = alt; + // speeddir + double sinlat = sin(lat); + double coslat = cos(lat); + double sinlng = sin(lng); + double coslng = cos(lng); + double vn = -vx*sinlat*coslng - vy*sinlat*sinlng + vz*coslat; + double ve = -vx*sinlng + vy*coslng; + double clb = vx*coslat*coslng + vy*coslat*sinlng + vz*sinlat; + double dir = atang2(vn, ve)/RAD; + if(dir<0.0) dir+=360.0; + si->dir = dir; + si->vs = clb; + si->hs = sqrt((float)(vn*vn + ve*ve)); + + Serial.printf("Pos: %f %f alt %f dir %f vs %f hs %f\n", si->lat, si->lon, si->alt, si->dir, si->vs, si->hs); + si->validPos = 0x3f; // maybe do some checks first... +} + +static uint8_t hex(uint32_t n) { + n = n % 16; + return (n<10) ? (n+'0') : (n-10+'A'); +} +// ret: 1=frame ok; 2=frame with errors; 0=ignored frame (m10dop-alternativ) +int MP3H::decodeframeMP3H(uint8_t *data) { + printRaw(data, MP3H_FRAMELEN); + + // + if(!checkMP3CRC(data)) { + // maybe add repairing frames later... + return 2; + } + + // data is a frame with correct CRC + SondeInfo *si = sonde.si(); + uint8_t cnt = data[pos_CNT1] & 0x0F; + uint32_t cfg = u4(data+pos_CFG); + if(cnt==15) { + // date + mp3hstate.gpsdate = cfg; + mp3hstate.dateok = true; + } else if(cnt==13) { + // id2 + mp3hstate.id2 = cfg; + mp3hstate.idok |= 2; + } else if(cnt==12) { + // id1 + mp3hstate.id1 = cfg; + mp3hstate.idok |= 1; + } + // get id + if((mp3hstate.idok&3) == 3) { + //... + si->type = STYPE_MP3H; + uint32_t n = mp3hstate.id1*100000 + mp3hstate.id2; + si->id[0] = 'M'; + si->id[1] = 'R'; + si->id[2] = 'Z'; + si->id[3] = hex(n/0x100000); + si->id[4] = hex(n/0x10000); + si->id[5] = hex(n/0x1000); + si->id[6] = hex(n/0x100); + si->id[7] = hex(n/0x10); + si->id[8] = hex(n); + si->id[9] = 0; + snprintf(si->ser, 12, "MRZ-%d-%d", mp3hstate.id1, mp3hstate.id2); + si->validID = true; + } + + // position + calcgps(data); + return 1; +#if 0 + int repairstep = 16; + int repl = 0; + bool crcok; + // error correction, inspired by oe5dxl's sondeudp + do { + crcok = checkMP3Hcrc(M10_CRCPOS, data); + if(crcok || repairstep==0) break; + repl = 0; + for(int i=0; i=repairstep) ) { + repl++; + data[i] = fixbytes[i]; + } + } + repairstep >>= 1; + } while(true); + if(crcok) { + for(int i=0; iid, ids, 10); + ids[0] = hex(data[95]/16); + ids[1] = dez((data[95]&0x0f)/10); + ids[2] = dez((data[95]&0x0f)); + ids[3] = dez(data[93]); + ids[4] = dez(id>>13); + id &= 0x1fff; + ids[5] = dez(id/1000); + ids[6] = dez((id/100)%10); + ids[7] = dez((id/10)%10); + ids[8] = dez(id%10); + strncpy(sonde.si()->ser, ids, 10); + sonde.si()->validID = true; + Serial.printf("ID is %s [%02x %02x %d]\n", ids, data[95], data[93], id); + // ID printed on sonde is ...-.-abbbb, with a=id>>13, bbbb=id&0x1fff in decimal + // position data + sonde.si()->lat = getint32(data+14) * DEGMUL; + sonde.si()->lon = getint32(data+18) * DEGMUL; + sonde.si()->alt = getint32(data+22) * 0.001; + float ve = getint16(data+4)*VMUL; + float vn = getint16(data+6)*VMUL; + sonde.si()->vs = getint16(data+8) * VMUL; + sonde.si()->hs = sqrt(ve*ve+vn*vn); + float dir = atan2(vn, ve)*(1.0/RAD); + if(dir<0) dir+=360; + sonde.si()->dir = dir; + sonde.si()->validPos = 0x3f; + + uint32_t gpstime = getint32(data+10); + uint16_t gpsweek = getint16(data+32); + // UTC is GPSTIME - 18s (24*60*60-18 = 86382) + // one week = 7*24*60*60 = 604800 seconds + // unix epoch starts jan 1st 1970 0:00 + // gps time starts jan 6, 1980 0:00. thats 315964800 epoch seconds. + // subtracting 86400 yields 315878400UL + sonde.si()->time = (gpstime/1000) + 86382 + gpsweek*604800 + 315878400UL; + sonde.si()->validTime = true; + } else { + Serial.printf("data is %02x %02x %02x\n", data[0], data[1], data[2]); + return 0; + } + return crcok?1:2; +#endif + return 0; +} + +static uint32_t rxdata; +static bool rxsearching=true; + +// search for +// 0xBF3H (or inverse) +void MP3H::processMP3Hdata(uint8_t dt) +{ + for(int i=0; i<8; i++) { + uint8_t d = (dt&0x80)?1:0; + dt <<= 1; + rxdata = (rxdata<<1) | d; + if( (rxbitc&1)==0 ) { + // "bit1" + rxbyte = (rxbyte<<1) | d; + } else { + // "bit2" ==> 01 or 10 => 1, otherweise => 0 + // rxbyte = rxbyte ^ d; + } + // BF3H => 1011 1111 0011 0101 => 10011010 10101010 01011010 01100110 => 9AAA5A66 // 6555a599 + if(rxsearching) { + if( rxdata == 0x9AAA5A66 || rxdata == 0x6555a599 ) { +//if( rxdata == 0x9AAA5A66 || rxdata == 0x6555a599 ) { + rxsearching = false; + rxbitc = 0; + rxp = 0; + headerDetected = 1; + Serial.print("SYNC\n"); +#if 0 + int rssi=sx1278.getRSSI(); + int fei=sx1278.getFEI(); + int afc=sx1278.getAFC(); + Serial.print("SYNC!!! Test: RSSI="); Serial.print(rssi); + Serial.print(" FEI="); Serial.print(fei); + Serial.print(" AFC="); Serial.println(afc); + sonde.si()->rssi = rssi; + sonde.si()->afc = afc; +#endif + } + } else { + rxbitc = (rxbitc+1)%16; // 16; + if(rxbitc == 0) { // got 8 data bit + dataptr[rxp++] = rxbyte&0xff; // (rxbyte>>1)&0xff; + //if(rxp==2 && dataptr[0]==0x45 && dataptr[1]==0x20) { isM20 = true; } + if(rxp>=MP3H_FRAMELEN) { + rxsearching = true; + haveNewFrame = decodeframeMP3H(dataptr); + } + } + } + } +} + +int MP3H::receive() { + unsigned long t0 = millis(); + Serial.printf("MP3H::receive() start at %ld\n",t0); + while( millis() - t0 < 1100 ) { + uint8_t value = sx1278.readRegister(REG_IRQ_FLAGS2); + if ( bitRead(value, 7) ) { + Serial.println("FIFO full"); + } + if ( bitRead(value, 4) ) { + Serial.println("FIFO overflow"); + } + if ( bitRead(value, 2) == 1 ) { + Serial.println("FIFO: ready()"); + sx1278.clearIRQFlags(); + } + if(bitRead(value, 6) == 0) { // while FIFO not empty + byte data = sx1278.readRegister(REG_FIFO); + Serial.printf("%02x:",data); + processMP3Hdata(data); + value = sx1278.readRegister(REG_IRQ_FLAGS2); + } else { + if(headerDetected) { + t0 = millis(); // restart timer... don't time out if header detected... + headerDetected = 0; + } + if(haveNewFrame) { + Serial.printf("MP3H::receive(): new frame complete after %ldms\n", millis()-t0); + printRaw(dataptr, MP3H_FRAMELEN); + int retval = haveNewFrame==1 ? RX_OK: RX_ERROR; + haveNewFrame = 0; + return retval; + } + delay(2); + } + } + int32_t afc = sx1278.getAFC(); + int16_t rssi = sx1278.getRSSI(); + Serial.printf("receive: AFC is %d, RSSI is %.1f\n", afc, rssi/2.0); + Serial.printf("MP3H::receive() timed out\n"); + return RX_TIMEOUT; // TODO RX_OK; +} + +int MP3H::waitRXcomplete() { + return 0; +} + + +MP3H mp3h = MP3H(); + diff --git a/libraries/SondeLib/MP3H.h b/libraries/SondeLib/MP3H.h new file mode 100644 index 0000000..9deea5b --- /dev/null +++ b/libraries/SondeLib/MP3H.h @@ -0,0 +1,35 @@ +/* + * MP3H.h + * Functions for decoding MP3H radiosonde + * Copyright (C) 2021 Hansi Reiser, dl9rdz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef MP3H_h +#define MP3H_h + +#include +#include +#include +#ifndef inttypes_h + #include +#endif + +/* Main class */ +class MP3H +{ +private: + void printRaw(uint8_t *data, int len); + void processMP3Hdata(uint8_t data); + int decodeframeMP3H(uint8_t *data); +public: + MP3H(); + int setup(float frequency); + int receive(); + int waitRXcomplete(); +}; + +extern MP3H mp3h; + +#endif diff --git a/libraries/SondeLib/RS41.cpp b/libraries/SondeLib/RS41.cpp index 1b437db..2b5263c 100644 --- a/libraries/SondeLib/RS41.cpp +++ b/libraries/SondeLib/RS41.cpp @@ -169,7 +169,7 @@ static uint32_t X2C_LSH(uint32_t a, int32_t length, int32_t n) return (a >> -n) & m; } -static double atang2(double x, double y) +double atang2(double x, double y) { double w; if (fabs(x)>fabs(y)) { @@ -408,7 +408,8 @@ static int32_t getint16(const byte frame[], uint32_t frame_len, return (int32_t)n; } /* end getint16() */ -static void wgs84r(double x, double y, double z, +// also used by MP3H.cpp +void wgs84r(double x, double y, double z, double * lat, double * long0, double * heig) { diff --git a/libraries/SondeLib/Sonde.cpp b/libraries/SondeLib/Sonde.cpp index fcbe8e0..5ac161e 100644 --- a/libraries/SondeLib/Sonde.cpp +++ b/libraries/SondeLib/Sonde.cpp @@ -6,6 +6,7 @@ #include "RS92.h" #include "DFM.h" #include "M10M20.h" +#include "MP3H.h" #include "SX1278FSK.h" #include "Display.h" #include @@ -191,6 +192,8 @@ void Sonde::defaultConfig() { config.dfm.rxbw=10400; config.m10m20.agcbw=20800; config.m10m20.rxbw=12500; + config.mp3h.agcbw=12500; + config.mp3h.rxbw=12500; config.udpfeed.active = 1; config.udpfeed.type = 0; strcpy(config.udpfeed.host, "192.168.42.20"); @@ -311,6 +314,10 @@ void Sonde::setConfig(const char *cfg) { config.m10m20.agcbw = atoi(val); } else if(strcmp(cfg,"m10m20.rxbw")==0) { config.m10m20.rxbw = atoi(val); + } else if(strcmp(cfg,"mp3h.agcbw")==0) { + config.mp3h.agcbw = atoi(val); + } else if(strcmp(cfg,"mp3h.rxbw")==0) { + config.mp3h.rxbw = atoi(val); } else if(strcmp(cfg,"dfm.agcbw")==0) { config.dfm.agcbw = atoi(val); } else if(strcmp(cfg,"dfm.rxbw")==0) { @@ -466,6 +473,9 @@ void Sonde::setup() { case STYPE_M20: m10m20.setup( sondeList[rxtask.currentSonde].freq * 1000000); break; + case STYPE_MP3H: + mp3h.setup( sondeList[rxtask.currentSonde].freq * 1000000); + break; } // debug int freq = (int)sx1278.getFrequency(); @@ -498,6 +508,9 @@ void Sonde::receive() { case STYPE_DFM: res = dfm.receive(); break; + case STYPE_MP3H: + res = mp3h.receive(); + break; } // state information for RX_TIMER / NORX_TIMER events @@ -595,6 +608,9 @@ rxloop: case STYPE_DFM: dfm.waitRXcomplete(); break; + case STYPE_MP3H: + mp3h.waitRXcomplete(); + break; } memmove(sonde.si()->rxStat+1, sonde.si()->rxStat, 17); sonde.si()->rxStat[0] = res; diff --git a/libraries/SondeLib/Sonde.h b/libraries/SondeLib/Sonde.h index c31ca9c..8a6a42b 100644 --- a/libraries/SondeLib/Sonde.h +++ b/libraries/SondeLib/Sonde.h @@ -53,8 +53,8 @@ extern const char *RXstr[]; // 01000000 => goto sonde -1 // 01000001 => goto sonde +1 -#define NSondeTypes 7 -enum SondeType { STYPE_DFM, STYPE_DFM09_OLD, STYPE_RS41, STYPE_RS92, STYPE_M10, STYPE_M20, STYPE_DFM06_OLD }; +#define NSondeTypes 8 +enum SondeType { STYPE_DFM, STYPE_DFM09_OLD, STYPE_RS41, STYPE_RS92, STYPE_M10, STYPE_M20, STYPE_DFM06_OLD, STYPE_MP3H }; extern const char *sondeTypeStr[NSondeTypes]; extern const char *sondeTypeLongStr[NSondeTypes]; extern const char sondeTypeChar[NSondeTypes]; @@ -143,6 +143,10 @@ struct st_m10m20config { int agcbw; int rxbw; }; +struct st_mp3hconfig { + int agcbw; + int rxbw; +}; enum IDTYPE { ID_DFMDXL, ID_DFMGRAW, ID_DFMAUTO }; @@ -215,6 +219,7 @@ typedef struct st_rdzconfig { struct st_rs92config rs92; struct st_dfmconfig dfm; struct st_m10m20config m10m20; + struct st_mp3hconfig mp3h; char ephftp[40]; // data feed configuration // for now, one feed for each type is enough, but might get extended to more?
%3.3f MHz, Type: %s
ID: %s", s->freq, sondeTypeLongStr[s->type], s->validID ? s->id : ""); - if (s->validID && (TYPE_IS_DFM(s->type) || TYPE_IS_METEO(s->type)) ) { + if (s->validID && (TYPE_IS_DFM(s->type) || TYPE_IS_METEO(s->type) || s->type==STYPE_MP3H) ) { sprintf(ptr + strlen(ptr), " (ser: %s)", s->ser); } sprintf(ptr + strlen(ptr), "
QTH: %.6f,%.6f h=%.0fm