Compare commits

...

31 Commits

Author SHA1 Message Date
Bryan Biedenkapp e50f1ec902 [NO FUNCTIONAL CHANGE] cleanup file headers containing lingering old comments;
3 months ago
村場 榞彦 5edc60fffa
Fixed spelling error in Makefile.STM32FX (#5)
11 months ago
Bryan Biedenkapp 718093aea3 handle serial buffer overflow condition (while the modem protocol *can* send frames >512 bytes the serial port handler can only handle frames up to 512 bytes); better handle transmitting double length (512 byte) P25 PDU frames;
11 months ago
Patrick W3AXL 251cfd44e2
Information on bookworm GPIO numbers for Pis.
1 year ago
Bryan Biedenkapp c45ec691a0 update copyrights;
2 years ago
Bryan Biedenkapp e23d16c25b implement support to software reboot into the system bootloader for flashing (using stm32flash);
2 years ago
Bryan Biedenkapp 40f9083e61 fix issue with double length frames not being correct;
2 years ago
Bryan Biedenkapp 13e51c6771 increase serial buffer size to 518 bytes;
2 years ago
Bryan Biedenkapp f0fd328381 fix Doxygen file include error;
2 years ago
Bryan Biedenkapp 994c348129 convert documentation format to Doxygen;
2 years ago
Bryan Biedenkapp 7840a3daf9 remove AUTHORS.md;
2 years ago
Bryan Biedenkapp 8d6611ef70
P25 data (#4)
2 years ago
Bryan Biedenkapp 07ec4612fc pass VSELP1/2 frames;
2 years ago
Bryan Biedenkapp 6dbbd6a8ef treewide: perform general refactor of file headers, I've modified the file headers to follow rules from: https://www.kernel.org/doc/html/next/process/license-rules.html, this trims/compresses the file header section a bit reducing the number of lines at the top of every file quite a bit, going forward all new files should follow this new format (if its good enough for the Linux kernel, its good enough for me);
2 years ago
Bryan Biedenkapp 74225c443f fix buffer overflow causing modem crash during calibration; fix file formatting; add support for force DMO configuration flag (used for calibration);
2 years ago
Bryan Biedenkapp 8008f967f1 cleanup debug log messages some more;
2 years ago
Bryan Biedenkapp 941f57b68a correct NXDN IF bandwidth to 12.5khz; compress debug messages;
2 years ago
Bryan Biedenkapp c75ff52d0c refactor ADF debug trace logging; correct some ADF IF filter configuration; correct some ADF data inversion configuration; correct some issues with DMR slot RX; remove m_endPtr from NXDNRX;
2 years ago
Bryan Biedenkapp c491e9344d ensure the hotspot returns to an idle state in the instance where a host doesn't gracefully disconnect (prevents the hotspot from getting stuck Tx);
2 years ago
Bryan Biedenkapp 77037d132d correct edge case situation where discriminator or post bandwidth may be set when they shouldn't be; cleanup bad references to the ADF7021's REG13 reference (the old code worked fine, but used magic numbers instead of proper named defines); add more verbose register debug output from the modem; display NXDN sync values copied to the bit buffer and not the sync bytes;
2 years ago
Bryan Biedenkapp f1a60d4da9 implement DMR_CLEAR1, DMR_CLEAR2, NXDN_CLEAR;
3 years ago
Bryan Biedenkapp 42f4ea03a1 add support for a CMD_SET_BUFFERS, this will allow the host to control the size of the transmit FIFO buffers; reduce the size of FIFO buffers;
3 years ago
Bryan Biedenkapp 4701bb4d6b flip values;
3 years ago
Bryan Biedenkapp 7bae382af6 fix an idiotic mistake;
3 years ago
Bryan Biedenkapp 54fed406d1 fix up priority of decoding; attempt to better sync header during non-voice and non-data streams;
3 years ago
Bryan Biedenkapp 880dca6062 update README.md;
3 years ago
Bryan Biedenkapp eb7ffb65e4 remove unnecessary compiler directives;
3 years ago
Bryan Biedenkapp 902bd7d23f update README.md;
3 years ago
Bryan Biedenkapp 03ddc2d5f4 update README.md;
3 years ago
Bryan Biedenkapp bc0ac8be7c update CI workflow;
3 years ago
Bryan Biedenkapp 9f65f935ff remove USB support from master branch (see usb-support branch);
3 years ago

@ -41,13 +41,6 @@ jobs:
rm -f dvm-firmware-hs_f1.bin
make -f Makefile.STM32FX mmdvm-hs-hat-dual
mv -f dvm-firmware-hs_f1.bin dvm-firmware-hs-hat-dual.bin
- name: Build STM32FX mmdvm-hs-hat-usb-dual Firmware
run: |
rm -rf obj_f1
rm -rf obj_f4
rm -f dvm-firmware-hs_f1bl.bin
make -f Makefile.STM32FX mmdvm-hs-hat-usb-dual
mv -f dvm-firmware-hs_f1bl.bin dvm-firmware-hs-hat-dual_usb.bin
- name: Build STM32FX mmdvm-hs-hat Firmware
run: |
rm -rf obj_f1
@ -55,13 +48,6 @@ jobs:
rm -f dvm-firmware-hs_f1.bin
make -f Makefile.STM32FX mmdvm-hs-hat
mv -f dvm-firmware-hs_f1.bin dvm-firmware-hs-hat.bin
- name: Build STM32FX mmdvm-hs-hat-usb Firmware
run: |
rm -rf obj_f1
rm -rf obj_f4
rm -f dvm-firmware-hs_f1bl.bin
make -f Makefile.STM32FX mmdvm-hs-hat-usb
mv -f dvm-firmware-hs_f1bl.bin dvm-firmware-hs-hat_usb.bin
- name: Firmware Hash
run: |
@ -76,23 +62,11 @@ jobs:
sha1 : $(sha1sum dvm-firmware-hs-hat-dual.bin)
sha256: $(sha256sum dvm-firmware-hs-hat-dual.bin)
dvm-firmware-hs-hat-dual_usb.bin
size : $(wc -c dvm-firmware-hs-hat-dual_usb.bin)
md5 : $(md5sum dvm-firmware-hs-hat-dual_usb.bin)
sha1 : $(sha1sum dvm-firmware-hs-hat-dual_usb.bin)
sha256: $(sha256sum dvm-firmware-hs-hat-dual_usb.bin)
dvm-firmware-hs-hat.bin
size : $(wc -c dvm-firmware-hs-hat.bin)
md5 : $(md5sum dvm-firmware-hs-hat.bin)
sha1 : $(sha1sum dvm-firmware-hs-hat.bin)
sha256: $(sha256sum dvm-firmware-hs-hat.bin)
dvm-firmware-hs-hat_usb.bin
size : $(wc -c dvm-firmware-hs-hat_usb.bin)
md5 : $(md5sum dvm-firmware-hs-hat_usb.bin)
sha1 : $(sha1sum dvm-firmware-hs-hat_usb.bin)
sha256: $(sha256sum dvm-firmware-hs-hat_usb.bin)
EOF
echo '```' >> release.txt
@ -103,6 +77,4 @@ jobs:
body_path: release.txt
files: |
dvm-firmware-hs-hat-dual.bin
dvm-firmware-hs-hat-dual_usb.bin
dvm-firmware-hs-hat.bin
dvm-firmware-hs-hat_usb.bin

@ -1,44 +1,26 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017,2018,2019,2020 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* Some of the code is based on work of Guus Van Dooren PE1PLM:
* https://github.com/ki6zum/gmsk-dstar/blob/master/firmware/dvmega/dvmega.ino
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2020,2021 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Jim McLaughlin, KI6ZUM
* Copyright (C) 2016,2017,2018,2019,2020 Andy Uribe, CA6JAU
* Copyright (C) 2017 Danilo, DB4PLE
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
#include <math.h>
#include "Globals.h"
#include "ADF7021.h"
/*
* Some of the code is based on work of Guus Van Dooren PE1PLM:
* https://github.com/ki6zum/gmsk-dstar/blob/master/firmware/dvmega/dvmega.ino
*/
#if defined(ENABLE_ADF7021)
// ---------------------------------------------------------------------------
@ -88,9 +70,8 @@ uint8_t m_afcRange;
// Global Functions
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/* */
static void AD7021_IOCTL_Shift()
{
for (int i = 31; i >= 0; i--) {
@ -109,9 +90,8 @@ static void AD7021_IOCTL_Shift()
io.SDATA(LOW);
}
/// <summary>
///
/// </summary>
/* */
static void AD7021_IOCTL_SLEPulse()
{
io.SLE1(HIGH);
@ -119,10 +99,8 @@ static void AD7021_IOCTL_SLEPulse()
io.SLE1(LOW);
}
/// <summary>
///
/// </summary>
/// <param name="doSle"></param>
/* */
static void AD7021_1_IOCTL(bool doSle = true)
{
AD7021_IOCTL_Shift();
@ -132,9 +110,8 @@ static void AD7021_1_IOCTL(bool doSle = true)
}
#if defined(DUPLEX)
/// <summary>
///
/// </summary>
/* */
static void AD7021_2_IOCTL_SLEPulse()
{
io.SLE2(HIGH);
@ -142,10 +119,8 @@ static void AD7021_2_IOCTL_SLEPulse()
io.SLE2(LOW);
}
/// <summary>
///
/// </summary>
/// <param name="doSle"></param>
/* */
static void AD7021_2_IOCTL(bool doSle = true)
{
AD7021_IOCTL_Shift();
@ -159,9 +134,8 @@ static void AD7021_2_IOCTL(bool doSle = true)
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Hardware interrupt handler.
/// </summary>
/* Hardware interrupt handler. */
void IO::interrupt1()
{
uint8_t bit = 0U;
@ -270,9 +244,8 @@ void IO::interrupt1()
}
#if defined(DUPLEX)
/// <summary>
/// Hardware interrupt handler.
/// </summary>
/* Hardware interrupt handler. */
void IO::interrupt2()
{
uint8_t bit = 0U;
@ -290,16 +263,13 @@ void IO::interrupt2()
}
#endif
/// <summary>
/// Sets the ADF7021 RF configuration.
/// </summary>
/// <param name="modemState"></param>
/// <param name="reset"></param>
/* Sets the ADF7021 RF configuration. */
void IO::rf1Conf(DVM_STATE modemState, bool reset)
{
uint32_t txFrequencyTmp, rxFrequencyTmp;
DEBUG4("IO::rf1Conf(): configuring ADF for Tx/Rx; modemState/reset/rxGain", modemState, reset, m_gainMode);
DEBUG4("IO::rf1Conf() ADF1 (Tx/Rx); modemState/reset/rxGain", modemState, reset, m_gainMode);
#if defined (ZUMSPOT_ADF7021) || defined(SKYBRIDGE_HS)
io.checkBand(m_rxFrequency, m_txFrequency);
@ -378,12 +348,16 @@ void IO::rf1Conf(DVM_STATE modemState, bool reset)
AD7021_CONTROL = ADF7021_REG3;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf() ADF1 REG3 =", (ADF7021_REG3 >> 16 & 0xFFFFU), (ADF7021_REG3 & 0xFFFFU));
/*
** Demodulator Setup (Register 4)
*/
AD7021_CONTROL = ADF7021_REG4;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf() ADF1 REG4 =", (ADF7021_REG4 >> 16 & 0xFFFFU), (ADF7021_REG4 & 0xFFFFU));
/*
** IF Fine Cal Setup (Register 6)
*/
@ -410,6 +384,8 @@ void IO::rf1Conf(DVM_STATE modemState, bool reset)
AD7021_CONTROL = ADF7021_REG2;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf() ADF1 REG2 =", (ADF7021_REG2 >> 16 & 0xFFFFU), (ADF7021_REG3 & 0xFFFFU));
/*
** Test DAC (Register 14)
*/
@ -446,6 +422,8 @@ void IO::rf1Conf(DVM_STATE modemState, bool reset)
AD7021_CONTROL = ADF7021_REG10;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf() ADF1 REG10 =", (ADF7021_REG10 >> 16 & 0xFFFFU), (ADF7021_REG10 & 0xFFFFU));
/*
** Sync Word Detect (Register 11)
*/
@ -464,6 +442,8 @@ void IO::rf1Conf(DVM_STATE modemState, bool reset)
AD7021_CONTROL = ADF7021_REG13;
AD7021_1_IOCTL();
DEBUG3("IO::rf1Conf() ADF1 REG13 =", (ADF7021_REG13 >> 16 & 0xFFFFU), (ADF7021_REG13 & 0xFFFFU));
/*
** Test Mode (Register 15)
*/
@ -486,14 +466,11 @@ void IO::rf1Conf(DVM_STATE modemState, bool reset)
}
#if defined(DUPLEX)
/// <summary>
/// Sets the ADF7021 RF configuration.
/// </summary>
/// <param name="modemState"></param>
/// <param name="reset"></param>
/* Sets the ADF7021 RF configuration. */
void IO::rf2Conf(DVM_STATE modemState)
{
DEBUG3("IO::rf2Conf(): configuring 2nd ADF for Rx; modemState/rxGain", modemState, m_gainMode);
DEBUG3("IO::rf2Conf() ADF2 (Rx); modemState/rxGain", modemState, m_gainMode);
// configure ADF Tx/RX
configureTxRx(modemState);
@ -511,12 +488,16 @@ void IO::rf2Conf(DVM_STATE modemState)
AD7021_CONTROL = ADF7021_REG3;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf() ADF2 REG3 =", (ADF7021_REG3 >> 16 & 0xFFFFU), (ADF7021_REG3 & 0xFFFFU));
/*
** Demodulator Setup (Register 4)
*/
AD7021_CONTROL = ADF7021_REG4;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf() ADF2 REG4 =", (ADF7021_REG4 >> 16 & 0xFFFFU), (ADF7021_REG4 & 0xFFFFU));
/*
** IF Fine Cal Setup (Register 6)
*/
@ -545,6 +526,8 @@ void IO::rf2Conf(DVM_STATE modemState)
AD7021_CONTROL = ADF7021_REG2;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf() ADF2 REG2 =", (ADF7021_REG2 >> 16 & 0xFFFFU), (ADF7021_REG3 & 0xFFFFU));
/*
** Test DAC (Register 14)
*/
@ -577,6 +560,8 @@ void IO::rf2Conf(DVM_STATE modemState)
AD7021_CONTROL = ADF7021_REG10;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf() ADF2 REG10 =", (ADF7021_REG10 >> 16 & 0xFFFFU), (ADF7021_REG10 & 0xFFFFU));
/*
** Sync Word Detect (Register 11)
*/
@ -595,6 +580,8 @@ void IO::rf2Conf(DVM_STATE modemState)
AD7021_CONTROL = ADF7021_REG13;
AD7021_2_IOCTL();
DEBUG3("IO::rf2Conf() ADF2 REG13 =", (ADF7021_REG13 >> 16 & 0xFFFFU), (ADF7021_REG13 & 0xFFFFU));
/*
** Test Mode (Register 15)
*/
@ -603,12 +590,8 @@ void IO::rf2Conf(DVM_STATE modemState)
}
#endif // DUPLEX
/// <summary>
///
/// </summary>
/// <param name="dmrTXLevel"></param>
/// <param name="p25TXLevel"></param>
/// <param name="nxdnTXLevel"></param>
/* Sets the deviation levels. */
void IO::setDeviations(uint8_t dmrTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel)
{
dmrDev = uint16_t((ADF7021_DEV_DMR * uint16_t(dmrTXLevel)) / 128U);
@ -616,17 +599,8 @@ void IO::setDeviations(uint8_t dmrTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLev
nxdnDev = uint16_t((ADF7021_DEV_NXDN * uint16_t(nxdnTXLevel)) / 128U);
}
/// <summary>
/// Sets the RF adjustment parameters.
/// </summary>
/// <param name="dmrDevAdj"></param>
/// <param name="p25DevAdj"></param>
/// <param name="dmrDiscBWAdj"></param>
/// <param name="p25DiscBWAdj"></param>
/// <param name="nxdnDiscBWAdj"></param>
/// <param name="dmrPostBWAdj"></param>
/// <param name="p25PostBWAdj"></param>
/// <param name="nxdnPostBWAdj"></param>
/* Sets the RF adjustment parameters. */
void IO::setRFAdjust(int8_t dmrDiscBWAdj, int8_t p25DiscBWAdj, int8_t nxdnDiscBWAdj, int8_t dmrPostBWAdj, int8_t p25PostBWAdj, int8_t nxdnPostBWADJ)
{
m_dmrDiscBWAdj = dmrDiscBWAdj;
@ -636,17 +610,12 @@ void IO::setRFAdjust(int8_t dmrDiscBWAdj, int8_t p25DiscBWAdj, int8_t nxdnDiscBW
m_p25PostBWAdj = p25PostBWAdj;
m_nxdnPostBWAdj = nxdnPostBWADJ;
DEBUG4("IO::setRFAdjust(): setting RF adjustment, discBW", dmrDiscBWAdj, p25DiscBWAdj, nxdnDiscBWAdj);
DEBUG4("IO::setRFAdjust(): setting RF adjustment, postBW", dmrPostBWAdj, p25PostBWAdj, nxdnPostBWADJ);
DEBUG4("IO::setRFAdjust() RF adjustment, discBW", dmrDiscBWAdj, p25DiscBWAdj, nxdnDiscBWAdj);
DEBUG4("IO::setRFAdjust() RF adjustment, postBW", dmrPostBWAdj, p25PostBWAdj, nxdnPostBWADJ);
}
/// <summary>
/// Sets the RF AFC parameters.
/// </summary>
/// <param name="afcEnable"></param>
/// <param name="afcKI"></param>
/// <param name="afcKP"></param>
/// <param name="afcRange"></param>
/* Sets the RF AFC parameters. */
void IO::setAFCParams(bool afcEnable, uint8_t afcKI, uint8_t afcKP, uint8_t afcRange)
{
m_afcEnable = afcEnable;
@ -654,12 +623,11 @@ void IO::setAFCParams(bool afcEnable, uint8_t afcKI, uint8_t afcKP, uint8_t afcR
m_afcKP = afcKP;
m_afcRange = afcRange;
DEBUG5("IO::setAFCParams(): setting AFC params", afcEnable, afcKI, afcKP, afcRange);
DEBUG5("IO::setAFCParams() AFC params", afcEnable, afcKI, afcKP, afcRange);
}
/// <summary>
///
/// </summary>
/* */
void IO::updateCal(DVM_STATE modemState)
{
uint32_t ADF7021_REG2;
@ -673,7 +641,7 @@ void IO::updateCal(DVM_STATE modemState)
AD7021_CONTROL = ADF7021_REG1;
AD7021_1_IOCTL();
// configure ADF Tx/RX
// configure ADF Tx/Rx
configureTxRx(modemState);
/*
@ -712,7 +680,7 @@ void IO::updateCal(DVM_STATE modemState)
AD7021_CONTROL = ADF7021_REG2;
AD7021_1_IOCTL();
DEBUG2("IO::updateCal(): updating ADF calibration; modemState", modemState);
DEBUG2("IO::updateCal() ADF calibration; modemState", modemState);
if (m_tx)
setTX();
@ -720,10 +688,8 @@ void IO::updateCal(DVM_STATE modemState)
setRX();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
uint16_t IO::readRSSI()
{
uint32_t AD7021_RB;
@ -812,9 +778,8 @@ uint16_t IO::readRSSI()
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/* */
void IO::configureBand()
{
/*
@ -881,13 +846,11 @@ void IO::configureBand()
else
f_div = 1U;
DEBUG3("IO::configureBand(): configuring ADF freq band; reg1/f_div", ADF7021_REG1, f_div);
DEBUG3("IO::configureBand() ADF freq band; reg1/f_div", ADF7021_REG1, f_div);
}
/// <summary>
///
/// </summary>
/// <param name="modemState"></param>
/* */
void IO::configureTxRx(DVM_STATE modemState)
{
uint16_t dmrDiscBW = ADF7021_DISC_BW_DMR, dmrPostBW = ADF7021_POST_BW_DMR;
@ -895,49 +858,61 @@ void IO::configureTxRx(DVM_STATE modemState)
uint16_t nxdnDiscBW = ADF7021_DISC_BW_NXDN, nxdnPostBW = ADF7021_POST_BW_NXDN;
// configure DMR discriminator and post demodulator BW
if (dmrDiscBW + m_dmrDiscBWAdj < 0U)
dmrDiscBW = 0U;
else
dmrDiscBW = ADF7021_DISC_BW_DMR + m_dmrDiscBWAdj;
if (dmrDiscBW > ADF7021_DISC_BW_MAX)
dmrDiscBW = ADF7021_DISC_BW_MAX;
if (m_dmrDiscBWAdj != 0) {
if (dmrDiscBW + m_dmrDiscBWAdj < 0)
dmrDiscBW = 0U;
else
dmrDiscBW = ADF7021_DISC_BW_DMR + m_dmrDiscBWAdj;
if (dmrDiscBW > ADF7021_DISC_BW_MAX)
dmrDiscBW = ADF7021_DISC_BW_MAX;
}
if (dmrPostBW + m_dmrPostBWAdj < 0)
dmrPostBW = 0U;
else
dmrPostBW = ADF7021_POST_BW_DMR + m_dmrPostBWAdj;
if (dmrPostBW > ADF7021_POST_BW_MAX)
dmrPostBW = ADF7021_POST_BW_MAX;
if (m_dmrPostBWAdj != 0) {
if (dmrPostBW + m_dmrPostBWAdj < 0)
dmrPostBW = 0U;
else
dmrPostBW = ADF7021_POST_BW_DMR + m_dmrPostBWAdj;
if (dmrPostBW > ADF7021_POST_BW_MAX)
dmrPostBW = ADF7021_POST_BW_MAX;
}
// configure P25 discriminator and post demodulator BW
if (p25DiscBW + m_p25DiscBWAdj < 0U)
p25DiscBW = 0U;
else
p25DiscBW = ADF7021_DISC_BW_P25 + m_p25DiscBWAdj;
if (p25DiscBW > ADF7021_DISC_BW_MAX)
p25DiscBW = ADF7021_DISC_BW_MAX;
if (m_p25DiscBWAdj != 0) {
if (p25DiscBW + m_p25DiscBWAdj < 0)
p25DiscBW = 0U;
else
p25DiscBW = ADF7021_DISC_BW_P25 + m_p25DiscBWAdj;
if (p25DiscBW > ADF7021_DISC_BW_MAX)
p25DiscBW = ADF7021_DISC_BW_MAX;
}
if (p25PostBW + m_p25PostBWAdj < 0)
p25PostBW = 0U;
else
p25PostBW = ADF7021_POST_BW_P25 + m_p25PostBWAdj;
if (p25PostBW > ADF7021_POST_BW_MAX)
p25PostBW = ADF7021_POST_BW_MAX;
if (m_p25PostBWAdj != 0) {
if (p25PostBW + m_p25PostBWAdj < 0)
p25PostBW = 0U;
else
p25PostBW = ADF7021_POST_BW_P25 + m_p25PostBWAdj;
if (p25PostBW > ADF7021_POST_BW_MAX)
p25PostBW = ADF7021_POST_BW_MAX;
}
// configure NXDN discriminator and post demodulator BW
if (nxdnDiscBW + m_nxdnDiscBWAdj < 0U)
nxdnDiscBW = 0U;
else
nxdnDiscBW = ADF7021_DISC_BW_NXDN + m_nxdnDiscBWAdj;
if (nxdnDiscBW > ADF7021_DISC_BW_MAX)
nxdnDiscBW = ADF7021_DISC_BW_MAX;
if (m_nxdnDiscBWAdj != 0) {
if (nxdnDiscBW + m_nxdnDiscBWAdj < 0)
nxdnDiscBW = 0U;
else
nxdnDiscBW = ADF7021_DISC_BW_NXDN + m_nxdnDiscBWAdj;
if (nxdnDiscBW > ADF7021_DISC_BW_MAX)
nxdnDiscBW = ADF7021_DISC_BW_MAX;
}
if (nxdnPostBW + m_nxdnPostBWAdj < 0)
nxdnPostBW = 0U;
else
nxdnPostBW = ADF7021_POST_BW_NXDN + m_nxdnPostBWAdj;
if (nxdnPostBW > ADF7021_POST_BW_MAX)
nxdnPostBW = ADF7021_POST_BW_MAX;
if (m_nxdnPostBWAdj != 0) {
if (nxdnPostBW + m_nxdnPostBWAdj < 0)
nxdnPostBW = 0U;
else
nxdnPostBW = ADF7021_POST_BW_NXDN + m_nxdnPostBWAdj;
if (nxdnPostBW > ADF7021_POST_BW_MAX)
nxdnPostBW = ADF7021_POST_BW_MAX;
}
/*
** Configure the remaining registers based on modem state.
@ -1007,7 +982,7 @@ void IO::configureTxRx(DVM_STATE modemState)
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)0b1101 << 0; // Register Address 13
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_DMR << 4; // Slicer Threshold
/*
@ -1081,12 +1056,12 @@ void IO::configureTxRx(DVM_STATE modemState)
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_INV_CLKDAT << 8; // Clock/Data Inversion
ADF7021_REG4 |= (uint32_t)(dmrDiscBW & 0x3FFU) << 10; // Discriminator BW
ADF7021_REG4 |= (uint32_t)(dmrPostBW & 0xFFFU) << 20; // Post Demod BW
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_125K << 30; // IF Filter
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_25K << 30; // IF Filter
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)0b1101 << 0; // Register Address 13
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_DMR << 4; // Slicer Threshold
/*
@ -1097,7 +1072,7 @@ void IO::configureTxRx(DVM_STATE modemState)
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_PA_DEF << 7; // PA Enable & PA Bias
ADF7021_REG2 |= (uint32_t)(m_rfPower & 0x3FU) << 13; // PA Level (0 - Off, 63 - 13 dBm)
ADF7021_REG2 |= (uint32_t)(dmrDev / div2) << 19; // Freq. Deviation
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_INV_CLKDAT << 28; // Clock/Data Inversion
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_INV_DATA << 28; // Data Inversion
ADF7021_REG2 |= (uint32_t)ADF7021_REG2_RC_5 << 30; // R-Cosine Alpha
}
break;
@ -1160,12 +1135,12 @@ void IO::configureTxRx(DVM_STATE modemState)
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_INV_CLKDAT << 8; // Clock/Data Inversion
ADF7021_REG4 |= (uint32_t)(p25DiscBW & 0x3FFU) << 10; // Discriminator BW
ADF7021_REG4 |= (uint32_t)(p25PostBW & 0xFFFU) << 20; // Post Demod BW
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_125K << 30; // IF Filter
ADF7021_REG4 |= (uint32_t)ADF7021_REG4_IF_25K << 30; // IF Filter
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)ADF70210_REG13_ADDR; // Register Address 13
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_P25 << 4; // Slicer Threshold
/*
@ -1256,7 +1231,7 @@ void IO::configureTxRx(DVM_STATE modemState)
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)ADF70210_REG13_ADDR; // Register Address 13
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_NXDN << 4; // Slicer Threshold
/*
@ -1334,7 +1309,7 @@ void IO::configureTxRx(DVM_STATE modemState)
/*
** 3FSK/4FSK Demod (Register 13)
*/
ADF7021_REG13 = (uint32_t)ADF70210_REG13_ADDR; // Register Address 13
ADF7021_REG13 = (uint32_t)ADF7021_REG13_ADDR; // Register Address 13
ADF7021_REG13 |= (uint32_t)ADF7021_SLICER_TH_DEFAULT << 4; // Slicer Threshold
/*
@ -1351,15 +1326,14 @@ void IO::configureTxRx(DVM_STATE modemState)
break;
}
DEBUG5("IO::configureTxRx(): configuring ADF Tx/Rx values; dmrDiscBW/dmrPostBW/p25DiscBW/p25PostBW", dmrDiscBW, dmrPostBW, p25DiscBW, p25PostBW);
DEBUG3("IO::configureTxRx(): configuring ADF Tx/Rx values; nxdnDiscBW/nxdnPostBW", nxdnDiscBW, nxdnPostBW);
DEBUG5("IO::configureTxRx(): configuring ADF Tx/Rx values; dmrSymDev/p25SymDev/nxdnSymDev/rfPower", (uint16_t)((ADF7021_PFD * dmrDev) / (f_div * 65536)),
DEBUG5("IO::configureTxRx() ADF Tx/Rx values; dmrDiscBW/dmrPostBW/p25DiscBW/p25PostBW", dmrDiscBW, dmrPostBW, p25DiscBW, p25PostBW);
DEBUG3("IO::configureTxRx() ADF Tx/Rx values; nxdnDiscBW/nxdnPostBW", nxdnDiscBW, nxdnPostBW);
DEBUG5("IO::configureTxRx() ADF Tx/Rx values; dmrSymDev/p25SymDev/nxdnSymDev/rfPower", (uint16_t)((ADF7021_PFD * dmrDev) / (f_div * 65536)),
(uint16_t)((ADF7021_PFD * p25Dev) / (f_div * 65536)), (uint16_t)((ADF7021_PFD * nxdnDev) / (f_div * 65536)), m_rfPower);
}
/// <summary>
///
/// </summary>
/* */
void IO::setTX()
{
// PTT pin on (doing it earlier helps to measure timing impact)
@ -1378,10 +1352,8 @@ void IO::setTX()
while(CLK());
}
/// <summary>
///
/// </summary>
/// <param name="doSle"></param>
/* */
void IO::setRX(bool doSle)
{
// PTT pin off (doing it earlier helps to measure timing impact)

@ -1,39 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* Some of the code is based on work of Guus Van Dooren PE1PLM:
* https://github.com/ki6zum/gmsk-dstar/blob/master/firmware/dvmega/dvmega.ino
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2020 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Jim McLaughlin, KI6ZUM
* Copyright (C) 2016,2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2017 Danilo, DB4PLE
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file ADF7021.h
* @ingroup hotspot_fw
*/
#if !defined(__ADF7021_H__)
#define __ADF7021_H__
@ -43,6 +24,11 @@
// Constants
// ---------------------------------------------------------------------------
/**
* @addtogroup hotspot_fw
* @{
*/
#define LOW 0
#define HIGH 1
@ -310,7 +296,7 @@
/*
** 3FSK/4FSK Demod (Register 13)
*/
#define ADF70210_REG13_ADDR 0b1101
#define ADF7021_REG13_ADDR 0b1101
// Slicer threshold for 4FSK demodulator
#define ADF7021_SLICER_TH_DEFAULT 0U
@ -331,4 +317,5 @@
#endif // ADF7021_N_VER
#endif // ENABLE_ADF7021
/** @} */
#endif // __ADF7021_H__

@ -1,11 +0,0 @@
# Digital Voice Modem Firmware (Hotspot)
## Project Technical Leads
- Bryan Biedenkapp (https://github.com/gatekeep)
## Developers
- Natalie Moore (https://github.com/jelimoore)
## Special thanks to
- Jonathan Naylor G4KLX (https://github.com/g4klx) and the MMDVM authors.
- Andy Uribe CA6JAU (https://github.com/juribeparada)

@ -1,44 +1,21 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Serial FIFO Control Copyright (C) 2015 by James McLaughlin KI6ZUM
*
* 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.
*
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Serial FIFO Control Copyright (C) 2015 by James McLaughlin, KI6ZUM
*
*/
#include "BitBuffer.h"
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the BitBuffer class.
/// </summary>
/* Initializes a new instance of the BitBuffer class. */
BitBuffer::BitBuffer(uint16_t length) :
m_length(length),
m_bits(NULL),
@ -52,10 +29,8 @@ BitBuffer::BitBuffer(uint16_t length) :
m_control = new uint8_t[length / 8U];
}
/// <summary>
/// Helper to get how much space the ring buffer has for samples.
/// </summary>
/// <returns></returns>
/* Helper to get how much space the ring buffer has for samples. */
uint16_t BitBuffer::getSpace() const
{
uint16_t n = 0U;
@ -73,10 +48,8 @@ uint16_t BitBuffer::getSpace() const
return n;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
uint16_t BitBuffer::getData() const
{
if (m_tail == m_head)
@ -87,11 +60,8 @@ uint16_t BitBuffer::getData() const
return m_length - m_tail + m_head;
}
/// <summary>
///
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
/* */
bool BitBuffer::put(uint8_t bit, uint8_t control)
{
if (m_full) {
@ -112,10 +82,8 @@ bool BitBuffer::put(uint8_t bit, uint8_t control)
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
bool BitBuffer::get(uint8_t& bit, uint8_t& control)
{
if (m_head == m_tail && !m_full)
@ -133,10 +101,8 @@ bool BitBuffer::get(uint8_t& bit, uint8_t& control)
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
bool BitBuffer::hasOverflowed()
{
bool overflow = m_overflow;

@ -1,35 +1,19 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Serial FIFO Control Copyright (C) 2015 by James McLaughlin KI6ZUM
*
* 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.
*
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Serial FIFO Control Copyright (C) 2015 by James McLaughlin, KI6ZUM
*
*/
/**
* @file BitBuffer.h
* @ingroup hotspot_fw
* @file BitBuffer.cpp
* @ingroup hotspot_fw
*/
#if !defined(__BIT_RB_H__)
#define __BIT_RB_H__
@ -44,27 +28,52 @@
// ---------------------------------------------------------------------------
// Class Declaration
// Implements a circular buffer for bit data.
// ---------------------------------------------------------------------------
/**
* @brief Implements a circular ring buffer for bit data.
* @ingroup hotspot_fw
*/
class DSP_FW_API BitBuffer {
public:
/// <summary>Initializes a new instance of the BitBuffer class.</summary>
/**
* @brief Initializes a new instance of the BitBuffer class.
* @param length Length of buffer.
*/
BitBuffer(uint16_t length);
/// <summary>Helper to get how much space the ring buffer has for samples.</summary>
/**
* @brief Helper to get how much space the ring buffer has for samples.
* @returns uint16_t Amount of space remaining for data.
*/
uint16_t getSpace() const;
/// <summary></summary>
/**
* @brief
* @returns uint16_t
*/
uint16_t getData() const;
/// <summary></summary>
/**
* @brief
* @param bit
* @param control
* @returns bool
*/
bool put(uint8_t bit, uint8_t control);
/// <summary></summary>
/**
* @brief
* @param[out] bit
* @param[out] control
* @returns bool
*/
bool get(uint8_t& bit, uint8_t& control);
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool hasOverflowed();
private:

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

@ -1,34 +1,14 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2017 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2017 Andy Uribe, CA6JAU
*
*/
#include "Globals.h"
#include "CWIdTX.h"
@ -101,9 +81,8 @@ const struct {
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CWIdTX class.
/// </summary>
/* Initializes a new instance of the CWIdTX class. */
CWIdTX::CWIdTX() :
m_poBuffer(),
m_poLen(0U),
@ -113,9 +92,8 @@ CWIdTX::CWIdTX() :
/* stub */
}
/// <summary>
/// Process local buffer and transmit on the air interface.
/// </summary>
/* Process local buffer and transmit on the air interface. */
void CWIdTX::process()
{
if (m_poLen == 0U)
@ -146,12 +124,8 @@ void CWIdTX::process()
}
}
/// <summary>
/// Write CW ID data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write CW ID data to the local buffer. */
uint8_t CWIdTX::write(const uint8_t* data, uint8_t length)
{
::memset(m_poBuffer, 0x00U, 300U * sizeof(uint8_t));
@ -187,14 +161,13 @@ uint8_t CWIdTX::write(const uint8_t* data, uint8_t length)
m_poLen += 5U;
DEBUG2("CWIdTx: write(): message created with length", m_poLen);
DEBUG2("CWIdTx::write() message length", m_poLen);
return RSN_OK;
}
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
/* Helper to reset data values to defaults. */
void CWIdTX::reset()
{
m_poLen = 0U;

@ -1,34 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2015 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2017 Andy Uribe, CA6JAU
*
*/
/**
* @file CWIdTX.h
* @ingroup hotspot_fw
* @file CWIdTX.cpp
* @ingroup hotspot_fw
*/
#if !defined(__CWID_TX_H__)
#define __CWID_TX_H__
@ -36,21 +22,35 @@
// ---------------------------------------------------------------------------
// Class Declaration
// Implements logic to transmit a CW ID.
// ---------------------------------------------------------------------------
/**
* @brief Implements logic to transmit a CW ID.
* @ingroup hotspot_fw
*/
class DSP_FW_API CWIdTX {
public:
/// <summary>Initializes a new instance of the CWIdTX class.</summary>
/**
* @brief Initializes a new instance of the CWIdTX class.
*/
CWIdTX();
/// <summary>Process local buffer and transmit on the air interface.</summary>
/**
* @brief Process local buffer and transmit on the air interface.
*/
void process();
/// <summary>Write CW ID data to the local buffer.</summary>
/**
* @brief Write CW ID data to the local buffer.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t write(const uint8_t* data, uint8_t length);
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset();
private:

@ -1,33 +1,13 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2018 Andy Uribe, CA6JAU
*
*/
#include "Globals.h"
#include "CalRSSI.h"
#include "Utils.h"
@ -36,9 +16,8 @@
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CalRSSI class.
/// </summary>
/* Initializes a new instance of the CalRSSI class. */
CalRSSI::CalRSSI() :
m_count(0U),
m_navg(0U),
@ -49,9 +28,8 @@ CalRSSI::CalRSSI() :
/* stub */
}
/// <summary>
/// Sample RSSI values from the air interface.
/// </summary>
/* Sample RSSI values from the air interface. */
void CalRSSI::process()
{
m_count++;

@ -1,33 +1,19 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2018 Andy Uribe, CA6JAU
*
*/
/**
* @file CalRSSI.h
* @ingroup hotspot_fw
* @file CalRSSI.cpp
* @ingroup hotspot_fw
*/
#if !defined(__CAL_RSSI_H__)
#define __CAL_RSSI_H__
@ -40,10 +26,14 @@
class DSP_FW_API CalRSSI {
public:
/// <summary>Initializes a new instance of the CalRSSI class.</summary>
/**
* @brief Initializes a new instance of the CalRSSI class.
*/
CalRSSI();
/// <summary>Sample RSSI values from the air interface.</summary>
/**
* @brief Sample RSSI values from the air interface.
*/
void process();
private:

@ -1,34 +1,18 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017,2018,2019,2020 by Andy Uribe CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2017,2018,2019,2020 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file Defines.h
* @ingroup hotspot_fw
*/
#if !defined(__DEFINES_H__)
#define __DEFINES_H__
@ -92,15 +76,6 @@ typedef unsigned long long ulong64_t;
#define DSP_FW_API
// Allow the DMR protocol
#define ENABLE_DMR
// Allow the P25 protocol
#define ENABLE_P25
// Allow the NXDN protocol
#define ENABLE_NXDN
// Enable ADF7021 support
#define ENABLE_ADF7021
@ -123,16 +98,54 @@ typedef unsigned long long ulong64_t;
#define FORCE_UHF_INTERAL_L
// Alternate P25 Deviation Levels
//#define P25_ALTERNATE_DEV_LEVEL
// #define P25_ALTERNATE_DEV_LEVEL
// Pass RSSI information to the host
// #define SEND_RSSI_DATA
// Enable for RPi 3B+, USB mode
#if defined(STM32_USB_HOST)
#define LONG_USB_RESET
#define DESCR_DMR "DMR, "
#define DESCR_P25 "P25, "
#define DESCR_NXDN "NXDN, "
#if defined(SEND_RSSI_DATA)
#define DESCR_RSSI "RSSI, "
#else
#define DESCR_RSSI ""
#endif
#if defined(ZUMSPOT_ADF7021)
#define BOARD_INFO "ZUMspot"
#elif defined(MMDVM_HS_HAT_REV12)
#define BOARD_INFO "MMDVM_HS_Hat"
#elif defined(MMDVM_HS_DUAL_HAT_REV10)
#define BOARD_INFO "MMDVM_HS_Dual_Hat"
#elif defined(NANO_HOTSPOT)
#define BOARD_INFO "Nano_hotSPOT"
#elif defined(NANO_DV_REV11)
#define BOARD_INFO "Nano_DV"
#elif defined(SKYBRIDGE_HS)
#define BOARD_INFO "SkyBridge"
#elif defined(LONESTAR_USB)
#define BOARD_INFO "LS_USB_STICK"
#else
#define BOARD_INFO "MMDVM_HS"
#endif
#if defined(ADF7021_14_7456)
#define DESCR_OSC "TCXO 14.7456, "
#endif
#if defined(ADF7021_12_2880)
#define DESCR_OSC "TCXO 12.2880, "
#endif
#if defined(ENABLE_ADF7021) && defined(ADF7021_N_VER)
#define RF_CHIP "ADF7021N, "
#elif defined(ENABLE_ADF7021)
#define RF_CHIP "ADF7021, "
#endif
#define DESCRIPTION "Digital Voice Modem DSP Hotspot [" BOARD_INFO "] (" RF_CHIP DESCR_DMR DESCR_P25 DESCR_NXDN DESCR_OSC DESCR_RSSI "CW Id)"
const uint8_t BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define CPU_TYPE_STM32 0x02U

@ -1,36 +1,17 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU
* Copyright (C) 2019 by Florian Wolters DF2ET
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Mathis Schmieder, DB9MAT
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2016,2017,2018,2019 Andy Uribe, CA6JAU
* Copyright (C) 2019 Florian Wolters, DF2ET
* Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
// ---------------------------------------------------------------------------
@ -42,58 +23,47 @@ DVM_STATE m_modemState = STATE_IDLE;
bool m_cwIdState = false;
uint8_t m_cwIdTXLevel = 30;
#ifdef ENABLE_DMR
bool m_dmrEnable = true;
#else
bool m_dmrEnable = false;
#endif
#ifdef ENABLE_P25
bool m_p25Enable = true;
#else
bool m_p25Enable = false;
#endif
#ifdef ENABLE_NXDN
bool m_nxdnEnable = true;
#else
bool m_nxdnEnable = false;
#endif
bool m_duplex = false;
bool m_forceDMO = false;
bool m_tx = false;
bool m_dcd = false;
uint8_t m_control;
/** DMR BS */
/* DMR BS */
#if defined(DUPLEX)
dmr::DMRIdleRX dmrIdleRX;
dmr::DMRRX dmrRX;
#endif
dmr::DMRTX dmrTX;
/** DMR MS-DMO */
/* DMR MS-DMO */
dmr::DMRDMORX dmrDMORX;
dmr::DMRDMOTX dmrDMOTX;
/** P25 */
/* P25 */
p25::P25RX p25RX;
p25::P25TX p25TX;
/** NXDN */
/* NXDN */
nxdn::NXDNRX nxdnRX;
nxdn::NXDNTX nxdnTX;
/** Calibration */
/* Calibration */
dmr::CalDMR calDMR;
p25::CalP25 calP25;
nxdn::CalNXDN calNXDN;
CalRSSI calRSSI;
/** CW */
/* CW */
CWIdTX cwIdTX;
/** RS232 and Air Interface I/O */
/* RS232 and Air Interface I/O */
SerialPort serial;
IO io;
@ -103,6 +73,8 @@ IO io;
void setup()
{
io.init();
serial.start();
}
@ -151,9 +123,68 @@ void loop()
// ---------------------------------------------------------------------------
// Firmware Entry Point
// ---------------------------------------------------------------------------
#include <stm32f10x_flash.h>
#define STM32_CNF_PAGE_ADDR (uint32_t)0x0800FC00
#define STM32_CNF_PAGE ((uint32_t *)0x0800FC00)
#define STM32_CNF_PAGE_24 24U
void jumpToBootLoader()
{
// Disable RCC, set it to default (after reset) settings Internal clock, no PLL, etc.
RCC_DeInit();
USART_DeInit(USART1);
USART_DeInit(UART5);
// Disable Systick timer
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// Clear Interrupt Enable Register & Interrupt Pending Register
for (uint8_t i = 0; i < sizeof(NVIC->ICER) / sizeof(NVIC->ICER[0]); i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
#if defined(STM32F10X_MD)
volatile uint32_t addr = 0x1FFFF000;
#endif
// Update the NVIC's vector
SCB->VTOR = addr;
void (*SysMemBootJump)(void);
SysMemBootJump = (void (*)(void))(*((uint32_t *)(addr + 4)));
__ASM volatile ("MSR msp, %0" : : "r" (*(uint32_t *)addr) : "sp"); // __set_MSP
SysMemBootJump();
}
int main()
{
// does the configuration page contain the request bootloader flag?
if ((STM32_CNF_PAGE[STM32_CNF_PAGE_24] != 0xFFFFFFFFU) && (STM32_CNF_PAGE[STM32_CNF_PAGE_24] != 0x00U)) {
uint8_t bootloadMode = (STM32_CNF_PAGE[STM32_CNF_PAGE_24] >> 8) & 0xFFU;
if ((bootloadMode & 0x20U) == 0x20U) {
// we unfortunately need to discard the configuration area entirely for bootloader mode...
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
#if defined(STM32F4XX) || defined(STM32F7XX)
if (FLASH_EraseSector(STM32_CNF_SECTOR, VoltageRange_3) != FLASH_COMPLETE) {
FLASH_Lock();
return RSN_FAILED_ERASE_FLASH;
}
#elif defined(STM32F10X_MD)
if (FLASH_ErasePage(STM32_CNF_PAGE_ADDR) != FLASH_COMPLETE) {
FLASH_Lock();
return RSN_FAILED_ERASE_FLASH;
}
#endif
jumpToBootLoader();
}
}
setup();
for (;;)

@ -1,35 +1,24 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU
* Copyright (C) 2019 by Florian Wolters DF2ET
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017,2018,2019 Andy Uribe, CA6JAU
* Copyright (C) 2019 Florian Wolters, DF2ET
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
/**
* @defgroup hotspot_fw Hotspot Firmware
* @brief Digital Voice Modem - Hotspot Firmware
* @details Firmware that is used for all-in-one hotspots.
* @ingroup hotspot_fw
*
* @file Globals.h
* @ingroup hotspot_fw
*/
#if !defined(__GLOBALS_H__)
#define __GLOBALS_H__
@ -72,8 +61,8 @@ const uint8_t MARK_SLOT1 = 0x08U;
const uint8_t MARK_SLOT2 = 0x04U;
const uint8_t MARK_NONE = 0x00U;
const uint8_t CONTROL_SLOT1 = 0x00U;
const uint8_t CONTROL_SLOT2 = 0x01U;
const uint8_t CONTROL_SLOT1 = 0x01U;
const uint8_t CONTROL_SLOT2 = 0x00U;
// ---------------------------------------------------------------------------
// Macros
@ -100,6 +89,7 @@ extern bool m_p25Enable;
extern bool m_nxdnEnable;
extern bool m_duplex;
extern bool m_forceDMO;
extern bool m_tx;
extern bool m_dcd;
@ -109,32 +99,32 @@ extern uint8_t m_control;
extern SerialPort serial;
extern IO io;
/** DMR BS */
/* DMR BS */
#if defined(DUPLEX)
extern dmr::DMRIdleRX dmrIdleRX;
extern dmr::DMRRX dmrRX;
#endif
extern dmr::DMRTX dmrTX;
/** DMR MS-DMO */
/* DMR MS-DMO */
extern dmr::DMRDMORX dmrDMORX;
extern dmr::DMRDMOTX dmrDMOTX;
/** P25 BS */
/* P25 BS */
extern p25::P25RX p25RX;
extern p25::P25TX p25TX;
/** NXDN BS */
/* NXDN BS */
extern nxdn::NXDNRX nxdnRX;
extern nxdn::NXDNTX nxdnTX;
/** Calibration */
/* Calibration */
extern dmr::CalDMR calDMR;
extern p25::CalP25 calP25;
extern nxdn::CalNXDN calNXDN;
extern CalRSSI calRSSI;
/** CW */
/* CW */
extern CWIdTX cwIdTX;
#endif // __GLOBALS_H__

195
IO.cpp

@ -1,35 +1,15 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2019,2020 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017,2018,2019,2020 Andy Uribe, CA6JAU
* Copyright (C) 2017 Danilo, DB4PLE
* Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "ADF7021.h"
#include "IO.h"
@ -38,9 +18,8 @@
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the IO class.
/// </summary>
/* Initializes a new instance of the IO class. */
IO::IO():
m_started(false),
m_rxBuffer(1024U),
@ -54,6 +33,13 @@ IO::IO():
m_txFrequency(DEFAULT_FREQUENCY),
m_rfPower(0U),
m_gainMode(ADF_GAIN_AUTO)
{
/* stub */
}
/* Initializes the air interface sampler. */
void IO::init()
{
initInt();
@ -80,9 +66,8 @@ IO::IO():
selfTest();
}
/// <summary>
/// Starts air interface sampler.
/// </summary>
/* Starts air interface sampler. */
void IO::start()
{
if (m_started)
@ -93,9 +78,8 @@ void IO::start()
m_started = true;
}
/// <summary>
/// Process samples from air interface.
/// </summary>
/* Process samples from air interface. */
void IO::process()
{
uint8_t bit;
@ -105,12 +89,13 @@ void IO::process()
if (m_started) {
// Two seconds timeout
if (m_watchdog >= 19200U) {
/*
if (m_modemState == STATE_DMR || m_modemState == STATE_P25) {
m_modemState = STATE_IDLE;
setMode(m_modemState);
if (m_modemState == STATE_DMR || m_modemState == STATE_P25 || m_modemState == STATE_NXDN) {
#if defined(DUPLEX)
if (m_modemState == STATE_DMR && m_tx)
dmrTX.setStart(false);
#endif
}
*/
m_watchdog = 0U;
}
@ -134,7 +119,7 @@ void IO::process()
if (m_cwIdState) {
// check for CW ID end of transmission
m_cwIdState = false;
DEBUG2("IO::process(): setting modem state", m_modemState);
DEBUG2("IO::process() setting modem state", m_modemState);
io.rf1Conf(m_modemState, true);
}
@ -147,7 +132,7 @@ void IO::process()
if (m_modemState == STATE_DMR) {
/** Digital Mobile Radio */
#if defined(DUPLEX)
if (m_duplex) {
if (m_duplex && !m_forceDMO) {
if (m_tx)
dmrRX.databit(bit, control);
else
@ -170,13 +155,8 @@ void IO::process()
}
}
/// <summary>
/// Write bits to air interface.
/// </summary>
/// <param name="mode"></param>
/// <param name="samples"></param>
/// <param name="length"></param>
/// <param name="control"></param>
/* Write bits to air interface. */
void IO::write(uint8_t* data, uint16_t length, const uint8_t* control)
{
if (!m_started)
@ -196,19 +176,15 @@ void IO::write(uint8_t* data, uint16_t length, const uint8_t* control)
}
}
/// <summary>
/// Helper to get how much space the transmit ring buffer has for samples.
/// </summary>
/// <returns></returns>
/* Helper to get how much space the transmit ring buffer has for samples. */
uint16_t IO::getSpace() const
{
return m_txBuffer.getSpace();
}
/// <summary>
///
/// </summary>
/// <param name="dcd"></param>
/* */
void IO::setDecode(bool dcd)
{
if (dcd != m_dcd)
@ -217,10 +193,8 @@ void IO::setDecode(bool dcd)
m_dcd = dcd;
}
/// <summary>
/// Helper to set the modem air interface state.
/// </summary>
/// <param name="modemState"></param>
/* Helper to set the modem air interface state. */
void IO::setMode(DVM_STATE modemState)
{
DVM_STATE relativeState = modemState;
@ -229,22 +203,17 @@ void IO::setMode(DVM_STATE modemState)
relativeState = serial.calRelativeState(modemState);
}
DEBUG3("IO::setMode(): setting modem state", modemState, relativeState);
DEBUG3("IO::setMode() setting modem state", modemState, relativeState);
rf1Conf(relativeState, true);
DEBUG4("IO::setMode(): setting lights", relativeState == STATE_DMR, relativeState == STATE_P25, relativeState == STATE_NXDN);
DEBUG4("IO::setMode() setting lights", relativeState == STATE_DMR, relativeState == STATE_P25, relativeState == STATE_NXDN);
setDMRInt(relativeState == STATE_DMR);
setP25Int(relativeState == STATE_P25);
setNXDNInt(relativeState == STATE_NXDN);
}
/// <summary>
/// Sets the RF parameters.
/// </summary>
/// <param name="rxFreq"></param>
/// <param name="txFreq"></param>
/// <param name="rfPower"></param>
/// <param name="gainMode"></param>
/* Sets the RF parameters. */
uint8_t IO::setRFParams(uint32_t rxFreq, uint32_t txFreq, uint8_t rfPower, ADF_GAIN_MODE gainMode)
{
m_rfPower = rfPower >> 2;
@ -252,22 +221,22 @@ uint8_t IO::setRFParams(uint32_t rxFreq, uint32_t txFreq, uint8_t rfPower, ADF_G
// check frequency ranges
if (!(
/** 136 - 174 mhz */
((rxFreq >= VHF_MIN) && (rxFreq < VHF_MAX)) || ((txFreq >= VHF_MIN) && (txFreq < VHF_MAX)) ||
/** 216 - 225 mhz */
((rxFreq >= VHF_220_MIN) && (rxFreq < VHF_220_MAX)) || ((txFreq >= VHF_220_MIN) && (txFreq < VHF_220_MAX)) ||
/** 380 - 431 mhz */
((rxFreq >= UHF_380_MIN) && (rxFreq < UHF_380_MAX)) || ((txFreq >= UHF_380_MIN) && (txFreq < UHF_380_MAX)) ||
/** 431 - 450 mhz */
((rxFreq >= UHF_1_MIN) && (rxFreq < UHF_1_MAX)) || ((txFreq >= UHF_1_MIN) && (txFreq < UHF_1_MAX)) ||
/** 450 - 470 mhz */
((rxFreq >= UHF_2_MIN) && (rxFreq < UHF_2_MAX)) || ((txFreq >= UHF_2_MIN) && (txFreq < UHF_2_MAX)) ||
/** 470 - 520 mhz */
((rxFreq >= UHF_T_MIN) && (rxFreq < UHF_T_MAX)) || ((txFreq >= UHF_T_MIN) && (txFreq < UHF_T_MAX)) ||
/** 842 - 900 mhz */
((rxFreq >= UHF_800_MIN) && (rxFreq < UHF_800_MAX)) || ((txFreq >= UHF_800_MIN) && (txFreq < UHF_800_MAX)) ||
/** 900 - 950 mhz */
((rxFreq >= UHF_900_MIN) && (rxFreq < UHF_900_MAX)) || ((txFreq >= UHF_900_MIN) && (txFreq < UHF_900_MAX))
/* 136 - 174 mhz */
((rxFreq >= VHF_MIN) && (rxFreq < VHF_MAX)) || ((txFreq >= VHF_MIN) && (txFreq < VHF_MAX)) ||
/* 216 - 225 mhz */
((rxFreq >= VHF_220_MIN) && (rxFreq < VHF_220_MAX)) || ((txFreq >= VHF_220_MIN) && (txFreq < VHF_220_MAX)) ||
/* 380 - 431 mhz */
((rxFreq >= UHF_380_MIN) && (rxFreq < UHF_380_MAX)) || ((txFreq >= UHF_380_MIN) && (txFreq < UHF_380_MAX)) ||
/* 431 - 450 mhz */
((rxFreq >= UHF_1_MIN) && (rxFreq < UHF_1_MAX)) || ((txFreq >= UHF_1_MIN) && (txFreq < UHF_1_MAX)) ||
/* 450 - 470 mhz */
((rxFreq >= UHF_2_MIN) && (rxFreq < UHF_2_MAX)) || ((txFreq >= UHF_2_MIN) && (txFreq < UHF_2_MAX)) ||
/* 470 - 520 mhz */
((rxFreq >= UHF_T_MIN) && (rxFreq < UHF_T_MAX)) || ((txFreq >= UHF_T_MIN) && (txFreq < UHF_T_MAX)) ||
/* 842 - 900 mhz */
((rxFreq >= UHF_800_MIN) && (rxFreq < UHF_800_MAX)) || ((txFreq >= UHF_800_MIN) && (txFreq < UHF_800_MAX)) ||
/* 900 - 950 mhz */
((rxFreq >= UHF_900_MIN) && (rxFreq < UHF_900_MAX)) || ((txFreq >= UHF_900_MIN) && (txFreq < UHF_900_MAX))
))
return RSN_INVALID_REQUEST;
@ -299,49 +268,41 @@ uint8_t IO::setRFParams(uint32_t rxFreq, uint32_t txFreq, uint8_t rfPower, ADF_G
m_rxFrequency = rxFreq;
m_txFrequency = txFreq;
DEBUG5("IO::setRFParams(): setting RF params", m_rxFrequency, m_txFrequency, m_rfPower, m_gainMode);
DEBUG5("IO::setRFParams() setting RF params", m_rxFrequency, m_txFrequency, m_rfPower, m_gainMode);
return RSN_OK;
}
/// <summary>
/// Flag indicating the TX ring buffer has overflowed.
/// </summary>
/// <returns></returns>
/* Flag indicating the TX ring buffer has overflowed. */
bool IO::hasTXOverflow()
{
return m_txBuffer.hasOverflowed();
}
/// <summary>
/// Flag indicating the RX ring buffer has overflowed.
/// </summary>
/// <returns></returns>
/* Flag indicating the RX ring buffer has overflowed. */
bool IO::hasRXOverflow()
{
return m_rxBuffer.hasOverflowed();
}
/// <summary>
///
/// </summary>
/* */
void IO::resetWatchdog()
{
m_watchdog = 0U;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
uint32_t IO::getWatchdog()
{
return m_watchdog;
}
/// <summary>
///
/// </summary>
/* */
void IO::selfTest()
{
bool ledValue = false;
@ -435,11 +396,8 @@ void IO::selfTest()
delayUS(125000U);
}
/// <summary>
///
/// </summary>
/// <param name="int1"></param>
/// <param name="int2"></param>
/* */
void IO::getIntCounter(uint16_t& int1, uint16_t& int2)
{
int1 = m_int1Counter;
@ -453,11 +411,8 @@ void IO::getIntCounter(uint16_t& int1, uint16_t& int2)
// ---------------------------------------------------------------------------
#if defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(SKYBRIDGE_HS)
/// <summary>
///
/// </summary>
/// <param name="rxFreq"></param>
/// <param name="txFreq"></param>
/* */
void IO::checkBand(uint32_t rxFreq, uint32_t txFreq)
{
// check hotspot configuration for single or dual ADF7021

379
IO.h

@ -1,35 +1,25 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2019,2020 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE
* Copyright (C) 2017-2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017,2018,2019,2020 Andy Uribe, CA6JAU
* Copyright (C) 2017 Danilo, DB4PLE
* Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file IO.h
* @ingroup hotspot_fw
* @file IO.cpp
* @ingroup hotspot_fw
* @file IOSTM.cpp
* @ingroup hotspot_fw
* @file ADF7021.cpp
* @ingroup hotspot_fw
*/
#if !defined(__IO_H__)
#define __IO_H__
@ -42,136 +32,257 @@
// ---------------------------------------------------------------------------
#if defined(DUPLEX)
#if defined(STM32_USB_HOST)
#define CAL_DLY_LOOP 98950U
#else
#define CAL_DLY_LOOP 96100U
#endif
#else
#if defined(STM32_USB_HOST)
#define CAL_DLY_LOOP 110850U
#else
#define CAL_DLY_LOOP 104600U
#endif
#endif
/**
* @brief ADF7021 Gain Modes
*/
enum ADF_GAIN_MODE {
// AGC automatic, default settings
ADF_GAIN_AUTO = 0U,
// AGC automatic with high LNA linearity
ADF_GAIN_AUTO_LIN = 1U,
// AGC OFF, lowest gain
ADF_GAIN_LOW = 2U,
// AGC OFF, highest gain
ADF_GAIN_HIGH = 3U
ADF_GAIN_AUTO = 0U, //! AGC automatic, default settings
ADF_GAIN_AUTO_LIN = 1U, //! AGC automatic with high LNA linearity
ADF_GAIN_LOW = 2U, //! AGC OFF, lowest gain
ADF_GAIN_HIGH = 3U //! AGC OFF, highest gain
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements the input/output data path with the radio air interface.
// ---------------------------------------------------------------------------
/**
* @brief Implements the input/output data path with the radio air interface.
* @ingroup hotspot_fw
*/
class DSP_FW_API IO {
public:
/// <summary>Initializes a new instance of the IO class.</summary>
/**
* @brief Initializes a new instance of the IO class.
*/
IO();
/// <summary>Starts air interface sampler.</summary>
/**
* @brief Initializes the air interface sampler.
*/
void init();
/**
* @brief Starts air interface sampler.
*/
void start();
/// <summary>Process bits from air interface.</summary>
/**
* @brief Process bits from air interface.
*/
void process();
/// <summary>Write bits to air interface.</summary>
/**
* @brief Write bits to air interface.
* @param data Data to write.
* @param length Length of data buffer.
* @param control
*/
void write(uint8_t* data, uint16_t length, const uint8_t* control = NULL);
/// <summary>Helper to get how much space the transmit ring buffer has for samples.</summary>
/**
* @brief Helper to get how much space the transmit ring buffer has for samples.
* @returns uint16_t Amount of space in the transmit ring buffer for samples.
*/
uint16_t getSpace(void) const;
/// <summary></summary>
/**
* @brief
* @param dcd
*/
void setDecode(bool dcd);
/// <summary>Set modem mode.</summary>
/**
* @brief Set modem mode.
* @param modemState
*/
void setMode(DVM_STATE modemState);
/// <summary>Hardware interrupt handler.</summary>
/**
* @brief Hardware interrupt handler.
*/
void interrupt1();
#if defined(DUPLEX)
/// <summary>Hardware interrupt handler.</summary>
/**
* @brief Hardware interrupt handler.
*/
void interrupt2();
#endif
/// <summary>Sets the ADF7021 RF configuration.</summary>
/**
* @brief Sets the ADF7021 RF configuration.
* @param modemState
* @param reset
*/
void rf1Conf(DVM_STATE modemState, bool reset);
#if defined(DUPLEX)
/// <summary>Sets the ADF7021 RF configuration.</summary>
/**
* @brief Sets the ADF7021 RF configuration.
* @param modemState
*/
void rf2Conf(DVM_STATE modemState);
#endif
/// <summary></summary>
/**
* @brief Sets the deviation levels.
* @param dmrTXLevel DMR Transmit Level.
* @param p25TXLevel P25 Transmit Level.
* @param nxdnTXLevel NXDN Transmit Level.
*/
void setDeviations(uint8_t dmrTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel);
/// <summary>Sets the RF parameters.</summary>
/**
* @brief Sets the RF parameters.
* @param rxFreq Receive Frequency (hz).
* @param txFreq Transmit Frequency (hz).
* @param rfPower RF Power Level.
* @param gainMode Gain Mode.
* @returns uint8_t Reason code.
*/
uint8_t setRFParams(uint32_t rxFreq, uint32_t txFreq, uint8_t rfPower, ADF_GAIN_MODE gainMode);
/// <summary>Sets the RF adjustment parameters.</summary>
/**
* @brief Sets the RF adjustment parameters.
* @param dmrDiscBWAdj DMR Discriminator Bandwidth Adjust.
* @param p25DiscBWAdj P25 Discriminator Bandwidth Adjust.
* @param nxdnDiscBWAdj NXDN Discriminator Bandwidth Adjust.
* @param dmrPostBWAdj DMR Post Bandwidth Adjust.
* @param p25PostBWAdj P25 Post Bandwidth Adjust.
* @param nxdnPostBWAdj NXDN Post Bandwidth Adjust.
*/
void setRFAdjust(int8_t dmrDiscBWAdj, int8_t p25DiscBWAdj, int8_t nxdnDiscBWAdj, int8_t dmrPostBWAdj, int8_t p25PostBWAdj, int8_t nxdnPostBWAdj);
/// <summary>Sets the RF AFC adjustment parameters.</summary>
/**
* @brief Sets the RF AFC adjustment parameters.
* @param afcEnable Flag indicating the Automatic Frequency Correction is enabled.
* @param afcKI
* @param afcKP
* @param afcRange
*/
void setAFCParams(bool afcEnable, uint8_t afcKI, uint8_t afcKP, uint8_t afcRange);
/// <summary>Flag indicating the TX ring buffer has overflowed.</summary>
/**
* @brief Flag indicating the TX ring buffer has overflowed.
* @returns bool Flag indicating the TX ring buffer has overflowed.
*/
bool hasTXOverflow(void);
/// <summary>Flag indicating the RX ring buffer has overflowed.</summary>
/**
* @brief Flag indicating the RX ring buffer has overflowed.
* @returns bool Flag indicating the RX ring buffer has overflowed.
*/
bool hasRXOverflow(void);
/// <summary></summary>
/**
* @brief
*/
void resetWatchdog(void);
/// <summary></summary>
/**
* @brief
* @returns uint32_t
*/
uint32_t getWatchdog(void);
/// <summary>Gets the CPU type the firmware is running on.</summary>
/**
* @brief Gets the CPU type the firmware is running on.
* @returns uint8_t
*/
uint8_t getCPU() const;
/// <summary>Gets the unique identifier for the air interface.</summary>
/**
* @brief Gets the unique identifier for the air interface.
* @param buffer
*/
void getUDID(uint8_t* buffer);
/// <summary></summary>
/**
* @brief
* @param modemState
*/
void updateCal(DVM_STATE modemState);
/// <summary></summary>
/**
* @brief
*/
void delayBit(void);
/// <summary></summary>
/**
* @brief
* @returns uint16_t
*/
uint16_t readRSSI(void);
/// <summary></summary>
/**
* @brief
*/
void selfTest();
/// <summary></summary>
/**
* @brief
*/
void resetMCU();
/**
* @brief
* @param[out] int1
* @param[out] int2
*/
void getIntCounter(uint16_t& int1, uint16_t& int2);
#if defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(SKYBRIDGE_HS)
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool isDualBand();
#endif
/// <summary></summary>
/**
* @brief
* @param on
*/
void SCLK(bool on);
/// <summary></summary>
/**
* @brief
* @param on
*/
void SDATA(bool on);
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool SREAD();
/// <summary></summary>
/**
* @brief
* @param on
*/
void SLE1(bool on);
#if defined(DUPLEX)
/// <summary></summary>
/**
* @brief
* @param on
*/
void SLE2(bool on);
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool RXD2();
#endif
/// <summary></summary>
/**
* @brief
* @param on
*/
void CE(bool on);
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool RXD1();
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool CLK();
private:
@ -193,58 +304,116 @@ private:
uint8_t m_rfPower;
ADF_GAIN_MODE m_gainMode;
/// <summary>Helper to check the frequencies are within band ranges of the ADF7021.</summary>
/**
* @brief Helper to check the frequencies are within band ranges of the ADF7021.
* @param rxFreq Receive Frequency (hz).
* @param txFreq Transmit Frequency (hz).
*/
void checkBand(uint32_t rxFreq, uint32_t txFreq);
#if defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(SKYBRIDGE_HS)
/// <summary></summary>
/**
* @brief
* @param enable
*/
void setBandVHF(bool enable);
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool hasSingleADF7021();
#endif
/// <summary></summary>
/**
* @brief
*/
void configureBand();
/// <summary></summary>
/**
* @brief
* @param modemState
*/
void configureTxRx(DVM_STATE modemState);
/// <summary></summary>
/**
* @brief
*/
void setTX();
/// <summary></summary>
/**
* @brief
* @param doSle
*/
void setRX(bool doSle = true);
/// <summary></summary>
/**
* @brief
*/
void delayIfCal();
/// <summary></summary>
/**
* @brief
*/
void delayReset();
/// <summary></summary>
/**
* @brief
* @param us
*/
void delayUS(uint32_t us);
// Hardware specific routines
/// <summary>Initializes hardware interrupts.</summary>
/**
* @brief Initializes hardware interrupts.
*/
void initInt();
/// <summary>Starts hardware interrupts.</summary>
/**
* @brief Starts hardware interrupts.
*/
void startInt();
/// <summary></summary>
/**
* @brief
* @param on
*/
void setTXDInt(bool on);
#if defined(BIDIR_DATA_PIN)
/// <summary></summary>
/**
* @brief
* @param dir
*/
void setDataDirOut(bool dir);
/// <summary></summary>
/**
* @brief
* @param on
*/
void setRXDInt(bool on);
#endif
/// <summary></summary>
/**
* @brief
* @param on
*/
void setLEDInt(bool on);
/// <summary></summary>
/**
* @brief
* @param on
*/
void setPTTInt(bool on);
/// <summary></summary>
/**
* @brief
* @param on
*/
void setCOSInt(bool on);
/// <summary></summary>
/**
* @brief
* @param on
*/
void setDMRInt(bool on);
/// <summary></summary>
/**
* @brief
* @param on
*/
void setP25Int(bool on);
/// <summary></summary>
/**
* @brief
* @param on
*/
void setNXDNInt(bool on);
};

@ -1,36 +1,16 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017,2018,2019,2020 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2020 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Jim McLaughlin, KI6ZUM
* Copyright (C) 2016,2017,2018,2019,2020 Andy Uribe, CA6JAU
* Copyright (C) 2017 Danilo, DB4PLE
* Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "IO.h"
@ -100,7 +80,7 @@
#define PIN_COS_LED GPIO_Pin_13
#define PORT_COS_LED GPIOB
#elif defined(ZUMSPOT_ADF7021) || defined(SKYBRIDGE_HS) || defined(LONESTAR_USB)
#elif defined(ZUMSPOT_ADF7021) || defined(SKYBRIDGE_HS)
#define PIN_SCLK GPIO_Pin_5
#define PORT_SCLK GPIOB
@ -162,11 +142,7 @@
#define PIN_DEB GPIO_Pin_9
#define PORT_DEB GPIOB
#if defined(STM32_USB_HOST)
#define PIN_NXDN_LED GPIO_Pin_1
#else
#define PIN_NXDN_LED GPIO_Pin_7
#endif
#define PORT_NXDN_LED GPIOA
#define PIN_DMR_LED GPIO_Pin_13
@ -248,7 +224,7 @@
#define PORT_COS_LED GPIOB
#else
#error "Either PI_HAT_7021_REV_02, ZUMSPOT_ADF7021, LONESTAR_USB, MMDVM_HS_HAT_REV12, MMDVM_HS_DUAL_HAT_REV10, NANO_HOTSPOT, NANO_DV_REV11, or SKYBRIDGE_HS need to be defined"
#error "Either PI_HAT_7021_REV_02, ZUMSPOT_ADF7021, MMDVM_HS_HAT_REV12, MMDVM_HS_DUAL_HAT_REV10, NANO_HOTSPOT, NANO_DV_REV11, or SKYBRIDGE_HS need to be defined"
#endif
// ---------------------------------------------------------------------------
@ -276,7 +252,7 @@ extern "C" {
}
#endif // BIDIR_DATA_PIN
#elif defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) || defined(SKYBRIDGE_HS)
#elif defined(ZUMSPOT_ADF7021) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) || defined(SKYBRIDGE_HS)
#if defined(BIDIR_DATA_PIN)
void EXTI3_IRQHandler(void) {
@ -313,10 +289,8 @@ extern "C" {
#endif
}
/// <summary>
/// Function delay_us() from stm32duino project
/// </summary>
/// <param name="us">Number of microseconds to delay.</param>
/* Function delay_us() from stm32duino project */
static inline void delay_us(uint32_t us)
{
us *= 12;
@ -332,9 +306,8 @@ static inline void delay_us(uint32_t us)
: "r0");
}
/// <summary>
///
/// </summary>
/* */
static inline void delay_ns()
{
@ -349,121 +322,115 @@ static inline void delay_ns()
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Gets the CPU type the firmware is running on.
/// </summary>
/// <returns></returns>
/* Gets the CPU type the firmware is running on. */
uint8_t IO::getCPU() const
{
return CPU_TYPE_STM32;
}
/// <summary>
/// Gets the unique identifier for the air interface.
/// </summary>
/// <returns></returns>
/* Gets the unique identifier for the air interface. */
void IO::getUDID(uint8_t* buffer)
{
::memcpy(buffer, (void*)STM32_UUID, 12U);
}
/// <summary>
///
/// </summary>
/* */
void IO::resetMCU()
{
DEBUG1("reset - bye-bye");
delayUS(250 * 1000);
setLEDInt(false);
setCOSInt(false);
setDMRInt(false);
setP25Int(false);
setNXDNInt(false);
delayUS(250 * 1000);
NVIC_SystemReset();
}
/* */
void IO::delayBit()
{
delay_ns();
}
#if defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(SKYBRIDGE_HS)
/// <summary>
///
/// </summary>
/// <returns></returns>
#if defined(ZUMSPOT_ADF7021) || defined(SKYBRIDGE_HS)
/* */
bool IO::isDualBand()
{
return GPIO_ReadInputDataBit(PORT_DL_DPX, PIN_DL_DPX) == Bit_SET;
}
#endif
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::SCLK(bool on)
{
GPIO_WriteBit(PORT_SCLK, PIN_SCLK, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::SDATA(bool on)
{
GPIO_WriteBit(PORT_SDATA, PIN_SDATA, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
bool IO::SREAD()
{
return GPIO_ReadInputDataBit(PORT_SREAD, PIN_SREAD) == Bit_SET;
}
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::SLE1(bool on)
{
GPIO_WriteBit(PORT_SLE, PIN_SLE, on ? Bit_SET : Bit_RESET);
}
#if defined(DUPLEX)
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::SLE2(bool on)
{
GPIO_WriteBit(PORT_SLE2, PIN_SLE2, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
bool IO::RXD2()
{
return GPIO_ReadInputDataBit(PORT_RXD2, PIN_RXD2) == Bit_SET;
}
#endif
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::CE(bool on)
{
GPIO_WriteBit(PORT_CE, PIN_CE, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
bool IO::RXD1()
{
return GPIO_ReadInputDataBit(PORT_RXD, PIN_RXD) == Bit_SET;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
bool IO::CLK()
{
#if defined(BIDIR_DATA_PIN)
@ -477,54 +444,45 @@ bool IO::CLK()
// Private Class Members
// ---------------------------------------------------------------------------
#if defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(SKYBRIDGE_HS)
/// <summary>
///
/// </summary>
/// <param name="enable"></param>
#if defined(ZUMSPOT_ADF7021) || defined(SKYBRIDGE_HS)
/* */
void IO::setBandVHF(bool enable)
{
GPIO_WriteBit(PORT_SET_BAND, PIN_SET_BAND, enable ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
bool IO::hasSingleADF7021()
{
return GPIO_ReadInputDataBit(PORT_SGL_DBL, PIN_SGL_DBL) == Bit_SET;
}
#endif
/// <summary>
///
/// </summary>
/* */
void IO::delayIfCal()
{
delayUS(10000);
}
/// <summary>
///
/// </summary>
/* */
void IO::delayReset()
{
delayUS(300);
}
/// <summary>
///
/// </summary>
/// <param name="us"></param>
/* */
void IO::delayUS(uint32_t us)
{
::delay_us(us);
}
/// <summary>
/// Initializes hardware interrupts.
/// </summary>
/* Initializes hardware interrupts. */
void IO::initInt()
{
GPIO_InitTypeDef GPIO_InitStruct;
@ -539,11 +497,11 @@ void IO::initInt()
#if defined(PI_HAT_7021_REV_02)
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
#elif defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) || defined(SKYBRIDGE_HS)
#elif defined(ZUMSPOT_ADF7021) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) || defined(SKYBRIDGE_HS)
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
#endif
#if defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(SKYBRIDGE_HS)
#if defined(ZUMSPOT_ADF7021) || defined(SKYBRIDGE_HS)
// Pin defines if the board has a single ADF7021 or double
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = PIN_SGL_DBL;
@ -566,30 +524,12 @@ void IO::initInt()
#endif
#if defined(STM32_USB_HOST)
// Pin PA11,PA12 = LOW, USB Reset
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_WriteBit(GPIOA, GPIO_Pin_11, Bit_RESET);
GPIO_WriteBit(GPIOA, GPIO_Pin_12, Bit_RESET);
#endif
#if defined(LONG_USB_RESET)
// 10 ms delay
delayUS(10000U);
#else
volatile unsigned int delay;
for (delay = 0; delay < 512; delay++);
#endif
#if !defined(STM32_USB_HOST)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
#endif
RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
@ -724,7 +664,7 @@ void IO::initInt()
EXTI_InitStructure.EXTI_Line = EXTI_Line14;
#endif
#elif defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) || defined(SKYBRIDGE_HS)
#elif defined(ZUMSPOT_ADF7021) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) || defined(SKYBRIDGE_HS)
#if defined(BIDIR_DATA_PIN)
// Connect EXTI3 Line
@ -742,7 +682,7 @@ void IO::initInt()
// Connect EXTI5 Line
GPIO_EXTILineConfig(PORT_TXD2_INT, PIN_TXD2_INT);
// Configure EXT5 line
#if defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(SKYBRIDGE_HS)
#if defined(ZUMSPOT_ADF7021) || defined(SKYBRIDGE_HS)
EXTI_InitStructure2.EXTI_Line = EXTI_Line8;
#else
EXTI_InitStructure2.EXTI_Line = EXTI_Line5;
@ -764,9 +704,8 @@ void IO::initInt()
#endif
}
/// <summary>
/// Starts hardware interrupts.
/// </summary>
/* Starts hardware interrupts. */
void IO::startInt()
{
NVIC_InitTypeDef NVIC_InitStructure;
@ -779,7 +718,7 @@ void IO::startInt()
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
#elif defined(ZUMSPOT_ADF7021) || defined(LONESTAR_USB) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) || defined(SKYBRIDGE_HS)
#elif defined(ZUMSPOT_ADF7021) || defined(LIBRE_KIT_ADF7021) || defined(MMDVM_HS_HAT_REV12) || defined(MMDVM_HS_DUAL_HAT_REV10) || defined(NANO_HOTSPOT) || defined(NANO_DV_REV11) || defined(D2RG_MMDVM_HS) || defined(SKYBRIDGE_HS)
#if defined(BIDIR_DATA_PIN)
// Enable and set EXTI3 Interrupt
@ -810,11 +749,8 @@ void IO::startInt()
#if defined(BIDIR_DATA_PIN)
/// <summary>
///
/// </summary>
/// <remarks>RXD pin is bidirectional in standard interfaces</remarks>
/// <param name="dir"></param>
/* */
void IO::setDataDirOut(bool dir)
{
GPIO_InitTypeDef GPIO_InitStruct;
@ -832,74 +768,58 @@ void IO::setDataDirOut(bool dir)
#endif
#if defined(BIDIR_DATA_PIN)
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::setRXDInt(bool on)
{
GPIO_WriteBit(PORT_RXD, PIN_RXD, on ? Bit_SET : Bit_RESET);
}
#endif
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::setTXDInt(bool on)
{
GPIO_WriteBit(PORT_TXD, PIN_TXD, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::setLEDInt(bool on)
{
GPIO_WriteBit(PORT_LED, PIN_LED, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::setPTTInt(bool on)
{
GPIO_WriteBit(PORT_PTT_LED, PIN_PTT_LED, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::setCOSInt(bool on)
{
GPIO_WriteBit(PORT_COS_LED, PIN_COS_LED, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::setDMRInt(bool on)
{
GPIO_WriteBit(PORT_DMR_LED, PIN_DMR_LED, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::setP25Int(bool on)
{
GPIO_WriteBit(PORT_P25_LED, PIN_P25_LED, on ? Bit_SET : Bit_RESET);
}
/// <summary>
///
/// </summary>
/// <param name="on"></param>
/* */
void IO::setNXDNInt(bool on)
{
GPIO_WriteBit(PORT_NXDN_LED, PIN_NXDN_LED, on ? Bit_SET : Bit_RESET);

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

@ -15,10 +15,7 @@ OBJDIR_F4=obj_f4
BINELF_F1=dvm-firmware-hs_f1.elf
BINHEX_F1=dvm-firmware-hs_f1.hex
BINBIN_F1=dvm-firmware-hs_f1.bin
BINELF_F1BL=dvm-firmware-hs_f1bl.elf
BINHEX_F1BL=dvm-firmware-hs_f1bl.hex
BINBIN_F1BL=dvm-firmware-hs_f1bl.bin
BINELF_F4=dvm-firwmare-hs_f4.elf
BINELF_F4=dvm-firmware-hs_f4.elf
BINHEX_F4=dvm-firmware-hs_f4.hex
BINBIN_F4=dvm-firmware-hs_f4.bin
@ -81,7 +78,6 @@ CSRC_STD_F4=$(wildcard $(STD_LIB_F4)/*.c)
SYS_F4=$(wildcard $(SYS_DIR_F4)/*.c)
STARTUP_F4=$(wildcard $(STARTUP_DIR_F4)/*.c)
OBJ_F1=$(CXXSRC:./%.cpp=$(OBJDIR_F1)/%.o) $(CSRC_STD_F1:$(STD_LIB_F1)/%.c=$(OBJDIR_F1)/%.o) $(SYS_F1:$(SYS_DIR_F1)/%.c=$(OBJDIR_F1)/%.o) $(STARTUP_F1:$(STARTUP_DIR_F1)/%.c=$(OBJDIR_F1)/%.o)
OBJ_F1BL=$(CXXSRC:./%.cpp=$(OBJDIR_F1)/%.o) $(CSRC_STD_F1:$(STD_LIB_F1)/%.c=$(OBJDIR_F1)/%.o) $(SYS_F1:$(SYS_DIR_F1)/%.c=$(OBJDIR_F1)/%.o) $(STARTUP_F1:$(STARTUP_DIR_F1)/%.c=$(OBJDIR_F1)/%.o) $(CXX_USB_F1:$(USB_F1)/%.cpp=$(OBJDIR_F1)/%.o) $(C_USB_F1:$(USB_F1)/%.c=$(OBJDIR_F1)/%.o)
OBJ_F4=$(CXXSRC:./%.cpp=$(OBJDIR_F4)/%.o) $(CSRC_STD_F4:$(STD_LIB_F4)/%.c=$(OBJDIR_F4)/%.o) $(SYS_F4:$(SYS_DIR_F4)/%.c=$(OBJDIR_F4)/%.o) $(STARTUP_F4:$(STARTUP_DIR_F4)/%.c=$(OBJDIR_F4)/%.o)
# MCU flags
@ -90,7 +86,6 @@ MCFLAGS_F4=-mcpu=cortex-m4 -mthumb -mlittle-endian -mfpu=fpv4-sp-d16 -mfloat-abi
# Compile flags
DEFS_F1_HS=-DUSE_STDPERIPH_DRIVER -DSTM32F10X_MD -DHSE_VALUE=$(OSC) -DVECT_TAB_OFFSET=0x0 -DMADEBYMAKEFILE
DEFS_F1_HS_BL=-DUSE_STDPERIPH_DRIVER -DSTM32F10X_MD -DHSE_VALUE=$(OSC) -DVECT_TAB_OFFSET=0x2000 -DMADEBYMAKEFILE
# STM32F446 Pi-Hat board:
DEFS_PI_F4=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
# STM32F4 Nucleo-64 F446RE board:
@ -104,7 +99,6 @@ CXXFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
# Linker flags
LDFLAGS_F1_N =-T stm32f10x_normal.ld $(MCFLAGS_F1) $(INCLUDES_LIBS_F1)
LDFLAGS_F1_D =-T stm32f10x_debug.ld $(MCFLAGS_F1) $(INCLUDES_LIBS_F1)
LDFLAGS_F1_BL =-T stm32f10x_bootloader.ld $(MCFLAGS_F1) $(INCLUDES_LIBS_F1)
LDFLAGS_F4 =-T stm32f4xx_link.ld $(MCFLAGS_F4) $(INCLUDES_LIBS_F4)
LDFLAGS_F4_D =-T stm32f4xx_link_debug.ld $(MCFLAGS_F4) $(INCLUDES_LIBS_F4)
@ -114,7 +108,7 @@ CXXFLAGS=-Os -g -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin
LDFLAGS=-Os -g --specs=nano.specs --specs=nosys.specs
# Build Rules
.PHONY: all release_f1 release_f4 hs bl pi-f4 f446 clean
.PHONY: all release_f1 release_f4 hs pi-f4 f446 clean
all: hs
@ -126,12 +120,6 @@ zumspot-adf7021: hs
zumspot-adf7021-duplex: CFLAGS+=-DDUPLEX
zumspot-adf7021-duplex: CXXFLAGS+=-DDUPLEX
zumspot-adf7021-duplex: zumspot-adf7021
zumspot-adf7021-usb: CFLAGS+=-DZUMSPOT_ADF7021 -DSTM32_USB_HOST
zumspot-adf7021-usb: CXXFLAGS+=-DZUMSPOT_ADF7021 -DSTM32_USB_HOST
zumspot-adf7021-usb: bl
zumspot-adf7021-usb-duplex: CFLAGS+=-DDUPLEX
zumspot-adf7021-usb-duplex: CXXFLAGS+=-DDUPLEX
zumspot-adf7021-usb-duplex: zumspot-adf7021-usb
pihat-7021-r2: CFLAGS+=-DPI_HAT_7021_REV_02 -DSTM32_USART1_HOST
pihat-7021-r2: CXXFLAGS+=-DZUMSPOT_ADF7021 -DSTM32_USART1_HOST
@ -140,10 +128,6 @@ pihat-7021-r2-duplex: CFLAGS+=-DDUPLEX
pihat-7021-r2-duplex: CXXFLAGS+=-DDUPLEX
pihat-7021-r2-duplex: pihat-7021-r2
lonestar-usb: CFLAGS+=-DLONESTAR_USB -DSTM32_USB_HOST
lonestar-usb: CXXFLAGS+=-DLONESTAR_USB -DSTM32_USB_HOST
lonestar-usb: bl
mmdvm-hs-hat: CFLAGS+=-DMMDVM_HS_HAT_REV12 -DSTM32_USART1_HOST
mmdvm-hs-hat: CXXFLAGS+=-DMMDVM_HS_HAT_REV12 -DSTM32_USART1_HOST
mmdvm-hs-hat: hs
@ -156,12 +140,6 @@ mmdvm-hs-hat-dual: mmdvm-hs-hat
mmdvm-hs-hat-dual-debug: CFLAGS+=-DDUPLEX
mmdvm-hs-hat-dual-debug: CXXFLAGS+=-DDUPLEX
mmdvm-hs-hat-dual-debug: mmdvm-hs-hat-debug
mmdvm-hs-hat-usb: CFLAGS+=-DMMDVM_HS_HAT_REV12 -DSTM32_USB_HOST
mmdvm-hs-hat-usb: CXXFLAGS+=-DMMDVM_HS_HAT_REV12 -DSTM32_USB_HOST
mmdvm-hs-hat-usb: bl
mmdvm-hs-hat-usb-dual: CFLAGS+=-DDUPLEX
mmdvm-hs-hat-usb-dual: CXXFLAGS+=-DDUPLEX
mmdvm-hs-hat-usb-dual: mmdvm-hs-hat-usb
hs: CFLAGS+=$(CFLAGS_F1) $(DEFS_F1_HS)
hs: CXXFLAGS+=$(CXXFLAGS_F1) $(DEFS_F1_HS)
@ -173,19 +151,10 @@ hs-debug: CXXFLAGS+=$(CXXFLAGS_F1) $(DEFS_F1_HS)
hs-debug: LDFLAGS+=$(LDFLAGS_F1_D)
hs-debug: release_f1
bl: CFLAGS+=$(CFLAGS_F1) $(DEFS_F1_HS_BL)
bl: CXXFLAGS+=$(CXXFLAGS_F1) $(DEFS_F1_HS_BL)
bl: LDFLAGS+=$(LDFLAGS_F1_BL)
bl: release_f1bl
release_f1: $(BINDIR)
release_f1: $(OBJDIR_F1)
release_f1: $(BINDIR)/$(BINBIN_F1)
release_f1bl: $(BINDIR)
release_f1bl: $(OBJDIR_F1)
release_f1bl: $(BINDIR)/$(BINBIN_F1BL)
release_f4: $(BINDIR)
release_f4: $(OBJDIR_F4)
release_f4: $(BINDIR)/$(BINBIN_F4)
@ -203,12 +172,6 @@ $(OBJDIR_F4):
mkdir $@/p25
mkdir $@/nxdn
$(BINDIR)/$(BINBIN_F1BL): $(BINDIR)/$(BINELF_F1BL)
$(CP) -O binary $< $@
$(BINDIR)/$(BINELF_F1BL): $(OBJ_F1BL)
$(CXX) $(OBJ_F1BL) $(LDFLAGS) -o $@
$(SIZE) $(BINDIR)/$(BINELF_F1BL)
$(BINDIR)/$(BINBIN_F1): $(BINDIR)/$(BINELF_F1)
$(CP) -O binary $< $@
$(BINDIR)/$(BINELF_F1): $(OBJ_F1)
@ -249,4 +212,3 @@ clean:
test ! -d $(OBJDIR_F1) || rm -rf $(OBJDIR_F1)
test ! -d $(OBJDIR_F4) || rm -rf $(OBJDIR_F4)
rm -f $(BINDIR)/*.bin $(BINDIR)/*.elf

@ -17,15 +17,11 @@ Please see the various Makefile's included in the project for more information.
To build the firmware, use the ```make``` command, followed by -f and the correct makefile, followed by the type of board you are using.
> **_NOTE:_** The only two known tested targets are ```mmdvm-hs-hat-dual``` and ```mmdvm-hs-hat-dual-usb```.
An example of this would be ```make -f Makefile.STM32FX mmdvm-hs-hat-dual``` for a full duplex modem hotspot, attached to GPIO.
## Firmware installation
The device can be used on top on a RPi attached via the GPIO port or standalone and connected via USB. Both variants require different handling of compiling and uploading the firmware, examples on flashing devices are mostly not included here because the methods to flash vary from device to device.
The USB connection requires firmware with bootloader support whereas the GPIO version does not. For USB connection a bootloader has to be installed initally. This requires STlink connection. After that is done the firmware upgrade can be done via the USB connection. The STlink connection can be used as fallback if wrongly configured firmware was installed for example.
The device can be used on top on a RPi attached via the GPIO port or standalone and connected via USB (see usb-support branch). Both variants require different handling of compiling and uploading the firmware, examples on flashing devices are mostly not included here because the methods to flash vary from device to device.
### Install the firmware via GPIO on Raspberry Pi
@ -36,9 +32,13 @@ Next, you will need to disable bluetooth on the board. Edit ```/boot/config.txt`
> Most sets of instructions reccomend to download stm32flash from online, however we have found the prepackaged version to work fine.
Once the hotspot is back on, navigate to the build folder where you compiled the firmware. Put a jumper across the J1 points on the board, and the RED heartbeat LED should stop flashing. Run the below command to flash.
Once the hotspot is back on, navigate to the build folder where you compiled the firmware. Put a jumper across the J1 points on the board, and the RED heartbeat LED should stop flashing. Run the below command to flash. Sudo is required on most systems to access GPIO pins.
```sudo stm32flash -v -w dvm-firmware-hs_f1.bin -i 20,-21,21,-20 -R /dev/ttyAMA0```
```stm32flash -v -w dvm-firmware-hs_f1.bin -i 20,-21,21,-20 -R /dev/ttyAMA0```
Note that on newer raspbian versions, the way GPIO chips are numbered has changed. If you're using raspbian bookworm (debian 12) or greater, use this command instead:
```sudo stm32flash -v -w dvm-firmware-hs_f1.bin -i 532,-533,533,-520 -R /dev/ttyAMA0```
You should see the below output if the board flashed successfully.
```
@ -48,47 +48,9 @@ Resetting device...
Reset done.
```
### Install the firmware with bootloader support for USB connection
If you want to use the device via USB port you have to install a bootloader and build the firmware with bootloader support. As the raw device cannot be used with USB you have to use a USB-serial adapter or STlink device.
* The bootloader (https://github.com/DVMProject/STM32F10X_Platform/blob/527fee72ae2291486304380cb812c48f36122c32/utils/bootloader/generic_boot20_pc13.bin) should be installed starting at offset 0x8000000.
* The firmware should be installed starting at offset 0x8002000.
An example Using STlink this can be done as follows:
```
user@host:~/dvmfirmware-hs$ -f Makefile.STM32FX mmdvm-hs-hat-usb-dual
...
user@host:~/dvmfirmware-hs$ ./STM32F10X_Platform/utils/linux64/st-flash write ./STM32F10X_Platform/utils/bootloader/generic_boot20_pc13.bin 0x8000000
2018-03-02T10:01:04 INFO src/usb.c: -- exit_dfu_mode
2018-03-02T10:01:04 INFO src/common.c: Loading device parameters....
2018-03-02T10:01:04 INFO src/common.c: Device connected is: F1 Medium-density device, id 0x20036410
2018-03-02T10:01:04 INFO src/common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes
2018-03-02T10:01:04 INFO src/common.c: Attempting to write 7160 (0x1bf8) bytes to stm32 address: 134217728 (0x8000000)
Flash page at addr: 0x08001800 erased
2018-03-02T10:01:04 INFO src/common.c: Finished erasing 7 pages of 1024 (0x400) bytes
2018-03-02T10:01:04 INFO src/common.c: Starting Flash write for VL/F0/F3 core id
2018-03-02T10:01:04 INFO src/common.c: Successfully loaded flash loader in sram
6/6 pages written
2018-03-02T10:01:05 INFO src/common.c: Starting verification of write complete
2018-03-02T10:01:05 INFO src/common.c: Flash written and verified! jolly good!
user@host:~/dvmfirmware-hs$ ./STM32F10X_Platform/utils/linux64/st-flash write dvm-firmware-hs_f1bl.bin 0x8002000
2018-03-02T10:01:05 INFO src/common.c: Loading device parameters....
2018-03-02T10:01:05 INFO src/common.c: Device connected is: F1 Medium-density device, id 0x20036410
2018-03-02T10:01:05 INFO src/common.c: SRAM size: 0x5000 bytes (20 KiB), Flash: 0x10000 bytes (64 KiB) in pages of 1024 bytes
2018-03-02T10:01:05 INFO src/common.c: Attempting to write 55016 (0xd6e8) bytes to stm32 address: 134225920 (0x8002000)
Flash page at addr: 0x0800f400 erased
2018-03-02T10:01:07 INFO src/common.c: Finished erasing 54 pages of 1024 (0x400) bytes
2018-03-02T10:01:07 INFO src/common.c: Starting Flash write for VL/F0/F3 core id
2018-03-02T10:01:07 INFO src/common.c: Successfully loaded flash loader in sram
53/53 pages written
2018-03-02T10:01:12 INFO src/common.c: Starting verification of write complete
2018-03-02T10:01:13 INFO src/common.c: Flash written and verified! jolly good!
```
The device should now be usable as /dev/ttyACMx.
## Notes
**USB Support Note**: See the usb-support branch for the version of this firmware that supports USB.
**NXDN Support Note**: NXDN support is currently experimental.
## License

@ -1,34 +1,13 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (c) 2020 Jonathan Naylor, G4KLX
* Copyright (c) 2020 Geoffrey Merck, F4FXL - KC3FRA
*
*/
#if defined(STM32F10X_MD) || defined(STM32F4XX)
#include "STM_UART.h"
@ -37,25 +16,23 @@
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the STM_UART class.
/// </summary>
/* Initializes a new instance of the STM_UART class. */
STM_UART::STM_UART() :
m_usart(NULL)
{
/* stub */
}
/// <summary></summary>
/// <param name="usart"></param>
/* */
void STM_UART::init(USART_TypeDef* usart)
{
m_usart = usart;
}
/// <summary></summary>
/// <param name="data"></param>
/// <param name="length"></param>
/* */
void STM_UART::write(const uint8_t* data, uint16_t length)
{
if (length == 0U || m_usart == NULL)
@ -72,14 +49,15 @@ void STM_UART::write(const uint8_t* data, uint16_t length)
USART_ITConfig(m_usart, USART_IT_TXE, ENABLE);//make sure TX IRQ is on
}
/// <summary></summary>
/// <returns></returns>
/* */
uint8_t STM_UART::read()
{
return m_rxFifo.get();
}
/// <summary></summary>
/* */
void STM_UART::handleIRQ()
{
if (m_usart == NULL)
@ -102,12 +80,8 @@ void STM_UART::handleIRQ()
}
}
/// <summary>
/// Flushes the transmit shift register.
/// </summary>
/// <remarks>
/// This call is blocking!
/// </remarks>
/* Flushes the transmit shift register. */
void STM_UART::flush()
{
if (m_usart == NULL)
@ -118,15 +92,15 @@ void STM_UART::flush()
;
}
/// <summary></summary>
/// <returns></returns>
/* */
uint16_t STM_UART::available()
{
return m_rxFifo.isEmpty() ? 0U : 1U;
}
/// <summary></summary>
/// <returns></returns>
/* */
uint16_t STM_UART::availableForWrite()
{
return m_txFifo.isFull() ? 0U : 1U;

@ -1,34 +1,19 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (c) 2020 Jonathan Naylor, G4KLX
* Copyright (c) 2020 Geoffrey Merck, F4FXL - KC3FRA
*
*/
/**
* @file STM_UART.h
* @ingroup hotspot_fw
* @file STM_UART.cpp
* @ingroup hotspot_fw
*/
#if defined(STM32F10X_MD) || defined(STM32F4XX)
#if !defined(__STM_UART_H__)
#define __STM_UART_H__
@ -46,12 +31,17 @@ const uint16_t BUFFER_MASK = BUFFER_SIZE - 1;
// ---------------------------------------------------------------------------
// Class Declaration
// This class represents a FIFO buffer on a STM32 UART.
// ---------------------------------------------------------------------------
/**
* @brief This class represents a FIFO buffer on a STM32 UART.
* @ingroup hotspot_fw
*/
class DSP_FW_API STM_UARTFIFO {
public:
/// <summary>Initializes a new instance of the STM_UARTFIFO class.</summary>
/**
* @brief Initializes a new instance of the STM_UARTFIFO class.
*/
STM_UARTFIFO() :
m_head(0U),
m_tail(0U)
@ -59,32 +49,46 @@ public:
/* stub */
}
/// <summary></summary>
/**
* @brief
* @returns uint8_t
*/
uint8_t get()
{
return m_buffer[BUFFER_MASK & (m_tail++)];
}
/// <summary></summary>
/**
* @brief
* @param data
*/
void put(uint8_t data)
{
m_buffer[BUFFER_MASK & (m_head++)] = data;
}
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset()
{
m_tail = 0U;
m_head = 0U;
}
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool isEmpty()
{
return m_tail == m_head;
}
/// <summary></summary>
/**
* @brief
* @returns bool
*/
bool isFull()
{
return ((m_head + 1U) & BUFFER_MASK) == (m_tail & BUFFER_MASK);
@ -98,32 +102,59 @@ private:
// ---------------------------------------------------------------------------
// Class Declaration
// This class represents an STM32 UART.
// ---------------------------------------------------------------------------
/**
* @brief This class represents an STM32 UART.
* @ingroup hotspot_fw
*/
class STM_UART {
public:
/// <summary>Initializes a new instance of the STM_UART class.</summary>
/**
* @brief Initializes a new instance of the STM_UART class.
*/
STM_UART();
/// <summary></summary>
/**
* @brief Initializes the UART.
* @param usart
*/
void init(USART_TypeDef* usart);
/// <summary></summary>
/**
* @brief
* @returns uint8_t
*/
uint8_t read();
/// <summary></summary>
/**
* @brief
* @param[in] data
* @param length
*/
void write(const uint8_t* data, uint16_t length);
/// <summary></summary>
/**
* @brief
*/
void handleIRQ();
/// <summary>Flushes the transmit shift register.</summary>
/**
* @brief Flushes the transmit shift register.
*
* This call is blocking!
*/
void flush();
/// <summary></summary>
/**
* @brief
* @returns uint16_t
*/
uint16_t available();
/// <summary></summary>
/**
* @brief
* @returns uint16_t
*/
uint16_t availableForWrite();
private:

@ -1,45 +1,22 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Serial FIFO Control Copyright (C) 2015 by James McLaughlin KI6ZUM
* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
*
* 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.
*
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Serial FIFO Control Copyright (C) 2015 by James McLaughlin, KI6ZUM
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL
*
*/
#include "SerialBuffer.h"
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the SerialBuffer class.
/// </summary>
/* Initializes a new instance of the SerialBuffer class. */
SerialBuffer::SerialBuffer(uint16_t length) :
m_length(length),
m_buffer(NULL),
@ -50,18 +27,15 @@ SerialBuffer::SerialBuffer(uint16_t length) :
m_buffer = new uint8_t[length];
}
/// <summary>
/// Finalizes a instance of the SerialBuffer class.
/// </summary>
/* Finalizes a instance of the SerialBuffer class. */
SerialBuffer::~SerialBuffer()
{
delete[] m_buffer;
}
/// <summary>
/// Helper to get how much space the ring buffer has for samples.
/// </summary>
/// <returns></returns>
/* Helper to get how much space the ring buffer has for samples. */
uint16_t SerialBuffer::getSpace() const
{
uint16_t n = 0U;
@ -79,10 +53,8 @@ uint16_t SerialBuffer::getSpace() const
return n;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
uint16_t SerialBuffer::getData() const
{
if (m_tail == m_head)
@ -93,9 +65,8 @@ uint16_t SerialBuffer::getData() const
return m_length - m_tail + m_head;
}
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
/* Helper to reset data values to defaults. */
void SerialBuffer::reset()
{
m_head = 0U;
@ -103,9 +74,8 @@ void SerialBuffer::reset()
m_full = false;
}
/// <summary>
/// Helper to reset and reinitialize data values to defaults.
/// </summary>
/* Helper to reset and reinitialize data values to defaults. */
void SerialBuffer::reinitialize(uint16_t length)
{
reset();
@ -116,11 +86,8 @@ void SerialBuffer::reinitialize(uint16_t length)
m_buffer = new uint8_t[length];
}
/// <summary>
///
/// </summary>
/// <param name="c"></param>
/// <returns></returns>
/* */
bool SerialBuffer::put(uint8_t c)
{
if (m_full)
@ -138,19 +105,15 @@ bool SerialBuffer::put(uint8_t c)
return true;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
uint8_t SerialBuffer::peek() const
{
return m_buffer[m_tail];
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* */
uint8_t SerialBuffer::get()
{
uint8_t value = m_buffer[m_tail];

@ -1,36 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Serial FIFO Control Copyright (C) 2015 by James McLaughlin KI6ZUM
* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
*
* 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.
*
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Serial FIFO Control Copyright (C) 2015 by James McLaughlin, KI6ZUM
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file SerialBuffer.h
* @ingroup hotspot_fw
* @file SerialBuffer.cpp
* @ingroup hotspot_fw
*/
#if !defined(__SERIAL_RB_H__)
#define __SERIAL_RB_H__
@ -51,34 +35,64 @@ const uint16_t SERIAL_RINGBUFFER_SIZE = 396U;
// ---------------------------------------------------------------------------
// Class Declaration
// Implements a circular buffer for serial data.
//
// ---------------------------------------------------------------------------
/**
* @brief Implements a circular ring buffer for serial data.
* @ingroup hotspot_fw
*/
class DSP_FW_API SerialBuffer {
public:
/// <summary>Initializes a new instance of the SerialBuffer class.</summary>
/**
* @brief Initializes a new instance of the SerialBuffer class.
* @param length Length of buffer.
*/
SerialBuffer(uint16_t length = SERIAL_RINGBUFFER_SIZE);
/// <summary>Finalizes a instance of the SerialBuffer class.</summary>
/**
* @brief Finalizes a instance of the SerialBuffer class.
*/
~SerialBuffer();
/// <summary>Helper to get how much space the ring buffer has for samples.</summary>
/**
* @brief Helper to get how much space the ring buffer has for samples.
* @returns uint16_t Amount of space remaining for data.
*/
uint16_t getSpace() const;
/// <summary></summary>
/**
* @brief
* @returns uint16_t
*/
uint16_t getData() const;
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset();
/// <summary>Helper to reset and reinitialize data values to defaults.</summary>
/**
* @brief Helper to reset and reinitialize data values to defaults.
* @param length Length of buffer.
*/
void reinitialize(uint16_t length);
/// <summary></summary>
/**
* @brief
* @param c
* @returns bool
*/
bool put(uint8_t c);
/// <summary></summary>
/**
* @brief
* @returns uint8_t
*/
uint8_t peek() const;
/// <summary></summary>
/**
* @brief
* @returns uint8_t
*/
uint8_t get();
private:

File diff suppressed because it is too large Load Diff

@ -1,34 +1,22 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2018,2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 2018,2021-2022 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2018,2020,2021 Jonathan Naylor, G4KLX
* Copyright (C) 2018 Andy Uribe, CA6JAU
* Copyright (C) 2018,2021-2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file SerialPort.h
* @ingroup hotspot_fw
* @file SerialPort.cpp
* @ingroup hotspot_fw
* @file SerialSTM.cpp
* @ingroup hotspot_fw
*/
#if !defined(__SERIAL_PORT_H__)
#define __SERIAL_PORT_H__
@ -40,209 +28,371 @@
// Constants
// ---------------------------------------------------------------------------
/**
* @addtogroup modem
* @{
*/
/**
* @brief Modem operation states.
*/
enum DVM_STATE {
STATE_IDLE = 0U,
STATE_IDLE = 0U, //! Idle
// DMR
STATE_DMR = 1U,
STATE_DMR = 1U, //! DMR
// Project 25
STATE_P25 = 2U,
STATE_P25 = 2U, //! Project 25
// NXDN
STATE_NXDN = 3U,
STATE_NXDN = 3U, //! NXDN
// CW
STATE_CW = 10U,
STATE_CW = 10U, //! Continuous Wave
// Calibration States
STATE_INT_CAL = 90U,
STATE_INT_CAL = 90U, //!
STATE_P25_CAL_1K = 92U,
STATE_P25_CAL_1K = 92U, //! Project 25 Calibration 1K
STATE_DMR_DMO_CAL_1K = 93U,
STATE_DMR_CAL_1K = 94U,
STATE_DMR_LF_CAL = 95U,
STATE_DMR_DMO_CAL_1K = 93U, //! DMR DMO Calibration 1K
STATE_DMR_CAL_1K = 94U, //! DMR Calibration 1K
STATE_DMR_LF_CAL = 95U, //! DMR Low Frequency Calibration
STATE_RSSI_CAL = 96U,
STATE_RSSI_CAL = 96U, //! RSSI Calibration
STATE_P25_CAL = 97U,
STATE_DMR_CAL = 98U,
STATE_NXDN_CAL = 99U
STATE_P25_CAL = 97U, //! Project 25 Calibration
STATE_DMR_CAL = 98U, //! DMR Calibration
STATE_NXDN_CAL = 99U //! NXDN Calibration
};
/**
* @brief Modem commands.
*/
enum DVM_COMMANDS {
CMD_GET_VERSION = 0x00U,
CMD_GET_STATUS = 0x01U,
CMD_SET_CONFIG = 0x02U,
CMD_SET_MODE = 0x03U,
CMD_SET_SYMLVLADJ = 0x04U,
CMD_SET_RXLEVEL = 0x05U,
CMD_SET_RFPARAMS = 0x06U,
CMD_CAL_DATA = 0x08U,
CMD_RSSI_DATA = 0x09U,
CMD_SEND_CWID = 0x0AU,
CMD_DMR_DATA1 = 0x18U,
CMD_DMR_LOST1 = 0x19U,
CMD_DMR_DATA2 = 0x1AU,
CMD_DMR_LOST2 = 0x1BU,
CMD_DMR_SHORTLC = 0x1CU,
CMD_DMR_START = 0x1DU,
CMD_DMR_ABORT = 0x1EU,
CMD_DMR_CACH_AT_CTRL = 0x1FU,
CMD_P25_DATA = 0x31U,
CMD_P25_LOST = 0x32U,
CMD_P25_CLEAR = 0x33U,
CMD_NXDN_DATA = 0x41U,
CMD_NXDN_LOST = 0x42U,
CMD_ACK = 0x70U,
CMD_NAK = 0x7FU,
CMD_FLSH_READ = 0xE0U,
CMD_FLSH_WRITE = 0xE1U,
CMD_DEBUG1 = 0xF1U,
CMD_DEBUG2 = 0xF2U,
CMD_DEBUG3 = 0xF3U,
CMD_DEBUG4 = 0xF4U,
CMD_DEBUG5 = 0xF5U,
CMD_DEBUG_DUMP = 0xFAU,
CMD_GET_VERSION = 0x00U, //! Get Modem Version
CMD_GET_STATUS = 0x01U, //! Get Modem Status
CMD_SET_CONFIG = 0x02U, //! Set Modem Configuration
CMD_SET_MODE = 0x03U, //! Set Modem Mode
CMD_SET_SYMLVLADJ = 0x04U, //! Set Symbol Level Adjustments
CMD_SET_RXLEVEL = 0x05U, //! Set Rx Level
CMD_SET_RFPARAMS = 0x06U, //! (Hotspot) Set RF Parameters
CMD_CAL_DATA = 0x08U, //! Calibration Data
CMD_RSSI_DATA = 0x09U, //! RSSI Data
CMD_SEND_CWID = 0x0AU, //! Send Continous Wave ID (Morse)
CMD_SET_BUFFERS = 0x0FU, //! Set FIFO Buffer Lengths
CMD_DMR_DATA1 = 0x18U, //! DMR Data Slot 1
CMD_DMR_LOST1 = 0x19U, //! DMR Data Lost Slot 1
CMD_DMR_DATA2 = 0x1AU, //! DMR Data Slot 2
CMD_DMR_LOST2 = 0x1BU, //! DMR Data Lost Slot 2
CMD_DMR_SHORTLC = 0x1CU, //! DMR Short Link Control
CMD_DMR_START = 0x1DU, //! DMR Start Transmit
CMD_DMR_ABORT = 0x1EU, //! DMR Abort
CMD_DMR_CACH_AT_CTRL = 0x1FU, //! DMR Set CACH AT Control
CMD_DMR_CLEAR1 = 0x20U, //! DMR Clear Slot 1 Buffer
CMD_DMR_CLEAR2 = 0x21U, //! DMR Clear Slot 2 Buffer
CMD_P25_DATA = 0x31U, //! Project 25 Data
CMD_P25_LOST = 0x32U, //! Project 25 Data Lost
CMD_P25_CLEAR = 0x33U, //! Project 25 Clear Buffer
CMD_NXDN_DATA = 0x41U, //! NXDN Data
CMD_NXDN_LOST = 0x42U, //! NXDN Data Lost
CMD_NXDN_CLEAR = 0x43U, //! NXDN Clear Buffer
CMD_ACK = 0x70U, //! Command ACK
CMD_NAK = 0x7FU, //! Command NACK
CMD_FLSH_READ = 0xE0U, //! Read Flash Partition
CMD_FLSH_WRITE = 0xE1U, //! Write Flash Partition
CMD_RESET_MCU = 0xEAU, //! Soft Reboot MCU
CMD_DEBUG1 = 0xF1U, //!
CMD_DEBUG2 = 0xF2U, //!
CMD_DEBUG3 = 0xF3U, //!
CMD_DEBUG4 = 0xF4U, //!
CMD_DEBUG5 = 0xF5U, //!
CMD_DEBUG_DUMP = 0xFAU, //!
};
/**
* @brief Modem response reason codes.
*/
enum CMD_REASON_CODE {
RSN_OK = 0U,
RSN_NAK = 1U,
RSN_OK = 0U, //! OK
RSN_NAK = 1U, //! Negative Acknowledge
RSN_ILLEGAL_LENGTH = 2U, //! Illegal Length
RSN_INVALID_REQUEST = 4U, //! Invalid Request
RSN_RINGBUFF_FULL = 8U, //! Ring Buffer Full
RSN_ILLEGAL_LENGTH = 2U,
RSN_INVALID_REQUEST = 4U,
RSN_RINGBUFF_FULL = 8U,
RSN_INVALID_FDMA_PREAMBLE = 10U, //! Invalid FDMA Preamble Length
RSN_INVALID_MODE = 11U, //! Invalid Mode
RSN_INVALID_FDMA_PREAMBLE = 10U,
RSN_INVALID_MODE = 11U,
RSN_INVALID_DMR_CC = 12U,
RSN_INVALID_DMR_SLOT = 13U,
RSN_INVALID_DMR_START = 14U,
RSN_INVALID_DMR_RX_DELAY = 15U,
RSN_INVALID_DMR_CC = 12U, //! Invalid DMR CC
RSN_INVALID_DMR_SLOT = 13U, //! Invalid DMR Slot
RSN_INVALID_DMR_START = 14U, //! Invaild DMR Start Transmit
RSN_INVALID_DMR_RX_DELAY = 15U, //! Invalid DMR Rx Delay
RSN_INVALID_P25_CORR_COUNT = 16U,
RSN_INVALID_P25_CORR_COUNT = 16U, //! Invalid P25 Correlation Count
RSN_NO_INTERNAL_FLASH = 20U,
RSN_FAILED_ERASE_FLASH = 21U,
RSN_FAILED_WRITE_FLASH = 22U,
RSN_FLASH_WRITE_TOO_BIG = 23U,
RSN_NO_INTERNAL_FLASH = 20U, //! No Internal Flash
RSN_FAILED_ERASE_FLASH = 21U, //! Failed to erase flash partition
RSN_FAILED_WRITE_FLASH = 22U, //! Failed to write flash partition
RSN_FLASH_WRITE_TOO_BIG = 23U, //! Data to large for flash partition
RSN_HS_NO_DUAL_MODE = 32U,
RSN_HS_NO_DUAL_MODE = 32U, //! (Hotspot) No Dual Mode Operation
RSN_DMR_DISABLED = 63U,
RSN_P25_DISABLED = 64U,
RSN_NXDN_DISABLED = 65U
RSN_DMR_DISABLED = 63U, //! DMR Disabled
RSN_P25_DISABLED = 64U, //! Project 25 Disabled
RSN_NXDN_DISABLED = 65U //! NXDN Disabled
};
const uint8_t DVM_FRAME_START = 0xFEU;
const uint8_t DVM_SHORT_FRAME_START = 0xFEU;
const uint8_t DVM_LONG_FRAME_START = 0xFDU;
#define SERIAL_FB_LEN 518U
#define SERIAL_SPEED 115200
#define STATE_SCAN_MAX 3
/** @} */
// ---------------------------------------------------------------------------
// Class Declaration
// Implements the RS232 serial bus to communicate with the HOST S/W.
// ---------------------------------------------------------------------------
/**
* @brief Implements the RS232 serial bus to communicate with the HOST S/W.
* @ingroup hotspot_fw
*/
class DSP_FW_API SerialPort {
public:
/// <summary>Initializes a new instance of the SerialPort class.</summary>
/**
* @brief Initializes a new instance of the SerialPort class.
*/
SerialPort();
/// <summary>Starts serial port communications.</summary>
/**
* @brief Starts serial port communications.
*/
void start();
/// <summary>Process data from serial port.</summary>
/**
* @brief Process data from serial port.
*/
void process();
/// <summary>Helper to check if the modem is in a calibration state.</summary>
/**
* @brief Helper to check if the modem is in a calibration state.
* @param state
* @returns bool
*/
bool isCalState(DVM_STATE state);
/// <summary>Helper to determine digital mode if the modem is in a calibration state.</summary>
/**
* @brief Helper to determine digital mode if the modem is in a calibration state.
* @param state
* @returns DVM_STATE
*/
DVM_STATE calRelativeState(DVM_STATE state);
/// <summary>Write DMR frame data to serial port.</summary>
/**
* @brief Write DMR frame data to serial port.
* @param slot DMR slot number.
* @param[in] data Data to write.
* @param length Length of data to write.
*/
void writeDMRData(bool slot, const uint8_t* data, uint8_t length);
/// <summary>Write lost DMR frame data to serial port.</summary>
/**
* @brief Write lost DMR frame data to serial port.
* @param slot DMR slot number.
*/
void writeDMRLost(bool slot);
/// <summary>Write P25 frame data to serial port.</summary>
void writeP25Data(const uint8_t* data, uint8_t length);
/// <summary>Write lost P25 frame data to serial port.</summary>
/**
* @brief Write P25 frame data to serial port.
* @param[in] data Data to write.
* @param length Length of data to write.
*/
void writeP25Data(const uint8_t* data, uint16_t length);
/**
* @brief Write lost P25 frame data to serial port.
*/
void writeP25Lost();
/// <summary>Write NXDN frame data to serial port.</summary>
/**
* @brief Write NXDN frame data to serial port.
* @param[in] data Data to write.
* @param length Length of data to write.
*/
void writeNXDNData(const uint8_t* data, uint8_t length);
/// <summary>Write lost NXDN frame data to serial port.</summary>
/**
* @brief Write lost NXDN frame data to serial port.
*/
void writeNXDNLost();
/// <summary>Write calibration frame data to serial port.</summary>
/**
* @brief Write calibration frame data to serial port.
* @param[in] data Data to write.
* @param length Length of data to write.
*/
void writeCalData(const uint8_t* data, uint8_t length);
/// <summary>Write RSSI frame data to serial port.</summary>
/**
* @brief Write RSSI frame data to serial port.
* @param[in] data Data to write.
* @param length Length of data to write.
*/
void writeRSSIData(const uint8_t* data, uint8_t length);
/// <summary></summary>
/**
* @brief
* @param[in] text
*/
void writeDebug(const char* text);
/// <summary></summary>
/**
* @brief
* @param[in] text
* @param n1
*/
void writeDebug(const char* text, int16_t n1);
/// <summary></summary>
/**
* @brief
* @param[in] text
* @param n1
* @param n2
*/
void writeDebug(const char* text, int16_t n1, int16_t n2);
/// <summary></summary>
/**
* @brief
* @param[in] text
* @param n1
* @param n2
* @param n3
*/
void writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3);
/// <summary></summary>
/**
* @brief
* @param[in] text
* @param n1
* @param n2
* @param n3
* @param n4
*/
void writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3, int16_t n4);
/// <summary></summary>
/**
* @brief
* @param[in] data
* @param length
*/
void writeDump(const uint8_t* data, uint16_t length);
private:
uint8_t m_buffer[256U];
uint8_t m_ptr;
uint8_t m_len;
uint8_t m_buffer[SERIAL_FB_LEN];
uint16_t m_ptr;
uint16_t m_len;
bool m_dblFrame;
bool m_debug;
/// <summary>Write acknowlegement.</summary>
/**
* @brief Write acknowlegement.
*/
void sendACK();
/// <summary>Write negative acknowlegement.</summary>
/**
* @brief Write negative acknowlegement.
* @param err
*/
void sendNAK(uint8_t err);
/// <summary>Write modem DSP status.</summary>
/**
* @brief Write modem DSP status.
*/
void getStatus();
/// <summary>Write modem DSP version.</summary>
/**
* @brief Write modem DSP version.
*/
void getVersion();
/// <summary>Helper to validate the passed modem state is valid.</summary>
/**
* @brief Helper to validate the passed modem state is valid.
* @param state
* @returns uint8_t Reason code.
*/
uint8_t modemStateCheck(DVM_STATE state);
/// <summary>Set modem DSP configuration from serial port data.</summary>
/**
* @brief Set modem DSP configuration from serial port data.
* @param[in] data Buffer containing configuration frame.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t setConfig(const uint8_t* data, uint8_t length);
/// <summary>Set modem DSP mode from serial port data.</summary>
/**
* @brief Set modem DSP mode from serial port data.
* @param[in] data Buffer containing mode frame.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t setMode(const uint8_t* data, uint8_t length);
/// <summary>Sets the modem state.</summary>
/**
* @brief Sets the modem state.
* @param modemState
*/
void setMode(DVM_STATE modemState);
/// <summary>Sets the RF parameters.</summary>
/**
* @brief Sets the RF parameters.
* @param[in] data Buffer containing RF parameters frame.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t setRFParams(const uint8_t* data, uint8_t length);
/// <summary></summary>
/**
* @brief Sets the protocol ring buffer sizes.
* @param[in] data Buffer containing set buffers frame.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t setBuffers(const uint8_t* data, uint8_t length);
/**
* @brief Reads data from the modem flash parititon.
*/
void flashRead();
/// <summary></summary>
/**
* @brief Writes data to the modem flash partition.
* @param[in] data Buffer containing data to write to flash partition.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t flashWrite(const uint8_t* data, uint8_t length);
// Hardware specific routines
/// <summary></summary>
/**
* @brief
* @param n
* @param speed
*/
void beginInt(uint8_t n, int speed);
/// <summary></summary>
/**
* @brief
* @param n
*/
int availableInt(uint8_t n);
/// <summary></summary>
/**
* @brief
* @param n
*/
int availableForWriteInt(uint8_t n);
/// <summary></summary>
/**
* @brief
* @param n
*/
uint8_t readInt(uint8_t n);
/// <summary></summary>
/**
* @brief
* @param n
* @param[in] data
* @param length
* @param flush
*/
void writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush = false);
};

@ -1,34 +1,14 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017,2018,2019 by Andy Uribe CA6JAU
* Copyright (C) 2021-2022 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2016 Jim McLaughlin, KI6ZUM
* Copyright (C) 2016,2017,2018,2019 Andy Uribe, CA6JAU
* Copyright (C) 2021,2022,2024 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "SerialPort.h"
#include "STM_UART.h"
@ -36,14 +16,6 @@
#if defined(STM32F10X_MD)
#include <stm32f10x_flash.h>
#if defined(STM32_USB_HOST)
#include <usb_serial.h>
#endif
#if defined(STM32_USART1_HOST) && defined(STM32_USB_HOST)
#error "You have to select STM32_USART1_HOST or STM32_USB_HOST, but not both"
#endif
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
@ -78,18 +50,18 @@ extern "C" {
static STM_UART m_USART1;
/// <summary>
///
/// </summary>
/**
* @brief Helper to handle the USART1 IRQ.
*/
void USART1_IRQHandler()
{
m_USART1.handleIRQ();
}
/// <summary>
///
/// </summary>
/// <param name="speed"></param>
/**
* @brief Initializes the USART1.
* @param speed Port speed.
*/
void InitUSART1(int speed)
{
// USART1 - TXD PA9 - RXD PA10
@ -143,18 +115,18 @@ void InitUSART1(int speed)
static STM_UART m_USART2;
/// <summary>
///
/// </summary>
/**
* @brief Helper to handle the USART5 IRQ.
*/
void USART2_IRQHandler()
{
m_USART2.handleIRQ();
}
/// <summary>
///
/// </summary>
/// <param name="speed"></param>
/**
* @brief Initializes the USART5.
* @param speed Port speed.
*/
void InitUSART2(int speed)
{
// USART2 - TXD PA2 - RXD PA3
@ -204,14 +176,13 @@ void InitUSART2(int speed)
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/* Reads data from the modem flash parititon. */
void SerialPort::flashRead()
{
uint8_t reply[249U];
reply[0U] = DVM_FRAME_START;
reply[0U] = DVM_SHORT_FRAME_START;
reply[1U] = 249U;
reply[2U] = CMD_FLSH_READ;
@ -220,11 +191,8 @@ void SerialPort::flashRead()
writeInt(1U, reply, 249U);
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/* Writes data to the modem flash partition. */
uint8_t SerialPort::flashWrite(const uint8_t* data, uint8_t length)
{
if (length > 249U) {
@ -270,20 +238,13 @@ uint8_t SerialPort::flashWrite(const uint8_t* data, uint8_t length)
return RSN_OK;
}
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/// <param name="speed"></param>
/* */
void SerialPort::beginInt(uint8_t n, int speed)
{
switch (n) {
case 1U:
#if defined(STM32_USART1_HOST)
InitUSART1(speed);
#elif defined(STM32_USB_HOST)
usbserial.begin();
#endif
break;
case 3U:
InitUSART2(speed);
@ -293,20 +254,13 @@ void SerialPort::beginInt(uint8_t n, int speed)
}
}
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
/* */
int SerialPort::availableInt(uint8_t n)
{
switch (n) {
case 1U:
#if defined(STM32_USART1_HOST)
return m_USART1.available();
#elif defined(STM32_USB_HOST)
return usbserial.available();
#endif
case 3U:
m_USART2.available();
default:
@ -314,21 +268,13 @@ int SerialPort::availableInt(uint8_t n)
}
}
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
/* */
int SerialPort::availableForWriteInt(uint8_t n)
{
switch (n) {
case 1U:
#if defined(STM32_USART1_HOST)
return m_USART1.availableForWrite();
#elif defined(STM32_USB_HOST)
//return usbserial.availableForWrite();
return 1U; // we don't have this -- so fake it
#endif
case 3U:
return m_USART2.availableForWrite();
default:
@ -336,20 +282,13 @@ int SerialPort::availableForWriteInt(uint8_t n)
}
}
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/// <returns></returns>
/* */
uint8_t SerialPort::readInt(uint8_t n)
{
switch (n) {
case 1U:
#if defined(STM32_USART1_HOST)
return m_USART1.read();
#elif defined(STM32_USB_HOST)
return usbserial.read();
#endif
case 3U:
return m_USART2.read();
default:
@ -358,26 +297,15 @@ uint8_t SerialPort::readInt(uint8_t n)
}
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/// <param name="data"></param>
/// <param name="length"></param>
/// <param name="flush"></param>
/* */
void SerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush)
{
switch (n) {
case 1U:
#if defined(STM32_USART1_HOST)
m_USART1.write(data, length);
if (flush)
m_USART1.flush();
#elif defined(STM32_USB_HOST)
usbserial.write(data, length);
if (flush)
usbserial.flush();
#endif
break;
case 3U:
m_USART2.write(data, length);

@ -1,33 +1,13 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2017 Andy Uribe, CA6JAU
*
*/
#include "Utils.h"
// ---------------------------------------------------------------------------
@ -45,11 +25,15 @@ const uint8_t BITS_TABLE[] = {
// Global Functions
// ---------------------------------------------------------------------------
/* Returns the count of bits in the passed 8 byte value. */
uint8_t countBits8(uint8_t bits)
{
return BITS_TABLE[bits];
}
/* Returns the count of bits in the passed 16 byte value. */
uint8_t countBits16(uint16_t bits)
{
uint8_t* p = (uint8_t*)&bits;
@ -59,6 +43,8 @@ uint8_t countBits16(uint16_t bits)
return n;
}
/* Returns the count of bits in the passed 32 byte value. */
uint8_t countBits32(uint32_t bits)
{
uint8_t* p = (uint8_t*)&bits;
@ -70,6 +56,8 @@ uint8_t countBits32(uint32_t bits)
return n;
}
/* Returns the count of bits in the passed 64 byte value. */
uint8_t countBits64(uint64_t bits)
{
uint8_t* p = (uint8_t*)&bits;

@ -1,33 +1,19 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2017 Andy Uribe, CA6JAU
*
*/
/**
* @file Utils.h
* @ingroup hotspot_fw
* @file Utils.cpp
* @ingroup hotspot_fw
*/
#if !defined(__UTILS_H__)
#define __UTILS_H__
@ -45,9 +31,29 @@
// Global Functions
// ---------------------------------------------------------------------------
/**
* @brief Returns the count of bits in the passed 8 byte value.
* @param bits uint8_t to count bits for.
* @returns uint8_t Count of bits in passed value.
*/
DSP_FW_API uint8_t countBits8(uint8_t bits);
/**
* @brief Returns the count of bits in the passed 16 byte value.
* @param bits uint16_t to count bits for.
* @returns uint8_t Count of bits in passed value.
*/
DSP_FW_API uint8_t countBits16(uint16_t bits);
/**
* @brief Returns the count of bits in the passed 32 byte value.
* @param bits uint32_t to count bits for.
* @returns uint8_t Count of bits in passed value.
*/
DSP_FW_API uint8_t countBits32(uint32_t bits);
/**
* @brief Returns the count of bits in the passed 64 byte value.
* @param bits ulong64_t to count bits for.
* @returns uint8_t Count of bits in passed value.
*/
DSP_FW_API uint8_t countBits64(ulong64_t bits);
#endif // __UTILS_H__

@ -1,34 +1,14 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2018,2019 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2015 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2018,2019 Andy Uribe, CA6JAU
*
*/
#include "Globals.h"
#include "dmr/CalDMR.h"
@ -40,42 +20,42 @@ using namespace dmr;
// Voice LC Header, CC: 1, srcID: 1, dstID: TG9
const uint8_t VH_1K[] = { 0x00U,
0x00U, 0x20U, 0x08U, 0x08U, 0x02U, 0x38U, 0x15U, 0x00U, 0x2CU, 0xA0U, 0x14U,
0x60U, 0x84U, 0x6DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xDEU, 0x30U, 0x30U,
0x01U, 0x10U, 0x01U, 0x40U, 0x03U, 0xC0U, 0x13U, 0xC1U, 0x1EU, 0x80U, 0x6FU };
0x00U, 0x20U, 0x08U, 0x08U, 0x02U, 0x38U, 0x15U, 0x00U, 0x2CU, 0xA0U, 0x14U,
0x60U, 0x84U, 0x6DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xDEU, 0x30U, 0x30U,
0x01U, 0x10U, 0x01U, 0x40U, 0x03U, 0xC0U, 0x13U, 0xC1U, 0x1EU, 0x80U, 0x6FU };
// Voice Term with LC, CC: 1, srcID: 1, dstID: TG9
const uint8_t VT_1K[] = { 0x00U,
0x00U, 0x4FU, 0x08U, 0xDCU, 0x02U, 0x88U, 0x15U, 0x78U, 0x2CU, 0xD0U, 0x14U,
0xC0U, 0x84U, 0xADU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD9U, 0x65U, 0x24U,
0x02U, 0x28U, 0x06U, 0x20U, 0x0FU, 0x80U, 0x1BU, 0xC1U, 0x07U, 0x80U, 0x5CU };
0x00U, 0x4FU, 0x08U, 0xDCU, 0x02U, 0x88U, 0x15U, 0x78U, 0x2CU, 0xD0U, 0x14U,
0xC0U, 0x84U, 0xADU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD9U, 0x65U, 0x24U,
0x02U, 0x28U, 0x06U, 0x20U, 0x0FU, 0x80U, 0x1BU, 0xC1U, 0x07U, 0x80U, 0x5CU };
// Voice LC MS Header, CC: 1, srcID: 1, dstID: TG9
const uint8_t VH_DMO1K[] = { 0x00U,
0x00U, 0x20U, 0x08U, 0x08U, 0x02U, 0x38U, 0x15U, 0x00U, 0x2CU, 0xA0U, 0x14U,
0x60U, 0x84U, 0x6DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x7EU, 0x30U, 0x30U,
0x01U, 0x10U, 0x01U, 0x40U, 0x03U, 0xC0U, 0x13U, 0xC1U, 0x1EU, 0x80U, 0x6FU };
0x00U, 0x20U, 0x08U, 0x08U, 0x02U, 0x38U, 0x15U, 0x00U, 0x2CU, 0xA0U, 0x14U,
0x60U, 0x84U, 0x6DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x7EU, 0x30U, 0x30U,
0x01U, 0x10U, 0x01U, 0x40U, 0x03U, 0xC0U, 0x13U, 0xC1U, 0x1EU, 0x80U, 0x6FU };
// Voice Term MS with LC, CC: 1, srcID: 1, dstID: TG9
const uint8_t VT_DMO1K[] = { 0x00U,
0x00U, 0x4FU, 0x08U, 0xDCU, 0x02U, 0x88U, 0x15U, 0x78U, 0x2CU, 0xD0U, 0x14U,
0xC0U, 0x84U, 0xADU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x79U, 0x65U, 0x24U,
0x02U, 0x28U, 0x06U, 0x20U, 0x0FU, 0x80U, 0x1BU, 0xC1U, 0x07U, 0x80U, 0x5CU };
0x00U, 0x4FU, 0x08U, 0xDCU, 0x02U, 0x88U, 0x15U, 0x78U, 0x2CU, 0xD0U, 0x14U,
0xC0U, 0x84U, 0xADU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x79U, 0x65U, 0x24U,
0x02U, 0x28U, 0x06U, 0x20U, 0x0FU, 0x80U, 0x1BU, 0xC1U, 0x07U, 0x80U, 0x5CU };
// Voice coding data + FEC, 1031 Hz Test Pattern
const uint8_t VOICE_1K[] = { 0x00U,
0xCEU, 0xA8U, 0xFEU, 0x83U, 0xACU, 0xC4U, 0x58U, 0x20U, 0x0AU, 0xCEU, 0xA8U,
0xFEU, 0x83U, 0xA0U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x0CU, 0xC4U, 0x58U,
0x20U, 0x0AU, 0xCEU, 0xA8U, 0xFEU, 0x83U, 0xACU, 0xC4U, 0x58U, 0x20U, 0x0AU };
0xCEU, 0xA8U, 0xFEU, 0x83U, 0xACU, 0xC4U, 0x58U, 0x20U, 0x0AU, 0xCEU, 0xA8U,
0xFEU, 0x83U, 0xA0U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x0CU, 0xC4U, 0x58U,
0x20U, 0x0AU, 0xCEU, 0xA8U, 0xFEU, 0x83U, 0xACU, 0xC4U, 0x58U, 0x20U, 0x0AU };
// Embedded LC: CC: 1, srcID: 1, dstID: TG9
const uint8_t SYNCEMB_1K[6][7] = {
{ 0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U }, // BS VOICE SYNC (audio seq 0)
{ 0x01U, 0x30U, 0x00U, 0x00U, 0x90U, 0x09U, 0x10U }, // EMB + Embedded LC1 (audio seq 1)
{ 0x01U, 0x70U, 0x00U, 0x90U, 0x00U, 0x07U, 0x40U }, // EMB + Embedded LC2 (audio seq 2)
{ 0x01U, 0x70U, 0x00U, 0x31U, 0x40U, 0x07U, 0x40U }, // EMB + Embedded LC3 (audio seq 3)
{ 0x01U, 0x50U, 0xA1U, 0x71U, 0xD1U, 0x70U, 0x70U }, // EMB + Embedded LC4 (audio seq 4)
{ 0x01U, 0x10U, 0x00U, 0x00U, 0x00U, 0x0EU, 0x20U } }; // EMB (audio seq 5)
{ 0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U }, // BS VOICE SYNC (audio seq 0)
{ 0x01U, 0x30U, 0x00U, 0x00U, 0x90U, 0x09U, 0x10U }, // EMB + Embedded LC1 (audio seq 1)
{ 0x01U, 0x70U, 0x00U, 0x90U, 0x00U, 0x07U, 0x40U }, // EMB + Embedded LC2 (audio seq 2)
{ 0x01U, 0x70U, 0x00U, 0x31U, 0x40U, 0x07U, 0x40U }, // EMB + Embedded LC3 (audio seq 3)
{ 0x01U, 0x50U, 0xA1U, 0x71U, 0xD1U, 0x70U, 0x70U }, // EMB + Embedded LC4 (audio seq 4)
{ 0x01U, 0x10U, 0x00U, 0x00U, 0x00U, 0x0EU, 0x20U } }; // EMB (audio seq 5)
// Embedded LC MS: CC: 1, srcID: 1, dstID: TG9
const uint8_t SYNCEMB_DMO1K[6][7] = {
@ -95,9 +75,8 @@ const uint8_t SHORTLC_1K[] = { 0x33U, 0x3AU, 0xA0U, 0x30U, 0x00U, 0x55U, 0xA6U,
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CalDMR class.
/// </summary>
/* Initializes a new instance of the CalDMR class. */
CalDMR::CalDMR() :
m_transmit(false),
m_state(DMRCAL1K_IDLE),
@ -109,9 +88,8 @@ CalDMR::CalDMR() :
::memcpy(m_dmr1k, VOICE_1K, DMR_FRAME_LENGTH_BYTES + 1U);
}
/// <summary>
/// Process local state and transmit on the air interface.
/// </summary>
/* Process local state and transmit on the air interface. */
void CalDMR::process()
{
switch (m_modemState) {
@ -149,10 +127,8 @@ void CalDMR::process()
}
}
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/* */
void CalDMR::createData1k(uint8_t n)
{
for (uint8_t i = 0; i < 5U; i++)
@ -164,10 +140,8 @@ void CalDMR::createData1k(uint8_t n)
m_dmr1k[20U] |= SYNCEMB_1K[n][6] & 0xF0U;
}
/// <summary>
///
/// </summary>
/// <param name="n"></param>
/* */
void CalDMR::createDataDMO1k(uint8_t n)
{
for (uint8_t i = 0; i < 5U; i++)
@ -179,9 +153,8 @@ void CalDMR::createDataDMO1k(uint8_t n)
m_dmr1k[20U] |= SYNCEMB_DMO1K[n][6] & 0xF0U;
}
/// <summary>
///
/// </summary>
/* */
void CalDMR::dmr1kcal()
{
#if defined(DUPLEX)
@ -230,9 +203,8 @@ void CalDMR::dmr1kcal()
#endif
}
/// <summary>
///
/// </summary>
/* */
void CalDMR::dmrDMO1kcal()
{
dmrDMOTX.process();
@ -268,12 +240,8 @@ void CalDMR::dmrDMO1kcal()
}
}
/// <summary>
/// Write DMR calibration state.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write DMR calibration state. */
uint8_t CalDMR::write(const uint8_t* data, uint8_t length)
{
if (length != 1U)

@ -1,34 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2015 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2018 Andy Uribe, CA6JAU
*
*/
/**
* @file CalDMR.h
* @ingroup dmr_hfw
* @file CalDMR.cpp
* @ingroup dmr_hfw
*/
#if !defined(__CAL_DMR_H__)
#define __CAL_DMR_H__
@ -41,43 +27,69 @@ namespace dmr
// Constants
// ---------------------------------------------------------------------------
enum DMRCAL1K {
DMRCAL1K_IDLE,
DMRCAL1K_VH,
DMRCAL1K_VOICE,
DMRCAL1K_VT,
DMRCAL1K_WAIT
/**
* @brief Calibration States
* @ingroup dmr_mfw
*/
enum DMR1KCAL {
DMRCAL1K_IDLE, //! Idle
DMRCAL1K_VH, //! Voice Header
DMRCAL1K_VOICE, //! Voice
DMRCAL1K_VT, //! Voice Terminator
DMRCAL1K_WAIT //!
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements logic for DMR calibration mode.
// ---------------------------------------------------------------------------
/**
* @brief Implements logic for DMR calibration mode.
* @ingroup dmr_hfw
*/
class DSP_FW_API CalDMR {
public:
/// <summary>Initializes a new instance of the CalDMR class.</summary>
/**
* @brief Initializes a new instance of the CalDMR class.
*/
CalDMR();
/// <summary>Process local state and transmit on the air interface.</summary>
/**
* @brief Process local state and transmit on the air interface.
*/
void process();
/// <summary></summary>
/**
* @brief
* @param n
*/
void createData1k(uint8_t n);
/// <summary></summary>
/**
* @brief
* @param n
*/
void createDataDMO1k(uint8_t n);
/// <summary></summary>
/**
* @brief
*/
void dmr1kcal();
/// <summary></summary>
/**
* @brief
*/
void dmrDMO1kcal();
/// <summary>Write DMR calibration state.</summary>
/**
* @brief Write DMR calibration state.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t write(const uint8_t* data, uint8_t length);
private:
bool m_transmit;
DMRCAL1K m_state;
DMR1KCAL m_state;
uint32_t m_frameStart;
uint8_t m_dmr1k[DMR_FRAME_LENGTH_BYTES + 1U];

@ -1,34 +1,14 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2021 by Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2016 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "dmr/DMRDMORX.h"
#include "dmr/DMRSlotType.h"
@ -54,9 +34,8 @@ const uint8_t CONTROL_DATA = 0x40U;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the DMRDMORX class.
/// </summary>
/* Initializes a new instance of the DMRDMORX class. */
DMRDMORX::DMRDMORX() :
m_bitBuffer(0x00U),
m_buffer(),
@ -74,9 +53,8 @@ DMRDMORX::DMRDMORX() :
/* stub */
}
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
/* Helper to reset data values to defaults. */
void DMRDMORX::reset()
{
m_syncPtr = 0U;
@ -87,10 +65,8 @@ void DMRDMORX::reset()
m_endPtr = NOENDPTR;
}
/// <summary>
/// Sample DMR bits from the air interface.
/// </summary>
/// <param name="bit"></param>
/* Sample DMR bits from the air interface. */
void DMRDMORX::databit(bool bit)
{
_WRITE_BIT(m_buffer, m_dataPtr, bit);
@ -141,7 +117,7 @@ void DMRDMORX::databit(bool bit)
switch (dataType) {
case DT_DATA_HEADER:
DEBUG2("DMRDMORX: databit(): data header found pos", m_syncPtr);
DEBUG2("DMRDMORX::databit() data header found pos", m_syncPtr);
writeRSSIData(frame);
m_state = DMORXS_DATA;
m_type = 0x00U;
@ -150,32 +126,32 @@ void DMRDMORX::databit(bool bit)
case DT_RATE_34_DATA:
case DT_RATE_1_DATA:
if (m_state == DMORXS_DATA) {
DEBUG2("DMRDMORX: databit(): data payload found pos", m_syncPtr);
DEBUG2("DMRDMORX::databit() data payload found pos", m_syncPtr);
writeRSSIData(frame);
m_type = dataType;
}
break;
case DT_VOICE_LC_HEADER:
DEBUG2("DMRDMORX: databit(): voice header found pos", m_syncPtr);
DEBUG2("DMRDMORX::databit() voice header found pos", m_syncPtr);
writeRSSIData(frame);
m_state = DMORXS_VOICE;
break;
case DT_VOICE_PI_HEADER:
if (m_state == DMORXS_VOICE) {
DEBUG2("DMRDMORX: databit(): voice pi header found pos", m_syncPtr);
DEBUG2("DMRDMORX::databit() voice pi header found pos", m_syncPtr);
writeRSSIData(frame);
}
m_state = DMORXS_VOICE;
break;
case DT_TERMINATOR_WITH_LC:
if (m_state == DMORXS_VOICE) {
DEBUG2("DMRDMORX: databit(): voice terminator found pos", m_syncPtr);
DEBUG2("DMRDMORX::databit() voice terminator found pos", m_syncPtr);
writeRSSIData(frame);
reset();
}
break;
default: // DT_CSBK
DEBUG2("DMRDMORX: databit(): csbk found pos", m_syncPtr);
DEBUG2("DMRDMORX::databit() csbk found pos", m_syncPtr);
writeRSSIData(frame);
reset();
break;
@ -184,7 +160,7 @@ void DMRDMORX::databit(bool bit)
}
else if (m_control == CONTROL_VOICE) {
// Voice sync
DEBUG2("DMRDMORX: databit(): voice sync found pos", m_syncPtr);
DEBUG2("DMRDMORX::databit() voice sync found pos", m_syncPtr);
writeRSSIData(frame);
m_state = DMORXS_VOICE;
@ -195,7 +171,7 @@ void DMRDMORX::databit(bool bit)
if (m_state != DMORXS_NONE) {
m_syncCount++;
if (m_syncCount >= MAX_SYNC_LOST_FRAMES) {
DEBUG1("DMRDMORX: databit(): sync timeout, lost lock");
DEBUG1("DMRDMORX::databit() sync timeout, lost lock");
serial.writeDMRLost(true);
reset();
}
@ -231,10 +207,8 @@ void DMRDMORX::databit(bool bit)
io.setDecode(m_state != DMORXS_NONE);
}
/// <summary>
/// Sets the DMR color code.
/// </summary>
/// <param name="colorCode">Color code.</param>
/* Sets the DMR color code. */
void DMRDMORX::setColorCode(uint8_t colorCode)
{
m_colorCode = colorCode;
@ -244,9 +218,8 @@ void DMRDMORX::setColorCode(uint8_t colorCode)
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Frame synchronization correlator.
/// </summary>
/* Frame synchronization correlator. */
void DMRDMORX::correlateSync()
{
// unpack sync bytes
@ -265,11 +238,11 @@ void DMRDMORX::correlateSync()
for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++)
errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_DATA_SYNC_BYTES[i]);
DEBUG2("DMRDMORX: correlateSync(): correlateSync errs", errs);
DEBUG2("DMRDMORX::correlateSync() sync errs", errs);
DEBUG4("DMRDMORX: correlateSync(): sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("DMRDMORX: correlateSync(): sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG2("DMRDMORX: correlateSync(): sync [b6]", sync[6]);
DEBUG4("DMRDMORX::correlateSync() sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("DMRDMORX::correlateSync() sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG2("DMRDMORX::correlateSync() sync [b6]", sync[6]);
m_control = CONTROL_DATA;
m_syncPtr = m_dataPtr;
@ -282,18 +255,18 @@ void DMRDMORX::correlateSync()
if (m_endPtr >= DMO_BUFFER_LENGTH_BITS)
m_endPtr -= DMO_BUFFER_LENGTH_BITS;
DEBUG4("DMRDMORX: correlateSync(): dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
DEBUG4("DMRDMORX::correlateSync() dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
} else if ((countBits64((m_bitBuffer & DMR_SYNC_BITS_MASK) ^ DMR_MS_VOICE_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) ||
(countBits64((m_bitBuffer & DMR_SYNC_BITS_MASK) ^ DMR_S2_VOICE_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS)) {
uint8_t errs = 0U;
for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++)
errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_VOICE_SYNC_BYTES[i]);
DEBUG2("DMRDMORX: correlateSync(): correlateSync errs", errs);
DEBUG2("DMRDMORX::correlateSync() correlateSync errs", errs);
DEBUG4("DMRDMORX: correlateSync(): sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("DMRDMORX: correlateSync(): sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG2("DMRDMORX: correlateSync(): sync [b6]", sync[6]);
DEBUG4("DMRDMORX::correlateSync() sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("DMRDMORX::correlateSync() sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG2("DMRDMORX::correlateSync() sync [b6]", sync[6]);
m_control = CONTROL_VOICE;
m_syncPtr = m_dataPtr;
@ -306,16 +279,12 @@ void DMRDMORX::correlateSync()
if (m_endPtr >= DMO_BUFFER_LENGTH_BITS)
m_endPtr -= DMO_BUFFER_LENGTH_BITS;
DEBUG4("DMRDMORX: correlateSync(): dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
DEBUG4("DMRDMORX::correlateSync() dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
}
}
/// <summary>
///
/// </summary>
/// <param name="start"></param>
/// <param name="count"></param>
/// <param name="buffer"></param>
/* */
void DMRDMORX::bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer)
{
for (uint8_t i = 0U; i < count; i++) {
@ -362,10 +331,8 @@ void DMRDMORX::bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer)
}
}
/// <summary>
///
/// </summary>
/// <param name="frame"></param>
/* */
void DMRDMORX::writeRSSIData(uint8_t* frame)
{
#if defined(SEND_RSSI_DATA)
@ -379,4 +346,3 @@ void DMRDMORX::writeRSSIData(uint8_t* frame)
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
}

@ -1,34 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2021 by Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file DMRDMORX.h
* @ingroup dmr_hfw
* @file DMRDMORX.cpp
* @ingroup dmr_hfw
*/
#if !defined(__DMR_DMO_RX_H__)
#define __DMR_DMO_RX_H__
@ -43,29 +29,46 @@ namespace dmr
const uint16_t DMO_BUFFER_LENGTH_BITS = 576U;
/**
* @brief DMR DMO Receiver State
* @ingroup dmr_hfw
*/
enum DMORX_STATE {
DMORXS_NONE,
DMORXS_VOICE,
DMORXS_DATA
DMORXS_NONE, //! None
DMORXS_VOICE, //! Voice Data
DMORXS_DATA //! PDU Data
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements receiver logic for DMR DMO mode operation.
// ---------------------------------------------------------------------------
/**
* @brief Implements receiver logic for DMR DMO mode operation.
* @ingroup dmr_hfw
*/
class DSP_FW_API DMRDMORX {
public:
/// <summary>Initializes a new instance of the DMRDMORX class.</summary>
/**
* @brief Initializes a new instance of the DMRDMORX class.
*/
DMRDMORX();
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset();
/// <summary>Sample DMR bits from the air interface.</summary>
/**
* @brief Sample DMR bits from the air interface.
* @param bit
*/
void databit(bool bit);
/// <summary>Sets the DMR color code.</summary>
/**
* @brief Sets the DMR color code.
* @param colorCode
*/
void setColorCode(uint8_t colorCode);
private:
@ -90,12 +93,22 @@ namespace dmr
uint8_t m_type;
/// <summary>Frame synchronization correlator.</summary>
/**
* @brief Frame synchronization correlator.
*/
void correlateSync();
/// <summary></summary>
/**
* @brief
* @param start
* @param count
* @param buffer
*/
void bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer);
/// <summary></summary>
/**
* @brief
* @param frame
*/
void writeRSSIData(uint8_t* frame);
};
} // namespace dmr

@ -1,35 +1,15 @@
/**
* Digital Voice Modem - DSP Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware
*
*/
//
// Based on code from the MMDVM project. (https://github.com/g4klx/MMDVM)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2021 by Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2016 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2016,2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "dmr/DMRSlotType.h"
@ -50,9 +30,8 @@ const uint8_t PR_FILL[] =
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the DMRDMOTX class.
/// </summary>
/* Initializes a new instance of the DMRDMOTX class. */
DMRDMOTX::DMRDMOTX() :
m_fifo(DMR_TX_BUFFER_LEN),
m_poBuffer(),
@ -63,9 +42,8 @@ DMRDMOTX::DMRDMOTX() :
/* stub */
}
/// <summary>
/// Process local buffer and transmit on the air interface.
/// </summary>
/* Process local buffer and transmit on the air interface. */
void DMRDMOTX::process()
{
if (m_poLen == 0U && m_fifo.getData() > 0U) {
@ -85,7 +63,6 @@ void DMRDMOTX::process()
m_poLen = 72U;
}
DEBUG2("DMRDMOTX: process(): poLen", m_poLen);
m_poPtr = 0U;
}
@ -108,19 +85,15 @@ void DMRDMOTX::process()
}
}
/// <summary>
/// Write data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write data to the local buffer. */
uint8_t DMRDMOTX::writeData(const uint8_t* data, uint8_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return RSN_ILLEGAL_LENGTH;
uint16_t space = m_fifo.getSpace();
DEBUG3("DMRDMOTX: writeData(): dataLength/fifoLength", length, space);
DEBUG3("DMRDMOTX::writeData() dataLength/fifoLength", length, space);
if (space < DMR_FRAME_LENGTH_BYTES)
return RSN_RINGBUFF_FULL;
@ -130,24 +103,28 @@ uint8_t DMRDMOTX::writeData(const uint8_t* data, uint8_t length)
return RSN_OK;
}
/// <summary>
/// Sets the FDMA preamble count.
/// </summary>
/// <param name="preambleCnt">Count of preambles.</param>
/* Sets the FDMA preamble count. */
void DMRDMOTX::setPreambleCount(uint8_t preambleCnt)
{
uint32_t preambles = (uint32_t)((float)preambleCnt / 0.2083F);
m_preambleCnt = DMRDMO_FIXED_DELAY + preambles;
// clamp preamble count to 250ms maximum
if (m_preambleCnt > 1200U)
m_preambleCnt = 1200U;
// clamp preamble count to 16ms maximum
if (m_preambleCnt > 80U)
m_preambleCnt = 80U;
}
/* Helper to resize the FIFO buffer. */
void DMRDMOTX::resizeBuffer(uint16_t size)
{
m_fifo.reset();
m_fifo.reinitialize(size);
}
/// <summary>
/// Helper to get how much space the ring buffer has for samples.
/// </summary>
/// <returns></returns>
/* Helper to get how much space the ring buffer has for samples. */
uint16_t DMRDMOTX::getSpace() const
{
return m_fifo.getSpace() / (DMR_FRAME_LENGTH_BYTES + 2U);
@ -157,10 +134,8 @@ uint16_t DMRDMOTX::getSpace() const
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/// <param name="c"></param>
/* Helper to write a raw byte to the DAC. */
void DMRDMOTX::writeByte(uint8_t c)
{
uint8_t bit;

@ -1,35 +1,21 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2021 by Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2016,2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file DMRDMOTX.h
* @ingroup dmr_hfw
* @file DMRDMOTX.cpp
* @ingroup dmr_hfw
*/
#if !defined(__DMR_DMO_TX_H__)
#define __DMR_DMO_TX_H__
@ -48,24 +34,48 @@ namespace dmr
// ---------------------------------------------------------------------------
// Class Declaration
// Implements transmitter logic for DMR DMO mode operation.
// ---------------------------------------------------------------------------
/**
* @brief Implements transmitter logic for DMR DMO mode operation.
* @ingroup dmr_hfw
*/
class DSP_FW_API DMRDMOTX {
public:
/// <summary>Initializes a new instance of the DMRDMOTX class.</summary>
/**
* @brief Initializes a new instance of the DMRDMOTX class.
*/
DMRDMOTX();
/// <summary>Process local buffer and transmit on the air interface.</summary>
/**
* @brief Process local buffer and transmit on the air interface.
*/
void process();
/// <summary>Write data to the local buffer.</summary>
/**
* @brief Write data to the local buffer.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t writeData(const uint8_t* data, uint8_t length);
/// <summary>Sets the FDMA preamble count.</summary>
/**
* @brief Sets the FDMA preamble count.
* @param preambleCnt FDMA preamble count.
*/
void setPreambleCount(uint8_t preambleCnt);
/// <summary>Helper to get how much space the ring buffer has for samples.</summary>
/**
* @brief Helper to resize the FIFO buffer.
* @param size
*/
void resizeBuffer(uint16_t size);
/**
* @brief Helper to get how much space the ring buffer has for samples.
* @returns uint8_t Amount of space in ring buffer for samples.
*/
uint16_t getSpace() const;
private:
@ -77,7 +87,10 @@ namespace dmr
uint32_t m_preambleCnt;
/// <summary></summary>
/**
* @brief Helper to write a raw byte to the DAC.
* @param c Byte.
*/
void writeByte(uint8_t c);
};
} // namespace dmr

@ -1,32 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* 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
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2016 Jonathan Naylor, G4KLX
*
*/
/**
* @defgroup dmr_hfw Digital Mobile Radio
* @brief Implementation for the ETSI TS-102 Digital Mobile Radio (DMR) standard.
* @ingroup hotspot_fw
*
* @file DMRDefines.h
* @ingroup dmr_hfw
*/
#if !defined(__DMR_DEFINES_H__)
#define __DMR_DEFINES_H__
@ -38,6 +26,11 @@ namespace dmr
// Constants
// ---------------------------------------------------------------------------
/**
* @addtogroup dmr_hfw
* @{
*/
const uint32_t DMR_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const uint32_t DMR_FRAME_LENGTH_BYTES = 33U;
@ -126,7 +119,8 @@ namespace dmr
const int8_t DMR_MS_VOICE_SYNC_SYMBOLS_VALUES[] = { +3, -3, -3, -3, +3, -3, -3, +3, +3, +3, -3, +3, -3, +3, +3, +3, +3, -3, -3, +3, -3, -3, -3, +3 };
const uint32_t DMR_TX_BUFFER_LEN = 538U; // 538 = DMR_FRAME_LENGTH_BYTES * 16 + 10 (BUFFER_LEN = DMR_FRAME_LENGTH_BYTES * NO_OF_FRAMES + 10)
// 505 = DMR_FRAME_LENGTH_BYTES * 15 + 10 (BUFFER_LEN = DMR_FRAME_LENGTH_BYTES * NO_OF_FRAMES + 10)
const uint32_t DMR_TX_BUFFER_LEN = 505U; // 15 frames + pad
// Data Type(s)
const uint8_t DT_VOICE_PI_HEADER = 0U;
@ -138,6 +132,8 @@ namespace dmr
const uint8_t DT_RATE_34_DATA = 8U;
const uint8_t DT_IDLE = 9U;
const uint8_t DT_RATE_1_DATA = 10U;
/** @} */
} // namespace dmr
#endif // __DMR_DEFINES_H__

@ -1,33 +1,13 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017,2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2017 Jonathan Naylor, G4KLX
* Copyright (C) 2017,2018 Andy Uribe, CA6JAU
*
*/
#include "Globals.h"
#include "dmr/DMRIdleRX.h"
#include "dmr/DMRSlotType.h"
@ -52,9 +32,8 @@ const uint8_t CONTROL_DATA = 0x40U;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the DMRIdleRX class.
/// </summary>
/* Initializes a new instance of the DMRIdleRX class. */
DMRIdleRX::DMRIdleRX() :
m_bitBuffer(0U),
m_buffer(),
@ -65,19 +44,16 @@ DMRIdleRX::DMRIdleRX() :
/* stub */
}
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
/* Helper to reset data values to defaults. */
void DMRIdleRX::reset()
{
m_dataPtr = 0U;
m_endPtr = NOENDPTR;
}
/// <summary>
/// Sample DMR bits from the air interface.
/// </summary>
/// <param name="bit"></param>
/* Sample DMR bits from the air interface. */
void DMRIdleRX::databit(bool bit)
{
_WRITE_BIT(m_buffer, m_dataPtr, bit);
@ -91,7 +67,7 @@ void DMRIdleRX::databit(bool bit)
if (m_endPtr >= DMR_IDLE_LENGTH_BITS)
m_endPtr -= DMR_IDLE_LENGTH_BITS;
DEBUG3("DMRIdleRx: databit(): dataPtr/endPtr", m_dataPtr, m_endPtr);
DEBUG3("DMRIdleRx::databit() dataPtr/endPtr", m_dataPtr, m_endPtr);
}
if (m_dataPtr == m_endPtr) {
@ -120,10 +96,8 @@ void DMRIdleRX::databit(bool bit)
m_dataPtr = 0U;
}
/// <summary>
/// Sets the DMR color code.
/// </summary>
/// <param name="colorCode">Color code.</param>
/* Sets the DMR color code. */
void DMRIdleRX::setColorCode(uint8_t colorCode)
{
m_colorCode = colorCode;
@ -133,12 +107,8 @@ void DMRIdleRX::setColorCode(uint8_t colorCode)
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/// <param name="start"></param>
/// <param name="count"></param>
/// <param name="buffer"></param>
/* */
void DMRIdleRX::bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer)
{
for (uint8_t i = 0U; i < count; i++) {

@ -1,33 +1,19 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015 by Jonathan Naylor G4KLX
* Copyright (C) 2017,2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015 Jonathan Naylor, G4KLX
* Copyright (C) 2017,2018 Andy Uribe, CA6JAU
*
*/
/**
* @file DMRIdleRX.h
* @ingroup dmr_mfw
* @file DMRIdleRX.cpp
* @ingroup dmr_mfw
*/
#if !defined(__DMR_IDLE_RX_H__)
#define __DMR_IDLE_RX_H__
@ -46,21 +32,34 @@ namespace dmr
// ---------------------------------------------------------------------------
// Class Declaration
// Implements receiver logic for idle DMR mode operation.
// ---------------------------------------------------------------------------
/**
* @brief Implements receiver logic for idle DMR mode operation.
* @ingroup dmr_hfw
*/
class DSP_FW_API DMRIdleRX {
public:
/// <summary>Initializes a new instance of the DMRIdleRX class.</summary>
/**
* @brief Initializes a new instance of the DMRIdleRX class.
*/
DMRIdleRX();
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset();
/// <summary>Sample DMR bits from the air interface.</summary>
/**
* @brief Sample DMR bits from the air interface.
* @param bit
*/
void databit(bool bit);
/// <summary>Sets the DMR color code.</summary>
/**
* @brief Sets the DMR color code.
* @param colorCode
*/
void setColorCode(uint8_t colorCode);
private:
@ -72,11 +71,15 @@ namespace dmr
uint8_t m_colorCode;
/// <summary></summary>
/**
* @brief
* @param start
* @param count
* @param buffer
*/
void bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer);
};
} // namespace dmr
#endif // DUPLEX
#endif // __DMR_IDLE_RX_H__

@ -1,34 +1,14 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "dmr/DMRRX.h"
@ -40,9 +20,8 @@ using namespace dmr;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the DMRRX class.
/// </summary>
/* Initializes a new instance of the DMRRX class. */
DMRRX::DMRRX() :
m_slot1RX(false),
m_slot2RX(true)
@ -51,19 +30,16 @@ DMRRX::DMRRX() :
}
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
/* Helper to reset data values to defaults. */
void DMRRX::reset()
{
m_slot1RX.reset();
m_slot2RX.reset();
}
/// <summary>
/// Sample DMR bits from the air interface.
/// </summary>
/// <param name="bit"></param>
/* Sample DMR bits from the air interface. */
void DMRRX::databit(bool bit, const uint8_t control)
{
bool dcd1 = false;
@ -86,20 +62,16 @@ void DMRRX::databit(bool bit, const uint8_t control)
io.setDecode(dcd1 || dcd2);
}
/// <summary>
/// Sets the DMR color code.
/// </summary>
/// <param name="colorCode">Color code.</param>
/* Sets the DMR color code. */
void DMRRX::setColorCode(uint8_t colorCode)
{
m_slot1RX.setColorCode(colorCode);
m_slot2RX.setColorCode(colorCode);
}
/// <summary>
/// Sets the number of samples to delay before processing.
/// </summary>
/// <param name="delay">Number of samples to delay.</param>
/* Sets the number of samples to delay before processing. */
void DMRRX::setRxDelay(uint8_t delay)
{
m_slot1RX.setRxDelay(delay);

@ -1,34 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file DMRRX.h
* @ingroup dmr_hfw
* @file DMRRX.cpp
* @ingroup dmr_hfw
*/
#if !defined(__DMR_RX_H__)
#define __DMR_RX_H__
@ -41,23 +27,40 @@ namespace dmr
{
// ---------------------------------------------------------------------------
// Class Declaration
// Implements receiver logic for duplex DMR mode operation.
// ---------------------------------------------------------------------------
/**
* @brief Implements receiver logic for duplex DMR mode operation.
* @ingroup dmr_hfw
*/
class DSP_FW_API DMRRX {
public:
/// <summary>Initializes a new instance of the DMRRX class.</summary>
/**
* @brief Initializes a new instance of the DMRRX class.
*/
DMRRX();
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset();
/// <summary>Sample DMR bits from the air interface.</summary>
/**
* @brief Sample DMR bits from the air interface.
* @param bit
* @param[in] control
*/
void databit(bool bit, const uint8_t control);
/// <summary>Sets the DMR color code.</summary>
/**
* @brief Sets the DMR color code.
* @param colorCode
*/
void setColorCode(uint8_t colorCode);
/// <summary>Sets the number of samples to delay before processing.</summary>
/**
* @brief Sets the number of samples to delay before processing.
* @param delay
*/
void setRxDelay(uint8_t delay);
private:
@ -67,5 +70,4 @@ namespace dmr
} // namespace dmr
#endif // DUPLEX
#endif // __DMR_RX_H__

@ -1,34 +1,14 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2017 Jonathan Naylor, G4KLX
* Copyright (C) 2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "dmr/DMRSlotRX.h"
#include "dmr/DMRSlotType.h"
@ -56,11 +36,10 @@ const uint8_t CONTROL_DATA = 0x40U;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the DMRSlotRX class.
/// </summary>
/* Initializes a new instance of the DMRSlotRX class. */
DMRSlotRX::DMRSlotRX(bool slot) :
m_slot(false),
m_slot(slot),
m_bitBuffer(0x00U),
m_buffer(),
m_dataPtr(0U),
@ -79,9 +58,8 @@ DMRSlotRX::DMRSlotRX(bool slot) :
/* stub */
}
/// <summary>
/// Helper to set data values for start of Rx.
/// </summary>
/* Helper to set data values for start of Rx. */
void DMRSlotRX::start()
{
m_dataPtr = 0U;
@ -89,28 +67,20 @@ void DMRSlotRX::start()
m_control = CONTROL_NONE;
}
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
/* Helper to reset data values to defaults. */
void DMRSlotRX::reset()
{
m_syncPtr = 0U;
m_dataPtr = 0U;
m_delayPtr = 0U;
m_bitBuffer = 0U;
m_control = CONTROL_NONE;
m_syncCount = 0U;
m_state = DMRRXS_NONE;
m_startPtr = 0U;
m_endPtr = NOENDPTR;
resetSlot();
}
/// <summary>
/// Sample DMR bits from the air interface.
/// </summary>
/// <param name="bit"></param>
/* Sample DMR bits from the air interface. */
bool DMRSlotRX::databit(bool bit)
{
uint16_t min, max;
@ -171,7 +141,7 @@ bool DMRSlotRX::databit(bool bit)
switch (dataType) {
case DT_DATA_HEADER:
DEBUG3("DMRSlotRX: databit(): data header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
DEBUG3("DMRSlotRX::databit() data header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_DATA;
m_type = 0x00U;
@ -180,33 +150,33 @@ bool DMRSlotRX::databit(bool bit)
case DT_RATE_34_DATA:
case DT_RATE_1_DATA:
if (m_state == DMRRXS_DATA) {
DEBUG3("DMRSlotRX: databit(): data payload found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
DEBUG3("DMRSlotRX::databit() data payload found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_type = dataType;
}
break;
case DT_VOICE_LC_HEADER:
DEBUG3("DMRSlotRX: databit(): voice header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
DEBUG3("DMRSlotRX::databit() voice header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_VOICE;
break;
case DT_VOICE_PI_HEADER:
if (m_state == DMRRXS_VOICE) {
DEBUG3("DMRSlotRX: databit(): voice pi header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
DEBUG3("DMRSlotRX::databit() voice pi header found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
}
m_state = DMRRXS_VOICE;
break;
case DT_TERMINATOR_WITH_LC:
if (m_state == DMRRXS_VOICE) {
DEBUG3("DMRSlotRX: databit(): voice terminator found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
DEBUG3("DMRSlotRX::databit() voice terminator found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_NONE;
m_endPtr = NOENDPTR;
}
break;
default: // DT_CSBK
DEBUG3("DMRSlotRX: databit(): csbk found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
DEBUG3("DMRSlotRX::databit() csbk found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_NONE;
m_endPtr = NOENDPTR;
@ -216,7 +186,7 @@ bool DMRSlotRX::databit(bool bit)
}
else if (m_control == CONTROL_VOICE) {
// Voice sync
DEBUG3("DMRSlotRX: databit(): voice sync found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
DEBUG3("DMRSlotRX::databit() voice sync found slot/pos", m_slot ? 2U : 1U, m_syncPtr);
writeRSSIData(frame);
m_state = DMRRXS_VOICE;
m_syncCount = 0U;
@ -226,10 +196,9 @@ bool DMRSlotRX::databit(bool bit)
if (m_state != DMRRXS_NONE) {
m_syncCount++;
if (m_syncCount >= MAX_SYNC_LOST_FRAMES) {
DEBUG1("DMRSlotRX: databit(): sync timeout, lost lock");
DEBUG1("DMRSlotRX::databit() sync timeout, lost lock");
serial.writeDMRLost(m_slot);
m_state = DMRRXS_NONE;
m_endPtr = NOENDPTR;
resetSlot();
}
}
@ -251,6 +220,9 @@ bool DMRSlotRX::databit(bool bit)
}
}
}
// end of this slot, reset some items for the next slot
m_control = CONTROL_NONE;
}
m_dataPtr++;
@ -260,19 +232,15 @@ bool DMRSlotRX::databit(bool bit)
return m_state != DMRRXS_NONE;
}
/// <summary>
/// Sets the DMR color code.
/// </summary>
/// <param name="colorCode">Color code.</param>
/* Sets the DMR color code. */
void DMRSlotRX::setColorCode(uint8_t colorCode)
{
m_colorCode = colorCode;
}
/// <summary>
/// Sets the number of samples to delay before processing.
/// </summary>
/// <param name="delay">Number of samples to delay.</param>
/* Sets the number of samples to delay before processing. */
void DMRSlotRX::setRxDelay(uint8_t delay)
{
m_delay = delay;
@ -282,10 +250,8 @@ void DMRSlotRX::setRxDelay(uint8_t delay)
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Frame synchronization correlator.
/// </summary>
/// <param name="first"></param>
/* Frame synchronization correlator. */
void DMRSlotRX::correlateSync()
{
// unpack sync bytes
@ -303,11 +269,11 @@ void DMRSlotRX::correlateSync()
for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++)
errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_DATA_SYNC_BYTES[i]);
DEBUG2("DMRSlotRX: correlateSync(): correlateSync errs", errs);
DEBUG2("DMRSlotRX::correlateSync() sync errs", errs);
DEBUG4("DMRSlotRX: correlateSync(): sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("DMRSlotRX: correlateSync(): sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG2("DMRSlotRX: correlateSync(): sync [b6]", sync[6]);
DEBUG4("DMRSlotRX::correlateSync() sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("DMRSlotRX::correlateSync() sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG2("DMRSlotRX::correlateSync() sync [b6]", sync[6]);
m_control = CONTROL_DATA;
m_syncPtr = m_dataPtr;
@ -320,17 +286,17 @@ void DMRSlotRX::correlateSync()
if (m_endPtr >= DMR_BUFFER_LENGTH_BITS)
m_endPtr -= DMR_BUFFER_LENGTH_BITS;
DEBUG4("DMRSlotRX: correlateSync(): dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
DEBUG4("DMRSlotRX::correlateSync() dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
} else if (countBits64((m_bitBuffer & DMR_SYNC_BITS_MASK) ^ DMR_MS_VOICE_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) {
uint8_t errs = 0U;
for (uint8_t i = 0U; i < DMR_SYNC_BYTES_LENGTH; i++)
errs += countBits8((sync[i] & DMR_SYNC_BYTES_MASK[i]) ^ DMR_MS_VOICE_SYNC_BYTES[i]);
DEBUG2("DMRSlotRX: correlateSync(): correlateSync errs", errs);
DEBUG2("DMRSlotRX::correlateSync() sync errs", errs);
DEBUG4("DMRSlotRX: correlateSync(): sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("DMRSlotRX: correlateSync(): sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG2("DMRSlotRX: correlateSync(): sync [b6]", sync[6]);
DEBUG4("DMRSlotRX::correlateSync() sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("DMRSlotRX::correlateSync() sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG2("DMRSlotRX::correlateSync() sync [b6]", sync[6]);
m_control = CONTROL_VOICE;
m_syncPtr = m_dataPtr;
@ -343,16 +309,27 @@ void DMRSlotRX::correlateSync()
if (m_endPtr >= DMR_BUFFER_LENGTH_BITS)
m_endPtr -= DMR_BUFFER_LENGTH_BITS;
DEBUG4("DMRSlotRX: correlateSync(): dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
DEBUG4("DMRSlotRX::correlateSync() dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
}
}
/// <summary>
///
/// </summary>
/// <param name="start"></param>
/// <param name="count"></param>
/// <param name="buffer"></param>
/* */
void DMRSlotRX::resetSlot()
{
m_syncPtr = 0U;
m_control = CONTROL_NONE;
m_syncCount = 0U;
m_state = DMRRXS_NONE;
m_startPtr = 0U;
m_endPtr = NOENDPTR;
m_type = 0U;
m_n = 0U;
}
/* */
void DMRSlotRX::bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer)
{
for (uint8_t i = 0U; i < count; i++) {
@ -399,10 +376,8 @@ void DMRSlotRX::bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer)
}
}
/// <summary>
///
/// </summary>
/// <param name="frame"></param>
/* */
void DMRSlotRX::writeRSSIData(uint8_t* frame)
{
#if defined(SEND_RSSI_DATA)

@ -1,34 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file DMRSlotRX.h
* @ingroup dmr_hfw
* @file DMRSlotRX.cpp
* @ingroup dmr_hfw
*/
#if !defined(__DMR_SLOT_RX_H__)
#define __DMR_SLOT_RX_H__
@ -45,33 +31,56 @@ namespace dmr
const uint16_t DMR_BUFFER_LENGTH_BITS = 576U;
/**
* @brief DMR Slot Receiver State
* @ingroup dmr_hfw
*/
enum DMRRX_STATE {
DMRRXS_NONE,
DMRRXS_VOICE,
DMRRXS_DATA
DMRRXS_NONE, //! None
DMRRXS_VOICE, //! Voice Data
DMRRXS_DATA //! PDU Data
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements receiver logic for DMR slots.
// ---------------------------------------------------------------------------
/**
* @brief Implements receiver logic for DMR slots.
* @ingroup dmr_hfw
*/
class DSP_FW_API DMRSlotRX {
public:
/// <summary>Initializes a new instance of the DMRSlotRX class.</summary>
/**
* @brief Initializes a new instance of the DMRSlotRX class.
* @param slot
*/
DMRSlotRX(bool slot);
/// <summary>Helper to set data values for start of Rx.</summary>
/**
* @brief Helper to set data values for start of Rx.
*/
void start();
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset();
/// <summary>Sample DMR bits from the air interface.</summary>
/**
* @brief Sample DMR bits from the air interface.
* @param bit
*/
bool databit(bool bit);
/// <summary>Sets the DMR color code.</summary>
/**
* @brief Sets the DMR color code.
* @param colorCode
*/
void setColorCode(uint8_t colorCode);
/// <summary>Sets the number of samples to delay before processing.</summary>
/**
* @brief Sets the number of samples to delay before processing.
* @param delay
*/
void setRxDelay(uint8_t delay);
@ -100,16 +109,29 @@ namespace dmr
uint8_t m_type;
/// <summary>Frame synchronization correlator.</summary>
/**
* @brief Frame synchronization correlator.
*/
void correlateSync();
/// <summary></summary>
/**
* @brief
*/
void resetSlot();
/**
* @brief
* @param start
* @param count
* @param buffer
*/
void bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer);
/// <summary></summary>
/**
* @brief
* @param frame
*/
void writeRSSIData(uint8_t* frame);
};
} // namespace dmr
#endif // DUPLEX
#endif // __DMR_SLOT_RX_H__

@ -1,32 +1,12 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* 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
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015 Jonathan Naylor, G4KLX
*
*/
#include "Globals.h"
#include "dmr/DMRSlotType.h"
@ -229,20 +209,15 @@ const uint32_t DECODING_TABLE_1987[] = {
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the DMRSlotType class.
/// </summary>
/* Initializes a new instance of the DMRSlotType class. */
DMRSlotType::DMRSlotType()
{
/* stub */
}
/// <summary>
/// Decodes DMR slot type.
/// </summary>
/// <param name="frame"></param>
/// <param name="colorCode"></param>
/// <param name="dataType"></param>
/* Decodes DMR slot type. */
void DMRSlotType::decode(const uint8_t* frame, uint8_t& colorCode, uint8_t& dataType) const
{
uint8_t slotType[3U];
@ -261,12 +236,8 @@ void DMRSlotType::decode(const uint8_t* frame, uint8_t& colorCode, uint8_t& data
dataType = (code >> 0) & 0x0FU;
}
/// <summary>
/// Encodes DMR slot type.
/// </summary>
/// <param name="colorCode"></param>
/// <param name="dataType"></param>
/// <param name="frame"></param>
/* Encodes DMR slot type. */
void DMRSlotType::encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) const
{
uint8_t slotType[3U];
@ -288,11 +259,8 @@ void DMRSlotType::encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) co
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
/* */
uint8_t DMRSlotType::decode2087(const uint8_t* data) const
{
uint32_t code = (data[0U] << 11) + (data[1U] << 3) + (data[2U] >> 5);
@ -305,20 +273,8 @@ uint8_t DMRSlotType::decode2087(const uint8_t* data) const
return code >> 11;
}
/// <summary>
///
/// </summary>
/// <remarks>
/// Compute the syndrome corresponding to the given pattern, i.e., the
/// remainder after dividing the pattern (when considering it as the vector
/// representation of a polynomial) by the generator polynomial, GENPOL.
/// In the program this pattern has several meanings: (1) pattern = infomation
/// bits, when constructing the encoding table; (2) pattern = error pattern,
/// when constructing the decoding table; and (3) pattern = received vector, to
/// obtain its syndrome in decoding.
/// </remarks>
/// <param name="pattern"></param>
/// <returns></returns>
/* */
uint32_t DMRSlotType::getSyndrome1987(uint32_t pattern) const
{
unsigned int aux = X18;

@ -1,32 +1,18 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* 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
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015 Jonathan Naylor, G4KLX
*
*/
/**
* @file DMRSlotType.h
* @ingroup dmr_hfw
* @file DMRSlotType.cpp
* @ingroup dmr_hfw
*/
#if !defined(__DMR_SLOT_TYPE_H__)
#define __DMR_SLOT_TYPE_H__
@ -36,23 +22,46 @@ namespace dmr
{
// ---------------------------------------------------------------------------
// Class Declaration
//
// ---------------------------------------------------------------------------
/**
* @brief Represents DMR slot type.
* @ingroup dmr_hfw
*/
class DSP_FW_API DMRSlotType {
public:
/// <summary>Initializes a new instance of the DMRSlotType class.</summary>
/**
* @brief Initializes a new instance of the DMRSlotType class.
*/
DMRSlotType();
/// <summary>Decodes DMR slot type.</summary>
/**
* @brief Decodes DMR slot type.
* @param[in] frame
* @param[out] colorCode
* @param[out] dataType
*/
void decode(const uint8_t* frame, uint8_t& colorCode, uint8_t& dataType) const;
/// <summary>Encodes DMR slot type.</summary>
/**
* @brief Encodes DMR slot type.
* @param colorCode
* @param dataType
* @param[out] frame
*/
void encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) const;
private:
/// <summary></summary>
/**
* @brief
* @param[in] data
* @returns uint8_t
*/
uint8_t decode2087(const uint8_t* data) const;
/// <summary></summary>
/**
* @brief
* @param pattern
* @returns uint32_t
*/
uint32_t getSyndrome1987(uint32_t pattern) const;
};
} // namespace dmr

@ -1,35 +1,15 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2017 by Andy Uribe CA6JAU
* Copyright (C) 2021-2022 by Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2009-2017 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2017 Andy Uribe, CA6JAU
* Copyright (C) 2021-2022 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "dmr/DMRSlotType.h"
@ -64,9 +44,8 @@ const uint32_t ABORT_COUNT = 6U;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the DMRTX class.
/// </summary>
/* Initializes a new instance of the DMRTX class. */
DMRTX::DMRTX() :
m_fifo(),
m_state(DMRTXSTATE_IDLE),
@ -97,9 +76,8 @@ DMRTX::DMRTX() :
m_abortCount[1U] = 0U;
}
/// <summary>
/// Process local buffer and transmit on the air interface.
/// </summary>
/* Process local buffer and transmit on the air interface. */
void DMRTX::process()
{
if (m_state == DMRTXSTATE_IDLE)
@ -131,8 +109,6 @@ void DMRTX::process()
m_state = DMRTXSTATE_SLOT1;
break;
}
DEBUG2("DMRTX: process(): poLen", m_poLen);
}
if (m_poLen > 0U) {
@ -156,19 +132,15 @@ void DMRTX::process()
}
}
/// <summary>
/// Write slot 1 data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write slot 1 data to the local buffer. */
uint8_t DMRTX::writeData1(const uint8_t* data, uint8_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return RSN_ILLEGAL_LENGTH;
uint16_t space = m_fifo[0U].getSpace();
DEBUG3("DMRTX: writeData1(): dataLength/fifoLength", length, space);
DEBUG3("DMRTX::writeData1() dataLength/fifoLength", length, space);
if (space < DMR_FRAME_LENGTH_BYTES)
return RSN_RINGBUFF_FULL;
@ -187,19 +159,15 @@ uint8_t DMRTX::writeData1(const uint8_t* data, uint8_t length)
return RSN_OK;
}
/// <summary>
/// Write slot 2 data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write slot 2 data to the local buffer. */
uint8_t DMRTX::writeData2(const uint8_t* data, uint8_t length)
{
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
return RSN_ILLEGAL_LENGTH;
uint16_t space = m_fifo[1U].getSpace();
DEBUG3("DMRTX: writeData2(): dataLength/fifoLength", length, space);
DEBUG3("DMRTX::writeData2() dataLength/fifoLength", length, space);
if (space < DMR_FRAME_LENGTH_BYTES)
return RSN_RINGBUFF_FULL;
@ -218,12 +186,8 @@ uint8_t DMRTX::writeData2(const uint8_t* data, uint8_t length)
return RSN_OK;
}
/// <summary>
/// Write short LC data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write short LC data to the local buffer. */
uint8_t DMRTX::writeShortLC(const uint8_t* data, uint8_t length)
{
if (length != 9U)
@ -240,12 +204,8 @@ uint8_t DMRTX::writeShortLC(const uint8_t* data, uint8_t length)
return RSN_OK;
}
/// <summary>
/// Write abort data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write abort data to the local buffer. */
uint8_t DMRTX::writeAbort(const uint8_t* data, uint8_t length)
{
if (length != 1U)
@ -267,10 +227,8 @@ uint8_t DMRTX::writeAbort(const uint8_t* data, uint8_t length)
}
}
/// <summary>
/// Helper to set the start state for Tx.
/// </summary>
/// <param name="start"></param>
/* Helper to set the start state for Tx. */
void DMRTX::setStart(bool start)
{
m_state = start ? DMRTXSTATE_SLOT1 : DMRTXSTATE_IDLE;
@ -283,37 +241,29 @@ void DMRTX::setStart(bool start)
m_abort[1U] = false;
}
/// <summary>
/// Helper to set the calibration state for Tx.
/// </summary>
/// <param name="start"></param>
/* Helper to set the calibration state for Tx. */
void DMRTX::setCal(bool start)
{
m_state = start ? DMRTXSTATE_CAL : DMRTXSTATE_IDLE;
}
/// <summary>
/// Helper to get how much space the slot 1 ring buffer has for samples.
/// </summary>
/// <returns></returns>
/* Helper to get how much space the slot 1 ring buffer has for samples. */
uint8_t DMRTX::getSpace1() const
{
return m_fifo[0U].getSpace() / (DMR_FRAME_LENGTH_BYTES + 2U);
}
/// <summary>
/// Helper to get how much space the slot 2 ring buffer has for samples.
/// </summary>
/// <returns></returns>
/* Helper to get how much space the slot 2 ring buffer has for samples. */
uint8_t DMRTX::getSpace2() const
{
return m_fifo[1U].getSpace() / (DMR_FRAME_LENGTH_BYTES + 2U);
}
/// <summary>
/// Sets the ignore flags for setting the CACH Access Type bit.
/// </summary>
/// <param name="slot"></param>
/* Sets the ignore flags for setting the CACH Access Type bit. */
void DMRTX::setIgnoreCACH_AT(uint8_t slot)
{
m_cachATControl = slot;
@ -322,10 +272,8 @@ void DMRTX::setIgnoreCACH_AT(uint8_t slot)
}
}
/// <summary>
/// Sets the DMR color code.
/// </summary>
/// <param name="colorCode">Color code.</param>
/* Sets the DMR color code. */
void DMRTX::setColorCode(uint8_t colorCode)
{
::memcpy(m_idle, IDLE_DATA, DMR_FRAME_LENGTH_BYTES);
@ -334,26 +282,32 @@ void DMRTX::setColorCode(uint8_t colorCode)
slotType.encode(colorCode, DT_IDLE, m_idle);
}
/// <summary>
/// Helper to reset data values to defaults for slot 1 FIFO.
/// </summary>
/* Helper to reset data values to defaults for slot 1 FIFO. */
void DMRTX::resetFifo1()
{
m_fifo[0U].reset();
}
/// <summary>
/// Helper to reset data values to defaults for slot 2 FIFO.
/// </summary>
/* Helper to reset data values to defaults for slot 2 FIFO. */
void DMRTX::resetFifo2()
{
m_fifo[1U].reset();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
/* Helper to resize the FIFO buffer. */
void DMRTX::resizeBuffer(uint16_t size)
{
m_fifo[0U].reset();
m_fifo[1U].reset();
m_fifo[0U].reinitialize(size);
m_fifo[1U].reinitialize(size);
}
/* */
uint32_t DMRTX::getFrameCount()
{
return m_frameCount;
@ -363,10 +317,8 @@ uint32_t DMRTX::getFrameCount()
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/// <param name="slotIndex"></param>
/* Helper to generate data. */
void DMRTX::createData(uint8_t slotIndex)
{
if (m_fifo[slotIndex].getData() > 0U && m_frameCount >= STARTUP_COUNT) {
@ -394,47 +346,8 @@ void DMRTX::createData(uint8_t slotIndex)
m_poPtr = 0U;
}
/// <summary>
///
/// </summary>
void DMRTX::createCal()
{
// 1.2 kHz sine wave generation
if (m_modemState == STATE_DMR_CAL) {
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
m_poBuffer[i] = DMR_START_SYNC;
m_markBuffer[i] = MARK_NONE;
}
m_poLen = DMR_FRAME_LENGTH_BYTES;
}
// 80 Hz square wave generation
if (m_modemState == STATE_DMR_LF_CAL) {
for (unsigned int i = 0U; i < 7U; i++) {
m_poBuffer[i] = 0x55U; // +3, +3, ... pattern
m_markBuffer[i] = MARK_NONE;
}
m_poBuffer[7U] = 0x5FU; // +3, +3, -3, -3 pattern
for (unsigned int i = 8U; i < 15U; i++) {
m_poBuffer[i] = 0xFFU; // -3, -3, ... pattern
m_markBuffer[i] = MARK_NONE;
}
m_poLen = 15U;
}
m_poLen = DMR_FRAME_LENGTH_BYTES;
m_poPtr = 0U;
}
/* Helper to generate the common access channel. */
/// <summary>
///
/// </summary>
/// <param name="txSlotIndex"></param>
/// <param name="rxSlotIndex"></param>
void DMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
{
m_frameCount++;
@ -494,11 +407,43 @@ void DMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
m_cachPtr += 3U;
}
/// <summary>
///
/// </summary>
/// <param name="c"></param>
/// <param name="control"></param>
/* Helper to generate calibration data. */
void DMRTX::createCal()
{
// 1.2 kHz sine wave generation
if (m_modemState == STATE_DMR_CAL) {
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
m_poBuffer[i] = DMR_START_SYNC;
m_markBuffer[i] = MARK_NONE;
}
m_poLen = DMR_FRAME_LENGTH_BYTES;
}
// 80 Hz square wave generation
if (m_modemState == STATE_DMR_LF_CAL) {
for (unsigned int i = 0U; i < 7U; i++) {
m_poBuffer[i] = 0x55U; // +3, +3, ... pattern
m_markBuffer[i] = MARK_NONE;
}
m_poBuffer[7U] = 0x5FU; // +3, +3, -3, -3 pattern
for (unsigned int i = 8U; i < 15U; i++) {
m_poBuffer[i] = 0xFFU; // -3, -3, ... pattern
m_markBuffer[i] = MARK_NONE;
}
m_poLen = 15U;
}
m_poLen = DMR_FRAME_LENGTH_BYTES;
m_poPtr = 0U;
}
/* Helper to write a raw byte to the DAC. */
void DMRTX::writeByte(uint8_t c, uint8_t control)
{
uint8_t bit;

@ -1,35 +1,21 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2017 by Andy Uribe CA6JAU
* Copyright (C) 2021-2022 by Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2016 Colin Durbridge, G4EML
* Copyright (C) 2017 Andy Uribe, CA6JAU
* Copyright (C) 2021-2022 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file DMRTX.h
* @ingroup dmr_hfw
* @file DMRTX.cpp
* @ingroup dmr_hfw
*/
#if !defined(__DMR_TX_H__)
#define __DMR_TX_H__
@ -43,58 +29,121 @@ namespace dmr
// Constants
// ---------------------------------------------------------------------------
/**
* @brief DMR Duplex Transmitter State
* @ingroup dmr_hfw
*/
enum DMRTXSTATE {
DMRTXSTATE_IDLE,
DMRTXSTATE_SLOT1,
DMRTXSTATE_CACH1,
DMRTXSTATE_SLOT2,
DMRTXSTATE_CACH2,
DMRTXSTATE_CAL
DMRTXSTATE_IDLE, //! Idle
DMRTXSTATE_SLOT1, //! Slot 1
DMRTXSTATE_CACH1, //! Common Access Channel 1
DMRTXSTATE_SLOT2, //! Slot 2
DMRTXSTATE_CACH2, //! Common Access Channel 2
DMRTXSTATE_CAL //! Calibration
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements receiver logic for duplex DMR mode operation.
// ---------------------------------------------------------------------------
/**
* @brief Implements receiver logic for duplex DMR mode operation.
* @ingroup dmr_hfw
*/
class DSP_FW_API DMRTX {
public:
/// <summary>Initializes a new instance of the DMRTX class.</summary>
/**
* @brief Initializes a new instance of the DMRTX class.
*/
DMRTX();
/// <summary>Process local buffer and transmit on the air interface.</summary>
/**
* @brief Process local buffer and transmit on the air interface.
*/
void process();
/// <summary>Write slot 1 data to the local buffer.</summary>
/**
* @brief Write slot 1 data to the local buffer.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t writeData1(const uint8_t* data, uint8_t length);
/// <summary>Write slot 2 data to the local buffer.</summary>
/**
* @brief Write slot 2 data to the local buffer.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t writeData2(const uint8_t* data, uint8_t length);
/// <summary>Write short LC data to the local buffer.</summary>
/**
* @brief Write short LC data to the local buffer.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t writeShortLC(const uint8_t* data, uint8_t length);
/// <summary>Write abort data to the local buffer.</summary>
/**
* @brief Write abort data to the local buffer.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t writeAbort(const uint8_t* data, uint8_t length);
/// <summary>Helper to set the start state for Tx.</summary>
/**
* @brief Helper to set the start state for Tx.
* @param start
*/
void setStart(bool start);
/// <summary>Helper to set the calibration state for Tx.</summary>
/**
* @brief Helper to set the calibration state for Tx.
* @param start
*/
void setCal(bool start);
/// <summary>Helper to get how much space the slot 1 ring buffer has for samples.</summary>
/**
* @brief Helper to get how much space the slot 1 ring buffer has for samples.
* @returns uint8_t Amount of space in the slot 1 ring buffer.
*/
uint8_t getSpace1() const;
/// <summary>Helper to get how much space the slot 2 ring buffer has for samples.</summary>
/**
* @brief Helper to get how much space the slot 2 ring buffer has for samples.
* @returns uint8_t Amount of space in the slot 2 ring buffer.
*/
uint8_t getSpace2() const;
/// <summary>Sets the ignore flags for setting the CACH Access Type bit.</summary>
/**
* @brief Sets the ignore flags for setting the CACH Access Type bit.
* @param slot DMR slot number.
*/
void setIgnoreCACH_AT(uint8_t slot);
/// <summary>Sets the DMR color code.</summary>
/**
* @brief Sets the DMR color code.
* @param colorCode Color code.
*/
void setColorCode(uint8_t colorCode);
/// <summary>Helper to reset data values to defaults for slot 1 FIFO.</summary>
/**
* @brief Helper to reset data values to defaults for slot 1 FIFO.
*/
void resetFifo1();
/// <summary>Helper to reset data values to defaults for slot 2 FIFO.</summary>
/**
* @brief Helper to reset data values to defaults for slot 2 FIFO.
*/
void resetFifo2();
/// <summary></summary>
/**
* @brief Helper to resize the FIFO buffer.
* @param size
*/
void resizeBuffer(uint16_t size);
/**
* @brief
* @returns uint32_t
*/
uint32_t getFrameCount();
private:
@ -123,14 +172,27 @@ namespace dmr
uint8_t m_controlPrev;
/// <summary></summary>
/**
* @brief Helper to generate data.
* @param slotIndex
*/
void createData(uint8_t slotIndex);
/// <summary></summary>
/**
* @brief Helper to generate the common access channel.
* @param txSlotIndex
* @param rxSlotIndex
*/
void createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex);
/// <summary></summary>
/**
* @brief Helper to generate calibration data.
*/
void createCal();
/// <summary></summary>
/**
* @brief Helper to write a raw byte to the DAC.
* @param c Byte.
* @param control
*/
void writeByte(uint8_t c, uint8_t control);
};
} // namespace dmr

@ -1,32 +1,12 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM project. (https://github.com/g4klx/MMDVM)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
* Copyright (C) 2018 Andy Uribe, CA6JAU
* Copyright (C) 2020 Jonathan Naylor, G4KLX
*
* 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 "Globals.h"
#include "nxdn/CalNXDN.h"
@ -72,9 +52,8 @@ const uint8_t NXDN_CAL1K[4][49] = {
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CalNXDN class.
/// </summary>
/* Initializes a new instance of the CalNXDN class. */
CalNXDN::CalNXDN() :
m_transmit(false),
m_state(NXDNCAL1K_IDLE),
@ -83,9 +62,8 @@ CalNXDN::CalNXDN() :
/* stub */
}
/// <summary>
/// Process local state and transmit on the air interface.
/// </summary>
/* Process local state and transmit on the air interface. */
void CalNXDN::process()
{
if (m_transmit) {
@ -120,12 +98,8 @@ void CalNXDN::process()
}
}
/// <summary>
/// Write P25 calibration data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write NXDN calibration data to the local buffer. */
uint8_t CalNXDN::write(const uint8_t* data, uint16_t length)
{
if (length != 1U)

@ -1,34 +1,19 @@
// SPDX-License-Identifier: GPL-2.0-only
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
* Copyright (C) 2018 Andy Uribe, CA6JAU
* Copyright (C) 2020 Jonathan Naylor, G4KLX
*
*/
//
// Based on code from the MMDVM project. (https://github.com/g4klx/MMDVM)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* 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
* 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.
/**
* @file CalNXDN.h
* @ingroup nxdn_hfw
* @file CalNXDN.cpp
* @ingroup nxdn_hfw
*/
#if !defined(__CAL_NXDN_H__)
#define __CAL_NXDN_H__
@ -41,25 +26,41 @@ namespace nxdn
// Constants
// ---------------------------------------------------------------------------
/**
* @brief Calibration States
* @ingroup nxdn_hfw
*/
enum NXDNCAL1K {
NXDNCAL1K_IDLE,
NXDNCAL1K_TX
NXDNCAL1K_IDLE, //! Idle
NXDNCAL1K_TX //! Transmit
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements logic for NXDN calibration mode.
// ---------------------------------------------------------------------------
/**
* @brief Implements logic for NXDN calibration mode.
* @ingroup nxdn_hfw
*/
class DSP_FW_API CalNXDN {
public:
/// <summary>Initializes a new instance of the CalNXDN class.</summary>
/**
* @brief Initializes a new instance of the CalNXDN class.
*/
CalNXDN();
/// <summary>Process local state and transmit on the air interface.</summary>
/**
* @brief Process local state and transmit on the air interface.
*/
void process();
/// <summary>Write NXDN calibration state.</summary>
/**
* @brief Write NXDN calibration state.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t write(const uint8_t* data, uint16_t length);
private:

@ -1,31 +1,19 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM project. (https://github.com/g4klx/MMDVM)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
* Copyright (C) 2016,2017,2018 Jonathan Naylor, G4KLX
*
* 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.
*/
/**
* @defgroup nxdn_hfw Next Generation Digital Narrowband
* @brief Implementation for the NXDN standard.
* @ingroup hotspot_fw
*
* @file NXDNDefines.h
* @ingroup nxdn_hfw
*/
#if !defined(__NXDN_DEFINES_H__)
#define __NXDN_DEFINES_H__
@ -38,6 +26,11 @@ namespace nxdn
// Constants
// ---------------------------------------------------------------------------
/**
* @addtogroup nxdn_hfw
* @{
*/
const uint32_t NXDN_RADIO_SYMBOL_LENGTH = 10U; // At 24 kHz sample rate
const uint32_t NXDN_FRAME_LENGTH_BITS = 384U;
@ -68,7 +61,10 @@ namespace nxdn
const uint16_t NXDN_FSW_SYMBOLS = 0x014DU;
const uint16_t NXDN_FSW_SYMBOLS_MASK = 0x03FFU;
const uint32_t NXDN_TX_BUFFER_LEN = 1018U; // 2026 = NXDN_FRAME_LENGTH_BYTES * 21 + 10 (BUFFER_LEN = NXDN_FRAME_LENGTH_BYTES * NO_OF_FRAMES)
// 538 = NXDN_FRAME_LENGTH_BYTES * 11 + 10 (BUFFER_LEN = NXDN_FRAME_LENGTH_BYTES * NO_OF_FRAMES)
const uint32_t NXDN_TX_BUFFER_LEN = 538U; // 11 frames + pad
/** @} */
} // namespace nxdn
#endif // __NXDN_DEFINES_H__

@ -1,32 +1,12 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM project. (https://github.com/g4klx/MMDVM)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2022 Bryan Biedenkapp N2PLL
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
* Copyright (C) 2009-2018,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL
*
* 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 "Globals.h"
#include "nxdn/NXDNRX.h"
@ -49,15 +29,13 @@ const uint16_t NOENDPTR = 9999U;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the NXDNRX class.
/// </summary>
/* Initializes a new instance of the NXDNRX class. */
NXDNRX::NXDNRX() :
m_bitBuffer(0x00U),
m_outBuffer(),
m_buffer(NULL),
m_dataPtr(0U),
m_endPtr(NOENDPTR),
m_lostCount(0U),
m_state(NXDNRXS_NONE)
{
@ -65,48 +43,32 @@ NXDNRX::NXDNRX() :
m_buffer = m_outBuffer + 1U;
}
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
/* Helper to reset data values to defaults. */
void NXDNRX::reset()
{
m_bitBuffer = 0x00U;
m_dataPtr = 0U;
m_endPtr = NOENDPTR;
m_lostCount = 0U;
m_state = NXDNRXS_NONE;
}
/// <summary>
/// Sample NXDN bits from the air interface.
/// </summary>
/// <param name="bit"></param>
/* Sample NXDN bits from the air interface. */
void NXDNRX::databit(bool bit)
{
m_bitBuffer <<= 1;
if (bit)
m_bitBuffer |= 0x01U;
if (m_state != NXDNRXS_NONE) {
_WRITE_BIT(m_buffer, m_dataPtr, bit);
m_dataPtr++;
if (m_dataPtr > NXDN_FRAME_LENGTH_BITS) {
reset();
}
}
if (m_state == NXDNRXS_DATA) {
processData(bit);
}
else {
m_bitBuffer <<= 1;
if (bit)
m_bitBuffer |= 0x01U;
bool ret = correlateSync(true);
if (ret) {
DEBUG3("NXDNRX: databit(): dataPtr/endPtr", m_dataPtr, m_endPtr);
m_state = NXDNRXS_DATA;
}
@ -118,24 +80,35 @@ void NXDNRX::databit(bool bit)
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Helper to process NXDN data bits.
/// </summary>
/// <param name="bit"></param>
/* Helper to process NXDN data bits. */
void NXDNRX::processData(bool bit)
{
m_bitBuffer <<= 1;
if (bit)
m_bitBuffer |= 0x01U;
_WRITE_BIT(m_buffer, m_dataPtr, bit);
m_dataPtr++;
if (m_dataPtr > NXDN_FRAME_LENGTH_BITS) {
reset();
}
// only search for a sync in the right place +-2 bits
if (m_dataPtr >= (NXDN_FSW_LENGTH_BITS - 2U) && m_dataPtr <= (NXDN_FSW_LENGTH_BITS + 2U)) {
correlateSync();
if (correlateSync()) {
DEBUG2("NXDNRX::processData() sync found pos", m_dataPtr - NXDN_FSW_LENGTH_BITS);
}
}
// process frame
if (m_dataPtr == m_endPtr) {
if (m_dataPtr == NXDN_FRAME_LENGTH_BITS) {
m_lostCount--;
// we've not seen a data sync for too long, signal sync lost and change to NXDNRXS_NONE
if (m_lostCount == 0U) {
DEBUG1("NXDNRX: processData(): sync timed out, lost lock");
DEBUG1("NXDNRX::processData() sync timed out, lost lock");
io.setDecode(false);
@ -143,8 +116,6 @@ void NXDNRX::processData(bool bit)
reset();
}
else {
DEBUG2("NXDNRX: processData(): sync found pos", m_dataPtr);
m_outBuffer[0U] = m_lostCount == (MAX_FSW_FRAMES - 1U) ? 0x01U : 0x00U; // set sync flag
serial.writeNXDNData(m_outBuffer, NXDN_FRAME_LENGTH_BYTES + 1U);
@ -154,11 +125,8 @@ void NXDNRX::processData(bool bit)
}
}
/// <summary>
/// Frame synchronization correlator.
/// </summary>
/// <param name="first"></param>
/// <returns></returns>
/* Frame synchronization correlator. */
bool NXDNRX::correlateSync(bool first)
{
uint8_t maxErrs;
@ -170,7 +138,7 @@ bool NXDNRX::correlateSync(bool first)
// fuzzy matching of the data sync bit sequence
uint8_t errs = countBits64((m_bitBuffer & NXDN_FSW_BITS_MASK) ^ NXDN_FSW_BITS);
if (errs <= maxErrs) {
DEBUG2("NXDNRX: correlateSync(): correlateSync errs", errs);
DEBUG2("NXDNRX::correlateSync() sync errs", errs);
if (first) {
// unpack sync bytes
@ -179,17 +147,16 @@ bool NXDNRX::correlateSync(bool first)
sync[1U] = (uint8_t)((m_bitBuffer >> 8) & NXDN_FSW_BYTES_MASK[1U]);
sync[2U] = (uint8_t)((m_bitBuffer >> 0) & NXDN_FSW_BYTES_MASK[2U]);
DEBUG4("NXDNRX: correlateSync(): sync [b0 - b2]", sync[0], sync[1], sync[2]);
for (uint8_t i = 0U; i < NXDN_FSW_BYTES_LENGTH; i++)
m_buffer[i] = sync[i];
DEBUG4("NXDNRX::correlateSync() sync [b0 - b2]", m_buffer[0], m_buffer[1], m_buffer[2]);
}
m_lostCount = MAX_FSW_FRAMES;
m_dataPtr = NXDN_FSW_LENGTH_BITS;
m_endPtr = NXDN_FRAME_LENGTH_BITS;
DEBUG3("NXDNRX: correlateSync(): dataPtr/endPtr", m_dataPtr, m_endPtr);
DEBUG2("NXDNRX::correlateSync() dataPtr", m_dataPtr - NXDN_FSW_LENGTH_BITS);
return true;
}

@ -1,32 +1,18 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM project. (https://github.com/g4klx/MMDVM)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2022 Bryan Biedenkapp N2PLL
*
* 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.
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
* Copyright (C) 2015,2016,2017,2018,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL
*
* 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.
*/
/**
* @file NXDNRX.h
* @ingroup nxdn_hfw
* @file NXDNRX.cpp
* @ingroup nxdn_hfw
*/
#if !defined(__NXDN_RX_H__)
#define __NXDN_RX_H__
@ -40,25 +26,39 @@ namespace nxdn
// Constants
// ---------------------------------------------------------------------------
/**
* @brief NXDN Receiver State
* @ingroup nxdn_hfw
*/
enum NXDNRX_STATE {
NXDNRXS_NONE,
NXDNRXS_DATA
NXDNRXS_NONE, //! None
NXDNRXS_DATA //! Data
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements receiver logic for DMR slots.
// ---------------------------------------------------------------------------
/**
* @brief Implements receiver logic for NXDN mode operation.
* @ingroup nxdn_mfw
*/
class DSP_FW_API NXDNRX {
public:
/// <summary>Initializes a new instance of the NXDNRX class.</summary>
/**
* @brief Initializes a new instance of the NXDNRX class.
*/
NXDNRX();
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset();
/// <summary>Sample NXDN bits from the air interface.</summary>
/**
* @brief Sample NXDN bits from the air interface.
* @param bit
*/
void databit(bool bit);
private:
@ -68,16 +68,20 @@ namespace nxdn
uint16_t m_dataPtr;
uint16_t m_endPtr;
uint16_t m_lostCount;
NXDNRX_STATE m_state;
/// <summary>Helper to process NXDN data bits.</summary>
/**
* @brief Helper to process NXDN data bits.
* @param bit
*/
void processData(bool bit);
/// <summary>Frame synchronization correlator.</summary>
/**
* @brief Frame synchronization correlator.
* @param first
*/
bool correlateSync(bool first = false);
};
} // namespace nxdn

@ -1,33 +1,13 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM project. (https://github.com/g4klx/MMDVM)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
* Copyright (C) 2009-2018,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2017 Andy Uribe, CA6JAU
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL
*
* 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 "Globals.h"
#include "nxdn/NXDNTX.h"
@ -39,9 +19,8 @@ using namespace nxdn;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the NXDNTX class.
/// </summary>
/* Initializes a new instance of the NXDNTX class. */
NXDNTX::NXDNTX() :
m_fifo(NXDN_TX_BUFFER_LEN),
m_state(NXDNTXSTATE_NORMAL),
@ -55,9 +34,8 @@ NXDNTX::NXDNTX() :
/* stub */
}
/// <summary>
/// Process local buffer and transmit on the air interface.
/// </summary>
/* Process local buffer and transmit on the air interface. */
void NXDNTX::process()
{
if (m_fifo.getData() == 0U && m_poLen == 0U && m_tailCnt > 0U &&
@ -91,8 +69,6 @@ void NXDNTX::process()
return;
createData();
DEBUG2("NXDNTX: process(): poLen", m_poLen);
}
if (m_poLen > 0U) {
@ -115,19 +91,15 @@ void NXDNTX::process()
}
}
/// <summary>
/// Write data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write data to the local buffer. */
uint8_t NXDNTX::writeData(const uint8_t* data, uint16_t length)
{
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
return RSN_ILLEGAL_LENGTH;
uint16_t space = m_fifo.getSpace();
DEBUG3("NXDNTX: writeData(): dataLength/fifoLength", length, space);
DEBUG3("NXDNTX::writeData() dataLength/fifoLength", length, space);
if (space < NXDN_FRAME_LENGTH_BYTES)
return RSN_RINGBUFF_FULL;
@ -137,48 +109,48 @@ uint8_t NXDNTX::writeData(const uint8_t* data, uint16_t length)
return RSN_OK;
}
/// <summary>
/// Clears the local buffer.
/// </summary>
/* Clears the local buffer. */
void NXDNTX::clear()
{
m_fifo.reset();
}
/// <summary>
/// Sets the FDMA preamble count.
/// </summary>
/// <param name="preambleCnt">Count of preambles.</param>
/* Sets the FDMA preamble count. */
void NXDNTX::setPreambleCount(uint8_t preambleCnt)
{
m_preambleCnt = 300U + uint16_t(preambleCnt) * 6U; // 500ms + tx delay
if (m_preambleCnt > 1200U)
m_preambleCnt = 1200U;
// clamp preamble count
if (m_preambleCnt > 60U)
m_preambleCnt = 60U;
}
/// <summary>
/// Sets the Tx hang time.
/// </summary>
/// <param name="txHang">Transmit hang time in seconds.</param>
/* Sets the Tx hang time. */
void NXDNTX::setTxHang(uint8_t txHang)
{
m_txHang = txHang * NXDN_FIXED_TX_HANG;
}
/// <summary>
/// Helper to set the calibration state for Tx.
/// </summary>
/// <param name="start"></param>
/* Helper to set the calibration state for Tx. */
void NXDNTX::setCal(bool start)
{
m_state = start ? NXDNTXSTATE_CAL : NXDNTXSTATE_NORMAL;
}
/// <summary>
/// Helper to get how much space the ring buffer has for samples.
/// </summary>
/// <returns></returns>
/* Helper to resize the FIFO buffer. */
void NXDNTX::resizeBuffer(uint16_t size)
{
m_fifo.reset();
m_fifo.reinitialize(size);
}
/* Helper to get how much space the ring buffer has for samples. */
uint8_t NXDNTX::getSpace() const
{
return m_fifo.getSpace() / NXDN_FRAME_LENGTH_BYTES;
@ -188,9 +160,8 @@ uint8_t NXDNTX::getSpace() const
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/* Helper to generate data. */
void NXDNTX::createData()
{
if (!m_tx) {
@ -202,7 +173,7 @@ void NXDNTX::createData()
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[2U];
}
else {
DEBUG2("NXDNTX: createData(): fifoSpace", m_fifo.getSpace());
DEBUG2("NXDNTX::createData() fifoSpace", m_fifo.getSpace());
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++) {
m_poBuffer[m_poLen++] = m_fifo.get();
}
@ -211,10 +182,8 @@ void NXDNTX::createData()
m_poPtr = 0U;
}
/// <summary>
///
/// </summary>
/// <param name="c"></param>
/* Helper to write a raw byte to the DAC. */
void NXDNTX::writeByte(uint8_t c)
{
uint8_t bit;
@ -230,9 +199,8 @@ void NXDNTX::writeByte(uint8_t c)
}
}
/// <summary>
///
/// </summary>
/* */
void NXDNTX::writeSilence()
{
uint8_t bit;

@ -1,34 +1,19 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM project. (https://github.com/g4klx/MMDVM)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2022 by Bryan Biedenkapp N2PLL
*
* 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.
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
* Copyright (C) 2015,2016,2017,2018,2020 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL
*
* 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.
*/
/**
* @file NXDNTX.h
* @ingroup nxdn_hfw
* @file NXDNTX.cpp
* @ingroup nxdn_hfw
*/
#if !defined(__NXDN_TX_H__)
#define __NXDN_TX_H__
@ -43,38 +28,74 @@ namespace nxdn
#define NXDN_FIXED_TX_HANG 600
/**
* @brief NXDN Transmitter States
* @ingroup nxdn_hfw
*/
enum NXDNTXSTATE {
NXDNTXSTATE_NORMAL,
NXDNTXSTATE_CAL
NXDNTXSTATE_NORMAL, //! Normal
NXDNTXSTATE_CAL //! Calibration
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements transmitter logic for NXDN mode operation.
// ---------------------------------------------------------------------------
/**
* @brief Implements transmitter logic for NXDN mode operation.
* @ingroup nxdn_hfw
*/
class DSP_FW_API NXDNTX {
public:
/// <summary>Initializes a new instance of the NXDNTX class.</summary>
/**
* @brief Initializes a new instance of the NXDNTX class.
*/
NXDNTX();
/// <summary>Process local buffer and transmit on the air interface.</summary>
/**
* @brief Process local buffer and transmit on the air interface.
*/
void process();
/// <summary>Write data to the local buffer.</summary>
/**
* @brief Write data to the local buffer.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t writeData(const uint8_t* data, uint16_t length);
/// <summary>Clears the local buffer.</summary>
/**
* @brief Clears the local buffer.
*/
void clear();
/// <summary>Sets the FDMA preamble count.</summary>
/**
* @brief Sets the FDMA preamble count.
* @param preambleCnt FDMA preamble count.
*/
void setPreambleCount(uint8_t preambleCnt);
/// <summary>Sets the transmit hang time.</summary>
/**
* @brief Sets the transmit hang time.
* @param txHang Transmit hang time.
*/
void setTxHang(uint8_t txHang);
/// <summary>Helper to set the calibration state for Tx.</summary>
/**
* @brief Helper to set the calibration state for Tx.
* @param start
*/
void setCal(bool start);
/// <summary>Helper to get how much space the ring buffer has for samples.</summary>
/**
* @brief Helper to resize the FIFO buffer.
* @param size
*/
void resizeBuffer(uint16_t size);
/**
* @brief Helper to get how much space the ring buffer has for samples.
* @returns uint8_t Amount of space in ring buffer for samples.
*/
uint8_t getSpace() const;
private:
@ -90,12 +111,19 @@ namespace nxdn
uint32_t m_txHang;
uint32_t m_tailCnt;
/// <summary></summary>
/**
* @brief Helper to generate data.
*/
void createData();
/// <summary></summary>
/**
* @brief Helper to write a raw byte to the DAC.
* @param c Byte.
*/
void writeByte(uint8_t c);
/// <summary></summary>
/**
* @brief
*/
void writeSilence();
};
} // namespace nxdn

@ -1,32 +1,12 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2018 Andy Uribe, CA6JAU
*
*/
#include "Globals.h"
#include "p25/CalP25.h"
@ -70,9 +50,8 @@ unsigned char LDU2_1K[] = { 0x00,
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CalP25 class.
/// </summary>
/* Initializes a new instance of the CalP25 class. */
CalP25::CalP25() :
m_transmit(false),
m_state(P25CAL1K_IDLE)
@ -80,9 +59,8 @@ CalP25::CalP25() :
/* stub */
}
/// <summary>
/// Process local state and transmit on the air interface.
/// </summary>
/* Process local state and transmit on the air interface. */
void CalP25::process()
{
if (m_modemState == STATE_P25_CAL) {
@ -122,12 +100,8 @@ void CalP25::process()
}
}
/// <summary>
/// Write P25 calibration data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
/* Write P25 calibration data to the local buffer. */
uint8_t CalP25::write(const uint8_t* data, uint8_t length)
{
if (length != 1U)

@ -1,32 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-only
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
* Copyright (C) 2018 Andy Uribe, CA6JAU
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* Copyright (C) 2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/**
* @file CalP25.h
* @ingroup p25_hfw
* @file CalP25.cpp
* @ingroup p25_hfw
*/
#if !defined(__CAL_P25_H__)
#define __CAL_P25_H__
@ -39,26 +25,42 @@ namespace p25
// Constants
// ---------------------------------------------------------------------------
/**
* @brief Calibration States
* @ingroup p25_hfw
*/
enum P25CAL1K {
P25CAL1K_IDLE,
P25CAL1K_LDU1,
P25CAL1K_LDU2
P25CAL1K_IDLE, //! Idle
P25CAL1K_LDU1, //! LDU1
P25CAL1K_LDU2 //! LDU2
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements logic for P25 calibration mode.
// ---------------------------------------------------------------------------
/**
* @brief Implements logic for P25 calibration mode.
* @ingroup p25_hfw
*/
class DSP_FW_API CalP25 {
public:
/// <summary>Initializes a new instance of the CalP25 class.</summary>
/**
* @brief Initializes a new instance of the CalP25 class.
*/
CalP25();
/// <summary>Process local state and transmit on the air interface.</summary>
/**
* @brief Process local state and transmit on the air interface.
*/
void process();
/// <summary>Write P25 calibration state.</summary>
/**
* @brief Write P25 calibration state.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t write(const uint8_t* data, uint8_t length);
private:

@ -1,51 +1,21 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Andy Uribe CA6JAU
* Copyright (C) 2017-2018 Bryan Biedenkapp N2PLL
*
* 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.
*/
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
* Copyright (C) 2009-2016 Jonathan Naylor, G4KLX
* Copyright (C) 2018 Andy Uribe, CA6JAU
* Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
*
* 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.
*/
/**
* @defgroup p25_hfw Project 25
* @brief Implementation for the TIA-102 Project 25 standard.
* @ingroup hotspot_fw
*
* @file P25Defines.h
* @ingroup p25_hfw
*/
#if !defined(__P25_DEFINES_H__)
#define __P25_DEFINES_H__
@ -58,6 +28,11 @@ namespace p25
// Constants
// ---------------------------------------------------------------------------
/**
* @addtogroup p25_hfw
* @{
*/
const uint32_t P25_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const uint32_t P25_HDU_FRAME_LENGTH_BYTES = 99U;
@ -80,6 +55,11 @@ namespace p25
const uint32_t P25_TSDU_FRAME_LENGTH_SYMBOLS = P25_TSDU_FRAME_LENGTH_BYTES * 4U;
const uint32_t P25_TSDU_FRAME_LENGTH_SAMPLES = P25_TSDU_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH;
const uint32_t P25_PDU_FRAME_LENGTH_BYTES = 512U;
const uint32_t P25_PDU_FRAME_LENGTH_BITS = P25_PDU_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_PDU_FRAME_LENGTH_SYMBOLS = P25_PDU_FRAME_LENGTH_BYTES * 4U;
const uint32_t P25_PDU_FRAME_LENGTH_SAMPLES = P25_PDU_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH;
const uint32_t P25_TDULC_FRAME_LENGTH_BYTES = 54U;
const uint32_t P25_TDULC_FRAME_LENGTH_BITS = P25_TDULC_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_TDULC_FRAME_LENGTH_SYMBOLS = P25_TDULC_FRAME_LENGTH_BYTES * 4U;
@ -95,11 +75,6 @@ namespace p25
const uint32_t P25_NID_LENGTH_SYMBOLS = P25_NID_LENGTH_BYTES * 4U;
const uint32_t P25_NID_LENGTH_SAMPLES = P25_NID_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH;
const uint32_t P25_PDU_HDU_FRAME_LENGTH_BYTES = 39U;
const uint32_t P25_PDU_HDU_FRAME_LENGTH_BITS = P25_PDU_HDU_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_PDU_HDU_FRAME_LENGTH_SYMBOLS = P25_PDU_HDU_FRAME_LENGTH_BYTES * 4U;
const uint32_t P25_PDU_HDU_FRAME_LENGTH_SAMPLES = P25_PDU_HDU_FRAME_LENGTH_SYMBOLS * P25_RADIO_SYMBOL_LENGTH;
const uint8_t P25_SYNC_BYTES[] = { 0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU };
const uint8_t P25_SYNC_BYTES_LENGTH = 6U;
const uint8_t P25_START_SYNC = 0x5FU;
@ -120,16 +95,21 @@ namespace p25
const uint32_t P25_SYNC_SYMBOLS = 0x00FB30A0U;
const uint32_t P25_SYNC_SYMBOLS_MASK = 0x00FFFFFFU;
const uint32_t P25_TX_BUFFER_LEN = 1738U; // 2592 = P25_LDU_FRAME_LENGTH_BYTES * 8 + 10 (BUFFER_LEN = P25_LDU_FRAME_LENGTH_BYTES * NO_OF_FRAMES + 10)
// 522 = P25_PDU_FRAME_LENGTH_BYTES + 10 (BUFFER_LEN = P25_PDU_FRAME_LENGTH_BYTES + 10)
const uint32_t P25_TX_BUFFER_LEN = 522U;
// Data Unit ID(s)
const uint8_t P25_DUID_HDU = 0x00U; // Header Data Unit
const uint8_t P25_DUID_TDU = 0x03U; // Simple Terminator Data Unit
const uint8_t P25_DUID_LDU1 = 0x05U; // Logical Link Data Unit 1
const uint8_t P25_DUID_VSELP1 = 0x06U; // Motorola VSELP 1
const uint8_t P25_DUID_TSDU = 0x07U; // Trunking System Data Unit
const uint8_t P25_DUID_VSELP2 = 0x09U; // Motorola VSELP 2
const uint8_t P25_DUID_LDU2 = 0x0AU; // Logical Link Data Unit 2
const uint8_t P25_DUID_PDU = 0x0CU; // Packet Data Unit
const uint8_t P25_DUID_TDULC = 0x0FU; // Terminator Data Unit with Link Control
/** @} */
} // namespace p25
#endif // __P25_DEFINES_H__

@ -1,34 +1,14 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2021-2024 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "p25/P25RX.h"
#include "Utils.h"
@ -50,14 +30,14 @@ const uint16_t NOENDPTR = 9999U;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the P25RX class.
/// </summary>
/* Initializes a new instance of the P25RX class. */
P25RX::P25RX() :
m_bitBuffer(0x00U),
m_buffer(),
m_dataPtr(0U),
m_endPtr(NOENDPTR),
m_pduEndPtr(NOENDPTR),
m_lostCount(0U),
m_nac(0xF7EU),
m_state(P25RXS_NONE),
@ -66,9 +46,8 @@ P25RX::P25RX() :
::memset(m_buffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U);
}
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
/* Helper to reset data values to defaults. */
void P25RX::reset()
{
m_bitBuffer = 0x00U;
@ -77,6 +56,7 @@ void P25RX::reset()
::memset(m_buffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U);
m_endPtr = NOENDPTR;
m_pduEndPtr = NOENDPTR;
m_lostCount = 0U;
@ -85,10 +65,8 @@ void P25RX::reset()
m_duid = 0xFFU;
}
/// <summary>
/// Sample P25 bits from the air interface.
/// </summary>
/// <param name="bit"></param>
/* Sample P25 bits from the air interface. */
void P25RX::databit(bool bit)
{
m_bitBuffer <<= 1;
@ -99,8 +77,14 @@ void P25RX::databit(bool bit)
_WRITE_BIT(m_buffer, m_dataPtr, bit);
m_dataPtr++;
if (m_dataPtr > P25_LDU_FRAME_LENGTH_BITS) {
reset();
if (m_state != P25RXS_DATA) {
if (m_dataPtr > P25_LDU_FRAME_LENGTH_BITS) {
reset();
}
} else {
if (m_dataPtr > P25_PDU_FRAME_LENGTH_BITS) {
reset();
}
}
}
@ -124,10 +108,8 @@ void P25RX::databit(bool bit)
}
}
/// <summary>
/// Sets the P25 NAC.
/// </summary>
/// <param name="nac">NAC.</param>
/* Sets the P25 NAC. */
void P25RX::setNAC(uint16_t nac)
{
m_nac = nac;
@ -137,15 +119,13 @@ void P25RX::setNAC(uint16_t nac)
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Helper to process P25 samples.
/// </summary>
/// <param name="bit"></param>
/* Helper to process P25 samples. */
void P25RX::processBit(bool bit)
{
// process NID
if (m_dataPtr == P25_SYNC_LENGTH_BITS + P25_NID_LENGTH_BITS + 1) {
DEBUG3("P25RX: processBit(): dataPtr/endPtr", m_dataPtr, m_endPtr);
DEBUG3("P25RX::processBit() dataPtr/endPtr", m_dataPtr, m_endPtr);
if (!decodeNid()) {
io.setDecode(false);
@ -157,43 +137,45 @@ void P25RX::processBit(bool bit)
switch (m_duid) {
case P25_DUID_HDU:
{
DEBUG2("P25RX: processBit(): sync found in HDU pos", m_dataPtr);
DEBUG2("P25RX::processBit() sync found in HDU pos", m_dataPtr);
m_endPtr = P25_HDU_FRAME_LENGTH_BITS;
}
break;
case P25_DUID_TDU:
{
DEBUG2("P25RX: processBit(): sync found in TDU pos", m_dataPtr);
DEBUG2("P25RX::processBit() sync found in TDU pos", m_dataPtr);
m_endPtr = P25_TDU_FRAME_LENGTH_BITS;
}
break;
case P25_DUID_LDU1:
case P25_DUID_VSELP1:
m_state = P25RXS_VOICE;
m_endPtr = P25_LDU_FRAME_LENGTH_BITS;
return;
case P25_DUID_TSDU:
{
DEBUG2("P25RX: processBit(): sync found in TSDU pos", m_dataPtr);
DEBUG2("P25RX::processBit() sync found in TSDU pos", m_dataPtr);
m_endPtr = P25_TSDU_FRAME_LENGTH_BITS;
}
break;
case P25_DUID_LDU2:
case P25_DUID_VSELP2:
m_state = P25RXS_VOICE;
m_endPtr = P25_LDU_FRAME_LENGTH_BITS;
return;
case P25_DUID_PDU:
m_state = P25RXS_DATA;
m_endPtr = P25_LDU_FRAME_LENGTH_BITS;
m_endPtr = m_pduEndPtr = P25_PDU_FRAME_LENGTH_BITS;
return;
case P25_DUID_TDULC:
{
DEBUG2("P25RX: processBit(): sync found in TDULC pos", m_dataPtr);
DEBUG2("P25RX::processBit() sync found in TDULC pos", m_dataPtr);
m_endPtr = P25_TDULC_FRAME_LENGTH_BITS;
}
break;
default:
{
DEBUG3("P25RX: processBit(): illegal DUID in NID", m_nac, m_duid);
DEBUG3("P25RX::processBit() illegal DUID in NID", m_nac, m_duid);
reset();
}
return;
@ -201,34 +183,40 @@ void P25RX::processBit(bool bit)
}
}
if (m_state == P25RXS_VOICE) {
m_lostCount = MAX_SYNC_FRAMES;
processVoice(bit);
}
if (m_state == P25RXS_SYNC) {
// only search for a sync in the right place +-2 bits
if (m_dataPtr >= (P25_SYNC_LENGTH_BITS - 2U) && m_dataPtr <= (P25_SYNC_LENGTH_BITS + 2U)) {
correlateSync();
}
if (m_state == P25RXS_DATA) {
m_lostCount = MAX_SYNC_FRAMES;
processData(bit);
}
// since we aren't processing voice or data -- simply wait till we've reached the end pointer
if (m_dataPtr == m_endPtr) {
// DEBUG3("P25RX: m_buffer dump endPtr/endPtrB", m_endPtr, m_endPtr / 8U);
// DEBUG_DUMP(m_buffer, P25_LDU_FRAME_LENGTH_BYTES + 3U);
// since we aren't processing voice or data -- simply wait till we've reached the end pointer
if (m_dataPtr == m_endPtr) {
// DEBUG3("P25RX: m_buffer dump endPtr/endPtrB", m_endPtr, m_endPtr / 8U);
// DEBUG_DUMP(m_buffer, P25_LDU_FRAME_LENGTH_BYTES + 3U);
uint8_t frame[P25_HDU_FRAME_LENGTH_BYTES + 1U];
::memcpy(frame + 1U, m_buffer, m_endPtr / 8U);
uint8_t frame[P25_HDU_FRAME_LENGTH_BYTES + 1U];
::memcpy(frame + 1U, m_buffer, m_endPtr / 8U);
frame[0U] = 0x01U; // has sync
serial.writeP25Data(frame, (m_endPtr / 8U) + 1U);
reset();
}
}
else {
if (m_state == P25RXS_VOICE) {
m_lostCount = MAX_SYNC_FRAMES;
processVoice(bit);
}
frame[0U] = 0x01U; // has sync
serial.writeP25Data(frame, (m_endPtr / 8U) + 1U);
reset();
if (m_state == P25RXS_DATA) {
m_lostCount = MAX_SYNC_FRAMES;
processData(bit);
}
}
}
/// <summary>
/// Helper to process LDU P25 bits.
/// </summary>
/// <param name="bit"></param>
/* Helper to process LDU P25 bits. */
void P25RX::processVoice(bool bit)
{
// only search for a sync in the right place +-2 bits
@ -238,7 +226,7 @@ void P25RX::processVoice(bool bit)
// process NID
if (m_dataPtr == P25_SYNC_LENGTH_BITS + P25_NID_LENGTH_BITS + 1) {
DEBUG3("P25RX: processVoice(): dataPtr/endPtr", m_dataPtr, m_endPtr);
DEBUG3("P25RX::processVoice() dataPtr/endPtr", m_dataPtr, m_endPtr);
if (!decodeNid()) {
io.setDecode(false);
@ -250,7 +238,7 @@ void P25RX::processVoice(bool bit)
switch (m_duid) {
case P25_DUID_TDU:
{
DEBUG2("P25RX: processVoice(): sync found in TDU pos", m_dataPtr);
DEBUG2("P25RX::processVoice() sync found in TDU pos", m_dataPtr);
m_endPtr = P25_TDU_FRAME_LENGTH_BITS;
}
break;
@ -262,7 +250,7 @@ void P25RX::processVoice(bool bit)
return;
default:
{
DEBUG3("P25RX: processVoice(): illegal DUID in NID", m_nac, m_duid);
DEBUG3("P25RX::processVoice() illegal DUID in NID", m_nac, m_duid);
reset();
}
return;
@ -273,7 +261,7 @@ void P25RX::processVoice(bool bit)
// if we've reached the end pointer and the DUID is a TDU; send it
if (m_dataPtr == m_endPtr && m_duid == P25_DUID_TDU)
{
DEBUG2("P25RX: processVoice(): sync found in TDU pos", m_dataPtr);
DEBUG2("P25RX::processVoice() sync found in TDU pos", m_dataPtr);
uint8_t frame[P25_TDU_FRAME_LENGTH_BYTES + 1U];
::memcpy(frame + 1U, m_buffer, m_endPtr / 8U);
@ -293,7 +281,7 @@ void P25RX::processVoice(bool bit)
// we've not seen a data sync for too long, signal sync lost and change to P25RXS_NONE
if (m_lostCount == 0U) {
DEBUG1("P25RX: processVoice(): sync timeout in LDU, lost lock");
DEBUG1("P25RX::processVoice() sync timeout in LDU, lost lock");
io.setDecode(false);
@ -301,7 +289,7 @@ void P25RX::processVoice(bool bit)
reset();
}
else {
DEBUG2("P25RX: processVoice(): sync found in LDU pos", m_dataPtr);
DEBUG2("P25RX::processVoice() sync found in LDU pos", m_dataPtr);
uint8_t frame[P25_LDU_FRAME_LENGTH_BYTES + 3U];
::memcpy(frame + 1U, m_buffer, m_endPtr / 8U);
@ -321,10 +309,8 @@ void P25RX::processVoice(bool bit)
}
}
/// <summary>
/// Helper to process PDU P25 bits.
/// </summary>
/// <param name="bit"></param>
/* Helper to process PDU P25 bits. */
void P25RX::processData(bool bit)
{
// only search for a sync in the right place +-2 bits
@ -334,7 +320,7 @@ void P25RX::processData(bool bit)
// process NID
if (m_dataPtr == P25_SYNC_LENGTH_BITS + P25_NID_LENGTH_BITS + 1) {
DEBUG3("P25RX: processVoice(): dataPtr/endPtr", m_dataPtr, m_endPtr);
DEBUG3("P25RX::processData() dataPtr/pduEndPtr", m_dataPtr, m_pduEndPtr);
if (!decodeNid()) {
io.setDecode(false);
@ -345,11 +331,11 @@ void P25RX::processData(bool bit)
else {
switch (m_duid) {
case P25_DUID_PDU:
m_endPtr = P25_LDU_FRAME_LENGTH_BITS;
m_endPtr = m_pduEndPtr = P25_PDU_FRAME_LENGTH_BITS;
return;
default:
{
DEBUG3("P25RX: processData(): illegal DUID in NID", m_nac, m_duid);
DEBUG3("P25RX::processData() illegal DUID in NID", m_nac, m_duid);
reset();
}
return;
@ -357,13 +343,13 @@ void P25RX::processData(bool bit)
}
}
// process voice frame
if (m_dataPtr == m_endPtr) {
// process data frame
if (m_dataPtr == m_pduEndPtr) {
m_lostCount--;
// we've not seen a data sync for too long, signal sync lost and change to P25RXS_NONE
if (m_lostCount == 0U) {
DEBUG1("P25RX: processData(): sync timeout in PDU, lost lock");
DEBUG1("P25RX::processData() sync timeout in PDU, lost lock");
io.setDecode(false);
@ -371,21 +357,19 @@ void P25RX::processData(bool bit)
reset();
}
else {
DEBUG2("P25RX: processData(): sync found in PDU pos", m_dataPtr);
DEBUG2("P25RX::processData() sync found in PDU pos", m_dataPtr);
uint8_t frame[P25_LDU_FRAME_LENGTH_BYTES + 1U];
::memcpy(frame + 1U, m_buffer, m_endPtr / 8U);
uint8_t frame[P25_PDU_FRAME_LENGTH_BYTES + 1U];
::memcpy(frame + 1U, m_buffer, m_pduEndPtr / 8U);
frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; // set sync flag
serial.writeP25Data(frame, P25_LDU_FRAME_LENGTH_BYTES + 1U);
serial.writeP25Data(frame, P25_PDU_FRAME_LENGTH_BYTES + 1U);
}
}
}
/// <summary>
/// Frame synchronization correlator.
/// </summary>
/// <returns></returns>
/* Frame synchronization correlator. */
bool P25RX::correlateSync()
{
uint8_t maxErrs;
@ -399,7 +383,7 @@ bool P25RX::correlateSync()
if (errs <= maxErrs) {
::memset(m_buffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U);
DEBUG2("P25RX: correlateSync(): correlateSync errs", errs);
DEBUG2("P25RX::correlateSync() sync errs", errs);
// unpack sync bytes
uint8_t sync[P25_SYNC_BYTES_LENGTH];
@ -410,8 +394,8 @@ bool P25RX::correlateSync()
sync[4U] = (uint8_t)((m_bitBuffer >> 8) & 0xFFU);
sync[5U] = (uint8_t)((m_bitBuffer >> 0) & 0xFFU);
DEBUG4("P25RX: correlateSync(): sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("P25RX: correlateSync(): sync [b3 - b5]", sync[3], sync[4], sync[5]);
DEBUG4("P25RX::correlateSync() sync [b0 - b2]", sync[0], sync[1], sync[2]);
DEBUG4("P25RX::correlateSync() sync [b3 - b5]", sync[3], sync[4], sync[5]);
for (uint8_t i = 0U; i < P25_SYNC_BYTES_LENGTH; i++)
m_buffer[i] = sync[i];
@ -422,11 +406,14 @@ bool P25RX::correlateSync()
m_endPtr = m_dataPtr + P25_LDU_FRAME_LENGTH_BITS - P25_SYNC_LENGTH_BITS;
if (m_endPtr >= P25_LDU_FRAME_LENGTH_BITS)
m_endPtr -= P25_LDU_FRAME_LENGTH_BITS;
m_pduEndPtr = m_dataPtr + P25_PDU_FRAME_LENGTH_BITS - P25_SYNC_LENGTH_BITS;
if (m_pduEndPtr >= P25_PDU_FRAME_LENGTH_BITS)
m_pduEndPtr -= P25_PDU_FRAME_LENGTH_BITS;
m_lostCount = MAX_SYNC_FRAMES;
m_dataPtr = P25_SYNC_LENGTH_BITS;
DEBUG3("P25RX: correlateSync(): dataPtr/endPtr", m_dataPtr, m_endPtr);
DEBUG4("P25RX::correlateSync() dataPtr/endPtr/pduEndPtr", m_dataPtr, m_endPtr, m_pduEndPtr);
return true;
}
@ -434,9 +421,8 @@ bool P25RX::correlateSync()
return false;
}
/// <summary>
/// Helper to decode the P25 NID.
/// </summary>
/* Helper to decode the P25 NID. */
bool P25RX::decodeNid()
{
uint8_t nid[P25_NID_LENGTH_BYTES];
@ -445,18 +431,18 @@ bool P25RX::decodeNid()
if (m_nac == 0xF7EU) {
m_duid = nid[1U] & 0x0FU;
DEBUG2("P25RX: decodeNid(): DUID for xDU", m_duid);
DEBUG2("P25RX::decodeNid() DUID for xDU", m_duid);
return true;
}
uint16_t nac = (nid[0U] << 4) | ((nid[1U] & 0xF0U) >> 4);
if (nac == m_nac) {
m_duid = nid[1U] & 0x0FU;
DEBUG2("P25RX: decodeNid(): DUID for xDU", m_duid);
DEBUG2("P25RX::decodeNid() DUID for xDU", m_duid);
return true;
}
else {
DEBUG3("P25RX: decodeNid(): invalid NAC found; nac != m_nac", nac, m_nac);
DEBUG3("P25RX::decodeNid() invalid NAC found; nac != m_nac", nac, m_nac);
}
return false;

@ -1,34 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2021 Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017,2018 Andy Uribe, CA6JAU
* Copyright (C) 2021-2024 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file P25RX.h
* @ingroup p25_hfw
* @file P25RX.cpp
* @ingroup p25_hfw
*/
#if !defined(__P25_RX_H__)
#define __P25_RX_H__
@ -41,39 +27,57 @@ namespace p25
// Constants
// ---------------------------------------------------------------------------
/**
* @brief P25 Receiver State
* @ingroup p25_hfw
*/
enum P25RX_STATE {
P25RXS_NONE,
P25RXS_SYNC,
P25RXS_VOICE,
P25RXS_DATA
P25RXS_NONE, //! None
P25RXS_SYNC, //! Found Sync
P25RXS_VOICE, //! Voice Data
P25RXS_DATA //! PDU Data
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements receiver logic for P25 mode operation.
// ---------------------------------------------------------------------------
/**
* @brief Implements receiver logic for P25 mode operation.
* @ingroup p25_hfw
*/
class DSP_FW_API P25RX {
public:
/// <summary>Initializes a new instance of the P25RX class.</summary>
/**
* @brief Initializes a new instance of the P25RX class.
*/
P25RX();
/// <summary>Helper to reset data values to defaults.</summary>
/**
* @brief Helper to reset data values to defaults.
*/
void reset();
/// <summary>Sample P25 bits from the air interface.</summary>
/**
* @brief Sample P25 bits from the air interface.
* @param bit
*/
void databit(bool bit);
/// <summary>Sets the P25 NAC.</summary>
/**
* @brief Sets the P25 NAC.
* @param nac Network Access Code.
*/
void setNAC(uint16_t nac);
private:
uint64_t m_bitBuffer;
uint8_t m_buffer[P25_LDU_FRAME_LENGTH_BYTES + 3U];
uint8_t m_buffer[P25_PDU_FRAME_LENGTH_BYTES + 3U];
uint16_t m_dataPtr;
uint16_t m_endPtr;
uint16_t m_pduEndPtr;
uint16_t m_lostCount;
@ -83,17 +87,32 @@ namespace p25
uint8_t m_duid;
/// <summary>Helper to process P25 bits.</summary>
/**
* @brief Helper to process P25 bits.
* @param bit
*/
void processBit(bool bit);
/// <summary>Helper to process LDU P25 bits.</summary>
/**
* @brief Helper to process LDU P25 bits.
* @param bit
*/
void processVoice(bool bit);
/// <summary>Helper to process PDU P25 bits.</summary>
/**
* @brief Helper to process PDU P25 bits.
* @param bit
*/
void processData(bool bit);
/// <summary>Frame synchronization correlator.</summary>
/**
* @brief Frame synchronization correlator.
* @returns bool
*/
bool correlateSync();
/// <summary>Helper to decode the P25 NID.</summary>
/**
* @brief Helper to decode the P25 NID.
* @returns bool True, if P25 NID was decoded, otherwise false.
*/
bool decodeNid();
};
} // namespace p25

@ -1,34 +1,14 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU
* Copyright (C) 2021-2022 by Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017 Andy Uribe, CA6JAU
* Copyright (C) 2021-2022 Bryan Biedenkapp, N2PLL
*
*/
#include "Globals.h"
#include "p25/P25TX.h"
#include "p25/P25Defines.h"
@ -39,9 +19,8 @@ using namespace p25;
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the P25TX class.
/// </summary>
/* Initializes a new instance of the P25TX class. */
P25TX::P25TX() :
m_fifo(P25_TX_BUFFER_LEN),
m_state(P25TXSTATE_NORMAL),
@ -55,9 +34,8 @@ P25TX::P25TX() :
/* stub */
}
/// <summary>
/// Process local buffer and transmit on the air interface.
/// </summary>
/* Process local buffer and transmit on the air interface. */
void P25TX::process()
{
if (m_fifo.getData() == 0U && m_poLen == 0U && m_tailCnt > 0U &&
@ -94,8 +72,6 @@ void P25TX::process()
createData();
}
DEBUG2("P25TX: process(): poLen", m_poLen);
}
if (m_poLen > 0U) {
@ -118,43 +94,44 @@ void P25TX::process()
}
}
/// <summary>
/// Write data to the local buffer.
/// </summary>
/// <param name="data"></param>
/// <param name="length"></param>
/// <returns></returns>
uint8_t P25TX::writeData(const uint8_t* data, uint8_t length)
/* Write data to the local buffer. */
uint8_t P25TX::writeData(const uint8_t* data, uint16_t length)
{
if (length < (P25_TDU_FRAME_LENGTH_BYTES + 1U))
return RSN_ILLEGAL_LENGTH;
uint16_t space = m_fifo.getSpace();
DEBUG3("P25TX: writeData(): dataLength/fifoLength", length, space);
DEBUG3("P25TX::writeData() dataLength/fifoLength", length, space);
if (space < length) {
m_fifo.reset();
return RSN_RINGBUFF_FULL;
}
m_fifo.put(length - 1U);
for (uint8_t i = 0U; i < (length - 1U); i++)
if (length <= 255U) {
m_fifo.put(DVM_SHORT_FRAME_START);
m_fifo.put(length - 1U);
} else {
m_fifo.put(DVM_LONG_FRAME_START);
m_fifo.put(((length - 1U) >> 8U) & 0xFFU);
m_fifo.put((length - 1U) & 0xFFU);
}
for (uint16_t i = 0U; i < (length - 1U); i++)
m_fifo.put(data[i + 1U]);
return RSN_OK;
}
/// <summary>
/// Clears the local buffer.
/// </summary>
/* Clears the local buffer. */
void P25TX::clear()
{
m_fifo.reset();
}
/// <summary>
/// Sets the FDMA preamble count.
/// </summary>
/// <param name="preambleCnt">Count of preambles.</param>
/* Sets the FDMA preamble count. */
void P25TX::setPreambleCount(uint8_t preambleCnt)
{
m_preambleCnt = P25_FIXED_DELAY + preambleCnt;
@ -164,10 +141,8 @@ void P25TX::setPreambleCount(uint8_t preambleCnt)
m_preambleCnt = 1200U;
}
/// <summary>
/// Sets the Tx hang time.
/// </summary>
/// <param name="txHang">Transmit hang time in seconds.</param>
/* Sets the Tx hang time. */
void P25TX::setTxHang(uint8_t txHang)
{
if (txHang > 0U)
@ -180,19 +155,23 @@ void P25TX::setTxHang(uint8_t txHang)
m_txHang = 13U * 1200U;
}
/// <summary>
/// Helper to set the calibration state for Tx.
/// </summary>
/// <param name="start"></param>
/* Helper to set the calibration state for Tx. */
void P25TX::setCal(bool start)
{
m_state = start ? P25TXSTATE_CAL : P25TXSTATE_NORMAL;
}
/// <summary>
/// Helper to get how much space the ring buffer has for samples.
/// </summary>
/// <returns></returns>
/* Helper to resize the FIFO buffer. */
void P25TX::resizeBuffer(uint16_t size)
{
m_fifo.reset();
m_fifo.reinitialize(size);
}
/* Helper to get how much space the ring buffer has for samples. */
uint8_t P25TX::getSpace() const
{
return m_fifo.getSpace() / P25_LDU_FRAME_LENGTH_BYTES;
@ -202,9 +181,8 @@ uint8_t P25TX::getSpace() const
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/* Helper to generate data. */
void P25TX::createData()
{
if (!m_tx) {
@ -212,9 +190,19 @@ void P25TX::createData()
m_poBuffer[m_poLen++] = P25_START_SYNC;
}
else {
uint8_t length = m_fifo.get();
DEBUG3("P25TX: createData(): dataLength/fifoSpace", length, m_fifo.getSpace());
for (uint8_t i = 0U; i < length; i++) {
uint8_t frameType = m_fifo.get();
uint16_t length = 0U;
switch (frameType) {
case DVM_SHORT_FRAME_START:
length = m_fifo.get();
break;
case DVM_LONG_FRAME_START:
length = ((m_fifo.get() & 0xFFU) << 8) + (m_fifo.get());
break;
}
DEBUG3("P25TX::createData() dataLength/fifoSpace", length, m_fifo.getSpace());
for (uint16_t i = 0U; i < length; i++) {
m_poBuffer[m_poLen++] = m_fifo.get();
}
}
@ -222,14 +210,13 @@ void P25TX::createData()
m_poPtr = 0U;
}
/// <summary>
///
/// </summary>
/* Helper to generate calibration data. */
void P25TX::createCal()
{
// 1.2 kHz sine wave generation
if (m_modemState == STATE_P25_CAL) {
for (unsigned int i = 0U; i < P25_LDU_FRAME_LENGTH_BYTES; i++) {
for (uint8_t i = 0U; i < P25_LDU_FRAME_LENGTH_BYTES; i++) {
m_poBuffer[i] = P25_START_SYNC;
}
@ -240,10 +227,8 @@ void P25TX::createCal()
m_poPtr = 0U;
}
/// <summary>
///
/// </summary>
/// <param name="c"></param>
/* Helper to write a raw byte to the DAC. */
void P25TX::writeByte(uint8_t c)
{
uint8_t bit;
@ -259,9 +244,8 @@ void P25TX::writeByte(uint8_t c)
}
}
/// <summary>
///
/// </summary>
/* */
void P25TX::writeSilence()
{
uint8_t bit;

@ -1,34 +1,20 @@
/**
* Digital Voice Modem - DSP Firmware (Hotspot)
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* @package DVM / DSP Firmware (Hotspot)
*
*/
//
// Based on code from the MMDVM_HS project. (https://github.com/juribeparada/MMDVM_HS)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU
* Copyright (C) 2021-2022 by Bryan Biedenkapp N2PLL
*
* 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.
*/
* Digital Voice Modem - Hotspot Firmware
* GPLv2 Open Source. Use is subject to license terms.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright (C) 2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2016,2017 Andy Uribe, CA6JAU
* Copyright (C) 2021-2022 Bryan Biedenkapp, N2PLL
*
*/
/**
* @file P25TX.h
* @ingroup p25_hfw
* @file P25TX.cpp
* @ingroup p25_hfw
*/
#if !defined(__P25_TX_H__)
#define __P25_TX_H__
@ -44,38 +30,74 @@ namespace p25
#define P25_FIXED_DELAY 90 // 90 = 20ms
#define P25_FIXED_TX_HANG 750 // 750 = 625ms
/**
* @brief P25 Transmitter State
* @ingroup p25_hfw
*/
enum P25TXSTATE {
P25TXSTATE_NORMAL,
P25TXSTATE_CAL
P25TXSTATE_NORMAL, //! Normal
P25TXSTATE_CAL //! Calibration
};
// ---------------------------------------------------------------------------
// Class Declaration
// Implements transmitter logic for P25 mode operation.
// ---------------------------------------------------------------------------
/**
* @brief Implements transmitter logic for P25 mode operation.
* @ingroup p25_hfw
*/
class DSP_FW_API P25TX {
public:
/// <summary>Initializes a new instance of the P25TX class.</summary>
/**
* @brief Initializes a new instance of the P25TX class.
*/
P25TX();
/// <summary>Process local buffer and transmit on the air interface.</summary>
/**
* @brief Process local buffer and transmit on the air interface.
*/
void process();
/// <summary>Write data to the local buffer.</summary>
uint8_t writeData(const uint8_t* data, uint8_t length);
/// <summary>Clears the local buffer.</summary>
/**
* @brief Write data to the local buffer.
* @param[in] data Buffer.
* @param length Length of buffer.
* @returns uint8_t Reason code.
*/
uint8_t writeData(const uint8_t* data, uint16_t length);
/**
* @brief Clears the local buffer.
*/
void clear();
/// <summary>Sets the FDMA preamble count.</summary>
/**
* @brief Sets the FDMA preamble count.
* @param preambleCnt FDMA preamble count.
*/
void setPreambleCount(uint8_t preambleCnt);
/// <summary>Sets the transmit hang time.</summary>
/**
* @brief Sets the transmit hang time.
* @param txHang Transmit hang time.
*/
void setTxHang(uint8_t txHang);
/// <summary>Helper to set the calibration state for Tx.</summary>
/**
* @brief Helper to set the calibration state for Tx.
* @param start
*/
void setCal(bool start);
/// <summary>Helper to get how much space the ring buffer has for samples.</summary>
/**
* @brief Helper to resize the FIFO buffer.
* @param size
*/
void resizeBuffer(uint16_t size);
/**
* @brief Helper to get how much space the ring buffer has for samples.
* @returns uint8_t Amount of space in ring buffer for samples.
*/
uint8_t getSpace() const;
private:
@ -91,14 +113,23 @@ namespace p25
uint32_t m_txHang;
uint32_t m_tailCnt;
/// <summary></summary>
/**
* @brief Helper to generate data.
*/
void createData();
/// <summary></summary>
/**
* @brief Helper to generate calibration data.
*/
void createCal();
/// <summary></summary>
/**
* @brief Helper to write a raw byte to the DAC.
* @param c Byte.
*/
void writeByte(uint8_t c);
/// <summary></summary>
/**
* @brief
*/
void writeSilence();
};
} // namespace p25

@ -1,26 +0,0 @@
/*
* Copyright (C) 2016-2018 by Andy Uribe CA6JAU
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Memory areas */
MEMORY
{
ROM (rx) : ORIGIN = 0x08002000, LENGTH = 120K /* FLASH */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K /* Main RAM */
}
INCLUDE stm32f10x_link.ld
Loading…
Cancel
Save

Powered by TurnKey Linux.