Compare commits

..
Author SHA1 Message Date
phl0 1be760ad56 Free already used pin 2018-07-24 21:04:53 +02:00
phl0 4c81f4ca7a Implement MODE pins for F7Hat 2018-07-24 20:46:41 +02:00
phl0 0d7d903e21 Add POCSAG mode pin 2018-07-24 20:36:17 +02:00
134 changed files with 5248 additions and 8668 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -77,7 +77,6 @@ const struct {
{',', 0xEEAEE000U, 22U},
{'-', 0xEAAE0000U, 18U},
{'=', 0xEAB80000U, 16U},
{'.', 0xBAEB8000U, 20U},
{' ', 0x00000000U, 4U},
{0U, 0x00000000U, 0U}
};
@@ -125,7 +124,7 @@ void CCWIdTX::process()
}
}
uint8_t CCWIdTX::write(const uint8_t* data, uint16_t length)
uint8_t CCWIdTX::write(const uint8_t* data, uint8_t length)
{
::memset(m_poBuffer, 0x00U, 1000U * sizeof(uint8_t));
@@ -171,3 +170,4 @@ void CCWIdTX::reset()
m_poPtr = 0U;
m_n = 0U;
}
+2 -2
View File
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2020 by Colin Durbridge G4EML
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* 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
@@ -28,7 +28,7 @@ public:
void process();
uint8_t write(const uint8_t* data, uint16_t length);
uint8_t write(const uint8_t* data, uint8_t length);
void reset();
+2 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -18,9 +18,6 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "CalDMR.h"
@@ -211,7 +208,7 @@ void CCalDMR::dmrdmo1k()
}
}
uint8_t CCalDMR::write(const uint8_t* data, uint16_t length)
uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
{
if (length != 1U)
return 4U;
@@ -224,5 +221,3 @@ uint8_t CCalDMR::write(const uint8_t* data, uint16_t length)
return 0U;
}
#endif
+3 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -17,13 +17,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(CALDMR_H)
#define CALDMR_H
#include "Config.h"
#include "DMRDefines.h"
enum DMRCAL1K {
@@ -44,7 +41,7 @@ public:
void createData1k(uint8_t n);
void createDataDMO1k(uint8_t n);
uint8_t write(const uint8_t* data, uint16_t length);
uint8_t write(const uint8_t* data, uint8_t length);
private:
bool m_transmit;
@@ -56,5 +53,3 @@ private:
#endif
#endif
+2 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2016 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#include "Globals.h"
#include "CalDStarRX.h"
#include "Utils.h"
@@ -27,7 +24,7 @@
const unsigned int BUFFER_LENGTH = 200U;
const uint32_t PLLMAX = 0x10000U;
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_SYMBOL_LENGTH;
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
const uint32_t INC = PLLINC / 32U;
// D-Star bit order version of 0x55 0x2D 0x16
@@ -129,5 +126,3 @@ void CCalDStarRX::process(q15_t value)
}
}
#endif
+2 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016 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
@@ -16,13 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#if !defined(CALDSTARRX_H)
#define CALDSTARRX_H
#include "Config.h"
#include "DStarDefines.h"
class CCalDStarRX {
@@ -43,5 +40,3 @@ private:
#endif
#endif
+2 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2016 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#include "Globals.h"
#include "CalDStarTX.h"
@@ -165,7 +162,7 @@ void CCalDStarTX::process()
m_count = (m_count + 1U) % (30U * 21U);
}
uint8_t CCalDStarTX::write(const uint8_t* data, uint16_t length)
uint8_t CCalDStarTX::write(const uint8_t* data, uint8_t length)
{
if (length != 1U)
return 4U;
@@ -184,5 +181,3 @@ uint8_t CCalDStarTX::write(const uint8_t* data, uint16_t length)
return 0U;
}
#endif
+3 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016 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
@@ -16,20 +16,17 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#if !defined(CALDSTARTX_H)
#define CALDSTARTX_H
#include "Config.h"
#include "DStarDefines.h"
class CCalDStarTX {
public:
CCalDStarTX();
uint8_t write(const uint8_t* data, uint16_t length);
uint8_t write(const uint8_t* data, uint8_t length);
void process();
@@ -40,5 +37,3 @@ private:
#endif
#endif
-133
View File
@@ -1,133 +0,0 @@
/*
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2020 by Phil Taylor M0VSE
*
* 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"
#if defined(MODE_FM)
#include "Globals.h"
#include "CalFM.h"
const struct TONE_TABLE {
uint16_t frequency;
uint16_t length;
q31_t increment;
} TONE_TABLE_DATA[] = {
{2495U, 10U, 223248821},
{2079U, 12U, 186025772},
{1633U, 15U, 146118367},
{1247U, 19U, 111579672},
{1039U, 23U, 93012886},
{956U, 25U, 85541432}};
const uint8_t TONE_TABLE_DATA_LEN = 6U;
CCalFM::CCalFM() :
m_frequency(0),
m_length(0),
m_tone(NULL),
m_level(128 * 12),
m_transmit(false),
m_audioSeq(0),
m_lastState(STATE_IDLE)
{
}
void CCalFM::process()
{
const TONE_TABLE* entry = NULL;
if (m_modemState != m_lastState)
{
switch (m_modemState) {
case STATE_FMCAL10K:
m_frequency = 956U;
break;
case STATE_FMCAL12K:
m_frequency = 1039U;
break;
case STATE_FMCAL15K:
m_frequency = 1247U;
break;
case STATE_FMCAL20K:
m_frequency = 1633U;
break;
case STATE_FMCAL25K:
m_frequency = 2079U;
break;
case STATE_FMCAL30K:
m_frequency = 2495U;
break;
default:
m_frequency = 0U;
break;
}
for (uint8_t i = 0U; i < TONE_TABLE_DATA_LEN; i++) {
if (TONE_TABLE_DATA[i].frequency == m_frequency) {
entry = TONE_TABLE_DATA + i;
break;
}
}
if (entry == NULL)
return;
m_length = entry->length;
delete[] m_tone;
m_tone = new q15_t[m_length];
q31_t arg = 0;
for (uint16_t i = 0U; i < m_length; i++) {
q63_t value = ::arm_sin_q31(arg) * q63_t(m_level);
m_tone[i] = q15_t(__SSAT((value >> 31), 16));
arg += entry->increment;
}
m_lastState=m_modemState;
}
if (m_transmit)
{
uint16_t space = io.getSpace();
while (space > m_length)
{
io.write(m_modemState,m_tone,m_length);
space -= m_length;
}
}
}
uint8_t CCalFM::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
m_transmit = data[0U] == 1U;
return 0U;
}
#endif
-55
View File
@@ -1,55 +0,0 @@
/*
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2020 by Phil Taylor M0VSE
*
* 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"
#if defined(MODE_FM)
#if !defined(CALFM_H)
#define CALFM_H
class CCalFM {
public:
CCalFM();
void process();
void fm10kcal();
void fm12k5cal();
void fm15kcal();
void fm20kcal();
void fm25kcal();
void fm30kcal();
uint8_t write(const uint8_t* data, uint16_t length);
private:
uint16_t m_frequency;
uint16_t m_length;
q15_t* m_tone;
q15_t m_level;
bool m_transmit;
uint8_t m_audioSeq;
uint8_t m_lastState;
};
#endif
#endif
+1 -7
View File
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 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
@@ -18,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_NXDN)
#include "Globals.h"
#include "CalNXDN.h"
@@ -83,7 +79,7 @@ void CCalNXDN::process()
}
}
uint8_t CCalNXDN::write(const uint8_t* data, uint16_t length)
uint8_t CCalNXDN::write(const uint8_t* data, uint8_t length)
{
if (length != 1U)
return 4U;
@@ -96,5 +92,3 @@ uint8_t CCalNXDN::write(const uint8_t* data, uint16_t length)
return 0U;
}
#endif
+3 -8
View File
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 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
@@ -17,13 +16,11 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_NXDN)
#if !defined(CALNXDN_H)
#define CALNXDN_H
#include "Config.h"
enum NXDNCAL1K {
NXDNCAL1K_IDLE,
NXDNCAL1K_TX
@@ -35,7 +32,7 @@ public:
void process();
uint8_t write(const uint8_t* data, uint16_t length);
uint8_t write(const uint8_t* data, uint8_t length);
private:
bool m_transmit;
@@ -45,5 +42,3 @@ private:
#endif
#endif
+1 -7
View File
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 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
@@ -18,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_P25)
#include "Globals.h"
#include "CalP25.h"
@@ -86,7 +82,7 @@ void CCalP25::process()
}
}
uint8_t CCalP25::write(const uint8_t* data, uint16_t length)
uint8_t CCalP25::write(const uint8_t* data, uint8_t length)
{
if (length != 1U)
return 4U;
@@ -99,5 +95,3 @@ uint8_t CCalP25::write(const uint8_t* data, uint16_t length)
return 0U;
}
#endif
+2 -8
View File
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 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
@@ -17,13 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_P25)
#if !defined(CALP25_H)
#define CALP25_H
#include "Config.h"
#include "P25Defines.h"
enum P25CAL1K {
@@ -38,7 +34,7 @@ public:
void process();
uint8_t write(const uint8_t* data, uint16_t length);
uint8_t write(const uint8_t* data, uint8_t length);
private:
bool m_transmit;
@@ -47,5 +43,3 @@ private:
#endif
#endif
-55
View File
@@ -1,55 +0,0 @@
/*
* Copyright (C) 2019 by Florian Wolters DF2ET
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_POCSAG)
#include "Globals.h"
#include "CalPOCSAG.h"
CCalPOCSAG::CCalPOCSAG() :
m_state(POCSAGCAL_IDLE)
{
}
void CCalPOCSAG::process()
{
if (m_state == POCSAGCAL_IDLE)
return;
uint16_t space = io.getSpace();
if (space <= 165U)
return;
pocsagTX.writeByte(0xAAU);
}
uint8_t CCalPOCSAG::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)
return 4U;
m_state = data[0U] == 1U ? POCSAGCAL_TX : POCSAGCAL_IDLE;
return 0U;
}
#endif
-47
View File
@@ -1,47 +0,0 @@
/*
* Copyright (C) 2019 by Florian Wolters DF2ET
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_POCSAG)
#if !defined(CALPOCSAG_H)
#define CALPOCSAG_H
enum POCSAGCAL {
POCSAGCAL_IDLE,
POCSAGCAL_TX
};
class CCalPOCSAG {
public:
CCalPOCSAG();
void process();
uint8_t write(const uint8_t* data, uint16_t length);
private:
POCSAGCAL m_state;
};
#endif
#endif
+14 -48
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 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
@@ -19,31 +19,6 @@
#if !defined(CONFIG_H)
#define CONFIG_H
// Allow for the selection of which modes to compile into the firmware. This is particularly useful for processors
// which have limited code space and processing power.
// Enable D-Star support.
#define MODE_DSTAR
// Enable DMR support.
#define MODE_DMR
// Enable System Fusion support.
#define MODE_YSF
// Enable P25 phase 1 support.
#define MODE_P25
// Enable NXDN support, the boxcar filter sometimes improves the performance of NXDN receive on some systems.
#define MODE_NXDN
#define USE_NXDN_BOXCAR
// Enable POCSAG support.
#define MODE_POCSAG
// Enable FM support.
#define MODE_FM
// Allow for the use of high quality external clock oscillators
// The number is the frequency of the oscillator in Hertz.
//
@@ -60,20 +35,20 @@
// For 19.2 MHz
// #define EXTERNAL_OSC 19200000
// Select a baud rate for host communication. The faster speeds are needed for external FM to work.
// #define SERIAL_SPEED 115200 // Suitable for most older boards (Arduino Due, etc). External FM will NOT work with this!
// #define SERIAL_SPEED 230400 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM might work with this
#define SERIAL_SPEED 460800 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM should work with this
//#define SERIAL_SPEED 500000 // Used with newer boards and Armbian on AllWinner SOCs (H2, H3) that do not support 460800
// Allow the use of the COS line to lockout the modem
// #define USE_COS_AS_LOCKOUT
// Use pins to output the current mode via LEDs
#define MODE_LEDS
// Use pins to output the current mode
// #define MODE_PINS
// For the original Arduino Due pin layout
// #define ARDUINO_DUE_PAPA
// For the ZUM V1.0 and V1.0.1 boards pin layout
// #define ARDUINO_DUE_ZUM_V10
#define ARDUINO_DUE_ZUM_V10
// For the SQ6POG board
// #define STM32F1_POG
// For the SP8NTH board
// #define ARDUINO_DUE_NTH
@@ -82,23 +57,17 @@
// #define STM32F4_NUCLEO_MORPHO_HEADER
// #define STM32F4_NUCLEO_ARDUINO_HEADER
// Use separate mode pins to switch external channel/filters/bandwidth for example
// #define MODE_PINS
// Use separate mode pins to switch external filters/bandwidth for example
// #define STM32F4_NUCLEO_MODE_PINS
// For the VK6MST Pi3 Shield communicating over i2c. i2c address & speed defined in i2cTeensy.cpp
// #define VK6MST_TEENSY_PI3_SHIELD_I2C
// Pass RSSI information to the host
#define SEND_RSSI_DATA
// #define SEND_RSSI_DATA
// Use the modem as a serial repeater for Nextion displays
#define SERIAL_REPEATER
// Set the baud rate of the modem serial repeater for Nextion displays
#define SERIAL_REPEATER_BAUD_RATE 9600
// Use the modem as an I2C repeater for OLED displays
// #define I2C_REPEATER
// #define SERIAL_REPEATER
// To reduce CPU load, you can remove the DC blocker by commenting out the next line
#define USE_DCBLOCKER
@@ -111,10 +80,7 @@
// #define USE_ALTERNATE_NXDN_LEDS
// Use the D-Star and DMR LEDs for POCSAG
#define USE_ALTERNATE_POCSAG_LEDS
// Use the D-Star and YSF LEDs for FM
#define USE_ALTERNATE_FM_LEDS
// #define USE_ALTERNATE_POCSAG_LEDS
#endif
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRDMORX.h"
#include "DMRSlotType.h"
@@ -426,6 +423,3 @@ void CDMRDMORX::writeRSSIData(uint8_t* frame)
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
}
#endif
+2 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017 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
@@ -16,13 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRDMORX_H)
#define DMRDMORX_H
#include "Config.h"
#include "DMRDefines.h"
const uint16_t DMO_BUFFER_LENGTH_SAMPLES = 1440U; // 60ms at 24 kHz
@@ -70,6 +67,3 @@ private:
};
#endif
#endif
+3 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
@@ -19,9 +19,6 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotType.h"
@@ -77,7 +74,7 @@ void CDMRDMOTX::process()
m_poLen = m_txDelay;
} else {
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++)
m_fifo.get(m_poBuffer[i]);
m_poBuffer[i] = m_fifo.get();
for (unsigned int i = 0U; i < 39U; i++)
m_poBuffer[i + DMR_FRAME_LENGTH_BYTES] = PR_FILL[i];
@@ -107,7 +104,7 @@ void CDMRDMOTX::process()
}
}
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint16_t length)
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -164,5 +161,3 @@ void CDMRDMOTX::setTXDelay(uint8_t delay)
m_txDelay = 1200U;
}
#endif
+5 -10
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -17,22 +17,19 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRDMOTX_H)
#define DMRDMOTX_H
#include "Config.h"
#include "DMRDefines.h"
#include "RingBuffer.h"
#include "SerialRB.h"
class CDMRDMOTX {
public:
CDMRDMOTX();
uint8_t writeData(const uint8_t* data, uint16_t length);
uint8_t writeData(const uint8_t* data, uint8_t length);
void process();
@@ -41,7 +38,7 @@ public:
uint8_t getSpace() const;
private:
CRingBuffer<uint8_t> m_fifo;
CSerialRB m_fifo;
arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
uint8_t m_poBuffer[1200U];
@@ -54,5 +51,3 @@ private:
#endif
#endif
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRIdleRX.h"
#include "DMRSlotType.h"
@@ -212,6 +209,3 @@ void CDMRIdleRX::setColorCode(uint8_t colorCode)
{
m_colorCode = colorCode;
}
#endif
+2 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015 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
@@ -16,13 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRIDLERX_H)
#define DMRIDLERX_H
#include "Config.h"
#include "DMRDefines.h"
class CDMRIdleRX {
@@ -52,5 +49,3 @@ private:
#endif
#endif
+1 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRRX.h"
@@ -71,5 +68,3 @@ void CDMRRX::reset()
m_slot2RX.reset();
}
#endif
+2 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016 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
@@ -16,13 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRRX_H)
#define DMRRX_H
#include "Config.h"
#include "DMRSlotRX.h"
class CDMRRX {
@@ -43,5 +40,3 @@ private:
#endif
#endif
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotRX.h"
#include "DMRSlotType.h"
@@ -403,6 +400,3 @@ void CDMRSlotRX::writeRSSIData(uint8_t* frame)
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
}
#endif
+2 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017 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
@@ -16,13 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRSLOTRX_H)
#define DMRSLOTRX_H
#include "Config.h"
#include "DMRDefines.h"
enum DMRRX_STATE {
@@ -73,6 +70,3 @@ private:
};
#endif
#endif
+1 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotType.h"
@@ -288,5 +285,3 @@ void CDMRSlotType::encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) c
frame[20U] = (frame[20U] & 0x03U) | ((slotType[1U] << 6) & 0xC0U) | ((slotType[2U] >> 2) & 0x3CU);
}
#endif
+1 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015 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
@@ -16,10 +16,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRSLOTTYPE_H)
#define DMRSLOTTYPE_H
@@ -39,5 +35,3 @@ private:
#endif
#endif
+6 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
@@ -19,9 +19,6 @@
*/
#include "Config.h"
#if defined(MODE_DMR)
#include "Globals.h"
#include "DMRSlotType.h"
@@ -147,7 +144,7 @@ void CDMRTX::process()
}
}
uint8_t CDMRTX::writeData1(const uint8_t* data, uint16_t length)
uint8_t CDMRTX::writeData1(const uint8_t* data, uint8_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -171,7 +168,7 @@ uint8_t CDMRTX::writeData1(const uint8_t* data, uint16_t length)
return 0U;
}
uint8_t CDMRTX::writeData2(const uint8_t* data, uint16_t length)
uint8_t CDMRTX::writeData2(const uint8_t* data, uint8_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -195,7 +192,7 @@ uint8_t CDMRTX::writeData2(const uint8_t* data, uint16_t length)
return 0U;
}
uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint16_t length)
uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length)
{
if (length != 9U)
return 4U;
@@ -211,7 +208,7 @@ uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint16_t length)
return 0U;
}
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint16_t length)
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint8_t length)
{
if (length != 1U)
return 4U;
@@ -296,7 +293,7 @@ void CDMRTX::createData(uint8_t slotIndex)
{
if (m_fifo[slotIndex].getData() >= DMR_FRAME_LENGTH_BYTES && m_frameCount >= STARTUP_COUNT && m_abortCount[slotIndex] >= ABORT_COUNT) {
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
m_fifo[slotIndex].get(m_poBuffer[i]);
m_poBuffer[i] = m_fifo[slotIndex].get();
m_markBuffer[i] = MARK_NONE;
}
} else {
@@ -417,6 +414,3 @@ uint32_t CDMRTX::getFrameCount()
{
return m_frameCount;
}
#endif
+8 -13
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -17,16 +17,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DMR)
#if !defined(DMRTX_H)
#define DMRTX_H
#include "Config.h"
#include "DMRDefines.h"
#include "RingBuffer.h"
#include "SerialRB.h"
enum DMRTXSTATE {
DMRTXSTATE_IDLE,
@@ -41,11 +38,11 @@ class CDMRTX {
public:
CDMRTX();
uint8_t writeData1(const uint8_t* data, uint16_t length);
uint8_t writeData2(const uint8_t* data, uint16_t length);
uint8_t writeData1(const uint8_t* data, uint8_t length);
uint8_t writeData2(const uint8_t* data, uint8_t length);
uint8_t writeShortLC(const uint8_t* data, uint16_t length);
uint8_t writeAbort(const uint8_t* data, uint16_t length);
uint8_t writeShortLC(const uint8_t* data, uint8_t length);
uint8_t writeAbort(const uint8_t* data, uint8_t length);
void setStart(bool start);
void setCal(bool start);
@@ -62,7 +59,7 @@ public:
void setColorCode(uint8_t colorCode);
private:
CRingBuffer<uint8_t> m_fifo[2U];
CSerialRB m_fifo[2U];
arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
DMRTXSTATE m_state;
@@ -86,5 +83,3 @@ private:
#endif
#endif
+17 -37
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2015,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2015 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
@@ -19,50 +19,30 @@
#if !defined(DSTARDEFINES_H)
#define DSTARDEFINES_H
const unsigned int DSTAR_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int DSTAR_RADIO_BIT_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
const unsigned int DSTAR_HEADER_LENGTH_BITS = DSTAR_HEADER_LENGTH_BYTES * 8U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_SYMBOLS = 660U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U;
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
const unsigned int DSTAR_DATA_LENGTH_SYMBOLS = DSTAR_DATA_LENGTH_BYTES * 8U;
const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U;
const unsigned int DSTAR_END_SYNC_LENGTH_BYTES = 6U;
const unsigned int DSTAR_END_SYNC_LENGTH_BITS = DSTAR_END_SYNC_LENGTH_BYTES * 8U;
const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U;
const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U;
const unsigned int DSTAR_FRAME_SYNC_LENGTH_BYTES = 3U;
const unsigned int DSTAR_FRAME_SYNC_LENGTH_SYMBOLS = DSTAR_FRAME_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_FRAME_SYNC_LENGTH_SAMPLES = DSTAR_FRAME_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const uint8_t DSTAR_DATA_SYNC_LENGTH_BYTES = 3U;
const uint8_t DSTAR_DATA_SYNC_LENGTH_BITS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_DATA_SYNC_LENGTH_BYTES = 3U;
const unsigned int DSTAR_DATA_SYNC_LENGTH_SYMBOLS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_DATA_SYNC_LENGTH_SAMPLES = DSTAR_DATA_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
// D-Star bit order version of 0x55 0x6E 0x0A
const uint32_t DSTAR_FRAME_SYNC_DATA = 0x00557650U;
const uint32_t DSTAR_FRAME_SYNC_MASK = 0x00FFFFFFU;
const bool DSTAR_FRAME_SYNC_SYMBOLS[] = {false, true, false, true, false, true, false, true, false, true, true, true, false, true, true, false, false, true, false, true, false, false, false, false};
// D-Star bit order version of 0x55 0x2D 0x16
const uint32_t DSTAR_DATA_SYNC_DATA = 0x00AAB468U;
const uint32_t DSTAR_DATA_SYNC_MASK = 0x00FFFFFFU;
const bool DSTAR_DATA_SYNC_SYMBOLS[] = {true, false, true, false, true, false, true, false, true, false, true, true, false, true, false, false, false, true, true, false, true, false, false, false};
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
const uint32_t DSTAR_END_SYNC_DATA = 0xAAAA135EU;
const uint32_t DSTAR_END_SYNC_MASK = 0xFFFFFFFFU;
const uint8_t DSTAR_END_SYNC_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
#endif
+142 -249
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
@@ -18,28 +18,31 @@
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#include "Globals.h"
#include "DStarRX.h"
#include "Utils.h"
const unsigned int MAX_FRAMES = 150U;
const unsigned int BUFFER_LENGTH = 200U;
const uint32_t PLLMAX = 0x10000U;
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
const uint32_t INC = PLLINC / 32U;
const unsigned int MAX_SYNC_BITS = 100U * DSTAR_DATA_LENGTH_BITS;
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
const uint64_t FRAME_SYNC_DATA = 0x0000000000557650U;
const uint64_t FRAME_SYNC_MASK = 0x0000000000FFFFFFU;
const uint32_t FRAME_SYNC_DATA = 0x00557650U;
const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU;
const uint8_t FRAME_SYNC_ERRS = 2U;
// D-Star bit order version of 0x55 0x2D 0x16
const uint64_t DATA_SYNC_DATA = 0x0000000000AAB468U;
const uint64_t DATA_SYNC_MASK = 0x0000000000FFFFFFU;
const uint32_t DATA_SYNC_DATA = 0x00AAB468U;
const uint32_t DATA_SYNC_MASK = 0x00FFFFFFU;
const uint8_t DATA_SYNC_ERRS = 2U;
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
const uint64_t END_SYNC_DATA = 0x0000AAAAAAAA135EU;
const uint64_t END_SYNC_MASK = 0x0000FFFFFFFFFFFFU;
const uint32_t END_SYNC_DATA = 0xAAAA135EU;
const uint32_t END_SYNC_MASK = 0xFFFFFFFFU;
const uint8_t END_SYNC_ERRS = 1U;
const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
@@ -234,24 +237,14 @@ const uint16_t CCITT_TABLE[] = {
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U};
const uint16_t NOENDPTR = 9999U;
CDStarRX::CDStarRX() :
m_pll(0U),
m_prev(false),
m_rxState(DSRXS_NONE),
m_bitBuffer(),
m_headerBuffer(),
m_dataBuffer(),
m_bitPtr(0U),
m_headerPtr(0U),
m_dataPtr(0U),
m_startPtr(NOENDPTR),
m_syncPtr(NOENDPTR),
m_minSyncPtr(NOENDPTR),
m_maxSyncPtr(NOENDPTR),
m_maxFrameCorr(0),
m_maxDataCorr(0),
m_frameCount(0U),
m_countdown(0U),
m_patternBuffer(0x00U),
m_rxBuffer(),
m_rxBufferBits(0U),
m_dataBits(0U),
m_mar(0U),
m_pathMetric(),
m_pathMemory0(),
@@ -266,20 +259,14 @@ m_rssiCount(0U)
void CDStarRX::reset()
{
m_rxState = DSRXS_NONE;
m_headerPtr = 0U;
m_dataPtr = 0U;
m_bitPtr = 0U;
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
m_startPtr = NOENDPTR;
m_syncPtr = NOENDPTR;
m_minSyncPtr = NOENDPTR;
m_maxSyncPtr = NOENDPTR;
m_frameCount = 0U;
m_countdown = 0U;
m_rssiAccum = 0U;
m_rssiCount = 0U;
m_pll = 0U;
m_prev = false;
m_rxState = DSRXS_NONE;
m_patternBuffer = 0x00U;
m_rxBufferBits = 0U;
m_dataBits = 0U;
m_rssiAccum = 0U;
m_rssiCount = 0U;
}
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
@@ -288,117 +275,125 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt
m_rssiAccum += rssi[i];
m_rssiCount++;
q15_t sample = samples[i];
bool bit = samples[i] < 0;
m_bitBuffer[m_bitPtr] <<= 1;
if (sample < 0)
m_bitBuffer[m_bitPtr] |= 0x01U;
m_dataBuffer[m_dataPtr] = sample;
switch (m_rxState) {
case DSRXS_HEADER:
processHeader(sample);
break;
case DSRXS_DATA:
processData();
break;
default:
processNone(sample);
break;
if (bit != m_prev) {
if (m_pll < (PLLMAX / 2U))
m_pll += INC;
else
m_pll -= INC;
}
m_dataPtr++;
if (m_dataPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_dataPtr = 0U;
m_prev = bit;
m_bitPtr++;
if (m_bitPtr >= DSTAR_RADIO_SYMBOL_LENGTH)
m_bitPtr = 0U;
m_pll += PLLINC;
if (m_pll >= PLLMAX) {
m_pll -= PLLMAX;
switch (m_rxState) {
case DSRXS_NONE:
processNone(bit);
break;
case DSRXS_HEADER:
processHeader(bit);
break;
case DSRXS_DATA:
processData(bit);
break;
default:
break;
}
}
}
}
void CDStarRX::processNone(q15_t sample)
void CDStarRX::processNone(bool bit)
{
// Fuzzy matching of the frame sync sequence
bool ret = correlateFrameSync();
if (ret) {
m_countdown = 5U;
m_patternBuffer <<= 1;
if (bit)
m_patternBuffer |= 0x01U;
m_headerBuffer[m_headerPtr] = sample;
m_headerPtr++;
// Fuzzy matching of the frame sync sequence
if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
DEBUG1("DStarRX: found frame sync in None");
::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES);
m_rxBufferBits = 0U;
m_rssiAccum = 0U;
m_rssiCount = 0U;
m_rxState = DSRXS_HEADER;
return;
}
// Fuzzy matching of the data sync bit sequence
ret = correlateDataSync();
if (ret) {
// Exact matching of the data sync bit sequence
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) {
DEBUG1("DStarRX: found data sync in None");
io.setDecode(true);
io.setADCDetection(true);
m_rxState = DSRXS_DATA;
// Suppress RSSI on the dummy sync message
m_rssiAccum = 0U;
m_rssiCount = 0U;
::memcpy(m_rxBuffer, DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES);
writeRSSIData(m_rxBuffer);
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U;
m_dataBits = MAX_SYNC_BITS;
m_rxState = DSRXS_DATA;
return;
}
}
void CDStarRX::processHeader(q15_t sample)
void CDStarRX::processHeader(bool bit)
{
if (m_countdown > 0U) {
correlateFrameSync();
m_countdown--;
}
m_patternBuffer <<= 1;
if (bit)
m_patternBuffer |= 0x01U;
m_headerBuffer[m_headerPtr] = sample;
m_headerPtr++;
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
m_rxBufferBits++;
// A full FEC header
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) {
uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES];
samplesToBits(m_headerBuffer, DSTAR_RADIO_SYMBOL_LENGTH, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES);
// Process the scrambling, interleaving and FEC, then return true if the chcksum was correct
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
bool ok = rxHeader(buffer, header);
if (!ok) {
// The checksum failed, return to looking for syncs
m_rxState = DSRXS_NONE;
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
} else {
if (m_rxBufferBits == DSTAR_FEC_SECTION_LENGTH_BITS) {
// Process the scrambling, interleaving and FEC, then return if the chcksum was correct
unsigned char header[DSTAR_HEADER_LENGTH_BYTES];
bool ok = rxHeader(m_rxBuffer, header);
if (ok) {
io.setDecode(true);
io.setADCDetection(true);
writeRSSIHeader(header);
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U;
m_rxState = DSRXS_DATA;
m_dataBits = MAX_SYNC_BITS;
} else {
// The checksum failed, return to looking for syncs
m_rxState = DSRXS_NONE;
}
}
// Ready to start the first data section
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH)) {
m_frameCount = 0U;
m_dataPtr = 0U;
m_startPtr = 476U;
m_syncPtr = 471U;
m_maxSyncPtr = 472U;
m_minSyncPtr = 470U;
DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
m_rxState = DSRXS_DATA;
}
}
void CDStarRX::processData()
void CDStarRX::processData(bool bit)
{
m_patternBuffer <<= 1;
if (bit)
m_patternBuffer |= 0x01U;
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
m_rxBufferBits++;
// Fuzzy matching of the end frame sequences
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= END_SYNC_ERRS) {
if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) {
DEBUG1("DStarRX: Found end sync in Data");
io.setDecode(false);
@@ -406,24 +401,35 @@ void CDStarRX::processData()
serial.writeDStarEOT();
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
m_rxState = DSRXS_NONE;
return;
}
// Fuzzy matching of the data sync bit sequence
if (m_minSyncPtr < m_maxSyncPtr) {
if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr)
correlateDataSync();
} else {
if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr)
correlateDataSync();
bool syncSeen = false;
if (m_rxBufferBits >= (DSTAR_DATA_LENGTH_BITS - 3U)) {
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) {
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS;
m_dataBits = MAX_SYNC_BITS;
syncSeen = true;
}
}
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
if (m_frameCount >= MAX_FRAMES) {
// Check to see if the sync is arriving late
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS && !syncSeen) {
for (uint8_t i = 1U; i <= 3U; i++) {
uint32_t syncMask = DATA_SYNC_MASK >> i;
uint32_t syncData = DATA_SYNC_DATA >> i;
if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) {
m_rxBufferBits -= i;
break;
}
}
}
m_dataBits--;
if (m_dataBits == 0U) {
DEBUG1("DStarRX: data sync timed out, lost lock");
io.setDecode(false);
@@ -431,35 +437,24 @@ void CDStarRX::processData()
serial.writeDStarLost();
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
m_rxState = DSRXS_NONE;
return;
}
// Send a data frame to the host if the required number of bits have been received
if (m_dataPtr == m_maxSyncPtr) {
uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U];
samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES);
if ((m_frameCount % 21U) == 0U) {
if (m_frameCount == 0U) {
buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
DEBUG5("DStarRX: found start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
}
writeRSSIData(buffer);
// Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) {
if (syncSeen) {
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
writeRSSIData(m_rxBuffer);
} else {
serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES);
}
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
}
m_frameCount++;
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
// Start the next frame
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U;
}
}
@@ -505,105 +500,6 @@ void CDStarRX::writeRSSIData(unsigned char* data)
m_rssiCount = 0U;
}
bool CDStarRX::correlateFrameSync()
{
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_FRAME_SYNC_MASK) ^ DSTAR_FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_FRAME_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
q31_t corr = 0;
for (uint8_t i = 0U; i < DSTAR_FRAME_SYNC_LENGTH_SYMBOLS; i++) {
q15_t val = m_dataBuffer[ptr];
if (DSTAR_FRAME_SYNC_SYMBOLS[i])
corr -= val;
else
corr += val;
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
}
if (corr > m_maxFrameCorr) {
m_maxFrameCorr = corr;
m_headerPtr = 0U;
return true;
}
}
return false;
}
bool CDStarRX::correlateDataSync()
{
uint8_t maxErrs = 0U;
if (m_rxState == DSRXS_DATA)
maxErrs = DATA_SYNC_ERRS;
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= maxErrs) {
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
q31_t corr = 0;
for (uint8_t i = 0U; i < DSTAR_DATA_SYNC_LENGTH_SYMBOLS; i++) {
q15_t val = m_dataBuffer[ptr];
if (DSTAR_DATA_SYNC_SYMBOLS[i])
corr -= val;
else
corr += val;
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
}
if (corr > m_maxDataCorr) {
m_maxDataCorr = corr;
m_frameCount = 0U;
m_syncPtr = m_dataPtr;
m_startPtr = m_dataPtr + DSTAR_RADIO_SYMBOL_LENGTH;
if (m_startPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_startPtr -= DSTAR_DATA_LENGTH_SAMPLES;
m_maxSyncPtr = m_syncPtr + 1U;
if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
m_minSyncPtr = m_syncPtr + DSTAR_DATA_LENGTH_SAMPLES - 1U;
if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
return true;
}
}
return false;
}
void CDStarRX::samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit)
{
for (uint16_t i = 0U; i < count; i++) {
q15_t sample = inBuffer[start];
if (sample < 0)
WRITE_BIT2(outBuffer, i, true);
else
WRITE_BIT2(outBuffer, i, false);
start += DSTAR_RADIO_SYMBOL_LENGTH;
if (start >= limit)
start -= limit;
}
}
bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
{
int i;
@@ -819,6 +715,3 @@ bool CDStarRX::checksum(const uint8_t* header) const
return crc8[0U] == header[DSTAR_HEADER_LENGTH_BYTES - 2U] && crc8[1U] == header[DSTAR_HEADER_LENGTH_BYTES - 1U];
}
#endif
+11 -27
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017 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
@@ -16,13 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#if !defined(DSTARRX_H)
#define DSTARRX_H
#include "Config.h"
#include "DStarDefines.h"
enum DSRX_STATE {
@@ -40,21 +37,13 @@ public:
void reset();
private:
uint32_t m_pll;
bool m_prev;
DSRX_STATE m_rxState;
uint64_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH];
q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH];
q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES];
uint16_t m_bitPtr;
uint16_t m_headerPtr;
uint16_t m_dataPtr;
uint16_t m_startPtr;
uint16_t m_syncPtr;
uint16_t m_minSyncPtr;
uint16_t m_maxSyncPtr;
q31_t m_maxFrameCorr;
q31_t m_maxDataCorr;
uint16_t m_frameCount;
uint8_t m_countdown;
uint32_t m_patternBuffer;
uint8_t m_rxBuffer[100U];
unsigned int m_rxBufferBits;
unsigned int m_dataBits;
unsigned int m_mar;
int m_pathMetric[4U];
unsigned int m_pathMemory0[42U];
@@ -65,12 +54,9 @@ private:
uint32_t m_rssiAccum;
uint16_t m_rssiCount;
void processNone(q15_t sample);
void processHeader(q15_t sample);
void processData();
bool correlateFrameSync();
bool correlateDataSync();
void samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit);
void processNone(bool bit);
void processHeader(bool bit);
void processData(bool bit);
void writeRSSIHeader(unsigned char* header);
void writeRSSIData(unsigned char* data);
bool rxHeader(uint8_t* in, uint8_t* out);
@@ -82,5 +68,3 @@ private:
#endif
#endif
+16 -24
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
@@ -18,9 +18,6 @@
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#include "Globals.h"
#include "DStarTX.h"
@@ -201,7 +198,7 @@ m_txDelay(60U) // 100ms
{
::memset(m_modState, 0x00U, 20U * sizeof(q15_t));
m_modFilter.L = DSTAR_RADIO_SYMBOL_LENGTH;
m_modFilter.L = DSTAR_RADIO_BIT_LENGTH;
m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN;
m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER;
m_modFilter.pState = m_modState;
@@ -220,12 +217,11 @@ void CDStarTX::process()
m_poBuffer[m_poLen++] = BIT_SYNC;
} else {
// Pop the type byte off
uint8_t dummy;
m_buffer.get(dummy);
m_buffer.get();
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
for (uint8_t i = 0U; i < DSTAR_HEADER_LENGTH_BYTES; i++)
m_buffer.get(header[i]);
header[i] = m_buffer.get();
uint8_t buffer[86U];
txHeader(header, buffer + 2U);
@@ -243,23 +239,21 @@ void CDStarTX::process()
if (type == DSTAR_DATA && m_poLen == 0U) {
// Pop the type byte off
uint8_t dummy;
m_buffer.get(dummy);
m_buffer.get();
for (uint8_t i = 0U; i < DSTAR_DATA_LENGTH_BYTES; i++)
m_buffer.get(m_poBuffer[m_poLen++]);
m_poBuffer[m_poLen++] = m_buffer.get();
m_poPtr = 0U;
}
if (type == DSTAR_EOT && m_poLen == 0U) {
// Pop the type byte off
uint8_t dummy;
m_buffer.get(dummy);
m_buffer.get();
for (uint8_t j = 0U; j < 3U; j++) {
for (uint8_t i = 0U; i < DSTAR_END_SYNC_LENGTH_BYTES; i++)
m_poBuffer[m_poLen++] = DSTAR_END_SYNC_BYTES[i];
for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++)
m_poBuffer[m_poLen++] = DSTAR_EOT_BYTES[i];
}
m_poPtr = 0U;
@@ -268,11 +262,11 @@ void CDStarTX::process()
if (m_poLen > 0U) {
uint16_t space = io.getSpace();
while (space > (8U * DSTAR_RADIO_SYMBOL_LENGTH)) {
while (space > (8U * DSTAR_RADIO_BIT_LENGTH)) {
uint8_t c = m_poBuffer[m_poPtr++];
writeByte(c);
space -= 8U * DSTAR_RADIO_SYMBOL_LENGTH;
space -= 8U * DSTAR_RADIO_BIT_LENGTH;
if (m_poPtr >= m_poLen) {
m_poPtr = 0U;
@@ -283,7 +277,7 @@ void CDStarTX::process()
}
}
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint16_t length)
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length)
{
if (length != DSTAR_HEADER_LENGTH_BYTES)
return 4U;
@@ -302,7 +296,7 @@ uint8_t CDStarTX::writeHeader(const uint8_t* header, uint16_t length)
return 0U;
}
uint8_t CDStarTX::writeData(const uint8_t* data, uint16_t length)
uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length)
{
if (length != DSTAR_DATA_LENGTH_BYTES)
return 4U;
@@ -394,7 +388,7 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const
if (i < 660U) {
if (d & 0x08U)
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
i++;
i++;
if (d & 0x04U)
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
@@ -418,7 +412,7 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const
void CDStarTX::writeByte(uint8_t c)
{
q15_t inBuffer[8U];
q15_t outBuffer[DSTAR_RADIO_SYMBOL_LENGTH * 8U];
q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U];
uint8_t mask = 0x01U;
@@ -433,7 +427,7 @@ void CDStarTX::writeByte(uint8_t c)
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U);
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_SYMBOL_LENGTH * 8U);
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U);
}
void CDStarTX::setTXDelay(uint8_t delay)
@@ -449,5 +443,3 @@ uint8_t CDStarTX::getSpace() const
return m_buffer.getSpace() / (DSTAR_DATA_LENGTH_BYTES + 1U);
}
#endif
+7 -11
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017 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
@@ -16,21 +16,19 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_DSTAR)
#if !defined(DSTARTX_H)
#define DSTARTX_H
#include "RingBuffer.h"
#include "Config.h"
#include "SerialRB.h"
class CDStarTX {
public:
CDStarTX();
uint8_t writeHeader(const uint8_t* header, uint16_t length);
uint8_t writeData(const uint8_t* data, uint16_t length);
uint8_t writeHeader(const uint8_t* header, uint8_t length);
uint8_t writeData(const uint8_t* data, uint8_t length);
uint8_t writeEOT();
void process();
@@ -40,7 +38,7 @@ public:
uint8_t getSpace() const;
private:
CRingBuffer<uint8_t> m_buffer;
CSerialRB m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter;
q15_t m_modState[20U]; // blockSize + phaseLength - 1, 8 + 9 - 1 plus some spare
uint8_t m_poBuffer[600U];
@@ -54,5 +52,3 @@ private:
#endif
#endif
+1 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017 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
@@ -27,7 +27,6 @@
#define DEBUG3(a,b,c) serial.writeDebug((a),(b),(c))
#define DEBUG4(a,b,c,d) serial.writeDebug((a),(b),(c),(d))
#define DEBUG5(a,b,c,d,e) serial.writeDebug((a),(b),(c),(d),(e))
#define DEBUG_DUMP(a,b) serial.writeDebugDump((a),(b))
#endif
-1312
View File
File diff suppressed because it is too large Load Diff
-144
View File
@@ -1,144 +0,0 @@
/*
* Copyright (C) 2020,2021,2023,2025 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FM_H)
#define FM_H
#include "FMBlanking.h"
#include "FMCTCSSRX.h"
#include "FMCTCSSTX.h"
#include "FMTimeout.h"
#include "FMKeyer.h"
#include "FMTimer.h"
#include "RingBuffer.h"
#include "FMDirectForm1.h"
#include "FMDownSampler.h"
#include "FMUpSampler.h"
#include "FMNoiseSquelch.h"
class CFM {
public:
CFM();
void samples(bool cos, q15_t* samples, const uint16_t* rssi, uint8_t length);
void process();
void reset();
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level);
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
uint8_t setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t frequency, uint8_t level);
uint8_t getSpace() const;
uint8_t writeData(const uint8_t* data, uint16_t length);
private:
CFMKeyer m_callsign;
CFMKeyer m_rfAck;
CFMKeyer m_extAck;
CFMCTCSSRX m_ctcssRX;
CFMCTCSSTX m_ctcssTX;
CFMNoiseSquelch m_squelch;
CFMTimeout m_timeoutTone;
uint8_t m_state;
bool m_callsignAtStart;
bool m_callsignAtEnd;
bool m_callsignAtLatch;
CFMTimer m_callsignTimer;
CFMTimer m_timeoutTimer;
CFMTimer m_holdoffTimer;
CFMTimer m_kerchunkTimer;
CFMTimer m_ackMinTimer;
CFMTimer m_ackDelayTimer;
CFMTimer m_hangTimer;
CFMTimer m_reverseTimer;
bool m_needReverse;
CFMDirectFormI m_filterStage1;
CFMDirectFormI m_filterStage2;
CFMDirectFormI m_filterStage3;
CFMBlanking m_blanking;
uint8_t m_accessMode;
bool m_linkMode;
bool m_cosInvert;
bool m_noiseSquelch;
q15_t m_rfAudioBoost;
q15_t m_extAudioBoost;
CFMDownSampler m_downSampler;
bool m_extEnabled;
q15_t m_rxLevel;
CRingBuffer<q15_t> m_inputRFRB;
CRingBuffer<q15_t> m_outputRFRB;
CFMUpSampler m_inputExtRB;
bool m_rfSignal;
bool m_extSignal;
uint32_t m_rssiAccum;
uint16_t m_rssiCount;
void stateMachine(bool validRFSignal, bool validExtSignal);
void repeaterSamples(bool cos, q15_t* samples, const uint16_t* rssi, uint8_t length);
void linkSamples(bool cos, q15_t* samples, uint8_t length);
void duplexStateMachine(bool validRFSignal, bool validExtSignal);
void listeningStateDuplex(bool validRFSignal, bool validExtSignal);
void kerchunkRFStateDuplex(bool validSignal);
void relayingRFStateDuplex(bool validSignal);
void relayingRFWaitStateDuplex(bool validSignal);
void timeoutRFStateDuplex(bool validSignal);
void timeoutRFWaitStateDuplex(bool validSignal);
void kerchunkExtStateDuplex(bool validSignal);
void relayingExtStateDuplex(bool validSignal);
void relayingExtWaitStateDuplex(bool validSignal);
void timeoutExtStateDuplex(bool validSignal);
void timeoutExtWaitStateDuplex(bool validSignal);
void hangStateDuplex(bool validRFSignal, bool validExtSignal);
void simplexStateMachine(bool validRFSignal, bool validExtSignal);
void listeningStateSimplex(bool validRFSignal, bool validExtSignal);
void relayingRFStateSimplex(bool validSignal);
void relayingRFWaitStateSimplex(bool validSignal);
void timeoutRFStateSimplex(bool validSignal);
void timeoutRFWaitStateSimplex(bool validSignal);
void relayingExtStateSimplex(bool validSignal);
void relayingExtWaitStateSimplex(bool validSignal);
void timeoutExtStateSimplex(bool validSignal);
void timeoutExtWaitStateSimplex(bool validSignal);
void linkStateMachine(bool validRFSignal, bool validExtSignal);
void clock(uint8_t length);
void sendCallsign();
void beginRelaying();
void insertDelay(uint16_t ms);
void insertSilence(uint16_t ms);
};
#endif
#endif
-88
View File
@@ -1,88 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMBlanking.h"
// 2000 Hz sine wave at 24000 Hz sample rate
const q31_t TONE[] = {0, 16384, 28378, 32767, 28378, 16384, 0, -16383, -28377, -32767, -28377, -16383};
const uint8_t TONE_LEN = 12U;
const uint32_t BLEEP_LEN = 2400U; // 100ms
CFMBlanking::CFMBlanking() :
m_posValue(0),
m_negValue(0),
m_level(128 * 128),
m_running(false),
m_pos(0U),
m_n(0U)
{
}
void CFMBlanking::setParams(uint8_t value, uint8_t level)
{
m_posValue = q15_t(value * 128);
m_negValue = -m_posValue;
m_level = q15_t(level * 128);
}
q15_t CFMBlanking::process(q15_t sample)
{
if (m_posValue == 0)
return sample;
if (!m_running) {
if (sample >= m_posValue) {
m_running = true;
m_pos = 0U;
m_n = 0U;
} else if (sample <= m_negValue) {
m_running = true;
m_pos = 0U;
m_n = 0U;
}
}
if (!m_running)
return sample;
if (m_pos <= BLEEP_LEN) {
q31_t value = TONE[m_n++] * m_level;
sample = q15_t(__SSAT((value >> 15), 16));
if (m_n >= TONE_LEN)
m_n = 0U;
} else {
sample = 0;
}
m_pos++;
if (m_pos >= 12000U)
m_running = false;
return sample;
}
#endif
-46
View File
@@ -1,46 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMBlanking_H)
#define FMBlanking_H
class CFMBlanking {
public:
CFMBlanking();
void setParams(uint8_t value, uint8_t level);
q15_t process(q15_t sample);
private:
q15_t m_posValue;
q15_t m_negValue;
q15_t m_level;
bool m_running;
uint32_t m_pos;
uint8_t m_n;
};
#endif
#endif
-181
View File
@@ -1,181 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMCTCSSRX.h"
const struct RX_CTCSS_TABLE {
uint8_t frequency;
q63_t coeffDivTwo;
} RX_CTCSS_TABLE_DATA[] = {
{ 67U, 2147153298},
{ 69U, 2147130228},
{ 71U, 2147103212},
{ 74U, 2147076297},
{ 77U, 2147047330},
{ 79U, 2147016195},
{ 82U, 2146982775},
{ 85U, 2146946945},
{ 88U, 2146907275},
{ 91U, 2146867538},
{ 94U, 2146822298},
{ 97U, 2146785526},
{100U, 2146747759},
{103U, 2146695349},
{107U, 2146637984},
{110U, 2146578604},
{114U, 2146513835},
{118U, 2146445080},
{123U, 2146370355},
{127U, 2146291161},
{131U, 2146205372},
{136U, 2146112589},
{141U, 2146014479},
{146U, 2145910829},
{151U, 2145796971},
{156U, 2145676831},
{159U, 2145604646},
{162U, 2145547790},
{165U, 2145468230},
{167U, 2145409363},
{171U, 2145324517},
{173U, 2145261046},
{177U, 2145170643},
{179U, 2145102321},
{183U, 2145006080},
{186U, 2144932648},
{189U, 2144830280},
{192U, 2144748638},
{196U, 2144639788},
{199U, 2144555290},
{203U, 2144436713},
{206U, 2144346237},
{210U, 2144217348},
{218U, 2143983951},
{225U, 2143735870},
{229U, 2143622139},
{233U, 2143469001},
{241U, 2143182299},
{250U, 2142874683},
{254U, 2142733729}};
const uint8_t CTCSS_TABLE_DATA_LEN = 50U;
// 4Hz bandwidth
const uint16_t N = 24000U / 4U;
CFMCTCSSRX::CFMCTCSSRX() :
m_coeffDivTwo(0),
m_highThreshold(0),
m_lowThreshold(0),
m_count(0U),
m_q0(0),
m_q1(0),
m_state(false)
{
}
uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold)
{
m_coeffDivTwo = 0;
for (uint8_t i = 0U; i < CTCSS_TABLE_DATA_LEN; i++) {
if (RX_CTCSS_TABLE_DATA[i].frequency == frequency) {
m_coeffDivTwo = RX_CTCSS_TABLE_DATA[i].coeffDivTwo;
break;
}
}
if (m_coeffDivTwo == 0)
return 4U;
m_highThreshold = q31_t(highThreshold);
m_lowThreshold = q31_t(lowThreshold);
return 0U;
}
bool CFMCTCSSRX::process(q15_t sample)
{
//get more dynamic into the decoder by multiplying the sample by 1.5
q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1);
q31_t q2 = m_q1;
m_q1 = m_q0;
// Q31 multiplication, t3 = m_coeffDivTwo * 2 * m_q1
q63_t t1 = m_coeffDivTwo * m_q1;
q31_t t2 = __SSAT((t1 >> 31), 31);
q31_t t3 = t2 * 2;
// m_q0 = m_coeffDivTwo * m_q1 * 2 - q2 + sample
m_q0 = t3 - q2 + sample31;
m_count++;
if (m_count == N) {
// Q31 multiplication, t2 = m_q0 * m_q0
q63_t t1 = q63_t(m_q0) * q63_t(m_q0);
q31_t t2 = __SSAT((t1 >> 31), 31);
// Q31 multiplication, t4 = m_q0 * m_q0
q63_t t3 = q63_t(m_q1) * q63_t(m_q1);
q31_t t4 = __SSAT((t3 >> 31), 31);
// Q31 multiplication, t9 = m_q0 * m_q1 * m_coeffDivTwo * 2
q63_t t5 = q63_t(m_q0) * q63_t(m_q1);
q31_t t6 = __SSAT((t5 >> 31), 31);
q63_t t7 = t6 * m_coeffDivTwo;
q31_t t8 = __SSAT((t7 >> 31), 31);
q31_t t9 = t8 * 2;
// value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2
q31_t value = t2 + t4 - t9;
bool previousState = m_state;
q31_t threshold = m_highThreshold;
if (previousState)
threshold = m_lowThreshold;
m_state = value >= threshold;
if (previousState != m_state)
DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, m_state);
m_count = 0U;
m_q0 = 0;
m_q1 = 0;
}
return m_state;
}
void CFMCTCSSRX::reset()
{
m_q0 = 0;
m_q1 = 0;
m_state = false;
m_count = 0U;
}
#endif
-49
View File
@@ -1,49 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMCTCSSRX_H)
#define FMCTCSSRX_H
class CFMCTCSSRX {
public:
CFMCTCSSRX();
uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold);
bool process(q15_t sample);
void reset();
private:
q63_t m_coeffDivTwo;
q31_t m_highThreshold;
q31_t m_lowThreshold;
uint16_t m_count;
q31_t m_q0;
q31_t m_q1;
bool m_state;
};
#endif
#endif
-134
View File
@@ -1,134 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMCTCSSTX.h"
const struct TX_CTCSS_TABLE {
uint8_t frequency;
uint16_t length;
q31_t increment;
} TX_CTCSS_TABLE_DATA[] = {
{ 67U, 358U, 5995059},
{ 69U, 346U, 6200860},
{ 71U, 334U, 6433504},
{ 74U, 323U, 6657200},
{ 77U, 312U, 6889844},
{ 79U, 301U, 7131436},
{ 82U, 291U, 7381976},
{ 85U, 281U, 7641463},
{ 88U, 271U, 7918846},
{ 91U, 262U, 8187282},
{ 94U, 253U, 8482561},
{ 97U, 246U, 8715205},
{100U, 240U, 8947849},
{103U, 232U, 9261024},
{107U, 224U, 9592094},
{110U, 216U, 9923165},
{114U, 209U, 10272131},
{118U, 202U, 10630045},
{123U, 195U, 11005854},
{127U, 189U, 11390612},
{131U, 182U, 11793265},
{136U, 176U, 12213814},
{141U, 170U, 12643310},
{146U, 164U, 13081755},
{151U, 159U, 13547043},
{156U, 153U, 14021279},
{159U, 150U, 14298662},
{162U, 148U, 14513411},
{165U, 145U, 14808690},
{167U, 143U, 15023438},
{171U, 140U, 15327665},
{173U, 138U, 15551361},
{177U, 135U, 15864536},
{179U, 133U, 16097180},
{183U, 131U, 16419303},
{186U, 129U, 16660894},
{189U, 126U, 16991965},
{192U, 124U, 17251452},
{196U, 122U, 17591471},
{199U, 120U, 17850958},
{203U, 118U, 18208872},
{206U, 116U, 18477308},
{210U, 114U, 18853117},
{218U, 110U, 19515258},
{225U, 106U, 20195295},
{229U, 105U, 20499521},
{233U, 103U, 20902175},
{241U, 99U, 21635898},
{250U, 96U, 22396465},
{254U, 94U, 22736484}};
const uint8_t CTCSS_TABLE_DATA_LEN = 50U;
CFMCTCSSTX::CFMCTCSSTX() :
m_values(NULL),
m_length(0U),
m_n(0U)
{
}
uint8_t CFMCTCSSTX::setParams(uint8_t frequency, uint8_t level)
{
const TX_CTCSS_TABLE* entry = NULL;
for (uint8_t i = 0U; i < CTCSS_TABLE_DATA_LEN; i++) {
if (TX_CTCSS_TABLE_DATA[i].frequency == frequency) {
entry = TX_CTCSS_TABLE_DATA + i;
break;
}
}
if (entry == NULL)
return 4U;
m_length = entry->length;
delete[] m_values;
m_values = new q15_t[m_length];
q31_t arg = 0;
for (uint16_t i = 0U; i < m_length; i++) {
q63_t value = ::arm_sin_q31(arg) * q63_t(level * 13);
m_values[i] = q15_t(__SSAT((value >> 31), 16));
arg += entry->increment;
}
return 0U;
}
q15_t CFMCTCSSTX::getAudio(bool reverse)
{
q15_t sample = m_values[m_n++];
if (m_n >= m_length)
m_n = 0U;
if (reverse)
return -sample;
else
return sample;
}
#endif
-43
View File
@@ -1,43 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMCTCSSTX_H)
#define FMCTCSSTX_H
class CFMCTCSSTX {
public:
CFMCTCSSTX();
uint8_t setParams(uint8_t frequency, uint8_t level);
q15_t getAudio(bool reverse);
private:
q15_t* m_values;
uint16_t m_length;
uint16_t m_n;
};
#endif
#endif
-113
View File
@@ -1,113 +0,0 @@
/*******************************************************************************
This header file has been taken from:
"A Collection of Useful C++ Classes for Digital Signal Processing"
By Vinnie Falco
Bernd Porr adapted it for Linux and turned it into a filter using
fixed point arithmetic.
--------------------------------------------------------------------------------
License: MIT License (http://www.opensource.org/licenses/mit-license.php)
Copyright (c) 2009 by Vinnie Falco
Copyright (C) 2013-2017, Bernd Porr, [email protected]
Copyright (C) 2020 , Mario Molitor , [email protected]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*******************************************************************************/
// based on https://raw.githubusercontent.com/berndporr/iir_fixed_point/master/DirectFormI.h
#include "Config.h"
#if defined(MODE_FM)
#include <cstdint>
#ifndef DIRECTFORMI_H_
#define DIRECTFORMI_H_
class CFMDirectFormI
{
public:
// convenience function which takes the a0 argument but ignores it!
CFMDirectFormI(const q31_t b0, const q31_t b1, const q31_t b2, const q31_t, const q31_t a1, const q31_t a2)
{
// FIR coefficients
c_b0 = b0;
c_b1 = b1;
c_b2 = b2;
// IIR coefficients
c_a1 = a1;
c_a2 = a2;
reset();
}
CFMDirectFormI(const CFMDirectFormI &my)
{
// delay line
m_x2 = my.m_x2; // x[n-2]
m_y2 = my.m_y2; // y[n-2]
m_x1 = my.m_x1; // x[n-1]
m_y1 = my.m_y1; // y[n-1]
// coefficients
c_b0 = my.c_b0;
c_b1 = my.c_b1;
c_b2 = my.c_b2; // FIR
c_a1 = my.c_a1;
c_a2 = my.c_a2; // IIR
}
void reset()
{
m_x1 = 0;
m_x2 = 0;
m_y1 = 0;
m_y2 = 0;
}
// filtering operation: one sample in and one out
inline q15_t filter(const q15_t in)
{
// calculate the output
q31_t out_upscaled = c_b0 * in + c_b1 * m_x1 + c_b2 * m_x2 - c_a1 * m_y1 - c_a2 * m_y2;
q15_t out = __SSAT(out_upscaled >> 15, 15);
// update the delay lines
m_x2 = m_x1;
m_y2 = m_y1;
m_x1 = in;
m_y1 = out;
return out;
}
private:
// delay line
q31_t m_x2; // x[n-2]
q31_t m_y2; // y[n-2]
q31_t m_x1; // x[n-1]
q31_t m_y1; // y[n-1]
// coefficients
q31_t c_b0,c_b1,c_b2; // FIR
q31_t c_a1,c_a2; // IIR
};
#endif /* DIRECTFORMI_H */
#endif
-80
View File
@@ -1,80 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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"
#if defined(MODE_FM)
#include "FMDownSampler.h"
CFMDownSampler::CFMDownSampler(uint16_t length) :
m_ringBuffer(length),
m_samplePack(0U),
m_samplePackPointer(NULL),
m_sampleIndex(0U)
{
m_samplePackPointer = (uint8_t*)&m_samplePack;
}
void CFMDownSampler::addSample(q15_t sample)
{
uint32_t usample = uint32_t(int32_t(sample) + 2048);
//only take one of three samples
switch(m_sampleIndex){
case 0:
m_samplePack = usample << 12;
break;
case 3:{
m_samplePack |= usample;
//we did not use MSB; skip it
TSamplePairPack pair{m_samplePackPointer[0U], m_samplePackPointer[1U], m_samplePackPointer[2U]};
m_ringBuffer.put(pair);
m_samplePack = 0U;//reset the sample pack
}
break;
default:
//Just skip this sample
break;
}
m_sampleIndex++;
if (m_sampleIndex >= 6U)//did we pack two samples ?
m_sampleIndex = 0U;
}
bool CFMDownSampler::getPackedData(TSamplePairPack& data)
{
return m_ringBuffer.get(data);
}
uint16_t CFMDownSampler::getData()
{
return m_ringBuffer.getData();
}
void CFMDownSampler::reset()
{
m_sampleIndex = 0U;
}
#endif
-52
View File
@@ -1,52 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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"
#if defined(MODE_FM)
#if !defined(FMDOWNSAMPLER_H)
#define FMDOWNSAMPLER_H
#include "RingBuffer.h"
#include "FMSamplePairPack.h"
class CFMDownSampler {
public:
CFMDownSampler(uint16_t length);
void addSample(q15_t sample);
bool getPackedData(TSamplePairPack& data);
uint16_t getData();
void reset();
private:
CRingBuffer<TSamplePairPack> m_ringBuffer;
uint32_t m_samplePack;
uint8_t* m_samplePackPointer;
uint8_t m_sampleIndex;
};
#endif
#endif
-222
View File
@@ -1,222 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMKeyer.h"
const struct {
char c;
uint32_t pattern;
uint8_t length;
} SYMBOL_LIST[] = {
{'A', 0xB8000000U, 8U},
{'B', 0xEA800000U, 12U},
{'C', 0xEBA00000U, 14U},
{'D', 0xEA000000U, 10U},
{'E', 0x80000000U, 4U},
{'F', 0xAE800000U, 12U},
{'G', 0xEE800000U, 12U},
{'H', 0xAA000000U, 10U},
{'I', 0xA0000000U, 6U},
{'J', 0xBBB80000U, 16U},
{'K', 0xEB800000U, 12U},
{'L', 0xBA800000U, 12U},
{'M', 0xEE000000U, 10U},
{'N', 0xE8000000U, 8U},
{'O', 0xEEE00000U, 14U},
{'P', 0xBBA00000U, 14U},
{'Q', 0xEEB80000U, 16U},
{'R', 0xBA000000U, 10U},
{'S', 0xA8000000U, 8U},
{'T', 0xE0000000U, 6U},
{'U', 0xAE000000U, 10U},
{'V', 0xAB800000U, 12U},
{'W', 0xBB800000U, 12U},
{'X', 0xEAE00000U, 14U},
{'Y', 0xEBB80000U, 16U},
{'Z', 0xEEA00000U, 14U},
{'1', 0xBBBB8000U, 20U},
{'2', 0xAEEE0000U, 18U},
{'3', 0xABB80000U, 16U},
{'4', 0xAAE00000U, 14U},
{'5', 0xAA800000U, 12U},
{'6', 0xEAA00000U, 14U},
{'7', 0xEEA80000U, 16U},
{'8', 0xEEEA0000U, 18U},
{'9', 0xEEEE8000U, 20U},
{'0', 0xEEEEE000U, 22U},
{'/', 0xEAE80000U, 16U},
{'?', 0xAEEA0000U, 18U},
{',', 0xEEAEE000U, 22U},
{'-', 0xEAAE0000U, 18U},
{'=', 0xEAB80000U, 16U},
{'.', 0xBAEB8000U, 20U},
{' ', 0x00000000U, 4U},
{0U, 0x00000000U, 0U}
};
const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT_FM(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT_FM(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CFMKeyer::CFMKeyer() :
m_wanted(false),
m_poBuffer(),
m_poLen(0U),
m_poPos(0U),
m_dotLen(0U),
m_dotPos(0U),
m_audio(NULL),
m_audioLen(0U),
m_audioPos(0U),
m_highLevel(0U),
m_lowLevel(0)
{
}
uint8_t CFMKeyer::setParams(const char* text, uint8_t speed, uint16_t frequency, uint8_t highLevel, uint8_t lowLevel)
{
m_poLen = 0U;
for (uint8_t i = 0U; text[i] != '\0'; i++) {
for (uint8_t j = 0U; SYMBOL_LIST[j].c != 0U; j++) {
if (SYMBOL_LIST[j].c == text[i]) {
uint32_t MASK = 0x80000000U;
for (uint8_t k = 0U; k < SYMBOL_LIST[j].length; k++, m_poLen++, MASK >>= 1) {
bool b = (SYMBOL_LIST[j].pattern & MASK) == MASK;
WRITE_BIT_FM(m_poBuffer, m_poLen, b);
if (m_poLen >= 995U) {
m_poLen = 0U;
return 4U;
}
}
break;
}
}
}
m_highLevel = q15_t(highLevel);
m_lowLevel = q15_t(lowLevel);
m_dotLen = 24000U / speed; // In samples
m_audioLen = 24000U / frequency; // In samples
delete[] m_audio;
m_audio = new bool[m_audioLen];
for (uint16_t i = 0U; i < m_audioLen; i++) {
if (i < (m_audioLen / 2U))
m_audio[i] = true;
else
m_audio[i] = false;
}
return 0U;
}
q15_t CFMKeyer::getHighAudio()
{
q15_t output = 0U;
if (!m_wanted)
return 0U;
bool b = READ_BIT_FM(m_poBuffer, m_poPos);
if (b)
output = m_audio[m_audioPos] ? m_highLevel : -m_highLevel;
m_audioPos++;
if (m_audioPos >= m_audioLen)
m_audioPos = 0U;
m_dotPos++;
if (m_dotPos >= m_dotLen) {
m_dotPos = 0U;
m_poPos++;
if (m_poPos >= m_poLen) {
stop();
return output;
}
}
return output;
}
q15_t CFMKeyer::getLowAudio()
{
q15_t output = 0U;
if (!m_wanted)
return 0U;
bool b = READ_BIT_FM(m_poBuffer, m_poPos);
if (b)
output = m_audio[m_audioPos] ? m_lowLevel : -m_lowLevel;
m_audioPos++;
if (m_audioPos >= m_audioLen)
m_audioPos = 0U;
m_dotPos++;
if (m_dotPos >= m_dotLen) {
m_dotPos = 0U;
m_poPos++;
if (m_poPos >= m_poLen) {
stop();
return output;
}
}
return output;
}
void CFMKeyer::start()
{
if (isRunning())
return;
m_wanted = true;
m_poPos = 0U;
m_dotPos = 0U;
m_audioPos = 0U;
}
void CFMKeyer::stop()
{
m_wanted = false;
m_poPos = 0U;
m_dotPos = 0U;
m_audioPos = 0U;
}
bool CFMKeyer::isWanted() const
{
return m_wanted;
}
bool CFMKeyer::isRunning() const
{
return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U;
}
#endif
-59
View File
@@ -1,59 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMKeyer_H)
#define FMKeyer_H
class CFMKeyer {
public:
CFMKeyer();
uint8_t setParams(const char* text, uint8_t speed, uint16_t frequency, uint8_t highLevel, uint8_t lowLevel);
q15_t getHighAudio();
q15_t getLowAudio();
void start();
void stop();
bool isRunning() const;
bool isWanted() const;
private:
bool m_wanted;
uint8_t m_poBuffer[1000U];
uint16_t m_poLen;
uint16_t m_poPos;
uint16_t m_dotLen;
uint16_t m_dotPos;
bool* m_audio;
uint16_t m_audioLen;
uint16_t m_audioPos;
q15_t m_highLevel;
q15_t m_lowLevel;
};
#endif
#endif
-133
View File
@@ -1,133 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMNoiseSquelch.h"
// 4500Hz centre frequency
const q31_t COEFF_DIV_TWO = 821806413;
// 400Hz bandwidth
const uint16_t N = 24000U / 400U;
CFMNoiseSquelch::CFMNoiseSquelch() :
m_highThreshold(0),
m_lowThreshold(0),
m_count(0U),
m_q0(0),
m_q1(0),
m_state(false),
m_validCount(0U)
{
}
void CFMNoiseSquelch::setParams(uint8_t highThreshold, uint8_t lowThreshold)
{
m_highThreshold = q31_t(highThreshold);
m_lowThreshold = q31_t(lowThreshold);
}
bool CFMNoiseSquelch::process(q15_t sample)
{
//get more dynamic into the decoder by multiplying the sample by 64
q31_t sample31 = q31_t(sample) << 6; //+ (q31_t(sample) >> 1);
q31_t q2 = m_q1;
m_q1 = m_q0;
// Q31 multiplication, t3 = m_coeffDivTwo * 2 * m_q1
q63_t t1 = COEFF_DIV_TWO * m_q1;
q31_t t2 = __SSAT((t1 >> 31), 31);
q31_t t3 = t2 * 2;
// m_q0 = m_coeffDivTwo * m_q1 * 2 - q2 + sample
m_q0 = t3 - q2 + sample31;
m_count++;
if (m_count == N) {
// Q31 multiplication, t2 = m_q0 * m_q0
q63_t t1 = q63_t(m_q0) * q63_t(m_q0);
q31_t t2 = __SSAT((t1 >> 31), 31);
// Q31 multiplication, t4 = m_q0 * m_q0
q63_t t3 = q63_t(m_q1) * q63_t(m_q1);
q31_t t4 = __SSAT((t3 >> 31), 31);
// Q31 multiplication, t9 = m_q0 * m_q1 * m_coeffDivTwo * 2
q63_t t5 = q63_t(m_q0) * q63_t(m_q1);
q31_t t6 = __SSAT((t5 >> 31), 31);
q63_t t7 = t6 * COEFF_DIV_TWO;
q31_t t8 = __SSAT((t7 >> 31), 31);
q31_t t9 = t8 * 2;
// value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2
q31_t value = t2 + t4 - t9;
bool previousState = m_state;
q31_t threshold = m_highThreshold;
if (previousState)
threshold = m_lowThreshold;
if (!m_state) {
if (value < threshold)
m_validCount++;
else
m_validCount = 0U;
}
if (m_state) {
if (value >= threshold)
m_invalidCount++;
else
m_invalidCount = 0U;
}
m_state = m_validCount >= 10U && m_invalidCount < 10U;
if(previousState && !m_state)
m_invalidCount = 0U;
if (previousState != m_state) {
DEBUG4("Noise Squelch Value / Threshold / Valid", value, threshold, m_state);
DEBUG3("Valid Count / Invalid Count", m_validCount, m_invalidCount);
}
m_count = 0U;
m_q0 = 0;
m_q1 = 0;
}
return m_state;
}
void CFMNoiseSquelch::reset()
{
m_q0 = 0;
m_q1 = 0;
m_state = false;
m_count = 0U;
}
#endif
-50
View File
@@ -1,50 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMNOISESQUELCH_H)
#define FMNOISESQUELCH_H
class CFMNoiseSquelch {
public:
CFMNoiseSquelch();
void setParams(uint8_t highThreshold, uint8_t lowThreshold);
bool process(q15_t sample);
void reset();
private:
q31_t m_highThreshold;
q31_t m_lowThreshold;
uint16_t m_count;
q31_t m_q0;
q31_t m_q1;
bool m_state;
uint8_t m_validCount;
uint8_t m_invalidCount;
};
#endif
#endif
-36
View File
@@ -1,36 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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"
#if defined(MODE_FM)
#if !defined(TSAMPLEPACK_H)
#define TSAMPLEPACK_H
struct TSamplePairPack {
uint8_t byte0;
uint8_t byte1;
uint8_t byte2;
};
#endif
#endif
-80
View File
@@ -1,80 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMTimeout.h"
// 400 Hz sine wave at 24000 Hz sample rate
const q15_t BUSY_AUDIO[] = {0, 3426, 6813, 10126, 13328, 16384, 19261, 21926, 24351, 26510, 28378, 29935, 31164, 32052, 32588, 32767, 32588, 32052, 31164, 29935, 28378, 26510, 24351,
21926, 19261, 16384, 13328, 10126, 6813, 3425, 0, -3425, -6813, -10126, -13328, -16384, -19261, -21926, -24351, -26510, -28378, -29935, -31164, -32052,
-32588, -32768, -32588, -32052, -31164, -29935, -28378, -26510, -24351, -21926, -19261, -16384, -13328, -10126, -6813, -3425};
const uint8_t BUSY_AUDIO_LEN = 60U;
CFMTimeout::CFMTimeout() :
m_level(128 * 128),
m_running(false),
m_pos(0U),
m_n(0U)
{
}
void CFMTimeout::setParams(uint8_t level)
{
m_level = q15_t(level * 5);
}
q15_t CFMTimeout::getAudio()
{
q15_t sample = 0;
if (!m_running)
return sample;
if (m_pos >= 12000U) {
q31_t sample31 = BUSY_AUDIO[m_n] * m_level;
sample = q15_t(__SSAT((sample31 >> 15), 16));
m_n++;
if (m_n >= BUSY_AUDIO_LEN)
m_n = 0U;
}
m_pos++;
if (m_pos >= 24000U)
m_pos = 0U;
return sample;
}
void CFMTimeout::start()
{
m_running = true;
m_pos = 0U;
m_n = 0U;
}
void CFMTimeout::stop()
{
m_running = false;
}
#endif
-47
View File
@@ -1,47 +0,0 @@
/*
* Copyright (C) 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.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMTimeout_H)
#define FMTimeout_H
class CFMTimeout {
public:
CFMTimeout();
void setParams(uint8_t level);
void start();
void stop();
q15_t getAudio();
private:
q15_t m_level;
bool m_running;
uint32_t m_pos;
uint8_t m_n;
};
#endif
#endif
-76
View File
@@ -1,76 +0,0 @@
/*
* Copyright (C) 2009,2010,2015,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.
*/
#include "Config.h"
#if defined(MODE_FM)
#include "Globals.h"
#include "FMTimer.h"
CFMTimer::CFMTimer() :
m_timeout(0U),
m_timer(0U)
{
}
void CFMTimer::setTimeout(uint16_t secs, uint32_t msecs)
{
m_timeout = (secs * 24000U) + (msecs * 24U);
}
uint32_t CFMTimer::getTimeout() const
{
return m_timeout / 24U;
}
void CFMTimer::start()
{
if (m_timeout > 0U)
m_timer = 1U;
}
void CFMTimer::stop()
{
m_timer = 0U;
}
void CFMTimer::clock(uint8_t length)
{
if (m_timer > 0U && m_timeout > 0U)
m_timer += length;
}
bool CFMTimer::isRunning() const
{
return m_timer > 0U;
}
bool CFMTimer::hasExpired() const
{
if (m_timeout == 0U || m_timer == 0U)
return false;
if (m_timer > m_timeout)
return true;
return false;
}
#endif
-52
View File
@@ -1,52 +0,0 @@
/*
* Copyright (C) 2009,2010,2015,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.
*/
#include "Config.h"
#if defined(MODE_FM)
#if !defined(FMTimer_H)
#define FMTimer_H
class CFMTimer {
public:
CFMTimer();
void setTimeout(uint16_t secs, uint32_t msecs);
uint32_t getTimeout() const;
void start();
void stop();
void clock(uint8_t length);
bool isRunning() const;
bool hasExpired() const;
private:
uint32_t m_timeout;
uint32_t m_timer;
};
#endif
#endif
-104
View File
@@ -1,104 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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"
#if defined(MODE_FM)
#include "FMUpSampler.h"
const uint32_t FM_UPSAMPLE_MASK = 0x00000FFFU;
CFMUpSampler::CFMUpSampler() :
m_upSampleIndex(0),
m_pack(0U),
m_packPointer(NULL),
m_samples(3600U), //300ms of 12 bit 8kHz audio
m_running(false)
{
m_packPointer = (uint8_t*)&m_pack;
}
void CFMUpSampler::reset()
{
m_upSampleIndex = 0U;
m_pack = 0U;
m_samples.reset();
m_running = false;
}
void CFMUpSampler::addData(const uint8_t* data, uint16_t length)
{
TSamplePairPack* packPointer = (TSamplePairPack*)data;
TSamplePairPack* packPointerEnd = packPointer + (length / 3U);
while(packPointer != packPointerEnd) {
m_samples.put(*packPointer);
packPointer++;
}
if(!m_running)
m_running = m_samples.getData() > 300U;//75ms of audio
}
bool CFMUpSampler::getSample(q15_t& sample)
{
if(!m_running)
return false;
switch (m_upSampleIndex)
{
case 0: {
TSamplePairPack pairPack;
if(!m_samples.get(pairPack)) {
m_running = false;
return false;
}
m_pack = 0U;
m_packPointer = (uint8_t*)&m_pack;
m_packPointer[0U] = pairPack.byte0;
m_packPointer[1U] = pairPack.byte1;
m_packPointer[2U] = pairPack.byte2;
sample = q15_t(m_pack >> 12) - 2048;
break;
}
case 3:
sample = q15_t(m_pack & FM_UPSAMPLE_MASK) - 2048;
break;
default:
sample = 0;
break;
}
m_upSampleIndex++;
if(m_upSampleIndex >= 6U)
m_upSampleIndex = 0U;
return true;
}
uint16_t CFMUpSampler::getSpace() const
{
//return available space in bytes
return m_samples.getSpace() * sizeof(TSamplePairPack);
}
#endif
-54
View File
@@ -1,54 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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"
#if defined(MODE_FM)
#if !defined(FMUPSAMPLER_H)
#define FMUPSAMPLER_H
#include "RingBuffer.h"
#include "FMSamplePairPack.h"
class CFMUpSampler {
public:
CFMUpSampler();
void reset();
void addData(const uint8_t* data, uint16_t length);
bool getSample(q15_t& sample);
uint16_t getSpace() const;
private:
uint8_t m_upSampleIndex;
uint32_t m_pack;
uint8_t * m_packPointer;
CRingBuffer<TSamplePairPack> m_samples;
bool m_running;
};
#endif
#endif
+13 -52
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 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
@@ -23,12 +23,14 @@
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#elif defined(STM32F105xC)
#include "stm32f1xx.h"
#include "STM32Utils.h"
#else
#include <Arduino.h>
#undef PI //Undefine PI to get rid of annoying warning as it is also defined in arm_math.h.
#endif
#if defined(__SAM3X8E__)
#if defined(__SAM3X8E__) || defined(STM32F105xC)
#define ARM_MATH_CM3
#elif defined(STM32F7XX)
#define ARM_MATH_CM7
@@ -48,7 +50,6 @@ enum MMDVM_STATE {
STATE_P25 = 4,
STATE_NXDN = 5,
STATE_POCSAG = 6,
STATE_FM = 10,
// Dummy states start at 90
STATE_NXDNCAL1K = 91,
@@ -59,15 +60,7 @@ enum MMDVM_STATE {
STATE_RSSICAL = 96,
STATE_CWID = 97,
STATE_DMRCAL = 98,
STATE_DSTARCAL = 99,
STATE_INTCAL = 100,
STATE_POCSAGCAL = 101,
STATE_FMCAL10K = 102,
STATE_FMCAL12K = 103,
STATE_FMCAL15K = 104,
STATE_FMCAL20K = 105,
STATE_FMCAL25K = 106,
STATE_FMCAL30K = 107
STATE_DSTARCAL = 99
};
#include "SerialPort.h"
@@ -87,16 +80,13 @@ enum MMDVM_STATE {
#include "POCSAGTX.h"
#include "CalDStarRX.h"
#include "CalDStarTX.h"
#include "CalFM.h"
#include "CalDMR.h"
#include "CalP25.h"
#include "CalNXDN.h"
#include "CalPOCSAG.h"
#include "CalRSSI.h"
#include "CWIdTX.h"
#include "Debug.h"
#include "IO.h"
#include "FM.h"
const uint8_t MARK_SLOT1 = 0x08U;
const uint8_t MARK_SLOT2 = 0x04U;
@@ -107,12 +97,6 @@ const uint16_t RX_BLOCK_SIZE = 2U;
const uint16_t TX_RINGBUFFER_SIZE = 500U;
const uint16_t RX_RINGBUFFER_SIZE = 600U;
#if defined(__MK20DX256__)
const uint16_t TX_BUFFER_LEN = 2000U;
#else
const uint16_t TX_BUFFER_LEN = 4000U;
#endif
extern MMDVM_STATE m_modemState;
extern bool m_dstarEnable;
@@ -121,7 +105,6 @@ extern bool m_ysfEnable;
extern bool m_p25Enable;
extern bool m_nxdnEnable;
extern bool m_pocsagEnable;
extern bool m_fmEnable;
extern bool m_duplex;
@@ -131,15 +114,9 @@ extern bool m_dcd;
extern CSerialPort serial;
extern CIO io;
#if defined(MODE_DSTAR)
extern CDStarRX dstarRX;
extern CDStarTX dstarTX;
extern CCalDStarRX calDStarRX;
extern CCalDStarTX calDStarTX;
#endif
#if defined(MODE_DMR)
extern CDMRIdleRX dmrIdleRX;
extern CDMRRX dmrRX;
extern CDMRTX dmrTX;
@@ -147,39 +124,23 @@ extern CDMRTX dmrTX;
extern CDMRDMORX dmrDMORX;
extern CDMRDMOTX dmrDMOTX;
extern CCalDMR calDMR;
#endif
#if defined(MODE_YSF)
extern CYSFRX ysfRX;
extern CYSFTX ysfTX;
#endif
#if defined(MODE_P25)
extern CP25RX p25RX;
extern CP25TX p25TX;
extern CCalP25 calP25;
#endif
#if defined(MODE_NXDN)
extern CNXDNRX nxdnRX;
extern CNXDNTX nxdnTX;
extern CCalNXDN calNXDN;
#endif
extern CPOCSAGTX pocsagTX;
#if defined(MODE_POCSAG)
extern CPOCSAGTX pocsagTX;
extern CCalPOCSAG calPOCSAG;
#endif
#if defined(MODE_FM)
extern CFM fm;
extern CCalFM calFM;
#endif
extern CCalRSSI calRSSI;
extern CCalDStarRX calDStarRX;
extern CCalDStarTX calDStarTX;
extern CCalDMR calDMR;
extern CCalP25 calP25;
extern CCalNXDN calNXDN;
extern CCalRSSI calRSSI;
extern CCWIdTX cwIdTX;
+1 -3
View File
@@ -1,6 +1,4 @@
/*
* Copyright (C) 2017 by Chris Huitema
*
* 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
@@ -184,7 +182,7 @@ void CSerialPort::beginInt(uint8_t n, int speed)
}
}
int CSerialPort::availableForReadInt(uint8_t n)
int CSerialPort::availableInt(uint8_t n)
{
switch (n) {
case 1U:
+178 -309
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2021,2023,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
* Copyright (C) 2016 by Colin Durbridge G4EML
*
@@ -22,26 +22,16 @@
#include "Globals.h"
#include "IO.h"
#if defined(USE_DCBLOCKER)
// Generated using [b, a] = butter(1, 0.001) in MATLAB
static q31_t DC_FILTER[] = {3367972, 0, 3367972, 0, 2140747704, 0}; // {b0, 0, b1, b2, -a1, -a2}
const uint32_t DC_FILTER_STAGES = 1U; // One Biquad stage
#endif
#if defined(MODE_DMR) || defined(MODE_YSF)
// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB
static q15_t RRC_0_2_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995,
11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112,
-553, -847, -731, -340, 104, 401, 0};
const uint16_t RRC_0_2_FILTER_LEN = 42U;
#endif
#if defined(MODE_NXDN)
#if defined(USE_NXDN_BOXCAR)
// One symbol boxcar filter
static q15_t BOXCAR10_FILTER[] = {6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000};
const uint16_t BOXCAR10_FILTER_LEN = 10U;
#else
// Generated using rcosdesign(0.2, 8, 10, 'sqrt') in MATLAB
static q15_t NXDN_0_2_FILTER[] = {284, 198, 73, -78, -240, -393, -517, -590, -599, -533, -391, -181, 79, 364, 643, 880, 1041, 1097, 1026, 819,
483, 39, -477, -1016, -1516, -1915, -2150, -2164, -1914, -1375, -545, 557, 1886, 3376, 4946, 6502, 7946, 9184,
@@ -53,20 +43,14 @@ const uint16_t NXDN_0_2_FILTER_LEN = 82U;
static q15_t NXDN_ISINC_FILTER[] = {790, -1085, -1073, -553, 747, 2341, 3156, 2152, -893, -4915, -7834, -7536, -3102, 4441, 12354, 17394, 17394,
12354, 4441, -3102, -7536, -7834, -4915, -893, 2152, 3156, 2341, 747, -553, -1073, -1085, 790};
const uint16_t NXDN_ISINC_FILTER_LEN = 32U;
#endif
#endif
#if defined(MODE_DSTAR)
// Generated using gaussfir(0.5, 4, 5) in MATLAB
static q15_t GAUSSIAN_0_5_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0};
const uint16_t GAUSSIAN_0_5_FILTER_LEN = 12U;
#endif
#if defined(MODE_P25)
// One symbol boxcar filter
static q15_t BOXCAR5_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0};
const uint16_t BOXCAR5_FILTER_LEN = 6U;
#endif
static q15_t BOXCAR_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0};
const uint16_t BOXCAR_FILTER_LEN = 6U;
const uint16_t DC_OFFSET = 2048U;
@@ -75,37 +59,18 @@ m_started(false),
m_rxBuffer(RX_RINGBUFFER_SIZE),
m_txBuffer(TX_RINGBUFFER_SIZE),
m_rssiBuffer(RX_RINGBUFFER_SIZE),
#if defined(USE_DCBLOCKER)
m_dcFilter(),
m_dcState(),
#endif
#if defined(MODE_DSTAR)
m_rrcFilter(),
m_gaussianFilter(),
m_gaussianState(),
#endif
#if defined(MODE_DMR)
m_rrc02Filter1(),
m_rrc02State1(),
#endif
#if defined(MODE_YSF)
m_rrc02Filter2(),
m_rrc02State2(),
#endif
#if defined(MODE_P25)
m_boxcar5Filter(),
m_boxcar5State(),
#endif
#if defined(MODE_NXDN)
#if defined(USE_NXDN_BOXCAR)
m_boxcar10Filter(),
m_boxcar10State(),
#else
m_boxcarFilter(),
m_nxdnFilter(),
m_nxdnISincFilter(),
m_rrcState(),
m_gaussianState(),
m_boxcarState(),
m_nxdnState(),
m_nxdnISincState(),
#endif
#endif
m_pttInvert(false),
m_rxLevel(128 * 128),
m_cwIdTXLevel(128 * 128),
@@ -115,10 +80,8 @@ m_ysfTXLevel(128 * 128),
m_p25TXLevel(128 * 128),
m_nxdnTXLevel(128 * 128),
m_pocsagTXLevel(128 * 128),
m_fmTXLevel(128 * 128),
m_rxDCOffset(DC_OFFSET),
m_txDCOffset(DC_OFFSET),
m_useCOSAsLockout(false),
m_ledCount(0U),
m_ledValue(true),
m_detect(false),
@@ -127,52 +90,30 @@ m_dacOverflow(0U),
m_watchdog(0U),
m_lockout(false)
{
#if defined(USE_DCBLOCKER)
::memset(m_dcState, 0x00U, 4U * sizeof(q31_t));
::memset(m_rrcState, 0x00U, 70U * sizeof(q15_t));
::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t));
::memset(m_boxcarState, 0x00U, 30U * sizeof(q15_t));
::memset(m_nxdnState, 0x00U, 110U * sizeof(q15_t));
::memset(m_nxdnISincState, 0x00U, 60U * sizeof(q15_t));
::memset(m_dcState, 0x00U, 4U * sizeof(q31_t));
m_dcFilter.numStages = DC_FILTER_STAGES;
m_dcFilter.pState = m_dcState;
m_dcFilter.pCoeffs = DC_FILTER;
m_dcFilter.postShift = 0;
#endif
#if defined(MODE_DSTAR)
::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t));
m_rrcFilter.numTaps = RRC_0_2_FILTER_LEN;
m_rrcFilter.pState = m_rrcState;
m_rrcFilter.pCoeffs = RRC_0_2_FILTER;
m_gaussianFilter.numTaps = GAUSSIAN_0_5_FILTER_LEN;
m_gaussianFilter.pState = m_gaussianState;
m_gaussianFilter.pCoeffs = GAUSSIAN_0_5_FILTER;
#endif
#if defined(MODE_DMR)
::memset(m_rrc02State1, 0x00U, 70U * sizeof(q15_t));
m_rrc02Filter1.numTaps = RRC_0_2_FILTER_LEN;
m_rrc02Filter1.pState = m_rrc02State1;
m_rrc02Filter1.pCoeffs = RRC_0_2_FILTER;
#endif
#if defined(MODE_YSF)
::memset(m_rrc02State2, 0x00U, 70U * sizeof(q15_t));
m_rrc02Filter2.numTaps = RRC_0_2_FILTER_LEN;
m_rrc02Filter2.pState = m_rrc02State2;
m_rrc02Filter2.pCoeffs = RRC_0_2_FILTER;
#endif
#if defined(MODE_P25)
::memset(m_boxcar5State, 0x00U, 30U * sizeof(q15_t));
m_boxcar5Filter.numTaps = BOXCAR5_FILTER_LEN;
m_boxcar5Filter.pState = m_boxcar5State;
m_boxcar5Filter.pCoeffs = BOXCAR5_FILTER;
#endif
#if defined(MODE_NXDN)
#if defined(USE_NXDN_BOXCAR)
::memset(m_boxcar10State, 0x00U, 40U * sizeof(q15_t));
m_boxcar10Filter.numTaps = BOXCAR10_FILTER_LEN;
m_boxcar10Filter.pState = m_boxcar10State;
m_boxcar10Filter.pCoeffs = BOXCAR10_FILTER;
#else
::memset(m_nxdnState, 0x00U, 110U * sizeof(q15_t));
::memset(m_nxdnISincState, 0x00U, 60U * sizeof(q15_t));
m_boxcarFilter.numTaps = BOXCAR_FILTER_LEN;
m_boxcarFilter.pState = m_boxcarState;
m_boxcarFilter.pCoeffs = BOXCAR_FILTER;
m_nxdnFilter.numTaps = NXDN_0_2_FILTER_LEN;
m_nxdnFilter.pState = m_nxdnState;
m_nxdnFilter.pCoeffs = NXDN_0_2_FILTER;
@@ -180,8 +121,6 @@ m_lockout(false)
m_nxdnISincFilter.numTaps = NXDN_ISINC_FILTER_LEN;
m_nxdnISincFilter.pState = m_nxdnISincState;
m_nxdnISincFilter.pCoeffs = NXDN_ISINC_FILTER;
#endif
#endif
initInt();
@@ -192,94 +131,129 @@ void CIO::selfTest()
{
bool ledValue = false;
for (uint8_t i = 0U; i < 6U; i++) {
for (uint8_t i = 0; i < 6; i++) {
ledValue = !ledValue;
// We exclude PTT to avoid trigger the transmitter
setLEDInt(ledValue);
setCOSInt(ledValue);
#if defined(MODE_LEDS)
#if defined(MODE_PINS)
setDStarInt(ledValue);
setDMRInt(ledValue);
setYSFInt(ledValue);
setP25Int(ledValue);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
setNXDNInt(ledValue);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
setPOCSAGInt(ledValue);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
setFMInt(ledValue);
#endif
#endif
delayInt(250);
}
#if defined(MODE_LEDS)
setDStarInt(false);
setDMRInt(false);
setYSFInt(false);
setP25Int(false);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
setNXDNInt(false);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
setPOCSAGInt(false);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
setFMInt(false);
#endif
#if defined(MODE_PINS)
setDStarInt(true);
delayInt(250);
setDMRInt(true);
delayInt(250);
setYSFInt(true);
delayInt(250);
setP25Int(true);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
delayInt(250);
setNXDNInt(true);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
delayInt(250);
setPOCSAGInt(true);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
delayInt(250);
setFMInt(true);
delayInt(250);
setFMInt(false);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
delayInt(250);
setPOCSAGInt(false);
#endif
#if !defined(USE_ALTERNATE_NXDN_LEDS)
delayInt(250);
setNXDNInt(false);
#endif
delayInt(250);
setP25Int(false);
delayInt(250);
setYSFInt(false);
delayInt(250);
setDMRInt(false);
setYSFInt(false);
setP25Int(false);
setNXDNInt(false);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(false);
setP25Int(false);
setNXDNInt(false);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(true);
setP25Int(false);
setNXDNInt(false);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(true);
setP25Int(true);
setNXDNInt(false);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(true);
setP25Int(true);
setNXDNInt(true);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(true);
setP25Int(true);
setNXDNInt(true);
setPOCSAGInt(true);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(true);
setP25Int(true);
setNXDNInt(true);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(true);
setP25Int(true);
setNXDNInt(false);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(true);
setP25Int(false);
setNXDNInt(false);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(true);
setYSFInt(false);
setP25Int(false);
setNXDNInt(false);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(true);
setDMRInt(false);
setYSFInt(false);
setP25Int(false);
setNXDNInt(false);
setPOCSAGInt(false);
delayInt(250);
setDStarInt(false);
setDMRInt(false);
setYSFInt(false);
setP25Int(false);
setNXDNInt(false);
setPOCSAGInt(false);
#endif
}
@@ -292,7 +266,7 @@ void CIO::start()
m_started = true;
setMode(STATE_IDLE);
setMode();
}
void CIO::process()
@@ -302,11 +276,10 @@ void CIO::process()
// Two seconds timeout
if (m_watchdog >= 48000U) {
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN || m_modemState == STATE_POCSAG) {
#if defined(MODE_DMR)
if (m_modemState == STATE_DMR && m_tx)
dmrTX.setStart(false);
#endif
setMode(STATE_IDLE);
m_modemState = STATE_IDLE;
setMode();
}
m_watchdog = 0U;
@@ -330,14 +303,14 @@ void CIO::process()
return;
}
if (m_useCOSAsLockout)
m_lockout = getCOSInt();
#if defined(USE_COS_AS_LOCKOUT)
m_lockout = getCOSInt();
#endif
// Switch off the transmitter if needed
if (m_txBuffer.getData() == 0U && m_tx) {
m_tx = false;
setPTTInt(m_pttInvert ? true : false);
DEBUG1("TX OFF");
}
if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) {
@@ -346,16 +319,15 @@ void CIO::process()
uint16_t rssi[RX_BLOCK_SIZE];
for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) {
TSample sample;
m_rxBuffer.get(sample);
control[i] = sample.control;
uint16_t sample;
m_rxBuffer.get(sample, control[i]);
m_rssiBuffer.get(rssi[i]);
// Detect ADC overflow
if (m_detect && (sample.sample == 0U || sample.sample == 4095U))
if (m_detect && (sample == 0U || sample == 4095U))
m_adcOverflow++;
q15_t res1 = q15_t(sample.sample) - m_rxDCOffset;
q15_t res1 = q15_t(sample) - m_rxDCOffset;
q31_t res2 = res1 * m_rxLevel;
samples[i] = q15_t(__SSAT((res2 >> 15), 16));
}
@@ -383,7 +355,6 @@ void CIO::process()
#endif
if (m_modemState == STATE_IDLE) {
#if defined(MODE_DSTAR)
if (m_dstarEnable) {
q15_t GMSKVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
@@ -393,80 +364,45 @@ void CIO::process()
#endif
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_P25)
if (m_p25Enable) {
q15_t P25Vals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, P25Vals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, P25Vals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_boxcar5Filter, samples, P25Vals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE);
#endif
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_NXDN)
if (m_nxdnEnable) {
q15_t NXDNVals[RX_BLOCK_SIZE];
#if defined(USE_NXDN_BOXCAR)
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_boxcar10Filter, dcSamples, NXDNVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_boxcar10Filter, samples, NXDNVals, RX_BLOCK_SIZE);
#endif
#else
q15_t NXDNValsTmp[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNValsTmp, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_nxdnFilter, samples, NXDNValsTmp, RX_BLOCK_SIZE);
#endif
q15_t NXDNVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_nxdnISincFilter, NXDNValsTmp, NXDNVals, RX_BLOCK_SIZE);
#endif
nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_DMR)
if (m_dmrEnable) {
q15_t DMRVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_rrc02Filter1, samples, DMRVals, RX_BLOCK_SIZE);
if (m_dmrEnable || m_ysfEnable) {
q15_t RRCVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_rrcFilter, samples, RRCVals, RX_BLOCK_SIZE);
if (m_duplex)
dmrIdleRX.samples(DMRVals, RX_BLOCK_SIZE);
else
dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE);
if (m_ysfEnable)
ysfRX.samples(RRCVals, rssi, RX_BLOCK_SIZE);
if (m_dmrEnable) {
if (m_duplex)
dmrIdleRX.samples(RRCVals, RX_BLOCK_SIZE);
else
dmrDMORX.samples(RRCVals, rssi, RX_BLOCK_SIZE);
}
}
#endif
#if defined(MODE_YSF)
if (m_ysfEnable) {
q15_t YSFVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_rrc02Filter2, dcSamples, YSFVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_rrc02Filter2, samples, YSFVals, RX_BLOCK_SIZE);
#endif
ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE);
}
#endif
#if defined(MODE_FM)
if (m_fmEnable) {
bool cos = getCOSInt();
#if defined(USE_DCBLOCKER)
fm.samples(cos, dcSamples, rssi, RX_BLOCK_SIZE);
#else
fm.samples(cos, samples, rssi, RX_BLOCK_SIZE);
#endif
}
#endif
}
#if defined(MODE_DSTAR)
else if (m_modemState == STATE_DSTAR) {
} else if (m_modemState == STATE_DSTAR) {
if (m_dstarEnable) {
q15_t GMSKVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
@@ -476,14 +412,10 @@ void CIO::process()
#endif
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
}
}
#endif
#if defined(MODE_DMR)
else if (m_modemState == STATE_DMR) {
} else if (m_modemState == STATE_DMR) {
if (m_dmrEnable) {
q15_t DMRVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_rrc02Filter1, samples, DMRVals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_rrcFilter, samples, DMRVals, RX_BLOCK_SIZE);
if (m_duplex) {
// If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs
@@ -495,82 +427,45 @@ void CIO::process()
dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE);
}
}
}
#endif
#if defined(MODE_YSF)
else if (m_modemState == STATE_YSF) {
} else if (m_modemState == STATE_YSF) {
if (m_ysfEnable) {
q15_t YSFVals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_rrc02Filter2, dcSamples, YSFVals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_rrcFilter, dcSamples, YSFVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_rrc02Filter2, samples, YSFVals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_rrcFilter, samples, YSFVals, RX_BLOCK_SIZE);
#endif
ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE);
}
}
#endif
#if defined(MODE_P25)
else if (m_modemState == STATE_P25) {
} else if (m_modemState == STATE_P25) {
if (m_p25Enable) {
q15_t P25Vals[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, P25Vals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, P25Vals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_boxcar5Filter, samples, P25Vals, RX_BLOCK_SIZE);
::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE);
#endif
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
}
}
#endif
#if defined(MODE_NXDN)
else if (m_modemState == STATE_NXDN) {
} else if (m_modemState == STATE_NXDN) {
if (m_nxdnEnable) {
q15_t NXDNVals[RX_BLOCK_SIZE];
#if defined(USE_NXDN_BOXCAR)
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_boxcar10Filter, dcSamples, NXDNVals, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_boxcar10Filter, samples, NXDNVals, RX_BLOCK_SIZE);
#endif
#else
q15_t NXDNValsTmp[RX_BLOCK_SIZE];
#if defined(USE_DCBLOCKER)
::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNValsTmp, RX_BLOCK_SIZE);
#else
::arm_fir_fast_q15(&m_nxdnFilter, samples, NXDNValsTmp, RX_BLOCK_SIZE);
#endif
q15_t NXDNVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_nxdnISincFilter, NXDNValsTmp, NXDNVals, RX_BLOCK_SIZE);
#endif
nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE);
}
}
#endif
#if defined(MODE_FM)
else if (m_modemState == STATE_FM) {
bool cos = getCOSInt();
#if defined(USE_DCBLOCKER)
fm.samples(cos, dcSamples, RX_BLOCK_SIZE);
#else
fm.samples(cos, samples, RX_BLOCK_SIZE);
#endif
}
#endif
#if defined(MODE_DSTAR)
else if (m_modemState == STATE_DSTARCAL) {
} else if (m_modemState == STATE_DSTARCAL) {
q15_t GMSKVals[RX_BLOCK_SIZE];
::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE);
calDStarRX.samples(GMSKVals, RX_BLOCK_SIZE);
}
#endif
else if (m_modemState == STATE_RSSICAL) {
} else if (m_modemState == STATE_RSSICAL) {
calRSSI.samples(rssi, RX_BLOCK_SIZE);
}
}
@@ -588,7 +483,6 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
if (!m_tx) {
m_tx = true;
setPTTInt(m_pttInvert ? false : true);
DEBUG1("TX ON");
}
q15_t txLevel = 0;
@@ -611,9 +505,6 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
case STATE_POCSAG:
txLevel = m_pocsagTXLevel;
break;
case STATE_FM:
txLevel = m_fmTXLevel;
break;
default:
txLevel = m_cwIdTXLevel;
break;
@@ -629,9 +520,9 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
m_dacOverflow++;
if (control == NULL)
m_txBuffer.put({res3, MARK_NONE});
m_txBuffer.put(res3, MARK_NONE);
else
m_txBuffer.put({res3, control[i]});
m_txBuffer.put(res3, control[i]);
}
}
@@ -653,39 +544,19 @@ void CIO::setADCDetection(bool detect)
m_detect = detect;
}
void CIO::setMode(MMDVM_STATE state)
void CIO::setMode()
{
if (state == m_modemState)
return;
#if defined(MODE_LEDS)
switch (m_modemState) {
case STATE_DSTAR: setDStarInt(false); break;
case STATE_DMR: setDMRInt(false); break;
case STATE_YSF: setYSFInt(false); break;
case STATE_P25: setP25Int(false); break;
case STATE_NXDN: setNXDNInt(false); break;
case STATE_POCSAG: setPOCSAGInt(false); break;
case STATE_FM: setFMInt(false); break;
default: break;
}
switch (state) {
case STATE_DSTAR: setDStarInt(true); break;
case STATE_DMR: setDMRInt(true); break;
case STATE_YSF: setYSFInt(true); break;
case STATE_P25: setP25Int(true); break;
case STATE_NXDN: setNXDNInt(true); break;
case STATE_POCSAG: setPOCSAGInt(true); break;
case STATE_FM: setFMInt(true); break;
default: break;
}
#if defined(MODE_PINS)
setDStarInt(m_modemState == STATE_DSTAR);
setDMRInt(m_modemState == STATE_DMR);
setYSFInt(m_modemState == STATE_YSF);
setP25Int(m_modemState == STATE_P25);
setNXDNInt(m_modemState == STATE_NXDN);
setPOCSAGInt(m_modemState == STATE_POCSAG);
#endif
m_modemState = state;
}
void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout)
void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, int16_t txDCOffset, int16_t rxDCOffset)
{
m_pttInvert = pttInvert;
@@ -697,12 +568,9 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx
m_p25TXLevel = q15_t(p25TXLevel * 128);
m_nxdnTXLevel = q15_t(nxdnTXLevel * 128);
m_pocsagTXLevel = q15_t(pocsagTXLevel * 128);
m_fmTXLevel = q15_t(fmTXLevel * 128);
m_rxDCOffset = DC_OFFSET + rxDCOffset;
m_txDCOffset = DC_OFFSET + txDCOffset;
m_useCOSAsLockout = useCOSAsLockout;
if (rxInvert)
m_rxLevel = -m_rxLevel;
@@ -750,3 +618,4 @@ bool CIO::hasLockout() const
{
return m_lockout;
}
+14 -49
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 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
@@ -21,12 +21,8 @@
#include "Globals.h"
#include "RingBuffer.h"
struct TSample {
volatile uint16_t sample;
volatile uint8_t control;
};
#include "SampleRB.h"
#include "RSSIRB.h"
class CIO {
public:
@@ -42,11 +38,11 @@ public:
void setDecode(bool dcd);
void setADCDetection(bool detect);
void setMode(MMDVM_STATE state);
void setMode();
void interrupt();
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout);
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, int16_t txDCOffset, int16_t rxDCOffset);
void getOverflow(bool& adcOverflow, bool& dacOverflow);
@@ -58,55 +54,28 @@ public:
void resetWatchdog();
uint32_t getWatchdog();
uint8_t getCPU() const;
void getUDID(uint8_t* buffer);
void selfTest();
private:
bool m_started;
bool m_started;
CRingBuffer<TSample> m_rxBuffer;
CRingBuffer<TSample> m_txBuffer;
CRingBuffer<uint16_t> m_rssiBuffer;
CSampleRB m_rxBuffer;
CSampleRB m_txBuffer;
CRSSIRB m_rssiBuffer;
#if defined(USE_DCBLOCKER)
arm_biquad_casd_df1_inst_q31 m_dcFilter;
q31_t m_dcState[4];
#endif
#if defined(MODE_DSTAR)
arm_fir_instance_q15 m_rrcFilter;
arm_fir_instance_q15 m_gaussianFilter;
q15_t m_gaussianState[40U]; // NoTaps + BlockSize - 1, 12 + 20 - 1 plus some spare
#endif
#if defined(MODE_DMR)
arm_fir_instance_q15 m_rrc02Filter1;
q15_t m_rrc02State1[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
#endif
#if defined(MODE_YSF)
arm_fir_instance_q15 m_rrc02Filter2;
q15_t m_rrc02State2[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
#endif
#if defined(MODE_P25)
arm_fir_instance_q15 m_boxcar5Filter;
q15_t m_boxcar5State[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare
#endif
#if defined(MODE_NXDN)
#if defined(USE_NXDN_BOXCAR)
arm_fir_instance_q15 m_boxcar10Filter;
q15_t m_boxcar10State[40U]; // NoTaps + BlockSize - 1, 10 + 20 - 1 plus some spare
#else
arm_fir_instance_q15 m_boxcarFilter;
arm_fir_instance_q15 m_nxdnFilter;
arm_fir_instance_q15 m_nxdnISincFilter;
q15_t m_rrcState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
q15_t m_gaussianState[40U]; // NoTaps + BlockSize - 1, 12 + 20 - 1 plus some spare
q15_t m_boxcarState[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare
q15_t m_nxdnState[110U]; // NoTaps + BlockSize - 1, 82 + 20 - 1 plus some spare
q15_t m_nxdnISincState[60U]; // NoTaps + BlockSize - 1, 32 + 20 - 1 plus some spare
#endif
#endif
bool m_pttInvert;
q15_t m_rxLevel;
@@ -117,13 +86,10 @@ private:
q15_t m_p25TXLevel;
q15_t m_nxdnTXLevel;
q15_t m_pocsagTXLevel;
q15_t m_fmTXLevel;
uint16_t m_rxDCOffset;
uint16_t m_txDCOffset;
bool m_useCOSAsLockout;
uint32_t m_ledCount;
bool m_ledValue;
@@ -152,7 +118,6 @@ private:
void setP25Int(bool on);
void setNXDNInt(bool on);
void setPOCSAGInt(bool on);
void setFMInt(bool on);
void delayInt(unsigned int dly);
};
+8 -51
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
* Copyright (C) 2016 by Colin Durbridge G4EML
*
@@ -35,7 +35,6 @@
#define PIN_P25 19
#define PIN_NXDN 20
#define PIN_POCSAG 4
#define PIN_FM 5
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
#define ADC_CDR_Chan 7
@@ -51,7 +50,6 @@
#define PIN_P25 6
#define PIN_NXDN 5
#define PIN_POCSAG 4
#define PIN_FM 3
#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13)
#define ADC_ISR_EOC_Chan ADC_ISR_EOC13
#define ADC_CDR_Chan 13
@@ -69,7 +67,6 @@
#define PIN_P25 6
#define PIN_NXDN 5
#define PIN_POCSAG 4
#define PIN_FM 3
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
#define ADC_CDR_Chan 7
@@ -98,7 +95,7 @@ void CIO::initInt()
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_COS, INPUT);
#if defined(MODE_LEDS)
#if defined(MODE_PINS)
// Set up the mode output pins
pinMode(PIN_DSTAR, OUTPUT);
pinMode(PIN_DMR, OUTPUT);
@@ -110,9 +107,6 @@ void CIO::initInt()
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
pinMode(PIN_POCSAG, OUTPUT);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
pinMode(PIN_FM, OUTPUT);
#endif
#endif
}
@@ -185,13 +179,14 @@ void CIO::startInt()
void CIO::interrupt()
{
if ((ADC->ADC_ISR & ADC_ISR_EOC_Chan) == ADC_ISR_EOC_Chan) { // Ensure there was an End-of-Conversion and we read the ISR reg
TSample sample = {DC_OFFSET, MARK_NONE};
uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET;
m_txBuffer.get(sample);
DACC->DACC_CDR = sample.sample;
m_txBuffer.get(sample, control);
DACC->DACC_CDR = sample;
sample.sample = ADC->ADC_CDR[ADC_CDR_Chan];
m_rxBuffer.put(sample);
sample = ADC->ADC_CDR[ADC_CDR_Chan];
m_rxBuffer.put(sample, control);
#if defined(SEND_RSSI_DATA)
m_rssiBuffer.put(ADC->ADC_CDR[RSSI_CDR_Chan]);
@@ -263,48 +258,10 @@ void CIO::setPOCSAGInt(bool on)
#endif
}
void CIO::setFMInt(bool on)
{
#if defined(USE_ALTERNATE_FM_LEDS)
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
digitalWrite(PIN_YSF, on ? HIGH : LOW);
#else
digitalWrite(PIN_FM, on ? HIGH : LOW);
#endif
}
void CIO::delayInt(unsigned int dly)
{
delay(dly);
}
uint8_t CIO::getCPU() const
{
return 0U;
}
// Code taken from https://github.com/emagii/at91sam3s/blob/master/examples/eefc_uniqueid/main.c
void CIO::getUDID(uint8_t* buffer)
{
uint32_t status;
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
do {
status = EFC1->EEFC_FSR;
} while ( (status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY );
for (uint8_t i = 0; i < 16; i+=4) {
buffer[i + 0] = *(uint32_t *)(IFLASH1_ADDR + i) >> 24;
buffer[i + 1] = *(uint32_t *)(IFLASH1_ADDR + i) >> 16;
buffer[i + 2] = *(uint32_t *)(IFLASH1_ADDR + i) >> 8;
buffer[i + 3] = *(uint32_t *)(IFLASH1_ADDR + i) >> 0;
}
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
do {
status = EFC1->EEFC_FSR;
} while ( (status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY );
}
#endif
-79
View File
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2019,2020 by BG5HHP
*
* 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.
*/
#ifndef _IO_PINS_H
#define _IO_PINS_H
#if !defined(CONFIG_H)
#error "Requires Config.h to be included first!"
#endif
#if defined(STM32F4_RPT_HAT_TGO)
#include "pins/pins_f4_rpt_tgo.h"
#elif defined(STM32F4_DISCOVERY)
#include "pins/pins_f4_discovery.h"
#elif defined(STM32F4_PI)
#include "pins/pins_f4_pi.h"
#elif defined(STM32F722_PI)
#include "pins/pins_f7_pi.h"
#elif defined(STM32F4_F4M)
#include "pins/pins_f4_f4m.h"
#elif defined(STM32F722_F7M)
#include "pins/pins_f7_f7m.h"
#elif defined(STM32F722_RPT_HAT)
#include "pins/pins_f7_rpt_hat.h"
#elif defined(STM32F4_NUCLEO)
#if defined(STM32F4_NUCLEO_MORPHO_HEADER)
#include "pins/pins_f4_nucleo_morpho.h"
#elif defined(STM32F4_NUCLEO_ARDUINO_HEADER)
#include "pins/pins_f4_nucleo_arduino.h"
#else
#error "Either STM32F4_NUCLEO_MORPHO_HEADER or STM32F4_NUCLEO_ARDUINO_HEADER need to be defined"
#endif
#elif defined(STM32F7_NUCLEO)
#include "pins/pins_f7_nucleo.h"
#elif defined(STM32F4_DVM)
#include "pins/pins_f4_stm32dvm_v3.h"
#elif defined(STM32F7_DVM)
#include "pins/pins_f7_stm32dvm_v5.h"
#elif defined(DRCC_DVM_NQF)
#include "pins/pins_f4_drcc_nqf.h"
#elif defined(DRCC_DVM_HHP446)
#include "pins/pins_f4_drcc_hhp446.h"
#elif defined(STM32F4_EDA_405) || defined(STM32F4_EDA_446)
#include "pins/pins_f4_stm32eda.h"
#else
#error "A valid board type macro need to be defined."
#endif
#endif //#ifndef _IO_PINS_H
+923 -103
View File
File diff suppressed because it is too large Load Diff
+466
View File
@@ -0,0 +1,466 @@
/*
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016, 2017 by Andy Uribe CA6JAU
* Copyright (C) 2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
*
* 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 "IO.h"
#if defined(STM32F1)
#if defined(STM32F1_POG)
/*
Pin definitions for STM32F1 POG Board:
PTT PB12 output
COSLED PB5 output
LED PB4 output
COS PB13 input/PD
DSTAR PB7 output
DMR PB6 output
YSF PB8 output
P25 PB9 output
NXDN PB10 output
POCSAG PB11 output
RX PB0 analog input (ADC1_8)
RSSI PB1 analog input (ADC2_9)
TX PA4 analog output (DAC_OUT1)
EXT_CLK PA15 input (AF: TIM2_CH1_ETR)
USART1_TXD PA9 output (AF)
USART1_RXD PA10 input (AF)
*/
#define PIN_PTT 12
#define PORT_PTT GPIOB
#define BB_PTT *((bitband_t)BITBAND_PERIPH(&PORT_PTT->ODR, PIN_PTT))
#define PIN_COSLED 5
#define PORT_COSLED GPIOB
#define BB_COSLED *((bitband_t)BITBAND_PERIPH(&PORT_COSLED->ODR, PIN_COSLED))
#define PIN_LED 4
#define PORT_LED GPIOB
#define BB_LED *((bitband_t)BITBAND_PERIPH(&PORT_LED->ODR, PIN_LED))
#define PIN_COS 13
#define PORT_COS GPIOB
#define BB_COS *((bitband_t)BITBAND_PERIPH(&PORT_COS->IDR, PIN_COS))
#define PIN_DSTAR 7
#define PORT_DSTAR GPIOB
#define BB_DSTAR *((bitband_t)BITBAND_PERIPH(&PORT_DSTAR->ODR, PIN_DSTAR))
#define PIN_DMR 6
#define PORT_DMR GPIOB
#define BB_DMR *((bitband_t)BITBAND_PERIPH(&PORT_DMR->ODR, PIN_DMR))
#define PIN_YSF 8
#define PORT_YSF GPIOB
#define BB_YSF *((bitband_t)BITBAND_PERIPH(&PORT_YSF->ODR, PIN_YSF))
#define PIN_P25 9
#define PORT_P25 GPIOB
#define BB_P25 *((bitband_t)BITBAND_PERIPH(&PORT_P25->ODR, PIN_P25))
#define PIN_NXDN 10
#define PORT_NXDN GPIOB
#define BB_NXDN *((bitband_t)BITBAND_PERIPH(&PORT_NXDN->ODR, PIN_NXDN))
#define PIN_POCSAG 11
#define PORT_POCSAG GPIOB
#define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG))
#define PIN_RX 0
#define PIN_RX_ADC_CH 8
#define PORT_RX GPIOB
#define PIN_RSSI 1
#define PIN_RSSI_ADC_CH 9
#define PORT_RSSI GPIOB
#define PIN_TX 4
#define PIN_TX_DAC_CH 1
#define PORT_TX GPIOA
#define PIN_EXT_CLK 15
#define SRC_EXT_CLK 15
#define PORT_EXT_CLK GPIOA
#define PIN_USART1_TXD 9
#define PORT_USART1_TXD GPIOA
#define PIN_USART1_RXD 10
#define PORT_USART1_RXD GPIOA
#else // defined(STM32F1_POG)
#error "Either STM32F1_POG, or sth need to be defined"
#endif // defined(STM32F1_POG)
const uint16_t DC_OFFSET = 2048U;
// Sampling frequency
#define SAMP_FREQ 24000
extern "C" {
void TIM2_IRQHandler() {
if ((TIM2->SR & TIM_SR_UIF) == TIM_SR_UIF) {
TIM2->SR = ~TIM_SR_UIF; // clear UI flag
io.interrupt();
}
}
}
void delay(uint32_t cnt)
{
while(cnt--)
asm("nop");
}
// source: http://www.freddiechopin.info/
void GPIOConfigPin(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value)
{
volatile uint32_t *cr_ptr;
uint32_t cr_value;
cr_ptr = &port_ptr->CRL; // configuration of pins [0,7] is in CRL
if (pin >= 8) // is pin in [8; 15]?
{ // configuration of pins [8,15] is in CRH
cr_ptr++; // advance to next struct element CRL -> CRH
pin -= 8; // crop the pin number
}
cr_value = *cr_ptr; // localize the CRL / CRH value
cr_value &= ~(0xF << (pin * 4)); // clear the MODE and CNF fields (now that pin is an analog input)
cr_value |= (mode_cnf_value << (pin * 4)); // save new MODE and CNF value for desired pin
*cr_ptr = cr_value; // save localized value to CRL / CRL
}
#if defined(STM32F1_POG)
void FancyLEDEffect()
{
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25};
for(int i=0; i<7; i++){
*foo[i] = 0x01;
}
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
delay(SystemCoreClock/1000*100);
for(int i=0; i<7; i++){
*foo[i] = 0x00;
}
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
delay(SystemCoreClock/1000*20);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
delay(SystemCoreClock/1000*10);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
*foo[0] = 0x01;
for(int i=1; i<7; i++){
delay(SystemCoreClock/1000*10);
*foo[i-1] = 0x00;
*foo[i] = 0x01;
}
for(int i=5; i>=0; i--){
delay(SystemCoreClock/1000*10);
*foo[i+1] = 0x00;
*foo[i] = 0x01;
}
delay(SystemCoreClock/1000*10);
*foo[5+1-6] = 0x00;
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
delay(SystemCoreClock/1000*10);
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
delay(SystemCoreClock/1000*50);
}
#endif
static inline void GPIOInit()
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN
| RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN
| RCC_APB2ENR_AFIOEN; // enable all GPIOs
// set all ports to input with pull-down
GPIOA->CRL = 0x88888888;
GPIOA->CRH = 0x88888888;
GPIOA->ODR = 0;
GPIOB->CRL = 0x88888888;
GPIOB->CRH = 0x88888888;
GPIOB->ODR = 0;
GPIOC->CRL = 0x88888888;
GPIOC->CRH = 0x88888888;
GPIOC->ODR = 0;
GPIOD->CRL = 0x88888888;
GPIOD->CRH = 0x88888888;
GPIOD->ODR = 0;
// configure ports
GPIOConfigPin(PORT_PTT, PIN_PTT, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_COSLED, PIN_COSLED, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_LED, PIN_LED, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_COS, PIN_COS, GPIO_CRL_CNF0_1);
GPIOConfigPin(PORT_DSTAR, PIN_DSTAR, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_DMR, PIN_DMR, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_YSF, PIN_YSF, GPIO_CRL_MODE0_1);
GPIOConfigPin(PORT_P25, PIN_P25, GPIO_CRL_MODE0_1);
#if !defined(USE_ALTERNATE_NXDN_LEDS)
GPIOConfigPin(PORT_NXDN, PIN_NXDN, GPIO_CRL_MODE0_1);
#endif
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
GPIOConfigPin(PORT_POCSAG, PIN_POCSAG, GPIO_CRL_MODE0_1);
#endif
GPIOConfigPin(PORT_RX, PIN_RX, 0);
#if defined(SEND_RSSI_DATA)
GPIOConfigPin(PORT_RSSI, PIN_RSSI, 0);
#endif
GPIOConfigPin(PORT_TX, PIN_TX, 0);
#if defined(EXTERNAL_OSC)
#if defined(STM32F1_POG)
GPIOConfigPin(PORT_EXT_CLK, PIN_EXT_CLK, GPIO_CRL_CNF0_0);
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_TIM2_REMAP) | AFIO_MAPR_TIM2_REMAP_0;
#endif
#endif
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
GPIOConfigPin(PORT_USART1_RXD, PIN_USART1_RXD, GPIO_CRL_CNF0_0);
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_SWJ_CFG) | AFIO_MAPR_SWJ_CFG_1;
}
static inline void ADCInit()
{
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_ADCPRE_Msk)
| RCC_CFGR_ADCPRE_DIV6; // ADC clock divided by 6 (72MHz/6 = 12MHz)
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
#if defined(SEND_RSSI_DATA)
RCC->APB2ENR |= RCC_APB2ENR_ADC2EN;
#endif
// Init ADCs in dual mode (RSSI)
#if defined(SEND_RSSI_DATA)
ADC1->CR1 = ADC_CR1_DUALMOD_1|ADC_CR1_DUALMOD_2; // Regular simultaneous mode
#endif
// Set sampling time to 7.5 cycles
if (PIN_RX_ADC_CH < 10) {
ADC1->SMPR2 = ADC_SMPR2_SMP0_0 << (3*PIN_RX_ADC_CH);
} else {
ADC1->SMPR1 = ADC_SMPR1_SMP10_0 << (3*PIN_RX_ADC_CH);
}
#if defined(SEND_RSSI_DATA)
if (PIN_RSSI_ADC_CH < 10) {
ADC2->SMPR2 = ADC_SMPR2_SMP0_0 << (3*PIN_RSSI_ADC_CH);
} else {
ADC2->SMPR1 = ADC_SMPR1_SMP10_0 << (3*PIN_RSSI_ADC_CH);
}
#endif
// Set conversion channel (single conversion)
ADC1->SQR3 = PIN_RX_ADC_CH;
#if defined(SEND_RSSI_DATA)
ADC2->SQR3 = PIN_RSSI_ADC_CH;
#endif
// Enable ADC
ADC1->CR2 |= ADC_CR2_ADON;
#if defined(SEND_RSSI_DATA)
// Enable ADC2
ADC2->CR2 |= ADC_CR2_ADON;
#endif
// Start calibration
delay(6*2);
ADC1->CR2 |= ADC_CR2_CAL;
while((ADC1->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL)
;
#if defined(SEND_RSSI_DATA)
ADC2->CR2 |= ADC_CR2_CAL;
while((ADC2->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL)
;
#endif
// Trigger first conversion
ADC1->CR2 |= ADC_CR2_ADON;
#if defined(SEND_RSSI_DATA)
ADC2->CR2 |= ADC_CR2_ADON;
#endif
}
static inline void DACInit()
{
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
DAC->CR = DAC_CR_EN1;
}
static inline void TimerInit()
{
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
#if defined(EXTERNAL_OSC)
// Enable external clock, prescaler /4
TIM2->SMCR = TIM_SMCR_ECE | TIM_SMCR_ETPS_1;
#endif
// TIM2 output frequency
TIM2->PSC = 0;
#if defined(EXTERNAL_OSC)
// TimerCount = ExternalOsc
// /4 (external clock prescaler)
// /SAMP_FREQ
TIM2->ARR = (uint16_t) ((EXTERNAL_OSC/(4*SAMP_FREQ)) - 1);
#else
TIM2->ARR = (uint16_t) ((SystemCoreClock/(SAMP_FREQ)) - 1);
#endif
// Enable TIse 1%-tolerance comM2 interrupt
TIM2->DIER = TIM_DIER_UIE;
NVIC_EnableIRQ(TIM2_IRQn);
// Enable TIM2
TIM2->CR1 |= TIM_CR1_CEN;
}
void CIO::initInt()
{
GPIOInit();
ADCInit();
DACInit();
#if defined(STM32F1_POG)
FancyLEDEffect();
#endif
}
void CIO::startInt()
{
TimerInit();
BB_COSLED = 0;
BB_LED = 1;
}
void CIO::interrupt()
{
uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET;
uint16_t rawRSSI = 0U;
bitband_t eoc = (bitband_t)BITBAND_PERIPH(&ADC1->SR, ADC_SR_EOS_Pos);
bitband_t adon = (bitband_t)BITBAND_PERIPH(&ADC1->CR2, ADC_CR2_ADON_Pos);
#if defined(SEND_RSSI_DATA)
bitband_t rssi_adon = (bitband_t)BITBAND_PERIPH(&ADC2->CR2, ADC_CR2_ADON_Pos);
#endif
if (*eoc) {
// trigger next conversion
*adon = 1;
#if defined(SEND_RSSI_DATA)
*rssi_adon = 1;
#endif
m_txBuffer.get(sample, control);
DAC->DHR12R1 = sample; // Send the value to the DAC
// Read value from ADC1 and ADC2
sample = ADC1->DR; // read conversion result; EOC is cleared by this read
m_rxBuffer.put(sample, control);
#if defined(SEND_RSSI_DATA)
rawRSSI = ADC2->DR;
m_rssiBuffer.put(rawRSSI);
#endif
m_watchdog++;
}
}
bool CIO::getCOSInt()
{
return BB_COS;
}
void CIO::setLEDInt(bool on)
{
BB_LED = !!on;
}
void CIO::setPTTInt(bool on)
{
BB_PTT = !!on;
}
void CIO::setCOSInt(bool on)
{
BB_COSLED = !!on;
}
void CIO::setDStarInt(bool on)
{
BB_DSTAR = !!on;
}
void CIO::setDMRInt(bool on)
{
BB_DMR = !!on;
}
void CIO::setYSFInt(bool on)
{
BB_YSF = !!on;
}
void CIO::setP25Int(bool on)
{
BB_P25 = !!on;
}
void CIO::setNXDNInt(bool on)
{
#if defined(USE_ALTERNATE_NXDN_LEDS)
BB_YSF = !!on;
BB_P25 = !!on;
#else
BB_NXDN = !!on;
#endif
}
void CIO::setPOCSAGInt(bool on)
{
#if defined(USE_ALTERNATE_POCSAG_LEDS)
BB_DSTAR = !!on;
BB_DMR = !!on;
#else
BB_POCSAG = !!on;
#endif
}
void CIO::delayInt(unsigned int dly)
{
delay(dly);
}
#endif
+8 -33
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2018,2020,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 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
@@ -37,11 +37,9 @@
#if defined(__MK20DX256__)
#define PIN_NXDN 2
#define PIN_POCSAG 3
#define PIN_FM 4
#else
#define PIN_NXDN 24
#define PIN_POCSAG 25
#define PIN_FM 26
#endif
#define PIN_ADC 5 // A0, Pin 14
#define PIN_RSSI 4 // Teensy 3.5/3.6, A16, Pin 35. Teensy 3.1/3.2, A17, Pin 28
@@ -66,7 +64,7 @@ void CIO::initInt()
pinMode(PIN_LED, OUTPUT);
pinMode(PIN_COS, INPUT);
#if defined(MODE_LEDS)
#if defined(MODE_PINS)
// Set up the mode output pins
pinMode(PIN_DSTAR, OUTPUT);
pinMode(PIN_DMR, OUTPUT);
@@ -78,9 +76,6 @@ void CIO::initInt()
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
pinMode(PIN_POCSAG, OUTPUT);
#endif
#if !defined(USE_ALTERNATE_FM_LEDS)
pinMode(PIN_FM, OUTPUT);
#endif
#endif
}
@@ -161,14 +156,15 @@ void CIO::startInt()
void CIO::interrupt()
{
TSample sample = {DC_OFFSET, MARK_NONE};
uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET;
m_txBuffer.get(sample);
*(int16_t *)&(DAC0_DAT0L) = sample.sample;
m_txBuffer.get(sample, control);
*(int16_t *)&(DAC0_DAT0L) = sample;
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
sample.sample = ADC0_RA;
m_rxBuffer.put(sample);
sample = ADC0_RA;
m_rxBuffer.put(sample, control);
}
#if defined(SEND_RSSI_DATA)
@@ -247,30 +243,9 @@ void CIO::setPOCSAGInt(bool on)
#endif
}
void CIO::setFMInt(bool on)
{
#if defined(USE_ALTERNATE_FM_LEDS)
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
digitalWrite(PIN_YSF, on ? HIGH : LOW);
#else
digitalWrite(PIN_FM, on ? HIGH : LOW);
#endif
}
void CIO::delayInt(unsigned int dly)
{
delay(dly);
}
uint8_t CIO::getCPU() const
{
return 1U;
}
void CIO::getUDID(uint8_t* buffer)
{
::memcpy(buffer, (void *)0x4058, 16U);
}
#endif
+26 -85
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
* Copyright (C) 2016 by Colin Durbridge G4EML
*
@@ -18,7 +18,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined(STM32F4XX) || defined(STM32F7XX)
#if defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32F105xC)
#include "Config.h"
#include "Globals.h"
@@ -32,62 +32,39 @@ bool m_ysfEnable = true;
bool m_p25Enable = true;
bool m_nxdnEnable = true;
bool m_pocsagEnable = true;
bool m_fmEnable = true;
bool m_duplex = true;
bool m_tx = false;
bool m_dcd = false;
#if defined(MODE_DSTAR)
CDStarRX dstarRX;
CDStarTX dstarTX;
CDStarRX dstarRX;
CDStarTX dstarTX;
CDMRIdleRX dmrIdleRX;
CDMRRX dmrRX;
CDMRTX dmrTX;
CDMRDMORX dmrDMORX;
CDMRDMOTX dmrDMOTX;
CYSFRX ysfRX;
CYSFTX ysfTX;
CP25RX p25RX;
CP25TX p25TX;
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CPOCSAGTX pocsagTX;
CCalDStarRX calDStarRX;
CCalDStarTX calDStarTX;
#endif
#if defined(MODE_DMR)
CDMRIdleRX dmrIdleRX;
CDMRRX dmrRX;
CDMRTX dmrTX;
CDMRDMORX dmrDMORX;
CDMRDMOTX dmrDMOTX;
CCalDMR calDMR;
#endif
#if defined(MODE_YSF)
CYSFRX ysfRX;
CYSFTX ysfTX;
#endif
#if defined(MODE_P25)
CP25RX p25RX;
CP25TX p25TX;
CCalP25 calP25;
#endif
#if defined(MODE_NXDN)
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CCalNXDN calNXDN;
#endif
#if defined(MODE_POCSAG)
CPOCSAGTX pocsagTX;
CCalPOCSAG calPOCSAG;
#endif
#if defined(MODE_FM)
CFM fm;
CCalFM calFM;
#endif
CCalRSSI calRSSI;
CCalDMR calDMR;
CCalP25 calP25;
CCalNXDN calNXDN;
CCalRSSI calRSSI;
CCWIdTX cwIdTX;
@@ -106,74 +83,39 @@ void loop()
io.process();
// The following is for transmitting
#if defined(MODE_DSTAR)
if (m_dstarEnable && m_modemState == STATE_DSTAR)
dstarTX.process();
#endif
#if defined(MODE_DMR)
if (m_dmrEnable && m_modemState == STATE_DMR) {
if (m_duplex)
dmrTX.process();
else
dmrDMOTX.process();
}
#endif
#if defined(MODE_YSF)
if (m_ysfEnable && m_modemState == STATE_YSF)
ysfTX.process();
#endif
#if defined(MODE_P25)
if (m_p25Enable && m_modemState == STATE_P25)
p25TX.process();
#endif
#if defined(MODE_NXDN)
if (m_nxdnEnable && m_modemState == STATE_NXDN)
nxdnTX.process();
#endif
#if defined(MODE_POCSAG)
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
pocsagTX.process();
#endif
#if defined(MODE_FM)
if (m_fmEnable && m_modemState == STATE_FM)
fm.process();
#endif
#if defined(MODE_DSTAR)
if (m_modemState == STATE_DSTARCAL)
calDStarTX.process();
#endif
#if defined(MODE_DMR)
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
calDMR.process();
#endif
#if defined(MODE_FM)
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K || m_modemState == STATE_FMCAL30K)
calFM.process();
#endif
#if defined(MODE_P25)
if (m_modemState == STATE_P25CAL1K)
calP25.process();
#endif
#if defined(MODE_NXDN)
if (m_modemState == STATE_NXDNCAL1K)
calNXDN.process();
#endif
#if defined(MODE_POCSAG)
if (m_modemState == STATE_POCSAGCAL)
calPOCSAG.process();
#endif
if (m_modemState == STATE_IDLE)
cwIdTX.process();
@@ -188,4 +130,3 @@ int main()
}
#endif
+25 -83
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
*
* This program is free software; you can redistribute it and/or modify
@@ -29,62 +29,39 @@ bool m_ysfEnable = true;
bool m_p25Enable = true;
bool m_nxdnEnable = true;
bool m_pocsagEnable = true;
bool m_fmEnable = true;
bool m_duplex = true;
bool m_tx = false;
bool m_dcd = false;
#if defined(MODE_DSTAR)
CDStarRX dstarRX;
CDStarTX dstarTX;
CDStarRX dstarRX;
CDStarTX dstarTX;
CDMRIdleRX dmrIdleRX;
CDMRRX dmrRX;
CDMRTX dmrTX;
CDMRDMORX dmrDMORX;
CDMRDMOTX dmrDMOTX;
CYSFRX ysfRX;
CYSFTX ysfTX;
CP25RX p25RX;
CP25TX p25TX;
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CPOCSAGTX pocsagTX;
CCalDStarRX calDStarRX;
CCalDStarTX calDStarTX;
#endif
#if defined(MODE_DMR)
CDMRIdleRX dmrIdleRX;
CDMRRX dmrRX;
CDMRTX dmrTX;
CDMRDMORX dmrDMORX;
CDMRDMOTX dmrDMOTX;
CCalDMR calDMR;
#endif
#if defined(MODE_YSF)
CYSFRX ysfRX;
CYSFTX ysfTX;
#endif
#if defined(MODE_P25)
CP25RX p25RX;
CP25TX p25TX;
CCalP25 calP25;
#endif
#if defined(MODE_NXDN)
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CCalNXDN calNXDN;
#endif
#if defined(MODE_POCSAG)
CPOCSAGTX pocsagTX;
CCalPOCSAG calPOCSAG;
#endif
#if defined(MODE_FM)
CFM fm;
CCalFM calFM;
#endif
CCalRSSI calRSSI;
CCalDMR calDMR;
CCalP25 calP25;
CCalNXDN calNXDN;
CCalRSSI calRSSI;
CCWIdTX cwIdTX;
@@ -103,74 +80,39 @@ void loop()
io.process();
// The following is for transmitting
#if defined(MODE_DSTAR)
if (m_dstarEnable && m_modemState == STATE_DSTAR)
dstarTX.process();
#endif
#if defined(MODE_DMR)
if (m_dmrEnable && m_modemState == STATE_DMR) {
if (m_duplex)
dmrTX.process();
else
dmrDMOTX.process();
}
#endif
#if defined(MODE_YSF)
if (m_ysfEnable && m_modemState == STATE_YSF)
ysfTX.process();
#endif
#if defined(MODE_P25)
if (m_p25Enable && m_modemState == STATE_P25)
p25TX.process();
#endif
#if defined(MODE_NXDN)
if (m_nxdnEnable && m_modemState == STATE_NXDN)
nxdnTX.process();
#endif
#if defined(MODE_POCSAG)
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
pocsagTX.process();
#endif
#if defined(MODE_FM)
if (m_fmEnable && m_modemState == STATE_FM)
fm.process();
#endif
#if defined(MODE_DSTAR)
if (m_modemState == STATE_DSTARCAL)
calDStarTX.process();
#endif
#if defined(MODE_DMR)
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
calDMR.process();
#endif
#if defined(MODE_FM)
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K || m_modemState == STATE_FMCAL30K)
calFM.process();
#endif
#if defined(MODE_P25)
if (m_modemState == STATE_P25CAL1K)
calP25.process();
#endif
#if defined(MODE_NXDN)
if (m_modemState == STATE_NXDNCAL1K)
calNXDN.process();
#endif
#if defined(MODE_POCSAG)
if (m_modemState == STATE_POCSAGCAL)
calPOCSAG.process();
#endif
if (m_modemState == STATE_IDLE)
cwIdTX.process();
+338
View File
@@ -0,0 +1,338 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Project version="2G - 1.7.8" name="MMDVM_STM32F4xx">
<Target name="MMDVM_Discovery_407" isCurrent="1">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="STM32F40_41xxx"/>
<Define name="HSE_VALUE=8000000"/>
<Define name="STM32F4_DISCOVERY"/>
<Define name="__FPU_USED"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_DIS"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Target name="MMDVM_Pi_446" isCurrent="0">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="__FPU_USED"/>
<Define name="STM32F446xx"/>
<Define name="HSE_VALUE=12000000"/>
<Define name="STM32F4_PI"/>
<Define name="MODE_PINS"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_PI"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Target name="MMDVM_Nucleo_446" isCurrent="0">
<Device manufacturerId="9" manufacturerName="ST" chipId="344" chipName="STM32F407VG" boardId="" boardName=""/>
<BuildOption>
<Compile>
<Option name="OptimizationLevel" value="4"/>
<Option name="UseFPU" value="0"/>
<Option name="UserEditCompiler" value=""/>
<Option name="SupportCPlusplus" value="1"/>
<Option name="FPU" value="2"/>
<Includepaths>
<Includepath path="."/>
</Includepaths>
<DefinedSymbols>
<Define name="STM32F4XX"/>
<Define name="USE_STDPERIPH_DRIVER"/>
<Define name="__ASSEMBLY__"/>
<Define name="SUPPORT_CPLUSPLUS"/>
<Define name="HSE_VALUE=8000000"/>
<Define name="__FPU_USED"/>
<Define name="STM32F4_NUCLEO"/>
<Define name="STM32F446xx"/>
</DefinedSymbols>
</Compile>
<Link useDefault="0">
<Option name="DiscardUnusedSection" value="0"/>
<Option name="UserEditLinkder" value=""/>
<Option name="UseMemoryLayout" value="0"/>
<Option name="nostartfiles" value="1"/>
<Option name="LTO" value="0"/>
<Option name="IsNewStartupCode" value="1"/>
<Option name="Library" value="Semihosting"/>
<Option name="UserEditLinker" value="-lstdc++; --specs=nano.specs;"/>
<LinkedLibraries>
<Libset dir="stm32f4xx_lib\cmsis\lib\gcc\" libs="arm_cortexm4lf_math"/>
</LinkedLibraries>
<MemoryAreas debugInFlashNotRAM="1">
<Memory name="IROM1" type="ReadOnly" size="0x00100000" startValue="0x08000000"/>
<Memory name="IRAM1" type="ReadWrite" size="0x00020000" startValue="0x20000000"/>
<Memory name="IROM2" type="ReadOnly" size="" startValue=""/>
<Memory name="IRAM2" type="ReadWrite" size="0x00010000" startValue="0x10000000"/>
</MemoryAreas>
<LocateLinkFile path="./stm32f4xx_link.ld" type="0"/>
</Link>
<Output>
<Option name="OutputFileType" value="0"/>
<Option name="Path" value="./"/>
<Option name="Name" value="MMDVM_NUCLEO"/>
<Option name="HEX" value="1"/>
<Option name="BIN" value="1"/>
</Output>
<User>
<UserRun name="Run#1" type="Before" checked="0" value=""/>
<UserRun name="Run#1" type="After" checked="0" value=""/>
</User>
</BuildOption>
<DebugOption>
<Option name="org.coocox.codebugger.gdbjtag.core.adapter" value="ST-Link"/>
<Option name="org.coocox.codebugger.gdbjtag.core.debugMode" value="SWD"/>
<Option name="org.coocox.codebugger.gdbjtag.core.clockDiv" value="1M"/>
<Option name="org.coocox.codebugger.gdbjtag.corerunToMain" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkgdbserver" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.userDefineGDBScript" value=""/>
<Option name="org.coocox.codebugger.gdbjtag.core.targetEndianess" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.jlinkResetMode" value="Type 0: Normal"/>
<Option name="org.coocox.codebugger.gdbjtag.core.resetMode" value="SYSRESETREQ"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifSemihost" value="0"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ifCacheRom" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.ipAddress" value="127.0.0.1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.portNumber" value="2009"/>
<Option name="org.coocox.codebugger.gdbjtag.core.autoDownload" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.verify" value="1"/>
<Option name="org.coocox.codebugger.gdbjtag.core.downloadFuction" value="Erase Effected"/>
<Option name="org.coocox.codebugger.gdbjtag.core.defaultAlgorithm" value="STM32F4xx_1024.elf"/>
</DebugOption>
<ExcludeFile/>
</Target>
<Components path="./">
</Components>
<Files>
<File name="DMRIdleRX.h" path="DMRIdleRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_dac.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_dac.c" type="1"/>
<File name="DMRDMOTX.cpp" path="DMRDMOTX.cpp" type="1"/>
<File name="DMRRX.cpp" path="DMRRX.cpp" type="1"/>
<File name="YSFRX.cpp" path="YSFRX.cpp" type="1"/>
<File name="CalRSSI.cpp" path="CalRSSI.cpp" type="1"/>
<File name="STM32F4XX_Lib/Device/stm32f4xx.h" path="STM32F4XX_Lib/Device/stm32f4xx.h" type="1"/>
<File name="SampleRB.cpp" path="SampleRB.cpp" type="1"/>
<File name="CalDStarTX.h" path="CalDStarTX.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cm4.h" path="STM32F4XX_Lib/CMSIS/Include/core_cm4.h" type="1"/>
<File name="DMRSlotRX.h" path="DMRSlotRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_tim.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_tim.c" type="1"/>
<File name="YSFRX.h" path="YSFRX.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include" path="" type="2"/>
<File name="IO.cpp" path="IO.cpp" type="1"/>
<File name="DMRDMORX.cpp" path="DMRDMORX.cpp" type="1"/>
<File name="P25RX.h" path="P25RX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/misc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/misc.c" type="1"/>
<File name="STM32F4XX_Lib/CMSIS" path="" type="2"/>
<File name="SerialArduino.cpp" path="SerialArduino.cpp" type="1"/>
<File name="SerialPort.cpp" path="SerialPort.cpp" type="1"/>
<File name="STM32F4XX_Lib/Device/stm32f4xx_conf.h" path="STM32F4XX_Lib/Device/stm32f4xx_conf.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_adc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_adc.c" type="1"/>
<File name="DStarTX.cpp" path="DStarTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_usart.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_usart.c" type="1"/>
<File name="SampleRB.h" path="SampleRB.h" type="1"/>
<File name="YSFTX.h" path="YSFTX.h" type="1"/>
<File name="DMRRX.h" path="DMRRX.h" type="1"/>
<File name="CalRSSI.h" path="CalRSSI.h" type="1"/>
<File name="IOTeensy.cpp" path="IOTeensy.cpp" type="1"/>
<File name="MMDVM.cpp" path="MMDVM.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmSimd.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmSimd.h" type="1"/>
<File name="DMRDMORX.h" path="DMRDMORX.h" type="1"/>
<File name="SerialPort.h" path="SerialPort.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_dac.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_dac.h" type="1"/>
<File name="CWIdTX.h" path="CWIdTX.h" type="1"/>
<File name="STM32F4XX_Lib/Device/system_stm32f4xx.h" path="STM32F4XX_Lib/Device/system_stm32f4xx.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmFunc.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmFunc.h" type="1"/>
<File name="CalDStarTX.cpp" path="CalDStarTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source" path="" type="2"/>
<File name="CalDMR.h" path="CalDMR.h" type="1"/>
<File name="DMRDMOTX.h" path="DMRDMOTX.h" type="1"/>
<File name="IODue.cpp" path="IODue.cpp" type="1"/>
<File name="DMRTX.cpp" path="DMRTX.cpp" type="1"/>
<File name="P25RX.cpp" path="P25RX.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/GCC" path="" type="2"/>
<File name="STM32F4XX_Lib" path="" type="2"/>
<File name="STM32F4XX_Lib/CMSIS/Include/core_cmInstr.h" path="STM32F4XX_Lib/CMSIS/Include/core_cmInstr.h" type="1"/>
<File name="DMRTX.h" path="DMRTX.h" type="1"/>
<File name="STM32F4XX_Lib/Device/system_stm32f4xx.c" path="STM32F4XX_Lib/Device/system_stm32f4xx.c" type="1"/>
<File name="RSSIRB.h" path="RSSIRB.h" type="1"/>
<File name="STM32F4XX_Lib/Device/startup/startup_stm32f4xx.c" path="STM32F4XX_Lib/Device/startup/startup_stm32f4xx.c" type="1"/>
<File name="STM32F4XX_Lib/Device/startup" path="" type="2"/>
<File name="SerialRB.h" path="SerialRB.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_gpio.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_gpio.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver" path="" type="2"/>
<File name="DMRDefines.h" path="DMRDefines.h" type="1"/>
<File name="CalDMR.cpp" path="CalDMR.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_adc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_adc.h" type="1"/>
<File name="SerialSTM.cpp" path="SerialSTM.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a" path="STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a" type="1"/>
<File name="DStarDefines.h" path="DStarDefines.h" type="1"/>
<File name="DStarRX.h" path="DStarRX.h" type="1"/>
<File name="Config.h" path="Config.h" type="1"/>
<File name="DMRSlotType.cpp" path="DMRSlotType.cpp" type="1"/>
<File name="Globals.h" path="Globals.h" type="1"/>
<File name="STM32F4XX_Lib/Device" path="" type="2"/>
<File name="CalDStarRX.cpp" path="CalDStarRX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_tim.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_tim.h" type="1"/>
<File name="CalDStarRX.h" path="CalDStarRX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include" path="" type="2"/>
<File name="IO.h" path="IO.h" type="1"/>
<File name="Utils.cpp" path="Utils.cpp" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/.DS_Store" path="STM32F4XX_Lib/CMSIS/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib/.DS_Store" path="STM32F4XX_Lib/CMSIS/Lib/.DS_Store" type="1"/>
<File name="Utils.h" path="Utils.h" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Lib" path="" type="2"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/.DS_Store" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/.DS_Store" path="STM32F4XX_Lib/CMSIS/Include/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/CMSIS/Include/arm_math.h" path="STM32F4XX_Lib/CMSIS/Include/arm_math.h" type="1"/>
<File name="YSFDefines.h" path="YSFDefines.h" type="1"/>
<File name="DStarTX.h" path="DStarTX.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_rcc.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_rcc.c" type="1"/>
<File name="STM32F4XX_Lib/Device/.DS_Store" path="STM32F4XX_Lib/Device/.DS_Store" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_rcc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_rcc.h" type="1"/>
<File name="P25Defines.h" path="P25Defines.h" type="1"/>
<File name="DMRSlotType.h" path="DMRSlotType.h" type="1"/>
<File name="Debug.h" path="Debug.h" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/misc.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/misc.h" type="1"/>
<File name="P25TX.h" path="P25TX.h" type="1"/>
<File name="RSSIRB.cpp" path="RSSIRB.cpp" type="1"/>
<File name="DStarRX.cpp" path="DStarRX.cpp" type="1"/>
<File name="DMRSlotRX.cpp" path="DMRSlotRX.cpp" type="1"/>
<File name="IOSTM.cpp" path="IOSTM.cpp" type="1"/>
<File name="P25TX.cpp" path="P25TX.cpp" type="1"/>
<File name="SerialRB.cpp" path="SerialRB.cpp" type="1"/>
<File name="CWIdTX.cpp" path="CWIdTX.cpp" type="1"/>
<File name="DMRIdleRX.cpp" path="DMRIdleRX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_usart.h" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/stm32f4xx_usart.h" type="1"/>
<File name="STM32F4XX_Lib/.DS_Store" path="STM32F4XX_Lib/.DS_Store" type="1"/>
<File name="YSFTX.cpp" path="YSFTX.cpp" type="1"/>
<File name="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_gpio.c" path="STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/source/stm32f4xx_gpio.c" type="1"/>
</Files>
</Project>
Binary file not shown.
+25 -76
View File
@@ -25,7 +25,6 @@ F7_LIB_PATH=./STM32F7XX_Lib
# MCU external clock frequency (Hz)
CLK_MMDVM_PI=12000000
CLK_NUCLEO=8000000
CLK_12MHZ=12000000
# Directory Structure
BINDIR=bin
@@ -94,8 +93,6 @@ ifndef $(OSC)
OSC=$(CLK_MMDVM_PI)
else ifeq ($(MAKECMDGOALS),pi-f722)
OSC=$(CLK_MMDVM_PI)
else ifeq ($(MAKECMDGOALS),drcc_nqf)
OSC=$(CLK_12MHZ)
else
OSC=$(CLK_NUCLEO)
endif
@@ -131,21 +128,10 @@ DEFS_NUCLEO_F767=-DUSE_HAL_DRIVER -DSTM32F767xx -DSTM32F7XX -DSTM32F7_NUCLEO -DH
DEFS_PI_F722=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_PI -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# MMDVM-F7M F0DEI board:
DEFS_F7M=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_F7M -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# MMDVM_RPT_Hat F0DEI, DB9MAT, DF2ET board:
DEFS_RPT_HAT=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_RPT_HAT -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# RB STM32F4_DVM board:
# MMDVM-F7-Hat F0DEI, DB9MAT, DF2ET board:
DEFS_F7HAT=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_F7HAT -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# STM32F4 DVM board:
DEFS_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# RB STM32F7 DVM board:
DEFS_DVM722=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F7_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# MMDVM_RPT_Hat BG4TGO, BG5HHP board:
DEFS_RPT_HAT_TGO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_RPT_HAT_TGO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# DRCC_DVM BG7NQF board:
DEFS_DRCC_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DDRCC_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# WA0EDA F405 MTR2K, MASTR3 board:
DEFS_EDA_405=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_EDA_405 -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# WA0EDA F446 MTR2K, MASTR3 board:
DEFS_EDA_446=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_EDA_446 -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# Build compiler flags
CFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
@@ -161,10 +147,10 @@ LDFLAGS_F722 =-T stm32f722_link.ld $(MCFLAGS_F7) --specs=nosys.specs $(INCLUDES_
# Common flags
CFLAGS=-Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
CXXFLAGS=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
LDFLAGS=-Os --specs=nano.specs -Wl,-Map=bin/mmdvm.map
LDFLAGS=-Os --specs=nano.specs
# Build Rules
.PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm drcc_nqf clean
.PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm clean
# Default target: Nucleo-64 F446RE board
all: nucleo
@@ -193,17 +179,11 @@ f7m: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_F7M)
f7m: LDFLAGS+=$(LDFLAGS_F722)
f7m: release_f7
rpt_hat: GitVersion.h
rpt_hat: CFLAGS+=$(CFLAGS_F7) $(DEFS_RPT_HAT)
rpt_hat: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_RPT_HAT)
rpt_hat: LDFLAGS+=$(LDFLAGS_F722)
rpt_hat: release_f7
rpt_hat_tgo: GitVersion.h
rpt_hat_tgo: CFLAGS+=$(CFLAGS_F4) $(DEFS_RPT_HAT_TGO)
rpt_hat_tgo: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_RPT_HAT_TGO)
rpt_hat_tgo: LDFLAGS+=$(LDFLAGS_F4)
rpt_hat_tgo: release_f4
f7hat: GitVersion.h
f7hat: CFLAGS+=$(CFLAGS_F7) $(DEFS_F7HAT)
f7hat: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_F7HAT)
f7hat: LDFLAGS+=$(LDFLAGS_F722)
f7hat: release_f7
nucleo: GitVersion.h
nucleo: CFLAGS+=$(CFLAGS_F4) $(DEFS_NUCLEO)
@@ -224,41 +204,11 @@ f767: LDFLAGS+=$(LDFLAGS_F767)
f767: release_f7
dvm: GitVersion.h
dvm: CFLAGS+=$(CFLAGS_F4) $(DEFS_DVM) -DDRCC_DVM_446
dvm: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DVM) -DDRCC_DVM_446
dvm: CFLAGS+=$(CFLAGS_F4) $(DEFS_DVM)
dvm: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DVM)
dvm: LDFLAGS+=$(LDFLAGS_F4)
dvm: release_f4
dvm722: GitVersion.h
dvm722: CFLAGS+=$(CFLAGS_F7) $(DEFS_DVM722) -DDRCC_DVM_722
dvm722: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_DVM722) -DDRCC_DVM_722
dvm722: LDFLAGS+=$(LDFLAGS_F722)
dvm722: release_f7
drcc_nqf: GitVersion.h
drcc_nqf: CFLAGS+=$(CFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_NQF
drcc_nqf: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_NQF
drcc_nqf: LDFLAGS+=$(LDFLAGS_F4)
drcc_nqf: release_f4
hhp446: GitVersion.h
hhp446: CFLAGS+=$(CFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_HHP446
hhp446: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_HHP446
hhp446: LDFLAGS+=$(LDFLAGS_F4)
hhp446: release_f4
eda405: GitVersion.h
eda405: CFLAGS+=$(CFLAGS_F4) $(DEFS_EDA_405)
eda405: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_EDA_405)
eda405: LDFLAGS+=$(LDFLAGS_F4)
eda405: release_f4
eda446: GitVersion.h
eda446: CFLAGS+=$(CFLAGS_F4) $(DEFS_EDA_446)
eda446: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_EDA_446)
eda446: LDFLAGS+=$(LDFLAGS_F4)
eda446: release_f4
release_f4: $(BINDIR)
release_f4: $(OBJDIR_F4)
release_f4: $(BINDIR)/$(BINHEX_F4)
@@ -281,7 +231,7 @@ $(OBJDIR_F7):
$(BINDIR)/$(BINHEX_F4): $(BINDIR)/$(BINELF_F4)
$(CP) -O ihex $< $@
@echo "Objcopy from ELF to IHEX complete!\n"
$(BINDIR)/$(BINBIN_F4): $(BINDIR)/$(BINELF_F4)
$(CP) -O binary $< $@
@echo "Objcopy from ELF to BINARY complete!\n"
@@ -294,7 +244,7 @@ $(BINDIR)/$(BINELF_F4): $(OBJ_F4)
$(BINDIR)/$(BINHEX_F7): $(BINDIR)/$(BINELF_F7)
$(CP) -O ihex $< $@
@echo "Objcopy from ELF to IHEX complete!\n"
$(BINDIR)/$(BINBIN_F7): $(BINDIR)/$(BINELF_F7)
$(CP) -O binary $< $@
@echo "Objcopy from ELF to BINARY complete!\n"
@@ -368,31 +318,34 @@ endif
deploy-pi:
ifneq ($(wildcard /usr/local/bin/stm32flash),)
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R /dev/ttyAMA0
-/usr/local/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F4)
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R -c /dev/ttyAMA0
endif
ifneq ($(wildcard /usr/bin/stm32flash),)
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
/usr/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R /dev/ttyAMA0
-/usr/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F4)
/usr/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R -c /dev/ttyAMA0
endif
deploy-f4m: deploy-pi
deploy-dvm: deploy-pi
deploy-eda405: deploy-pi
deploy-eda446: deploy-pi
deploy-pi-f7:
ifneq ($(wildcard /usr/local/bin/stm32flash),)
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R /dev/ttyAMA0
-/usr/local/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F7)
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
endif
else ifneq ($(wildcard /usr/bin/stm32flash),)
ifneq ($(wildcard /usr/bin/stm32flash),)
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
/usr/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R /dev/ttyAMA0
-/usr/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F7)
/usr/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
endif
deploy-f7m: deploy-pi-f7
deploy-rpt_hat: deploy-pi-f7
deploy-f7hat: deploy-pi-f7
# Export the current git version if the index file exists, else 000...
GitVersion.h:
@@ -407,7 +360,3 @@ else
echo "#define GITVERSION \"0000000\"" > $@
endif
endif
flash_f4:
@echo "flashing firmware..."
st-flash write bin/$(BINBIN_F4) 0x8000000
+2 -2
View File
@@ -1,5 +1,5 @@
#!/usr/bin/make
# makefile for the arduino due (works with arduino IDE 1.6.12)
# makefile for the arduino due (works with arduino IDE 1.6.11)
#
# The original file can be found at https://github.com/pauldreik/arduino-due-makefile
#
@@ -34,7 +34,7 @@ OBJCOPY:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-n
C:=$(CC)
#SAM:=arduino/sam/
SAM:=$(ADIR)/packages/arduino/hardware/sam/1.6.12
SAM:=$(ADIR)/packages/arduino/hardware/sam/1.6.11
#CMSIS:=arduino/sam/system/CMSIS/
#LIBSAM:=arduino/sam/system/libsam
TMPDIR:=$(PWD)/build
+151
View File
@@ -0,0 +1,151 @@
# The name for the project
TARGET:=mmdvm
# The CPU architecture (will be used for -mcpu)
MCPU:=cortex-m3
MCU:=STM32F105xC
# The source files of the project
CSRC:=
CXXSRC:=$(wildcard *.cpp)
# Include directory for the system include files and system source file
SYSDIR:=system_stm32f1xx
SYSSRC:=$(SYSDIR)/system_stm32f1xx.c
# Other include directories
INCDIR:=
# Definitions
CDEFS:=
CXXDEFS:=
# The name of the startup file which matches to the architecture (MCPU)
STARTUP:=$(SYSDIR)/startup_stm32f105xc.S
STARTUP_DEFS=
# Include directory for CMSIS
CMSISDIR:=/opt/STM32Cube_FW_F1_V1.4.0/Drivers/CMSIS
# Libraries
LIBDIR:=
LIBS:=-larm_cortexM3l_math
# Name of the linker script
LDSCRIPT:=$(SYSDIR)/gcc.ld
# Target objects and binaries directory
OBJDIR:=obj
BINDIR:=bin
# Port definition for programming via bootloader (using stm32flash)
BL_PORT:=ttyUSB0
# Internal Variables
ELF:=$(BINDIR)/$(TARGET).elf
HEX:=$(BINDIR)/$(TARGET).hex
DIS:=$(BINDIR)/$(TARGET).dis
MAP:=$(BINDIR)/$(TARGET).map
OBJ:=$(CSRC:%.c=$(OBJDIR)/%.o) $(CXXSRC:%.cpp=$(OBJDIR)/%.o)
OBJ+=$(SYSSRC:$(SYSDIR)/%.c=$(OBJDIR)/%.o) $(STARTUP:$(SYSDIR)/%.S=$(OBJDIR)/%.o)
# Replace standard build tools by arm tools
CC:=arm-none-eabi-gcc
CXX:=arm-none-eabi-g++
AS:=arm-none-eabi-gcc
LD:=arm-none-eabi-g++
OBJCOPY:=arm-none-eabi-objcopy
OBJDUMP:=arm-none-eabi-objdump
SIZE:=arm-none-eabi-size
# Common flags
COMMON_FLAGS =-mthumb -mlittle-endian -mcpu=$(MCPU)
COMMON_FLAGS+= -Wall
COMMON_FLAGS+= -I. -I$(CMSISDIR)/Include -I$(CMSISDIR)/Device/ST/STM32F1xx/Include -I$(SYSDIR)
COMMON_FLAGS+= $(addprefix -I,$(INCDIR))
COMMON_FLAGS+= -D$(MCU)
COMMON_FLAGS+= -Os -flto -ffunction-sections -fdata-sections
COMMON_FLAGS+= -g
# Assembler flags
ASFLAGS:=$(COMMON_FLAGS)
# C flags
CFLAGS:=$(COMMON_FLAGS) $(addprefix -D,$(CDEFS))
CFLAGS+= -std=gnu11 -nostdlib
# CXX flags
CXXFLAGS:=$(COMMON_FLAGS) $(addprefix -D,$(CXXDEFS))
CXXFLAGS+= -nostdlib -fno-exceptions -fno-rtti
# LD flags
LDFLAGS:=$(COMMON_FLAGS) -Wl,--gc-sections -Wl,-Map=$(MAP) -Wl,--no-wchar-size-warning
LDFLAGS+= --specs=nosys.specs --specs=nano.specs
LDFLAGS+= -L$(CMSISDIR)/Lib/GCC/ $(addprefix -L,$(LIBDIR))
LDLIBS:=-T$(LDSCRIPT) $(LIBS)
# Dependecies
DEPENDS:=$(CSRC:%.c=$(OBJDIR)/%.d) $(CXXSRC:%.cpp=$(OBJDIR)/%.d)
# Additional Suffixes
.SUFFIXES: .elf .hex
# Targets
.PHONY: all
all: $(DIS) $(HEX)
$(SIZE) $(ELF)
.PHONY: program
program: $(HEX) $(ELF)
openocd -f openocd.cfg \
-c "program $(HEX) verify reset exit"
$(SIZE) $(ELF)
.PHONY: program_bl
program_bl: $(HEX) $(ELF)
stm32flash -w $(HEX) -v /dev/$(BL_PORT)
$(SIZE) $(ELF)
.PHONY: run
run: $(HEX) $(ELF)
openocd -f openocd.cfg \
-c "init" -c "reset" -c "exit"
.PHONY: debug
debug: $(ELF)
./debug.sh $(ELF)
.PHONY: clean
clean:
$(RM) $(OBJ) $(HEX) $(ELF) $(DIS) $(MAP) $(DEPENDS)
# implicit rules
.elf.hex:
$(OBJCOPY) -O ihex $< $@
$(OBJDIR)/%.o: %.c
$(CC) -MMD $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o: %.cpp
$(CXX) -MMD $(CXXFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(SYSDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o: $(SYSDIR)/%.S
$(AS) $(ASFLAGS) -c $< -o $@
# explicit rules
$(OBJDIR):
mkdir -p $(OBJDIR)
$(BINDIR):
mkdir -p $(BINDIR)
$(ELF): $(OBJDIR) $(BINDIR) $(OBJ)
$(LD) $(OBJ) $(LDFLAGS) $(LDLIBS) -o $@
$(DIS): $(ELF)
$(OBJDUMP) -S $< > $@
# include dependecies
-include $(DEPENDS)
+1 -6
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2018 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_NXDN)
#include "Globals.h"
#include "NXDNRX.h"
#include "Utils.h"
@@ -406,5 +403,3 @@ void CNXDNRX::writeRSSIData(uint8_t* data)
m_rssiCount = 0U;
}
#endif
+2 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 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
@@ -16,13 +16,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_NXDN)
#if !defined(NXDNRX_H)
#define NXDNRX_H
#include "Config.h"
#include "NXDNDefines.h"
enum NXDNRX_STATE {
@@ -70,5 +67,3 @@ private:
#endif
#endif
+9 -47
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
@@ -18,9 +18,6 @@
*/
#include "Config.h"
#if defined(MODE_NXDN)
#include "Globals.h"
#include "NXDNTX.h"
@@ -48,7 +45,7 @@ const uint8_t NXDN_PREAMBLE[] = {0x57U, 0x75U, 0xFDU};
const uint8_t NXDN_SYNC = 0x5FU;
CNXDNTX::CNXDNTX() :
m_buffer(TX_BUFFER_LEN),
m_buffer(4000U),
m_modFilter(),
m_sincFilter(),
m_modState(),
@@ -56,9 +53,7 @@ m_sincState(),
m_poBuffer(),
m_poLen(0U),
m_poPtr(0U),
m_txDelay(240U), // 200ms
m_txHang(3000U), // 5s
m_txCount(0U)
m_txDelay(240U) // 200ms
{
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
::memset(m_sincState, 0x00U, 70U * sizeof(q15_t));
@@ -75,7 +70,10 @@ m_txCount(0U)
void CNXDNTX::process()
{
if (m_poLen == 0U && m_buffer.getData() > 0U) {
if (m_buffer.getData() == 0U && m_poLen == 0U)
return;
if (m_poLen == 0U) {
if (!m_tx) {
for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = NXDN_SYNC;
@@ -84,8 +82,7 @@ void CNXDNTX::process()
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[2U];
} else {
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++) {
uint8_t c = 0U;
m_buffer.get(c);
uint8_t c = m_buffer.get();
m_poBuffer[m_poLen++] = c;
}
}
@@ -101,8 +98,6 @@ void CNXDNTX::process()
writeByte(c);
space -= 4U * NXDN_RADIO_SYMBOL_LENGTH;
if (m_duplex)
m_txCount = m_txHang;
if (m_poPtr >= m_poLen) {
m_poPtr = 0U;
@@ -110,23 +105,10 @@ void CNXDNTX::process()
return;
}
}
} else if (m_txCount > 0U) {
// Transmit silence until the hang timer has expired.
uint16_t space = io.getSpace();
while (space > (4U * NXDN_RADIO_SYMBOL_LENGTH)) {
writeSilence();
space -= 4U * NXDN_RADIO_SYMBOL_LENGTH;
m_txCount--;
if (m_txCount == 0U)
return;
}
}
}
uint8_t CNXDNTX::writeData(const uint8_t* data, uint16_t length)
uint8_t CNXDNTX::writeData(const uint8_t* data, uint8_t length)
{
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -173,19 +155,6 @@ void CNXDNTX::writeByte(uint8_t c)
io.write(STATE_NXDN, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
}
void CNXDNTX::writeSilence()
{
q15_t inBuffer[4U] = {0, 0, 0, 0};
q15_t intBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
q15_t outBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, intBuffer, 4U);
::arm_fir_fast_q15(&m_sincFilter, intBuffer, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
io.write(STATE_NXDN, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
}
void CNXDNTX::setTXDelay(uint8_t delay)
{
m_txDelay = 300U + uint16_t(delay) * 6U; // 500ms + tx delay
@@ -199,10 +168,3 @@ uint8_t CNXDNTX::getSpace() const
return m_buffer.getSpace() / NXDN_FRAME_LENGTH_BYTES;
}
void CNXDNTX::setParams(uint8_t txHang)
{
m_txHang = txHang * 600U;
}
#endif
+6 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 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
@@ -16,20 +16,18 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_NXDN)
#if !defined(NXDNTX_H)
#define NXDNTX_H
#include "RingBuffer.h"
#include "Config.h"
#include "SerialRB.h"
class CNXDNTX {
public:
CNXDNTX();
uint8_t writeData(const uint8_t* data, uint16_t length);
uint8_t writeData(const uint8_t* data, uint8_t length);
void process();
@@ -37,10 +35,8 @@ public:
uint8_t getSpace() const;
void setParams(uint8_t txHang);
private:
CRingBuffer<uint8_t> m_buffer;
CSerialRB m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter;
arm_fir_instance_q15 m_sincFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
@@ -49,14 +45,9 @@ private:
uint16_t m_poLen;
uint16_t m_poPtr;
uint16_t m_txDelay;
uint32_t m_txHang;
uint32_t m_txCount;
void writeByte(uint8_t c);
void writeSilence();
};
#endif
#endif
-5
View File
@@ -47,11 +47,6 @@ const unsigned int P25_TSDU_FRAME_LENGTH_BITS = P25_TSDU_FRAME_LENGTH_BYTES
const unsigned int P25_TSDU_FRAME_LENGTH_SYMBOLS = P25_TSDU_FRAME_LENGTH_BYTES * 4U;
const unsigned int P25_TSDU_FRAME_LENGTH_SAMPLES = P25_TSDU_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH;
const unsigned int P25_PDU_HDR_FRAME_LENGTH_BYTES = 45U;
const unsigned int P25_PDU_HDR_FRAME_LENGTH_BITS = P25_PDU_HDR_FRAME_LENGTH_BYTES * 8U;
const unsigned int P25_PDU_HDR_FRAME_LENGTH_SYMBOLS = P25_PDU_HDR_FRAME_LENGTH_BYTES * 4U;
const unsigned int P25_PDU_HDR_FRAME_LENGTH_SAMPLES = P25_PDU_HDR_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH;
const unsigned int P25_SYNC_LENGTH_BYTES = 6U;
const unsigned int P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U;
const unsigned int P25_SYNC_LENGTH_SYMBOLS = P25_SYNC_LENGTH_BYTES * 4U;
+2 -20
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Bryan Biedenkapp <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
@@ -18,9 +18,6 @@
*/
#include "Config.h"
#if defined(MODE_P25)
#include "Globals.h"
#include "P25RX.h"
#include "Utils.h"
@@ -202,19 +199,7 @@ void CP25RX::processHdr(q15_t sample)
serial.writeP25Hdr(frame, P25_HDR_FRAME_LENGTH_BYTES + 1U);
}
break;
case P25_DUID_PDU: {
calculateLevels(m_hdrSyncPtr, P25_PDU_HDR_FRAME_LENGTH_SYMBOLS);
DEBUG4("P25RX: sync found in PDU pos/centre/threshold", m_hdrSyncPtr, m_centreVal, m_thresholdVal);
uint8_t frame[P25_PDU_HDR_FRAME_LENGTH_BYTES + 1U];
samplesToBits(m_hdrSyncPtr, P25_PDU_HDR_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centreVal, m_thresholdVal);
frame[0U] = 0x01U;
serial.writeP25Hdr(frame, P25_PDU_HDR_FRAME_LENGTH_BYTES + 1U);
}
break;
case P25_DUID_TSDU: {
case P25_DUID_TSDU: {
calculateLevels(m_hdrStartPtr, P25_TSDU_FRAME_LENGTH_SYMBOLS);
DEBUG4("P25RX: sync found in TSDU pos/centre/threshold", m_hdrSyncPtr, m_centreVal, m_thresholdVal);
@@ -538,6 +523,3 @@ void CP25RX::writeRSSILdu(uint8_t* ldu)
m_rssiAccum = 0U;
m_rssiCount = 0U;
}
#endif
+2 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Bryan Biedenkapp <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,13 +17,10 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_P25)
#if !defined(P25RX_H)
#define P25RX_H
#include "Config.h"
#include "P25Defines.h"
enum P25RX_STATE {
@@ -75,6 +72,3 @@ private:
};
#endif
#endif
+11 -51
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
@@ -18,9 +18,6 @@
*/
#include "Config.h"
#if defined(MODE_P25)
#include "Globals.h"
#include "P25TX.h"
@@ -46,7 +43,7 @@ const q15_t P25_LEVELD = -1260;
const uint8_t P25_START_SYNC = 0x77U;
CP25TX::CP25TX() :
m_buffer(TX_BUFFER_LEN),
m_buffer(4000U),
m_modFilter(),
m_lpFilter(),
m_modState(),
@@ -54,9 +51,7 @@ m_lpState(),
m_poBuffer(),
m_poLen(0U),
m_poPtr(0U),
m_txDelay(240U), // 200ms
m_txHang(6000U), // 5s
m_txCount(0U)
m_txDelay(240U) // 200ms
{
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
::memset(m_lpState, 0x00U, 60U * sizeof(q15_t));
@@ -73,16 +68,17 @@ m_txCount(0U)
void CP25TX::process()
{
if (m_poLen == 0U && m_buffer.getData() > 0U) {
if (m_buffer.getData() == 0U && m_poLen == 0U)
return;
if (m_poLen == 0U) {
if (!m_tx) {
for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = P25_START_SYNC;
} else {
uint8_t length;
m_buffer.get(length);
uint8_t length = m_buffer.get();
for (uint8_t i = 0U; i < length; i++) {
uint8_t c = 0U;
m_buffer.get(c);
uint8_t c = m_buffer.get();
m_poBuffer[m_poLen++] = c;
}
}
@@ -98,32 +94,17 @@ void CP25TX::process()
writeByte(c);
space -= 4U * P25_RADIO_SYMBOL_LENGTH;
if (m_duplex)
m_txCount = m_txHang;
if (m_poPtr >= m_poLen) {
m_poPtr = 0U;
m_poLen = 0U;
return;
}
}
} else if (m_txCount > 0U) {
// Transmit silence until the hang timer has expired.
uint16_t space = io.getSpace();
while (space > (4U * P25_RADIO_SYMBOL_LENGTH)) {
writeSilence();
space -= 4U * P25_RADIO_SYMBOL_LENGTH;
m_txCount--;
if (m_txCount == 0U)
return;
}
}
}
uint8_t CP25TX::writeData(const uint8_t* data, uint16_t length)
uint8_t CP25TX::writeData(const uint8_t* data, uint8_t length)
{
if (length < (P25_TERM_FRAME_LENGTH_BYTES + 1U))
return 4U;
@@ -171,19 +152,6 @@ void CP25TX::writeByte(uint8_t c)
io.write(STATE_P25, outBuffer, P25_RADIO_SYMBOL_LENGTH * 4U);
}
void CP25TX::writeSilence()
{
q15_t inBuffer[4U] = {0, 0, 0, 0};
q15_t intBuffer[P25_RADIO_SYMBOL_LENGTH * 4U];
q15_t outBuffer[P25_RADIO_SYMBOL_LENGTH * 4U];
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, intBuffer, 4U);
::arm_fir_fast_q15(&m_lpFilter, intBuffer, outBuffer, P25_RADIO_SYMBOL_LENGTH * 4U);
io.write(STATE_P25, outBuffer, P25_RADIO_SYMBOL_LENGTH * 4U);
}
void CP25TX::setTXDelay(uint8_t delay)
{
m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay
@@ -196,11 +164,3 @@ uint8_t CP25TX::getSpace() const
{
return m_buffer.getSpace() / P25_LDU_FRAME_LENGTH_BYTES;
}
void CP25TX::setParams(uint8_t txHang)
{
m_txHang = txHang * 1200U;
}
#endif
+6 -15
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017 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
@@ -16,20 +16,18 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_P25)
#if !defined(P25TX_H)
#define P25TX_H
#include "RingBuffer.h"
#include "Config.h"
#include "SerialRB.h"
class CP25TX {
public:
CP25TX();
uint8_t writeData(const uint8_t* data, uint16_t length);
uint8_t writeData(const uint8_t* data, uint8_t length);
void process();
@@ -37,10 +35,8 @@ public:
uint8_t getSpace() const;
void setParams(uint8_t txHang);
private:
CRingBuffer<uint8_t> m_buffer;
CSerialRB m_buffer;
arm_fir_interpolate_instance_q15 m_modFilter;
arm_fir_instance_q15 m_lpFilter;
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
@@ -49,14 +45,9 @@ private:
uint16_t m_poLen;
uint16_t m_poPtr;
uint16_t m_txDelay;
uint32_t m_txHang;
uint32_t m_txCount;
void writeByte(uint8_t c);
void writeSilence();
};
#endif
#endif
+3 -9
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2009-2018 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
@@ -17,9 +17,6 @@
*/
#include "Config.h"
#if defined(MODE_POCSAG)
#include "Globals.h"
#include "POCSAGTX.h"
@@ -64,8 +61,7 @@ void CPOCSAGTX::process()
m_poBuffer[m_poLen++] = POCSAG_SYNC;
} else {
for (uint8_t i = 0U; i < POCSAG_FRAME_LENGTH_BYTES; i++) {
uint8_t c = 0U;
m_buffer.get(c);
uint8_t c = m_buffer.get();
m_poBuffer[m_poLen++] = c;
}
}
@@ -99,7 +95,7 @@ bool CPOCSAGTX::busy()
return false;
}
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint16_t length)
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint8_t length)
{
if (length != POCSAG_FRAME_LENGTH_BYTES)
return 4U;
@@ -151,5 +147,3 @@ uint8_t CPOCSAGTX::getSpace() const
return m_buffer.getSpace() / POCSAG_FRAME_LENGTH_BYTES;
}
#endif
+8 -12
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 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
@@ -16,22 +16,18 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Config.h"
#if defined(MODE_POCSAG)
#if !defined(POCSAGTX_H)
#define POCSAGTX_H
#include "RingBuffer.h"
#include "Config.h"
#include "SerialRB.h"
class CPOCSAGTX {
public:
CPOCSAGTX();
uint8_t writeData(const uint8_t* data, uint16_t length);
void writeByte(uint8_t c);
uint8_t writeData(const uint8_t* data, uint8_t length);
void process();
@@ -42,16 +38,16 @@ public:
bool busy();
private:
CRingBuffer<uint8_t> m_buffer;
CSerialRB m_buffer;
arm_fir_instance_q15 m_modFilter;
q15_t m_modState[170U]; // NoTaps + BlockSize - 1, 6 + 160 - 1 plus some spare
uint8_t m_poBuffer[200U];
uint16_t m_poLen;
uint16_t m_poPtr;
uint16_t m_txDelay;
void writeByte(uint8_t c);
};
#endif
#endif
+4 -32
View File
@@ -1,35 +1,7 @@
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion, P25, NXDN, POCSAG, and FM modes.
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion, P25, NXDN, and POCSAG modes.
It runs on the Arduino Due, the ST-Micro STM32F4xxx and STM32F7xxx processors, as well as the Teensy 3.5/3.6. What these platforms have in common is the use of an ARM Cortex-M3, M4, or M7 processors with a minimum clock speed greater of 80 MHz, and access to at least one analogue to digital converter, one digital to analogue converter, as well as a number of GPIO pins.
It runs on the Arduino Due, the ST-Micro STM32F1xxx, STM32F4xxx and STM32F7xxx processors, as well as the Teensy 3.1/3.2/3.5/3.6. What these platforms have in common is the use of an ARM Cortex-M3 or M4 processor with a clock speed greater than 70 MHz, and access to at least one analogue to digital converter and one digital to analogue converter.
In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. The STM32 support is supplied via the ARM GCC compiler. The Teensy support uses Teensyduino.
In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. The STM32 support is being supplied via the Coocox IDE with ARM GCC. The Teensy support uses Teensyduino.
This software is licenced under the GPL v2 and is primarily intended for amateur and educational use.
Portions of the ARM support code include the following copyright:
Copyright (c) 2011 - 2013 ARM LIMITED
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of ARM nor the names of its contributors may be used
to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.
+102
View File
@@ -0,0 +1,102 @@
/*
TX fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "RSSIRB.h"
CRSSIRB::CRSSIRB(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false),
m_overflow(false)
{
m_rssi = new uint16_t[length];
}
uint16_t CRSSIRB::getSpace() const
{
uint16_t n = 0U;
if (m_tail == m_head)
n = m_full ? 0U : m_length;
else if (m_tail < m_head)
n = m_length - m_head + m_tail;
else
n = m_tail - m_head;
if (n > m_length)
n = 0U;
return n;
}
uint16_t CRSSIRB::getData() const
{
if (m_tail == m_head)
return m_full ? m_length : 0U;
else if (m_tail < m_head)
return m_head - m_tail;
else
return m_length - m_tail + m_head;
}
bool CRSSIRB::put(uint16_t rssi)
{
if (m_full) {
m_overflow = true;
return false;
}
m_rssi[m_head] = rssi;
m_head++;
if (m_head >= m_length)
m_head = 0U;
if (m_head == m_tail)
m_full = true;
return true;
}
bool CRSSIRB::get(uint16_t& rssi)
{
if (m_head == m_tail && !m_full)
return false;
rssi = m_rssi[m_tail];
m_full = false;
m_tail++;
if (m_tail >= m_length)
m_tail = 0U;
return true;
}
bool CRSSIRB::hasOverflowed()
{
bool overflow = m_overflow;
m_overflow = false;
return overflow;
}
+59
View File
@@ -0,0 +1,59 @@
/*
Serial fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#if !defined(RSSIRB_H)
#define RSSIRB_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#elif defined(STM32F105xC)
#include "stm32f1xx.h"
#include <cstddef>
#else
#include <Arduino.h>
#endif
class CRSSIRB {
public:
CRSSIRB(uint16_t length);
uint16_t getSpace() const;
uint16_t getData() const;
bool put(uint16_t rssi);
bool get(uint16_t& rssi);
bool hasOverflowed();
private:
uint16_t m_length;
volatile uint16_t* m_rssi;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
};
#endif
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2017 Wojciech Krutnik N0CALL
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* FIFO ring buffer
* source:
* http://stackoverflow.com/questions/6822548/correct-way-of-implementing-a-uart-receive-buffer-in-a-small-arm-microcontroller
* (modified)
*
*/
#if !defined(RINGBUFF_H)
#define RINGBUFF_H
#define RINGBUFF_SIZE(ringBuff) (ringBuff.size) /* serial buffer in bytes (power 2) */
#define RINGBUFF_MASK(ringBuff) (ringBuff.size-1U) /* buffer size mask */
/* Buffer read / write macros */
#define RINGBUFF_RESET(ringBuff) (ringBuff).rdIdx = ringBuff.wrIdx = 0
#define RINGBUFF_WRITE(ringBuff, dataIn) (ringBuff).data[RINGBUFF_MASK(ringBuff) & ringBuff.wrIdx++] = (dataIn)
#define RINGBUFF_READ(ringBuff) ((ringBuff).data[RINGBUFF_MASK(ringBuff) & ((ringBuff).rdIdx++)])
#define RINGBUFF_EMPTY(ringBuff) ((ringBuff).rdIdx == (ringBuff).wrIdx)
#define RINGBUFF_FULL(ringBuff) ((RINGBUFF_MASK(ringBuff) & ringFifo.rdIdx) == (RINGBUFF_MASK(ringBuff) & ringFifo.wrIdx))
#define RINGBUFF_COUNT(ringBuff) (RINGBUFF_MASK(ringBuff) & ((ringBuff).wrIdx - (ringBuff).rdIdx))
/* Buffer type */
#define DECLARE_RINGBUFFER_TYPE(name, _size) \
typedef struct{ \
uint32_t size; \
uint32_t wrIdx; \
uint32_t rdIdx; \
uint8_t data[_size]; \
}name##_t
#endif
-74
View File
@@ -1,74 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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(RINGBUFFER_H)
#define RINGBUFFER_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#else
#include <Arduino.h>
#undef PI
#endif
#if defined(__SAM3X8E__)
#define ARM_MATH_CM3
#elif defined(STM32F7XX)
#define ARM_MATH_CM7
#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define ARM_MATH_CM4
#else
#error "Unknown processor type"
#endif
#include <arm_math.h>
template <typename TDATATYPE>
class CRingBuffer {
public:
CRingBuffer(uint16_t length = 370U);
uint16_t getSpace() const;
uint16_t getData() const;
bool put(TDATATYPE item) volatile;
bool get(TDATATYPE& item) volatile;
TDATATYPE peek() const;
bool hasOverflowed();
void reset();
private:
uint16_t m_length;
TDATATYPE* m_buffer;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
};
#include "RingBuffer.impl.h"
#endif
-114
View File
@@ -1,114 +0,0 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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 "RingBuffer.h"
template <typename TDATATYPE> CRingBuffer<TDATATYPE>::CRingBuffer(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false),
m_overflow(false)
{
m_buffer = new TDATATYPE[length];
}
template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getSpace() const
{
uint16_t n = 0U;
if (m_tail == m_head)
n = m_full ? 0U : m_length;
else if (m_tail < m_head)
n = m_length - m_head + m_tail;
else
n = m_tail - m_head;
if (n > m_length)
n = 0U;
return n;
}
template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getData() const
{
if (m_tail == m_head)
return m_full ? m_length : 0U;
else if (m_tail < m_head)
return m_head - m_tail;
else
return m_length - m_tail + m_head;
}
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::put(TDATATYPE item) volatile
{
if (m_full) {
m_overflow = true;
return false;
}
m_buffer[m_head] = item;
m_head++;
if (m_head >= m_length)
m_head = 0U;
if (m_head == m_tail)
m_full = true;
return true;
}
template <typename TDATATYPE> TDATATYPE CRingBuffer<TDATATYPE>::peek() const
{
return m_buffer[m_tail];
}
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::get(TDATATYPE& item) volatile
{
if (m_head == m_tail && !m_full)
return false;
item = m_buffer[m_tail];
m_full = false;
m_tail++;
if (m_tail >= m_length)
m_tail = 0U;
return true;
}
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::hasOverflowed()
{
bool overflow = m_overflow;
m_overflow = false;
return overflow;
}
template <typename TDATATYPE> void CRingBuffer<TDATATYPE>::reset()
{
m_head = 0U;
m_tail = 0U;
m_full = false;
m_overflow = false;
}
+1 -3
View File
@@ -1,7 +1,5 @@
/*
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
*
* Source: http://mightydevices.com/?p=144
* source: http://mightydevices.com/?p=144
*
* 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
-100
View File
@@ -1,100 +0,0 @@
/*
* Copyright (c) 2020 by Jonathan Naylor G4KLX
* Copyright (c) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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(STM32F4XX) || defined(STM32F7XX)
#include "STMUART.h"
CSTMUART::CSTMUART() :
m_usart(NULL)
{
}
void CSTMUART::init(USART_TypeDef* usart)
{
m_usart = usart;
}
void CSTMUART::write(const uint8_t * data, uint16_t length)
{
if(length == 0U || m_usart == NULL)
return;
m_txFifo.put(data[0]);
USART_ITConfig(m_usart, USART_IT_TXE, ENABLE);//switch TX IRQ is on
for(uint16_t i = 1U; i < length; i++) {
m_txFifo.put(data[i]);
}
USART_ITConfig(m_usart, USART_IT_TXE, ENABLE);//make sure TX IRQ is on
}
uint8_t CSTMUART::read()
{
return m_rxFifo.get();
}
void CSTMUART::handleIRQ()
{
if(m_usart == NULL)
return;
if (USART_GetITStatus(m_usart, USART_IT_RXNE)) {
if(!m_rxFifo.isFull())
m_rxFifo.put((uint8_t) USART_ReceiveData(m_usart));
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
if (USART_GetITStatus(m_usart, USART_IT_TXE)) {
if(!m_txFifo.isEmpty())
USART_SendData(m_usart, m_txFifo.get());
USART_ClearITPendingBit(m_usart, USART_IT_TXE);
if (m_txFifo.isEmpty()) // if there's no more data to transmit then turn off TX interrupts
USART_ITConfig(m_usart, USART_IT_TXE, DISABLE);
}
}
// Flushes the transmit shift register
// warning: this call is blocking
void CSTMUART::flush()
{
if(m_usart == NULL)
return;
// wait until the TXE shows the shift register is empty
while (USART_GetITStatus(m_usart, USART_FLAG_TXE))
;
}
uint16_t CSTMUART::available()
{
return m_rxFifo.isEmpty() ? 0U : 1U;
}
uint16_t CSTMUART::availableForWrite()
{
return m_txFifo.isFull() ? 0U : 1U;
}
#endif
-91
View File
@@ -1,91 +0,0 @@
/*
* Copyright (c) 2020 by Jonathan Naylor G4KLX
* Copyright (c) 2020 by Geoffrey Merck F4FXL - KC3FRA
*
* 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(STM32F4XX) || defined(STM32F7XX)
#if !defined(STMUART_H)
#define STMUART_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#endif
const uint16_t BUFFER_SIZE = 2048U; //needs to be a power of 2 !
const uint16_t BUFFER_MASK = BUFFER_SIZE - 1;
class CSTMUARTFIFO {
public:
CSTMUARTFIFO() :
m_head(0U),
m_tail(0U)
{
}
void put(uint8_t data)
{
m_buffer[BUFFER_MASK & (m_head++)] = data;
}
uint8_t get()
{
return m_buffer[BUFFER_MASK & (m_tail++)];
}
void reset()
{
m_tail = 0U;
m_head = 0U;
}
bool isEmpty()
{
return m_tail == m_head;
}
bool isFull()
{
return ((m_head + 1U) & BUFFER_MASK) == (m_tail & BUFFER_MASK);
}
private:
volatile uint8_t m_buffer[BUFFER_SIZE];
volatile uint16_t m_head;
volatile uint16_t m_tail;
};
class CSTMUART {
public:
CSTMUART();
void init(USART_TypeDef* usart);
void write(const uint8_t * data, uint16_t length);
uint8_t read();
void handleIRQ();
void flush();
uint16_t available();
uint16_t availableForWrite();
private:
USART_TypeDef * m_usart;
CSTMUARTFIFO m_rxFifo;
CSTMUARTFIFO m_txFifo;
};
#endif
#endif
+106
View File
@@ -0,0 +1,106 @@
/*
TX fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "SampleRB.h"
CSampleRB::CSampleRB(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false),
m_overflow(false)
{
m_samples = new uint16_t[length];
m_control = new uint8_t[length];
}
uint16_t CSampleRB::getSpace() const
{
uint16_t n = 0U;
if (m_tail == m_head)
n = m_full ? 0U : m_length;
else if (m_tail < m_head)
n = m_length - m_head + m_tail;
else
n = m_tail - m_head;
if (n > m_length)
n = 0U;
return n;
}
uint16_t CSampleRB::getData() const
{
if (m_tail == m_head)
return m_full ? m_length : 0U;
else if (m_tail < m_head)
return m_head - m_tail;
else
return m_length - m_tail + m_head;
}
bool CSampleRB::put(uint16_t sample, uint8_t control)
{
if (m_full) {
m_overflow = true;
return false;
}
m_samples[m_head] = sample;
m_control[m_head] = control;
m_head++;
if (m_head >= m_length)
m_head = 0U;
if (m_head == m_tail)
m_full = true;
return true;
}
bool CSampleRB::get(uint16_t& sample, uint8_t& control)
{
if (m_head == m_tail && !m_full)
return false;
sample = m_samples[m_tail];
control = m_control[m_tail];
m_full = false;
m_tail++;
if (m_tail >= m_length)
m_tail = 0U;
return true;
}
bool CSampleRB::hasOverflowed()
{
bool overflow = m_overflow;
m_overflow = false;
return overflow;
}
+60
View File
@@ -0,0 +1,60 @@
/*
Serial fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#if !defined(SAMPLERB_H)
#define SAMPLERB_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#elif defined(STM32F105xC)
#include "stm32f1xx.h"
#include <cstddef>
#else
#include <Arduino.h>
#endif
class CSampleRB {
public:
CSampleRB(uint16_t length);
uint16_t getSpace() const;
uint16_t getData() const;
bool put(uint16_t sample, uint8_t control);
bool get(uint16_t& sample, uint8_t& control);
bool hasOverflowed();
private:
uint16_t m_length;
volatile uint16_t* m_samples;
volatile uint8_t* m_control;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
};
#endif
+1 -1
View File
@@ -43,7 +43,7 @@ void CSerialPort::beginInt(uint8_t n, int speed)
}
}
int CSerialPort::availableForReadInt(uint8_t n)
int CSerialPort::availableInt(uint8_t n)
{
switch (n) {
case 1U:

Some files were not shown because too many files have changed in this diff Show More