Initial work on M17 support. ADF7021 parameters not correct or complete yet.

This commit is contained in:
Jonathan Naylor 2020-10-23 14:43:06 +01:00
parent 89daa20476
commit bb9fe7f561
32 changed files with 702 additions and 26 deletions

View file

@ -1,4 +1,5 @@
/* /*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM * Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE * Copyright (C) 2017 by Danilo DB4PLE
@ -48,6 +49,7 @@ uint16_t m_dmrDev;
uint16_t m_ysfDev; uint16_t m_ysfDev;
uint16_t m_p25Dev; uint16_t m_p25Dev;
uint16_t m_nxdnDev; uint16_t m_nxdnDev;
uint16_t m_m17Dev;
uint16_t m_pocsagDev; uint16_t m_pocsagDev;
static void Send_AD7021_control_shift() static void Send_AD7021_control_shift()
@ -273,6 +275,9 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
case STATE_NXDN: case STATE_NXDN:
AFC_OFFSET = AFC_OFFSET_NXDN; AFC_OFFSET = AFC_OFFSET_NXDN;
break; break;
case STATE_M17:
AFC_OFFSET = AFC_OFFSET_M17;
break;
default: default:
break; break;
} }
@ -499,6 +504,33 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
#endif #endif
break; break;
case STATE_M17:
// Dev: +1 symb 600 Hz, symb rate = 4800
ADF7021_REG3 = ADF7021_REG3_M17;
ADF7021_REG10 = ADF7021_REG10_M17;
// K=32
ADF7021_REG4 = (uint32_t) 0b0100 << 0; // register 4
ADF7021_REG4 |= (uint32_t) 0b011 << 4; // mode, 4FSK
ADF7021_REG4 |= (uint32_t) 0b0 << 7;
ADF7021_REG4 |= (uint32_t) 0b11 << 8;
ADF7021_REG4 |= (uint32_t) ADF7021_DISC_BW_M17 << 10; // Disc BW
ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_M17 << 20; // Post dem BW
ADF7021_REG4 |= (uint32_t) 0b00 << 30; // IF filter (12.5 kHz)
ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13
ADF7021_REG13 |= (uint32_t) ADF7021_SLICER_TH_M17 << 4; // slicer threshold
ADF7021_REG2 = (uint32_t) 0b10 << 28; // invert data (and RC alpha = 0.5)
ADF7021_REG2 |= (uint32_t) (m_m17Dev / div2) << 19; // deviation
#if defined(ADF7021_DISABLE_RC_4FSK)
ADF7021_REG2 |= (uint32_t) 0b011 << 4; // modulation (4FSK)
#else
ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK)
#endif
break;
default: default:
break; break;
} }
@ -721,6 +753,29 @@ void CIO::ifConf2(MMDVM_STATE modemState)
ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK) ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK)
break; break;
case STATE_M17:
// Dev: +1 symb 600 Hz, symb rate = 4800
ADF7021_REG3 = ADF7021_REG3_M17;
ADF7021_REG10 = ADF7021_REG10_M17;
// K=32
ADF7021_REG4 = (uint32_t) 0b0100 << 0; // register 4
ADF7021_REG4 |= (uint32_t) 0b011 << 4; // mode, 4FSK
ADF7021_REG4 |= (uint32_t) 0b0 << 7;
ADF7021_REG4 |= (uint32_t) 0b11 << 8;
ADF7021_REG4 |= (uint32_t) ADF7021_DISC_BW_M17 << 10; // Disc BW
ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_M17 << 20; // Post dem BW
ADF7021_REG4 |= (uint32_t) 0b00 << 30; // IF filter (12.5 kHz)
ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13
ADF7021_REG13 |= (uint32_t) ADF7021_SLICER_TH_M17 << 4; // slicer threshold
ADF7021_REG2 = (uint32_t) 0b10 << 28; // invert data (and RC alpha = 0.5)
ADF7021_REG2 |= (uint32_t) (m_m17Dev / div2) << 19; // deviation
ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK)
break;
default: default:
break; break;
} }
@ -959,7 +1014,7 @@ void CIO::setPower(uint8_t power)
m_power = power >> 2; m_power = power >> 2;
} }
void CIO::setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, bool ysfLoDev) void CIO::setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t m17TXLevel, uint8_t pocsagTXLevel, bool ysfLoDev)
{ {
m_dstarDev = uint16_t((ADF7021_DEV_DSTAR * uint16_t(dstarTXLevel)) / 128U); m_dstarDev = uint16_t((ADF7021_DEV_DSTAR * uint16_t(dstarTXLevel)) / 128U);
m_dmrDev = uint16_t((ADF7021_DEV_DMR * uint16_t(dmrTXLevel)) / 128U); m_dmrDev = uint16_t((ADF7021_DEV_DMR * uint16_t(dmrTXLevel)) / 128U);
@ -971,6 +1026,7 @@ void CIO::setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXL
m_p25Dev = uint16_t((ADF7021_DEV_P25 * uint16_t(p25TXLevel)) / 128U); m_p25Dev = uint16_t((ADF7021_DEV_P25 * uint16_t(p25TXLevel)) / 128U);
m_nxdnDev = uint16_t((ADF7021_DEV_NXDN * uint16_t(nxdnTXLevel)) / 128U); m_nxdnDev = uint16_t((ADF7021_DEV_NXDN * uint16_t(nxdnTXLevel)) / 128U);
m_m17Dev = uint16_t((ADF7021_DEV_M17 * uint16_t(m17TXLevel)) / 128U);
m_pocsagDev = uint16_t((ADF7021_DEV_POCSAG * uint16_t(pocsagTXLevel)) / 128U); m_pocsagDev = uint16_t((ADF7021_DEV_POCSAG * uint16_t(pocsagTXLevel)) / 128U);
} }
@ -1090,6 +1146,11 @@ uint16_t CIO::devNXDN()
return (uint16_t)((ADF7021_PFD * m_nxdnDev) / (f_div * 65536)); return (uint16_t)((ADF7021_PFD * m_nxdnDev) / (f_div * 65536));
} }
uint16_t CIO::devM17()
{
return (uint16_t)((ADF7021_PFD * m_m17Dev) / (f_div * 65536));
}
uint16_t CIO::devPOCSAG() uint16_t CIO::devPOCSAG()
{ {
return (uint16_t)((ADF7021_PFD * m_pocsagDev) / (f_div * 65536)); return (uint16_t)((ADF7021_PFD * m_pocsagDev) / (f_div * 65536));
@ -1106,6 +1167,7 @@ void CIO::printConf()
DEBUG2("YSF +1 sym dev (Hz):", devYSF()); DEBUG2("YSF +1 sym dev (Hz):", devYSF());
DEBUG2("P25 +1 sym dev (Hz):", devP25()); DEBUG2("P25 +1 sym dev (Hz):", devP25());
DEBUG2("NXDN +1 sym dev (Hz):", devNXDN()); DEBUG2("NXDN +1 sym dev (Hz):", devNXDN());
DEBUG2("M17 +1 sym dev (Hz):", devM17());
DEBUG2("POCSAG dev (Hz):", devPOCSAG()); DEBUG2("POCSAG dev (Hz):", devPOCSAG());
} }

View file

@ -87,6 +87,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_DEV_P25 22U #define ADF7021_DEV_P25 22U
#endif #endif
#define ADF7021_DEV_NXDN 13U #define ADF7021_DEV_NXDN 13U
#define ADF7021_DEV_M17 23U // XXX FIXME
#define ADF7021_DEV_POCSAG 160U #define ADF7021_DEV_POCSAG 160U
// TX/RX CLOCK register (REG 03) // TX/RX CLOCK register (REG 03)
@ -97,12 +98,14 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_REG3_YSF_H 0x2A4C0493 #define ADF7021_REG3_YSF_H 0x2A4C0493
#define ADF7021_REG3_P25 0x2A4C04D3 #define ADF7021_REG3_P25 0x2A4C04D3
#define ADF7021_REG3_NXDN 0x2A4C04D3 #define ADF7021_REG3_NXDN 0x2A4C04D3
#define ADF7021_REG3_M17 0x2A4C04D3 // XXX FIXME
#else #else
#define ADF7021_REG3_DMR 0x2A4C80D3 #define ADF7021_REG3_DMR 0x2A4C80D3
#define ADF7021_REG3_YSF_L 0x2A4C80D3 #define ADF7021_REG3_YSF_L 0x2A4C80D3
#define ADF7021_REG3_YSF_H 0x2A4CC093 #define ADF7021_REG3_YSF_H 0x2A4CC093
#define ADF7021_REG3_P25 0x2A4C80D3 #define ADF7021_REG3_P25 0x2A4C80D3
#define ADF7021_REG3_NXDN 0x2A4CC113 #define ADF7021_REG3_NXDN 0x2A4CC113
#define ADF7021_REG3_M17 0x2A4C80D3 // XXX FIXME
#endif #endif
#define ADF7021_REG3_POCSAG 0x2A4F0093 #define ADF7021_REG3_POCSAG 0x2A4F0093
@ -139,26 +142,31 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_REG10_YSF 0x01FE473A #define ADF7021_REG10_YSF 0x01FE473A
#define ADF7021_REG10_P25 0x01FE473A #define ADF7021_REG10_P25 0x01FE473A
#define ADF7021_REG10_NXDN 0x01FE473A #define ADF7021_REG10_NXDN 0x01FE473A
#define ADF7021_REG10_M17 0x01FE473A
#if defined(ADF7021_AFC_POS) #if defined(ADF7021_AFC_POS)
#define AFC_OFFSET_DMR -250 #define AFC_OFFSET_DMR -250
#define AFC_OFFSET_YSF -250 #define AFC_OFFSET_YSF -250
#define AFC_OFFSET_P25 -250 #define AFC_OFFSET_P25 -250
#define AFC_OFFSET_NXDN -250 #define AFC_OFFSET_NXDN -250
#define AFC_OFFSET_M17 -250
#else #else
#define AFC_OFFSET_DMR 250 #define AFC_OFFSET_DMR 250
#define AFC_OFFSET_YSF 250 #define AFC_OFFSET_YSF 250
#define AFC_OFFSET_P25 250 #define AFC_OFFSET_P25 250
#define AFC_OFFSET_NXDN 250 #define AFC_OFFSET_NXDN 250
#define AFC_OFFSET_M17 250
#endif #endif
#else #else
#define ADF7021_REG10_DMR 0x049E472A #define ADF7021_REG10_DMR 0x049E472A
#define ADF7021_REG10_YSF 0x049E472A #define ADF7021_REG10_YSF 0x049E472A
#define ADF7021_REG10_P25 0x049E472A #define ADF7021_REG10_P25 0x049E472A
#define ADF7021_REG10_NXDN 0x049E472A #define ADF7021_REG10_NXDN 0x049E472A
#define ADF7021_REG10_M17 0x049E472A
#define AFC_OFFSET_DMR 0 #define AFC_OFFSET_DMR 0
#define AFC_OFFSET_YSF 0 #define AFC_OFFSET_YSF 0
#define AFC_OFFSET_P25 0 #define AFC_OFFSET_P25 0
#define AFC_OFFSET_NXDN 0 #define AFC_OFFSET_NXDN 0
#define AFC_OFFSET_M17 0
#endif #endif
/****** Support for 12.2880 MHz TCXO ******/ /****** Support for 12.2880 MHz TCXO ******/
@ -198,12 +206,14 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_REG3_YSF_H 0x29EC0493 #define ADF7021_REG3_YSF_H 0x29EC0493
#define ADF7021_REG3_P25 0x29EC0493 #define ADF7021_REG3_P25 0x29EC0493
#define ADF7021_REG3_NXDN 0x29EC0493 #define ADF7021_REG3_NXDN 0x29EC0493
#define ADF7021_REG3_M17 0x29EC0493
#else #else
#define ADF7021_REG3_DMR 0x29ECA093 #define ADF7021_REG3_DMR 0x29ECA093
#define ADF7021_REG3_YSF_L 0x29ECA093 #define ADF7021_REG3_YSF_L 0x29ECA093
#define ADF7021_REG3_YSF_H 0x29ECA093 #define ADF7021_REG3_YSF_H 0x29ECA093
#define ADF7021_REG3_P25 0x29ECA093 #define ADF7021_REG3_P25 0x29ECA093
#define ADF7021_REG3_NXDN 0x29ECA113 #define ADF7021_REG3_NXDN 0x29ECA113
#define ADF7021_REG3_M17 0x29ECA093
#endif #endif
#define ADF7021_REG3_POCSAG 0x29EE8093 #define ADF7021_REG3_POCSAG 0x29EE8093
@ -240,26 +250,31 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_REG10_YSF 0x01FE557A #define ADF7021_REG10_YSF 0x01FE557A
#define ADF7021_REG10_P25 0x01FE557A #define ADF7021_REG10_P25 0x01FE557A
#define ADF7021_REG10_NXDN 0x01FE557A #define ADF7021_REG10_NXDN 0x01FE557A
#define ADF7021_REG10_M17 0x01FE557A
#if defined(ADF7021_AFC_POS) #if defined(ADF7021_AFC_POS)
#define AFC_OFFSET_DMR -250 #define AFC_OFFSET_DMR -250
#define AFC_OFFSET_YSF -250 #define AFC_OFFSET_YSF -250
#define AFC_OFFSET_P25 -250 #define AFC_OFFSET_P25 -250
#define AFC_OFFSET_NXDN -250 #define AFC_OFFSET_NXDN -250
#define AFC_OFFSET_M17 -250
#else #else
#define AFC_OFFSET_DMR 250 #define AFC_OFFSET_DMR 250
#define AFC_OFFSET_YSF 250 #define AFC_OFFSET_YSF 250
#define AFC_OFFSET_P25 250 #define AFC_OFFSET_P25 250
#define AFC_OFFSET_NXDN 250 #define AFC_OFFSET_NXDN 250
#define AFC_OFFSET_M17 250
#endif #endif
#else #else
#define ADF7021_REG10_DMR 0x049E556A #define ADF7021_REG10_DMR 0x049E556A
#define ADF7021_REG10_YSF 0x049E556A #define ADF7021_REG10_YSF 0x049E556A
#define ADF7021_REG10_P25 0x049E556A #define ADF7021_REG10_P25 0x049E556A
#define ADF7021_REG10_NXDN 0x049E556A #define ADF7021_REG10_NXDN 0x049E556A
#define ADF7021_REG10_M17 0x049E556A
#define AFC_OFFSET_DMR 0 #define AFC_OFFSET_DMR 0
#define AFC_OFFSET_YSF 0 #define AFC_OFFSET_YSF 0
#define AFC_OFFSET_P25 0 #define AFC_OFFSET_P25 0
#define AFC_OFFSET_NXDN 0 #define AFC_OFFSET_NXDN 0
#define AFC_OFFSET_M17 0
#endif #endif
#endif #endif

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU
* Copyright (C) 2019 by Florian Wolters DF2ET * Copyright (C) 2019 by Florian Wolters DF2ET
* *
@ -42,6 +42,7 @@ enum MMDVM_STATE {
STATE_P25 = 4, STATE_P25 = 4,
STATE_NXDN = 5, STATE_NXDN = 5,
STATE_POCSAG = 6, STATE_POCSAG = 6,
STATE_M17 = 7,
// Dummy states start at 90 // Dummy states start at 90
STATE_DMRDMO1K = 92, STATE_DMRDMO1K = 92,
@ -77,6 +78,8 @@ const uint8_t MARK_NONE = 0x00U;
#include "YSFTX.h" #include "YSFTX.h"
#include "P25RX.h" #include "P25RX.h"
#include "P25TX.h" #include "P25TX.h"
#include "M17RX.h"
#include "M17TX.h"
#include "NXDNRX.h" #include "NXDNRX.h"
#include "NXDNTX.h" #include "NXDNTX.h"
#include "POCSAGTX.h" #include "POCSAGTX.h"
@ -103,6 +106,7 @@ extern bool m_dmrEnable;
extern bool m_ysfEnable; extern bool m_ysfEnable;
extern bool m_p25Enable; extern bool m_p25Enable;
extern bool m_nxdnEnable; extern bool m_nxdnEnable;
extern bool m_m17Enable;
extern bool m_pocsagEnable; extern bool m_pocsagEnable;
extern bool m_duplex; extern bool m_duplex;
@ -133,6 +137,9 @@ extern CYSFTX ysfTX;
extern CP25RX p25RX; extern CP25RX p25RX;
extern CP25TX p25TX; extern CP25TX p25TX;
extern CM17RX m17RX;
extern CM17TX m17TX;
extern CNXDNRX nxdnRX; extern CNXDNRX nxdnRX;
extern CNXDNTX nxdnTX; extern CNXDNTX nxdnTX;

30
IO.cpp
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE * Copyright (C) 2017 by Danilo DB4PLE
@ -51,6 +51,7 @@ m_int2counter(0U)
YSF_pin(LOW); YSF_pin(LOW);
P25_pin(LOW); P25_pin(LOW);
NXDN_pin(LOW); NXDN_pin(LOW);
M17_pin(LOW);
POCSAG_pin(LOW); POCSAG_pin(LOW);
COS_pin(LOW); COS_pin(LOW);
DEB_pin(LOW); DEB_pin(LOW);
@ -89,6 +90,7 @@ void CIO::selfTest()
YSF_pin(ledValue); YSF_pin(ledValue);
P25_pin(ledValue); P25_pin(ledValue);
NXDN_pin(ledValue); NXDN_pin(ledValue);
M17_pin(ledValue);
POCSAG_pin(ledValue); POCSAG_pin(ledValue);
COS_pin(ledValue); COS_pin(ledValue);
@ -111,7 +113,7 @@ void CIO::process()
if (m_started) { if (m_started) {
// Two seconds timeout // Two seconds timeout
if (m_watchdog >= 19200U) { if (m_watchdog >= 19200U) {
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN) { if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN || m_modemState == STATE_M17) {
m_modemState = STATE_IDLE; m_modemState = STATE_IDLE;
setMode(m_modemState); setMode(m_modemState);
} }
@ -178,6 +180,8 @@ void CIO::process()
scantime = SCAN_TIME; scantime = SCAN_TIME;
else if(m_modemState_prev == STATE_NXDN) else if(m_modemState_prev == STATE_NXDN)
scantime = SCAN_TIME; scantime = SCAN_TIME;
else if(m_modemState_prev == STATE_M17)
scantime = SCAN_TIME;
else else
scantime = SCAN_TIME; scantime = SCAN_TIME;
@ -221,6 +225,9 @@ void CIO::process()
case STATE_NXDN: case STATE_NXDN:
nxdnRX.databit(bit); nxdnRX.databit(bit);
break; break;
case STATE_M17:
m17RX.databit(bit);
break;
default: default:
break; break;
} }
@ -252,6 +259,10 @@ void CIO::start()
m_Modes[m_TotalModes] = STATE_NXDN; m_Modes[m_TotalModes] = STATE_NXDN;
m_TotalModes++; m_TotalModes++;
} }
if(m_m17Enable) {
m_Modes[m_TotalModes] = STATE_M17;
m_TotalModes++;
}
#if defined(ENABLE_SCAN_MODE) #if defined(ENABLE_SCAN_MODE)
if(m_TotalModes > 1U) if(m_TotalModes > 1U)
@ -412,6 +423,14 @@ void CIO::setMode(MMDVM_STATE modemState)
#if defined(USE_ALTERNATE_NXDN_LEDS) #if defined(USE_ALTERNATE_NXDN_LEDS)
} }
#endif #endif
#if defined(USE_ALTERNATE_M17_LEDS)
if (modemState != STATE_M17) {
#endif
YSF_pin(modemState == STATE_DSTAR);
P25_pin(modemState == STATE_P25);
#if defined(USE_ALTERNATE_M17_LEDS)
}
#endif
#if defined(USE_ALTERNATE_NXDN_LEDS) #if defined(USE_ALTERNATE_NXDN_LEDS)
if (modemState != STATE_YSF && modemState != STATE_P25) { if (modemState != STATE_YSF && modemState != STATE_P25) {
#endif #endif
@ -426,6 +445,13 @@ void CIO::setMode(MMDVM_STATE modemState)
#if defined(USE_ALTERNATE_POCSAG_LEDS) #if defined(USE_ALTERNATE_POCSAG_LEDS)
} }
#endif #endif
#if defined(USE_ALTERNATE_M17_LEDS)
if (modemState != STATE_DSTAR && modemState != STATE_P25) {
#endif
M17_pin(modemState == STATE_M17);
#if defined(USE_ALTERNATE_M17_LEDS)
}
#endif
} }
void CIO::setDecode(bool dcd) void CIO::setDecode(bool dcd)

8
IO.h
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE * Copyright (C) 2017 by Danilo DB4PLE
@ -98,6 +98,7 @@ public:
void YSF_pin(bool on); void YSF_pin(bool on);
void P25_pin(bool on); void P25_pin(bool on);
void NXDN_pin(bool on); void NXDN_pin(bool on);
void M17_pin(bool on);
void POCSAG_pin(bool on); void POCSAG_pin(bool on);
void COS_pin(bool on); void COS_pin(bool on);
void interrupt(void); void interrupt(void);
@ -141,7 +142,7 @@ public:
#endif #endif
void start(void); void start(void);
void startInt(void); void startInt(void);
void setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, bool ysfLoDev); void setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t m17TXLevel, uint8_t pocsagTXLevel, bool ysfLoDev);
void updateCal(void); void updateCal(void);
#if defined(SEND_RSSI_DATA) #if defined(SEND_RSSI_DATA)
@ -162,6 +163,7 @@ public:
uint16_t devYSF(void); uint16_t devYSF(void);
uint16_t devP25(void); uint16_t devP25(void);
uint16_t devNXDN(void); uint16_t devNXDN(void);
uint16_t devM17(void);
uint16_t devPOCSAG(void); uint16_t devPOCSAG(void);
void printConf(); void printConf();
#endif #endif
@ -181,7 +183,7 @@ private:
uint32_t m_scanPauseCnt; uint32_t m_scanPauseCnt;
uint8_t m_scanPos; uint8_t m_scanPos;
uint8_t m_TotalModes; uint8_t m_TotalModes;
MMDVM_STATE m_Modes[5]; MMDVM_STATE m_Modes[6];
bool m_ledValue; bool m_ledValue;
volatile uint32_t m_watchdog; volatile uint32_t m_watchdog;
volatile uint16_t m_int1counter; volatile uint16_t m_int1counter;

47
M17Defines.h Normal file
View file

@ -0,0 +1,47 @@
/*
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(M17DEFINES_H)
#define M17DEFINES_H
const unsigned int M17_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int M17_FRAME_LENGTH_BITS = 384U;
const unsigned int M17_FRAME_LENGTH_BYTES = M17_FRAME_LENGTH_BITS / 8U;
const unsigned int M17_FRAME_LENGTH_SYMBOLS = M17_FRAME_LENGTH_BITS / 2U;
const unsigned int M17_FRAME_LENGTH_SAMPLES = M17_FRAME_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH;
const unsigned int M17_SYNC_LENGTH_BITS = 16U;
const unsigned int M17_SYNC_LENGTH_SYMBOLS = M17_SYNC_LENGTH_BITS / 2U;
const unsigned int M17_SYNC_LENGTH_SAMPLES = M17_SYNC_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH;
const uint8_t M17_SYNC_BYTES[] = {0x32U, 0x43U};
const uint8_t M17_SYNC_BYTES_LENGTH = 2U;
const uint16_t M17_SYNC_BITS = 0x3243U;
// 3 2 4 3
// 00 11 00 10 01 00 00 11
// +1 -3 +1 -1 +3 +1 +1 -3
const int8_t M17_SYNC_SYMBOLS_VALUES[] = {+1, -3, +1, -1, +3, +1, +1, -3};
const uint8_t M17_SYNC_SYMBOLS = 0xAEU;
#endif

137
M17RX.cpp Normal file
View file

@ -0,0 +1,137 @@
/*
* Copyright (C) 2009-2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#include "Globals.h"
#include "M17RX.h"
#include "Utils.h"
const uint8_t MAX_SYNC_BIT_START_ERRS = 0U;
const uint8_t MAX_SYNC_BIT_RUN_ERRS = 2U;
const unsigned int MAX_SYNC_FRAMES = 5U + 1U;
const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
CM17RX::CM17RX() :
m_state(M17RXS_NONE),
m_bitBuffer(0x00U),
m_outBuffer(),
m_buffer(NULL),
m_bufferPtr(0U),
m_lostCount(0U)
{
m_buffer = m_outBuffer + 1U;
}
void CM17RX::reset()
{
m_state = M17RXS_NONE;
m_bitBuffer = 0x00U;
m_bufferPtr = 0U;
m_lostCount = 0U;
}
void CM17RX::databit(bool bit)
{
if (m_state == M17RXS_NONE)
processNone(bit);
else
processData(bit);
}
void CM17RX::processNone(bool bit)
{
m_bitBuffer <<= 1;
if (bit)
m_bitBuffer |= 0x01U;
// Fuzzy matching of the data sync bit sequence
if (countBits32(m_bitBuffer ^ M17_SYNC_BITS) <= MAX_SYNC_BIT_START_ERRS) {
DEBUG1("M17RX: sync found in None");
for (uint8_t i = 0U; i < M17_SYNC_BYTES_LENGTH; i++)
m_buffer[i] = M17_SYNC_BYTES[i];
m_lostCount = MAX_SYNC_FRAMES;
m_bufferPtr = M17_SYNC_LENGTH_BITS;
m_state = M17RXS_DATA;
io.setDecode(true);
}
}
void CM17RX::processData(bool bit)
{
m_bitBuffer <<= 1;
if (bit)
m_bitBuffer |= 0x01U;
WRITE_BIT1(m_buffer, m_bufferPtr, bit);
m_bufferPtr++;
if (m_bufferPtr > M17_FRAME_LENGTH_BITS)
reset();
// Only search for a sync in the right place +-2 symbols
if (m_bufferPtr >= (M17_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (M17_SYNC_LENGTH_BITS + 2U)) {
// Fuzzy matching of the data sync bit sequence
if (countBits32(m_bitBuffer ^ M17_SYNC_BITS) <= MAX_SYNC_BIT_RUN_ERRS) {
DEBUG2("M17RX: found sync in Data, pos", m_bufferPtr - M17_SYNC_LENGTH_BITS);
m_lostCount = MAX_SYNC_FRAMES;
m_bufferPtr = M17_SYNC_LENGTH_BITS;
}
}
// Send a data frame to the host if the required number of bits have been received
if (m_bufferPtr == M17_FRAME_LENGTH_BITS) {
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
m_lostCount--;
if (m_lostCount == 0U) {
DEBUG1("M17RX: sync timed out, lost lock");
io.setDecode(false);
serial.writeM17Lost();
reset();
} else {
// Write data to host
m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
writeRSSIData(m_outBuffer);
// Start the next frame
::memset(m_outBuffer, 0x00U, M17_FRAME_LENGTH_BYTES + 3U);
m_bufferPtr = 0U;
}
}
}
void CM17RX::writeRSSIData(uint8_t* data)
{
#if defined(SEND_RSSI_DATA)
uint16_t rssi = io.readRSSI();
data[49U] = (rssi >> 8) & 0xFFU;
data[50U] = (rssi >> 0) & 0xFFU;
serial.writeM17Data(data, M17_FRAME_LENGTH_BYTES + 3U);
#else
serial.writeM17Data(data, M17_FRAME_LENGTH_BYTES + 1U);
#endif
}

51
M17RX.h Normal file
View file

@ -0,0 +1,51 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(M17RX_H)
#define M17RX_H
#include "M17Defines.h"
enum M17RX_STATE {
M17RXS_NONE,
M17RXS_DATA
};
class CM17RX {
public:
CM17RX();
void databit(bool bit);
void reset();
private:
M17RX_STATE m_state;
uint32_t m_bitBuffer;
uint8_t m_outBuffer[M17_FRAME_LENGTH_BYTES + 3U];
uint8_t* m_buffer;
uint16_t m_bufferPtr;
uint16_t m_lostCount;
void processNone(bool bit);
void processData(bool bit);
void writeRSSIData(uint8_t* data);
};
#endif

124
M17TX.cpp Normal file
View file

@ -0,0 +1,124 @@
/*
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#include "Globals.h"
#include "M17TX.h"
#include "M17Defines.h"
const uint8_t M17_SYNC = 0x77U;
const uint8_t M17_PREAMBLE = 0x77U;
CM17TX::CM17TX() :
m_buffer(1500U),
m_poBuffer(),
m_poLen(0U),
m_poPtr(0U),
m_txDelay(240U), // 200ms
m_delay(false)
{
}
void CM17TX::process()
{
if (m_buffer.getData() == 0U && m_poLen == 0U)
return;
if (m_poLen == 0U) {
if (!m_tx) {
m_delay = true;
m_poLen = m_txDelay;
} else {
m_delay = false;
for (uint8_t i = 0U; i < M17_FRAME_LENGTH_BYTES; i++)
m_poBuffer[m_poLen++] = m_buffer.get();
}
m_poPtr = 0U;
}
if (m_poLen > 0U) {
uint16_t space = io.getSpace();
while (space > 8U) {
if (m_delay) {
writeByte(M17_SYNC);
m_poPtr++;
} else
writeByte(m_poBuffer[m_poPtr++]);
space -= 8U;
if (m_poPtr >= m_poLen) {
if (m_delay) {
m_delay = false;
m_poPtr = 0U;
m_poLen = 3U;
} else {
m_poPtr = 0U;
m_poLen = 0U;
m_delay = false;
return;
}
}
}
}
}
uint8_t CM17TX::writeData(const uint8_t* data, uint8_t length)
{
if (length != (M17_FRAME_LENGTH_BYTES + 1U))
return 4U;
uint16_t space = m_buffer.getSpace();
if (space < M17_FRAME_LENGTH_BYTES)
return 5U;
for (uint8_t i = 0U; i < M17_FRAME_LENGTH_BYTES; i++)
m_buffer.put(data[i + 1U]);
return 0U;
}
void CM17TX::writeByte(uint8_t c)
{
uint8_t bit;
uint8_t mask = 0x80U;
for (uint8_t i = 0U; i < 8U; i++, c <<= 1) {
if ((c & mask) == mask)
bit = 1U;
else
bit = 0U;
io.write(&bit, 1);
}
}
void CM17TX::setTXDelay(uint8_t delay)
{
m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay
}
uint8_t CM17TX::getSpace() const
{
return m_buffer.getSpace() / M17_FRAME_LENGTH_BYTES;
}

50
M17TX.h Normal file
View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(M17TX_H)
#define M17TX_H
#include "Config.h"
#include "SerialRB.h"
class CM17TX {
public:
CM17TX();
uint8_t writeData(const uint8_t* data, uint8_t length);
void process();
void setTXDelay(uint8_t delay);
uint8_t getSpace() const;
private:
CSerialRB m_buffer;
uint8_t m_poBuffer[1200U];
uint16_t m_poLen;
uint16_t m_poPtr;
uint16_t m_txDelay;
bool m_delay;
void writeByte(uint8_t c);
};
#endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Mathis Schmieder DB9MAT * Copyright (C) 2016 by Mathis Schmieder DB9MAT
* Copyright (C) 2016 by Colin Durbridge G4EML * Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU
@ -43,6 +43,7 @@ bool m_dmrEnable = true;
bool m_ysfEnable = true; bool m_ysfEnable = true;
bool m_p25Enable = true; bool m_p25Enable = true;
bool m_nxdnEnable = true; bool m_nxdnEnable = true;
bool m_m17Enable = true;
bool m_pocsagEnable = true; bool m_pocsagEnable = true;
bool m_duplex = false; bool m_duplex = false;
@ -70,6 +71,9 @@ CYSFTX ysfTX;
CP25RX p25RX; CP25RX p25RX;
CP25TX p25TX; CP25TX p25TX;
CM17RX m17RX;
CM17TX m17TX;
CNXDNRX nxdnRX; CNXDNRX nxdnRX;
CNXDNTX nxdnTX; CNXDNTX nxdnTX;
@ -125,6 +129,9 @@ void loop()
if (m_nxdnEnable && m_modemState == STATE_NXDN) if (m_nxdnEnable && m_modemState == STATE_NXDN)
nxdnTX.process(); nxdnTX.process();
if (m_m17Enable && m_modemState == STATE_M17)
m17TX.process();
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy())) if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
pocsagTX.process(); pocsagTX.process();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML * Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU * Copyright (C) 2016,2017 by Andy Uribe CA6JAU
* *
@ -38,6 +38,7 @@ bool m_dmrEnable = true;
bool m_ysfEnable = true; bool m_ysfEnable = true;
bool m_p25Enable = true; bool m_p25Enable = true;
bool m_nxdnEnable = true; bool m_nxdnEnable = true;
bool m_m17Enable = true;
bool m_pocsagEnable = true; bool m_pocsagEnable = true;
bool m_duplex = false; bool m_duplex = false;
@ -65,6 +66,9 @@ CYSFTX ysfTX;
CP25RX p25RX; CP25RX p25RX;
CP25TX p25TX; CP25TX p25TX;
CM17RX m17RX;
CM17TX m17TX;
CNXDNRX nxdnRX; CNXDNRX nxdnRX;
CNXDNTX nxdnTX; CNXDNTX nxdnTX;
@ -115,6 +119,9 @@ void loop()
if (m_nxdnEnable && m_modemState == STATE_NXDN) if (m_nxdnEnable && m_modemState == STATE_NXDN)
nxdnTX.process(); nxdnTX.process();
if (m_m17Enable && m_modemState == STATE_M17)
m17TX.process();
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy())) if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
pocsagTX.process(); pocsagTX.process();

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013,2015,2016,2018 by Jonathan Naylor G4KLX * Copyright (C) 2013,2015,2016,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML * Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU
* Copyright (C) 2019 by Florian Wolters DF2ET * Copyright (C) 2019 by Florian Wolters DF2ET
@ -60,6 +60,9 @@ const uint8_t MMDVM_P25_LOST = 0x32U;
const uint8_t MMDVM_NXDN_DATA = 0x40U; const uint8_t MMDVM_NXDN_DATA = 0x40U;
const uint8_t MMDVM_NXDN_LOST = 0x41U; const uint8_t MMDVM_NXDN_LOST = 0x41U;
const uint8_t MMDVM_M17_DATA = 0x45U;
const uint8_t MMDVM_M17_LOST = 0x46U;
const uint8_t MMDVM_POCSAG_DATA = 0x50U; const uint8_t MMDVM_POCSAG_DATA = 0x50U;
const uint8_t MMDVM_ACK = 0x70U; const uint8_t MMDVM_ACK = 0x70U;
@ -126,7 +129,7 @@ void CSerialPort::getStatus()
// Send all sorts of interesting internal values // Send all sorts of interesting internal values
reply[0U] = MMDVM_FRAME_START; reply[0U] = MMDVM_FRAME_START;
reply[1U] = 13U; reply[1U] = 14U;
reply[2U] = MMDVM_GET_STATUS; reply[2U] = MMDVM_GET_STATUS;
reply[3U] = 0x00U; reply[3U] = 0x00U;
@ -142,6 +145,8 @@ void CSerialPort::getStatus()
reply[3U] |= 0x10U; reply[3U] |= 0x10U;
if (m_pocsagEnable) if (m_pocsagEnable)
reply[3U] |= 0x20U; reply[3U] |= 0x20U;
if (m_m17Enable)
reply[3U] |= 0x80U;
reply[4U] = uint8_t(m_modemState); reply[4U] = uint8_t(m_modemState);
@ -196,7 +201,12 @@ void CSerialPort::getStatus()
else else
reply[12U] = 0U; reply[12U] = 0U;
writeInt(1U, reply, 13); if (m_m17Enable)
reply[13U] = m17TX.getSpace();
else
reply[13U] = 0U;
writeInt(1U, reply, 14);
} }
void CSerialPort::getVersion() void CSerialPort::getVersion()
@ -226,7 +236,7 @@ void CSerialPort::getVersion()
uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
{ {
if (length < 13U) if (length < 23U)
return 4U; return 4U;
bool ysfLoDev = (data[0U] & 0x08U) == 0x08U; bool ysfLoDev = (data[0U] & 0x08U) == 0x08U;
@ -240,6 +250,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
bool p25Enable = (data[1U] & 0x08U) == 0x08U; bool p25Enable = (data[1U] & 0x08U) == 0x08U;
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U; bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
bool pocsagEnable = (data[1U] & 0x20U) == 0x20U; bool pocsagEnable = (data[1U] & 0x20U) == 0x20U;
bool m17Enable = (data[1U] & 0x80U) == 0x80U;
uint8_t txDelay = data[2U]; uint8_t txDelay = data[2U];
if (txDelay > 50U) if (txDelay > 50U)
@ -247,7 +258,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
MMDVM_STATE modemState = MMDVM_STATE(data[3U]); MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_DMRDMO1K && modemState != STATE_INTCAL && modemState != STATE_RSSICAL && modemState != STATE_POCSAGCAL) if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_M17 && modemState != STATE_POCSAG && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_DMRDMO1K && modemState != STATE_INTCAL && modemState != STATE_RSSICAL && modemState != STATE_POCSAGCAL)
return 4U; return 4U;
if (modemState == STATE_DSTAR && !dstarEnable) if (modemState == STATE_DSTAR && !dstarEnable)
return 4U; return 4U;
@ -261,6 +272,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
return 4U; return 4U;
if (modemState == STATE_POCSAG && !pocsagEnable) if (modemState == STATE_POCSAG && !pocsagEnable)
return 4U; return 4U;
if (modemState == STATE_M17 && !m17Enable)
return 4U;
uint8_t colorCode = data[6U]; uint8_t colorCode = data[6U];
if (colorCode > 15U) if (colorCode > 15U)
@ -276,22 +289,18 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
uint8_t dmrTXLevel = data[10U]; uint8_t dmrTXLevel = data[10U];
uint8_t ysfTXLevel = data[11U]; uint8_t ysfTXLevel = data[11U];
uint8_t p25TXLevel = data[12U]; uint8_t p25TXLevel = data[12U];
uint8_t nxdnTXLevel = 128U; uint8_t nxdnTXLevel = data[15U];
uint8_t pocsagTXLevel = 128U; uint8_t pocsagTXLevel = data[17U];
uint8_t m17TXLevel = data[21U];
if (length >= 16U) io.setDeviations(dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, m17TXLevel, pocsagTXLevel, ysfLoDev);
nxdnTXLevel = data[15U];
if (length >= 18U)
pocsagTXLevel = data[17U];
io.setDeviations(dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, ysfLoDev);
m_dstarEnable = dstarEnable; m_dstarEnable = dstarEnable;
m_dmrEnable = dmrEnable; m_dmrEnable = dmrEnable;
m_ysfEnable = ysfEnable; m_ysfEnable = ysfEnable;
m_p25Enable = p25Enable; m_p25Enable = p25Enable;
m_nxdnEnable = nxdnEnable; m_nxdnEnable = nxdnEnable;
m_m17Enable = m17Enable;
m_pocsagEnable = pocsagEnable; m_pocsagEnable = pocsagEnable;
if (modemState == STATE_DMRCAL || modemState == STATE_DMRDMO1K || modemState == STATE_RSSICAL || modemState == STATE_INTCAL) { if (modemState == STATE_DMRCAL || modemState == STATE_DMRDMO1K || modemState == STATE_RSSICAL || modemState == STATE_INTCAL) {
@ -332,6 +341,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
ysfTX.setTXDelay(txDelay); ysfTX.setTXDelay(txDelay);
p25TX.setTXDelay(txDelay); p25TX.setTXDelay(txDelay);
nxdnTX.setTXDelay(txDelay); nxdnTX.setTXDelay(txDelay);
m17TX.setTXDelay(txDelay);
pocsagTX.setTXDelay(txDelay); pocsagTX.setTXDelay(txDelay);
dmrDMOTX.setTXDelay(txDelay); dmrDMOTX.setTXDelay(txDelay);
@ -357,6 +367,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
io.ifConf(STATE_P25, true); io.ifConf(STATE_P25, true);
else if(m_nxdnEnable) else if(m_nxdnEnable)
io.ifConf(STATE_NXDN, true); io.ifConf(STATE_NXDN, true);
else if(m_m17Enable)
io.ifConf(STATE_M17, true);
else if(m_pocsagEnable) else if(m_pocsagEnable)
io.ifConf(STATE_POCSAG, true); io.ifConf(STATE_POCSAG, true);
} }
@ -383,7 +395,7 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
if (modemState == m_modemState) if (modemState == m_modemState)
return 0U; return 0U;
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_DMRDMO1K && modemState != STATE_RSSICAL && modemState != STATE_INTCAL && modemState != STATE_POCSAGCAL) if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_M17 && modemState != STATE_POCSAG && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_DMRDMO1K && modemState != STATE_RSSICAL && modemState != STATE_INTCAL && modemState != STATE_POCSAGCAL)
return 4U; return 4U;
if (modemState == STATE_DSTAR && !m_dstarEnable) if (modemState == STATE_DSTAR && !m_dstarEnable)
return 4U; return 4U;
@ -395,6 +407,8 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
return 4U; return 4U;
if (modemState == STATE_NXDN && !m_nxdnEnable) if (modemState == STATE_NXDN && !m_nxdnEnable)
return 4U; return 4U;
if (modemState == STATE_M17 && !m_m17Enable)
return 4U;
if (modemState == STATE_POCSAG && !m_pocsagEnable) if (modemState == STATE_POCSAG && !m_pocsagEnable)
return 4U; return 4U;
@ -469,6 +483,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
ysfRX.reset(); ysfRX.reset();
p25RX.reset(); p25RX.reset();
nxdnRX.reset(); nxdnRX.reset();
m17RX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
case STATE_DSTAR: case STATE_DSTAR:
@ -481,6 +496,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
ysfRX.reset(); ysfRX.reset();
p25RX.reset(); p25RX.reset();
nxdnRX.reset(); nxdnRX.reset();
m17RX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
case STATE_YSF: case STATE_YSF:
@ -493,6 +509,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
dstarRX.reset(); dstarRX.reset();
p25RX.reset(); p25RX.reset();
nxdnRX.reset(); nxdnRX.reset();
m17RX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
case STATE_P25: case STATE_P25:
@ -505,6 +522,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
dstarRX.reset(); dstarRX.reset();
ysfRX.reset(); ysfRX.reset();
nxdnRX.reset(); nxdnRX.reset();
m17RX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
case STATE_NXDN: case STATE_NXDN:
@ -517,6 +535,20 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
dstarRX.reset(); dstarRX.reset();
ysfRX.reset(); ysfRX.reset();
p25RX.reset(); p25RX.reset();
m17RX.reset();
cwIdTX.reset();
break;
case STATE_M17:
DEBUG1("Mode set to M17");
#if defined(DUPLEX)
dmrIdleRX.reset();
dmrRX.reset();
#endif
dmrDMORX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
nxdnRX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
case STATE_POCSAG: case STATE_POCSAG:
@ -530,6 +562,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
ysfRX.reset(); ysfRX.reset();
p25RX.reset(); p25RX.reset();
nxdnRX.reset(); nxdnRX.reset();
m17RX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
default: default:
@ -831,6 +864,20 @@ void CSerialPort::process()
} }
break; break;
case MMDVM_M17_DATA:
if (m_m17Enable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_M17)
err = m17TX.writeData(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_M17);
} else {
DEBUG2("Received invalid M17 data", err);
sendNAK(err);
}
break;
case MMDVM_POCSAG_DATA: case MMDVM_POCSAG_DATA:
if (m_pocsagEnable) { if (m_pocsagEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_POCSAG) { if (m_modemState == STATE_IDLE || m_modemState == STATE_POCSAG) {
@ -1186,6 +1233,46 @@ void CSerialPort::writeNXDNLost()
writeInt(1U, reply, 3); writeInt(1U, reply, 3);
} }
void CSerialPort::writeM17Data(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_M17 && m_modemState != STATE_IDLE)
return;
if (!m_m17Enable)
return;
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_M17_DATA;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
writeInt(1U, reply, count);
}
void CSerialPort::writeM17Lost()
{
if (m_modemState != STATE_M17 && m_modemState != STATE_IDLE)
return;
if (!m_m17Enable)
return;
uint8_t reply[3U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = MMDVM_M17_LOST;
writeInt(1U, reply, 3);
}
#if defined(SEND_RSSI_DATA) #if defined(SEND_RSSI_DATA)
void CSerialPort::writeRSSIData(const uint8_t* data, uint8_t length) void CSerialPort::writeRSSIData(const uint8_t* data, uint8_t length)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Andy Uribe CA6JAU * Copyright (C) 2018 by Andy Uribe CA6JAU
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -52,6 +52,9 @@ public:
void writeNXDNData(const uint8_t* data, uint8_t length); void writeNXDNData(const uint8_t* data, uint8_t length);
void writeNXDNLost(); void writeNXDNLost();
void writeM17Data(const uint8_t* data, uint8_t length);
void writeM17Lost();
#if defined(SEND_RSSI_DATA) #if defined(SEND_RSSI_DATA)
void writeRSSIData(const uint8_t* data, uint8_t length); void writeRSSIData(const uint8_t* data, uint8_t length);
#endif #endif

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
#define USE_ALTERNATE_POCSAG_LEDS #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
#define USE_ALTERNATE_POCSAG_LEDS #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
#define USE_ALTERNATE_POCSAG_LEDS #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
#define USE_ALTERNATE_POCSAG_LEDS #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -92,6 +92,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -91,6 +91,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -93,6 +93,9 @@
// Use the YSF and P25 LEDs for NXDN // Use the YSF and P25 LEDs for NXDN
// #define USE_ALTERNATE_NXDN_LEDS // #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and P25 LEDs for M17
// #define USE_ALTERNATE_M17_LEDS
// Use the D-Star and DMR LEDs for POCSAG // Use the D-Star and DMR LEDs for POCSAG
// #define USE_ALTERNATE_POCSAG_LEDS // #define USE_ALTERNATE_POCSAG_LEDS

View file

@ -25,7 +25,7 @@
#define VER_MAJOR "1" #define VER_MAJOR "1"
#define VER_MINOR "5" #define VER_MINOR "5"
#define VER_REV "1b" #define VER_REV "1b"
#define VERSION_DATE "20191201" #define VERSION_DATE "20201023"
#if defined(ZUMSPOT_ADF7021) #if defined(ZUMSPOT_ADF7021)
#define BOARD_INFO "ZUMspot" #define BOARD_INFO "ZUMspot"