mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-10-15 16:24:11 +02:00
Compare commits
71
Commits
PlatformIO
..
boxcar
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2a7c11dee | ||
|
|
d2061e05ac | ||
|
|
3a0409c5a1 | ||
|
|
230c26ac4f | ||
|
|
c3db2cd730 | ||
|
|
fe2846a894 | ||
|
|
273e4f63aa | ||
|
|
ef26b598f9 | ||
|
|
341bfe4815 | ||
|
|
a53b3656ff | ||
|
|
5dade9c1d9 | ||
|
|
bcd71edd90 | ||
|
|
ace9780b1f | ||
|
|
0aace49867 | ||
|
|
ac7bd9d2fd | ||
|
|
c06a32af07 | ||
|
|
b40701a8e6 | ||
|
|
608a10d159 | ||
|
|
7ef6708d9d | ||
|
|
a0706c9fd4 | ||
|
|
21cd848064 | ||
|
|
a69d1adaf0 | ||
|
|
2eff3090a9 | ||
|
|
ce51b8daa8 | ||
|
|
aa70be0973 | ||
|
|
cadbfaa546 | ||
|
|
bd413d2e05 | ||
|
|
7ab774d941 | ||
|
|
1a1f721b3f | ||
|
|
bed9665b3a | ||
|
|
056016c022 | ||
|
|
a582cbe1e3 | ||
|
|
7454a08e4a | ||
|
|
0fc3e8182d | ||
|
|
335fba3930 | ||
|
|
374fae594c | ||
|
|
24ac2b902d | ||
|
|
dbd84d7803 | ||
|
|
c1f12705a9 | ||
|
|
6192a88b98 | ||
|
|
8651e3a77b | ||
|
|
cb00f4aba7 | ||
|
|
91a87f4581 | ||
|
|
bf1de4f307 | ||
|
|
5f8a323dde | ||
|
|
436ca1d851 | ||
|
|
ec34eb4a64 | ||
|
|
b76e95b540 | ||
|
|
b017e75787 | ||
|
|
6221386873 | ||
|
|
3c1b41c03f | ||
|
|
7e85a64a41 | ||
|
|
c820b22524 | ||
|
|
7fae32042f | ||
|
|
ebd86df3ef | ||
|
|
918403c399 | ||
|
|
7c243af5da | ||
|
|
7bb042a6ca | ||
|
|
fbd9c4d18b | ||
|
|
58966406da | ||
|
|
e707391a5e | ||
|
|
cff5a58bc7 | ||
|
|
51577efd79 | ||
|
|
469be87dc3 | ||
|
|
8ce38eec9a | ||
|
|
68f0fa8132 | ||
|
|
954131f73c | ||
|
|
06ec4b79a5 | ||
|
|
de0aed2d2b | ||
|
|
4b253f888d | ||
|
|
316085f2a6 |
+5
-3
@@ -1,3 +1,5 @@
|
|||||||
.pio
|
*.o
|
||||||
.vscode
|
obj/
|
||||||
|
bin/
|
||||||
|
GitVersion.h
|
||||||
|
build/
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
[submodule "STM32F4XX_Lib"]
|
||||||
|
path = STM32F4XX_Lib
|
||||||
|
url = https://github.com/juribeparada/STM32F4XX_Lib.git
|
||||||
|
[submodule "STM32F7XX_Lib"]
|
||||||
|
path = STM32F7XX_Lib
|
||||||
|
url = https://github.com/juribeparada/STM32F7XX_Lib.git
|
||||||
|
[submodule "STM32F10X_Lib"]
|
||||||
|
path = STM32F10X_Lib
|
||||||
|
url = https://github.com/shawnchain/STM32F10X_Lib.git
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
In order to build MMDVM, you need to tell the Arduino GUI to link with the
|
||||||
|
CMSIS DSP library, which is doesn't do by default.
|
||||||
|
|
||||||
|
My development is on Windows and so I can vouch for the following instructions.
|
||||||
|
|
||||||
|
For Arduino 1.6.3 with SAM 1.6.4
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
1. Go to the where the platform.txt file is located. On my Windows machine it's
|
||||||
|
in:
|
||||||
|
|
||||||
|
C:\Users\Jonathan\AppData\Roaming\Arduino15\packages\arduino\hardware\sam\1.6.4
|
||||||
|
|
||||||
|
On Mac OS X it's located in:
|
||||||
|
|
||||||
|
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/sam
|
||||||
|
Or
|
||||||
|
~/Library/Arduino15/packages/arduino/hardware/sam/1.6.6
|
||||||
|
|
||||||
|
2. You'll need to open the file in a text editor and find the line:
|
||||||
|
|
||||||
|
## Combine gc-sections, archives, and objects
|
||||||
|
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
|
||||||
|
|
||||||
|
In my version it's line 73.
|
||||||
|
|
||||||
|
3. Modify it to read as follows:
|
||||||
|
|
||||||
|
## Combine gc-sections, archives, and objects
|
||||||
|
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
|
||||||
|
|
||||||
|
The change is near the end, and is the addition of:
|
||||||
|
|
||||||
|
"{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib"
|
||||||
|
|
||||||
|
Which is the CMSIS AMR3 DSP library for little-endian operation.
|
||||||
|
|
||||||
|
4. Save the file and start up the Arduino GUI and build MMDVM.
|
||||||
|
|
||||||
|
I would like to get instructions for doing the same on a Linux platform. As a
|
||||||
|
starter find the relevent platform.txt and try adding:
|
||||||
|
|
||||||
|
"{build.system.path}/CMSIS/CMSIS/Lib/ARM/libarm_cortexM3l_math.a"
|
||||||
|
|
||||||
|
or maybe:
|
||||||
|
|
||||||
|
"{build.variant.path}/libarm_cortexM3l_math.a"
|
||||||
|
|
||||||
|
Likely on Linux
|
||||||
|
|
||||||
|
"{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a"
|
||||||
|
|
||||||
|
As with Arduino 1.6.7 with SAM 1.6.6, see below.
|
||||||
|
|
||||||
|
|
||||||
|
For Arduino 1.6.7 with SAM 1.6.6
|
||||||
|
--------------------------------
|
||||||
|
(checked OK on Arduino 1.6.11 and SAM 1.6.9)
|
||||||
|
|
||||||
|
1. Go to the where the platform.txt file is located. On my Windows machine it's
|
||||||
|
in:
|
||||||
|
|
||||||
|
C:\Users\Jonathan\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.6
|
||||||
|
|
||||||
|
On Mac OS X it's located in:
|
||||||
|
|
||||||
|
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/sam
|
||||||
|
|
||||||
|
On Linux, it's located in my home directory, downloaded and extracted from Arduino website, but must be installed.
|
||||||
|
|
||||||
|
/home/m1geo/arduino-1.6.7/hardware/arduino/sam
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
/home/m1geo/.arduino15/packages/arduino/hardware/sam/1.6.9 (if you let the board/library manager install SAM)
|
||||||
|
|
||||||
|
|
||||||
|
I (M1GEO) found it was necessary to download SAM-1.6.6 outside of the Arduino IDE, and manually extract the files.
|
||||||
|
The Board Manager didn't seem to install the SAM files correctly. Here's how I did it:
|
||||||
|
|
||||||
|
a) wget http://downloads.arduino.cc/cores/sam-1.6.6.tar.bz2 -O /tmp/sam-1.6.6.tar.bz2 (download and save in /tmp)
|
||||||
|
b) cd arduino-1.6.7/hardware/arduino/ (Arduino root, here, in my home directory)
|
||||||
|
c) tar xvfj /tmp/sam-1.6.6.tar.bz2
|
||||||
|
|
||||||
|
2. You'll need to open the file (platform.txt) in a text editor and find the line:
|
||||||
|
|
||||||
|
## Combine gc-sections, archives, and objects
|
||||||
|
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group "{build.path}/core/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
|
||||||
|
|
||||||
|
In my version it's line 73.
|
||||||
|
|
||||||
|
3. Modify it to read as follows:
|
||||||
|
|
||||||
|
## Combine gc-sections, archives, and objects
|
||||||
|
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group "{build.path}/core/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
|
||||||
|
|
||||||
|
The change is near the end, and is the addition of:
|
||||||
|
|
||||||
|
"{build.system.path}/CMSIS/CMSIS/Lib/ARM/arm_cortexM3l_math.lib"
|
||||||
|
|
||||||
|
On Linux, the path was found to differ slightly (GCC instead of ARM):
|
||||||
|
|
||||||
|
"{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a"
|
||||||
|
|
||||||
|
Which is the CMSIS AMR3 DSP library for little-endian operation.
|
||||||
|
|
||||||
|
4. Save the file and start up the Arduino GUI and build MMDVM.
|
||||||
|
|
||||||
|
For Arduino 1.6.9 with SAM 1.6.8
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
1. Locate platform.txt. On Ubuntu 14.04 LTS x86_64 OS it is in:
|
||||||
|
|
||||||
|
/home/$user/.arduino15/packages/arduino/hardware/sam/1.6.8/
|
||||||
|
|
||||||
|
2. Open the file in a text editor and change the line:
|
||||||
|
|
||||||
|
## Combine gc-sections, archives, and objects
|
||||||
|
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
|
||||||
|
|
||||||
|
to
|
||||||
|
|
||||||
|
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.system.path}/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc
|
||||||
|
|
||||||
|
3. Save the file, open the Arduino IDE and build MMDVM
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -125,7 +125,7 @@ void CCWIdTX::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CCWIdTX::write(const uint8_t* data, uint16_t length)
|
uint8_t CCWIdTX::write(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
::memset(m_poBuffer, 0x00U, 1000U * sizeof(uint8_t));
|
::memset(m_poBuffer, 0x00U, 1000U * sizeof(uint8_t));
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016,2020 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
uint8_t write(const uint8_t* data, uint16_t length);
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -18,9 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "CalDMR.h"
|
#include "CalDMR.h"
|
||||||
|
|
||||||
@@ -211,7 +208,7 @@ void CCalDMR::dmrdmo1k()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CCalDMR::write(const uint8_t* data, uint16_t length)
|
uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != 1U)
|
if (length != 1U)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -224,5 +221,3 @@ uint8_t CCalDMR::write(const uint8_t* data, uint16_t length)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -17,13 +17,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#if !defined(CALDMR_H)
|
#if !defined(CALDMR_H)
|
||||||
#define CALDMR_H
|
#define CALDMR_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DMRDefines.h"
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
enum DMRCAL1K {
|
enum DMRCAL1K {
|
||||||
@@ -44,7 +41,7 @@ public:
|
|||||||
void createData1k(uint8_t n);
|
void createData1k(uint8_t n);
|
||||||
void createDataDMO1k(uint8_t n);
|
void createDataDMO1k(uint8_t n);
|
||||||
|
|
||||||
uint8_t write(const uint8_t* data, uint16_t length);
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_transmit;
|
bool m_transmit;
|
||||||
@@ -56,5 +53,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2016,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "CalDStarRX.h"
|
#include "CalDStarRX.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
@@ -27,7 +24,7 @@
|
|||||||
const unsigned int BUFFER_LENGTH = 200U;
|
const unsigned int BUFFER_LENGTH = 200U;
|
||||||
|
|
||||||
const uint32_t PLLMAX = 0x10000U;
|
const uint32_t PLLMAX = 0x10000U;
|
||||||
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_SYMBOL_LENGTH;
|
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
|
||||||
const uint32_t INC = PLLINC / 32U;
|
const uint32_t INC = PLLINC / 32U;
|
||||||
|
|
||||||
// D-Star bit order version of 0x55 0x2D 0x16
|
// D-Star bit order version of 0x55 0x2D 0x16
|
||||||
@@ -129,5 +126,3 @@ void CCalDStarRX::process(q15_t value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,13 +16,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
|
|
||||||
#if !defined(CALDSTARRX_H)
|
#if !defined(CALDSTARRX_H)
|
||||||
#define CALDSTARRX_H
|
#define CALDSTARRX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DStarDefines.h"
|
#include "DStarDefines.h"
|
||||||
|
|
||||||
class CCalDStarRX {
|
class CCalDStarRX {
|
||||||
@@ -43,5 +40,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2016,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "CalDStarTX.h"
|
#include "CalDStarTX.h"
|
||||||
|
|
||||||
@@ -165,7 +162,7 @@ void CCalDStarTX::process()
|
|||||||
m_count = (m_count + 1U) % (30U * 21U);
|
m_count = (m_count + 1U) % (30U * 21U);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CCalDStarTX::write(const uint8_t* data, uint16_t length)
|
uint8_t CCalDStarTX::write(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != 1U)
|
if (length != 1U)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -184,5 +181,3 @@ uint8_t CCalDStarTX::write(const uint8_t* data, uint16_t length)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,20 +16,17 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
|
|
||||||
#if !defined(CALDSTARTX_H)
|
#if !defined(CALDSTARTX_H)
|
||||||
#define CALDSTARTX_H
|
#define CALDSTARTX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DStarDefines.h"
|
#include "DStarDefines.h"
|
||||||
|
|
||||||
class CCalDStarTX {
|
class CCalDStarTX {
|
||||||
public:
|
public:
|
||||||
CCalDStarTX();
|
CCalDStarTX();
|
||||||
|
|
||||||
uint8_t write(const uint8_t* data, uint16_t length);
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
@@ -40,5 +37,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
* Copyright (C) 2020 by Phil Taylor M0VSE
|
* Copyright (C) 2020 by Phil Taylor M0VSE
|
||||||
*
|
*
|
||||||
@@ -19,9 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "CalFM.h"
|
#include "CalFM.h"
|
||||||
|
|
||||||
@@ -55,7 +52,7 @@ void CCalFM::process()
|
|||||||
{
|
{
|
||||||
const TONE_TABLE* entry = NULL;
|
const TONE_TABLE* entry = NULL;
|
||||||
|
|
||||||
if (m_modemState != m_lastState)
|
if (m_modemState!=m_lastState)
|
||||||
{
|
{
|
||||||
switch (m_modemState) {
|
switch (m_modemState) {
|
||||||
case STATE_FMCAL10K:
|
case STATE_FMCAL10K:
|
||||||
@@ -119,7 +116,7 @@ void CCalFM::process()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t CCalFM::write(const uint8_t* data, uint16_t length)
|
uint8_t CCalFM::write(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != 1U)
|
if (length != 1U)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -128,6 +125,3 @@ uint8_t CCalFM::write(const uint8_t* data, uint16_t length)
|
|||||||
|
|
||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
* Copyright (C) 2020 by Phil Taylor M0VSE
|
* Copyright (C) 2020 by Phil Taylor M0VSE
|
||||||
*
|
*
|
||||||
@@ -18,13 +18,11 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#if !defined(CALFM_H)
|
#if !defined(CALFM_H)
|
||||||
#define CALFM_H
|
#define CALFM_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
class CCalFM {
|
class CCalFM {
|
||||||
public:
|
public:
|
||||||
CCalFM();
|
CCalFM();
|
||||||
@@ -37,7 +35,7 @@ public:
|
|||||||
void fm25kcal();
|
void fm25kcal();
|
||||||
void fm30kcal();
|
void fm30kcal();
|
||||||
|
|
||||||
uint8_t write(const uint8_t* data, uint16_t length);
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t m_frequency;
|
uint16_t m_frequency;
|
||||||
@@ -51,5 +49,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -18,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "CalNXDN.h"
|
#include "CalNXDN.h"
|
||||||
|
|
||||||
@@ -83,7 +79,7 @@ void CCalNXDN::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CCalNXDN::write(const uint8_t* data, uint16_t length)
|
uint8_t CCalNXDN::write(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != 1U)
|
if (length != 1U)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -96,5 +92,3 @@ uint8_t CCalNXDN::write(const uint8_t* data, uint16_t length)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,13 +16,11 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
|
|
||||||
#if !defined(CALNXDN_H)
|
#if !defined(CALNXDN_H)
|
||||||
#define CALNXDN_H
|
#define CALNXDN_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
enum NXDNCAL1K {
|
enum NXDNCAL1K {
|
||||||
NXDNCAL1K_IDLE,
|
NXDNCAL1K_IDLE,
|
||||||
NXDNCAL1K_TX
|
NXDNCAL1K_TX
|
||||||
@@ -35,7 +32,7 @@ public:
|
|||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
uint8_t write(const uint8_t* data, uint16_t length);
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_transmit;
|
bool m_transmit;
|
||||||
@@ -45,5 +42,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -18,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "CalP25.h"
|
#include "CalP25.h"
|
||||||
|
|
||||||
@@ -86,7 +82,7 @@ void CCalP25::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CCalP25::write(const uint8_t* data, uint16_t length)
|
uint8_t CCalP25::write(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != 1U)
|
if (length != 1U)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -99,5 +95,3 @@ uint8_t CCalP25::write(const uint8_t* data, uint16_t length)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,13 +16,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
|
|
||||||
#if !defined(CALP25_H)
|
#if !defined(CALP25_H)
|
||||||
#define CALP25_H
|
#define CALP25_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "P25Defines.h"
|
#include "P25Defines.h"
|
||||||
|
|
||||||
enum P25CAL1K {
|
enum P25CAL1K {
|
||||||
@@ -38,7 +34,7 @@ public:
|
|||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
uint8_t write(const uint8_t* data, uint16_t length);
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_transmit;
|
bool m_transmit;
|
||||||
@@ -47,5 +43,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 by Florian Wolters DF2ET
|
* Copyright (C) 2019 by Florian Wolters DF2ET
|
||||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -18,12 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_POCSAG)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "CalPOCSAG.h"
|
#include "CalPOCSAG.h"
|
||||||
|
|
||||||
|
|
||||||
CCalPOCSAG::CCalPOCSAG() :
|
CCalPOCSAG::CCalPOCSAG() :
|
||||||
m_state(POCSAGCAL_IDLE)
|
m_state(POCSAGCAL_IDLE)
|
||||||
{
|
{
|
||||||
@@ -41,7 +38,7 @@ void CCalPOCSAG::process()
|
|||||||
pocsagTX.writeByte(0xAAU);
|
pocsagTX.writeByte(0xAAU);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CCalPOCSAG::write(const uint8_t* data, uint16_t length)
|
uint8_t CCalPOCSAG::write(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != 1U)
|
if (length != 1U)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -50,6 +47,3 @@ uint8_t CCalPOCSAG::write(const uint8_t* data, uint16_t length)
|
|||||||
|
|
||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 by Florian Wolters DF2ET
|
* Copyright (C) 2019 by Florian Wolters DF2ET
|
||||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,13 +16,11 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_POCSAG)
|
|
||||||
|
|
||||||
#if !defined(CALPOCSAG_H)
|
#if !defined(CALPOCSAG_H)
|
||||||
#define CALPOCSAG_H
|
#define CALPOCSAG_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
enum POCSAGCAL {
|
enum POCSAGCAL {
|
||||||
POCSAGCAL_IDLE,
|
POCSAGCAL_IDLE,
|
||||||
POCSAGCAL_TX
|
POCSAGCAL_TX
|
||||||
@@ -35,13 +32,10 @@ public:
|
|||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
uint8_t write(const uint8_t* data, uint16_t length);
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
POCSAGCAL m_state;
|
POCSAGCAL m_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(CONFIG_H)
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
// Allow for the use of high quality external clock oscillators
|
||||||
|
// The number is the frequency of the oscillator in Hertz.
|
||||||
|
//
|
||||||
|
// The frequency of the TCXO must be an integer multiple of 48000.
|
||||||
|
// Frequencies such as 12.0 Mhz (48000 * 250) and 14.4 Mhz (48000 * 300) are suitable.
|
||||||
|
// Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable.
|
||||||
|
//
|
||||||
|
// For 12 MHz
|
||||||
|
#define EXTERNAL_OSC 12000000
|
||||||
|
// For 12.288 MHz
|
||||||
|
// #define EXTERNAL_OSC 12288000
|
||||||
|
// For 14.4 MHz
|
||||||
|
// #define EXTERNAL_OSC 14400000
|
||||||
|
// For 19.2 MHz
|
||||||
|
// #define EXTERNAL_OSC 19200000
|
||||||
|
|
||||||
|
// Allow the use of the COS line to lockout the modem
|
||||||
|
// #define USE_COS_AS_LOCKOUT
|
||||||
|
|
||||||
|
// Use pins to output the current mode via LEDs
|
||||||
|
// #define MODE_LEDS
|
||||||
|
|
||||||
|
// For the original Arduino Due pin layout
|
||||||
|
// #define ARDUINO_DUE_PAPA
|
||||||
|
|
||||||
|
#if defined(STM32F1)
|
||||||
|
// For the SQ6POG board
|
||||||
|
#define STM32F1_POG
|
||||||
|
#else
|
||||||
|
// For the ZUM V1.0 and V1.0.1 boards pin layout
|
||||||
|
#define ARDUINO_DUE_ZUM_V10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// For the SP8NTH board
|
||||||
|
// #define ARDUINO_DUE_NTH
|
||||||
|
|
||||||
|
// For ST Nucleo-64 STM32F446RE board
|
||||||
|
// #define STM32F4_NUCLEO_MORPHO_HEADER
|
||||||
|
// #define STM32F4_NUCLEO_ARDUINO_HEADER
|
||||||
|
|
||||||
|
// Use separate mode pins to switch external channel/filters/bandwidth for example
|
||||||
|
// #define MODE_PINS
|
||||||
|
|
||||||
|
// For the VK6MST Pi3 Shield communicating over i2c. i2c address & speed defined in i2cTeensy.cpp
|
||||||
|
// #define VK6MST_TEENSY_PI3_SHIELD_I2C
|
||||||
|
|
||||||
|
// Pass RSSI information to the host
|
||||||
|
// #define SEND_RSSI_DATA
|
||||||
|
|
||||||
|
// Use the modem as a serial repeater for Nextion displays
|
||||||
|
// #define SERIAL_REPEATER
|
||||||
|
|
||||||
|
// To reduce CPU load, you can remove the DC blocker by commenting out the next line
|
||||||
|
#define USE_DCBLOCKER
|
||||||
|
|
||||||
|
// Constant Service LED once repeater is running
|
||||||
|
// Do not use if employing an external hardware watchdog
|
||||||
|
// #define CONSTANT_SRV_LED
|
||||||
|
|
||||||
|
// Use the YSF and P25 LEDs for NXDN
|
||||||
|
// #define USE_ALTERNATE_NXDN_LEDS
|
||||||
|
|
||||||
|
// Use the D-Star and DMR LEDs for POCSAG
|
||||||
|
// #define USE_ALTERNATE_POCSAG_LEDS
|
||||||
|
|
||||||
|
// Use the D-Star and YSF LEDs for FM
|
||||||
|
#define USE_ALTERNATE_FM_LEDS
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DMRDMORX.h"
|
#include "DMRDMORX.h"
|
||||||
#include "DMRSlotType.h"
|
#include "DMRSlotType.h"
|
||||||
@@ -426,6 +423,3 @@ void CDMRDMORX::writeRSSIData(uint8_t* frame)
|
|||||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,13 +16,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#if !defined(DMRDMORX_H)
|
#if !defined(DMRDMORX_H)
|
||||||
#define DMRDMORX_H
|
#define DMRDMORX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DMRDefines.h"
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
const uint16_t DMO_BUFFER_LENGTH_SAMPLES = 1440U; // 60ms at 24 kHz
|
const uint16_t DMO_BUFFER_LENGTH_SAMPLES = 1440U; // 60ms at 24 kHz
|
||||||
@@ -70,6 +67,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||||
*
|
*
|
||||||
@@ -19,9 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DMRSlotType.h"
|
#include "DMRSlotType.h"
|
||||||
|
|
||||||
@@ -77,7 +74,7 @@ void CDMRDMOTX::process()
|
|||||||
m_poLen = m_txDelay;
|
m_poLen = m_txDelay;
|
||||||
} else {
|
} else {
|
||||||
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++)
|
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++)
|
||||||
m_fifo.get(m_poBuffer[i]);
|
m_poBuffer[i] = m_fifo.get();
|
||||||
|
|
||||||
for (unsigned int i = 0U; i < 39U; i++)
|
for (unsigned int i = 0U; i < 39U; i++)
|
||||||
m_poBuffer[i + DMR_FRAME_LENGTH_BYTES] = PR_FILL[i];
|
m_poBuffer[i + DMR_FRAME_LENGTH_BYTES] = PR_FILL[i];
|
||||||
@@ -107,7 +104,7 @@ void CDMRDMOTX::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint16_t length)
|
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -164,5 +161,3 @@ void CDMRDMOTX::setTXDelay(uint8_t delay)
|
|||||||
m_txDelay = 1200U;
|
m_txDelay = 1200U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -17,22 +17,19 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#if !defined(DMRDMOTX_H)
|
#if !defined(DMRDMOTX_H)
|
||||||
#define DMRDMOTX_H
|
#define DMRDMOTX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DMRDefines.h"
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "SerialRB.h"
|
||||||
|
|
||||||
class CDMRDMOTX {
|
class CDMRDMOTX {
|
||||||
public:
|
public:
|
||||||
CDMRDMOTX();
|
CDMRDMOTX();
|
||||||
|
|
||||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
@@ -41,7 +38,7 @@ public:
|
|||||||
uint8_t getSpace() const;
|
uint8_t getSpace() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRingBuffer<uint8_t> m_fifo;
|
CSerialRB m_fifo;
|
||||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||||
uint8_t m_poBuffer[1200U];
|
uint8_t m_poBuffer[1200U];
|
||||||
@@ -54,5 +51,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DMRIdleRX.h"
|
#include "DMRIdleRX.h"
|
||||||
#include "DMRSlotType.h"
|
#include "DMRSlotType.h"
|
||||||
@@ -212,6 +209,3 @@ void CDMRIdleRX::setColorCode(uint8_t colorCode)
|
|||||||
{
|
{
|
||||||
m_colorCode = colorCode;
|
m_colorCode = colorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,13 +16,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#if !defined(DMRIDLERX_H)
|
#if !defined(DMRIDLERX_H)
|
||||||
#define DMRIDLERX_H
|
#define DMRIDLERX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DMRDefines.h"
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
class CDMRIdleRX {
|
class CDMRIdleRX {
|
||||||
@@ -52,5 +49,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DMRRX.h"
|
#include "DMRRX.h"
|
||||||
|
|
||||||
@@ -71,5 +68,3 @@ void CDMRRX::reset()
|
|||||||
m_slot2RX.reset();
|
m_slot2RX.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,13 +16,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#if !defined(DMRRX_H)
|
#if !defined(DMRRX_H)
|
||||||
#define DMRRX_H
|
#define DMRRX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DMRSlotRX.h"
|
#include "DMRSlotRX.h"
|
||||||
|
|
||||||
class CDMRRX {
|
class CDMRRX {
|
||||||
@@ -43,5 +40,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DMRSlotRX.h"
|
#include "DMRSlotRX.h"
|
||||||
#include "DMRSlotType.h"
|
#include "DMRSlotType.h"
|
||||||
@@ -403,6 +400,3 @@ void CDMRSlotRX::writeRSSIData(uint8_t* frame)
|
|||||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,13 +16,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#if !defined(DMRSLOTRX_H)
|
#if !defined(DMRSLOTRX_H)
|
||||||
#define DMRSLOTRX_H
|
#define DMRSLOTRX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DMRDefines.h"
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
enum DMRRX_STATE {
|
enum DMRRX_STATE {
|
||||||
@@ -73,6 +70,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DMRSlotType.h"
|
#include "DMRSlotType.h"
|
||||||
|
|
||||||
@@ -288,5 +285,3 @@ void CDMRSlotType::encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) c
|
|||||||
frame[20U] = (frame[20U] & 0x03U) | ((slotType[1U] << 6) & 0xC0U) | ((slotType[2U] >> 2) & 0x3CU);
|
frame[20U] = (frame[20U] & 0x03U) | ((slotType[1U] << 6) & 0xC0U) | ((slotType[2U] >> 2) & 0x3CU);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,10 +16,6 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#if !defined(DMRSLOTTYPE_H)
|
#if !defined(DMRSLOTTYPE_H)
|
||||||
#define DMRSLOTTYPE_H
|
#define DMRSLOTTYPE_H
|
||||||
|
|
||||||
@@ -39,5 +35,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||||
*
|
*
|
||||||
@@ -19,9 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DMRSlotType.h"
|
#include "DMRSlotType.h"
|
||||||
|
|
||||||
@@ -147,7 +144,7 @@ void CDMRTX::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CDMRTX::writeData1(const uint8_t* data, uint16_t length)
|
uint8_t CDMRTX::writeData1(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -171,7 +168,7 @@ uint8_t CDMRTX::writeData1(const uint8_t* data, uint16_t length)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CDMRTX::writeData2(const uint8_t* data, uint16_t length)
|
uint8_t CDMRTX::writeData2(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -195,7 +192,7 @@ uint8_t CDMRTX::writeData2(const uint8_t* data, uint16_t length)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint16_t length)
|
uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != 9U)
|
if (length != 9U)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -211,7 +208,7 @@ uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint16_t length)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint16_t length)
|
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != 1U)
|
if (length != 1U)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -296,7 +293,7 @@ void CDMRTX::createData(uint8_t slotIndex)
|
|||||||
{
|
{
|
||||||
if (m_fifo[slotIndex].getData() >= DMR_FRAME_LENGTH_BYTES && m_frameCount >= STARTUP_COUNT && m_abortCount[slotIndex] >= ABORT_COUNT) {
|
if (m_fifo[slotIndex].getData() >= DMR_FRAME_LENGTH_BYTES && m_frameCount >= STARTUP_COUNT && m_abortCount[slotIndex] >= ABORT_COUNT) {
|
||||||
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
|
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
|
||||||
m_fifo[slotIndex].get(m_poBuffer[i]);
|
m_poBuffer[i] = m_fifo[slotIndex].get();
|
||||||
m_markBuffer[i] = MARK_NONE;
|
m_markBuffer[i] = MARK_NONE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -417,6 +414,3 @@ uint32_t CDMRTX::getFrameCount()
|
|||||||
{
|
{
|
||||||
return m_frameCount;
|
return m_frameCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -17,16 +17,13 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
|
|
||||||
#if !defined(DMRTX_H)
|
#if !defined(DMRTX_H)
|
||||||
#define DMRTX_H
|
#define DMRTX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DMRDefines.h"
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "SerialRB.h"
|
||||||
|
|
||||||
enum DMRTXSTATE {
|
enum DMRTXSTATE {
|
||||||
DMRTXSTATE_IDLE,
|
DMRTXSTATE_IDLE,
|
||||||
@@ -41,11 +38,11 @@ class CDMRTX {
|
|||||||
public:
|
public:
|
||||||
CDMRTX();
|
CDMRTX();
|
||||||
|
|
||||||
uint8_t writeData1(const uint8_t* data, uint16_t length);
|
uint8_t writeData1(const uint8_t* data, uint8_t length);
|
||||||
uint8_t writeData2(const uint8_t* data, uint16_t length);
|
uint8_t writeData2(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
uint8_t writeShortLC(const uint8_t* data, uint16_t length);
|
uint8_t writeShortLC(const uint8_t* data, uint8_t length);
|
||||||
uint8_t writeAbort(const uint8_t* data, uint16_t length);
|
uint8_t writeAbort(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
void setStart(bool start);
|
void setStart(bool start);
|
||||||
void setCal(bool start);
|
void setCal(bool start);
|
||||||
@@ -62,7 +59,7 @@ public:
|
|||||||
void setColorCode(uint8_t colorCode);
|
void setColorCode(uint8_t colorCode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRingBuffer<uint8_t> m_fifo[2U];
|
CSerialRB m_fifo[2U];
|
||||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||||
DMRTXSTATE m_state;
|
DMRTXSTATE m_state;
|
||||||
@@ -86,5 +83,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DSTARDEFINES_H)
|
||||||
|
#define DSTARDEFINES_H
|
||||||
|
|
||||||
|
const unsigned int DSTAR_RADIO_BIT_LENGTH = 5U; // At 24 kHz sample rate
|
||||||
|
|
||||||
|
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
|
||||||
|
const unsigned int DSTAR_HEADER_LENGTH_BITS = DSTAR_HEADER_LENGTH_BYTES * 8U;
|
||||||
|
|
||||||
|
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
|
||||||
|
const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U;
|
||||||
|
|
||||||
|
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
|
||||||
|
const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U;
|
||||||
|
|
||||||
|
const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U;
|
||||||
|
const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U;
|
||||||
|
|
||||||
|
const uint8_t DSTAR_DATA_SYNC_LENGTH_BYTES = 3U;
|
||||||
|
const uint8_t DSTAR_DATA_SYNC_LENGTH_BITS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
|
||||||
|
|
||||||
|
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
|
||||||
|
|
||||||
|
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
|
||||||
|
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
|
||||||
|
|
||||||
|
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
+142
-249
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -18,28 +18,31 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DStarRX.h"
|
#include "DStarRX.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
const unsigned int MAX_FRAMES = 150U;
|
const unsigned int BUFFER_LENGTH = 200U;
|
||||||
|
|
||||||
|
const uint32_t PLLMAX = 0x10000U;
|
||||||
|
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
|
||||||
|
const uint32_t INC = PLLINC / 32U;
|
||||||
|
|
||||||
|
const unsigned int MAX_SYNC_BITS = 100U * DSTAR_DATA_LENGTH_BITS;
|
||||||
|
|
||||||
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
|
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
|
||||||
const uint64_t FRAME_SYNC_DATA = 0x0000000000557650U;
|
const uint32_t FRAME_SYNC_DATA = 0x00557650U;
|
||||||
const uint64_t FRAME_SYNC_MASK = 0x0000000000FFFFFFU;
|
const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU;
|
||||||
const uint8_t FRAME_SYNC_ERRS = 2U;
|
const uint8_t FRAME_SYNC_ERRS = 2U;
|
||||||
|
|
||||||
// D-Star bit order version of 0x55 0x2D 0x16
|
// D-Star bit order version of 0x55 0x2D 0x16
|
||||||
const uint64_t DATA_SYNC_DATA = 0x0000000000AAB468U;
|
const uint32_t DATA_SYNC_DATA = 0x00AAB468U;
|
||||||
const uint64_t DATA_SYNC_MASK = 0x0000000000FFFFFFU;
|
const uint32_t DATA_SYNC_MASK = 0x00FFFFFFU;
|
||||||
const uint8_t DATA_SYNC_ERRS = 2U;
|
const uint8_t DATA_SYNC_ERRS = 2U;
|
||||||
|
|
||||||
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
|
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
|
||||||
const uint64_t END_SYNC_DATA = 0x0000AAAAAAAA135EU;
|
const uint32_t END_SYNC_DATA = 0xAAAA135EU;
|
||||||
const uint64_t END_SYNC_MASK = 0x0000FFFFFFFFFFFFU;
|
const uint32_t END_SYNC_MASK = 0xFFFFFFFFU;
|
||||||
const uint8_t END_SYNC_ERRS = 1U;
|
const uint8_t END_SYNC_ERRS = 1U;
|
||||||
|
|
||||||
const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
|
const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
|
||||||
@@ -234,24 +237,14 @@ const uint16_t CCITT_TABLE[] = {
|
|||||||
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
|
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
|
||||||
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U};
|
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U};
|
||||||
|
|
||||||
const uint16_t NOENDPTR = 9999U;
|
|
||||||
|
|
||||||
CDStarRX::CDStarRX() :
|
CDStarRX::CDStarRX() :
|
||||||
|
m_pll(0U),
|
||||||
|
m_prev(false),
|
||||||
m_rxState(DSRXS_NONE),
|
m_rxState(DSRXS_NONE),
|
||||||
m_bitBuffer(),
|
m_patternBuffer(0x00U),
|
||||||
m_headerBuffer(),
|
m_rxBuffer(),
|
||||||
m_dataBuffer(),
|
m_rxBufferBits(0U),
|
||||||
m_bitPtr(0U),
|
m_dataBits(0U),
|
||||||
m_headerPtr(0U),
|
|
||||||
m_dataPtr(0U),
|
|
||||||
m_startPtr(NOENDPTR),
|
|
||||||
m_syncPtr(NOENDPTR),
|
|
||||||
m_minSyncPtr(NOENDPTR),
|
|
||||||
m_maxSyncPtr(NOENDPTR),
|
|
||||||
m_maxFrameCorr(0),
|
|
||||||
m_maxDataCorr(0),
|
|
||||||
m_frameCount(0U),
|
|
||||||
m_countdown(0U),
|
|
||||||
m_mar(0U),
|
m_mar(0U),
|
||||||
m_pathMetric(),
|
m_pathMetric(),
|
||||||
m_pathMemory0(),
|
m_pathMemory0(),
|
||||||
@@ -266,20 +259,14 @@ m_rssiCount(0U)
|
|||||||
|
|
||||||
void CDStarRX::reset()
|
void CDStarRX::reset()
|
||||||
{
|
{
|
||||||
m_rxState = DSRXS_NONE;
|
m_pll = 0U;
|
||||||
m_headerPtr = 0U;
|
m_prev = false;
|
||||||
m_dataPtr = 0U;
|
m_rxState = DSRXS_NONE;
|
||||||
m_bitPtr = 0U;
|
m_patternBuffer = 0x00U;
|
||||||
m_maxFrameCorr = 0;
|
m_rxBufferBits = 0U;
|
||||||
m_maxDataCorr = 0;
|
m_dataBits = 0U;
|
||||||
m_startPtr = NOENDPTR;
|
m_rssiAccum = 0U;
|
||||||
m_syncPtr = NOENDPTR;
|
m_rssiCount = 0U;
|
||||||
m_minSyncPtr = NOENDPTR;
|
|
||||||
m_maxSyncPtr = NOENDPTR;
|
|
||||||
m_frameCount = 0U;
|
|
||||||
m_countdown = 0U;
|
|
||||||
m_rssiAccum = 0U;
|
|
||||||
m_rssiCount = 0U;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
||||||
@@ -288,117 +275,125 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt
|
|||||||
m_rssiAccum += rssi[i];
|
m_rssiAccum += rssi[i];
|
||||||
m_rssiCount++;
|
m_rssiCount++;
|
||||||
|
|
||||||
q15_t sample = samples[i];
|
bool bit = samples[i] < 0;
|
||||||
|
|
||||||
m_bitBuffer[m_bitPtr] <<= 1;
|
if (bit != m_prev) {
|
||||||
if (sample < 0)
|
if (m_pll < (PLLMAX / 2U))
|
||||||
m_bitBuffer[m_bitPtr] |= 0x01U;
|
m_pll += INC;
|
||||||
|
else
|
||||||
m_dataBuffer[m_dataPtr] = sample;
|
m_pll -= INC;
|
||||||
|
|
||||||
switch (m_rxState) {
|
|
||||||
case DSRXS_HEADER:
|
|
||||||
processHeader(sample);
|
|
||||||
break;
|
|
||||||
case DSRXS_DATA:
|
|
||||||
processData();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
processNone(sample);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dataPtr++;
|
m_prev = bit;
|
||||||
if (m_dataPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
|
||||||
m_dataPtr = 0U;
|
|
||||||
|
|
||||||
m_bitPtr++;
|
m_pll += PLLINC;
|
||||||
if (m_bitPtr >= DSTAR_RADIO_SYMBOL_LENGTH)
|
|
||||||
m_bitPtr = 0U;
|
if (m_pll >= PLLMAX) {
|
||||||
|
m_pll -= PLLMAX;
|
||||||
|
|
||||||
|
switch (m_rxState) {
|
||||||
|
case DSRXS_NONE:
|
||||||
|
processNone(bit);
|
||||||
|
break;
|
||||||
|
case DSRXS_HEADER:
|
||||||
|
processHeader(bit);
|
||||||
|
break;
|
||||||
|
case DSRXS_DATA:
|
||||||
|
processData(bit);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDStarRX::processNone(q15_t sample)
|
void CDStarRX::processNone(bool bit)
|
||||||
{
|
{
|
||||||
// Fuzzy matching of the frame sync sequence
|
m_patternBuffer <<= 1;
|
||||||
bool ret = correlateFrameSync();
|
if (bit)
|
||||||
if (ret) {
|
m_patternBuffer |= 0x01U;
|
||||||
m_countdown = 5U;
|
|
||||||
|
|
||||||
m_headerBuffer[m_headerPtr] = sample;
|
// Fuzzy matching of the frame sync sequence
|
||||||
m_headerPtr++;
|
if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
|
||||||
|
DEBUG1("DStarRX: found frame sync in None");
|
||||||
|
|
||||||
|
::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES);
|
||||||
|
m_rxBufferBits = 0U;
|
||||||
|
|
||||||
m_rssiAccum = 0U;
|
m_rssiAccum = 0U;
|
||||||
m_rssiCount = 0U;
|
m_rssiCount = 0U;
|
||||||
|
|
||||||
m_rxState = DSRXS_HEADER;
|
m_rxState = DSRXS_HEADER;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fuzzy matching of the data sync bit sequence
|
// Exact matching of the data sync bit sequence
|
||||||
ret = correlateDataSync();
|
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) {
|
||||||
if (ret) {
|
|
||||||
DEBUG1("DStarRX: found data sync in None");
|
DEBUG1("DStarRX: found data sync in None");
|
||||||
|
|
||||||
io.setDecode(true);
|
io.setDecode(true);
|
||||||
io.setADCDetection(true);
|
io.setADCDetection(true);
|
||||||
|
|
||||||
m_rxState = DSRXS_DATA;
|
// Suppress RSSI on the dummy sync message
|
||||||
|
m_rssiAccum = 0U;
|
||||||
|
m_rssiCount = 0U;
|
||||||
|
|
||||||
|
::memcpy(m_rxBuffer, DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES);
|
||||||
|
writeRSSIData(m_rxBuffer);
|
||||||
|
|
||||||
|
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||||
|
m_rxBufferBits = 0U;
|
||||||
|
|
||||||
|
m_dataBits = MAX_SYNC_BITS;
|
||||||
|
m_rxState = DSRXS_DATA;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDStarRX::processHeader(q15_t sample)
|
void CDStarRX::processHeader(bool bit)
|
||||||
{
|
{
|
||||||
if (m_countdown > 0U) {
|
m_patternBuffer <<= 1;
|
||||||
correlateFrameSync();
|
if (bit)
|
||||||
m_countdown--;
|
m_patternBuffer |= 0x01U;
|
||||||
}
|
|
||||||
|
|
||||||
m_headerBuffer[m_headerPtr] = sample;
|
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
||||||
m_headerPtr++;
|
m_rxBufferBits++;
|
||||||
|
|
||||||
// A full FEC header
|
// A full FEC header
|
||||||
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) {
|
if (m_rxBufferBits == DSTAR_FEC_SECTION_LENGTH_BITS) {
|
||||||
uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES];
|
// Process the scrambling, interleaving and FEC, then return if the chcksum was correct
|
||||||
samplesToBits(m_headerBuffer, DSTAR_RADIO_SYMBOL_LENGTH, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES);
|
unsigned char header[DSTAR_HEADER_LENGTH_BYTES];
|
||||||
|
bool ok = rxHeader(m_rxBuffer, header);
|
||||||
// Process the scrambling, interleaving and FEC, then return true if the chcksum was correct
|
if (ok) {
|
||||||
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
|
|
||||||
bool ok = rxHeader(buffer, header);
|
|
||||||
if (!ok) {
|
|
||||||
// The checksum failed, return to looking for syncs
|
|
||||||
m_rxState = DSRXS_NONE;
|
|
||||||
m_maxFrameCorr = 0;
|
|
||||||
m_maxDataCorr = 0;
|
|
||||||
} else {
|
|
||||||
io.setDecode(true);
|
io.setDecode(true);
|
||||||
io.setADCDetection(true);
|
io.setADCDetection(true);
|
||||||
|
|
||||||
writeRSSIHeader(header);
|
writeRSSIHeader(header);
|
||||||
|
|
||||||
|
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||||
|
m_rxBufferBits = 0U;
|
||||||
|
|
||||||
|
m_rxState = DSRXS_DATA;
|
||||||
|
m_dataBits = MAX_SYNC_BITS;
|
||||||
|
} else {
|
||||||
|
// The checksum failed, return to looking for syncs
|
||||||
|
m_rxState = DSRXS_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ready to start the first data section
|
|
||||||
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH)) {
|
|
||||||
m_frameCount = 0U;
|
|
||||||
m_dataPtr = 0U;
|
|
||||||
|
|
||||||
m_startPtr = 476U;
|
|
||||||
m_syncPtr = 471U;
|
|
||||||
m_maxSyncPtr = 472U;
|
|
||||||
m_minSyncPtr = 470U;
|
|
||||||
|
|
||||||
DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
|
|
||||||
|
|
||||||
m_rxState = DSRXS_DATA;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDStarRX::processData()
|
void CDStarRX::processData(bool bit)
|
||||||
{
|
{
|
||||||
|
m_patternBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_patternBuffer |= 0x01U;
|
||||||
|
|
||||||
|
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
||||||
|
m_rxBufferBits++;
|
||||||
|
|
||||||
// Fuzzy matching of the end frame sequences
|
// Fuzzy matching of the end frame sequences
|
||||||
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= END_SYNC_ERRS) {
|
if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) {
|
||||||
DEBUG1("DStarRX: Found end sync in Data");
|
DEBUG1("DStarRX: Found end sync in Data");
|
||||||
|
|
||||||
io.setDecode(false);
|
io.setDecode(false);
|
||||||
@@ -406,24 +401,35 @@ void CDStarRX::processData()
|
|||||||
|
|
||||||
serial.writeDStarEOT();
|
serial.writeDStarEOT();
|
||||||
|
|
||||||
m_maxFrameCorr = 0;
|
|
||||||
m_maxDataCorr = 0;
|
|
||||||
|
|
||||||
m_rxState = DSRXS_NONE;
|
m_rxState = DSRXS_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fuzzy matching of the data sync bit sequence
|
// Fuzzy matching of the data sync bit sequence
|
||||||
if (m_minSyncPtr < m_maxSyncPtr) {
|
bool syncSeen = false;
|
||||||
if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr)
|
if (m_rxBufferBits >= (DSTAR_DATA_LENGTH_BITS - 3U)) {
|
||||||
correlateDataSync();
|
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) {
|
||||||
} else {
|
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS;
|
||||||
if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr)
|
m_dataBits = MAX_SYNC_BITS;
|
||||||
correlateDataSync();
|
syncSeen = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
// Check to see if the sync is arriving late
|
||||||
if (m_frameCount >= MAX_FRAMES) {
|
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS && !syncSeen) {
|
||||||
|
for (uint8_t i = 1U; i <= 3U; i++) {
|
||||||
|
uint32_t syncMask = DATA_SYNC_MASK >> i;
|
||||||
|
uint32_t syncData = DATA_SYNC_DATA >> i;
|
||||||
|
if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) {
|
||||||
|
m_rxBufferBits -= i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dataBits--;
|
||||||
|
|
||||||
|
if (m_dataBits == 0U) {
|
||||||
DEBUG1("DStarRX: data sync timed out, lost lock");
|
DEBUG1("DStarRX: data sync timed out, lost lock");
|
||||||
|
|
||||||
io.setDecode(false);
|
io.setDecode(false);
|
||||||
@@ -431,35 +437,24 @@ void CDStarRX::processData()
|
|||||||
|
|
||||||
serial.writeDStarLost();
|
serial.writeDStarLost();
|
||||||
|
|
||||||
m_maxFrameCorr = 0;
|
|
||||||
m_maxDataCorr = 0;
|
|
||||||
|
|
||||||
m_rxState = DSRXS_NONE;
|
m_rxState = DSRXS_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a data frame to the host if the required number of bits have been received
|
// Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen
|
||||||
if (m_dataPtr == m_maxSyncPtr) {
|
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) {
|
||||||
uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U];
|
if (syncSeen) {
|
||||||
samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES);
|
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
|
||||||
|
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
|
||||||
if ((m_frameCount % 21U) == 0U) {
|
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
|
||||||
if (m_frameCount == 0U) {
|
writeRSSIData(m_rxBuffer);
|
||||||
buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
|
|
||||||
buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
|
|
||||||
buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
|
|
||||||
DEBUG5("DStarRX: found start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
writeRSSIData(buffer);
|
|
||||||
} else {
|
} else {
|
||||||
serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES);
|
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_frameCount++;
|
// Start the next frame
|
||||||
|
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||||
m_maxFrameCorr = 0;
|
m_rxBufferBits = 0U;
|
||||||
m_maxDataCorr = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,105 +500,6 @@ void CDStarRX::writeRSSIData(unsigned char* data)
|
|||||||
m_rssiCount = 0U;
|
m_rssiCount = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CDStarRX::correlateFrameSync()
|
|
||||||
{
|
|
||||||
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_FRAME_SYNC_MASK) ^ DSTAR_FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
|
|
||||||
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_FRAME_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
|
|
||||||
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
|
|
||||||
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
|
|
||||||
|
|
||||||
q31_t corr = 0;
|
|
||||||
|
|
||||||
for (uint8_t i = 0U; i < DSTAR_FRAME_SYNC_LENGTH_SYMBOLS; i++) {
|
|
||||||
q15_t val = m_dataBuffer[ptr];
|
|
||||||
|
|
||||||
if (DSTAR_FRAME_SYNC_SYMBOLS[i])
|
|
||||||
corr -= val;
|
|
||||||
else
|
|
||||||
corr += val;
|
|
||||||
|
|
||||||
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
|
|
||||||
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
|
|
||||||
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (corr > m_maxFrameCorr) {
|
|
||||||
m_maxFrameCorr = corr;
|
|
||||||
m_headerPtr = 0U;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDStarRX::correlateDataSync()
|
|
||||||
{
|
|
||||||
uint8_t maxErrs = 0U;
|
|
||||||
if (m_rxState == DSRXS_DATA)
|
|
||||||
maxErrs = DATA_SYNC_ERRS;
|
|
||||||
|
|
||||||
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= maxErrs) {
|
|
||||||
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
|
|
||||||
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
|
|
||||||
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
|
|
||||||
|
|
||||||
q31_t corr = 0;
|
|
||||||
|
|
||||||
for (uint8_t i = 0U; i < DSTAR_DATA_SYNC_LENGTH_SYMBOLS; i++) {
|
|
||||||
q15_t val = m_dataBuffer[ptr];
|
|
||||||
|
|
||||||
if (DSTAR_DATA_SYNC_SYMBOLS[i])
|
|
||||||
corr -= val;
|
|
||||||
else
|
|
||||||
corr += val;
|
|
||||||
|
|
||||||
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
|
|
||||||
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
|
|
||||||
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (corr > m_maxDataCorr) {
|
|
||||||
m_maxDataCorr = corr;
|
|
||||||
m_frameCount = 0U;
|
|
||||||
|
|
||||||
m_syncPtr = m_dataPtr;
|
|
||||||
|
|
||||||
m_startPtr = m_dataPtr + DSTAR_RADIO_SYMBOL_LENGTH;
|
|
||||||
if (m_startPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
|
||||||
m_startPtr -= DSTAR_DATA_LENGTH_SAMPLES;
|
|
||||||
|
|
||||||
m_maxSyncPtr = m_syncPtr + 1U;
|
|
||||||
if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
|
||||||
m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
|
|
||||||
|
|
||||||
m_minSyncPtr = m_syncPtr + DSTAR_DATA_LENGTH_SAMPLES - 1U;
|
|
||||||
if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
|
||||||
m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDStarRX::samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit)
|
|
||||||
{
|
|
||||||
for (uint16_t i = 0U; i < count; i++) {
|
|
||||||
q15_t sample = inBuffer[start];
|
|
||||||
|
|
||||||
if (sample < 0)
|
|
||||||
WRITE_BIT2(outBuffer, i, true);
|
|
||||||
else
|
|
||||||
WRITE_BIT2(outBuffer, i, false);
|
|
||||||
|
|
||||||
start += DSTAR_RADIO_SYMBOL_LENGTH;
|
|
||||||
if (start >= limit)
|
|
||||||
start -= limit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
|
bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -819,6 +715,3 @@ bool CDStarRX::checksum(const uint8_t* header) const
|
|||||||
|
|
||||||
return crc8[0U] == header[DSTAR_HEADER_LENGTH_BYTES - 2U] && crc8[1U] == header[DSTAR_HEADER_LENGTH_BYTES - 1U];
|
return crc8[0U] == header[DSTAR_HEADER_LENGTH_BYTES - 2U] && crc8[1U] == header[DSTAR_HEADER_LENGTH_BYTES - 1U];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,13 +16,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
|
|
||||||
#if !defined(DSTARRX_H)
|
#if !defined(DSTARRX_H)
|
||||||
#define DSTARRX_H
|
#define DSTARRX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "DStarDefines.h"
|
#include "DStarDefines.h"
|
||||||
|
|
||||||
enum DSRX_STATE {
|
enum DSRX_STATE {
|
||||||
@@ -40,21 +37,13 @@ public:
|
|||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint32_t m_pll;
|
||||||
|
bool m_prev;
|
||||||
DSRX_STATE m_rxState;
|
DSRX_STATE m_rxState;
|
||||||
uint64_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH];
|
uint32_t m_patternBuffer;
|
||||||
q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH];
|
uint8_t m_rxBuffer[100U];
|
||||||
q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES];
|
unsigned int m_rxBufferBits;
|
||||||
uint16_t m_bitPtr;
|
unsigned int m_dataBits;
|
||||||
uint16_t m_headerPtr;
|
|
||||||
uint16_t m_dataPtr;
|
|
||||||
uint16_t m_startPtr;
|
|
||||||
uint16_t m_syncPtr;
|
|
||||||
uint16_t m_minSyncPtr;
|
|
||||||
uint16_t m_maxSyncPtr;
|
|
||||||
q31_t m_maxFrameCorr;
|
|
||||||
q31_t m_maxDataCorr;
|
|
||||||
uint16_t m_frameCount;
|
|
||||||
uint8_t m_countdown;
|
|
||||||
unsigned int m_mar;
|
unsigned int m_mar;
|
||||||
int m_pathMetric[4U];
|
int m_pathMetric[4U];
|
||||||
unsigned int m_pathMemory0[42U];
|
unsigned int m_pathMemory0[42U];
|
||||||
@@ -65,12 +54,9 @@ private:
|
|||||||
uint32_t m_rssiAccum;
|
uint32_t m_rssiAccum;
|
||||||
uint16_t m_rssiCount;
|
uint16_t m_rssiCount;
|
||||||
|
|
||||||
void processNone(q15_t sample);
|
void processNone(bool bit);
|
||||||
void processHeader(q15_t sample);
|
void processHeader(bool bit);
|
||||||
void processData();
|
void processData(bool bit);
|
||||||
bool correlateFrameSync();
|
|
||||||
bool correlateDataSync();
|
|
||||||
void samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit);
|
|
||||||
void writeRSSIHeader(unsigned char* header);
|
void writeRSSIHeader(unsigned char* header);
|
||||||
void writeRSSIData(unsigned char* data);
|
void writeRSSIData(unsigned char* data);
|
||||||
bool rxHeader(uint8_t* in, uint8_t* out);
|
bool rxHeader(uint8_t* in, uint8_t* out);
|
||||||
@@ -82,5 +68,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -18,9 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DStarTX.h"
|
#include "DStarTX.h"
|
||||||
|
|
||||||
@@ -201,7 +198,7 @@ m_txDelay(60U) // 100ms
|
|||||||
{
|
{
|
||||||
::memset(m_modState, 0x00U, 20U * sizeof(q15_t));
|
::memset(m_modState, 0x00U, 20U * sizeof(q15_t));
|
||||||
|
|
||||||
m_modFilter.L = DSTAR_RADIO_SYMBOL_LENGTH;
|
m_modFilter.L = DSTAR_RADIO_BIT_LENGTH;
|
||||||
m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN;
|
m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN;
|
||||||
m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER;
|
m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER;
|
||||||
m_modFilter.pState = m_modState;
|
m_modFilter.pState = m_modState;
|
||||||
@@ -220,12 +217,11 @@ void CDStarTX::process()
|
|||||||
m_poBuffer[m_poLen++] = BIT_SYNC;
|
m_poBuffer[m_poLen++] = BIT_SYNC;
|
||||||
} else {
|
} else {
|
||||||
// Pop the type byte off
|
// Pop the type byte off
|
||||||
uint8_t dummy;
|
m_buffer.get();
|
||||||
m_buffer.get(dummy);
|
|
||||||
|
|
||||||
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
|
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
|
||||||
for (uint8_t i = 0U; i < DSTAR_HEADER_LENGTH_BYTES; i++)
|
for (uint8_t i = 0U; i < DSTAR_HEADER_LENGTH_BYTES; i++)
|
||||||
m_buffer.get(header[i]);
|
header[i] = m_buffer.get();
|
||||||
|
|
||||||
uint8_t buffer[86U];
|
uint8_t buffer[86U];
|
||||||
txHeader(header, buffer + 2U);
|
txHeader(header, buffer + 2U);
|
||||||
@@ -243,23 +239,21 @@ void CDStarTX::process()
|
|||||||
|
|
||||||
if (type == DSTAR_DATA && m_poLen == 0U) {
|
if (type == DSTAR_DATA && m_poLen == 0U) {
|
||||||
// Pop the type byte off
|
// Pop the type byte off
|
||||||
uint8_t dummy;
|
m_buffer.get();
|
||||||
m_buffer.get(dummy);
|
|
||||||
|
|
||||||
for (uint8_t i = 0U; i < DSTAR_DATA_LENGTH_BYTES; i++)
|
for (uint8_t i = 0U; i < DSTAR_DATA_LENGTH_BYTES; i++)
|
||||||
m_buffer.get(m_poBuffer[m_poLen++]);
|
m_poBuffer[m_poLen++] = m_buffer.get();
|
||||||
|
|
||||||
m_poPtr = 0U;
|
m_poPtr = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == DSTAR_EOT && m_poLen == 0U) {
|
if (type == DSTAR_EOT && m_poLen == 0U) {
|
||||||
// Pop the type byte off
|
// Pop the type byte off
|
||||||
uint8_t dummy;
|
m_buffer.get();
|
||||||
m_buffer.get(dummy);
|
|
||||||
|
|
||||||
for (uint8_t j = 0U; j < 3U; j++) {
|
for (uint8_t j = 0U; j < 3U; j++) {
|
||||||
for (uint8_t i = 0U; i < DSTAR_END_SYNC_LENGTH_BYTES; i++)
|
for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++)
|
||||||
m_poBuffer[m_poLen++] = DSTAR_END_SYNC_BYTES[i];
|
m_poBuffer[m_poLen++] = DSTAR_EOT_BYTES[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
m_poPtr = 0U;
|
m_poPtr = 0U;
|
||||||
@@ -268,11 +262,11 @@ void CDStarTX::process()
|
|||||||
if (m_poLen > 0U) {
|
if (m_poLen > 0U) {
|
||||||
uint16_t space = io.getSpace();
|
uint16_t space = io.getSpace();
|
||||||
|
|
||||||
while (space > (8U * DSTAR_RADIO_SYMBOL_LENGTH)) {
|
while (space > (8U * DSTAR_RADIO_BIT_LENGTH)) {
|
||||||
uint8_t c = m_poBuffer[m_poPtr++];
|
uint8_t c = m_poBuffer[m_poPtr++];
|
||||||
writeByte(c);
|
writeByte(c);
|
||||||
|
|
||||||
space -= 8U * DSTAR_RADIO_SYMBOL_LENGTH;
|
space -= 8U * DSTAR_RADIO_BIT_LENGTH;
|
||||||
|
|
||||||
if (m_poPtr >= m_poLen) {
|
if (m_poPtr >= m_poLen) {
|
||||||
m_poPtr = 0U;
|
m_poPtr = 0U;
|
||||||
@@ -283,7 +277,7 @@ void CDStarTX::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint16_t length)
|
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != DSTAR_HEADER_LENGTH_BYTES)
|
if (length != DSTAR_HEADER_LENGTH_BYTES)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -302,7 +296,7 @@ uint8_t CDStarTX::writeHeader(const uint8_t* header, uint16_t length)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CDStarTX::writeData(const uint8_t* data, uint16_t length)
|
uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != DSTAR_DATA_LENGTH_BYTES)
|
if (length != DSTAR_DATA_LENGTH_BYTES)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -418,7 +412,7 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const
|
|||||||
void CDStarTX::writeByte(uint8_t c)
|
void CDStarTX::writeByte(uint8_t c)
|
||||||
{
|
{
|
||||||
q15_t inBuffer[8U];
|
q15_t inBuffer[8U];
|
||||||
q15_t outBuffer[DSTAR_RADIO_SYMBOL_LENGTH * 8U];
|
q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U];
|
||||||
|
|
||||||
uint8_t mask = 0x01U;
|
uint8_t mask = 0x01U;
|
||||||
|
|
||||||
@@ -433,7 +427,7 @@ void CDStarTX::writeByte(uint8_t c)
|
|||||||
|
|
||||||
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U);
|
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U);
|
||||||
|
|
||||||
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_SYMBOL_LENGTH * 8U);
|
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDStarTX::setTXDelay(uint8_t delay)
|
void CDStarTX::setTXDelay(uint8_t delay)
|
||||||
@@ -449,5 +443,3 @@ uint8_t CDStarTX::getSpace() const
|
|||||||
return m_buffer.getSpace() / (DSTAR_DATA_LENGTH_BYTES + 1U);
|
return m_buffer.getSpace() / (DSTAR_DATA_LENGTH_BYTES + 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,21 +16,19 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
|
|
||||||
#if !defined(DSTARTX_H)
|
#if !defined(DSTARTX_H)
|
||||||
#define DSTARTX_H
|
#define DSTARTX_H
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
class CDStarTX {
|
class CDStarTX {
|
||||||
public:
|
public:
|
||||||
CDStarTX();
|
CDStarTX();
|
||||||
|
|
||||||
uint8_t writeHeader(const uint8_t* header, uint16_t length);
|
uint8_t writeHeader(const uint8_t* header, uint8_t length);
|
||||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
uint8_t writeEOT();
|
uint8_t writeEOT();
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
@@ -40,7 +38,7 @@ public:
|
|||||||
uint8_t getSpace() const;
|
uint8_t getSpace() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRingBuffer<uint8_t> m_buffer;
|
CSerialRB m_buffer;
|
||||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||||
q15_t m_modState[20U]; // blockSize + phaseLength - 1, 8 + 9 - 1 plus some spare
|
q15_t m_modState[20U]; // blockSize + phaseLength - 1, 8 + 9 - 1 plus some spare
|
||||||
uint8_t m_poBuffer[600U];
|
uint8_t m_poBuffer[600U];
|
||||||
@@ -54,5 +52,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2021 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -27,7 +27,6 @@
|
|||||||
#define DEBUG3(a,b,c) serial.writeDebug((a),(b),(c))
|
#define DEBUG3(a,b,c) serial.writeDebug((a),(b),(c))
|
||||||
#define DEBUG4(a,b,c,d) serial.writeDebug((a),(b),(c),(d))
|
#define DEBUG4(a,b,c,d) serial.writeDebug((a),(b),(c),(d))
|
||||||
#define DEBUG5(a,b,c,d,e) serial.writeDebug((a),(b),(c),(d),(e))
|
#define DEBUG5(a,b,c,d,e) serial.writeDebug((a),(b),(c),(d),(e))
|
||||||
#define DEBUG_DUMP(a,b) serial.writeDebugDump((a),(b))
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,490 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "FM.h"
|
||||||
|
|
||||||
|
CFM::CFM() :
|
||||||
|
m_callsign(),
|
||||||
|
m_rfAck(),
|
||||||
|
m_ctcssRX(),
|
||||||
|
m_ctcssTX(),
|
||||||
|
m_timeoutTone(),
|
||||||
|
m_state(FS_LISTENING),
|
||||||
|
m_callsignAtStart(false),
|
||||||
|
m_callsignAtEnd(false),
|
||||||
|
m_callsignAtLatch(false),
|
||||||
|
m_callsignTimer(),
|
||||||
|
m_timeoutTimer(),
|
||||||
|
m_holdoffTimer(),
|
||||||
|
m_kerchunkTimer(),
|
||||||
|
m_ackMinTimer(),
|
||||||
|
m_ackDelayTimer(),
|
||||||
|
m_hangTimer(),
|
||||||
|
m_filterStage1( 724, 1448, 724, 32768, -37895, 21352),//3rd order Cheby Filter 300 to 2700Hz, 0.2dB passband ripple, sampling rate 24kHz
|
||||||
|
m_filterStage2(32768, 0,-32768, 32768, -50339, 19052),
|
||||||
|
m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460),
|
||||||
|
m_blanking(),
|
||||||
|
m_useCOS(true),
|
||||||
|
m_cosInvert(false),
|
||||||
|
m_rfAudioBoost(1U),
|
||||||
|
m_downsampler(128U),//Size might need adjustement
|
||||||
|
m_rxLevel(1),
|
||||||
|
m_inputRB(4800U), // 200ms of audio
|
||||||
|
m_outputRB(2400U) // 100ms of audio
|
||||||
|
{
|
||||||
|
insertDelay(100U);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::samples(bool cos, const q15_t* samples, uint8_t length)
|
||||||
|
{
|
||||||
|
if (m_useCOS) {
|
||||||
|
if (m_cosInvert)
|
||||||
|
cos = !cos;
|
||||||
|
} else {
|
||||||
|
cos = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock(length);
|
||||||
|
|
||||||
|
uint8_t i = 0U;
|
||||||
|
for (; i < length; i++) {
|
||||||
|
// ARMv7-M has hardware integer division
|
||||||
|
q15_t currentSample = q15_t((q31_t(samples[i]) << 8) / m_rxLevel);
|
||||||
|
|
||||||
|
uint8_t ctcssState = m_ctcssRX.process(currentSample);
|
||||||
|
|
||||||
|
if (!m_useCOS) {
|
||||||
|
// Delay the audio by 100ms to better match the CTCSS detector output
|
||||||
|
m_inputRB.put(currentSample);
|
||||||
|
m_inputRB.get(currentSample);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) {
|
||||||
|
//Not enough samples to determine if you have CTCSS, just carry on
|
||||||
|
continue;
|
||||||
|
} else if (CTCSS_READY(ctcssState) && m_modemState != STATE_FM) {
|
||||||
|
//we had enough samples for CTCSS and we are in some other mode than FM
|
||||||
|
bool validCTCSS = CTCSS_VALID(ctcssState);
|
||||||
|
stateMachine(validCTCSS && cos);
|
||||||
|
if (m_modemState != STATE_FM)
|
||||||
|
continue;
|
||||||
|
} else if (CTCSS_READY(ctcssState) && m_modemState == STATE_FM) {
|
||||||
|
//We had enough samples for CTCSS and we are in FM mode, trigger the state machine
|
||||||
|
bool validCTCSS = CTCSS_VALID(ctcssState);
|
||||||
|
stateMachine(validCTCSS && cos);
|
||||||
|
if (m_modemState != STATE_FM)
|
||||||
|
break;
|
||||||
|
} else if (CTCSS_NOT_READY(ctcssState) && m_modemState == STATE_FM && i == length - 1) {
|
||||||
|
//Not enough samples for CTCSS but we already are in FM, trigger the state machine
|
||||||
|
//but do not trigger the state machine on every single sample, save CPU!
|
||||||
|
bool validCTCSS = CTCSS_VALID(ctcssState);
|
||||||
|
stateMachine(validCTCSS && cos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only let audio through when relaying audio
|
||||||
|
if (m_state == FS_RELAYING || m_state == FS_KERCHUNK) {
|
||||||
|
// m_downsampler.addSample(currentSample);
|
||||||
|
currentSample = m_blanking.process(currentSample);
|
||||||
|
currentSample *= m_rfAudioBoost;
|
||||||
|
} else {
|
||||||
|
currentSample = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_callsign.isRunning())
|
||||||
|
currentSample += m_rfAck.getHighAudio();
|
||||||
|
|
||||||
|
if (!m_rfAck.isRunning()) {
|
||||||
|
if (m_state == FS_LISTENING)
|
||||||
|
currentSample += m_callsign.getHighAudio();
|
||||||
|
else
|
||||||
|
currentSample += m_callsign.getLowAudio();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_callsign.isRunning() && !m_rfAck.isRunning())
|
||||||
|
currentSample += m_timeoutTone.getAudio();
|
||||||
|
|
||||||
|
currentSample = m_filterStage3.filter(m_filterStage2.filter(m_filterStage1.filter(currentSample)));
|
||||||
|
|
||||||
|
currentSample += m_ctcssTX.getAudio();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_FM)
|
||||||
|
m_outputRB.put(currentSample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::process()
|
||||||
|
{
|
||||||
|
q15_t sample;
|
||||||
|
while (io.getSpace() >= 3U && m_outputRB.get(sample))
|
||||||
|
io.write(STATE_FM, &sample, 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::reset()
|
||||||
|
{
|
||||||
|
m_state = FS_LISTENING;
|
||||||
|
|
||||||
|
m_callsignTimer.stop();
|
||||||
|
m_timeoutTimer.stop();
|
||||||
|
m_kerchunkTimer.stop();
|
||||||
|
m_ackMinTimer.stop();
|
||||||
|
m_ackDelayTimer.stop();
|
||||||
|
m_hangTimer.stop();
|
||||||
|
|
||||||
|
m_ctcssRX.reset();
|
||||||
|
m_rfAck.stop();
|
||||||
|
m_callsign.stop();
|
||||||
|
m_timeoutTone.stop();
|
||||||
|
|
||||||
|
m_outputRB.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch)
|
||||||
|
{
|
||||||
|
m_callsignAtStart = callsignAtStart;
|
||||||
|
m_callsignAtEnd = callsignAtEnd;
|
||||||
|
m_callsignAtLatch = callsignAtLatch;
|
||||||
|
|
||||||
|
uint16_t holdoffTime = holdoff * 60U;
|
||||||
|
uint16_t callsignTime = time * 60U;
|
||||||
|
|
||||||
|
m_holdoffTimer.setTimeout(holdoffTime, 0U);
|
||||||
|
m_callsignTimer.setTimeout(callsignTime, 0U);
|
||||||
|
|
||||||
|
if (holdoffTime > 0U)
|
||||||
|
m_holdoffTimer.start();
|
||||||
|
|
||||||
|
return m_callsign.setParams(callsign, speed, frequency, highLevel, lowLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level)
|
||||||
|
{
|
||||||
|
m_ackDelayTimer.setTimeout(0U, delay);
|
||||||
|
|
||||||
|
if (minTime > 0U)
|
||||||
|
m_ackMinTimer.setTimeout(minTime, delay);
|
||||||
|
|
||||||
|
return m_rfAck.setParams(rfAck, speed, frequency, level, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel)
|
||||||
|
{
|
||||||
|
m_useCOS = useCOS;
|
||||||
|
m_cosInvert = cosInvert;
|
||||||
|
|
||||||
|
m_rfAudioBoost = q15_t(rfAudioBoost);
|
||||||
|
|
||||||
|
m_timeoutTimer.setTimeout(timeout, 0U);
|
||||||
|
m_kerchunkTimer.setTimeout(kerchunkTime, 0U);
|
||||||
|
m_hangTimer.setTimeout(hangTime, 0U);
|
||||||
|
|
||||||
|
m_timeoutTone.setParams(timeoutLevel);
|
||||||
|
m_blanking.setParams(maxDev, timeoutLevel);
|
||||||
|
|
||||||
|
m_rxLevel = rxLevel; //q15_t(255)/q15_t(rxLevel >> 1);
|
||||||
|
|
||||||
|
uint8_t ret = m_ctcssRX.setParams(ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold);
|
||||||
|
if (ret != 0U)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return m_ctcssTX.setParams(ctcssFrequency, ctcssLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::stateMachine(bool validSignal)
|
||||||
|
{
|
||||||
|
switch (m_state) {
|
||||||
|
case FS_LISTENING:
|
||||||
|
listeningState(validSignal);
|
||||||
|
break;
|
||||||
|
case FS_KERCHUNK:
|
||||||
|
kerchunkState(validSignal);
|
||||||
|
break;
|
||||||
|
case FS_RELAYING:
|
||||||
|
relayingState(validSignal);
|
||||||
|
break;
|
||||||
|
case FS_RELAYING_WAIT:
|
||||||
|
relayingWaitState(validSignal);
|
||||||
|
break;
|
||||||
|
case FS_TIMEOUT:
|
||||||
|
timeoutState(validSignal);
|
||||||
|
break;
|
||||||
|
case FS_TIMEOUT_WAIT:
|
||||||
|
timeoutWaitState(validSignal);
|
||||||
|
break;
|
||||||
|
case FS_HANG:
|
||||||
|
hangState(validSignal);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state == FS_LISTENING && m_modemState == STATE_FM) {
|
||||||
|
if (!m_callsign.isWanted() && !m_rfAck.isWanted()) {
|
||||||
|
DEBUG1("Change to STATE_IDLE");
|
||||||
|
m_modemState = STATE_IDLE;
|
||||||
|
m_callsignTimer.stop();
|
||||||
|
m_timeoutTimer.stop();
|
||||||
|
m_kerchunkTimer.stop();
|
||||||
|
m_ackMinTimer.stop();
|
||||||
|
m_ackDelayTimer.stop();
|
||||||
|
m_hangTimer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::clock(uint8_t length)
|
||||||
|
{
|
||||||
|
m_callsignTimer.clock(length);
|
||||||
|
m_timeoutTimer.clock(length);
|
||||||
|
m_holdoffTimer.clock(length);
|
||||||
|
m_kerchunkTimer.clock(length);
|
||||||
|
m_ackMinTimer.clock(length);
|
||||||
|
m_ackDelayTimer.clock(length);
|
||||||
|
m_hangTimer.clock(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::listeningState(bool validSignal)
|
||||||
|
{
|
||||||
|
if (validSignal) {
|
||||||
|
if (m_kerchunkTimer.getTimeout() > 0U) {
|
||||||
|
DEBUG1("State to KERCHUNK");
|
||||||
|
m_state = FS_KERCHUNK;
|
||||||
|
m_kerchunkTimer.start();
|
||||||
|
if (m_callsignAtStart && !m_callsignAtLatch)
|
||||||
|
sendCallsign();
|
||||||
|
} else {
|
||||||
|
DEBUG1("State to RELAYING");
|
||||||
|
m_state = FS_RELAYING;
|
||||||
|
if (m_callsignAtStart)
|
||||||
|
sendCallsign();
|
||||||
|
}
|
||||||
|
|
||||||
|
insertSilence(50U);
|
||||||
|
|
||||||
|
beginRelaying();
|
||||||
|
|
||||||
|
m_callsignTimer.start();
|
||||||
|
|
||||||
|
io.setDecode(true);
|
||||||
|
io.setADCDetection(true);
|
||||||
|
|
||||||
|
DEBUG1("Change to STATE_FM");
|
||||||
|
m_modemState = STATE_FM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::kerchunkState(bool validSignal)
|
||||||
|
{
|
||||||
|
if (validSignal) {
|
||||||
|
if (m_kerchunkTimer.hasExpired()) {
|
||||||
|
DEBUG1("State to RELAYING");
|
||||||
|
m_state = FS_RELAYING;
|
||||||
|
m_kerchunkTimer.stop();
|
||||||
|
if (m_callsignAtStart && m_callsignAtLatch) {
|
||||||
|
sendCallsign();
|
||||||
|
m_callsignTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
io.setDecode(false);
|
||||||
|
io.setADCDetection(false);
|
||||||
|
|
||||||
|
DEBUG1("State to LISTENING");
|
||||||
|
m_state = FS_LISTENING;
|
||||||
|
m_kerchunkTimer.stop();
|
||||||
|
m_timeoutTimer.stop();
|
||||||
|
m_ackMinTimer.stop();
|
||||||
|
m_callsignTimer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::relayingState(bool validSignal)
|
||||||
|
{
|
||||||
|
if (validSignal) {
|
||||||
|
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
|
||||||
|
DEBUG1("State to TIMEOUT");
|
||||||
|
m_state = FS_TIMEOUT;
|
||||||
|
m_ackMinTimer.stop();
|
||||||
|
m_timeoutTimer.stop();
|
||||||
|
m_timeoutTone.start();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
io.setDecode(false);
|
||||||
|
io.setADCDetection(false);
|
||||||
|
|
||||||
|
DEBUG1("State to RELAYING_WAIT");
|
||||||
|
m_state = FS_RELAYING_WAIT;
|
||||||
|
m_ackDelayTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
|
||||||
|
sendCallsign();
|
||||||
|
m_callsignTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::relayingWaitState(bool validSignal)
|
||||||
|
{
|
||||||
|
if (validSignal) {
|
||||||
|
io.setDecode(true);
|
||||||
|
io.setADCDetection(true);
|
||||||
|
|
||||||
|
DEBUG1("State to RELAYING");
|
||||||
|
m_state = FS_RELAYING;
|
||||||
|
m_ackDelayTimer.stop();
|
||||||
|
} else {
|
||||||
|
if (m_ackDelayTimer.isRunning() && m_ackDelayTimer.hasExpired()) {
|
||||||
|
DEBUG1("State to HANG");
|
||||||
|
m_state = FS_HANG;
|
||||||
|
|
||||||
|
if (m_ackMinTimer.isRunning()) {
|
||||||
|
if (m_ackMinTimer.hasExpired()) {
|
||||||
|
DEBUG1("Send ack");
|
||||||
|
m_rfAck.start();
|
||||||
|
m_ackMinTimer.stop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG1("Send ack");
|
||||||
|
m_rfAck.start();
|
||||||
|
m_ackMinTimer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ackDelayTimer.stop();
|
||||||
|
m_timeoutTimer.stop();
|
||||||
|
m_hangTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
|
||||||
|
sendCallsign();
|
||||||
|
m_callsignTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::hangState(bool validSignal)
|
||||||
|
{
|
||||||
|
if (validSignal) {
|
||||||
|
io.setDecode(true);
|
||||||
|
io.setADCDetection(true);
|
||||||
|
|
||||||
|
DEBUG1("State to RELAYING");
|
||||||
|
m_state = FS_RELAYING;
|
||||||
|
DEBUG1("Stop ack");
|
||||||
|
m_rfAck.stop();
|
||||||
|
beginRelaying();
|
||||||
|
} else {
|
||||||
|
if (m_hangTimer.isRunning() && m_hangTimer.hasExpired()) {
|
||||||
|
DEBUG1("State to LISTENING");
|
||||||
|
m_state = FS_LISTENING;
|
||||||
|
m_hangTimer.stop();
|
||||||
|
|
||||||
|
if (m_callsignAtEnd)
|
||||||
|
sendCallsign();
|
||||||
|
|
||||||
|
m_callsignTimer.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
|
||||||
|
sendCallsign();
|
||||||
|
m_callsignTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::timeoutState(bool validSignal)
|
||||||
|
{
|
||||||
|
if (!validSignal) {
|
||||||
|
io.setDecode(false);
|
||||||
|
io.setADCDetection(false);
|
||||||
|
|
||||||
|
DEBUG1("State to TIMEOUT_WAIT");
|
||||||
|
m_state = FS_TIMEOUT_WAIT;
|
||||||
|
m_ackDelayTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
|
||||||
|
sendCallsign();
|
||||||
|
m_callsignTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::timeoutWaitState(bool validSignal)
|
||||||
|
{
|
||||||
|
if (validSignal) {
|
||||||
|
io.setDecode(true);
|
||||||
|
io.setADCDetection(true);
|
||||||
|
|
||||||
|
DEBUG1("State to TIMEOUT");
|
||||||
|
m_state = FS_TIMEOUT;
|
||||||
|
m_ackDelayTimer.stop();
|
||||||
|
} else {
|
||||||
|
if (m_ackDelayTimer.isRunning() && m_ackDelayTimer.hasExpired()) {
|
||||||
|
DEBUG1("State to HANG");
|
||||||
|
m_state = FS_HANG;
|
||||||
|
m_timeoutTone.stop();
|
||||||
|
DEBUG1("Send ack");
|
||||||
|
m_rfAck.start();
|
||||||
|
m_ackDelayTimer.stop();
|
||||||
|
m_ackMinTimer.stop();
|
||||||
|
m_timeoutTimer.stop();
|
||||||
|
m_hangTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_callsignTimer.isRunning() && m_callsignTimer.hasExpired()) {
|
||||||
|
sendCallsign();
|
||||||
|
m_callsignTimer.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::sendCallsign()
|
||||||
|
{
|
||||||
|
if (m_holdoffTimer.isRunning()) {
|
||||||
|
if (m_holdoffTimer.hasExpired()) {
|
||||||
|
DEBUG1("Send callsign");
|
||||||
|
m_callsign.start();
|
||||||
|
m_holdoffTimer.start();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG1("Send callsign");
|
||||||
|
m_callsign.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::beginRelaying()
|
||||||
|
{
|
||||||
|
m_timeoutTimer.start();
|
||||||
|
m_ackMinTimer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::insertDelay(uint16_t ms)
|
||||||
|
{
|
||||||
|
uint32_t nSamples = ms * 24U;
|
||||||
|
|
||||||
|
for (uint32_t i = 0U; i < nSamples; i++)
|
||||||
|
m_inputRB.put(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFM::insertSilence(uint16_t ms)
|
||||||
|
{
|
||||||
|
uint32_t nSamples = ms * 24U;
|
||||||
|
|
||||||
|
for (uint32_t i = 0U; i < nSamples; i++)
|
||||||
|
m_outputRB.put(0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(FM_H)
|
||||||
|
#define FM_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "FMBlanking.h"
|
||||||
|
#include "FMCTCSSRX.h"
|
||||||
|
#include "FMCTCSSTX.h"
|
||||||
|
#include "FMTimeout.h"
|
||||||
|
#include "FMKeyer.h"
|
||||||
|
#include "FMTimer.h"
|
||||||
|
#include "FMRB.h"
|
||||||
|
#include "FMDirectForm1.h"
|
||||||
|
#include "FMDownsampler.h"
|
||||||
|
|
||||||
|
enum FM_STATE {
|
||||||
|
FS_LISTENING,
|
||||||
|
FS_KERCHUNK,
|
||||||
|
FS_RELAYING,
|
||||||
|
FS_RELAYING_WAIT,
|
||||||
|
FS_TIMEOUT,
|
||||||
|
FS_TIMEOUT_WAIT,
|
||||||
|
FS_HANG
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class CFM {
|
||||||
|
public:
|
||||||
|
CFM();
|
||||||
|
|
||||||
|
void samples(bool cos, const q15_t* samples, uint8_t length);
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
|
||||||
|
uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level);
|
||||||
|
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
CFMKeyer m_callsign;
|
||||||
|
CFMKeyer m_rfAck;
|
||||||
|
CFMCTCSSRX m_ctcssRX;
|
||||||
|
CFMCTCSSTX m_ctcssTX;
|
||||||
|
CFMTimeout m_timeoutTone;
|
||||||
|
FM_STATE m_state;
|
||||||
|
bool m_callsignAtStart;
|
||||||
|
bool m_callsignAtEnd;
|
||||||
|
bool m_callsignAtLatch;
|
||||||
|
CFMTimer m_callsignTimer;
|
||||||
|
CFMTimer m_timeoutTimer;
|
||||||
|
CFMTimer m_holdoffTimer;
|
||||||
|
CFMTimer m_kerchunkTimer;
|
||||||
|
CFMTimer m_ackMinTimer;
|
||||||
|
CFMTimer m_ackDelayTimer;
|
||||||
|
CFMTimer m_hangTimer;
|
||||||
|
CFMDirectFormI m_filterStage1;
|
||||||
|
CFMDirectFormI m_filterStage2;
|
||||||
|
CFMDirectFormI m_filterStage3;
|
||||||
|
CFMBlanking m_blanking;
|
||||||
|
bool m_useCOS;
|
||||||
|
bool m_cosInvert;
|
||||||
|
q15_t m_rfAudioBoost;
|
||||||
|
CFMDownsampler m_downsampler;
|
||||||
|
q15_t m_rxLevel;
|
||||||
|
CFMRB m_inputRB;
|
||||||
|
CFMRB m_outputRB;
|
||||||
|
|
||||||
|
void stateMachine(bool validSignal);
|
||||||
|
void listeningState(bool validSignal);
|
||||||
|
void kerchunkState(bool validSignal);
|
||||||
|
void relayingState(bool validSignal);
|
||||||
|
void relayingWaitState(bool validSignal);
|
||||||
|
void timeoutState(bool validSignal);
|
||||||
|
void timeoutWaitState(bool validSignal);
|
||||||
|
void hangState(bool validSignal);
|
||||||
|
|
||||||
|
void clock(uint8_t length);
|
||||||
|
|
||||||
|
void sendCallsign();
|
||||||
|
void beginRelaying();
|
||||||
|
|
||||||
|
void insertDelay(uint16_t ms);
|
||||||
|
void insertSilence(uint16_t ms);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "FMBlanking.h"
|
#include "FMBlanking.h"
|
||||||
|
|
||||||
@@ -83,6 +80,3 @@ q15_t CFMBlanking::process(q15_t sample)
|
|||||||
|
|
||||||
return sample;
|
return sample;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -16,13 +16,11 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#if !defined(FMBlanking_H)
|
#if !defined(FMBlanking_H)
|
||||||
#define FMBlanking_H
|
#define FMBlanking_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
class CFMBlanking {
|
class CFMBlanking {
|
||||||
public:
|
public:
|
||||||
CFMBlanking();
|
CFMBlanking();
|
||||||
@@ -41,6 +39,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "FMCTCSSRX.h"
|
#include "FMCTCSSRX.h"
|
||||||
|
|
||||||
@@ -90,7 +87,7 @@ m_lowThreshold(0),
|
|||||||
m_count(0U),
|
m_count(0U),
|
||||||
m_q0(0),
|
m_q0(0),
|
||||||
m_q1(0),
|
m_q1(0),
|
||||||
m_state(false)
|
m_result(CTS_NONE)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,11 +111,13 @@ uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t highThreshold, uint8_t
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFMCTCSSRX::process(q15_t sample)
|
uint8_t CFMCTCSSRX::process(q15_t sample)
|
||||||
{
|
{
|
||||||
//get more dynamic into the decoder by multiplying the sample by 1.5
|
//get more dynamic into the decoder by multiplying the sample by 1.5
|
||||||
q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1);
|
q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1);
|
||||||
|
|
||||||
|
m_result &= ~CTS_READY;
|
||||||
|
|
||||||
q31_t q2 = m_q1;
|
q31_t q2 = m_q1;
|
||||||
m_q1 = m_q0;
|
m_q1 = m_q0;
|
||||||
|
|
||||||
@@ -150,32 +149,33 @@ bool CFMCTCSSRX::process(q15_t sample)
|
|||||||
// value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2
|
// value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2
|
||||||
q31_t value = t2 + t4 - t9;
|
q31_t value = t2 + t4 - t9;
|
||||||
|
|
||||||
bool previousState = m_state;
|
bool previousCTCSSValid = CTCSS_VALID(m_result);
|
||||||
|
|
||||||
q31_t threshold = m_highThreshold;
|
q31_t threshold = m_highThreshold;
|
||||||
if (previousState)
|
if (previousCTCSSValid)
|
||||||
threshold = m_lowThreshold;
|
threshold = m_lowThreshold;
|
||||||
|
|
||||||
m_state = value >= threshold;
|
m_result |= CTS_READY;
|
||||||
|
if (value >= threshold)
|
||||||
|
m_result |= CTS_VALID;
|
||||||
|
else
|
||||||
|
m_result &= ~CTS_VALID;
|
||||||
|
|
||||||
if (previousState != m_state)
|
if (previousCTCSSValid != CTCSS_VALID(m_result))
|
||||||
DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, m_state);
|
DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, CTCSS_VALID(m_result));
|
||||||
|
|
||||||
m_count = 0U;
|
m_count = 0U;
|
||||||
m_q0 = 0;
|
m_q0 = 0;
|
||||||
m_q1 = 0;
|
m_q1 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_state;
|
return m_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFMCTCSSRX::reset()
|
void CFMCTCSSRX::reset()
|
||||||
{
|
{
|
||||||
m_q0 = 0;
|
m_q0 = 0;
|
||||||
m_q1 = 0;
|
m_q1 = 0;
|
||||||
m_state = false;
|
m_result = CTS_NONE;
|
||||||
m_count = 0U;
|
m_count = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -16,20 +16,27 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#if !defined(FMCTCSSRX_H)
|
#if !defined(FMCTCSSRX_H)
|
||||||
#define FMCTCSSRX_H
|
#define FMCTCSSRX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
const uint8_t CTS_NONE = 0U;
|
||||||
|
const uint8_t CTS_READY = 1U;
|
||||||
|
const uint8_t CTS_VALID = 2U;
|
||||||
|
|
||||||
|
#define CTCSS_READY(a) ((a & CTS_READY) != 0)
|
||||||
|
#define CTCSS_NOT_READY(a) ((a & CTS_READY) == 0)
|
||||||
|
#define CTCSS_VALID(a) ((a & CTS_VALID) != 0)
|
||||||
|
#define CTCSS_NOT_VALID(a) ((a & CTS_VALID) == 0)
|
||||||
|
|
||||||
class CFMCTCSSRX {
|
class CFMCTCSSRX {
|
||||||
public:
|
public:
|
||||||
CFMCTCSSRX();
|
CFMCTCSSRX();
|
||||||
|
|
||||||
uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold);
|
uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold);
|
||||||
|
|
||||||
bool process(q15_t sample);
|
uint8_t process(q15_t sample);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
@@ -40,10 +47,7 @@ private:
|
|||||||
uint16_t m_count;
|
uint16_t m_count;
|
||||||
q31_t m_q0;
|
q31_t m_q0;
|
||||||
q31_t m_q1;
|
q31_t m_q1;
|
||||||
bool m_state;
|
uint8_t m_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "FMCTCSSTX.h"
|
#include "FMCTCSSTX.h"
|
||||||
|
|
||||||
@@ -118,17 +115,11 @@ uint8_t CFMCTCSSTX::setParams(uint8_t frequency, uint8_t level)
|
|||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
q15_t CFMCTCSSTX::getAudio(bool reverse)
|
q15_t CFMCTCSSTX::getAudio()
|
||||||
{
|
{
|
||||||
q15_t sample = m_values[m_n++];
|
q15_t sample = m_values[m_n++];
|
||||||
if (m_n >= m_length)
|
if(m_n >= m_length)
|
||||||
m_n = 0U;
|
m_n = 0U;
|
||||||
|
|
||||||
if (reverse)
|
return sample;
|
||||||
return -sample;
|
|
||||||
else
|
|
||||||
return sample;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -16,20 +16,18 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#if !defined(FMCTCSSTX_H)
|
#if !defined(FMCTCSSTX_H)
|
||||||
#define FMCTCSSTX_H
|
#define FMCTCSSTX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
class CFMCTCSSTX {
|
class CFMCTCSSTX {
|
||||||
public:
|
public:
|
||||||
CFMCTCSSTX();
|
CFMCTCSSTX();
|
||||||
|
|
||||||
uint8_t setParams(uint8_t frequency, uint8_t level);
|
uint8_t setParams(uint8_t frequency, uint8_t level);
|
||||||
|
|
||||||
q15_t getAudio(bool reverse);
|
q15_t getAudio();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
q15_t* m_values;
|
q15_t* m_values;
|
||||||
@@ -38,6 +36,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -29,11 +29,7 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
// based on https://raw.githubusercontent.com/berndporr/iir_fixed_point/master/DirectFormI.h
|
// based on https://raw.githubusercontent.com/berndporr/iir_fixed_point/master/DirectFormI.h
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Globals.h"
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
#ifndef DIRECTFORMI_H_
|
#ifndef DIRECTFORMI_H_
|
||||||
#define DIRECTFORMI_H_
|
#define DIRECTFORMI_H_
|
||||||
@@ -42,7 +38,8 @@ class CFMDirectFormI
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
// convenience function which takes the a0 argument but ignores it!
|
// convenience function which takes the a0 argument but ignores it!
|
||||||
CFMDirectFormI(const q31_t b0, const q31_t b1, const q31_t b2, const q31_t, const q31_t a1, const q31_t a2)
|
CFMDirectFormI(const q31_t b0, const q31_t b1, const q31_t b2,
|
||||||
|
const q31_t, const q31_t a1, const q31_t a2)
|
||||||
{
|
{
|
||||||
// FIR coefficients
|
// FIR coefficients
|
||||||
c_b0 = b0;
|
c_b0 = b0;
|
||||||
@@ -56,21 +53,21 @@ public:
|
|||||||
|
|
||||||
CFMDirectFormI(const CFMDirectFormI &my)
|
CFMDirectFormI(const CFMDirectFormI &my)
|
||||||
{
|
{
|
||||||
// delay line
|
// delay line
|
||||||
m_x2 = my.m_x2; // x[n-2]
|
m_x2 = my.m_x2; // x[n-2]
|
||||||
m_y2 = my.m_y2; // y[n-2]
|
m_y2 = my.m_y2; // y[n-2]
|
||||||
m_x1 = my.m_x1; // x[n-1]
|
m_x1 = my.m_x1; // x[n-1]
|
||||||
m_y1 = my.m_y1; // y[n-1]
|
m_y1 = my.m_y1; // y[n-1]
|
||||||
|
|
||||||
// coefficients
|
// coefficients
|
||||||
c_b0 = my.c_b0;
|
c_b0 = my.c_b0;
|
||||||
c_b1 = my.c_b1;
|
c_b1 = my.c_b1;
|
||||||
c_b2 = my.c_b2; // FIR
|
c_b2 = my.c_b2; // FIR
|
||||||
c_a1 = my.c_a1;
|
c_a1 = my.c_a1;
|
||||||
c_a2 = my.c_a2; // IIR
|
c_a2 = my.c_a2; // IIR
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset()
|
void reset ()
|
||||||
{
|
{
|
||||||
m_x1 = 0;
|
m_x1 = 0;
|
||||||
m_x2 = 0;
|
m_x2 = 0;
|
||||||
@@ -82,7 +79,11 @@ public:
|
|||||||
inline q15_t filter(const q15_t in)
|
inline q15_t filter(const q15_t in)
|
||||||
{
|
{
|
||||||
// calculate the output
|
// calculate the output
|
||||||
q31_t out_upscaled = c_b0 * in + c_b1 * m_x1 + c_b2 * m_x2 - c_a1 * m_y1 - c_a2 * m_y2;
|
register q31_t out_upscaled = c_b0 * in
|
||||||
|
+ c_b1 * m_x1
|
||||||
|
+ c_b2 * m_x2
|
||||||
|
- c_a1 * m_y1
|
||||||
|
- c_a2 * m_y2;
|
||||||
|
|
||||||
q15_t out = __SSAT(out_upscaled >> 15, 15);
|
q15_t out = __SSAT(out_upscaled >> 15, 15);
|
||||||
|
|
||||||
@@ -108,6 +109,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DIRECTFORMI_H */
|
#endif /* DIRECTFORMI_H */
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,19 +16,20 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
|
||||||
|
|
||||||
template <typename TDATATYPE> CRingBuffer<TDATATYPE>::CRingBuffer(uint16_t length) :
|
#include "FMDownsampleRB.h"
|
||||||
|
|
||||||
|
CFMDownsampleRB::CFMDownsampleRB(uint16_t length) :
|
||||||
m_length(length),
|
m_length(length),
|
||||||
m_head(0U),
|
m_head(0U),
|
||||||
m_tail(0U),
|
m_tail(0U),
|
||||||
m_full(false),
|
m_full(false),
|
||||||
m_overflow(false)
|
m_overflow(false)
|
||||||
{
|
{
|
||||||
m_buffer = new TDATATYPE[length];
|
m_samples = new uint8_t[length];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getSpace() const
|
uint16_t CFMDownsampleRB::getSpace() const
|
||||||
{
|
{
|
||||||
uint16_t n = 0U;
|
uint16_t n = 0U;
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getSpace() const
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getData() const
|
uint16_t CFMDownsampleRB::getData() const
|
||||||
{
|
{
|
||||||
if (m_tail == m_head)
|
if (m_tail == m_head)
|
||||||
return m_full ? m_length : 0U;
|
return m_full ? m_length : 0U;
|
||||||
@@ -56,14 +56,14 @@ template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getData() const
|
|||||||
return m_length - m_tail + m_head;
|
return m_length - m_tail + m_head;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::put(TDATATYPE item) volatile
|
bool CFMDownsampleRB::put(uint8_t sample)
|
||||||
{
|
{
|
||||||
if (m_full) {
|
if (m_full) {
|
||||||
m_overflow = true;
|
m_overflow = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_buffer[m_head] = item;
|
m_samples[m_head] = sample;
|
||||||
|
|
||||||
m_head++;
|
m_head++;
|
||||||
if (m_head >= m_length)
|
if (m_head >= m_length)
|
||||||
@@ -75,17 +75,12 @@ template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::put(TDATATYPE item) v
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TDATATYPE> TDATATYPE CRingBuffer<TDATATYPE>::peek() const
|
bool CFMDownsampleRB::get(uint8_t& sample)
|
||||||
{
|
|
||||||
return m_buffer[m_tail];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::get(TDATATYPE& item) volatile
|
|
||||||
{
|
{
|
||||||
if (m_head == m_tail && !m_full)
|
if (m_head == m_tail && !m_full)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
item = m_buffer[m_tail];
|
sample = m_samples[m_tail];
|
||||||
|
|
||||||
m_full = false;
|
m_full = false;
|
||||||
|
|
||||||
@@ -96,7 +91,7 @@ template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::get(TDATATYPE& item)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::hasOverflowed()
|
bool CFMDownsampleRB::hasOverflowed()
|
||||||
{
|
{
|
||||||
bool overflow = m_overflow;
|
bool overflow = m_overflow;
|
||||||
|
|
||||||
@@ -104,11 +99,3 @@ template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::hasOverflowed()
|
|||||||
|
|
||||||
return overflow;
|
return overflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TDATATYPE> void CRingBuffer<TDATATYPE>::reset()
|
|
||||||
{
|
|
||||||
m_head = 0U;
|
|
||||||
m_tail = 0U;
|
|
||||||
m_full = false;
|
|
||||||
m_overflow = false;
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020,2024 by Jonathan Naylor G4KLX
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,42 +16,53 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !defined(RINGBUFFER_H)
|
#if !defined(FMDOWNSAMPLERB_H)
|
||||||
#define RINGBUFFER_H
|
#define FMDOWNSAMPLERB_H
|
||||||
|
|
||||||
|
#if defined(STM32F4XX)
|
||||||
|
#include "stm32f4xx.h"
|
||||||
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
|
#elif defined(STM32F105xC)
|
||||||
|
#include "stm32f1xx.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#else
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#undef PI
|
#endif
|
||||||
|
|
||||||
|
#if defined(__SAM3X8E__) || defined(STM32F105xC)
|
||||||
|
#define ARM_MATH_CM3
|
||||||
|
#elif defined(STM32F7XX)
|
||||||
|
#define ARM_MATH_CM7
|
||||||
|
#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||||
|
#define ARM_MATH_CM4
|
||||||
|
#else
|
||||||
|
#error "Unknown processor type"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <arm_math.h>
|
#include <arm_math.h>
|
||||||
|
|
||||||
template <typename TDATATYPE>
|
class CFMDownsampleRB {
|
||||||
class CRingBuffer {
|
|
||||||
public:
|
public:
|
||||||
CRingBuffer(uint16_t length = 370U);
|
CFMDownsampleRB(uint16_t length);
|
||||||
|
|
||||||
uint16_t getSpace() const;
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
uint16_t getData() const;
|
uint16_t getData() const;
|
||||||
|
|
||||||
bool put(TDATATYPE item) volatile;
|
bool put(uint8_t sample);
|
||||||
|
|
||||||
bool get(TDATATYPE& item) volatile;
|
bool get(uint8_t& sample);
|
||||||
|
|
||||||
TDATATYPE peek() const;
|
|
||||||
|
|
||||||
bool hasOverflowed();
|
bool hasOverflowed();
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t m_length;
|
uint16_t m_length;
|
||||||
TDATATYPE* m_buffer;
|
volatile uint8_t* m_samples;
|
||||||
volatile uint16_t m_head;
|
volatile uint16_t m_head;
|
||||||
volatile uint16_t m_tail;
|
volatile uint16_t m_tail;
|
||||||
volatile bool m_full;
|
volatile bool m_full;
|
||||||
bool m_overflow;
|
bool m_overflow;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "RingBuffer.impl.h"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "FMDownsampler.h"
|
||||||
|
|
||||||
|
|
||||||
|
CFMDownsampler::CFMDownsampler(uint16_t length) :
|
||||||
|
m_ringBuffer(length),//length might need tweaking
|
||||||
|
m_packIndex(0),
|
||||||
|
m_downSampleIndex(0)
|
||||||
|
{
|
||||||
|
m_samplePack = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFMDownsampler::addSample(q15_t sample)
|
||||||
|
{
|
||||||
|
//only take one of three samples
|
||||||
|
if(m_downSampleIndex == 0) {
|
||||||
|
switch(m_packIndex){
|
||||||
|
case 0:
|
||||||
|
m_samplePack = int32_t(sample) << 12;
|
||||||
|
break;
|
||||||
|
case 1:{
|
||||||
|
m_samplePack |= int32_t(sample);
|
||||||
|
|
||||||
|
//we did not use MSB; skip it
|
||||||
|
m_ringBuffer.put(m_samplePackBytes[1]);
|
||||||
|
m_ringBuffer.put(m_samplePackBytes[2]);
|
||||||
|
m_ringBuffer.put(m_samplePackBytes[3]);
|
||||||
|
|
||||||
|
m_samplePack = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//should never happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_packIndex++;
|
||||||
|
if(m_packIndex >= 2)
|
||||||
|
m_packIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_downSampleIndex++;
|
||||||
|
if(m_downSampleIndex >= 3)
|
||||||
|
m_downSampleIndex = 0;
|
||||||
|
}
|
||||||
@@ -17,36 +17,27 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#if !defined(FMDOWNSAMPLER_H)
|
#if !defined(FMDOWNSAMPLER_H)
|
||||||
#define FMDOWNSAMPLER_H
|
#define FMDOWNSAMPLER_H
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "Config.h"
|
||||||
#include "FMSamplePairPack.h"
|
#include "FMDownsampleRB.h"
|
||||||
|
|
||||||
class CFMDownSampler {
|
class CFMDownsampler {
|
||||||
public:
|
public:
|
||||||
CFMDownSampler(uint16_t length);
|
CFMDownsampler(uint16_t length);
|
||||||
|
|
||||||
void addSample(q15_t sample);
|
void addSample(q15_t sample);
|
||||||
|
inline bool getPackedData(uint8_t& data){ return m_ringBuffer.get(data); };
|
||||||
bool getPackedData(TSamplePairPack& data);
|
inline bool hasOverflowed() { return m_ringBuffer.hasOverflowed(); };
|
||||||
|
|
||||||
uint16_t getData();
|
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRingBuffer<TSamplePairPack> m_ringBuffer;
|
CFMDownsampleRB m_ringBuffer;
|
||||||
uint32_t m_samplePack;
|
union {
|
||||||
uint8_t* m_samplePackPointer;
|
int32_t m_samplePack;
|
||||||
uint8_t m_sampleIndex;
|
int8_t m_samplePackBytes[4];
|
||||||
|
};
|
||||||
|
uint8_t m_packIndex;
|
||||||
|
uint8_t m_downSampleIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "FMKeyer.h"
|
#include "FMKeyer.h"
|
||||||
|
|
||||||
@@ -217,6 +214,3 @@ bool CFMKeyer::isRunning() const
|
|||||||
{
|
{
|
||||||
return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U;
|
return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -16,13 +16,11 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#if !defined(FMKeyer_H)
|
#if !defined(FMKeyer_H)
|
||||||
#define FMKeyer_H
|
#define FMKeyer_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
class CFMKeyer {
|
class CFMKeyer {
|
||||||
public:
|
public:
|
||||||
CFMKeyer();
|
CFMKeyer();
|
||||||
@@ -54,6 +52,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
TX fifo control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "FMRB.h"
|
||||||
|
|
||||||
|
CFMRB::CFMRB(uint16_t length) :
|
||||||
|
m_length(length),
|
||||||
|
m_head(0U),
|
||||||
|
m_tail(0U),
|
||||||
|
m_full(false),
|
||||||
|
m_overflow(false)
|
||||||
|
{
|
||||||
|
m_samples = new q15_t[length];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CFMRB::getSpace() const
|
||||||
|
{
|
||||||
|
uint16_t n = 0U;
|
||||||
|
|
||||||
|
if (m_tail == m_head)
|
||||||
|
n = m_full ? 0U : m_length;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
n = m_length - m_head + m_tail;
|
||||||
|
else
|
||||||
|
n = m_tail - m_head;
|
||||||
|
|
||||||
|
if (n > m_length)
|
||||||
|
n = 0U;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CFMRB::getData() const
|
||||||
|
{
|
||||||
|
if (m_tail == m_head)
|
||||||
|
return m_full ? m_length : 0U;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
return m_head - m_tail;
|
||||||
|
else
|
||||||
|
return m_length - m_tail + m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFMRB::put(q15_t sample)
|
||||||
|
{
|
||||||
|
if (m_full) {
|
||||||
|
m_overflow = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_samples[m_head] = sample;
|
||||||
|
|
||||||
|
m_head++;
|
||||||
|
if (m_head >= m_length)
|
||||||
|
m_head = 0U;
|
||||||
|
|
||||||
|
if (m_head == m_tail)
|
||||||
|
m_full = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFMRB::get(q15_t& sample)
|
||||||
|
{
|
||||||
|
if (m_head == m_tail && !m_full)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sample = m_samples[m_tail];
|
||||||
|
|
||||||
|
m_full = false;
|
||||||
|
|
||||||
|
m_tail++;
|
||||||
|
if (m_tail >= m_length)
|
||||||
|
m_tail = 0U;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFMRB::hasOverflowed()
|
||||||
|
{
|
||||||
|
bool overflow = m_overflow;
|
||||||
|
|
||||||
|
m_overflow = false;
|
||||||
|
|
||||||
|
return overflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFMRB::reset()
|
||||||
|
{
|
||||||
|
m_head = 0U;
|
||||||
|
m_tail = 0U;
|
||||||
|
m_full = false;
|
||||||
|
m_overflow = false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
Serial fifo control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(FMRB_H)
|
||||||
|
#define FMRB_H
|
||||||
|
|
||||||
|
#if defined(STM32F4XX)
|
||||||
|
#include "stm32f4xx.h"
|
||||||
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
|
#elif defined(STM32F105xC)
|
||||||
|
#include "stm32f1xx.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#else
|
||||||
|
#include <Arduino.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__SAM3X8E__) || defined(STM32F105xC)
|
||||||
|
#define ARM_MATH_CM3
|
||||||
|
#elif defined(STM32F7XX)
|
||||||
|
#define ARM_MATH_CM7
|
||||||
|
#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||||
|
#define ARM_MATH_CM4
|
||||||
|
#else
|
||||||
|
#error "Unknown processor type"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <arm_math.h>
|
||||||
|
|
||||||
|
class CFMRB {
|
||||||
|
public:
|
||||||
|
CFMRB(uint16_t length);
|
||||||
|
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
|
uint16_t getData() const;
|
||||||
|
|
||||||
|
bool put(q15_t sample);
|
||||||
|
|
||||||
|
bool get(q15_t& sample);
|
||||||
|
|
||||||
|
bool hasOverflowed();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t m_length;
|
||||||
|
volatile q15_t* m_samples;
|
||||||
|
volatile uint16_t m_head;
|
||||||
|
volatile uint16_t m_tail;
|
||||||
|
volatile bool m_full;
|
||||||
|
bool m_overflow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "FMTimeout.h"
|
#include "FMTimeout.h"
|
||||||
|
|
||||||
@@ -39,22 +36,24 @@ m_n(0U)
|
|||||||
|
|
||||||
void CFMTimeout::setParams(uint8_t level)
|
void CFMTimeout::setParams(uint8_t level)
|
||||||
{
|
{
|
||||||
m_level = q15_t(level * 5);
|
m_level = q15_t(level * 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
q15_t CFMTimeout::getAudio()
|
q15_t CFMTimeout::getAudio()
|
||||||
{
|
{
|
||||||
q15_t sample = 0;
|
q15_t sample = 0U;
|
||||||
if (!m_running)
|
if (!m_running)
|
||||||
return sample;
|
return sample;
|
||||||
|
|
||||||
if (m_pos >= 12000U) {
|
if (m_pos > 12000U) {
|
||||||
q31_t sample31 = BUSY_AUDIO[m_n] * m_level;
|
q31_t sample = BUSY_AUDIO[m_n] * m_level;
|
||||||
sample = q15_t(__SSAT((sample31 >> 15), 16));
|
sample = q15_t(__SSAT((sample >> 15), 16));
|
||||||
|
|
||||||
m_n++;
|
m_n++;
|
||||||
if (m_n >= BUSY_AUDIO_LEN)
|
if (m_n >= BUSY_AUDIO_LEN)
|
||||||
m_n = 0U;
|
m_n = 0U;
|
||||||
|
} else {
|
||||||
|
sample = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_pos++;
|
m_pos++;
|
||||||
@@ -75,6 +74,3 @@ void CFMTimeout::stop()
|
|||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -16,13 +16,11 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#if !defined(FMTimeout_H)
|
#if !defined(FMTimeout_H)
|
||||||
#define FMTimeout_H
|
#define FMTimeout_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
class CFMTimeout {
|
class CFMTimeout {
|
||||||
public:
|
public:
|
||||||
CFMTimeout();
|
CFMTimeout();
|
||||||
@@ -42,6 +40,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "FMTimer.h"
|
#include "FMTimer.h"
|
||||||
|
|
||||||
@@ -71,6 +68,3 @@ bool CFMTimer::hasExpired() const
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -16,13 +16,11 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
|
|
||||||
#if !defined(FMTimer_H)
|
#if !defined(FMTimer_H)
|
||||||
#define FMTimer_H
|
#define FMTimer_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
class CFMTimer {
|
class CFMTimer {
|
||||||
public:
|
public:
|
||||||
CFMTimer();
|
CFMTimer();
|
||||||
@@ -47,6 +45,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+54
-80
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2018,2020,2021,2024 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,8 +19,26 @@
|
|||||||
#if !defined(GLOBALS_H)
|
#if !defined(GLOBALS_H)
|
||||||
#define GLOBALS_H
|
#define GLOBALS_H
|
||||||
|
|
||||||
|
#if defined(STM32F4XX)
|
||||||
|
#include "stm32f4xx.h"
|
||||||
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
|
#elif defined(STM32F105xC)
|
||||||
|
#include "stm32f1xx.h"
|
||||||
|
#include "STM32Utils.h"
|
||||||
|
#else
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#undef PI //Undefine PI to get rid of annoying warning as it is also defined in arm_math.h.
|
#endif
|
||||||
|
|
||||||
|
#if defined(__SAM3X8E__) || defined(STM32F105xC)
|
||||||
|
#define ARM_MATH_CM3
|
||||||
|
#elif defined(STM32F7XX)
|
||||||
|
#define ARM_MATH_CM7
|
||||||
|
#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||||
|
#define ARM_MATH_CM4
|
||||||
|
#else
|
||||||
|
#error "Unknown processor type"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <arm_math.h>
|
#include <arm_math.h>
|
||||||
|
|
||||||
@@ -32,9 +50,7 @@ enum MMDVM_STATE {
|
|||||||
STATE_P25 = 4,
|
STATE_P25 = 4,
|
||||||
STATE_NXDN = 5,
|
STATE_NXDN = 5,
|
||||||
STATE_POCSAG = 6,
|
STATE_POCSAG = 6,
|
||||||
STATE_M17 = 7,
|
|
||||||
STATE_FM = 10,
|
STATE_FM = 10,
|
||||||
STATE_AX25 = 11,
|
|
||||||
|
|
||||||
// Dummy states start at 90
|
// Dummy states start at 90
|
||||||
STATE_NXDNCAL1K = 91,
|
STATE_NXDNCAL1K = 91,
|
||||||
@@ -53,43 +69,36 @@ enum MMDVM_STATE {
|
|||||||
STATE_FMCAL15K = 104,
|
STATE_FMCAL15K = 104,
|
||||||
STATE_FMCAL20K = 105,
|
STATE_FMCAL20K = 105,
|
||||||
STATE_FMCAL25K = 106,
|
STATE_FMCAL25K = 106,
|
||||||
STATE_FMCAL30K = 107,
|
STATE_FMCAL30K = 107
|
||||||
STATE_M17CAL = 108
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "SerialPort.h"
|
#include "SerialPort.h"
|
||||||
|
#include "DMRIdleRX.h"
|
||||||
#include "POCSAG/CalPOCSAG.h"
|
#include "DMRDMORX.h"
|
||||||
#include "DStar/CalDStarRX.h"
|
#include "DMRDMOTX.h"
|
||||||
#include "DStar/CalDStarTX.h"
|
#include "DStarRX.h"
|
||||||
#include "POCSAG/POCSAGTX.h"
|
#include "DStarTX.h"
|
||||||
#include "DStar/DStarRX.h"
|
#include "DMRRX.h"
|
||||||
#include "DStar/DStarTX.h"
|
#include "DMRTX.h"
|
||||||
#include "DMR/DMRIdleRX.h"
|
#include "YSFRX.h"
|
||||||
#include "DMR/DMRDMORX.h"
|
#include "YSFTX.h"
|
||||||
#include "DMR/DMRDMOTX.h"
|
#include "P25RX.h"
|
||||||
#include "NXDN/CalNXDN.h"
|
#include "P25TX.h"
|
||||||
#include "NXDN/NXDNRX.h"
|
#include "NXDNRX.h"
|
||||||
#include "NXDN/NXDNTX.h"
|
#include "NXDNTX.h"
|
||||||
#include "AX25/AX25RX.h"
|
#include "POCSAGTX.h"
|
||||||
#include "AX25/AX25TX.h"
|
#include "CalDStarRX.h"
|
||||||
#include "DMR/CalDMR.h"
|
#include "CalDStarTX.h"
|
||||||
#include "P25/CalP25.h"
|
#include "CalFM.h"
|
||||||
#include "M17/CalM17.h"
|
#include "CalDMR.h"
|
||||||
#include "DMR/DMRRX.h"
|
#include "CalP25.h"
|
||||||
#include "DMR/DMRTX.h"
|
#include "CalNXDN.h"
|
||||||
#include "YSF/YSFRX.h"
|
#include "CalPOCSAG.h"
|
||||||
#include "YSF/YSFTX.h"
|
|
||||||
#include "P25/P25RX.h"
|
|
||||||
#include "P25/P25TX.h"
|
|
||||||
#include "M17/M17RX.h"
|
|
||||||
#include "M17/M17TX.h"
|
|
||||||
#include "FM/CalFM.h"
|
|
||||||
#include "CalRSSI.h"
|
#include "CalRSSI.h"
|
||||||
#include "CWIdTX.h"
|
#include "CWIdTX.h"
|
||||||
#include "FM/FM.h"
|
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "IO.h"
|
#include "IO.h"
|
||||||
|
#include "FM.h"
|
||||||
|
|
||||||
const uint8_t MARK_SLOT1 = 0x08U;
|
const uint8_t MARK_SLOT1 = 0x08U;
|
||||||
const uint8_t MARK_SLOT2 = 0x04U;
|
const uint8_t MARK_SLOT2 = 0x04U;
|
||||||
@@ -100,9 +109,7 @@ const uint16_t RX_BLOCK_SIZE = 2U;
|
|||||||
const uint16_t TX_RINGBUFFER_SIZE = 500U;
|
const uint16_t TX_RINGBUFFER_SIZE = 500U;
|
||||||
const uint16_t RX_RINGBUFFER_SIZE = 600U;
|
const uint16_t RX_RINGBUFFER_SIZE = 600U;
|
||||||
|
|
||||||
const uint32_t SAMPLE_RATE = 24000U;
|
#if defined(STM32F105xC) || defined(__MK20DX256__)
|
||||||
|
|
||||||
#if defined(__MK20DX256__)
|
|
||||||
const uint16_t TX_BUFFER_LEN = 2000U;
|
const uint16_t TX_BUFFER_LEN = 2000U;
|
||||||
#else
|
#else
|
||||||
const uint16_t TX_BUFFER_LEN = 4000U;
|
const uint16_t TX_BUFFER_LEN = 4000U;
|
||||||
@@ -116,9 +123,7 @@ extern bool m_ysfEnable;
|
|||||||
extern bool m_p25Enable;
|
extern bool m_p25Enable;
|
||||||
extern bool m_nxdnEnable;
|
extern bool m_nxdnEnable;
|
||||||
extern bool m_pocsagEnable;
|
extern bool m_pocsagEnable;
|
||||||
extern bool m_m17Enable;
|
|
||||||
extern bool m_fmEnable;
|
extern bool m_fmEnable;
|
||||||
extern bool m_ax25Enable;
|
|
||||||
|
|
||||||
extern bool m_duplex;
|
extern bool m_duplex;
|
||||||
|
|
||||||
@@ -128,15 +133,9 @@ extern bool m_dcd;
|
|||||||
extern CSerialPort serial;
|
extern CSerialPort serial;
|
||||||
extern CIO io;
|
extern CIO io;
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
extern CDStarRX dstarRX;
|
extern CDStarRX dstarRX;
|
||||||
extern CDStarTX dstarTX;
|
extern CDStarTX dstarTX;
|
||||||
|
|
||||||
extern CCalDStarRX calDStarRX;
|
|
||||||
extern CCalDStarTX calDStarTX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
extern CDMRIdleRX dmrIdleRX;
|
extern CDMRIdleRX dmrIdleRX;
|
||||||
extern CDMRRX dmrRX;
|
extern CDMRRX dmrRX;
|
||||||
extern CDMRTX dmrTX;
|
extern CDMRTX dmrTX;
|
||||||
@@ -144,53 +143,28 @@ extern CDMRTX dmrTX;
|
|||||||
extern CDMRDMORX dmrDMORX;
|
extern CDMRDMORX dmrDMORX;
|
||||||
extern CDMRDMOTX dmrDMOTX;
|
extern CDMRDMOTX dmrDMOTX;
|
||||||
|
|
||||||
extern CCalDMR calDMR;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_YSF)
|
|
||||||
extern CYSFRX ysfRX;
|
extern CYSFRX ysfRX;
|
||||||
extern CYSFTX ysfTX;
|
extern CYSFTX ysfTX;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
extern CP25RX p25RX;
|
extern CP25RX p25RX;
|
||||||
extern CP25TX p25TX;
|
extern CP25TX p25TX;
|
||||||
|
|
||||||
extern CCalP25 calP25;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
extern CNXDNRX nxdnRX;
|
extern CNXDNRX nxdnRX;
|
||||||
extern CNXDNTX nxdnTX;
|
extern CNXDNTX nxdnTX;
|
||||||
|
|
||||||
extern CCalNXDN calNXDN;
|
extern CPOCSAGTX pocsagTX;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_POCSAG)
|
extern CFM fm;
|
||||||
extern CPOCSAGTX pocsagTX;
|
|
||||||
extern CCalPOCSAG calPOCSAG;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_M17)
|
extern CCalDStarRX calDStarRX;
|
||||||
extern CM17RX m17RX;
|
extern CCalDStarTX calDStarTX;
|
||||||
extern CM17TX m17TX;
|
extern CCalDMR calDMR;
|
||||||
|
extern CCalFM calFM;
|
||||||
extern CCalM17 calM17;
|
extern CCalP25 calP25;
|
||||||
#endif
|
extern CCalNXDN calNXDN;
|
||||||
|
extern CCalPOCSAG calPOCSAG;
|
||||||
#if defined(MODE_FM)
|
extern CCalRSSI calRSSI;
|
||||||
extern CFM fm;
|
|
||||||
extern CCalFM calFM;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_AX25)
|
|
||||||
extern CAX25RX ax25RX;
|
|
||||||
extern CAX25TX ax25TX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern CCalRSSI calRSSI;
|
|
||||||
|
|
||||||
extern CCWIdTX cwIdTX;
|
extern CCWIdTX cwIdTX;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
+235
@@ -0,0 +1,235 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 28-4-2017 Created for MMDVM Pi shield for Teensy by Chris Huitema
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#if defined(VK6MST_TEENSY_PI3_SHIELD_I2C)
|
||||||
|
|
||||||
|
#include <i2c_t3.h> //available here https://github.com/nox771/i2c_t3 or maybe the normal wire will work #include <wire.h> justs need to test i guess
|
||||||
|
|
||||||
|
#define I2C_ADDRESS 0x22
|
||||||
|
#define I2C_SPEED 100000
|
||||||
|
|
||||||
|
// Function prototypes
|
||||||
|
void receiveEvent(size_t count);
|
||||||
|
void requestEvent(void);
|
||||||
|
|
||||||
|
#define TX_FIFO_SIZE 512U
|
||||||
|
#define RX_FIFO_SIZE 512U
|
||||||
|
|
||||||
|
volatile uint8_t TXfifo[TX_FIFO_SIZE];
|
||||||
|
volatile uint8_t RXfifo[RX_FIFO_SIZE];
|
||||||
|
volatile uint16_t TXfifohead, TXfifotail;
|
||||||
|
volatile uint16_t RXfifohead, RXfifotail;
|
||||||
|
|
||||||
|
// Init queues
|
||||||
|
void TXfifoinit(void)
|
||||||
|
{
|
||||||
|
TXfifohead = 0U;
|
||||||
|
TXfifotail = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RXfifoinit()
|
||||||
|
{
|
||||||
|
RXfifohead = 0U;
|
||||||
|
RXfifotail = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
// How full is queue
|
||||||
|
|
||||||
|
uint16_t TXfifolevel(void)
|
||||||
|
{
|
||||||
|
uint32_t tail = TXfifotail;
|
||||||
|
uint32_t head = TXfifohead;
|
||||||
|
|
||||||
|
if (tail > head)
|
||||||
|
return TX_FIFO_SIZE + head - tail;
|
||||||
|
else
|
||||||
|
return head - tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t RXfifolevel(void)
|
||||||
|
{
|
||||||
|
uint32_t tail = RXfifotail;
|
||||||
|
uint32_t head = RXfifohead;
|
||||||
|
|
||||||
|
if (tail > head)
|
||||||
|
return RX_FIFO_SIZE + head - tail;
|
||||||
|
else
|
||||||
|
return head - tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t TXfifoput(uint8_t next)
|
||||||
|
{
|
||||||
|
if (TXfifolevel() < TX_FIFO_SIZE) {
|
||||||
|
TXfifo[TXfifohead] = next;
|
||||||
|
|
||||||
|
TXfifohead++;
|
||||||
|
if (TXfifohead >= TX_FIFO_SIZE)
|
||||||
|
TXfifohead = 0U;
|
||||||
|
return 1U;
|
||||||
|
} else {
|
||||||
|
return 0U; // signal an overflow occurred by returning a zero count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2Cbegin(void)
|
||||||
|
{
|
||||||
|
// Setup for Slave mode, address 0x22, pins 18/19, external pullups, speed in hz
|
||||||
|
Wire.begin(I2C_SLAVE, I2C_ADDRESS, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_SPEED);
|
||||||
|
|
||||||
|
// register events
|
||||||
|
Wire.onReceive(receiveEvent);
|
||||||
|
Wire.onRequest(requestEvent);
|
||||||
|
|
||||||
|
// initialize the fifos
|
||||||
|
TXfifoinit();
|
||||||
|
RXfifoinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int I2Cavailable(void)
|
||||||
|
{
|
||||||
|
if (RXfifolevel() > 0U)
|
||||||
|
return 1U;
|
||||||
|
else
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t I2Cread(void)
|
||||||
|
{
|
||||||
|
uint8_t data_c = RXfifo[RXfifotail];
|
||||||
|
|
||||||
|
RXfifotail++;
|
||||||
|
if (RXfifotail >= RX_FIFO_SIZE)
|
||||||
|
RXfifotail = 0U;
|
||||||
|
|
||||||
|
return data_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void I2Cwrite(const uint8_t* data, uint16_t length)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0U; i < length; i++)
|
||||||
|
TXfifoput(data[i]); //puts it in the fifo
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// handle Rx Event (incoming I2C data)
|
||||||
|
//
|
||||||
|
void receiveEvent(size_t count)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0U; i < count; i++)
|
||||||
|
{
|
||||||
|
if (RXfifolevel() < RX_FIFO_SIZE) {
|
||||||
|
RXfifo[RXfifohead] = Wire.readByte();
|
||||||
|
if (RXfifo[RXfifohead] != -1){
|
||||||
|
RXfifohead++;
|
||||||
|
if (RXfifohead >= RX_FIFO_SIZE) RXfifohead = 0U;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Wire.readByte(); // drop data if mem full.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// handle Tx Event (outgoing I2C data)
|
||||||
|
//
|
||||||
|
void requestEvent(void)
|
||||||
|
{
|
||||||
|
if (TXfifolevel() > 0) {
|
||||||
|
if (Wire.write(TXfifo[TXfifotail])){ //write to i2c
|
||||||
|
TXfifotail++;
|
||||||
|
if (TXfifotail >= TX_FIFO_SIZE) TXfifotail = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************/
|
||||||
|
|
||||||
|
void CSerialPort::beginInt(uint8_t n, int speed)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
return I2Cbegin();
|
||||||
|
case 3U:
|
||||||
|
Serial3.begin(speed);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSerialPort::availableInt(uint8_t n)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
return I2Cavailable();
|
||||||
|
case 3U:
|
||||||
|
return Serial3.available();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSerialPort::availableForWriteInt(uint8_t n)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 3U:
|
||||||
|
return Serial3.availableForWrite();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSerialPort::readInt(uint8_t n)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
return I2Cread();
|
||||||
|
case 3U:
|
||||||
|
return Serial3.read();
|
||||||
|
default:
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
I2Cwrite(data, length);
|
||||||
|
break;
|
||||||
|
case 3U:
|
||||||
|
Serial3.write(data, length);
|
||||||
|
if (flush)
|
||||||
|
Serial3.flush();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,538 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
||||||
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "IO.h"
|
||||||
|
|
||||||
|
// Generated using [b, a] = butter(1, 0.001) in MATLAB
|
||||||
|
static q31_t DC_FILTER[] = {3367972, 0, 3367972, 0, 2140747704, 0}; // {b0, 0, b1, b2, -a1, -a2}
|
||||||
|
const uint32_t DC_FILTER_STAGES = 1U; // One Biquad stage
|
||||||
|
|
||||||
|
// One symbol boxcar filters
|
||||||
|
static q15_t BOXCAR5_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0};
|
||||||
|
const uint16_t BOXCAR5_FILTER_LEN = 6U;
|
||||||
|
|
||||||
|
static q15_t BOXCAR10_FILTER[] = {6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000};
|
||||||
|
const uint16_t BOXCAR10_FILTER_LEN = 10U;
|
||||||
|
|
||||||
|
const uint16_t DC_OFFSET = 2048U;
|
||||||
|
|
||||||
|
CIO::CIO() :
|
||||||
|
m_started(false),
|
||||||
|
m_rxBuffer(RX_RINGBUFFER_SIZE),
|
||||||
|
m_txBuffer(TX_RINGBUFFER_SIZE),
|
||||||
|
m_rssiBuffer(RX_RINGBUFFER_SIZE),
|
||||||
|
m_dcFilter(),
|
||||||
|
m_dcState(),
|
||||||
|
m_boxcar5Filter(),
|
||||||
|
m_boxcar10Filter(),
|
||||||
|
m_boxcar5State(),
|
||||||
|
m_boxcar10State(),
|
||||||
|
m_pttInvert(false),
|
||||||
|
m_rxLevel(128 * 128),
|
||||||
|
m_cwIdTXLevel(128 * 128),
|
||||||
|
m_dstarTXLevel(128 * 128),
|
||||||
|
m_dmrTXLevel(128 * 128),
|
||||||
|
m_ysfTXLevel(128 * 128),
|
||||||
|
m_p25TXLevel(128 * 128),
|
||||||
|
m_nxdnTXLevel(128 * 128),
|
||||||
|
m_pocsagTXLevel(128 * 128),
|
||||||
|
m_fmTXLevel(128 * 128),
|
||||||
|
m_rxDCOffset(DC_OFFSET),
|
||||||
|
m_txDCOffset(DC_OFFSET),
|
||||||
|
m_ledCount(0U),
|
||||||
|
m_ledValue(true),
|
||||||
|
m_detect(false),
|
||||||
|
m_adcOverflow(0U),
|
||||||
|
m_dacOverflow(0U),
|
||||||
|
m_watchdog(0U),
|
||||||
|
m_lockout(false)
|
||||||
|
{
|
||||||
|
::memset(m_boxcar5State, 0x00U, 30U * sizeof(q15_t));
|
||||||
|
::memset(m_boxcar10State, 0x00U, 40U * sizeof(q15_t));
|
||||||
|
::memset(m_dcState, 0x00U, 4U * sizeof(q31_t));
|
||||||
|
|
||||||
|
m_dcFilter.numStages = DC_FILTER_STAGES;
|
||||||
|
m_dcFilter.pState = m_dcState;
|
||||||
|
m_dcFilter.pCoeffs = DC_FILTER;
|
||||||
|
m_dcFilter.postShift = 0;
|
||||||
|
|
||||||
|
m_boxcar5Filter.numTaps = BOXCAR5_FILTER_LEN;
|
||||||
|
m_boxcar5Filter.pState = m_boxcar5State;
|
||||||
|
m_boxcar5Filter.pCoeffs = BOXCAR5_FILTER;
|
||||||
|
|
||||||
|
m_boxcar10Filter.numTaps = BOXCAR10_FILTER_LEN;
|
||||||
|
m_boxcar10Filter.pState = m_boxcar10State;
|
||||||
|
m_boxcar10Filter.pCoeffs = BOXCAR10_FILTER;
|
||||||
|
|
||||||
|
initInt();
|
||||||
|
|
||||||
|
selfTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::selfTest()
|
||||||
|
{
|
||||||
|
bool ledValue = false;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 6; i++) {
|
||||||
|
ledValue = !ledValue;
|
||||||
|
|
||||||
|
// We exclude PTT to avoid trigger the transmitter
|
||||||
|
setLEDInt(ledValue);
|
||||||
|
setCOSInt(ledValue);
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
setDStarInt(ledValue);
|
||||||
|
setDMRInt(ledValue);
|
||||||
|
setYSFInt(ledValue);
|
||||||
|
setP25Int(ledValue);
|
||||||
|
setNXDNInt(ledValue);
|
||||||
|
setPOCSAGInt(ledValue);
|
||||||
|
setFMInt(ledValue);
|
||||||
|
#endif
|
||||||
|
delayInt(250);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(false);
|
||||||
|
setYSFInt(false);
|
||||||
|
setP25Int(false);
|
||||||
|
setNXDNInt(false);
|
||||||
|
setPOCSAGInt(false);
|
||||||
|
setFMInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
setDMRInt(true);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
setYSFInt(true);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
setP25Int(true);
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
delayInt(250);
|
||||||
|
setNXDNInt(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
delayInt(250);
|
||||||
|
setPOCSAGInt(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
delayInt(250);
|
||||||
|
setFMInt(true);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
setFMInt(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
delayInt(250);
|
||||||
|
setPOCSAGInt(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
delayInt(250);
|
||||||
|
setNXDNInt(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
setP25Int(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
setYSFInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
setDMRInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
setDStarInt(false);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::start()
|
||||||
|
{
|
||||||
|
if (m_started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
startInt();
|
||||||
|
|
||||||
|
m_started = true;
|
||||||
|
|
||||||
|
setMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::process()
|
||||||
|
{
|
||||||
|
m_ledCount++;
|
||||||
|
if (m_started) {
|
||||||
|
// Two seconds timeout
|
||||||
|
if (m_watchdog >= 48000U) {
|
||||||
|
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN || m_modemState == STATE_POCSAG) {
|
||||||
|
if (m_modemState == STATE_DMR && m_tx)
|
||||||
|
dmrTX.setStart(false);
|
||||||
|
m_modemState = STATE_IDLE;
|
||||||
|
setMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_watchdog = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONSTANT_SRV_LED)
|
||||||
|
setLEDInt(true);
|
||||||
|
#else
|
||||||
|
if (m_ledCount >= 24000U) {
|
||||||
|
m_ledCount = 0U;
|
||||||
|
m_ledValue = !m_ledValue;
|
||||||
|
setLEDInt(m_ledValue);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (m_ledCount >= 240000U) {
|
||||||
|
m_ledCount = 0U;
|
||||||
|
m_ledValue = !m_ledValue;
|
||||||
|
setLEDInt(m_ledValue);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USE_COS_AS_LOCKOUT)
|
||||||
|
m_lockout = getCOSInt();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Switch off the transmitter if needed
|
||||||
|
if (m_txBuffer.getData() == 0U && m_tx) {
|
||||||
|
m_tx = false;
|
||||||
|
setPTTInt(m_pttInvert ? true : false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) {
|
||||||
|
q15_t samples[RX_BLOCK_SIZE];
|
||||||
|
uint8_t control[RX_BLOCK_SIZE];
|
||||||
|
uint16_t rssi[RX_BLOCK_SIZE];
|
||||||
|
|
||||||
|
for (uint16_t i = 0U; i < RX_BLOCK_SIZE; i++) {
|
||||||
|
uint16_t sample;
|
||||||
|
m_rxBuffer.get(sample, control[i]);
|
||||||
|
m_rssiBuffer.get(rssi[i]);
|
||||||
|
|
||||||
|
// Detect ADC overflow
|
||||||
|
if (m_detect && (sample == 0U || sample == 4095U))
|
||||||
|
m_adcOverflow++;
|
||||||
|
|
||||||
|
q15_t res1 = q15_t(sample) - m_rxDCOffset;
|
||||||
|
q31_t res2 = res1 * m_rxLevel;
|
||||||
|
samples[i] = q15_t(__SSAT((res2 >> 15), 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_lockout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
q31_t q31Samples[RX_BLOCK_SIZE];
|
||||||
|
::arm_q15_to_q31(samples, q31Samples, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
q31_t dcValues[RX_BLOCK_SIZE];
|
||||||
|
::arm_biquad_cascade_df1_q31(&m_dcFilter, q31Samples, dcValues, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
q31_t dcLevel = 0;
|
||||||
|
for (uint8_t i = 0U; i < RX_BLOCK_SIZE; i++)
|
||||||
|
dcLevel += dcValues[i];
|
||||||
|
dcLevel /= RX_BLOCK_SIZE;
|
||||||
|
|
||||||
|
q15_t offset = q15_t(__SSAT((dcLevel >> 16), 16));;
|
||||||
|
|
||||||
|
q15_t dcSamples[RX_BLOCK_SIZE];
|
||||||
|
for (uint8_t i = 0U; i < RX_BLOCK_SIZE; i++)
|
||||||
|
dcSamples[i] = samples[i] - offset;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (m_modemState == STATE_IDLE) {
|
||||||
|
if (m_dstarEnable || m_dmrEnable || m_ysfEnable || m_p25Enable) {
|
||||||
|
q15_t vals[RX_BLOCK_SIZE];
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, samples, vals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (m_dstarEnable)
|
||||||
|
dstarRX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (m_p25Enable)
|
||||||
|
p25RX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (m_ysfEnable)
|
||||||
|
ysfRX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (m_dmrEnable) {
|
||||||
|
if (m_duplex)
|
||||||
|
dmrIdleRX.samples(vals, RX_BLOCK_SIZE);
|
||||||
|
else
|
||||||
|
dmrDMORX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_nxdnEnable) {
|
||||||
|
q15_t vals[RX_BLOCK_SIZE];
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
::arm_fir_fast_q15(&m_boxcar10Filter, dcSamples, vals, RX_BLOCK_SIZE);
|
||||||
|
#else
|
||||||
|
::arm_fir_fast_q15(&m_boxcar10Filter, samples, vals, RX_BLOCK_SIZE);
|
||||||
|
#endif
|
||||||
|
nxdnRX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_fmEnable) {
|
||||||
|
bool cos = getCOSInt();
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
fm.samples(cos, dcSamples, RX_BLOCK_SIZE);
|
||||||
|
#else
|
||||||
|
fm.samples(cos, samples, RX_BLOCK_SIZE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else if (m_modemState == STATE_DSTAR) {
|
||||||
|
if (m_dstarEnable) {
|
||||||
|
q15_t vals[RX_BLOCK_SIZE];
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, vals, RX_BLOCK_SIZE);
|
||||||
|
#else
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, samples, vals, RX_BLOCK_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dstarRX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
} else if (m_modemState == STATE_DMR) {
|
||||||
|
if (m_dmrEnable) {
|
||||||
|
q15_t vals[RX_BLOCK_SIZE];
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, samples, vals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (m_duplex) {
|
||||||
|
// If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs
|
||||||
|
if (m_tx)
|
||||||
|
dmrRX.samples(vals, rssi, control, RX_BLOCK_SIZE);
|
||||||
|
else
|
||||||
|
dmrIdleRX.samples(vals, RX_BLOCK_SIZE);
|
||||||
|
} else {
|
||||||
|
dmrDMORX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (m_modemState == STATE_YSF) {
|
||||||
|
if (m_ysfEnable) {
|
||||||
|
q15_t vals[RX_BLOCK_SIZE];
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, vals, RX_BLOCK_SIZE);
|
||||||
|
#else
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, samples, vals, RX_BLOCK_SIZE);
|
||||||
|
#endif
|
||||||
|
ysfRX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
} else if (m_modemState == STATE_P25) {
|
||||||
|
if (m_p25Enable) {
|
||||||
|
q15_t vals[RX_BLOCK_SIZE];
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, vals, RX_BLOCK_SIZE);
|
||||||
|
#else
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, samples, vals, RX_BLOCK_SIZE);
|
||||||
|
#endif
|
||||||
|
p25RX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
} else if (m_modemState == STATE_NXDN) {
|
||||||
|
if (m_nxdnEnable) {
|
||||||
|
q15_t vals[RX_BLOCK_SIZE];
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
::arm_fir_fast_q15(&m_boxcar10Filter, dcSamples, vals, RX_BLOCK_SIZE);
|
||||||
|
#else
|
||||||
|
::arm_fir_fast_q15(&m_boxcar10Filter, samples, vals, RX_BLOCK_SIZE);
|
||||||
|
#endif
|
||||||
|
nxdnRX.samples(vals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
} else if (m_modemState == STATE_FM) {
|
||||||
|
bool cos = getCOSInt();
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
fm.samples(cos, dcSamples, RX_BLOCK_SIZE);
|
||||||
|
#else
|
||||||
|
fm.samples(cos, samples, RX_BLOCK_SIZE);
|
||||||
|
#endif
|
||||||
|
} else if (m_modemState == STATE_DSTARCAL) {
|
||||||
|
q15_t vals[RX_BLOCK_SIZE];
|
||||||
|
#if defined(USE_DCBLOCKER)
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, vals, RX_BLOCK_SIZE);
|
||||||
|
#else
|
||||||
|
::arm_fir_fast_q15(&m_boxcar5Filter, samples, vals, RX_BLOCK_SIZE);
|
||||||
|
#endif
|
||||||
|
calDStarRX.samples(vals, RX_BLOCK_SIZE);
|
||||||
|
} else if (m_modemState == STATE_RSSICAL) {
|
||||||
|
calRSSI.samples(rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t* control)
|
||||||
|
{
|
||||||
|
if (!m_started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_lockout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Switch the transmitter on if needed
|
||||||
|
if (!m_tx) {
|
||||||
|
m_tx = true;
|
||||||
|
setPTTInt(m_pttInvert ? false : true);
|
||||||
|
}
|
||||||
|
|
||||||
|
q15_t txLevel = 0;
|
||||||
|
switch (mode) {
|
||||||
|
case STATE_DSTAR:
|
||||||
|
txLevel = m_dstarTXLevel;
|
||||||
|
break;
|
||||||
|
case STATE_DMR:
|
||||||
|
txLevel = m_dmrTXLevel;
|
||||||
|
break;
|
||||||
|
case STATE_YSF:
|
||||||
|
txLevel = m_ysfTXLevel;
|
||||||
|
break;
|
||||||
|
case STATE_P25:
|
||||||
|
txLevel = m_p25TXLevel;
|
||||||
|
break;
|
||||||
|
case STATE_NXDN:
|
||||||
|
txLevel = m_nxdnTXLevel;
|
||||||
|
break;
|
||||||
|
case STATE_POCSAG:
|
||||||
|
txLevel = m_pocsagTXLevel;
|
||||||
|
break;
|
||||||
|
case STATE_FM:
|
||||||
|
txLevel = m_fmTXLevel;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
txLevel = m_cwIdTXLevel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0U; i < length; i++) {
|
||||||
|
q31_t res1 = samples[i] * txLevel;
|
||||||
|
q15_t res2 = q15_t(__SSAT((res1 >> 15), 16));
|
||||||
|
uint16_t res3 = uint16_t(res2 + m_txDCOffset);
|
||||||
|
|
||||||
|
// Detect DAC overflow
|
||||||
|
if (res3 > 4095U)
|
||||||
|
m_dacOverflow++;
|
||||||
|
|
||||||
|
if (control == NULL)
|
||||||
|
m_txBuffer.put(res3, MARK_NONE);
|
||||||
|
else
|
||||||
|
m_txBuffer.put(res3, control[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CIO::getSpace() const
|
||||||
|
{
|
||||||
|
return m_txBuffer.getSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDecode(bool dcd)
|
||||||
|
{
|
||||||
|
if (dcd != m_dcd)
|
||||||
|
setCOSInt(dcd ? true : false);
|
||||||
|
|
||||||
|
m_dcd = dcd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setADCDetection(bool detect)
|
||||||
|
{
|
||||||
|
m_detect = detect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setMode()
|
||||||
|
{
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
setDStarInt(m_modemState == STATE_DSTAR);
|
||||||
|
setDMRInt(m_modemState == STATE_DMR);
|
||||||
|
setYSFInt(m_modemState == STATE_YSF);
|
||||||
|
setP25Int(m_modemState == STATE_P25);
|
||||||
|
setNXDNInt(m_modemState == STATE_NXDN);
|
||||||
|
setPOCSAGInt(m_modemState == STATE_POCSAG);
|
||||||
|
setFMInt(m_modemState == STATE_FM);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset)
|
||||||
|
{
|
||||||
|
m_pttInvert = pttInvert;
|
||||||
|
|
||||||
|
m_rxLevel = q15_t(rxLevel * 128);
|
||||||
|
m_cwIdTXLevel = q15_t(cwIdTXLevel * 128);
|
||||||
|
m_dstarTXLevel = q15_t(dstarTXLevel * 128);
|
||||||
|
m_dmrTXLevel = q15_t(dmrTXLevel * 128);
|
||||||
|
m_ysfTXLevel = q15_t(ysfTXLevel * 128);
|
||||||
|
m_p25TXLevel = q15_t(p25TXLevel * 128);
|
||||||
|
m_nxdnTXLevel = q15_t(nxdnTXLevel * 128);
|
||||||
|
m_pocsagTXLevel = q15_t(pocsagTXLevel * 128);
|
||||||
|
m_fmTXLevel = q15_t(fmTXLevel * 128);
|
||||||
|
|
||||||
|
m_rxDCOffset = DC_OFFSET + rxDCOffset;
|
||||||
|
m_txDCOffset = DC_OFFSET + txDCOffset;
|
||||||
|
|
||||||
|
if (rxInvert)
|
||||||
|
m_rxLevel = -m_rxLevel;
|
||||||
|
|
||||||
|
if (txInvert) {
|
||||||
|
m_dstarTXLevel = -m_dstarTXLevel;
|
||||||
|
m_dmrTXLevel = -m_dmrTXLevel;
|
||||||
|
m_ysfTXLevel = -m_ysfTXLevel;
|
||||||
|
m_p25TXLevel = -m_p25TXLevel;
|
||||||
|
m_nxdnTXLevel = -m_nxdnTXLevel;
|
||||||
|
m_pocsagTXLevel = -m_pocsagTXLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::getOverflow(bool& adcOverflow, bool& dacOverflow)
|
||||||
|
{
|
||||||
|
adcOverflow = m_adcOverflow > 0U;
|
||||||
|
dacOverflow = m_dacOverflow > 0U;
|
||||||
|
|
||||||
|
m_adcOverflow = 0U;
|
||||||
|
m_dacOverflow = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::hasTXOverflow()
|
||||||
|
{
|
||||||
|
return m_txBuffer.hasOverflowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::hasRXOverflow()
|
||||||
|
{
|
||||||
|
return m_rxBuffer.hasOverflowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::resetWatchdog()
|
||||||
|
{
|
||||||
|
m_watchdog = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CIO::getWatchdog()
|
||||||
|
{
|
||||||
|
return m_watchdog;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::hasLockout() const
|
||||||
|
{
|
||||||
|
return m_lockout;
|
||||||
|
}
|
||||||
+27
-70
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2018,2020,2021,2024 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -21,12 +21,8 @@
|
|||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "SampleRB.h"
|
||||||
|
#include "RSSIRB.h"
|
||||||
struct TSample {
|
|
||||||
volatile uint16_t sample;
|
|
||||||
volatile uint8_t control;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CIO {
|
class CIO {
|
||||||
public:
|
public:
|
||||||
@@ -42,11 +38,11 @@ public:
|
|||||||
|
|
||||||
void setDecode(bool dcd);
|
void setDecode(bool dcd);
|
||||||
void setADCDetection(bool detect);
|
void setADCDetection(bool detect);
|
||||||
void setMode(MMDVM_STATE state);
|
void setMode();
|
||||||
|
|
||||||
void interrupt();
|
void interrupt();
|
||||||
|
|
||||||
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t m17TXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, uint8_t ax25TXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout);
|
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset);
|
||||||
|
|
||||||
void getOverflow(bool& adcOverflow, bool& dacOverflow);
|
void getOverflow(bool& adcOverflow, bool& dacOverflow);
|
||||||
|
|
||||||
@@ -61,55 +57,19 @@ public:
|
|||||||
void selfTest();
|
void selfTest();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HardwareTimer m_timer;
|
bool m_started;
|
||||||
|
|
||||||
bool m_started;
|
CSampleRB m_rxBuffer;
|
||||||
|
CSampleRB m_txBuffer;
|
||||||
|
CRSSIRB m_rssiBuffer;
|
||||||
|
|
||||||
CRingBuffer<TSample> m_rxBuffer;
|
|
||||||
CRingBuffer<TSample> m_txBuffer;
|
|
||||||
CRingBuffer<uint16_t> m_rssiBuffer;
|
|
||||||
|
|
||||||
#if defined(USE_DCBLOCKER)
|
|
||||||
arm_biquad_casd_df1_inst_q31 m_dcFilter;
|
arm_biquad_casd_df1_inst_q31 m_dcFilter;
|
||||||
q31_t m_dcState[4];
|
q31_t m_dcState[4];
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
arm_fir_instance_q15 m_gaussianFilter;
|
|
||||||
q15_t m_gaussianState[40U]; // NoTaps + BlockSize - 1, 12 + 20 - 1 plus some spare
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
arm_fir_instance_q15 m_rrc02Filter1;
|
|
||||||
q15_t m_rrc02State1[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_YSF)
|
|
||||||
arm_fir_instance_q15 m_rrc02Filter2;
|
|
||||||
q15_t m_rrc02State2[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
arm_fir_instance_q15 m_boxcar5Filter;
|
arm_fir_instance_q15 m_boxcar5Filter;
|
||||||
q15_t m_boxcar5State[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
#if defined(USE_NXDN_BOXCAR)
|
|
||||||
arm_fir_instance_q15 m_boxcar10Filter;
|
arm_fir_instance_q15 m_boxcar10Filter;
|
||||||
q15_t m_boxcar10State[40U]; // NoTaps + BlockSize - 1, 10 + 20 - 1 plus some spare
|
q15_t m_boxcar5State[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare
|
||||||
#else
|
q15_t m_boxcar10State[40U]; // NoTaps + BlockSize - 1, 10 + 20 - 1 plus some spare
|
||||||
arm_fir_instance_q15 m_nxdnFilter;
|
|
||||||
arm_fir_instance_q15 m_nxdnISincFilter;
|
|
||||||
q15_t m_nxdnState[110U]; // NoTaps + BlockSize - 1, 82 + 20 - 1 plus some spare
|
|
||||||
q15_t m_nxdnISincState[60U]; // NoTaps + BlockSize - 1, 32 + 20 - 1 plus some spare
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_M17)
|
|
||||||
arm_fir_instance_q15 m_rrc05Filter;
|
|
||||||
q15_t m_rrc05State[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool m_pttInvert;
|
bool m_pttInvert;
|
||||||
q15_t m_rxLevel;
|
q15_t m_rxLevel;
|
||||||
@@ -119,16 +79,12 @@ private:
|
|||||||
q15_t m_ysfTXLevel;
|
q15_t m_ysfTXLevel;
|
||||||
q15_t m_p25TXLevel;
|
q15_t m_p25TXLevel;
|
||||||
q15_t m_nxdnTXLevel;
|
q15_t m_nxdnTXLevel;
|
||||||
q15_t m_m17TXLevel;
|
|
||||||
q15_t m_pocsagTXLevel;
|
q15_t m_pocsagTXLevel;
|
||||||
q15_t m_fmTXLevel;
|
q15_t m_fmTXLevel;
|
||||||
q15_t m_ax25TXLevel;
|
|
||||||
|
|
||||||
uint16_t m_rxDCOffset;
|
uint16_t m_rxDCOffset;
|
||||||
uint16_t m_txDCOffset;
|
uint16_t m_txDCOffset;
|
||||||
|
|
||||||
bool m_useCOSAsLockout;
|
|
||||||
|
|
||||||
uint32_t m_ledCount;
|
uint32_t m_ledCount;
|
||||||
bool m_ledValue;
|
bool m_ledValue;
|
||||||
|
|
||||||
@@ -141,24 +97,25 @@ private:
|
|||||||
|
|
||||||
bool m_lockout;
|
bool m_lockout;
|
||||||
|
|
||||||
// Hardware access routines
|
// Hardware specific routines
|
||||||
void initHardware();
|
void initInt();
|
||||||
void startHardware();
|
void startInt();
|
||||||
|
|
||||||
bool getCOS();
|
bool getCOSInt();
|
||||||
|
|
||||||
void setLED(bool on);
|
void setLEDInt(bool on);
|
||||||
void setPTT(bool on);
|
void setPTTInt(bool on);
|
||||||
void setCOS(bool on);
|
void setCOSInt(bool on);
|
||||||
|
|
||||||
void setDStar(bool on);
|
void setDStarInt(bool on);
|
||||||
void setDMR(bool on);
|
void setDMRInt(bool on);
|
||||||
void setYSF(bool on);
|
void setYSFInt(bool on);
|
||||||
void setP25(bool on);
|
void setP25Int(bool on);
|
||||||
void setNXDN(bool on);
|
void setNXDNInt(bool on);
|
||||||
void setPOCSAG(bool on);
|
void setPOCSAGInt(bool on);
|
||||||
void setM17(bool on);
|
void setFMInt(bool on);
|
||||||
void setFM(bool on);
|
|
||||||
|
void delayInt(unsigned int dly);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,282 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
||||||
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "IO.h"
|
||||||
|
|
||||||
|
#if defined(__SAM3X8E__)
|
||||||
|
|
||||||
|
// An Arduino Due
|
||||||
|
#if defined(ARDUINO_DUE_PAPA)
|
||||||
|
#define PIN_COS 7
|
||||||
|
#define PIN_PTT 8
|
||||||
|
#define PIN_COSLED 11
|
||||||
|
#define PIN_DSTAR 16
|
||||||
|
#define PIN_DMR 17
|
||||||
|
#define PIN_YSF 18
|
||||||
|
#define PIN_P25 19
|
||||||
|
#define PIN_NXDN 20
|
||||||
|
#define PIN_POCSAG 4
|
||||||
|
#define PIN_FM 5
|
||||||
|
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
|
||||||
|
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
|
||||||
|
#define ADC_CDR_Chan 7
|
||||||
|
#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0
|
||||||
|
#define DACC_CHER_Chan DACC_CHER_CH0
|
||||||
|
#elif defined(ARDUINO_DUE_ZUM_V10)
|
||||||
|
#define PIN_COS 52
|
||||||
|
#define PIN_PTT 23
|
||||||
|
#define PIN_COSLED 22
|
||||||
|
#define PIN_DSTAR 9
|
||||||
|
#define PIN_DMR 8
|
||||||
|
#define PIN_YSF 7
|
||||||
|
#define PIN_P25 6
|
||||||
|
#define PIN_NXDN 5
|
||||||
|
#define PIN_POCSAG 4
|
||||||
|
#define PIN_FM 3
|
||||||
|
#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13)
|
||||||
|
#define ADC_ISR_EOC_Chan ADC_ISR_EOC13
|
||||||
|
#define ADC_CDR_Chan 13
|
||||||
|
#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL1 // DAC on Due DAC1
|
||||||
|
#define DACC_CHER_Chan DACC_CHER_CH1
|
||||||
|
#define RSSI_CHER_Chan (1<<1) // ADC on Due pin A6 - Due AD1 - (1 << 1)
|
||||||
|
#define RSSI_CDR_Chan 1
|
||||||
|
#elif defined(ARDUINO_DUE_NTH)
|
||||||
|
#define PIN_COS A7
|
||||||
|
#define PIN_PTT A8
|
||||||
|
#define PIN_COSLED A11
|
||||||
|
#define PIN_DSTAR 9
|
||||||
|
#define PIN_DMR 8
|
||||||
|
#define PIN_YSF 7
|
||||||
|
#define PIN_P25 6
|
||||||
|
#define PIN_NXDN 5
|
||||||
|
#define PIN_POCSAG 4
|
||||||
|
#define PIN_FM 3
|
||||||
|
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
|
||||||
|
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
|
||||||
|
#define ADC_CDR_Chan 7
|
||||||
|
#define DACC_MR_USER_SEL_Chan DACC_MR_USER_SEL_CHANNEL0 // DAC on Due DAC0
|
||||||
|
#define DACC_CHER_Chan DACC_CHER_CH0
|
||||||
|
#define RSSI_CHER_Chan (1<<1) // ADC on Due pin A6 - Due AD1 - (1 << 1)
|
||||||
|
#define RSSI_CDR_Chan 1
|
||||||
|
#else
|
||||||
|
#error "Either ARDUINO_DUE_PAPA, ARDUINO_DUE_ZUM_V10, or ARDUINO_DUE_NTH need to be defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const uint16_t DC_OFFSET = 2048U;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void ADC_Handler()
|
||||||
|
{
|
||||||
|
io.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::initInt()
|
||||||
|
{
|
||||||
|
// Set up the TX, COS and LED pins
|
||||||
|
pinMode(PIN_PTT, OUTPUT);
|
||||||
|
pinMode(PIN_COSLED, OUTPUT);
|
||||||
|
pinMode(PIN_LED, OUTPUT);
|
||||||
|
pinMode(PIN_COS, INPUT);
|
||||||
|
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
// Set up the mode output pins
|
||||||
|
pinMode(PIN_DSTAR, OUTPUT);
|
||||||
|
pinMode(PIN_DMR, OUTPUT);
|
||||||
|
pinMode(PIN_YSF, OUTPUT);
|
||||||
|
pinMode(PIN_P25, OUTPUT);
|
||||||
|
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
pinMode(PIN_NXDN, OUTPUT);
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
pinMode(PIN_POCSAG, OUTPUT);
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
pinMode(PIN_FM, OUTPUT);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::startInt()
|
||||||
|
{
|
||||||
|
if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg
|
||||||
|
io.interrupt();
|
||||||
|
|
||||||
|
// Set up the ADC
|
||||||
|
NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector
|
||||||
|
ADC->ADC_IDR = 0xFFFFFFFF; // Disable interrupts
|
||||||
|
ADC->ADC_IER = ADC_CHER_Chan; // Enable End-Of-Conv interrupt
|
||||||
|
ADC->ADC_CHDR = 0xFFFF; // Disable all channels
|
||||||
|
ADC->ADC_CHER = ADC_CHER_Chan; // Enable rx input channel
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
ADC->ADC_CHER |= RSSI_CHER_Chan; // and RSSI input
|
||||||
|
#endif
|
||||||
|
ADC->ADC_CGR = 0x15555555; // All gains set to x1
|
||||||
|
ADC->ADC_COR = 0x00000000; // All offsets off
|
||||||
|
ADC->ADC_MR = (ADC->ADC_MR & 0xFFFFFFF0) | (1 << 1) | ADC_MR_TRGEN; // 1 = trig source TIO from TC0
|
||||||
|
|
||||||
|
#if defined(EXTERNAL_OSC)
|
||||||
|
// Set up the external clock input on PA4 = AI5
|
||||||
|
REG_PIOA_ODR = 0x10; // Set pin as input
|
||||||
|
REG_PIOA_PDR = 0x10; // Disable PIO A bit 4
|
||||||
|
REG_PIOA_ABSR &= ~0x10; // Select A peripheral = TCLK1 Input
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set up the timer
|
||||||
|
pmc_enable_periph_clk(TC_INTERFACE_ID + 0*3+0) ; // Clock the TC0 channel 0
|
||||||
|
TcChannel* t = &(TC0->TC_CHANNEL)[0]; // Pointer to TC0 registers for its channel 0
|
||||||
|
t->TC_CCR = TC_CCR_CLKDIS; // Disable internal clocking while setup regs
|
||||||
|
t->TC_IDR = 0xFFFFFFFF; // Disable interrupts
|
||||||
|
t->TC_SR; // Read int status reg to clear pending
|
||||||
|
#if defined(EXTERNAL_OSC)
|
||||||
|
t->TC_CMR = TC_CMR_TCCLKS_XC1 | // Use XC1 = TCLK1 external clock
|
||||||
|
#else
|
||||||
|
t->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Use TCLK1 (prescale by 2, = 42MHz)
|
||||||
|
#endif
|
||||||
|
TC_CMR_WAVE | // Waveform mode
|
||||||
|
TC_CMR_WAVSEL_UP_RC | // Count-up PWM using RC as threshold
|
||||||
|
TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output)
|
||||||
|
TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
|
||||||
|
TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR;
|
||||||
|
#if defined(EXTERNAL_OSC)
|
||||||
|
t->TC_RC = EXTERNAL_OSC / 24000; // Counter resets on RC, so sets period in terms of the external clock
|
||||||
|
t->TC_RA = EXTERNAL_OSC / 48000; // Roughly square wave
|
||||||
|
#else
|
||||||
|
t->TC_RC = 1750; // Counter resets on RC, so sets period in terms of 42MHz internal clock
|
||||||
|
t->TC_RA = 880; // Roughly square wave
|
||||||
|
#endif
|
||||||
|
t->TC_CMR = (t->TC_CMR & 0xFFF0FFFF) | TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET; // Set clear and set from RA and RC compares
|
||||||
|
t->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; // re-enable local clocking and switch to hardware trigger source.
|
||||||
|
|
||||||
|
// Set up the DAC
|
||||||
|
pmc_enable_periph_clk(DACC_INTERFACE_ID); // Start clocking DAC
|
||||||
|
DACC->DACC_CR = DACC_CR_SWRST; // Reset DAC
|
||||||
|
DACC->DACC_MR =
|
||||||
|
DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(1) | // Trigger 1 = TIO output of TC0
|
||||||
|
DACC_MR_USER_SEL_Chan | // Select channel
|
||||||
|
(24 << DACC_MR_STARTUP_Pos); // 24 = 1536 cycles which I think is in range 23..45us since DAC clock = 42MHz
|
||||||
|
DACC->DACC_IDR = 0xFFFFFFFF; // No interrupts
|
||||||
|
DACC->DACC_CHER = DACC_CHER_Chan; // Enable channel
|
||||||
|
|
||||||
|
digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW);
|
||||||
|
digitalWrite(PIN_COSLED, LOW);
|
||||||
|
digitalWrite(PIN_LED, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::interrupt()
|
||||||
|
{
|
||||||
|
if ((ADC->ADC_ISR & ADC_ISR_EOC_Chan) == ADC_ISR_EOC_Chan) { // Ensure there was an End-of-Conversion and we read the ISR reg
|
||||||
|
uint8_t control = MARK_NONE;
|
||||||
|
uint16_t sample = DC_OFFSET;
|
||||||
|
|
||||||
|
m_txBuffer.get(sample, control);
|
||||||
|
DACC->DACC_CDR = sample;
|
||||||
|
|
||||||
|
sample = ADC->ADC_CDR[ADC_CDR_Chan];
|
||||||
|
m_rxBuffer.put(sample, control);
|
||||||
|
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
m_rssiBuffer.put(ADC->ADC_CDR[RSSI_CDR_Chan]);
|
||||||
|
#else
|
||||||
|
m_rssiBuffer.put(0U);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_watchdog++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::getCOSInt()
|
||||||
|
{
|
||||||
|
return digitalRead(PIN_COS) == HIGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setLEDInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setPTTInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_PTT, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setCOSInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_COSLED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDStarInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDMRInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_DMR, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setYSFInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_YSF, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setP25Int(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_P25, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setNXDNInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
digitalWrite(PIN_YSF, on ? HIGH : LOW);
|
||||||
|
digitalWrite(PIN_P25, on ? HIGH : LOW);
|
||||||
|
#else
|
||||||
|
digitalWrite(PIN_NXDN, on ? HIGH : LOW);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setPOCSAGInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
|
||||||
|
digitalWrite(PIN_DMR, on ? HIGH : LOW);
|
||||||
|
#else
|
||||||
|
digitalWrite(PIN_POCSAG, on ? HIGH : LOW);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setFMInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
|
||||||
|
digitalWrite(PIN_YSF, on ? HIGH : LOW);
|
||||||
|
#else
|
||||||
|
digitalWrite(PIN_FM, on ? HIGH : LOW);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::delayInt(unsigned int dly)
|
||||||
|
{
|
||||||
|
delay(dly);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019,2020 by BG5HHP
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _IO_PINS_H
|
||||||
|
#define _IO_PINS_H
|
||||||
|
|
||||||
|
#if !defined(CONFIG_H)
|
||||||
|
#error "Requires Config.h to be included first!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(STM32F4_RPT_HAT_TGO)
|
||||||
|
#include "pins/pins_f4_rpt_tgo.h"
|
||||||
|
|
||||||
|
#elif defined(STM32F4_DISCOVERY)
|
||||||
|
#include "pins/pins_f4_discovery.h"
|
||||||
|
|
||||||
|
#elif defined(STM32F4_PI)
|
||||||
|
#include "pins/pins_f4_pi.h"
|
||||||
|
|
||||||
|
#elif defined(STM32F722_PI)
|
||||||
|
#include "pins/pins_f7_pi.h"
|
||||||
|
|
||||||
|
#elif defined(STM32F4_F4M)
|
||||||
|
#include "pins/pins_f4_f4m.h"
|
||||||
|
|
||||||
|
#elif defined(STM32F722_F7M)
|
||||||
|
#include "pins/pins_f7_f7m.h"
|
||||||
|
|
||||||
|
#elif defined(STM32F722_RPT_HAT)
|
||||||
|
#include "pins/pins_f7_rpt_hat.h"
|
||||||
|
|
||||||
|
#elif defined(STM32F4_NUCLEO)
|
||||||
|
#if defined(STM32F4_NUCLEO_MORPHO_HEADER)
|
||||||
|
#include "pins/pins_f4_nucleo_morpho.h"
|
||||||
|
#elif defined(STM32F4_NUCLEO_ARDUINO_HEADER)
|
||||||
|
#include "pins/pins_f4_nucleo_arduino.h"
|
||||||
|
#else
|
||||||
|
#error "Either STM32F4_NUCLEO_MORPHO_HEADER or STM32F4_NUCLEO_ARDUINO_HEADER need to be defined"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(STM32F7_NUCLEO)
|
||||||
|
#include "pins/pins_f7_nucleo.h"
|
||||||
|
|
||||||
|
#elif defined(STM32F4_DVM)
|
||||||
|
#include "pins/pins_f4_stm32dvm_v3.h"
|
||||||
|
|
||||||
|
#elif defined(DRCC_DVM_NQF)
|
||||||
|
#include "pins/pins_f4_drcc_nqf.h"
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "A valid board type macro need to be defined."
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //#ifndef _IO_PINS_H
|
||||||
@@ -0,0 +1,512 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||||
|
* Copyright (C) 2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2019,2020 by BG5HHP
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "IO.h"
|
||||||
|
|
||||||
|
#if defined(STM32F4XX) || defined(STM32F7XX)
|
||||||
|
#include "IOPins.h"
|
||||||
|
|
||||||
|
|
||||||
|
const uint16_t DC_OFFSET = 2048U;
|
||||||
|
|
||||||
|
// Sampling frequency
|
||||||
|
#define SAMP_FREQ 24000
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void TIM2_IRQHandler() {
|
||||||
|
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
|
||||||
|
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
||||||
|
io.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::initInt()
|
||||||
|
{
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
|
GPIO_StructInit(&GPIO_InitStruct);
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed;
|
||||||
|
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
|
||||||
|
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
|
||||||
|
|
||||||
|
// PTT pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_PTT, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_PTT;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_PTT, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// COSLED pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_COSLED, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_COSLED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_COSLED, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// LED pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_LED, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_LED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_LED, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Init the input pins PIN_COS
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_COS, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_COS;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
|
||||||
|
GPIO_Init(PORT_COS, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
// DSTAR pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_DSTAR, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_DSTAR;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_DSTAR, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// DMR pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_DMR, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_DMR;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_DMR, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// YSF pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_YSF, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_YSF;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_YSF, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// P25 pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_P25, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_P25;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_P25, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
// NXDN pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_NXDN, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_NXDN;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_NXDN, &GPIO_InitStruct);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
// POCSAG pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_POCSAG, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_POCSAG;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_POCSAG, &GPIO_InitStruct);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
// FM pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_FM, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_FM;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_FM, &GPIO_InitStruct);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT))
|
||||||
|
// DSTAR mode pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_MDSTAR, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_MDSTAR;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_MDSTAR, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// DMR mode pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_MDMR, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_MDMR;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_MDMR, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// YSF mode pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_MYSF, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_MYSF;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_MYSF, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// P25 mode pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_MP25, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_MP25;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_MP25, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
// NXDN mode pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_MNXDN, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_MNXDN;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_MNXDN, &GPIO_InitStruct);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
// POCSAG mode pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_MPOCSAG, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_MPOCSAG;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_MPOCSAG, &GPIO_InitStruct);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
// FM mode pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_MFM, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_MFM;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_MFM, &GPIO_InitStruct);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::startInt()
|
||||||
|
{
|
||||||
|
if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET))
|
||||||
|
io.interrupt();
|
||||||
|
|
||||||
|
// Init the ADC
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
|
ADC_InitTypeDef ADC_InitStructure;
|
||||||
|
ADC_CommonInitTypeDef ADC_CommonInitStructure;
|
||||||
|
|
||||||
|
GPIO_StructInit(&GPIO_InitStruct);
|
||||||
|
ADC_CommonStructInit(&ADC_CommonInitStructure);
|
||||||
|
ADC_StructInit(&ADC_InitStructure);
|
||||||
|
|
||||||
|
// Enable ADC1 clock
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_RX, ENABLE);
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
|
||||||
|
// Enable ADC1 GPIO
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_RX;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
|
||||||
|
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL ;
|
||||||
|
GPIO_Init(PORT_RX, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
// Enable ADC2 clock
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_RSSI, ENABLE);
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
|
||||||
|
// Enable ADC2 GPIO
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_RSSI;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
|
||||||
|
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL ;
|
||||||
|
GPIO_Init(PORT_RSSI, &GPIO_InitStruct);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Init ADCs in dual mode (RSSI), div clock by two
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
ADC_CommonInitStructure.ADC_Mode = ADC_DualMode_RegSimult;
|
||||||
|
#else
|
||||||
|
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
|
||||||
|
#endif
|
||||||
|
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
|
||||||
|
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
|
||||||
|
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
|
||||||
|
ADC_CommonInit(&ADC_CommonInitStructure);
|
||||||
|
|
||||||
|
// Init ADC1 and ADC2: 12bit, single-conversion
|
||||||
|
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
|
||||||
|
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
|
||||||
|
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
|
||||||
|
ADC_InitStructure.ADC_ExternalTrigConvEdge = 0;
|
||||||
|
ADC_InitStructure.ADC_ExternalTrigConv = 0;
|
||||||
|
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
|
||||||
|
ADC_InitStructure.ADC_NbrOfConversion = 1;
|
||||||
|
|
||||||
|
ADC_Init(ADC1, &ADC_InitStructure);
|
||||||
|
|
||||||
|
ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE);
|
||||||
|
ADC_RegularChannelConfig(ADC1, PIN_RX_CH, 1, ADC_SampleTime_3Cycles);
|
||||||
|
|
||||||
|
// Enable ADC1
|
||||||
|
ADC_Cmd(ADC1, ENABLE);
|
||||||
|
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
ADC_Init(ADC2, &ADC_InitStructure);
|
||||||
|
|
||||||
|
ADC_EOCOnEachRegularChannelCmd(ADC2, ENABLE);
|
||||||
|
ADC_RegularChannelConfig(ADC2, PIN_RSSI_CH, 1, ADC_SampleTime_3Cycles);
|
||||||
|
|
||||||
|
// Enable ADC2
|
||||||
|
ADC_Cmd(ADC2, ENABLE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Init the DAC
|
||||||
|
DAC_InitTypeDef DAC_InitStructure;
|
||||||
|
|
||||||
|
GPIO_StructInit(&GPIO_InitStruct);
|
||||||
|
DAC_StructInit(&DAC_InitStructure);
|
||||||
|
|
||||||
|
// GPIOA clock enable
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
|
||||||
|
|
||||||
|
// DAC Periph clock enable
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
|
||||||
|
|
||||||
|
// GPIO CONFIGURATION of DAC Pin
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_TX;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AN;
|
||||||
|
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
|
||||||
|
GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
|
||||||
|
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
|
||||||
|
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
|
||||||
|
DAC_Init(PIN_TX_CH, &DAC_InitStructure);
|
||||||
|
DAC_Cmd(PIN_TX_CH, ENABLE);
|
||||||
|
|
||||||
|
// Init the timer
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||||
|
|
||||||
|
#if defined(EXTERNAL_OSC) && !(defined(STM32F4_PI) || defined(STM32F722_PI))
|
||||||
|
// Configure a GPIO as external TIM2 clock source
|
||||||
|
GPIO_PinAFConfig(PORT_EXT_CLK, SRC_EXT_CLK, GPIO_AF_TIM2);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_EXT_CLK;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
|
||||||
|
GPIO_Init(PORT_EXT_CLK, &GPIO_InitStruct);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TIM_TimeBaseInitTypeDef timerInitStructure;
|
||||||
|
TIM_TimeBaseStructInit (&timerInitStructure);
|
||||||
|
|
||||||
|
// TIM2 output frequency
|
||||||
|
#if defined(EXTERNAL_OSC) && !(defined(STM32F4_PI) || defined(STM32F722_PI))
|
||||||
|
timerInitStructure.TIM_Prescaler = (uint16_t) ((EXTERNAL_OSC/(2*SAMP_FREQ)) - 1);
|
||||||
|
timerInitStructure.TIM_Period = 1;
|
||||||
|
#else
|
||||||
|
timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(6*SAMP_FREQ)) - 1);
|
||||||
|
timerInitStructure.TIM_Period = 2;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||||
|
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||||
|
timerInitStructure.TIM_RepetitionCounter = 0;
|
||||||
|
TIM_TimeBaseInit(TIM2, &timerInitStructure);
|
||||||
|
|
||||||
|
#if defined(EXTERNAL_OSC) && !(defined(STM32F4_PI) || defined(STM32F722_PI))
|
||||||
|
// Enable external clock
|
||||||
|
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);
|
||||||
|
#else
|
||||||
|
// Enable internal clock
|
||||||
|
TIM_InternalClockConfig(TIM2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Enable TIM2
|
||||||
|
TIM_Cmd(TIM2, ENABLE);
|
||||||
|
// Enable TIM2 interrupt
|
||||||
|
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
|
||||||
|
|
||||||
|
NVIC_InitTypeDef nvicStructure;
|
||||||
|
nvicStructure.NVIC_IRQChannel = TIM2_IRQn;
|
||||||
|
nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||||
|
nvicStructure.NVIC_IRQChannelSubPriority = 1;
|
||||||
|
nvicStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||||
|
NVIC_Init(&nvicStructure);
|
||||||
|
|
||||||
|
GPIO_ResetBits(PORT_COSLED, PIN_COSLED);
|
||||||
|
GPIO_SetBits(PORT_LED, PIN_LED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::interrupt()
|
||||||
|
{
|
||||||
|
uint8_t control = MARK_NONE;
|
||||||
|
uint16_t sample = DC_OFFSET;
|
||||||
|
uint16_t rawRSSI = 0U;
|
||||||
|
|
||||||
|
m_txBuffer.get(sample, control);
|
||||||
|
|
||||||
|
// Send the value to the DAC
|
||||||
|
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
|
||||||
|
DAC_SetChannel2Data(DAC_Align_12b_R, sample);
|
||||||
|
#else
|
||||||
|
DAC_SetChannel1Data(DAC_Align_12b_R, sample);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Read value from ADC1 and ADC2
|
||||||
|
if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET)) {
|
||||||
|
// shouldn't be still in reset at this point so null the sample value?
|
||||||
|
sample = 0U;
|
||||||
|
} else {
|
||||||
|
sample = ADC_GetConversionValue(ADC1);
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
rawRSSI = ADC_GetConversionValue(ADC2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// trigger next ADC1
|
||||||
|
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
|
||||||
|
ADC_SoftwareStartConv(ADC1);
|
||||||
|
|
||||||
|
m_rxBuffer.put(sample, control);
|
||||||
|
m_rssiBuffer.put(rawRSSI);
|
||||||
|
|
||||||
|
m_watchdog++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::getCOSInt()
|
||||||
|
{
|
||||||
|
return GPIO_ReadInputDataBit(PORT_COS, PIN_COS) == Bit_SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setLEDInt(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_LED, PIN_LED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setPTTInt(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_PTT, PIN_PTT, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setCOSInt(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_COSLED, PIN_COSLED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDStarInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_DSTAR, PIN_DSTAR, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT))
|
||||||
|
GPIO_WriteBit(PORT_MDSTAR, PIN_MDSTAR, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDMRInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_DMR, PIN_DMR, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT))
|
||||||
|
GPIO_WriteBit(PORT_MDMR, PIN_MDMR, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setYSFInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_YSF, PIN_YSF, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT))
|
||||||
|
GPIO_WriteBit(PORT_MYSF, PIN_MYSF, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setP25Int(bool on)
|
||||||
|
{
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_P25, PIN_P25, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT))
|
||||||
|
GPIO_WriteBit(PORT_MP25, PIN_MP25, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setNXDNInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_YSF, PIN_YSF, on ? Bit_SET : Bit_RESET);
|
||||||
|
GPIO_WriteBit(PORT_P25, PIN_P25, on ? Bit_SET : Bit_RESET);
|
||||||
|
#else
|
||||||
|
GPIO_WriteBit(PORT_NXDN, PIN_NXDN, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT))
|
||||||
|
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_MYSF, PIN_MYSF, on ? Bit_SET : Bit_RESET);
|
||||||
|
GPIO_WriteBit(PORT_MP25, PIN_MP25, on ? Bit_SET : Bit_RESET);
|
||||||
|
#else
|
||||||
|
GPIO_WriteBit(PORT_MNXDN, PIN_MNXDN, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setPOCSAGInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_DSTAR, PIN_DSTAR, on ? Bit_SET : Bit_RESET);
|
||||||
|
GPIO_WriteBit(PORT_DMR, PIN_DMR, on ? Bit_SET : Bit_RESET);
|
||||||
|
#else
|
||||||
|
GPIO_WriteBit(PORT_POCSAG, PIN_POCSAG, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT))
|
||||||
|
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_MDSTAR, PIN_MDSTAR, on ? Bit_SET : Bit_RESET);
|
||||||
|
GPIO_WriteBit(PORT_MDMR, PIN_MDMR, on ? Bit_SET : Bit_RESET);
|
||||||
|
#else
|
||||||
|
GPIO_WriteBit(PORT_MPOCSAG, PIN_MPOCSAG, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setFMInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_DSTAR, PIN_DSTAR, on ? Bit_SET : Bit_RESET);
|
||||||
|
GPIO_WriteBit(PORT_YSF, PIN_YSF, on ? Bit_SET : Bit_RESET);
|
||||||
|
#else
|
||||||
|
GPIO_WriteBit(PORT_FM, PIN_FM, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && (defined(STM32F4_NUCLEO) || defined(STM32F722_RPT_HAT))
|
||||||
|
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
GPIO_WriteBit(PORT_MDSTAR, PIN_MDSTAR, on ? Bit_SET : Bit_RESET);
|
||||||
|
GPIO_WriteBit(PORT_MYSF, PIN_MYSF, on ? Bit_SET : Bit_RESET);
|
||||||
|
#else
|
||||||
|
GPIO_WriteBit(PORT_MFM, PIN_MFM, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple delay function for STM32
|
||||||
|
// Example from: http://thehackerworkshop.com/?p=1209
|
||||||
|
void CIO::delayInt(unsigned int dly)
|
||||||
|
{
|
||||||
|
#if defined(STM32F7XX)
|
||||||
|
unsigned int loopsPerMillisecond = (SystemCoreClock/1000);
|
||||||
|
#else
|
||||||
|
unsigned int loopsPerMillisecond = (SystemCoreClock/1000) / 3;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (; dly > 0; dly--)
|
||||||
|
{
|
||||||
|
asm volatile //this routine waits (approximately) one millisecond
|
||||||
|
(
|
||||||
|
"mov r3, %[loopsPerMillisecond] \n\t" //load the initial loop counter
|
||||||
|
"loop: \n\t"
|
||||||
|
"subs r3, #1 \n\t"
|
||||||
|
"bne loop \n\t"
|
||||||
|
|
||||||
|
: //empty output list
|
||||||
|
: [loopsPerMillisecond] "r" (loopsPerMillisecond) //input to the asm routine
|
||||||
|
: "r3", "cc" //clobber list
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+508
@@ -0,0 +1,508 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
* Copyright (C) 2016, 2017 by Andy Uribe CA6JAU
|
||||||
|
* Copyright (C) 2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "IO.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(STM32F1)
|
||||||
|
|
||||||
|
#if defined(STM32F1_POG)
|
||||||
|
/*
|
||||||
|
Pin definitions for STM32F1 POG Board:
|
||||||
|
|
||||||
|
PTT PB12 output
|
||||||
|
COSLED PB5 output
|
||||||
|
LED PB4 output
|
||||||
|
COS PB13 input/PD
|
||||||
|
|
||||||
|
DSTAR PB7 output
|
||||||
|
DMR PB6 output
|
||||||
|
YSF PB8 output
|
||||||
|
P25 PB9 output
|
||||||
|
NXDN PB10 output
|
||||||
|
POCSAG PB11 output
|
||||||
|
FM PB12 output
|
||||||
|
|
||||||
|
RX PB0 analog input (ADC1_8)
|
||||||
|
RSSI PB1 analog input (ADC2_9)
|
||||||
|
TX PA4 analog output (DAC_OUT1)
|
||||||
|
|
||||||
|
EXT_CLK PA15 input (AF: TIM2_CH1_ETR)
|
||||||
|
|
||||||
|
USART1_TXD PA9 output (AF)
|
||||||
|
USART1_RXD PA10 input (AF)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PIN_PTT 12
|
||||||
|
#define PORT_PTT GPIOB
|
||||||
|
#define BB_PTT *((bitband_t)BITBAND_PERIPH(&PORT_PTT->ODR, PIN_PTT))
|
||||||
|
#define PIN_COSLED 5
|
||||||
|
#define PORT_COSLED GPIOB
|
||||||
|
#define BB_COSLED *((bitband_t)BITBAND_PERIPH(&PORT_COSLED->ODR, PIN_COSLED))
|
||||||
|
#define PIN_LED 4
|
||||||
|
#define PORT_LED GPIOB
|
||||||
|
#define BB_LED *((bitband_t)BITBAND_PERIPH(&PORT_LED->ODR, PIN_LED))
|
||||||
|
#define PIN_COS 13
|
||||||
|
#define PORT_COS GPIOB
|
||||||
|
#define BB_COS *((bitband_t)BITBAND_PERIPH(&PORT_COS->IDR, PIN_COS))
|
||||||
|
|
||||||
|
#define PIN_DSTAR 7
|
||||||
|
#define PORT_DSTAR GPIOB
|
||||||
|
#define BB_DSTAR *((bitband_t)BITBAND_PERIPH(&PORT_DSTAR->ODR, PIN_DSTAR))
|
||||||
|
#define PIN_DMR 6
|
||||||
|
#define PORT_DMR GPIOB
|
||||||
|
#define BB_DMR *((bitband_t)BITBAND_PERIPH(&PORT_DMR->ODR, PIN_DMR))
|
||||||
|
#define PIN_YSF 8
|
||||||
|
#define PORT_YSF GPIOB
|
||||||
|
#define BB_YSF *((bitband_t)BITBAND_PERIPH(&PORT_YSF->ODR, PIN_YSF))
|
||||||
|
#define PIN_P25 9
|
||||||
|
#define PORT_P25 GPIOB
|
||||||
|
#define BB_P25 *((bitband_t)BITBAND_PERIPH(&PORT_P25->ODR, PIN_P25))
|
||||||
|
#define PIN_NXDN 10
|
||||||
|
#define PORT_NXDN GPIOB
|
||||||
|
#define BB_NXDN *((bitband_t)BITBAND_PERIPH(&PORT_NXDN->ODR, PIN_NXDN))
|
||||||
|
#define PIN_POCSAG 11
|
||||||
|
#define PORT_POCSAG GPIOB
|
||||||
|
#define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG))
|
||||||
|
#define PIN_FM 14
|
||||||
|
#define PORT_FM GPIOB
|
||||||
|
#define BB_FM *((bitband_t)BITBAND_PERIPH(&PORT_FM->ODR, PIN_FM))
|
||||||
|
|
||||||
|
#define PIN_RX 0
|
||||||
|
#define PIN_RX_ADC_CH 8
|
||||||
|
#define PORT_RX GPIOB
|
||||||
|
#define PIN_RSSI 1
|
||||||
|
#define PIN_RSSI_ADC_CH 9
|
||||||
|
#define PORT_RSSI GPIOB
|
||||||
|
#define PIN_TX 4
|
||||||
|
#define PIN_TX_DAC_CH 1
|
||||||
|
#define PORT_TX GPIOA
|
||||||
|
|
||||||
|
#define PIN_EXT_CLK 15
|
||||||
|
#define SRC_EXT_CLK 15
|
||||||
|
#define PORT_EXT_CLK GPIOA
|
||||||
|
|
||||||
|
#define PIN_USART1_TXD 9
|
||||||
|
#define PORT_USART1_TXD GPIOA
|
||||||
|
#define PIN_USART1_RXD 10
|
||||||
|
#define PORT_USART1_RXD GPIOA
|
||||||
|
|
||||||
|
#else // defined(STM32F1_POG)
|
||||||
|
#error "Either STM32F1_POG, or sth need to be defined"
|
||||||
|
#endif // defined(STM32F1_POG)
|
||||||
|
|
||||||
|
const uint16_t DC_OFFSET = 2048U;
|
||||||
|
|
||||||
|
// Sampling frequency
|
||||||
|
#define SAMP_FREQ 24000
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void TIM2_IRQHandler() {
|
||||||
|
if ((TIM2->SR & TIM_SR_UIF) == TIM_SR_UIF) {
|
||||||
|
TIM2->SR = ~TIM_SR_UIF; // clear UI flag
|
||||||
|
io.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void delay(uint32_t cnt)
|
||||||
|
{
|
||||||
|
while(cnt--)
|
||||||
|
asm("nop");
|
||||||
|
}
|
||||||
|
|
||||||
|
// source: http://www.freddiechopin.info/
|
||||||
|
void GPIOConfigPin(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value)
|
||||||
|
{
|
||||||
|
volatile uint32_t *cr_ptr;
|
||||||
|
uint32_t cr_value;
|
||||||
|
|
||||||
|
cr_ptr = &port_ptr->CRL; // configuration of pins [0,7] is in CRL
|
||||||
|
|
||||||
|
if (pin >= 8) // is pin in [8; 15]?
|
||||||
|
{ // configuration of pins [8,15] is in CRH
|
||||||
|
cr_ptr++; // advance to next struct element CRL -> CRH
|
||||||
|
pin -= 8; // crop the pin number
|
||||||
|
}
|
||||||
|
|
||||||
|
cr_value = *cr_ptr; // localize the CRL / CRH value
|
||||||
|
|
||||||
|
cr_value &= ~(0xF << (pin * 4)); // clear the MODE and CNF fields (now that pin is an analog input)
|
||||||
|
cr_value |= (mode_cnf_value << (pin * 4)); // save new MODE and CNF value for desired pin
|
||||||
|
|
||||||
|
*cr_ptr = cr_value; // save localized value to CRL / CRL
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(STM32F1_POG)
|
||||||
|
void FancyLEDEffect()
|
||||||
|
{
|
||||||
|
int ledCount = 10;
|
||||||
|
|
||||||
|
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25,
|
||||||
|
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
NULL,
|
||||||
|
#else
|
||||||
|
&BB_NXDN,
|
||||||
|
#endif
|
||||||
|
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
NULL,
|
||||||
|
#else
|
||||||
|
&BB_POCSAG,
|
||||||
|
#endif
|
||||||
|
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
NULL};
|
||||||
|
#else
|
||||||
|
&BB_FM};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i=0; i<ledCount; i++){
|
||||||
|
if(foo[i] != NULL)
|
||||||
|
*foo[i] = 0x01;
|
||||||
|
}
|
||||||
|
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1);
|
||||||
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||||
|
delay(SystemCoreClock/1000*100);
|
||||||
|
for(int i=0; i<ledCount; i++){
|
||||||
|
if(foo[i] != NULL)
|
||||||
|
*foo[i] = 0x00;
|
||||||
|
}
|
||||||
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||||
|
delay(SystemCoreClock/1000*20);
|
||||||
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||||
|
delay(SystemCoreClock/1000*10);
|
||||||
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||||
|
|
||||||
|
*foo[0] = 0x01;
|
||||||
|
for(int i=1; i<ledCount; i++){
|
||||||
|
delay(SystemCoreClock/1000*10);
|
||||||
|
if (foo[i-1] != NULL)
|
||||||
|
*foo[i-1] = 0x00;
|
||||||
|
if (foo[i] != NULL)
|
||||||
|
*foo[i] = 0x01;
|
||||||
|
}
|
||||||
|
for(int i=ledCount - 2; i>=0; i--) {
|
||||||
|
delay(SystemCoreClock/1000*10);
|
||||||
|
if (foo[i+1] != NULL)
|
||||||
|
*foo[i+1] = 0x00;
|
||||||
|
if (foo[i] != NULL)
|
||||||
|
*foo[i] = 0x01;
|
||||||
|
}
|
||||||
|
delay(SystemCoreClock/1000*10);
|
||||||
|
*foo[0] = 0x00;
|
||||||
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||||
|
delay(SystemCoreClock/1000*10);
|
||||||
|
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||||
|
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
|
||||||
|
delay(SystemCoreClock/1000*50);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void GPIOInit()
|
||||||
|
{
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN
|
||||||
|
| RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN
|
||||||
|
| RCC_APB2ENR_AFIOEN; // enable all GPIOs
|
||||||
|
|
||||||
|
// set all ports to input with pull-down
|
||||||
|
GPIOA->CRL = 0x88888888;
|
||||||
|
GPIOA->CRH = 0x88888888;
|
||||||
|
GPIOA->ODR = 0;
|
||||||
|
GPIOB->CRL = 0x88888888;
|
||||||
|
GPIOB->CRH = 0x88888888;
|
||||||
|
GPIOB->ODR = 0;
|
||||||
|
GPIOC->CRL = 0x88888888;
|
||||||
|
GPIOC->CRH = 0x88888888;
|
||||||
|
GPIOC->ODR = 0;
|
||||||
|
GPIOD->CRL = 0x88888888;
|
||||||
|
GPIOD->CRH = 0x88888888;
|
||||||
|
GPIOD->ODR = 0;
|
||||||
|
|
||||||
|
// configure ports
|
||||||
|
GPIOConfigPin(PORT_PTT, PIN_PTT, GPIO_CRL_MODE0_1);
|
||||||
|
GPIOConfigPin(PORT_COSLED, PIN_COSLED, GPIO_CRL_MODE0_1);
|
||||||
|
GPIOConfigPin(PORT_LED, PIN_LED, GPIO_CRL_MODE0_1);
|
||||||
|
GPIOConfigPin(PORT_COS, PIN_COS, GPIO_CRL_CNF0_1);
|
||||||
|
|
||||||
|
GPIOConfigPin(PORT_DSTAR, PIN_DSTAR, GPIO_CRL_MODE0_1);
|
||||||
|
GPIOConfigPin(PORT_DMR, PIN_DMR, GPIO_CRL_MODE0_1);
|
||||||
|
GPIOConfigPin(PORT_YSF, PIN_YSF, GPIO_CRL_MODE0_1);
|
||||||
|
GPIOConfigPin(PORT_P25, PIN_P25, GPIO_CRL_MODE0_1);
|
||||||
|
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
GPIOConfigPin(PORT_NXDN, PIN_NXDN, GPIO_CRL_MODE0_1);
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
GPIOConfigPin(PORT_POCSAG, PIN_POCSAG, GPIO_CRL_MODE0_1);
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
GPIOConfigPin(PORT_FM, PIN_FM, GPIO_CRL_MODE0_1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GPIOConfigPin(PORT_RX, PIN_RX, 0);
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
GPIOConfigPin(PORT_RSSI, PIN_RSSI, 0);
|
||||||
|
#endif
|
||||||
|
GPIOConfigPin(PORT_TX, PIN_TX, 0);
|
||||||
|
|
||||||
|
#if defined(EXTERNAL_OSC)
|
||||||
|
#if defined(STM32F1_POG)
|
||||||
|
GPIOConfigPin(PORT_EXT_CLK, PIN_EXT_CLK, GPIO_CRL_CNF0_0);
|
||||||
|
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_TIM2_REMAP) | AFIO_MAPR_TIM2_REMAP_0;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
|
||||||
|
GPIOConfigPin(PORT_USART1_RXD, PIN_USART1_RXD, GPIO_CRL_CNF0_0);
|
||||||
|
|
||||||
|
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_SWJ_CFG) | AFIO_MAPR_SWJ_CFG_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void ADCInit()
|
||||||
|
{
|
||||||
|
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_ADCPRE_Msk)
|
||||||
|
| RCC_CFGR_ADCPRE_DIV6; // ADC clock divided by 6 (72MHz/6 = 12MHz)
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
RCC->APB2ENR |= RCC_APB2ENR_ADC2EN;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Init ADCs in dual mode (RSSI)
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
ADC1->CR1 = ADC_CR1_DUALMOD_1|ADC_CR1_DUALMOD_2; // Regular simultaneous mode
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set sampling time to 7.5 cycles
|
||||||
|
if (PIN_RX_ADC_CH < 10) {
|
||||||
|
ADC1->SMPR2 = ADC_SMPR2_SMP0_0 << (3*PIN_RX_ADC_CH);
|
||||||
|
} else {
|
||||||
|
ADC1->SMPR1 = ADC_SMPR1_SMP10_0 << (3*PIN_RX_ADC_CH);
|
||||||
|
}
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
if (PIN_RSSI_ADC_CH < 10) {
|
||||||
|
ADC2->SMPR2 = ADC_SMPR2_SMP0_0 << (3*PIN_RSSI_ADC_CH);
|
||||||
|
} else {
|
||||||
|
ADC2->SMPR1 = ADC_SMPR1_SMP10_0 << (3*PIN_RSSI_ADC_CH);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set conversion channel (single conversion)
|
||||||
|
ADC1->SQR3 = PIN_RX_ADC_CH;
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
ADC2->SQR3 = PIN_RSSI_ADC_CH;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Enable ADC
|
||||||
|
ADC1->CR2 |= ADC_CR2_ADON;
|
||||||
|
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
// Enable ADC2
|
||||||
|
ADC2->CR2 |= ADC_CR2_ADON;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Start calibration
|
||||||
|
delay(6*2);
|
||||||
|
ADC1->CR2 |= ADC_CR2_CAL;
|
||||||
|
while((ADC1->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL)
|
||||||
|
;
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
ADC2->CR2 |= ADC_CR2_CAL;
|
||||||
|
while((ADC2->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL)
|
||||||
|
;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Trigger first conversion
|
||||||
|
ADC1->CR2 |= ADC_CR2_ADON;
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
ADC2->CR2 |= ADC_CR2_ADON;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void DACInit()
|
||||||
|
{
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
|
||||||
|
|
||||||
|
DAC->CR = DAC_CR_EN1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void TimerInit()
|
||||||
|
{
|
||||||
|
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||||
|
|
||||||
|
#if defined(EXTERNAL_OSC)
|
||||||
|
// Enable external clock, prescaler /4
|
||||||
|
TIM2->SMCR = TIM_SMCR_ECE | TIM_SMCR_ETPS_1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TIM2 output frequency
|
||||||
|
TIM2->PSC = 0;
|
||||||
|
#if defined(EXTERNAL_OSC)
|
||||||
|
// TimerCount = ExternalOsc
|
||||||
|
// /4 (external clock prescaler)
|
||||||
|
// /SAMP_FREQ
|
||||||
|
TIM2->ARR = (uint16_t) ((EXTERNAL_OSC/(4*SAMP_FREQ)) - 1);
|
||||||
|
#else
|
||||||
|
TIM2->ARR = (uint16_t) ((SystemCoreClock/(SAMP_FREQ)) - 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Enable TIse 1%-tolerance comM2 interrupt
|
||||||
|
TIM2->DIER = TIM_DIER_UIE;
|
||||||
|
NVIC_EnableIRQ(TIM2_IRQn);
|
||||||
|
|
||||||
|
// Enable TIM2
|
||||||
|
TIM2->CR1 |= TIM_CR1_CEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CIO::initInt()
|
||||||
|
{
|
||||||
|
GPIOInit();
|
||||||
|
ADCInit();
|
||||||
|
DACInit();
|
||||||
|
#if defined(STM32F1_POG)
|
||||||
|
FancyLEDEffect();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::startInt()
|
||||||
|
{
|
||||||
|
TimerInit();
|
||||||
|
|
||||||
|
BB_COSLED = 0;
|
||||||
|
BB_LED = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::interrupt()
|
||||||
|
{
|
||||||
|
uint8_t control = MARK_NONE;
|
||||||
|
uint16_t sample = DC_OFFSET;
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
uint16_t rawRSSI = 0U;
|
||||||
|
#endif
|
||||||
|
bitband_t eoc = (bitband_t)BITBAND_PERIPH(&ADC1->SR, ADC_SR_EOS_Pos);
|
||||||
|
bitband_t adon = (bitband_t)BITBAND_PERIPH(&ADC1->CR2, ADC_CR2_ADON_Pos);
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
bitband_t rssi_adon = (bitband_t)BITBAND_PERIPH(&ADC2->CR2, ADC_CR2_ADON_Pos);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (*eoc) {
|
||||||
|
// trigger next conversion
|
||||||
|
*adon = 1;
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
*rssi_adon = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_txBuffer.get(sample, control);
|
||||||
|
DAC->DHR12R1 = sample; // Send the value to the DAC
|
||||||
|
|
||||||
|
// Read value from ADC1 and ADC2
|
||||||
|
sample = ADC1->DR; // read conversion result; EOC is cleared by this read
|
||||||
|
m_rxBuffer.put(sample, control);
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
rawRSSI = ADC2->DR;
|
||||||
|
m_rssiBuffer.put(rawRSSI);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_watchdog++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::getCOSInt()
|
||||||
|
{
|
||||||
|
return BB_COS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setLEDInt(bool on)
|
||||||
|
{
|
||||||
|
BB_LED = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setPTTInt(bool on)
|
||||||
|
{
|
||||||
|
BB_PTT = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setCOSInt(bool on)
|
||||||
|
{
|
||||||
|
BB_COSLED = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDStarInt(bool on)
|
||||||
|
{
|
||||||
|
BB_DSTAR = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDMRInt(bool on)
|
||||||
|
{
|
||||||
|
BB_DMR = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setYSFInt(bool on)
|
||||||
|
{
|
||||||
|
BB_YSF = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setP25Int(bool on)
|
||||||
|
{
|
||||||
|
BB_P25 = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setNXDNInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
BB_YSF = !!on;
|
||||||
|
BB_P25 = !!on;
|
||||||
|
#else
|
||||||
|
BB_NXDN = !!on;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setPOCSAGInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
BB_DSTAR = !!on;
|
||||||
|
BB_DMR = !!on;
|
||||||
|
#else
|
||||||
|
BB_POCSAG = !!on;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setFMInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
BB_DSTAR = !!on;
|
||||||
|
BB_YSF = !!on;
|
||||||
|
#else
|
||||||
|
BB_FM = !!on;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::delayInt(unsigned int dly)
|
||||||
|
{
|
||||||
|
delay(dly);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+266
@@ -0,0 +1,266 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "IO.h"
|
||||||
|
|
||||||
|
#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||||
|
|
||||||
|
#if defined(EXTERNAL_OSC)
|
||||||
|
#define PIN_LED 3
|
||||||
|
#else
|
||||||
|
#define PIN_LED 13
|
||||||
|
#endif
|
||||||
|
#define PIN_COS 4
|
||||||
|
#define PIN_PTT 5
|
||||||
|
#define PIN_COSLED 6
|
||||||
|
#define PIN_DSTAR 9
|
||||||
|
#define PIN_DMR 10
|
||||||
|
#define PIN_YSF 11
|
||||||
|
#define PIN_P25 12
|
||||||
|
#if defined(__MK20DX256__)
|
||||||
|
#define PIN_NXDN 2
|
||||||
|
#define PIN_POCSAG 3
|
||||||
|
#define PIN_FM 4
|
||||||
|
#else
|
||||||
|
#define PIN_NXDN 24
|
||||||
|
#define PIN_POCSAG 25
|
||||||
|
#define PIN_FM 26
|
||||||
|
#endif
|
||||||
|
#define PIN_ADC 5 // A0, Pin 14
|
||||||
|
#define PIN_RSSI 4 // Teensy 3.5/3.6, A16, Pin 35. Teensy 3.1/3.2, A17, Pin 28
|
||||||
|
|
||||||
|
#define PDB_CHnC1_TOS 0x0100
|
||||||
|
#define PDB_CHnC1_EN 0x0001
|
||||||
|
|
||||||
|
const uint16_t DC_OFFSET = 2048U;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void adc0_isr()
|
||||||
|
{
|
||||||
|
io.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::initInt()
|
||||||
|
{
|
||||||
|
// Set up the TX, COS and LED pins
|
||||||
|
pinMode(PIN_PTT, OUTPUT);
|
||||||
|
pinMode(PIN_COSLED, OUTPUT);
|
||||||
|
pinMode(PIN_LED, OUTPUT);
|
||||||
|
pinMode(PIN_COS, INPUT);
|
||||||
|
|
||||||
|
#if defined(MODE_LEDS)
|
||||||
|
// Set up the mode output pins
|
||||||
|
pinMode(PIN_DSTAR, OUTPUT);
|
||||||
|
pinMode(PIN_DMR, OUTPUT);
|
||||||
|
pinMode(PIN_YSF, OUTPUT);
|
||||||
|
pinMode(PIN_P25, OUTPUT);
|
||||||
|
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
pinMode(PIN_NXDN, OUTPUT);
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
pinMode(PIN_POCSAG, OUTPUT);
|
||||||
|
#endif
|
||||||
|
#if !defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
pinMode(PIN_FM, OUTPUT);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::startInt()
|
||||||
|
{
|
||||||
|
// Initialise the DAC
|
||||||
|
SIM_SCGC2 |= SIM_SCGC2_DAC0;
|
||||||
|
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
|
||||||
|
|
||||||
|
// Initialise ADC0
|
||||||
|
SIM_SCGC6 |= SIM_SCGC6_ADC0;
|
||||||
|
ADC0_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time
|
||||||
|
ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP;
|
||||||
|
ADC0_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb
|
||||||
|
ADC0_SC2 = ADC_SC2_REFSEL(0) | ADC_SC2_ADTRG; // Voltage ref external, hardware trigger
|
||||||
|
ADC0_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples
|
||||||
|
|
||||||
|
ADC0_SC3 |= ADC_SC3_CAL;
|
||||||
|
while (ADC0_SC3 & ADC_SC3_CAL) // Wait for calibration
|
||||||
|
;
|
||||||
|
|
||||||
|
uint16_t sum0 = ADC0_CLPS + ADC0_CLP4 + ADC0_CLP3 + // Plus side gain
|
||||||
|
ADC0_CLP2 + ADC0_CLP1 + ADC0_CLP0;
|
||||||
|
sum0 = (sum0 / 2U) | 0x8000U;
|
||||||
|
ADC0_PG = sum0;
|
||||||
|
|
||||||
|
ADC0_SC1A = ADC_SC1_AIEN | PIN_ADC; // Enable ADC interrupt, use A0
|
||||||
|
NVIC_ENABLE_IRQ(IRQ_ADC0);
|
||||||
|
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
// Initialise ADC1
|
||||||
|
SIM_SCGC3 |= SIM_SCGC3_ADC1;
|
||||||
|
ADC1_CFG1 = ADC_CFG1_ADIV(1) | ADC_CFG1_ADICLK(1) | // Single-ended 12 bits, long sample time
|
||||||
|
ADC_CFG1_MODE(1) | ADC_CFG1_ADLSMP;
|
||||||
|
ADC1_CFG2 = ADC_CFG2_MUXSEL | ADC_CFG2_ADLSTS(2); // Select channels ADxxxb
|
||||||
|
ADC1_SC2 = ADC_SC2_REFSEL(0); // Voltage ref external, software trigger
|
||||||
|
ADC1_SC3 = ADC_SC3_AVGE | ADC_SC3_AVGS(0); // Enable averaging, 4 samples
|
||||||
|
|
||||||
|
ADC1_SC3 |= ADC_SC3_CAL;
|
||||||
|
while (ADC1_SC3 & ADC_SC3_CAL) // Wait for calibration
|
||||||
|
;
|
||||||
|
|
||||||
|
uint16_t sum1 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + // Plus side gain
|
||||||
|
ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
|
||||||
|
sum1 = (sum1 / 2U) | 0x8000U;
|
||||||
|
ADC1_PG = sum1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(EXTERNAL_OSC)
|
||||||
|
// Set ADC0 to trigger from the LPTMR at 24 kHz
|
||||||
|
SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN | // Enable ADC0 alternate trigger
|
||||||
|
SIM_SOPT7_ADC0TRGSEL(14); // Trigger ADC0 by LPTMR0
|
||||||
|
|
||||||
|
CORE_PIN13_CONFIG = PORT_PCR_MUX(3);
|
||||||
|
|
||||||
|
SIM_SCGC5 |= SIM_SCGC5_LPTIMER; // Enable Low Power Timer Access
|
||||||
|
LPTMR0_CSR = 0; // Disable
|
||||||
|
LPTMR0_PSR = LPTMR_PSR_PBYP; // Bypass prescaler/filter
|
||||||
|
LPTMR0_CMR = (EXTERNAL_OSC / 24000) - 1; // Frequency divided by CMR + 1
|
||||||
|
LPTMR0_CSR = LPTMR_CSR_TPS(2) | // Pin: 0=CMP0, 1=xtal, 2=pin13
|
||||||
|
LPTMR_CSR_TMS; // Mode Select, 0=timer, 1=counter
|
||||||
|
LPTMR0_CSR |= LPTMR_CSR_TEN; // Enable
|
||||||
|
#else
|
||||||
|
// Setup PDB for ADC0 at 24 kHz
|
||||||
|
SIM_SCGC6 |= SIM_SCGC6_PDB; // Enable PDB clock
|
||||||
|
PDB0_MOD = (F_BUS / 24000) - 1; // Timer period - 1
|
||||||
|
PDB0_IDLY = 0; // Interrupt delay
|
||||||
|
PDB0_CH0C1 = PDB_CHnC1_TOS | PDB_CHnC1_EN; // Enable pre-trigger for ADC0
|
||||||
|
PDB0_SC = PDB_SC_TRGSEL(15) | PDB_SC_PDBEN | // SW trigger, enable interrupts, continuous mode
|
||||||
|
PDB_SC_PDBIE | PDB_SC_CONT | PDB_SC_LDOK; // No prescaling
|
||||||
|
PDB0_SC |= PDB_SC_SWTRIG; // Software trigger (reset and restart counter)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
digitalWrite(PIN_PTT, m_pttInvert ? HIGH : LOW);
|
||||||
|
digitalWrite(PIN_COSLED, LOW);
|
||||||
|
digitalWrite(PIN_LED, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::interrupt()
|
||||||
|
{
|
||||||
|
uint8_t control = MARK_NONE;
|
||||||
|
uint16_t sample = DC_OFFSET;
|
||||||
|
|
||||||
|
m_txBuffer.get(sample, control);
|
||||||
|
*(int16_t *)&(DAC0_DAT0L) = sample;
|
||||||
|
|
||||||
|
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
|
||||||
|
sample = ADC0_RA;
|
||||||
|
m_rxBuffer.put(sample, control);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
|
||||||
|
uint16_t rssi = ADC1_RA;
|
||||||
|
m_rssiBuffer.put(rssi);
|
||||||
|
} else {
|
||||||
|
m_rssiBuffer.put(0U);
|
||||||
|
}
|
||||||
|
|
||||||
|
ADC1_SC1A = PIN_RSSI; // Start the next RSSI conversion
|
||||||
|
#else
|
||||||
|
m_rssiBuffer.put(0U);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_watchdog++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::getCOSInt()
|
||||||
|
{
|
||||||
|
return digitalRead(PIN_COS) == HIGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setLEDInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setPTTInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_PTT, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setCOSInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_COSLED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDStarInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDMRInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_DMR, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setYSFInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_YSF, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setP25Int(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_P25, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setNXDNInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||||
|
digitalWrite(PIN_YSF, on ? HIGH : LOW);
|
||||||
|
digitalWrite(PIN_P25, on ? HIGH : LOW);
|
||||||
|
#else
|
||||||
|
digitalWrite(PIN_NXDN, on ? HIGH : LOW);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setPOCSAGInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||||
|
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
|
||||||
|
digitalWrite(PIN_DMR, on ? HIGH : LOW);
|
||||||
|
#else
|
||||||
|
digitalWrite(PIN_POCSAG, on ? HIGH : LOW);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setFMInt(bool on)
|
||||||
|
{
|
||||||
|
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||||
|
digitalWrite(PIN_DSTAR, on ? HIGH : LOW);
|
||||||
|
digitalWrite(PIN_YSF, on ? HIGH : LOW);
|
||||||
|
#else
|
||||||
|
digitalWrite(PIN_FM, on ? HIGH : LOW);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::delayInt(unsigned int dly)
|
||||||
|
{
|
||||||
|
delay(dly);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
|
||||||
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32F105xC)
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
MMDVM_STATE m_modemState = STATE_IDLE;
|
||||||
|
|
||||||
|
bool m_dstarEnable = true;
|
||||||
|
bool m_dmrEnable = true;
|
||||||
|
bool m_ysfEnable = true;
|
||||||
|
bool m_p25Enable = true;
|
||||||
|
bool m_nxdnEnable = true;
|
||||||
|
bool m_pocsagEnable = true;
|
||||||
|
bool m_fmEnable = true;
|
||||||
|
|
||||||
|
bool m_duplex = true;
|
||||||
|
|
||||||
|
bool m_tx = false;
|
||||||
|
bool m_dcd = false;
|
||||||
|
|
||||||
|
CDStarRX dstarRX;
|
||||||
|
CDStarTX dstarTX;
|
||||||
|
|
||||||
|
CDMRIdleRX dmrIdleRX;
|
||||||
|
CDMRRX dmrRX;
|
||||||
|
CDMRTX dmrTX;
|
||||||
|
|
||||||
|
CDMRDMORX dmrDMORX;
|
||||||
|
CDMRDMOTX dmrDMOTX;
|
||||||
|
|
||||||
|
CYSFRX ysfRX;
|
||||||
|
CYSFTX ysfTX;
|
||||||
|
|
||||||
|
CP25RX p25RX;
|
||||||
|
CP25TX p25TX;
|
||||||
|
|
||||||
|
CNXDNRX nxdnRX;
|
||||||
|
CNXDNTX nxdnTX;
|
||||||
|
|
||||||
|
CPOCSAGTX pocsagTX;
|
||||||
|
|
||||||
|
CFM fm;
|
||||||
|
|
||||||
|
CCalDStarRX calDStarRX;
|
||||||
|
CCalDStarTX calDStarTX;
|
||||||
|
CCalDMR calDMR;
|
||||||
|
CCalP25 calP25;
|
||||||
|
CCalNXDN calNXDN;
|
||||||
|
CCalFM calFM;
|
||||||
|
CCalPOCSAG calPOCSAG;
|
||||||
|
CCalRSSI calRSSI;
|
||||||
|
|
||||||
|
CCWIdTX cwIdTX;
|
||||||
|
|
||||||
|
CSerialPort serial;
|
||||||
|
CIO io;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
serial.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
serial.process();
|
||||||
|
|
||||||
|
io.process();
|
||||||
|
|
||||||
|
// The following is for transmitting
|
||||||
|
if (m_dstarEnable && m_modemState == STATE_DSTAR)
|
||||||
|
dstarTX.process();
|
||||||
|
|
||||||
|
if (m_dmrEnable && m_modemState == STATE_DMR) {
|
||||||
|
if (m_duplex)
|
||||||
|
dmrTX.process();
|
||||||
|
else
|
||||||
|
dmrDMOTX.process();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ysfEnable && m_modemState == STATE_YSF)
|
||||||
|
ysfTX.process();
|
||||||
|
|
||||||
|
if (m_p25Enable && m_modemState == STATE_P25)
|
||||||
|
p25TX.process();
|
||||||
|
|
||||||
|
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||||
|
nxdnTX.process();
|
||||||
|
|
||||||
|
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
|
||||||
|
pocsagTX.process();
|
||||||
|
|
||||||
|
if (m_fmEnable && m_modemState == STATE_FM)
|
||||||
|
fm.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_DSTARCAL)
|
||||||
|
calDStarTX.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
||||||
|
calDMR.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_P25CAL1K)
|
||||||
|
calP25.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_NXDNCAL1K)
|
||||||
|
calNXDN.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_POCSAGCAL)
|
||||||
|
calPOCSAG.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K ||m_modemState == STATE_FMCAL30K)
|
||||||
|
calFM.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
cwIdTX.process();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
setup();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+29
-103
@@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
|
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -29,77 +28,45 @@ bool m_dmrEnable = true;
|
|||||||
bool m_ysfEnable = true;
|
bool m_ysfEnable = true;
|
||||||
bool m_p25Enable = true;
|
bool m_p25Enable = true;
|
||||||
bool m_nxdnEnable = true;
|
bool m_nxdnEnable = true;
|
||||||
bool m_m17Enable = true;
|
|
||||||
bool m_pocsagEnable = true;
|
bool m_pocsagEnable = true;
|
||||||
bool m_fmEnable = true;
|
bool m_fmEnable = true;
|
||||||
bool m_ax25Enable = true;
|
|
||||||
|
|
||||||
bool m_duplex = true;
|
bool m_duplex = true;
|
||||||
|
|
||||||
bool m_tx = false;
|
bool m_tx = false;
|
||||||
bool m_dcd = false;
|
bool m_dcd = false;
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
CDStarRX dstarRX;
|
||||||
CDStarRX dstarRX;
|
CDStarTX dstarTX;
|
||||||
CDStarTX dstarTX;
|
|
||||||
|
CDMRIdleRX dmrIdleRX;
|
||||||
|
CDMRRX dmrRX;
|
||||||
|
CDMRTX dmrTX;
|
||||||
|
|
||||||
|
CDMRDMORX dmrDMORX;
|
||||||
|
CDMRDMOTX dmrDMOTX;
|
||||||
|
|
||||||
|
CYSFRX ysfRX;
|
||||||
|
CYSFTX ysfTX;
|
||||||
|
|
||||||
|
CP25RX p25RX;
|
||||||
|
CP25TX p25TX;
|
||||||
|
|
||||||
|
CNXDNRX nxdnRX;
|
||||||
|
CNXDNTX nxdnTX;
|
||||||
|
|
||||||
|
CPOCSAGTX pocsagTX;
|
||||||
|
|
||||||
|
CFM fm;
|
||||||
|
|
||||||
CCalDStarRX calDStarRX;
|
CCalDStarRX calDStarRX;
|
||||||
CCalDStarTX calDStarTX;
|
CCalDStarTX calDStarTX;
|
||||||
#endif
|
CCalDMR calDMR;
|
||||||
|
CCalFM calFM;
|
||||||
#if defined(MODE_DMR)
|
CCalP25 calP25;
|
||||||
CDMRIdleRX dmrIdleRX;
|
CCalNXDN calNXDN;
|
||||||
CDMRRX dmrRX;
|
CCalPOCSAG calPOCSAG;
|
||||||
CDMRTX dmrTX;
|
CCalRSSI calRSSI;
|
||||||
|
|
||||||
CDMRDMORX dmrDMORX;
|
|
||||||
CDMRDMOTX dmrDMOTX;
|
|
||||||
|
|
||||||
CCalDMR calDMR;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_YSF)
|
|
||||||
CYSFRX ysfRX;
|
|
||||||
CYSFTX ysfTX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
CP25RX p25RX;
|
|
||||||
CP25TX p25TX;
|
|
||||||
|
|
||||||
CCalP25 calP25;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
CNXDNRX nxdnRX;
|
|
||||||
CNXDNTX nxdnTX;
|
|
||||||
|
|
||||||
CCalNXDN calNXDN;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_M17)
|
|
||||||
CM17RX m17RX;
|
|
||||||
CM17TX m17TX;
|
|
||||||
|
|
||||||
CCalM17 calM17;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_POCSAG)
|
|
||||||
CPOCSAGTX pocsagTX;
|
|
||||||
CCalPOCSAG calPOCSAG;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
CFM fm;
|
|
||||||
CCalFM calFM;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_AX25)
|
|
||||||
CAX25RX ax25RX;
|
|
||||||
CAX25TX ax25TX;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CCalRSSI calRSSI;
|
|
||||||
|
|
||||||
CCWIdTX cwIdTX;
|
CCWIdTX cwIdTX;
|
||||||
|
|
||||||
@@ -118,89 +85,48 @@ void loop()
|
|||||||
io.process();
|
io.process();
|
||||||
|
|
||||||
// The following is for transmitting
|
// The following is for transmitting
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
if (m_dstarEnable && m_modemState == STATE_DSTAR)
|
if (m_dstarEnable && m_modemState == STATE_DSTAR)
|
||||||
dstarTX.process();
|
dstarTX.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
if (m_dmrEnable && m_modemState == STATE_DMR) {
|
if (m_dmrEnable && m_modemState == STATE_DMR) {
|
||||||
if (m_duplex)
|
if (m_duplex)
|
||||||
dmrTX.process();
|
dmrTX.process();
|
||||||
else
|
else
|
||||||
dmrDMOTX.process();
|
dmrDMOTX.process();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_YSF)
|
|
||||||
if (m_ysfEnable && m_modemState == STATE_YSF)
|
if (m_ysfEnable && m_modemState == STATE_YSF)
|
||||||
ysfTX.process();
|
ysfTX.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
if (m_p25Enable && m_modemState == STATE_P25)
|
if (m_p25Enable && m_modemState == STATE_P25)
|
||||||
p25TX.process();
|
p25TX.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||||
nxdnTX.process();
|
nxdnTX.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_M17)
|
|
||||||
if (m_m17Enable && m_modemState == STATE_M17)
|
|
||||||
m17TX.process();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_POCSAG)
|
|
||||||
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
|
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
|
||||||
pocsagTX.process();
|
pocsagTX.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_AX25)
|
|
||||||
if (m_ax25Enable && (m_modemState == STATE_IDLE || m_modemState == STATE_FM))
|
|
||||||
ax25TX.process();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
if (m_fmEnable && m_modemState == STATE_FM)
|
if (m_fmEnable && m_modemState == STATE_FM)
|
||||||
fm.process();
|
fm.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_DSTAR)
|
|
||||||
if (m_modemState == STATE_DSTARCAL)
|
if (m_modemState == STATE_DSTARCAL)
|
||||||
calDStarTX.process();
|
calDStarTX.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_DMR)
|
|
||||||
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
||||||
calDMR.process();
|
calDMR.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_FM)
|
|
||||||
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K || m_modemState == STATE_FMCAL30K)
|
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K || m_modemState == STATE_FMCAL30K)
|
||||||
calFM.process();
|
calFM.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
if (m_modemState == STATE_P25CAL1K)
|
if (m_modemState == STATE_P25CAL1K)
|
||||||
calP25.process();
|
calP25.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
if (m_modemState == STATE_NXDNCAL1K)
|
if (m_modemState == STATE_NXDNCAL1K)
|
||||||
calNXDN.process();
|
calNXDN.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_M17)
|
|
||||||
if (m_modemState == STATE_M17CAL)
|
|
||||||
calM17.process();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MODE_POCSAG)
|
|
||||||
if (m_modemState == STATE_POCSAGCAL)
|
if (m_modemState == STATE_POCSAGCAL)
|
||||||
calPOCSAG.process();
|
calPOCSAG.process();
|
||||||
#endif
|
|
||||||
|
|
||||||
if (m_modemState == STATE_IDLE)
|
if (m_modemState == STATE_IDLE)
|
||||||
cwIdTX.process();
|
cwIdTX.process();
|
||||||
Binary file not shown.
@@ -0,0 +1,383 @@
|
|||||||
|
# Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||||
|
# Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# MMDVM source files
|
||||||
|
MMDVM_PATH=.
|
||||||
|
|
||||||
|
# STM32 library paths
|
||||||
|
F4_LIB_PATH=./STM32F4XX_Lib
|
||||||
|
F7_LIB_PATH=./STM32F7XX_Lib
|
||||||
|
|
||||||
|
# MCU external clock frequency (Hz)
|
||||||
|
CLK_MMDVM_PI=12000000
|
||||||
|
CLK_NUCLEO=8000000
|
||||||
|
CLK_12MHZ=12000000
|
||||||
|
|
||||||
|
# Directory Structure
|
||||||
|
BINDIR=bin
|
||||||
|
OBJDIR_F4=obj_f4
|
||||||
|
OBJDIR_F7=obj_f7
|
||||||
|
|
||||||
|
# Output files
|
||||||
|
BINELF_F4=mmdvm_f4.elf
|
||||||
|
BINHEX_F4=mmdvm_f4.hex
|
||||||
|
BINBIN_F4=mmdvm_f4.bin
|
||||||
|
BINELF_F7=mmdvm_f7.elf
|
||||||
|
BINHEX_F7=mmdvm_f7.hex
|
||||||
|
BINBIN_F7=mmdvm_f7.bin
|
||||||
|
|
||||||
|
# Header directories
|
||||||
|
INC_F4= . $(F4_LIB_PATH)/CMSIS/Include/ $(F4_LIB_PATH)/Device/ $(F4_LIB_PATH)/STM32F4xx_StdPeriph_Driver/include/
|
||||||
|
INCLUDES_F4=$(INC_F4:%=-I%)
|
||||||
|
INC_F7= . $(F7_LIB_PATH)/CMSIS/Include/ $(F7_LIB_PATH)/Device/ $(F7_LIB_PATH)/STM32F7xx_StdPeriph_Driver/inc/
|
||||||
|
INCLUDES_F7=$(INC_F7:%=-I%)
|
||||||
|
|
||||||
|
# CMSIS libraries
|
||||||
|
INCLUDES_LIBS_F4=$(F4_LIB_PATH)/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a
|
||||||
|
INCLUDES_LIBS_F7=$(F7_LIB_PATH)/CMSIS/Lib/GCC/libarm_cortexM7lfsp_math.a
|
||||||
|
|
||||||
|
# STM32F4 Standard Peripheral Libraries source path
|
||||||
|
STD_LIB_F4=$(F4_LIB_PATH)/STM32F4xx_StdPeriph_Driver/source
|
||||||
|
|
||||||
|
# STM32F7 Standard Peripheral Libraries source path
|
||||||
|
STD_LIB_F7=$(F7_LIB_PATH)/STM32F7xx_StdPeriph_Driver/src
|
||||||
|
|
||||||
|
# STM32F4 system source path
|
||||||
|
SYS_DIR_F4=$(F4_LIB_PATH)/Device
|
||||||
|
STARTUP_DIR_F4=$(F4_LIB_PATH)/Device/startup
|
||||||
|
|
||||||
|
# STM32F7 system source path
|
||||||
|
SYS_DIR_F7=$(F7_LIB_PATH)/Device
|
||||||
|
STARTUP_DIR_F7=$(F7_LIB_PATH)/Device/startup
|
||||||
|
|
||||||
|
# GNU ARM Embedded Toolchain
|
||||||
|
CC=arm-none-eabi-gcc
|
||||||
|
CXX=arm-none-eabi-g++
|
||||||
|
LD=arm-none-eabi-ld
|
||||||
|
AR=arm-none-eabi-ar
|
||||||
|
AS=arm-none-eabi-as
|
||||||
|
CP=arm-none-eabi-objcopy
|
||||||
|
OD=arm-none-eabi-objdump
|
||||||
|
NM=arm-none-eabi-nm
|
||||||
|
SIZE=arm-none-eabi-size
|
||||||
|
A2L=arm-none-eabi-addr2line
|
||||||
|
|
||||||
|
# "SystemRoot" is only defined in Windows
|
||||||
|
ifdef SYSTEMROOT
|
||||||
|
CLEANCMD=del /S *.o *.hex *.bin *.elf GitVersion.h
|
||||||
|
MDDIRS=md $@
|
||||||
|
else ifdef SystemRoot
|
||||||
|
CLEANCMD=del /S *.o *.hex *.bin *.elf GitVersion.h
|
||||||
|
MDDIRS=md $@
|
||||||
|
else
|
||||||
|
CLEANCMD=rm -f $(OBJ_F4) $(OBJ_F7) $(BINDIR)/*.hex $(BINDIR)/*.bin $(BINDIR)/*.elf GitVersion.h
|
||||||
|
MDDIRS=mkdir $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Default reference oscillator frequencies
|
||||||
|
ifndef $(OSC)
|
||||||
|
ifeq ($(MAKECMDGOALS),pi)
|
||||||
|
OSC=$(CLK_MMDVM_PI)
|
||||||
|
else ifeq ($(MAKECMDGOALS),pi-f722)
|
||||||
|
OSC=$(CLK_MMDVM_PI)
|
||||||
|
else ifeq ($(MAKECMDGOALS),drcc_nqf)
|
||||||
|
OSC=$(CLK_12MHZ)
|
||||||
|
else
|
||||||
|
OSC=$(CLK_NUCLEO)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Build object lists
|
||||||
|
CXXSRC=$(wildcard $(MMDVM_PATH)/*.cpp)
|
||||||
|
CSRC_STD_F4=$(wildcard $(STD_LIB_F4)/*.c)
|
||||||
|
SYS_F4=$(wildcard $(SYS_DIR_F4)/*.c)
|
||||||
|
STARTUP_F4=$(wildcard $(STARTUP_DIR_F4)/*.c)
|
||||||
|
CSRC_STD_F7=$(wildcard $(STD_LIB_F7)/*.c)
|
||||||
|
SYS_F7=$(wildcard $(SYS_DIR_F7)/*.c)
|
||||||
|
STARTUP_F7=$(wildcard $(STARTUP_DIR_F7)/*.c)
|
||||||
|
OBJ_F4=$(CXXSRC:$(MMDVM_PATH)/%.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)
|
||||||
|
OBJ_F7=$(CXXSRC:$(MMDVM_PATH)/%.cpp=$(OBJDIR_F7)/%.o) $(CSRC_STD_F7:$(STD_LIB_F7)/%.c=$(OBJDIR_F7)/%.o) $(SYS_F7:$(SYS_DIR_F7)/%.c=$(OBJDIR_F7)/%.o) $(STARTUP_F7:$(STARTUP_DIR_F7)/%.c=$(OBJDIR_F7)/%.o)
|
||||||
|
|
||||||
|
# MCU flags
|
||||||
|
MCFLAGS_F4=-mcpu=cortex-m4 -mthumb -mlittle-endian -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb-interwork
|
||||||
|
MCFLAGS_F7=-mcpu=cortex-m7 -mthumb -mlittle-endian -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb-interwork
|
||||||
|
|
||||||
|
# Compile flags
|
||||||
|
# STM32F4 Discovery board:
|
||||||
|
DEFS_DIS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_DISCOVERY -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# MMDVM-Pi board:
|
||||||
|
DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# MMDVM-F4M F0DEI board:
|
||||||
|
DEFS_F4M=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_F4M -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# STM32F4 Nucleo-64 F446RE board:
|
||||||
|
DEFS_NUCLEO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_NUCLEO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# STM32F7 Nucleo-144 F767ZI board:
|
||||||
|
DEFS_NUCLEO_F767=-DUSE_HAL_DRIVER -DSTM32F767xx -DSTM32F7XX -DSTM32F7_NUCLEO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# MMDVM-Pi F722 board:
|
||||||
|
DEFS_PI_F722=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_PI -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# MMDVM-F7M F0DEI board:
|
||||||
|
DEFS_F7M=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_F7M -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# MMDVM_RPT_Hat F0DEI, DB9MAT, DF2ET board:
|
||||||
|
DEFS_RPT_HAT=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_RPT_HAT -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# STM32F4 DVM board:
|
||||||
|
DEFS_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# MMDVM_RPT_Hat BG4TGO, BG5HHP board:
|
||||||
|
DEFS_RPT_HAT_TGO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_RPT_HAT_TGO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# DRCC_DVM BG7NQF board:
|
||||||
|
DEFS_DRCC_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DDRCC_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
|
||||||
|
|
||||||
|
# Build compiler flags
|
||||||
|
CFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
|
||||||
|
CXXFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
|
||||||
|
CFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7)
|
||||||
|
CXXFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7)
|
||||||
|
|
||||||
|
# Linker flags
|
||||||
|
LDFLAGS_F4 =-T stm32f4xx_link.ld $(MCFLAGS_F4) --specs=nosys.specs $(INCLUDES_LIBS_F4)
|
||||||
|
LDFLAGS_F767 =-T stm32f767_link.ld $(MCFLAGS_F7) --specs=nosys.specs $(INCLUDES_LIBS_F7)
|
||||||
|
LDFLAGS_F722 =-T stm32f722_link.ld $(MCFLAGS_F7) --specs=nosys.specs $(INCLUDES_LIBS_F7)
|
||||||
|
|
||||||
|
# Common flags
|
||||||
|
CFLAGS=-Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
|
||||||
|
CXXFLAGS=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
|
||||||
|
LDFLAGS=-Os --specs=nano.specs -Wl,-Map=bin/mmdvm.map
|
||||||
|
|
||||||
|
# Build Rules
|
||||||
|
.PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm drcc_nqf clean
|
||||||
|
|
||||||
|
# Default target: Nucleo-64 F446RE board
|
||||||
|
all: nucleo
|
||||||
|
|
||||||
|
pi: GitVersion.h
|
||||||
|
pi: CFLAGS+=$(CFLAGS_F4) $(DEFS_PI)
|
||||||
|
pi: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_PI)
|
||||||
|
pi: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
|
pi: release_f4
|
||||||
|
|
||||||
|
pi-f722: GitVersion.h
|
||||||
|
pi-f722: CFLAGS+=$(CFLAGS_F7) $(DEFS_PI_F722)
|
||||||
|
pi-f722: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_PI_F722)
|
||||||
|
pi-f722: LDFLAGS+=$(LDFLAGS_F722)
|
||||||
|
pi-f722: release_f7
|
||||||
|
|
||||||
|
f4m: GitVersion.h
|
||||||
|
f4m: CFLAGS+=$(CFLAGS_F4) $(DEFS_F4M)
|
||||||
|
f4m: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_F4M)
|
||||||
|
f4m: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
|
f4m: release_f4
|
||||||
|
|
||||||
|
f7m: GitVersion.h
|
||||||
|
f7m: CFLAGS+=$(CFLAGS_F7) $(DEFS_F7M)
|
||||||
|
f7m: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_F7M)
|
||||||
|
f7m: LDFLAGS+=$(LDFLAGS_F722)
|
||||||
|
f7m: release_f7
|
||||||
|
|
||||||
|
rpt_hat: GitVersion.h
|
||||||
|
rpt_hat: CFLAGS+=$(CFLAGS_F7) $(DEFS_RPT_HAT)
|
||||||
|
rpt_hat: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_RPT_HAT)
|
||||||
|
rpt_hat: LDFLAGS+=$(LDFLAGS_F722)
|
||||||
|
rpt_hat: release_f7
|
||||||
|
|
||||||
|
rpt_hat_tgo: GitVersion.h
|
||||||
|
rpt_hat_tgo: CFLAGS+=$(CFLAGS_F4) $(DEFS_RPT_HAT_TGO)
|
||||||
|
rpt_hat_tgo: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_RPT_HAT_TGO)
|
||||||
|
rpt_hat_tgo: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
|
rpt_hat_tgo: release_f4
|
||||||
|
|
||||||
|
nucleo: GitVersion.h
|
||||||
|
nucleo: CFLAGS+=$(CFLAGS_F4) $(DEFS_NUCLEO)
|
||||||
|
nucleo: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_NUCLEO)
|
||||||
|
nucleo: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
|
nucleo: release_f4
|
||||||
|
|
||||||
|
dis: GitVersion.h
|
||||||
|
dis: CFLAGS+=$(CFLAGS_F4) $(DEFS_DIS)
|
||||||
|
dis: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DIS)
|
||||||
|
dis: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
|
dis: release_f4
|
||||||
|
|
||||||
|
f767: GitVersion.h
|
||||||
|
f767: CFLAGS+=$(CFLAGS_F7) $(DEFS_NUCLEO_F767)
|
||||||
|
f767: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_NUCLEO_F767)
|
||||||
|
f767: LDFLAGS+=$(LDFLAGS_F767)
|
||||||
|
f767: release_f7
|
||||||
|
|
||||||
|
dvm: GitVersion.h
|
||||||
|
dvm: CFLAGS+=$(CFLAGS_F4) $(DEFS_DVM)
|
||||||
|
dvm: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DVM)
|
||||||
|
dvm: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
|
dvm: release_f4
|
||||||
|
|
||||||
|
drcc_nqf: GitVersion.h
|
||||||
|
drcc_nqf: CFLAGS+=$(CFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_NQF
|
||||||
|
drcc_nqf: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_NQF
|
||||||
|
drcc_nqf: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
|
drcc_nqf: release_f4
|
||||||
|
|
||||||
|
release_f4: $(BINDIR)
|
||||||
|
release_f4: $(OBJDIR_F4)
|
||||||
|
release_f4: $(BINDIR)/$(BINHEX_F4)
|
||||||
|
release_f4: $(BINDIR)/$(BINBIN_F4)
|
||||||
|
|
||||||
|
release_f7: $(BINDIR)
|
||||||
|
release_f7: $(OBJDIR_F7)
|
||||||
|
release_f7: $(BINDIR)/$(BINHEX_F7)
|
||||||
|
release_f7: $(BINDIR)/$(BINBIN_F7)
|
||||||
|
|
||||||
|
$(BINDIR):
|
||||||
|
$(MDDIRS)
|
||||||
|
|
||||||
|
$(OBJDIR_F4):
|
||||||
|
$(MDDIRS)
|
||||||
|
|
||||||
|
$(OBJDIR_F7):
|
||||||
|
$(MDDIRS)
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINHEX_F4): $(BINDIR)/$(BINELF_F4)
|
||||||
|
$(CP) -O ihex $< $@
|
||||||
|
@echo "Objcopy from ELF to IHEX complete!\n"
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINBIN_F4): $(BINDIR)/$(BINELF_F4)
|
||||||
|
$(CP) -O binary $< $@
|
||||||
|
@echo "Objcopy from ELF to BINARY complete!\n"
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINELF_F4): $(OBJ_F4)
|
||||||
|
$(CXX) $(OBJ_F4) $(LDFLAGS) -o $@
|
||||||
|
@echo "Linking complete!\n"
|
||||||
|
$(SIZE) $(BINDIR)/$(BINELF_F4)
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINHEX_F7): $(BINDIR)/$(BINELF_F7)
|
||||||
|
$(CP) -O ihex $< $@
|
||||||
|
@echo "Objcopy from ELF to IHEX complete!\n"
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINBIN_F7): $(BINDIR)/$(BINELF_F7)
|
||||||
|
$(CP) -O binary $< $@
|
||||||
|
@echo "Objcopy from ELF to BINARY complete!\n"
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINELF_F7): $(OBJ_F7)
|
||||||
|
$(CXX) $(OBJ_F7) $(LDFLAGS) -o $@
|
||||||
|
@echo "Linking complete!\n"
|
||||||
|
$(SIZE) $(BINDIR)/$(BINELF_F7)
|
||||||
|
|
||||||
|
$(OBJDIR_F4)/%.o: $(MMDVM_PATH)/%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F7)/%.o: $(MMDVM_PATH)/%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F4)/%.o: $(STD_LIB_F4)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F7)/%.o: $(STD_LIB_F7)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F4)/%.o: $(SYS_DIR_F4)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F4)/%.o: $(STARTUP_DIR_F4)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F7)/%.o: $(SYS_DIR_F7)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F7)/%.o: $(STARTUP_DIR_F7)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(CLEANCMD)
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
ifneq ($(wildcard /usr/bin/openocd),)
|
||||||
|
/usr/bin/openocd -f /usr/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/share/openocd/scripts/target/stm32f4x.cfg -c "program bin/$(BINELF_F4) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /usr/local/bin/openocd),)
|
||||||
|
/usr/local/bin/openocd -f /usr/local/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/local/share/openocd/scripts/target/stm32f4x.cfg -c "program bin/$(BINELF_F4) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /opt/openocd/bin/openocd),)
|
||||||
|
/opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/interface/stlink-v2-1.cfg -f /opt/openocd/share/openocd/scripts/target/stm32f4x.cfg -c "program bin/$(BINELF_F4) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
deploy-f7:
|
||||||
|
ifneq ($(wildcard /usr/bin/openocd),)
|
||||||
|
/usr/bin/openocd -f /usr/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/share/openocd/scripts/target/stm32f7x.cfg -c "program bin/$(BINELF_F7) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /usr/local/bin/openocd),)
|
||||||
|
/usr/local/bin/openocd -f /usr/local/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/local/share/openocd/scripts/target/stm32f7x.cfg -c "program bin/$(BINELF_F7) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /opt/openocd/bin/openocd),)
|
||||||
|
/opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/interface/stlink-v2-1.cfg -f /opt/openocd/share/openocd/scripts/target/stm32f7x.cfg -c "program bin/$(BINELF_F7) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
deploy-pi:
|
||||||
|
ifneq ($(wildcard /usr/local/bin/stm32flash),)
|
||||||
|
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
||||||
|
-/usr/local/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F4)
|
||||||
|
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R -c /dev/ttyAMA0
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /usr/bin/stm32flash),)
|
||||||
|
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
||||||
|
-/usr/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F4)
|
||||||
|
/usr/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R -c /dev/ttyAMA0
|
||||||
|
endif
|
||||||
|
|
||||||
|
deploy-f4m: deploy-pi
|
||||||
|
deploy-dvm: deploy-pi
|
||||||
|
|
||||||
|
deploy-pi-f7:
|
||||||
|
ifneq ($(wildcard /usr/local/bin/stm32flash),)
|
||||||
|
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
||||||
|
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
|
||||||
|
|
||||||
|
else ifneq ($(wildcard /usr/bin/stm32flash),)
|
||||||
|
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
||||||
|
/usr/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
|
||||||
|
endif
|
||||||
|
|
||||||
|
deploy-f7m: deploy-pi-f7
|
||||||
|
deploy-rpt_hat: deploy-pi-f7
|
||||||
|
|
||||||
|
# Export the current git version if the index file exists, else 000...
|
||||||
|
GitVersion.h:
|
||||||
|
ifdef SYSTEMROOT
|
||||||
|
echo #define GITVERSION "0000000" > $@
|
||||||
|
else ifdef SystemRoot
|
||||||
|
echo #define GITVERSION "0000000" > $@
|
||||||
|
else
|
||||||
|
ifneq ("$(wildcard .git/index)","")
|
||||||
|
echo "#define GITVERSION \"$(shell git rev-parse --short HEAD)\"" > $@
|
||||||
|
else
|
||||||
|
echo "#define GITVERSION \"0000000\"" > $@
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
flash_f4:
|
||||||
|
@echo "flashing firmware..."
|
||||||
|
st-flash write bin/$(BINBIN_F4) 0x8000000
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
#!/usr/bin/make
|
||||||
|
# makefile for the arduino due (works with arduino IDE 1.6.11)
|
||||||
|
#
|
||||||
|
# The original file can be found at https://github.com/pauldreik/arduino-due-makefile
|
||||||
|
#
|
||||||
|
# USAGE: put this file in the same dir as your .ino file is.
|
||||||
|
# configure the PORT variable and ADIR at the top of the file
|
||||||
|
# to match your local configuration.
|
||||||
|
# Type make upload to compile and upload.
|
||||||
|
#
|
||||||
|
|
||||||
|
#user specific settings:
|
||||||
|
#where to find the IDE
|
||||||
|
ADIR:=$(HOME)/.arduino15
|
||||||
|
#which serial port to use (add a file with SUBSYSTEMS=="usb",
|
||||||
|
#ATTRS{product}=="Arduino Due Prog. Port", ATTRS{idProduct}=="003d",
|
||||||
|
#ATTRS{idVendor}=="2341", SYMLINK+="arduino_due" in /etc/udev/rules.d/
|
||||||
|
#to get this working). Do not prefix the port with /dev/, just take
|
||||||
|
#the basename.
|
||||||
|
PORT:=ttyACM0
|
||||||
|
#if you want to verify the bossac upload, define this to -v
|
||||||
|
VERIFY:=-v
|
||||||
|
|
||||||
|
|
||||||
|
#end of user configuration.
|
||||||
|
|
||||||
|
|
||||||
|
#then some general settings. They should not be necessary to modify.
|
||||||
|
#CXX:=$(ADIR)/tools/g++_arm_none_eabi/bin/arm-none-eabi-g++
|
||||||
|
CXX:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-g++
|
||||||
|
#CC:=$(ADIR)/tools/g++_arm_none_eabi/bin/arm-none-eabi-gcc
|
||||||
|
CC:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-gcc
|
||||||
|
OBJCOPY:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-objcopy
|
||||||
|
|
||||||
|
C:=$(CC)
|
||||||
|
#SAM:=arduino/sam/
|
||||||
|
SAM:=$(ADIR)/packages/arduino/hardware/sam/1.6.11
|
||||||
|
#CMSIS:=arduino/sam/system/CMSIS/
|
||||||
|
#LIBSAM:=arduino/sam/system/libsam
|
||||||
|
TMPDIR:=$(PWD)/build
|
||||||
|
AR:=$(ADIR)/tools/g++_arm_none_eabi/bin/arm-none-eabi-ar
|
||||||
|
AR:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-ar
|
||||||
|
|
||||||
|
|
||||||
|
#all these values are hard coded and should maybe be configured somehow else,
|
||||||
|
#like olikraus does in his makefile.
|
||||||
|
DEFINES:=-Dprintf=iprintf -DF_CPU=84000000 -DARDUINO=10611 -D__SAM3X8E__ -DUSB_PID=0x003e -DUSB_VID=0x2341 -DUSBCON \
|
||||||
|
-DARDUINO_SAM_DUE -DARDUINO_ARCH_SAM '-DUSB_MANUFACTURER="Arduino LLC"' '-DUSB_PRODUCT="Arduino Due"' \
|
||||||
|
-DMADEBYMAKEFILE
|
||||||
|
|
||||||
|
INCLUDES:=-I$(SAM)/system/libsam -I$(SAM)/system/CMSIS/CMSIS/Include/ \
|
||||||
|
-I$(SAM)/system/CMSIS/Device/ATMEL/ -I$(SAM)/cores/arduino \
|
||||||
|
-I$(SAM)/variants/arduino_due_x
|
||||||
|
|
||||||
|
#also include the current dir for convenience
|
||||||
|
INCLUDES += -I.
|
||||||
|
|
||||||
|
#compilation flags common to both c and c++
|
||||||
|
COMMON_FLAGS:=-g -Os -w -ffunction-sections -fdata-sections -nostdlib \
|
||||||
|
--param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb \
|
||||||
|
-fno-threadsafe-statics
|
||||||
|
#for compiling c (do not warn, this is not our code)
|
||||||
|
CFLAGS:=$(COMMON_FLAGS) -std=gnu11
|
||||||
|
#for compiling c++
|
||||||
|
CXXFLAGS:=$(COMMON_FLAGS) -fno-rtti -fno-exceptions -std=gnu++11 -Wall -Wextra
|
||||||
|
|
||||||
|
#let the results be named after the project
|
||||||
|
PROJNAME:=$(shell basename *.ino .ino)
|
||||||
|
|
||||||
|
#we will make a new mainfile from the ino file.
|
||||||
|
NEWMAINFILE:=$(TMPDIR)/$(PROJNAME).ino.cpp
|
||||||
|
|
||||||
|
#our own sourcefiles is the (converted) ino file and any local cpp files
|
||||||
|
MYSRCFILES:=$(NEWMAINFILE) $(shell ls *.cpp 2>/dev/null)
|
||||||
|
MYOBJFILES:=$(addsuffix .o,$(addprefix $(TMPDIR)/,$(notdir $(MYSRCFILES))))
|
||||||
|
|
||||||
|
#These source files are the ones forming core.a
|
||||||
|
CORESRCXX:=$(shell ls ${SAM}/cores/arduino/*.cpp ${SAM}/cores/arduino/USB/*.cpp ${SAM}/variants/arduino_due_x/variant.cpp)
|
||||||
|
CORESRC:=$(shell ls ${SAM}/cores/arduino/*.c)
|
||||||
|
|
||||||
|
#hey this one is needed too: $(SAM)/cores/arduino/wiring_pulse_asm.S" add -x assembler-with-cpp
|
||||||
|
#and this one: /1.6.11/cores/arduino/avr/dtostrf.c but it seems to work
|
||||||
|
#anyway, probably because I do not use that functionality.
|
||||||
|
|
||||||
|
#convert the core source files to object files. assume no clashes.
|
||||||
|
COREOBJSXX:=$(addprefix $(TMPDIR)/core/,$(notdir $(CORESRCXX)) )
|
||||||
|
COREOBJSXX:=$(addsuffix .o,$(COREOBJSXX))
|
||||||
|
COREOBJS:=$(addprefix $(TMPDIR)/core/,$(notdir $(CORESRC)) )
|
||||||
|
COREOBJS:=$(addsuffix .o,$(COREOBJS))
|
||||||
|
|
||||||
|
default:
|
||||||
|
@echo default rule, does nothing. Try make compile or make upload.
|
||||||
|
|
||||||
|
#This rule is good to just make sure stuff compiles, without having to wait
|
||||||
|
#for bossac.
|
||||||
|
compile: GitVersion.h $(TMPDIR)/$(PROJNAME).elf $(TMPDIR)/$(PROJNAME).bin
|
||||||
|
|
||||||
|
#This is a make rule template to create object files from the source files.
|
||||||
|
# arg 1=src file
|
||||||
|
# arg 2=object file
|
||||||
|
# arg 3= XX if c++, empty if c
|
||||||
|
define OBJ_template
|
||||||
|
$(2): $(1)
|
||||||
|
$(C$(3)) -MD -c $(C$(3)FLAGS) $(DEFINES) $(INCLUDES) $(1) -o $(2)
|
||||||
|
endef
|
||||||
|
#now invoke the template both for c++ sources
|
||||||
|
$(foreach src,$(CORESRCXX), $(eval $(call OBJ_template,$(src),$(addsuffix .o,$(addprefix $(TMPDIR)/core/,$(notdir $(src)))),XX) ) )
|
||||||
|
#...and for c sources:
|
||||||
|
$(foreach src,$(CORESRC), $(eval $(call OBJ_template,$(src),$(addsuffix .o,$(addprefix $(TMPDIR)/core/,$(notdir $(src)))),) ) )
|
||||||
|
|
||||||
|
#and our own c++ sources
|
||||||
|
$(foreach src,$(MYSRCFILES), $(eval $(call OBJ_template,$(src),$(addsuffix .o,$(addprefix $(TMPDIR)/,$(notdir $(src)))),XX) ) )
|
||||||
|
|
||||||
|
|
||||||
|
clean:
|
||||||
|
test ! -d $(TMPDIR) || rm -rf $(TMPDIR)
|
||||||
|
$(RM) GitVersion.h
|
||||||
|
|
||||||
|
.PHONY: .FORCE upload default
|
||||||
|
|
||||||
|
$(TMPDIR):
|
||||||
|
mkdir -p $(TMPDIR)
|
||||||
|
|
||||||
|
$(TMPDIR)/core:
|
||||||
|
mkdir -p $(TMPDIR)/core
|
||||||
|
|
||||||
|
#creates the cpp file from the .ino file
|
||||||
|
$(NEWMAINFILE): $(PROJNAME).ino
|
||||||
|
cat $(SAM)/cores/arduino/main.cpp > $(NEWMAINFILE)
|
||||||
|
cat $(PROJNAME).ino >> $(NEWMAINFILE)
|
||||||
|
echo 'extern "C" void __cxa_pure_virtual() {while (true);}' >> $(NEWMAINFILE)
|
||||||
|
|
||||||
|
#include the dependencies for our own files
|
||||||
|
-include $(MYOBJFILES:.o=.d)
|
||||||
|
|
||||||
|
#create the core library from the core objects. Do this EXACTLY as the
|
||||||
|
#arduino IDE does it, seems *really* picky about this.
|
||||||
|
#Sorry for the hard coding.
|
||||||
|
$(TMPDIR)/core.a: $(TMPDIR)/core $(COREOBJS) $(COREOBJSXX)
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring_shift.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring_analog.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/itoa.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/cortex_handlers.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/hooks.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/WInterrupts.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/syscalls_sam3.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/iar_calls_sam3.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring_digital.c.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/Print.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/USARTClass.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/WString.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/PluggableUSB.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/USBCore.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/CDC.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/wiring_pulse.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/UARTClass.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/main.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/new.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/watchdog.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/Stream.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/RingBuffer.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/IPAddress.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/Reset.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/WMath.cpp.o
|
||||||
|
$(AR) rcs $(TMPDIR)/core.a $(TMPDIR)/core/variant.cpp.o
|
||||||
|
|
||||||
|
#link our own object files with core to form the elf file
|
||||||
|
$(TMPDIR)/$(PROJNAME).elf: $(TMPDIR)/core.a $(TMPDIR)/core/syscalls_sam3.c.o $(MYOBJFILES)
|
||||||
|
$(CC) -mcpu=cortex-m3 -mthumb -Os -Wl,--gc-sections -T$(SAM)/variants/arduino_due_x/linker_scripts/gcc/flash.ld -Wl,-Map,$(NEWMAINFILE).map -o $@ -L$(TMPDIR) -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group -u _sbrk -u link -u _close -u _fstat -u _isatty -u _lseek -u _read -u _write -u _exit -u kill -u _getpid $(MYOBJFILES) $(TMPDIR)/core/variant.cpp.o $(SAM)/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a $(SAM)/system/CMSIS/CMSIS/Lib/GCC/libarm_cortexM3l_math.a $(TMPDIR)/core.a -Wl,--end-group -lm -gcc
|
||||||
|
|
||||||
|
#copy from the hex to our bin file (why?)
|
||||||
|
$(TMPDIR)/$(PROJNAME).bin: $(TMPDIR)/$(PROJNAME).elf
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
|
#upload to the arduino by first resetting it (stty) and the running bossac
|
||||||
|
upload: compile
|
||||||
|
stty -F /dev/$(PORT) cs8 1200 hupcl
|
||||||
|
$(ADIR)/packages/arduino/tools/bossac/1.6.1-arduino/bossac -i --port=$(PORT) -U false -e -w $(VERIFY) -b $(TMPDIR)/$(PROJNAME).bin -R
|
||||||
|
|
||||||
|
# Export the current git version if the index file exists, else 000...
|
||||||
|
GitVersion.h: .FORCE
|
||||||
|
ifneq ("$(wildcard .git/index)","")
|
||||||
|
echo "#define GITVERSION \"$(shell git rev-parse --short HEAD)\"" > $@
|
||||||
|
else
|
||||||
|
echo "#define GITVERSION \"0000000\"" > $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
.FORCE:
|
||||||
+165
@@ -0,0 +1,165 @@
|
|||||||
|
# The name for the project
|
||||||
|
TARGET:=mmdvm
|
||||||
|
|
||||||
|
# The CPU architecture (will be used for -mcpu)
|
||||||
|
MCPU:=cortex-m3
|
||||||
|
MCU:=STM32F105xC
|
||||||
|
|
||||||
|
# The source files of the project
|
||||||
|
CSRC:=
|
||||||
|
CXXSRC:=$(wildcard *.cpp)
|
||||||
|
|
||||||
|
# Include directory for the system include files and system source file
|
||||||
|
SYSDIR:=system_stm32f1xx
|
||||||
|
SYSSRC:=$(SYSDIR)/system_stm32f1xx.c
|
||||||
|
|
||||||
|
# Other include directories
|
||||||
|
INCDIR:=
|
||||||
|
|
||||||
|
# Definitions
|
||||||
|
CDEFS:=
|
||||||
|
CXXDEFS:=
|
||||||
|
|
||||||
|
# The name of the startup file which matches to the architecture (MCPU)
|
||||||
|
STARTUP:=$(SYSDIR)/startup_stm32f105xc.S
|
||||||
|
STARTUP_DEFS=
|
||||||
|
|
||||||
|
# Include directory for CMSIS
|
||||||
|
CMSISDIR:=STM32F10X_Lib/CMSIS
|
||||||
|
|
||||||
|
# Libraries
|
||||||
|
LIBDIR:=
|
||||||
|
LIBS:=-larm_cortexM3l_math
|
||||||
|
|
||||||
|
# Name of the linker script
|
||||||
|
LDSCRIPT:=$(SYSDIR)/gcc.ld
|
||||||
|
|
||||||
|
# Target objects and binaries directory
|
||||||
|
OBJDIR:=obj
|
||||||
|
BINDIR:=bin
|
||||||
|
|
||||||
|
# Port definition for programming via bootloader (using stm32flash)
|
||||||
|
BL_PORT:=ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Internal Variables
|
||||||
|
ELF:=$(BINDIR)/$(TARGET).elf
|
||||||
|
HEX:=$(BINDIR)/$(TARGET).hex
|
||||||
|
DIS:=$(BINDIR)/$(TARGET).dis
|
||||||
|
MAP:=$(BINDIR)/$(TARGET).map
|
||||||
|
OBJ:=$(CSRC:%.c=$(OBJDIR)/%.o) $(CXXSRC:%.cpp=$(OBJDIR)/%.o)
|
||||||
|
OBJ+=$(SYSSRC:$(SYSDIR)/%.c=$(OBJDIR)/%.o) $(STARTUP:$(SYSDIR)/%.S=$(OBJDIR)/%.o)
|
||||||
|
|
||||||
|
# Replace standard build tools by arm tools
|
||||||
|
CC:=arm-none-eabi-gcc
|
||||||
|
CXX:=arm-none-eabi-g++
|
||||||
|
AS:=arm-none-eabi-gcc
|
||||||
|
LD:=arm-none-eabi-g++
|
||||||
|
OBJCOPY:=arm-none-eabi-objcopy
|
||||||
|
OBJDUMP:=arm-none-eabi-objdump
|
||||||
|
SIZE:=arm-none-eabi-size
|
||||||
|
|
||||||
|
# Common flags
|
||||||
|
COMMON_FLAGS =-mthumb -mlittle-endian -mcpu=$(MCPU)
|
||||||
|
COMMON_FLAGS+= -Wall
|
||||||
|
COMMON_FLAGS+= -I. -I$(CMSISDIR)/Include -I$(CMSISDIR)/Device/ST/STM32F1xx/Include -I$(SYSDIR)
|
||||||
|
COMMON_FLAGS+= $(addprefix -I,$(INCDIR))
|
||||||
|
COMMON_FLAGS+= -D$(MCU) -DMADEBYMAKEFILE -DSTM32F1
|
||||||
|
COMMON_FLAGS+= -Os -flto -ffunction-sections -fdata-sections
|
||||||
|
COMMON_FLAGS+= -g
|
||||||
|
# Assembler flags
|
||||||
|
ASFLAGS:=$(COMMON_FLAGS)
|
||||||
|
# C flags
|
||||||
|
CFLAGS:=$(COMMON_FLAGS) $(addprefix -D,$(CDEFS))
|
||||||
|
CFLAGS+= -std=gnu11 -nostdlib
|
||||||
|
# CXX flags
|
||||||
|
CXXFLAGS:=$(COMMON_FLAGS) $(addprefix -D,$(CXXDEFS))
|
||||||
|
CXXFLAGS+= -nostdlib -fno-exceptions -fno-rtti
|
||||||
|
# LD flags
|
||||||
|
LDFLAGS:=$(COMMON_FLAGS) -Wl,--gc-sections -Wl,-Map=$(MAP) -Wl,--no-wchar-size-warning
|
||||||
|
LDFLAGS+= --specs=nosys.specs --specs=nano.specs
|
||||||
|
LDFLAGS+= -L$(CMSISDIR)/Lib/GCC/ $(addprefix -L,$(LIBDIR))
|
||||||
|
LDLIBS:=-T$(LDSCRIPT) $(LIBS)
|
||||||
|
|
||||||
|
# Dependecies
|
||||||
|
DEPENDS:=$(CSRC:%.c=$(OBJDIR)/%.d) $(CXXSRC:%.cpp=$(OBJDIR)/%.d)
|
||||||
|
|
||||||
|
|
||||||
|
# Additional Suffixes
|
||||||
|
.SUFFIXES: .elf .hex
|
||||||
|
|
||||||
|
# Targets
|
||||||
|
.PHONY: all
|
||||||
|
all: GitVersion.h $(DIS) $(HEX)
|
||||||
|
$(SIZE) $(ELF)
|
||||||
|
|
||||||
|
.PHONY: program
|
||||||
|
program: $(HEX) $(ELF)
|
||||||
|
openocd -f openocd.cfg \
|
||||||
|
-c "program $(HEX) verify reset exit"
|
||||||
|
$(SIZE) $(ELF)
|
||||||
|
|
||||||
|
.PHONY: program_bl
|
||||||
|
program_bl: $(HEX) $(ELF)
|
||||||
|
stm32flash -w $(HEX) -v /dev/$(BL_PORT)
|
||||||
|
$(SIZE) $(ELF)
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
run: $(HEX) $(ELF)
|
||||||
|
openocd -f openocd.cfg \
|
||||||
|
-c "init" -c "reset" -c "exit"
|
||||||
|
|
||||||
|
.PHONY: debug
|
||||||
|
debug: $(ELF)
|
||||||
|
./debug.sh $(ELF)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(RM) $(OBJ) $(HEX) $(ELF) $(DIS) $(MAP) $(DEPENDS) GitVersion.h
|
||||||
|
|
||||||
|
# implicit rules
|
||||||
|
.elf.hex:
|
||||||
|
$(OBJCOPY) -O ihex $< $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.c
|
||||||
|
$(CC) -MMD $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: %.cpp
|
||||||
|
$(CXX) -MMD $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SYSDIR)/%.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
$(OBJDIR)/%.o: $(SYSDIR)/%.S
|
||||||
|
$(AS) $(ASFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# explicit rules
|
||||||
|
$(OBJDIR):
|
||||||
|
mkdir -p $(OBJDIR)
|
||||||
|
|
||||||
|
$(BINDIR):
|
||||||
|
mkdir -p $(BINDIR)
|
||||||
|
|
||||||
|
$(ELF): $(OBJDIR) $(BINDIR) $(OBJ)
|
||||||
|
$(LD) $(OBJ) $(LDFLAGS) $(LDLIBS) -o $@
|
||||||
|
|
||||||
|
$(DIS): $(ELF)
|
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# include dependecies
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
# Export the current git version if the index file exists, else 000...
|
||||||
|
GitVersion.h:
|
||||||
|
ifdef SYSTEMROOT
|
||||||
|
echo #define GITVERSION "0000000" > $@
|
||||||
|
else ifdef SystemRoot
|
||||||
|
echo #define GITVERSION "0000000" > $@
|
||||||
|
else
|
||||||
|
ifneq ("$(wildcard .git/index)","")
|
||||||
|
echo "#define GITVERSION \"$(shell git rev-parse --short HEAD)\"" > $@
|
||||||
|
else
|
||||||
|
echo "#define GITVERSION \"0000000\"" > $@
|
||||||
|
endif
|
||||||
|
endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "NXDNRX.h"
|
#include "NXDNRX.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
@@ -406,5 +403,3 @@ void CNXDNRX::writeRSSIData(uint8_t* data)
|
|||||||
m_rssiCount = 0U;
|
m_rssiCount = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,13 +16,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
|
|
||||||
#if !defined(NXDNRX_H)
|
#if !defined(NXDNRX_H)
|
||||||
#define NXDNRX_H
|
#define NXDNRX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "NXDNDefines.h"
|
#include "NXDNDefines.h"
|
||||||
|
|
||||||
enum NXDNRX_STATE {
|
enum NXDNRX_STATE {
|
||||||
@@ -70,5 +67,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -18,9 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "NXDNTX.h"
|
#include "NXDNTX.h"
|
||||||
|
|
||||||
@@ -84,8 +81,7 @@ void CNXDNTX::process()
|
|||||||
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[2U];
|
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[2U];
|
||||||
} else {
|
} else {
|
||||||
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++) {
|
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++) {
|
||||||
uint8_t c = 0U;
|
uint8_t c = m_buffer.get();
|
||||||
m_buffer.get(c);
|
|
||||||
m_poBuffer[m_poLen++] = c;
|
m_poBuffer[m_poLen++] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +122,7 @@ void CNXDNTX::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CNXDNTX::writeData(const uint8_t* data, uint16_t length)
|
uint8_t CNXDNTX::writeData(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
|
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -203,6 +199,3 @@ void CNXDNTX::setParams(uint8_t txHang)
|
|||||||
{
|
{
|
||||||
m_txHang = txHang * 600U;
|
m_txHang = txHang * 600U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -16,20 +16,18 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_NXDN)
|
|
||||||
|
|
||||||
#if !defined(NXDNTX_H)
|
#if !defined(NXDNTX_H)
|
||||||
#define NXDNTX_H
|
#define NXDNTX_H
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
class CNXDNTX {
|
class CNXDNTX {
|
||||||
public:
|
public:
|
||||||
CNXDNTX();
|
CNXDNTX();
|
||||||
|
|
||||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
@@ -40,7 +38,7 @@ public:
|
|||||||
void setParams(uint8_t txHang);
|
void setParams(uint8_t txHang);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRingBuffer<uint8_t> m_buffer;
|
CSerialRB m_buffer;
|
||||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||||
arm_fir_instance_q15 m_sincFilter;
|
arm_fir_instance_q15 m_sincFilter;
|
||||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||||
@@ -57,6 +55,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -18,9 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "P25RX.h"
|
#include "P25RX.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
@@ -538,6 +535,3 @@ void CP25RX::writeRSSILdu(uint8_t* ldu)
|
|||||||
m_rssiAccum = 0U;
|
m_rssiAccum = 0U;
|
||||||
m_rssiCount = 0U;
|
m_rssiCount = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -17,13 +17,10 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
|
|
||||||
#if !defined(P25RX_H)
|
#if !defined(P25RX_H)
|
||||||
#define P25RX_H
|
#define P25RX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
#include "P25Defines.h"
|
#include "P25Defines.h"
|
||||||
|
|
||||||
enum P25RX_STATE {
|
enum P25RX_STATE {
|
||||||
@@ -75,6 +72,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -18,9 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "P25TX.h"
|
#include "P25TX.h"
|
||||||
|
|
||||||
@@ -78,11 +75,9 @@ void CP25TX::process()
|
|||||||
for (uint16_t i = 0U; i < m_txDelay; i++)
|
for (uint16_t i = 0U; i < m_txDelay; i++)
|
||||||
m_poBuffer[m_poLen++] = P25_START_SYNC;
|
m_poBuffer[m_poLen++] = P25_START_SYNC;
|
||||||
} else {
|
} else {
|
||||||
uint8_t length = 0U;
|
uint8_t length = m_buffer.get();
|
||||||
m_buffer.get(length);
|
|
||||||
for (uint8_t i = 0U; i < length; i++) {
|
for (uint8_t i = 0U; i < length; i++) {
|
||||||
uint8_t c = 0U;
|
uint8_t c = m_buffer.get();
|
||||||
m_buffer.get(c);
|
|
||||||
m_poBuffer[m_poLen++] = c;
|
m_poBuffer[m_poLen++] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,7 +118,7 @@ void CP25TX::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CP25TX::writeData(const uint8_t* data, uint16_t length)
|
uint8_t CP25TX::writeData(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length < (P25_TERM_FRAME_LENGTH_BYTES + 1U))
|
if (length < (P25_TERM_FRAME_LENGTH_BYTES + 1U))
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -201,6 +196,3 @@ void CP25TX::setParams(uint8_t txHang)
|
|||||||
{
|
{
|
||||||
m_txHang = txHang * 1200U;
|
m_txHang = txHang * 1200U;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -16,20 +16,18 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_P25)
|
|
||||||
|
|
||||||
#if !defined(P25TX_H)
|
#if !defined(P25TX_H)
|
||||||
#define P25TX_H
|
#define P25TX_H
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
class CP25TX {
|
class CP25TX {
|
||||||
public:
|
public:
|
||||||
CP25TX();
|
CP25TX();
|
||||||
|
|
||||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
@@ -40,7 +38,7 @@ public:
|
|||||||
void setParams(uint8_t txHang);
|
void setParams(uint8_t txHang);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRingBuffer<uint8_t> m_buffer;
|
CSerialRB m_buffer;
|
||||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||||
arm_fir_instance_q15 m_lpFilter;
|
arm_fir_instance_q15 m_lpFilter;
|
||||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||||
@@ -57,6 +55,3 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,9 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#if defined(MODE_POCSAG)
|
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "POCSAGTX.h"
|
#include "POCSAGTX.h"
|
||||||
|
|
||||||
@@ -64,8 +61,7 @@ void CPOCSAGTX::process()
|
|||||||
m_poBuffer[m_poLen++] = POCSAG_SYNC;
|
m_poBuffer[m_poLen++] = POCSAG_SYNC;
|
||||||
} else {
|
} else {
|
||||||
for (uint8_t i = 0U; i < POCSAG_FRAME_LENGTH_BYTES; i++) {
|
for (uint8_t i = 0U; i < POCSAG_FRAME_LENGTH_BYTES; i++) {
|
||||||
uint8_t c = 0U;
|
uint8_t c = m_buffer.get();
|
||||||
m_buffer.get(c);
|
|
||||||
m_poBuffer[m_poLen++] = c;
|
m_poBuffer[m_poLen++] = c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,7 +95,7 @@ bool CPOCSAGTX::busy()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint16_t length)
|
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length != POCSAG_FRAME_LENGTH_BYTES)
|
if (length != POCSAG_FRAME_LENGTH_BYTES)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -151,5 +147,3 @@ uint8_t CPOCSAGTX::getSpace() const
|
|||||||
return m_buffer.getSpace() / POCSAG_FRAME_LENGTH_BYTES;
|
return m_buffer.getSpace() / POCSAG_FRAME_LENGTH_BYTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,20 +16,18 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
#if defined(MODE_POCSAG)
|
|
||||||
|
|
||||||
#if !defined(POCSAGTX_H)
|
#if !defined(POCSAGTX_H)
|
||||||
#define POCSAGTX_H
|
#define POCSAGTX_H
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
class CPOCSAGTX {
|
class CPOCSAGTX {
|
||||||
public:
|
public:
|
||||||
CPOCSAGTX();
|
CPOCSAGTX();
|
||||||
|
|
||||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
void writeByte(uint8_t c);
|
void writeByte(uint8_t c);
|
||||||
|
|
||||||
@@ -42,7 +40,7 @@ public:
|
|||||||
bool busy();
|
bool busy();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CRingBuffer<uint8_t> m_buffer;
|
CSerialRB m_buffer;
|
||||||
arm_fir_instance_q15 m_modFilter;
|
arm_fir_instance_q15 m_modFilter;
|
||||||
q15_t m_modState[170U]; // NoTaps + BlockSize - 1, 6 + 160 - 1 plus some spare
|
q15_t m_modState[170U]; // NoTaps + BlockSize - 1, 6 + 160 - 1 plus some spare
|
||||||
uint8_t m_poBuffer[200U];
|
uint8_t m_poBuffer[200U];
|
||||||
@@ -53,5 +51,3 @@ private:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,35 +1,7 @@
|
|||||||
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion, P25, NXDN, M17, POCSAG, AX.25, and FM modes.
|
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion, P25, NXDN, and POCSAG modes.
|
||||||
|
|
||||||
It runs on the Arduino Due, the ST-Micro STM32F4xxx and STM32F7xxx processors, as well as the Teensy 3.5/3.6. What these platforms have in common is the use of an ARM Cortex-M3, M4, or M7 processors with a minimum clock speed greater of 80 MHz, and access to at least one analogue to digital converter, one digital to analogue converter, as well as a number of GPIO pins.
|
It runs on the Arduino Due, the ST-Micro STM32F1xxx, STM32F4xxx and STM32F7xxx processors, as well as the Teensy 3.1/3.2/3.5/3.6. What these platforms have in common is the use of an ARM Cortex-M3 or M4 processor with a clock speed greater than 70 MHz, and access to at least one analogue to digital converter and one digital to analogue converter.
|
||||||
|
|
||||||
In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. The STM32 support is supplied via the ARM GCC compiler. The Teensy support uses Teensyduino.
|
In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. The STM32 support is being supplied via the Coocox IDE with ARM GCC. The Teensy support uses Teensyduino.
|
||||||
|
|
||||||
This software is licenced under the GPL v2 and is primarily intended for amateur and educational use.
|
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.
|
||||||
|
|
||||||
Portions of the ARM support code include the following copyright:
|
|
||||||
|
|
||||||
Copyright (c) 2011 - 2013 ARM LIMITED
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
- Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
- Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
- Neither the name of ARM nor the names of its contributors may be used
|
|
||||||
to endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|||||||
+102
@@ -0,0 +1,102 @@
|
|||||||
|
/*
|
||||||
|
TX fifo control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "RSSIRB.h"
|
||||||
|
|
||||||
|
CRSSIRB::CRSSIRB(uint16_t length) :
|
||||||
|
m_length(length),
|
||||||
|
m_head(0U),
|
||||||
|
m_tail(0U),
|
||||||
|
m_full(false),
|
||||||
|
m_overflow(false)
|
||||||
|
{
|
||||||
|
m_rssi = new uint16_t[length];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CRSSIRB::getSpace() const
|
||||||
|
{
|
||||||
|
uint16_t n = 0U;
|
||||||
|
|
||||||
|
if (m_tail == m_head)
|
||||||
|
n = m_full ? 0U : m_length;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
n = m_length - m_head + m_tail;
|
||||||
|
else
|
||||||
|
n = m_tail - m_head;
|
||||||
|
|
||||||
|
if (n > m_length)
|
||||||
|
n = 0U;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CRSSIRB::getData() const
|
||||||
|
{
|
||||||
|
if (m_tail == m_head)
|
||||||
|
return m_full ? m_length : 0U;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
return m_head - m_tail;
|
||||||
|
else
|
||||||
|
return m_length - m_tail + m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRSSIRB::put(uint16_t rssi)
|
||||||
|
{
|
||||||
|
if (m_full) {
|
||||||
|
m_overflow = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rssi[m_head] = rssi;
|
||||||
|
|
||||||
|
m_head++;
|
||||||
|
if (m_head >= m_length)
|
||||||
|
m_head = 0U;
|
||||||
|
|
||||||
|
if (m_head == m_tail)
|
||||||
|
m_full = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRSSIRB::get(uint16_t& rssi)
|
||||||
|
{
|
||||||
|
if (m_head == m_tail && !m_full)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rssi = m_rssi[m_tail];
|
||||||
|
|
||||||
|
m_full = false;
|
||||||
|
|
||||||
|
m_tail++;
|
||||||
|
if (m_tail >= m_length)
|
||||||
|
m_tail = 0U;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CRSSIRB::hasOverflowed()
|
||||||
|
{
|
||||||
|
bool overflow = m_overflow;
|
||||||
|
|
||||||
|
m_overflow = false;
|
||||||
|
|
||||||
|
return overflow;
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
Serial fifo control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(RSSIRB_H)
|
||||||
|
#define RSSIRB_H
|
||||||
|
|
||||||
|
#if defined(STM32F4XX)
|
||||||
|
#include "stm32f4xx.h"
|
||||||
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
|
#elif defined(STM32F105xC)
|
||||||
|
#include "stm32f1xx.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#else
|
||||||
|
#include <Arduino.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CRSSIRB {
|
||||||
|
public:
|
||||||
|
CRSSIRB(uint16_t length);
|
||||||
|
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
|
uint16_t getData() const;
|
||||||
|
|
||||||
|
bool put(uint16_t rssi);
|
||||||
|
|
||||||
|
bool get(uint16_t& rssi);
|
||||||
|
|
||||||
|
bool hasOverflowed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t m_length;
|
||||||
|
volatile uint16_t* m_rssi;
|
||||||
|
volatile uint16_t m_head;
|
||||||
|
volatile uint16_t m_tail;
|
||||||
|
volatile bool m_full;
|
||||||
|
bool m_overflow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Wojciech Krutnik N0CALL
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* FIFO ring buffer
|
||||||
|
* source:
|
||||||
|
* http://stackoverflow.com/questions/6822548/correct-way-of-implementing-a-uart-receive-buffer-in-a-small-arm-microcontroller
|
||||||
|
* (modified)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(RINGBUFF_H)
|
||||||
|
#define RINGBUFF_H
|
||||||
|
|
||||||
|
#define RINGBUFF_SIZE(ringBuff) (ringBuff.size) /* serial buffer in bytes (power 2) */
|
||||||
|
#define RINGBUFF_MASK(ringBuff) (ringBuff.size-1U) /* buffer size mask */
|
||||||
|
|
||||||
|
/* Buffer read / write macros */
|
||||||
|
#define RINGBUFF_RESET(ringBuff) (ringBuff).rdIdx = ringBuff.wrIdx = 0
|
||||||
|
#define RINGBUFF_WRITE(ringBuff, dataIn) (ringBuff).data[RINGBUFF_MASK(ringBuff) & ringBuff.wrIdx++] = (dataIn)
|
||||||
|
#define RINGBUFF_READ(ringBuff) ((ringBuff).data[RINGBUFF_MASK(ringBuff) & ((ringBuff).rdIdx++)])
|
||||||
|
#define RINGBUFF_EMPTY(ringBuff) ((ringBuff).rdIdx == (ringBuff).wrIdx)
|
||||||
|
#define RINGBUFF_FULL(ringBuff) ((RINGBUFF_MASK(ringBuff) & ringFifo.rdIdx) == (RINGBUFF_MASK(ringBuff) & ringFifo.wrIdx))
|
||||||
|
#define RINGBUFF_COUNT(ringBuff) (RINGBUFF_MASK(ringBuff) & ((ringBuff).wrIdx - (ringBuff).rdIdx))
|
||||||
|
|
||||||
|
/* Buffer type */
|
||||||
|
#define DECLARE_RINGBUFFER_TYPE(name, _size) \
|
||||||
|
typedef struct{ \
|
||||||
|
uint32_t size; \
|
||||||
|
uint32_t wrIdx; \
|
||||||
|
uint32_t rdIdx; \
|
||||||
|
uint8_t data[_size]; \
|
||||||
|
}name##_t
|
||||||
|
|
||||||
|
#endif
|
||||||
Submodule
+1
Submodule STM32F10X_Lib added at 417e0c2f4a
Submodule
+1
Submodule STM32F4XX_Lib added at bcd346f530
Submodule
+1
Submodule STM32F7XX_Lib added at 2d5f4236fa
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* source: http://mightydevices.com/?p=144
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(STM32UTILS_H)
|
||||||
|
#define STM32UTILS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* ram function */
|
||||||
|
#define RAMFUNC __attribute__ ((long_call, section (".data")))
|
||||||
|
/* eeprom data */
|
||||||
|
/* for placing variables in eeprom memory */
|
||||||
|
#define EEMEM __attribute__((section(".eeprom")))
|
||||||
|
|
||||||
|
/* bitband type */
|
||||||
|
typedef volatile uint32_t * const bitband_t;
|
||||||
|
|
||||||
|
/* base address for bit banding */
|
||||||
|
#define BITBAND_SRAM_REF (0x20000000)
|
||||||
|
/* base address for bit banding */
|
||||||
|
#define BITBAND_SRAM_BASE (0x22000000)
|
||||||
|
/* base address for bit banding */
|
||||||
|
#define BITBAND_PERIPH_REF (0x40000000)
|
||||||
|
/* base address for bit banding */
|
||||||
|
#define BITBAND_PERIPH_BASE (0x42000000)
|
||||||
|
|
||||||
|
/* sram bit band */
|
||||||
|
#define BITBAND_SRAM(address, bit) ((void*)(BITBAND_SRAM_BASE + \
|
||||||
|
(((uint32_t)address) - BITBAND_SRAM_REF) * 32 + (bit) * 4))
|
||||||
|
|
||||||
|
/* periph bit band */
|
||||||
|
#define BITBAND_PERIPH(address, bit) ((void *)(BITBAND_PERIPH_BASE + \
|
||||||
|
(((uint32_t)address) - BITBAND_PERIPH_REF) * 32 + (bit) * 4))
|
||||||
|
|
||||||
|
#endif
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
TX fifo control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SampleRB.h"
|
||||||
|
|
||||||
|
CSampleRB::CSampleRB(uint16_t length) :
|
||||||
|
m_length(length),
|
||||||
|
m_head(0U),
|
||||||
|
m_tail(0U),
|
||||||
|
m_full(false),
|
||||||
|
m_overflow(false)
|
||||||
|
{
|
||||||
|
m_samples = new uint16_t[length];
|
||||||
|
m_control = new uint8_t[length];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CSampleRB::getSpace() const
|
||||||
|
{
|
||||||
|
uint16_t n = 0U;
|
||||||
|
|
||||||
|
if (m_tail == m_head)
|
||||||
|
n = m_full ? 0U : m_length;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
n = m_length - m_head + m_tail;
|
||||||
|
else
|
||||||
|
n = m_tail - m_head;
|
||||||
|
|
||||||
|
if (n > m_length)
|
||||||
|
n = 0U;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CSampleRB::getData() const
|
||||||
|
{
|
||||||
|
if (m_tail == m_head)
|
||||||
|
return m_full ? m_length : 0U;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
return m_head - m_tail;
|
||||||
|
else
|
||||||
|
return m_length - m_tail + m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSampleRB::put(uint16_t sample, uint8_t control)
|
||||||
|
{
|
||||||
|
if (m_full) {
|
||||||
|
m_overflow = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_samples[m_head] = sample;
|
||||||
|
m_control[m_head] = control;
|
||||||
|
|
||||||
|
m_head++;
|
||||||
|
if (m_head >= m_length)
|
||||||
|
m_head = 0U;
|
||||||
|
|
||||||
|
if (m_head == m_tail)
|
||||||
|
m_full = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSampleRB::get(uint16_t& sample, uint8_t& control)
|
||||||
|
{
|
||||||
|
if (m_head == m_tail && !m_full)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sample = m_samples[m_tail];
|
||||||
|
control = m_control[m_tail];
|
||||||
|
|
||||||
|
m_full = false;
|
||||||
|
|
||||||
|
m_tail++;
|
||||||
|
if (m_tail >= m_length)
|
||||||
|
m_tail = 0U;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSampleRB::hasOverflowed()
|
||||||
|
{
|
||||||
|
bool overflow = m_overflow;
|
||||||
|
|
||||||
|
m_overflow = false;
|
||||||
|
|
||||||
|
return overflow;
|
||||||
|
}
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user