mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-08-21 14:36:21 +02:00
Compare commits
341
Commits
FM
...
57e692ad8c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57e692ad8c | ||
|
|
841d7505c2 | ||
|
|
549dfd7258 | ||
|
|
30ba4c4c55 | ||
|
|
a696fd454c | ||
|
|
3fd84d5ed4 | ||
|
|
78216afbb7 | ||
|
|
0308bfc6c7 | ||
|
|
278c69152a | ||
|
|
8e144e81d0 | ||
|
|
5dd59fc473 | ||
|
|
5fb5986d50 | ||
|
|
824c9b9852 | ||
|
|
f324f96db7 | ||
|
|
15227d9cec | ||
|
|
c3246dbcb7 | ||
|
|
65c51bf849 | ||
|
|
edd60caad3 | ||
|
|
b8a0f7b1cf | ||
|
|
28e564738e | ||
|
|
a7fddc37e1 | ||
|
|
a8bf99037e | ||
|
|
029e6df4b9 | ||
|
|
85d3086d4c | ||
|
|
ccf3b7301e | ||
|
|
6b3a811ae7 | ||
|
|
508018c89c | ||
|
|
3e079f58ad | ||
|
|
7ef0d992d9 | ||
|
|
bf23a94038 | ||
|
|
b2755864ef | ||
|
|
7276ca3929 | ||
|
|
d14b9dede3 | ||
|
|
de87d77ad6 | ||
|
|
2626ad5580 | ||
|
|
031b078e76 | ||
|
|
5d987969a9 | ||
|
|
f898390956 | ||
|
|
f8d1cc7aed | ||
|
|
cf9fa93cb9 | ||
|
|
69adaf2ebb | ||
|
|
7f4ae790ba | ||
|
|
416fc8fc8b | ||
|
|
5b79356ddb | ||
|
|
26fc87aca6 | ||
|
|
54745130c2 | ||
|
|
f65d52bf2f | ||
|
|
5800b33f21 | ||
|
|
105dba2c27 | ||
|
|
777cc9f2ea | ||
|
|
e879b4615a | ||
|
|
8d69fc59be | ||
|
|
2f4e9cc269 | ||
|
|
ee07f76bd5 | ||
|
|
d063a1da1e | ||
|
|
6a4dad4c44 | ||
|
|
ed6bd66fab | ||
|
|
1a07a6f0d1 | ||
|
|
70bf47f93e | ||
|
|
a5eaafc7e0 | ||
|
|
2200945857 | ||
|
|
63a8e61a45 | ||
|
|
7275f65e44 | ||
|
|
2aabdb61ab | ||
|
|
96c0e5b141 | ||
|
|
9c883cfafd | ||
|
|
8a1ab88c3a | ||
|
|
f4e1c0b401 | ||
|
|
43b53fe2fc | ||
|
|
6517229f87 | ||
|
|
d0557ab723 | ||
|
|
b5d106dcb6 | ||
|
|
34cbff41c9 | ||
|
|
752e13821f | ||
|
|
86b45c15eb | ||
|
|
4fa0e052f8 | ||
|
|
0736a5cbe8 | ||
|
|
6ffb68450c | ||
|
|
1ad20fd4a0 | ||
|
|
34f6dfc5bb | ||
|
|
1e065ba17f | ||
|
|
1df7d7a7fc | ||
|
|
7e919b12f7 | ||
|
|
bada4d9285 | ||
|
|
9ae4a5376d | ||
|
|
8038ce9c9c | ||
|
|
842dcdb5c5 | ||
|
|
f7ead5cc0e | ||
|
|
b155597693 | ||
|
|
7148cf9f7d | ||
|
|
9440b43114 | ||
|
|
c06a83660f | ||
|
|
657e71238d | ||
|
|
510d433906 | ||
|
|
ff39a9031b | ||
|
|
4f3aa8b7e1 | ||
|
|
a35b8f929a | ||
|
|
6d0335b357 | ||
|
|
54f4dcabf0 | ||
|
|
19e2ccf150 | ||
|
|
0c4f49fa68 | ||
|
|
98ebefe84b | ||
|
|
029e7eef4a | ||
|
|
ca4fff2ba6 | ||
|
|
23ba73cabd | ||
|
|
519af80ac4 | ||
|
|
c5b542f438 | ||
|
|
3503e0cc2a | ||
|
|
955578789d | ||
|
|
061e10e395 | ||
|
|
fa9040fdf0 | ||
|
|
8240225371 | ||
|
|
f2c7c19444 | ||
|
|
2e5f174cdd | ||
|
|
d144ce6f1c | ||
|
|
31744a237a | ||
|
|
46c0958704 | ||
|
|
99d2a0d822 | ||
|
|
81518bf74c | ||
|
|
dd5a465a39 | ||
|
|
a345586ee9 | ||
|
|
55c89a4413 | ||
|
|
60f87072ba | ||
|
|
f2d2033733 | ||
|
|
0334b5a791 | ||
|
|
a62fd814ae | ||
|
|
02000c8049 | ||
|
|
2509ab5ba1 | ||
|
|
2de9e4d533 | ||
|
|
fda1e3dcf4 | ||
|
|
cb3ed795d0 | ||
|
|
632ddda68b | ||
|
|
b6093406ad | ||
|
|
8d9b49bdb0 | ||
|
|
625ec93af8 | ||
|
|
b2111553c6 | ||
|
|
252d54a484 | ||
|
|
1ad9799123 | ||
|
|
6d67b9f104 | ||
|
|
fb85505433 | ||
|
|
823b91c97d | ||
|
|
2a001f491d | ||
|
|
b5ba384495 | ||
|
|
d8f138066e | ||
|
|
6964251122 | ||
|
|
0fca178bd7 | ||
|
|
a60ecb3e57 | ||
|
|
a2978d9e91 | ||
|
|
e304f5cce2 | ||
|
|
99a7df7c13 | ||
|
|
6dfe1a9271 | ||
|
|
9ff59570c7 | ||
|
|
d5e9b5a315 | ||
|
|
1ac0628c1c | ||
|
|
dc41fd83d2 | ||
|
|
20013e3adc | ||
|
|
5960fb97f3 | ||
|
|
8f8dc92a14 | ||
|
|
ccdbe126e0 | ||
|
|
d29a0bc3a6 | ||
|
|
4ff057069b | ||
|
|
f8d8f85841 | ||
|
|
ad77fd60fd | ||
|
|
aab8f5469f | ||
|
|
f1d6a8b36e | ||
|
|
843997ccad | ||
|
|
d5f2d1c382 | ||
|
|
c99f50575d | ||
|
|
29c8cf9414 | ||
|
|
2c6e2c2a11 | ||
|
|
8d10555dc9 | ||
|
|
14d5098018 | ||
|
|
52a351d0f1 | ||
|
|
43f84ae968 | ||
|
|
a73376671c | ||
|
|
759efd1da4 | ||
|
|
ea0c1953cc | ||
|
|
a29cb23a75 | ||
|
|
bb66c72ef3 | ||
|
|
2da28ede64 | ||
|
|
a7ac55795d | ||
|
|
835ef46aef | ||
|
|
3de10fe98b | ||
|
|
7ad70d04a4 | ||
|
|
e210062365 | ||
|
|
f9fcdc5292 | ||
|
|
0ea732780d | ||
|
|
33d922b8c2 | ||
|
|
114c2bcb15 | ||
|
|
6dbda2795a | ||
|
|
6a80d0ec09 | ||
|
|
0e8f20e1cc | ||
|
|
af11be16dc | ||
|
|
e332dbba8e | ||
|
|
746d915bf9 | ||
|
|
c896cf823e | ||
|
|
c2959466fd | ||
|
|
121c76f3d8 | ||
|
|
22cb16f831 | ||
|
|
57e18e337f | ||
|
|
e1d1ac4a4d | ||
|
|
64fe59382f | ||
|
|
a2e2853241 | ||
|
|
1309ad9326 | ||
|
|
411d439d78 | ||
|
|
ec9428d63e | ||
|
|
2a4b28c35e | ||
|
|
4f060c0047 | ||
|
|
1ed3a4c9d5 | ||
|
|
f414288c9b | ||
|
|
72cd2ce03e | ||
|
|
9137af8e3f | ||
|
|
cdfe3d0ec9 | ||
|
|
4dfab06a50 | ||
|
|
47649171fc | ||
|
|
0bd79fa440 | ||
|
|
26d055a67b | ||
|
|
5db1adb5ea | ||
|
|
f86b5435bb | ||
|
|
31f0e24588 | ||
|
|
04d0b15545 | ||
|
|
f14222e77d | ||
|
|
5039dfbe68 | ||
|
|
f9f81b9b8e | ||
|
|
3cc5d67696 | ||
|
|
3f960f9fc5 | ||
|
|
489853f200 | ||
|
|
96e1a765f9 | ||
|
|
04982c25c0 | ||
|
|
a3ffa9ed36 | ||
|
|
e7a22482db | ||
|
|
625749a546 | ||
|
|
d75042dc4c | ||
|
|
296ac88842 | ||
|
|
48e863d1d0 | ||
|
|
7b915f9cac | ||
|
|
e330c9f52a | ||
|
|
9470b1d6d3 | ||
|
|
388620b182 | ||
|
|
72e45177f3 | ||
|
|
90b82621f2 | ||
|
|
cfcb7ed852 | ||
|
|
b245be464f | ||
|
|
139003d4c7 | ||
|
|
c47eacd010 | ||
|
|
6b01f12602 | ||
|
|
4f93c6022c | ||
|
|
81f6b6be53 | ||
|
|
fa9f89700f | ||
|
|
9023b6ae13 | ||
|
|
df23e15c91 | ||
|
|
51e5e7b851 | ||
|
|
056dd908b3 | ||
|
|
62f239ccc9 | ||
|
|
994226e4b1 | ||
|
|
2cc6c1f68f | ||
|
|
8e8cf35b19 | ||
|
|
66de35b6d8 | ||
|
|
7dc420c8ff | ||
|
|
df0a9ebe72 | ||
|
|
e957f0154e | ||
|
|
b10c72fd78 | ||
|
|
496afcb40e | ||
|
|
9467b10e5c | ||
|
|
13c5f7b0b4 | ||
|
|
b64712f657 | ||
|
|
d23c0900c1 | ||
|
|
a0a3080da2 | ||
|
|
0fad84b46d | ||
|
|
1b40044a23 | ||
|
|
a671263398 | ||
|
|
ca1cc7096a | ||
|
|
a5aabd8fac | ||
|
|
6d0e57ea88 | ||
|
|
1d04c1e903 | ||
|
|
042c26b3bb | ||
|
|
b4a125a759 | ||
|
|
8ecf80ff8f | ||
|
|
6786b9b6b1 | ||
|
|
86ffc69b30 | ||
|
|
5d4df6ffd9 | ||
|
|
eac2aa4ac1 | ||
|
|
8cbd52aa72 | ||
|
|
99b853a976 | ||
|
|
15bc1a4027 | ||
|
|
1836ba928e | ||
|
|
4a5a260c28 | ||
|
|
4bcc1e88c4 | ||
|
|
89458a2c93 | ||
|
|
c91a42f53d | ||
|
|
470a070d96 | ||
|
|
36537c981c | ||
|
|
c85978a4e3 | ||
|
|
3ad443dc2a | ||
|
|
da16ee277c | ||
|
|
0f51ddd0bd | ||
|
|
aaa72e769f | ||
|
|
0e8fdb381a | ||
|
|
0b31c40c2b | ||
|
|
2b3df4e901 | ||
|
|
807f01ba72 | ||
|
|
03f18451f7 | ||
|
|
16c3d418eb | ||
|
|
55df5fe04c | ||
|
|
b0ba3b5dd8 | ||
|
|
05d21c0a14 | ||
|
|
26a703c68c | ||
|
|
6c3dd265ab | ||
|
|
c04e207821 | ||
|
|
67e0bf02e2 | ||
|
|
7302dc8bd7 | ||
|
|
bb7383a301 | ||
|
|
61a69d8536 | ||
|
|
5a11fcea5b | ||
|
|
05775f0bfa | ||
|
|
973a1391d7 | ||
|
|
5d45649096 | ||
|
|
e91c4417cb | ||
|
|
ff3e6feeb6 | ||
|
|
0e2a83bc7b | ||
|
|
c84dbd02e5 | ||
|
|
c0aad5effa | ||
|
|
e0234dfc00 | ||
|
|
7c9385beab | ||
|
|
4c6601d778 | ||
|
|
e3a951b33b | ||
|
|
97192602d8 | ||
|
|
604957b3e2 | ||
|
|
bb731e7890 | ||
|
|
c81d13395b | ||
|
|
18bc0a75b8 | ||
|
|
f1a43ee520 | ||
|
|
b73bca237d | ||
|
|
e7ff0d1898 | ||
|
|
880df2536d | ||
|
|
09b6929100 | ||
|
|
9afcf3acc9 | ||
|
|
d7cd7096d0 | ||
|
|
5d1b66dde3 | ||
|
|
96364dc189 | ||
|
|
a816818e3f |
@@ -1,3 +1,5 @@
|
||||
.pio
|
||||
.vscode
|
||||
*.o
|
||||
obj/
|
||||
bin/
|
||||
|
||||
@@ -4,6 +4,3 @@
|
||||
[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
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
* 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, uint8_t length)
|
||||
uint8_t CCWIdTX::write(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
::memset(m_poBuffer, 0x00U, 1000U * sizeof(uint8_t));
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
* Copyright (C) 2016,2020 by Colin Durbridge G4EML
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
|
||||
void process();
|
||||
|
||||
uint8_t write(const uint8_t* data, uint8_t length);
|
||||
uint8_t write(const uint8_t* data, uint16_t length);
|
||||
|
||||
void reset();
|
||||
|
||||
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -18,6 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CalDMR.h"
|
||||
|
||||
@@ -208,7 +211,7 @@ void CCalDMR::dmrdmo1k()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
|
||||
uint8_t CCalDMR::write(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != 1U)
|
||||
return 4U;
|
||||
@@ -221,3 +224,5 @@ uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,10 +17,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#if !defined(CALDMR_H)
|
||||
#define CALDMR_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DMRDefines.h"
|
||||
|
||||
enum DMRCAL1K {
|
||||
@@ -41,7 +44,7 @@ public:
|
||||
void createData1k(uint8_t n);
|
||||
void createDataDMO1k(uint8_t n);
|
||||
|
||||
uint8_t write(const uint8_t* data, uint8_t length);
|
||||
uint8_t write(const uint8_t* data, uint16_t length);
|
||||
|
||||
private:
|
||||
bool m_transmit;
|
||||
@@ -53,3 +56,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2016,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CalDStarRX.h"
|
||||
#include "Utils.h"
|
||||
@@ -24,7 +27,7 @@
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
const uint32_t PLLMAX = 0x10000U;
|
||||
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
|
||||
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
const uint32_t INC = PLLINC / 32U;
|
||||
|
||||
// D-Star bit order version of 0x55 0x2D 0x16
|
||||
@@ -126,3 +129,5 @@ void CCalDStarRX::process(q15_t value)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,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
|
||||
@@ -16,10 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
|
||||
#if !defined(CALDSTARRX_H)
|
||||
#define CALDSTARRX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DStarDefines.h"
|
||||
|
||||
class CCalDStarRX {
|
||||
@@ -40,3 +43,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2016,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CalDStarTX.h"
|
||||
|
||||
@@ -162,7 +165,7 @@ void CCalDStarTX::process()
|
||||
m_count = (m_count + 1U) % (30U * 21U);
|
||||
}
|
||||
|
||||
uint8_t CCalDStarTX::write(const uint8_t* data, uint8_t length)
|
||||
uint8_t CCalDStarTX::write(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != 1U)
|
||||
return 4U;
|
||||
@@ -181,3 +184,5 @@ uint8_t CCalDStarTX::write(const uint8_t* data, uint8_t length)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+8
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,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
|
||||
@@ -16,17 +16,20 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
|
||||
#if !defined(CALDSTARTX_H)
|
||||
#define CALDSTARTX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DStarDefines.h"
|
||||
|
||||
class CCalDStarTX {
|
||||
public:
|
||||
CCalDStarTX();
|
||||
|
||||
uint8_t write(const uint8_t* data, uint8_t length);
|
||||
uint8_t write(const uint8_t* data, uint16_t length);
|
||||
|
||||
void process();
|
||||
|
||||
@@ -37,3 +40,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
* Copyright (C) 2020 by Phil Taylor M0VSE
|
||||
*
|
||||
@@ -19,6 +19,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CalFM.h"
|
||||
|
||||
@@ -52,7 +55,7 @@ void CCalFM::process()
|
||||
{
|
||||
const TONE_TABLE* entry = NULL;
|
||||
|
||||
if (m_modemState!=m_lastState)
|
||||
if (m_modemState != m_lastState)
|
||||
{
|
||||
switch (m_modemState) {
|
||||
case STATE_FMCAL10K:
|
||||
@@ -116,7 +119,7 @@ void CCalFM::process()
|
||||
}
|
||||
|
||||
|
||||
uint8_t CCalFM::write(const uint8_t* data, uint8_t length)
|
||||
uint8_t CCalFM::write(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != 1U)
|
||||
return 4U;
|
||||
@@ -125,3 +128,6 @@ uint8_t CCalFM::write(const uint8_t* data, uint8_t length)
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2015,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
* Copyright (C) 2020 by Phil Taylor M0VSE
|
||||
*
|
||||
@@ -18,11 +18,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(CALFM_H)
|
||||
#define CALFM_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
class CCalFM {
|
||||
public:
|
||||
CCalFM();
|
||||
@@ -35,7 +37,7 @@ public:
|
||||
void fm25kcal();
|
||||
void fm30kcal();
|
||||
|
||||
uint8_t write(const uint8_t* data, uint8_t length);
|
||||
uint8_t write(const uint8_t* data, uint16_t length);
|
||||
|
||||
private:
|
||||
uint16_t m_frequency;
|
||||
@@ -49,3 +51,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-1
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CalNXDN.h"
|
||||
|
||||
@@ -79,7 +83,7 @@ void CCalNXDN::process()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CCalNXDN::write(const uint8_t* data, uint8_t length)
|
||||
uint8_t CCalNXDN::write(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != 1U)
|
||||
return 4U;
|
||||
@@ -92,3 +96,5 @@ uint8_t CCalNXDN::write(const uint8_t* data, uint8_t length)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,11 +17,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
|
||||
#if !defined(CALNXDN_H)
|
||||
#define CALNXDN_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
enum NXDNCAL1K {
|
||||
NXDNCAL1K_IDLE,
|
||||
NXDNCAL1K_TX
|
||||
@@ -32,7 +35,7 @@ public:
|
||||
|
||||
void process();
|
||||
|
||||
uint8_t write(const uint8_t* data, uint8_t length);
|
||||
uint8_t write(const uint8_t* data, uint16_t length);
|
||||
|
||||
private:
|
||||
bool m_transmit;
|
||||
@@ -42,3 +45,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-1
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_P25)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CalP25.h"
|
||||
|
||||
@@ -82,7 +86,7 @@ void CCalP25::process()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CCalP25::write(const uint8_t* data, uint8_t length)
|
||||
uint8_t CCalP25::write(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != 1U)
|
||||
return 4U;
|
||||
@@ -95,3 +99,5 @@ uint8_t CCalP25::write(const uint8_t* data, uint8_t length)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +17,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_P25)
|
||||
|
||||
#if !defined(CALP25_H)
|
||||
#define CALP25_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "P25Defines.h"
|
||||
|
||||
enum P25CAL1K {
|
||||
@@ -34,7 +38,7 @@ public:
|
||||
|
||||
void process();
|
||||
|
||||
uint8_t write(const uint8_t* data, uint8_t length);
|
||||
uint8_t write(const uint8_t* data, uint16_t length);
|
||||
|
||||
private:
|
||||
bool m_transmit;
|
||||
@@ -43,3 +47,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+8
-2
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2019 by Florian Wolters DF2ET
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,10 +18,12 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "CalPOCSAG.h"
|
||||
|
||||
|
||||
CCalPOCSAG::CCalPOCSAG() :
|
||||
m_state(POCSAGCAL_IDLE)
|
||||
{
|
||||
@@ -38,7 +41,7 @@ void CCalPOCSAG::process()
|
||||
pocsagTX.writeByte(0xAAU);
|
||||
}
|
||||
|
||||
uint8_t CCalPOCSAG::write(const uint8_t* data, uint8_t length)
|
||||
uint8_t CCalPOCSAG::write(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != 1U)
|
||||
return 4U;
|
||||
@@ -47,3 +50,6 @@ uint8_t CCalPOCSAG::write(const uint8_t* data, uint8_t length)
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+9
-3
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2019 by Florian Wolters DF2ET
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,11 +17,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
|
||||
#if !defined(CALPOCSAG_H)
|
||||
#define CALPOCSAG_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
enum POCSAGCAL {
|
||||
POCSAGCAL_IDLE,
|
||||
POCSAGCAL_TX
|
||||
@@ -32,10 +35,13 @@ public:
|
||||
|
||||
void process();
|
||||
|
||||
uint8_t write(const uint8_t* data, uint8_t length);
|
||||
uint8_t write(const uint8_t* data, uint16_t length);
|
||||
|
||||
private:
|
||||
POCSAGCAL m_state;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2025 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,31 @@
|
||||
#if !defined(CONFIG_H)
|
||||
#define CONFIG_H
|
||||
|
||||
// Allow for the selection of which modes to compile into the firmware. This is particularly useful for processors
|
||||
// which have limited code space and processing power.
|
||||
|
||||
// Enable D-Star support.
|
||||
#define MODE_DSTAR
|
||||
|
||||
// Enable DMR support.
|
||||
#define MODE_DMR
|
||||
|
||||
// Enable System Fusion support.
|
||||
#define MODE_YSF
|
||||
|
||||
// Enable P25 phase 1 support.
|
||||
#define MODE_P25
|
||||
|
||||
// Enable NXDN support, the boxcar filter sometimes improves the performance of NXDN receive on some systems.
|
||||
#define MODE_NXDN
|
||||
#define USE_NXDN_BOXCAR
|
||||
|
||||
// Enable POCSAG support.
|
||||
#define MODE_POCSAG
|
||||
|
||||
// Enable FM support.
|
||||
#define MODE_FM
|
||||
|
||||
// Allow for the use of high quality external clock oscillators
|
||||
// The number is the frequency of the oscillator in Hertz.
|
||||
//
|
||||
@@ -35,22 +60,20 @@
|
||||
// For 19.2 MHz
|
||||
// #define EXTERNAL_OSC 19200000
|
||||
|
||||
// Allow the use of the COS line to lockout the modem
|
||||
// #define USE_COS_AS_LOCKOUT
|
||||
// Select a baud rate for host communication. The faster speeds are needed for external FM to work.
|
||||
// #define SERIAL_SPEED 115200 // Suitable for most older boards (Arduino Due, etc). External FM will NOT work with this!
|
||||
// #define SERIAL_SPEED 230400 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM might work with this
|
||||
#define SERIAL_SPEED 460800 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM should work with this
|
||||
//#define SERIAL_SPEED 500000 // Used with newer boards and Armbian on AllWinner SOCs (H2, H3) that do not support 460800
|
||||
|
||||
// Use pins to output the current mode via LEDs
|
||||
// #define MODE_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
|
||||
// #define ARDUINO_DUE_ZUM_V10
|
||||
|
||||
// For the SP8NTH board
|
||||
// #define ARDUINO_DUE_NTH
|
||||
@@ -66,10 +89,16 @@
|
||||
// #define VK6MST_TEENSY_PI3_SHIELD_I2C
|
||||
|
||||
// Pass RSSI information to the host
|
||||
// #define SEND_RSSI_DATA
|
||||
#define SEND_RSSI_DATA
|
||||
|
||||
// Use the modem as a serial repeater for Nextion displays
|
||||
// #define SERIAL_REPEATER
|
||||
#define SERIAL_REPEATER
|
||||
|
||||
// Set the baud rate of the modem serial repeater for Nextion displays
|
||||
#define SERIAL_REPEATER_BAUD_RATE 9600
|
||||
|
||||
// Use the modem as an I2C repeater for OLED displays
|
||||
// #define I2C_REPEATER
|
||||
|
||||
// To reduce CPU load, you can remove the DC blocker by commenting out the next line
|
||||
#define USE_DCBLOCKER
|
||||
@@ -82,9 +111,10 @@
|
||||
// #define USE_ALTERNATE_NXDN_LEDS
|
||||
|
||||
// Use the D-Star and DMR LEDs for POCSAG
|
||||
// #define USE_ALTERNATE_POCSAG_LEDS
|
||||
#define USE_ALTERNATE_POCSAG_LEDS
|
||||
|
||||
// Use the D-Star and YSF LEDs for FM
|
||||
#define USE_ALTERNATE_FM_LEDS
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DMRDMORX.h"
|
||||
#include "DMRSlotType.h"
|
||||
@@ -423,3 +426,6 @@ void CDMRDMORX::writeRSSIData(uint8_t* frame)
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#if !defined(DMRDMORX_H)
|
||||
#define DMRDMORX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DMRDefines.h"
|
||||
|
||||
const uint16_t DMO_BUFFER_LENGTH_SAMPLES = 1440U; // 60ms at 24 kHz
|
||||
@@ -67,3 +70,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+8
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||
*
|
||||
@@ -19,6 +19,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DMRSlotType.h"
|
||||
|
||||
@@ -74,7 +77,7 @@ void CDMRDMOTX::process()
|
||||
m_poLen = m_txDelay;
|
||||
} else {
|
||||
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++)
|
||||
m_poBuffer[i] = m_fifo.get();
|
||||
m_fifo.get(m_poBuffer[i]);
|
||||
|
||||
for (unsigned int i = 0U; i < 39U; i++)
|
||||
m_poBuffer[i + DMR_FRAME_LENGTH_BYTES] = PR_FILL[i];
|
||||
@@ -104,7 +107,7 @@ void CDMRDMOTX::process()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length)
|
||||
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
||||
return 4U;
|
||||
@@ -161,3 +164,5 @@ void CDMRDMOTX::setTXDelay(uint8_t delay)
|
||||
m_txDelay = 1200U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+10
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,19 +17,22 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#if !defined(DMRDMOTX_H)
|
||||
#define DMRDMOTX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DMRDefines.h"
|
||||
|
||||
#include "SerialRB.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
class CDMRDMOTX {
|
||||
public:
|
||||
CDMRDMOTX();
|
||||
|
||||
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
||||
|
||||
void process();
|
||||
|
||||
@@ -38,7 +41,7 @@ public:
|
||||
uint8_t getSpace() const;
|
||||
|
||||
private:
|
||||
CSerialRB m_fifo;
|
||||
CRingBuffer<uint8_t> m_fifo;
|
||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||
uint8_t m_poBuffer[1200U];
|
||||
@@ -51,3 +54,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DMRIdleRX.h"
|
||||
#include "DMRSlotType.h"
|
||||
@@ -209,3 +212,6 @@ void CDMRIdleRX::setColorCode(uint8_t colorCode)
|
||||
{
|
||||
m_colorCode = colorCode;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#if !defined(DMRIDLERX_H)
|
||||
#define DMRIDLERX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DMRDefines.h"
|
||||
|
||||
class CDMRIdleRX {
|
||||
@@ -49,3 +52,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DMRRX.h"
|
||||
|
||||
@@ -68,3 +71,5 @@ void CDMRRX::reset()
|
||||
m_slot2RX.reset();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,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
|
||||
@@ -16,10 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#if !defined(DMRRX_H)
|
||||
#define DMRRX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DMRSlotRX.h"
|
||||
|
||||
class CDMRRX {
|
||||
@@ -40,3 +43,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DMRSlotRX.h"
|
||||
#include "DMRSlotType.h"
|
||||
@@ -400,3 +403,6 @@ void CDMRSlotRX::writeRSSIData(uint8_t* frame)
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+8
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#if !defined(DMRSLOTRX_H)
|
||||
#define DMRSLOTRX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DMRDefines.h"
|
||||
|
||||
enum DMRRX_STATE {
|
||||
@@ -70,3 +73,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DMRSlotType.h"
|
||||
|
||||
@@ -285,3 +288,5 @@ void CDMRSlotType::encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) c
|
||||
frame[20U] = (frame[20U] & 0x03U) | ((slotType[1U] << 6) & 0xC0U) | ((slotType[2U] >> 2) & 0x3CU);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,6 +16,10 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#if !defined(DMRSLOTTYPE_H)
|
||||
#define DMRSLOTTYPE_H
|
||||
|
||||
@@ -35,3 +39,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2022,2023,2026 by Adrian Musceac YO8RZZ
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +20,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DMRSlotType.h"
|
||||
|
||||
@@ -39,6 +43,12 @@ const uint8_t IDLE_DATA[] =
|
||||
0x36U, 0x00U, 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U, 0x03U, 0xF6U,
|
||||
0xE4U, 0x65U, 0x17U, 0x1BU, 0x48U, 0xCAU, 0x6DU, 0x4FU, 0xC6U, 0x10U, 0xB4U};
|
||||
|
||||
// DT Terminator with LC, empty
|
||||
const uint8_t TERMINATOR_DATA[] =
|
||||
{0x00U, 0xCCU, 0x01U, 0x80U, 0x01U, 0x94U, 0x01U, 0x48U, 0x08U, 0xB0U, 0x08U,
|
||||
0x80U, 0x04U, 0xADU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD9U, 0x65U, 0x90U,
|
||||
0x01U, 0x78U, 0x00U, 0xD0U, 0x08U, 0x40U, 0x14U, 0x00U, 0x0DU, 0x80U, 0x15U};
|
||||
|
||||
const uint8_t CACH_INTERLEAVE[] =
|
||||
{ 1U, 2U, 3U, 5U, 6U, 7U, 9U, 10U, 11U, 13U, 15U, 16U, 17U, 19U, 20U, 21U, 23U,
|
||||
25U, 26U, 27U, 29U, 30U, 31U, 33U, 34U, 35U, 37U, 39U, 40U, 41U, 43U, 44U, 45U, 47U,
|
||||
@@ -62,6 +72,7 @@ m_modFilter(),
|
||||
m_modState(),
|
||||
m_state(DMRTXSTATE_IDLE),
|
||||
m_idle(),
|
||||
m_aloha(),
|
||||
m_cachPtr(0U),
|
||||
m_shortLC(),
|
||||
m_newShortLC(),
|
||||
@@ -71,7 +82,9 @@ m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_frameCount(0U),
|
||||
m_abortCount(),
|
||||
m_abort()
|
||||
m_abort(),
|
||||
m_controlChannel(false),
|
||||
m_trunking(false)
|
||||
{
|
||||
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
|
||||
|
||||
@@ -144,7 +157,7 @@ void CDMRTX::process()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CDMRTX::writeData1(const uint8_t* data, uint8_t length)
|
||||
uint8_t CDMRTX::writeData1(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
||||
return 4U;
|
||||
@@ -168,7 +181,7 @@ uint8_t CDMRTX::writeData1(const uint8_t* data, uint8_t length)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
uint8_t CDMRTX::writeData2(const uint8_t* data, uint8_t length)
|
||||
uint8_t CDMRTX::writeData2(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
||||
return 4U;
|
||||
@@ -192,7 +205,7 @@ uint8_t CDMRTX::writeData2(const uint8_t* data, uint8_t length)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length)
|
||||
uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != 9U)
|
||||
return 4U;
|
||||
@@ -208,7 +221,18 @@ uint8_t CDMRTX::writeShortLC(const uint8_t* data, uint8_t length)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint8_t length)
|
||||
uint8_t CDMRTX::writeAloha(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != DMR_FRAME_LENGTH_BYTES)
|
||||
return 4U;
|
||||
|
||||
::memcpy(m_aloha, data, length);
|
||||
m_controlChannel = true;
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
uint8_t CDMRTX::writeAbort(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != 1U)
|
||||
return 4U;
|
||||
@@ -291,16 +315,20 @@ uint8_t CDMRTX::getSpace2() const
|
||||
|
||||
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++) {
|
||||
m_poBuffer[i] = m_fifo[slotIndex].get();
|
||||
m_fifo[slotIndex].get(m_poBuffer[i]);
|
||||
m_markBuffer[i] = MARK_NONE;
|
||||
}
|
||||
} else {
|
||||
m_abort[slotIndex] = false;
|
||||
// Transmit an idle message
|
||||
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
|
||||
m_poBuffer[i] = m_idle[i];
|
||||
if ((slotIndex == 0U) && m_controlChannel && m_trunking)
|
||||
m_poBuffer[i] = m_aloha[i];
|
||||
else
|
||||
m_poBuffer[i] = m_idle[i];
|
||||
|
||||
m_markBuffer[i] = MARK_NONE;
|
||||
}
|
||||
}
|
||||
@@ -351,10 +379,14 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
|
||||
m_cachPtr = 0U;
|
||||
|
||||
if (m_cachPtr == 0U) {
|
||||
if (m_fifo[0U].getData() == 0U && m_fifo[1U].getData() == 0U)
|
||||
::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U);
|
||||
else
|
||||
if ((m_fifo[0U].getData() == 0U) && (m_fifo[1U].getData() == 0U)) {
|
||||
if (m_trunking)
|
||||
::memcpy(m_shortLC, m_newShortLC, 12U);
|
||||
else
|
||||
::memcpy(m_shortLC, EMPTY_SHORT_LC, 12U);
|
||||
} else {
|
||||
::memcpy(m_shortLC, m_newShortLC, 12U);
|
||||
}
|
||||
}
|
||||
|
||||
::memcpy(m_poBuffer, m_shortLC + m_cachPtr, 3U);
|
||||
@@ -364,8 +396,8 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
|
||||
|
||||
bool at = false;
|
||||
if (m_frameCount >= STARTUP_COUNT)
|
||||
at = m_fifo[rxSlotIndex].getData() > 0U;
|
||||
bool tc = txSlotIndex == 1U;
|
||||
at = (m_fifo[rxSlotIndex].getData() > 0U);
|
||||
bool tc = (txSlotIndex == 1U);
|
||||
bool ls0 = true; // For 1 and 2
|
||||
bool ls1 = true;
|
||||
|
||||
@@ -394,10 +426,18 @@ void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
|
||||
|
||||
void CDMRTX::setColorCode(uint8_t colorCode)
|
||||
{
|
||||
::memcpy(m_idle, IDLE_DATA, DMR_FRAME_LENGTH_BYTES);
|
||||
if (m_trunking)
|
||||
::memcpy(m_idle, TERMINATOR_DATA, DMR_FRAME_LENGTH_BYTES);
|
||||
else
|
||||
::memcpy(m_idle, IDLE_DATA, DMR_FRAME_LENGTH_BYTES);
|
||||
|
||||
CDMRSlotType slotType;
|
||||
slotType.encode(colorCode, DT_IDLE, m_idle);
|
||||
if (m_trunking) {
|
||||
slotType.encode(colorCode, DT_TERMINATOR_WITH_LC, m_idle);
|
||||
slotType.encode(colorCode, DT_CSBK, m_aloha);
|
||||
} else {
|
||||
slotType.encode(colorCode, DT_IDLE, m_idle);
|
||||
}
|
||||
}
|
||||
|
||||
void CDMRTX::resetFifo1()
|
||||
@@ -414,3 +454,10 @@ uint32_t CDMRTX::getFrameCount()
|
||||
{
|
||||
return m_frameCount;
|
||||
}
|
||||
|
||||
void CDMRTX::setTrunking(bool trunking)
|
||||
{
|
||||
m_trunking = trunking;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
* Copyright (C) 2026 by Adrian Musceac YO8RZZ
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,13 +18,16 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
|
||||
#if !defined(DMRTX_H)
|
||||
#define DMRTX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DMRDefines.h"
|
||||
|
||||
#include "SerialRB.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
enum DMRTXSTATE {
|
||||
DMRTXSTATE_IDLE,
|
||||
@@ -38,14 +42,16 @@ class CDMRTX {
|
||||
public:
|
||||
CDMRTX();
|
||||
|
||||
uint8_t writeData1(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeData2(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeData1(const uint8_t* data, uint16_t length);
|
||||
uint8_t writeData2(const uint8_t* data, uint16_t length);
|
||||
|
||||
uint8_t writeShortLC(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeAbort(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeShortLC(const uint8_t* data, uint16_t length);
|
||||
uint8_t writeAloha(const uint8_t* data, uint16_t length);
|
||||
uint8_t writeAbort(const uint8_t* data, uint16_t length);
|
||||
|
||||
void setStart(bool start);
|
||||
void setCal(bool start);
|
||||
void setTrunking(bool trunking);
|
||||
|
||||
void process();
|
||||
|
||||
@@ -59,11 +65,12 @@ public:
|
||||
void setColorCode(uint8_t colorCode);
|
||||
|
||||
private:
|
||||
CSerialRB m_fifo[2U];
|
||||
CRingBuffer<uint8_t> m_fifo[2U];
|
||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||
DMRTXSTATE m_state;
|
||||
uint8_t m_idle[DMR_FRAME_LENGTH_BYTES];
|
||||
uint8_t m_aloha[DMR_FRAME_LENGTH_BYTES];
|
||||
uint8_t m_cachPtr;
|
||||
uint8_t m_shortLC[12U];
|
||||
uint8_t m_newShortLC[12U];
|
||||
@@ -74,6 +81,8 @@ private:
|
||||
uint32_t m_frameCount;
|
||||
uint32_t m_abortCount[2U];
|
||||
bool m_abort[2U];
|
||||
bool m_controlChannel;
|
||||
bool m_trunking;
|
||||
|
||||
void createData(uint8_t slotIndex);
|
||||
void createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex);
|
||||
@@ -83,3 +92,4 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+37
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2015,2017,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,30 +19,50 @@
|
||||
#if !defined(DSTARDEFINES_H)
|
||||
#define DSTARDEFINES_H
|
||||
|
||||
const unsigned int DSTAR_RADIO_BIT_LENGTH = 5U; // At 24 kHz sample rate
|
||||
const unsigned int DSTAR_RADIO_SYMBOL_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_HEADER_LENGTH_BYTES = 41U;
|
||||
|
||||
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
|
||||
const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U;
|
||||
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
|
||||
const unsigned int DSTAR_FEC_SECTION_LENGTH_SYMBOLS = 660U;
|
||||
const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
|
||||
const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U;
|
||||
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
|
||||
const unsigned int DSTAR_DATA_LENGTH_SYMBOLS = DSTAR_DATA_LENGTH_BYTES * 8U;
|
||||
const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U;
|
||||
const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U;
|
||||
const unsigned int DSTAR_END_SYNC_LENGTH_BYTES = 6U;
|
||||
const unsigned int DSTAR_END_SYNC_LENGTH_BITS = DSTAR_END_SYNC_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 unsigned int DSTAR_FRAME_SYNC_LENGTH_BYTES = 3U;
|
||||
const unsigned int DSTAR_FRAME_SYNC_LENGTH_SYMBOLS = DSTAR_FRAME_SYNC_LENGTH_BYTES * 8U;
|
||||
const unsigned int DSTAR_FRAME_SYNC_LENGTH_SAMPLES = DSTAR_FRAME_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
|
||||
const unsigned int DSTAR_DATA_SYNC_LENGTH_BYTES = 3U;
|
||||
const unsigned int DSTAR_DATA_SYNC_LENGTH_SYMBOLS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
|
||||
const unsigned int DSTAR_DATA_SYNC_LENGTH_SAMPLES = DSTAR_DATA_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
|
||||
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
|
||||
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
|
||||
|
||||
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
|
||||
// D-Star bit order version of 0x55 0x6E 0x0A
|
||||
const uint32_t DSTAR_FRAME_SYNC_DATA = 0x00557650U;
|
||||
const uint32_t DSTAR_FRAME_SYNC_MASK = 0x00FFFFFFU;
|
||||
const bool DSTAR_FRAME_SYNC_SYMBOLS[] = {false, true, false, true, false, true, false, true, false, true, true, true, false, true, true, false, false, true, false, true, false, false, false, false};
|
||||
|
||||
// D-Star bit order version of 0x55 0x2D 0x16
|
||||
const uint32_t DSTAR_DATA_SYNC_DATA = 0x00AAB468U;
|
||||
const uint32_t DSTAR_DATA_SYNC_MASK = 0x00FFFFFFU;
|
||||
const bool DSTAR_DATA_SYNC_SYMBOLS[] = {true, false, true, false, true, false, true, false, true, false, true, true, false, true, false, false, false, true, true, false, true, false, false, false};
|
||||
|
||||
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
|
||||
const uint32_t DSTAR_END_SYNC_DATA = 0xAAAA135EU;
|
||||
const uint32_t DSTAR_END_SYNC_MASK = 0xFFFFFFFFU;
|
||||
const uint8_t DSTAR_END_SYNC_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
|
||||
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
|
||||
|
||||
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+249
-142
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -18,31 +18,28 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DStarRX.h"
|
||||
#include "Utils.h"
|
||||
|
||||
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;
|
||||
const unsigned int MAX_FRAMES = 150U;
|
||||
|
||||
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
|
||||
const uint32_t FRAME_SYNC_DATA = 0x00557650U;
|
||||
const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU;
|
||||
const uint64_t FRAME_SYNC_DATA = 0x0000000000557650U;
|
||||
const uint64_t FRAME_SYNC_MASK = 0x0000000000FFFFFFU;
|
||||
const uint8_t FRAME_SYNC_ERRS = 2U;
|
||||
|
||||
// D-Star bit order version of 0x55 0x2D 0x16
|
||||
const uint32_t DATA_SYNC_DATA = 0x00AAB468U;
|
||||
const uint32_t DATA_SYNC_MASK = 0x00FFFFFFU;
|
||||
const uint64_t DATA_SYNC_DATA = 0x0000000000AAB468U;
|
||||
const uint64_t DATA_SYNC_MASK = 0x0000000000FFFFFFU;
|
||||
const uint8_t DATA_SYNC_ERRS = 2U;
|
||||
|
||||
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
|
||||
const uint32_t END_SYNC_DATA = 0xAAAA135EU;
|
||||
const uint32_t END_SYNC_MASK = 0xFFFFFFFFU;
|
||||
const uint64_t END_SYNC_DATA = 0x0000AAAAAAAA135EU;
|
||||
const uint64_t END_SYNC_MASK = 0x0000FFFFFFFFFFFFU;
|
||||
const uint8_t END_SYNC_ERRS = 1U;
|
||||
|
||||
const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
|
||||
@@ -237,14 +234,24 @@ const uint16_t CCITT_TABLE[] = {
|
||||
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
|
||||
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U};
|
||||
|
||||
const uint16_t NOENDPTR = 9999U;
|
||||
|
||||
CDStarRX::CDStarRX() :
|
||||
m_pll(0U),
|
||||
m_prev(false),
|
||||
m_rxState(DSRXS_NONE),
|
||||
m_patternBuffer(0x00U),
|
||||
m_rxBuffer(),
|
||||
m_rxBufferBits(0U),
|
||||
m_dataBits(0U),
|
||||
m_bitBuffer(),
|
||||
m_headerBuffer(),
|
||||
m_dataBuffer(),
|
||||
m_bitPtr(0U),
|
||||
m_headerPtr(0U),
|
||||
m_dataPtr(0U),
|
||||
m_startPtr(NOENDPTR),
|
||||
m_syncPtr(NOENDPTR),
|
||||
m_minSyncPtr(NOENDPTR),
|
||||
m_maxSyncPtr(NOENDPTR),
|
||||
m_maxFrameCorr(0),
|
||||
m_maxDataCorr(0),
|
||||
m_frameCount(0U),
|
||||
m_countdown(0U),
|
||||
m_mar(0U),
|
||||
m_pathMetric(),
|
||||
m_pathMemory0(),
|
||||
@@ -259,14 +266,20 @@ m_rssiCount(0U)
|
||||
|
||||
void CDStarRX::reset()
|
||||
{
|
||||
m_pll = 0U;
|
||||
m_prev = false;
|
||||
m_rxState = DSRXS_NONE;
|
||||
m_patternBuffer = 0x00U;
|
||||
m_rxBufferBits = 0U;
|
||||
m_dataBits = 0U;
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
m_rxState = DSRXS_NONE;
|
||||
m_headerPtr = 0U;
|
||||
m_dataPtr = 0U;
|
||||
m_bitPtr = 0U;
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
m_startPtr = NOENDPTR;
|
||||
m_syncPtr = NOENDPTR;
|
||||
m_minSyncPtr = NOENDPTR;
|
||||
m_maxSyncPtr = NOENDPTR;
|
||||
m_frameCount = 0U;
|
||||
m_countdown = 0U;
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
||||
@@ -275,125 +288,117 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt
|
||||
m_rssiAccum += rssi[i];
|
||||
m_rssiCount++;
|
||||
|
||||
bool bit = samples[i] < 0;
|
||||
q15_t sample = samples[i];
|
||||
|
||||
if (bit != m_prev) {
|
||||
if (m_pll < (PLLMAX / 2U))
|
||||
m_pll += INC;
|
||||
else
|
||||
m_pll -= INC;
|
||||
m_bitBuffer[m_bitPtr] <<= 1;
|
||||
if (sample < 0)
|
||||
m_bitBuffer[m_bitPtr] |= 0x01U;
|
||||
|
||||
m_dataBuffer[m_dataPtr] = sample;
|
||||
|
||||
switch (m_rxState) {
|
||||
case DSRXS_HEADER:
|
||||
processHeader(sample);
|
||||
break;
|
||||
case DSRXS_DATA:
|
||||
processData();
|
||||
break;
|
||||
default:
|
||||
processNone(sample);
|
||||
break;
|
||||
}
|
||||
|
||||
m_prev = bit;
|
||||
m_dataPtr++;
|
||||
if (m_dataPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
m_dataPtr = 0U;
|
||||
|
||||
m_pll += PLLINC;
|
||||
|
||||
if (m_pll >= PLLMAX) {
|
||||
m_pll -= PLLMAX;
|
||||
|
||||
switch (m_rxState) {
|
||||
case DSRXS_NONE:
|
||||
processNone(bit);
|
||||
break;
|
||||
case DSRXS_HEADER:
|
||||
processHeader(bit);
|
||||
break;
|
||||
case DSRXS_DATA:
|
||||
processData(bit);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_bitPtr++;
|
||||
if (m_bitPtr >= DSTAR_RADIO_SYMBOL_LENGTH)
|
||||
m_bitPtr = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CDStarRX::processNone(bool bit)
|
||||
void CDStarRX::processNone(q15_t sample)
|
||||
{
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
m_patternBuffer |= 0x01U;
|
||||
|
||||
// Fuzzy matching of the frame sync sequence
|
||||
if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
|
||||
DEBUG1("DStarRX: found frame sync in None");
|
||||
bool ret = correlateFrameSync();
|
||||
if (ret) {
|
||||
m_countdown = 5U;
|
||||
|
||||
::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES);
|
||||
m_rxBufferBits = 0U;
|
||||
m_headerBuffer[m_headerPtr] = sample;
|
||||
m_headerPtr++;
|
||||
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
|
||||
m_rxState = DSRXS_HEADER;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Exact matching of the data sync bit sequence
|
||||
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) {
|
||||
// Fuzzy matching of the data sync bit sequence
|
||||
ret = correlateDataSync();
|
||||
if (ret) {
|
||||
DEBUG1("DStarRX: found data sync in None");
|
||||
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
// 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;
|
||||
m_rxState = DSRXS_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
void CDStarRX::processHeader(bool bit)
|
||||
void CDStarRX::processHeader(q15_t sample)
|
||||
{
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
m_patternBuffer |= 0x01U;
|
||||
if (m_countdown > 0U) {
|
||||
correlateFrameSync();
|
||||
m_countdown--;
|
||||
}
|
||||
|
||||
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
||||
m_rxBufferBits++;
|
||||
m_headerBuffer[m_headerPtr] = sample;
|
||||
m_headerPtr++;
|
||||
|
||||
// A full FEC header
|
||||
if (m_rxBufferBits == DSTAR_FEC_SECTION_LENGTH_BITS) {
|
||||
// Process the scrambling, interleaving and FEC, then return if the chcksum was correct
|
||||
unsigned char header[DSTAR_HEADER_LENGTH_BYTES];
|
||||
bool ok = rxHeader(m_rxBuffer, header);
|
||||
if (ok) {
|
||||
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) {
|
||||
uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES];
|
||||
samplesToBits(m_headerBuffer, DSTAR_RADIO_SYMBOL_LENGTH, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES);
|
||||
|
||||
// Process the scrambling, interleaving and FEC, then return true if the chcksum was correct
|
||||
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
|
||||
bool ok = rxHeader(buffer, header);
|
||||
if (!ok) {
|
||||
// The checksum failed, return to looking for syncs
|
||||
m_rxState = DSRXS_NONE;
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
} else {
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
writeRSSIHeader(header);
|
||||
|
||||
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||
m_rxBufferBits = 0U;
|
||||
|
||||
m_rxState = DSRXS_DATA;
|
||||
m_dataBits = MAX_SYNC_BITS;
|
||||
} else {
|
||||
// The checksum failed, return to looking for syncs
|
||||
m_rxState = DSRXS_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
// Ready to start the first data section
|
||||
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH)) {
|
||||
m_frameCount = 0U;
|
||||
m_dataPtr = 0U;
|
||||
|
||||
m_startPtr = 476U;
|
||||
m_syncPtr = 471U;
|
||||
m_maxSyncPtr = 472U;
|
||||
m_minSyncPtr = 470U;
|
||||
|
||||
DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
|
||||
|
||||
m_rxState = DSRXS_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
void CDStarRX::processData(bool bit)
|
||||
void CDStarRX::processData()
|
||||
{
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
m_patternBuffer |= 0x01U;
|
||||
|
||||
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
||||
m_rxBufferBits++;
|
||||
|
||||
// Fuzzy matching of the end frame sequences
|
||||
if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) {
|
||||
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= END_SYNC_ERRS) {
|
||||
DEBUG1("DStarRX: Found end sync in Data");
|
||||
|
||||
io.setDecode(false);
|
||||
@@ -401,35 +406,24 @@ void CDStarRX::processData(bool bit)
|
||||
|
||||
serial.writeDStarEOT();
|
||||
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
|
||||
m_rxState = DSRXS_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fuzzy matching of the data sync bit sequence
|
||||
bool syncSeen = false;
|
||||
if (m_rxBufferBits >= (DSTAR_DATA_LENGTH_BITS - 3U)) {
|
||||
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) {
|
||||
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS;
|
||||
m_dataBits = MAX_SYNC_BITS;
|
||||
syncSeen = true;
|
||||
}
|
||||
if (m_minSyncPtr < m_maxSyncPtr) {
|
||||
if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr)
|
||||
correlateDataSync();
|
||||
} else {
|
||||
if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr)
|
||||
correlateDataSync();
|
||||
}
|
||||
|
||||
// Check to see if the sync is arriving late
|
||||
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS && !syncSeen) {
|
||||
for (uint8_t i = 1U; i <= 3U; i++) {
|
||||
uint32_t syncMask = DATA_SYNC_MASK >> i;
|
||||
uint32_t syncData = DATA_SYNC_DATA >> i;
|
||||
if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) {
|
||||
m_rxBufferBits -= i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_dataBits--;
|
||||
|
||||
if (m_dataBits == 0U) {
|
||||
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
||||
if (m_frameCount >= MAX_FRAMES) {
|
||||
DEBUG1("DStarRX: data sync timed out, lost lock");
|
||||
|
||||
io.setDecode(false);
|
||||
@@ -437,24 +431,35 @@ void CDStarRX::processData(bool bit)
|
||||
|
||||
serial.writeDStarLost();
|
||||
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
|
||||
m_rxState = DSRXS_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen
|
||||
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) {
|
||||
if (syncSeen) {
|
||||
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
|
||||
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
|
||||
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
|
||||
writeRSSIData(m_rxBuffer);
|
||||
} else {
|
||||
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
|
||||
}
|
||||
// Send a data frame to the host if the required number of bits have been received
|
||||
if (m_dataPtr == m_maxSyncPtr) {
|
||||
uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U];
|
||||
samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES);
|
||||
|
||||
// Start the next frame
|
||||
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||
m_rxBufferBits = 0U;
|
||||
if ((m_frameCount % 21U) == 0U) {
|
||||
if (m_frameCount == 0U) {
|
||||
buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
|
||||
buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
|
||||
buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
|
||||
DEBUG5("DStarRX: found start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
|
||||
}
|
||||
|
||||
writeRSSIData(buffer);
|
||||
} else {
|
||||
serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES);
|
||||
}
|
||||
|
||||
m_frameCount++;
|
||||
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,6 +505,105 @@ void CDStarRX::writeRSSIData(unsigned char* data)
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
bool CDStarRX::correlateFrameSync()
|
||||
{
|
||||
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_FRAME_SYNC_MASK) ^ DSTAR_FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
|
||||
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_FRAME_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
|
||||
|
||||
q31_t corr = 0;
|
||||
|
||||
for (uint8_t i = 0U; i < DSTAR_FRAME_SYNC_LENGTH_SYMBOLS; i++) {
|
||||
q15_t val = m_dataBuffer[ptr];
|
||||
|
||||
if (DSTAR_FRAME_SYNC_SYMBOLS[i])
|
||||
corr -= val;
|
||||
else
|
||||
corr += val;
|
||||
|
||||
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
|
||||
}
|
||||
|
||||
if (corr > m_maxFrameCorr) {
|
||||
m_maxFrameCorr = corr;
|
||||
m_headerPtr = 0U;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CDStarRX::correlateDataSync()
|
||||
{
|
||||
uint8_t maxErrs = 0U;
|
||||
if (m_rxState == DSRXS_DATA)
|
||||
maxErrs = DATA_SYNC_ERRS;
|
||||
|
||||
if (countBits64((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= maxErrs) {
|
||||
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
|
||||
|
||||
q31_t corr = 0;
|
||||
|
||||
for (uint8_t i = 0U; i < DSTAR_DATA_SYNC_LENGTH_SYMBOLS; i++) {
|
||||
q15_t val = m_dataBuffer[ptr];
|
||||
|
||||
if (DSTAR_DATA_SYNC_SYMBOLS[i])
|
||||
corr -= val;
|
||||
else
|
||||
corr += val;
|
||||
|
||||
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
|
||||
}
|
||||
|
||||
if (corr > m_maxDataCorr) {
|
||||
m_maxDataCorr = corr;
|
||||
m_frameCount = 0U;
|
||||
|
||||
m_syncPtr = m_dataPtr;
|
||||
|
||||
m_startPtr = m_dataPtr + DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
if (m_startPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
m_startPtr -= DSTAR_DATA_LENGTH_SAMPLES;
|
||||
|
||||
m_maxSyncPtr = m_syncPtr + 1U;
|
||||
if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
|
||||
|
||||
m_minSyncPtr = m_syncPtr + DSTAR_DATA_LENGTH_SAMPLES - 1U;
|
||||
if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CDStarRX::samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit)
|
||||
{
|
||||
for (uint16_t i = 0U; i < count; i++) {
|
||||
q15_t sample = inBuffer[start];
|
||||
|
||||
if (sample < 0)
|
||||
WRITE_BIT2(outBuffer, i, true);
|
||||
else
|
||||
WRITE_BIT2(outBuffer, i, false);
|
||||
|
||||
start += DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
if (start >= limit)
|
||||
start -= limit;
|
||||
}
|
||||
}
|
||||
|
||||
bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
|
||||
{
|
||||
int i;
|
||||
@@ -715,3 +819,6 @@ bool CDStarRX::checksum(const uint8_t* header) const
|
||||
|
||||
return crc8[0U] == header[DSTAR_HEADER_LENGTH_BYTES - 2U] && crc8[1U] == header[DSTAR_HEADER_LENGTH_BYTES - 1U];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
|
||||
#if !defined(DSTARRX_H)
|
||||
#define DSTARRX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "DStarDefines.h"
|
||||
|
||||
enum DSRX_STATE {
|
||||
@@ -37,13 +40,21 @@ public:
|
||||
void reset();
|
||||
|
||||
private:
|
||||
uint32_t m_pll;
|
||||
bool m_prev;
|
||||
DSRX_STATE m_rxState;
|
||||
uint32_t m_patternBuffer;
|
||||
uint8_t m_rxBuffer[100U];
|
||||
unsigned int m_rxBufferBits;
|
||||
unsigned int m_dataBits;
|
||||
uint64_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH];
|
||||
q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH];
|
||||
q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES];
|
||||
uint16_t m_bitPtr;
|
||||
uint16_t m_headerPtr;
|
||||
uint16_t m_dataPtr;
|
||||
uint16_t m_startPtr;
|
||||
uint16_t m_syncPtr;
|
||||
uint16_t m_minSyncPtr;
|
||||
uint16_t m_maxSyncPtr;
|
||||
q31_t m_maxFrameCorr;
|
||||
q31_t m_maxDataCorr;
|
||||
uint16_t m_frameCount;
|
||||
uint8_t m_countdown;
|
||||
unsigned int m_mar;
|
||||
int m_pathMetric[4U];
|
||||
unsigned int m_pathMemory0[42U];
|
||||
@@ -54,9 +65,12 @@ private:
|
||||
uint32_t m_rssiAccum;
|
||||
uint16_t m_rssiCount;
|
||||
|
||||
void processNone(bool bit);
|
||||
void processHeader(bool bit);
|
||||
void processData(bool bit);
|
||||
void processNone(q15_t sample);
|
||||
void processHeader(q15_t sample);
|
||||
void processData();
|
||||
bool correlateFrameSync();
|
||||
bool correlateDataSync();
|
||||
void samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit);
|
||||
void writeRSSIHeader(unsigned char* header);
|
||||
void writeRSSIData(unsigned char* data);
|
||||
bool rxHeader(uint8_t* in, uint8_t* out);
|
||||
@@ -68,3 +82,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+23
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -18,6 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "DStarTX.h"
|
||||
|
||||
@@ -198,7 +201,7 @@ m_txDelay(60U) // 100ms
|
||||
{
|
||||
::memset(m_modState, 0x00U, 20U * sizeof(q15_t));
|
||||
|
||||
m_modFilter.L = DSTAR_RADIO_BIT_LENGTH;
|
||||
m_modFilter.L = DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN;
|
||||
m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER;
|
||||
m_modFilter.pState = m_modState;
|
||||
@@ -217,11 +220,12 @@ void CDStarTX::process()
|
||||
m_poBuffer[m_poLen++] = BIT_SYNC;
|
||||
} else {
|
||||
// Pop the type byte off
|
||||
m_buffer.get();
|
||||
uint8_t dummy;
|
||||
m_buffer.get(dummy);
|
||||
|
||||
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
|
||||
for (uint8_t i = 0U; i < DSTAR_HEADER_LENGTH_BYTES; i++)
|
||||
header[i] = m_buffer.get();
|
||||
m_buffer.get(header[i]);
|
||||
|
||||
uint8_t buffer[86U];
|
||||
txHeader(header, buffer + 2U);
|
||||
@@ -239,21 +243,23 @@ void CDStarTX::process()
|
||||
|
||||
if (type == DSTAR_DATA && m_poLen == 0U) {
|
||||
// Pop the type byte off
|
||||
m_buffer.get();
|
||||
uint8_t dummy;
|
||||
m_buffer.get(dummy);
|
||||
|
||||
for (uint8_t i = 0U; i < DSTAR_DATA_LENGTH_BYTES; i++)
|
||||
m_poBuffer[m_poLen++] = m_buffer.get();
|
||||
m_buffer.get(m_poBuffer[m_poLen++]);
|
||||
|
||||
m_poPtr = 0U;
|
||||
}
|
||||
|
||||
if (type == DSTAR_EOT && m_poLen == 0U) {
|
||||
// Pop the type byte off
|
||||
m_buffer.get();
|
||||
uint8_t dummy;
|
||||
m_buffer.get(dummy);
|
||||
|
||||
for (uint8_t j = 0U; j < 3U; j++) {
|
||||
for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++)
|
||||
m_poBuffer[m_poLen++] = DSTAR_EOT_BYTES[i];
|
||||
for (uint8_t i = 0U; i < DSTAR_END_SYNC_LENGTH_BYTES; i++)
|
||||
m_poBuffer[m_poLen++] = DSTAR_END_SYNC_BYTES[i];
|
||||
}
|
||||
|
||||
m_poPtr = 0U;
|
||||
@@ -262,11 +268,11 @@ void CDStarTX::process()
|
||||
if (m_poLen > 0U) {
|
||||
uint16_t space = io.getSpace();
|
||||
|
||||
while (space > (8U * DSTAR_RADIO_BIT_LENGTH)) {
|
||||
while (space > (8U * DSTAR_RADIO_SYMBOL_LENGTH)) {
|
||||
uint8_t c = m_poBuffer[m_poPtr++];
|
||||
writeByte(c);
|
||||
|
||||
space -= 8U * DSTAR_RADIO_BIT_LENGTH;
|
||||
space -= 8U * DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
if (m_poPtr >= m_poLen) {
|
||||
m_poPtr = 0U;
|
||||
@@ -277,7 +283,7 @@ void CDStarTX::process()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length)
|
||||
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint16_t length)
|
||||
{
|
||||
if (length != DSTAR_HEADER_LENGTH_BYTES)
|
||||
return 4U;
|
||||
@@ -296,7 +302,7 @@ uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length)
|
||||
uint8_t CDStarTX::writeData(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != DSTAR_DATA_LENGTH_BYTES)
|
||||
return 4U;
|
||||
@@ -412,7 +418,7 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const
|
||||
void CDStarTX::writeByte(uint8_t c)
|
||||
{
|
||||
q15_t inBuffer[8U];
|
||||
q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U];
|
||||
q15_t outBuffer[DSTAR_RADIO_SYMBOL_LENGTH * 8U];
|
||||
|
||||
uint8_t mask = 0x01U;
|
||||
|
||||
@@ -427,7 +433,7 @@ void CDStarTX::writeByte(uint8_t c)
|
||||
|
||||
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U);
|
||||
|
||||
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U);
|
||||
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_SYMBOL_LENGTH * 8U);
|
||||
}
|
||||
|
||||
void CDStarTX::setTXDelay(uint8_t delay)
|
||||
@@ -443,3 +449,5 @@ uint8_t CDStarTX::getSpace() const
|
||||
return m_buffer.getSpace() / (DSTAR_DATA_LENGTH_BYTES + 1U);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,19 +16,21 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
|
||||
#if !defined(DSTARTX_H)
|
||||
#define DSTARTX_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "SerialRB.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
class CDStarTX {
|
||||
public:
|
||||
CDStarTX();
|
||||
|
||||
uint8_t writeHeader(const uint8_t* header, uint8_t length);
|
||||
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeHeader(const uint8_t* header, uint16_t length);
|
||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
||||
uint8_t writeEOT();
|
||||
|
||||
void process();
|
||||
@@ -38,7 +40,7 @@ public:
|
||||
uint8_t getSpace() const;
|
||||
|
||||
private:
|
||||
CSerialRB m_buffer;
|
||||
CRingBuffer<uint8_t> m_buffer;
|
||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||
q15_t m_modState[20U]; // blockSize + phaseLength - 1, 8 + 9 - 1 plus some spare
|
||||
uint8_t m_poBuffer[600U];
|
||||
@@ -52,3 +54,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -27,6 +27,7 @@
|
||||
#define DEBUG3(a,b,c) serial.writeDebug((a),(b),(c))
|
||||
#define DEBUG4(a,b,c,d) serial.writeDebug((a),(b),(c),(d))
|
||||
#define DEBUG5(a,b,c,d,e) serial.writeDebug((a),(b),(c),(d),(e))
|
||||
#define DEBUG_DUMP(a,b) serial.writeDebugDump((a),(b))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020,2021,2023,2025 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,39 +16,31 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#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 "RingBuffer.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
|
||||
};
|
||||
|
||||
|
||||
#include "FMDownSampler.h"
|
||||
#include "FMUpSampler.h"
|
||||
#include "FMNoiseSquelch.h"
|
||||
|
||||
|
||||
class CFM {
|
||||
public:
|
||||
CFM();
|
||||
|
||||
void samples(bool cos, const q15_t* samples, uint8_t length);
|
||||
void samples(bool cos, q15_t* samples, const uint16_t* rssi, uint8_t length);
|
||||
|
||||
void process();
|
||||
|
||||
@@ -56,15 +48,22 @@ public:
|
||||
|
||||
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);
|
||||
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
|
||||
uint8_t setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t frequency, uint8_t level);
|
||||
|
||||
uint8_t getSpace() const;
|
||||
|
||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
||||
|
||||
private:
|
||||
CFMKeyer m_callsign;
|
||||
CFMKeyer m_rfAck;
|
||||
CFMKeyer m_extAck;
|
||||
CFMCTCSSRX m_ctcssRX;
|
||||
CFMCTCSSTX m_ctcssTX;
|
||||
CFMNoiseSquelch m_squelch;
|
||||
CFMTimeout m_timeoutTone;
|
||||
FM_STATE m_state;
|
||||
uint8_t m_state;
|
||||
bool m_callsignAtStart;
|
||||
bool m_callsignAtEnd;
|
||||
bool m_callsignAtLatch;
|
||||
@@ -75,26 +74,60 @@ private:
|
||||
CFMTimer m_ackMinTimer;
|
||||
CFMTimer m_ackDelayTimer;
|
||||
CFMTimer m_hangTimer;
|
||||
CFMTimer m_reverseTimer;
|
||||
bool m_needReverse;
|
||||
CFMDirectFormI m_filterStage1;
|
||||
CFMDirectFormI m_filterStage2;
|
||||
CFMDirectFormI m_filterStage3;
|
||||
CFMBlanking m_blanking;
|
||||
bool m_useCOS;
|
||||
uint8_t m_accessMode;
|
||||
bool m_linkMode;
|
||||
bool m_cosInvert;
|
||||
bool m_noiseSquelch;
|
||||
q15_t m_rfAudioBoost;
|
||||
CFMDownsampler m_downsampler;
|
||||
q15_t m_extAudioBoost;
|
||||
CFMDownSampler m_downSampler;
|
||||
bool m_extEnabled;
|
||||
q15_t m_rxLevel;
|
||||
CFMRB m_inputRB;
|
||||
CFMRB m_outputRB;
|
||||
CRingBuffer<q15_t> m_inputRFRB;
|
||||
CRingBuffer<q15_t> m_outputRFRB;
|
||||
CFMUpSampler m_inputExtRB;
|
||||
bool m_rfSignal;
|
||||
bool m_extSignal;
|
||||
uint32_t m_rssiAccum;
|
||||
uint16_t m_rssiCount;
|
||||
|
||||
void stateMachine(bool 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 stateMachine(bool validRFSignal, bool validExtSignal);
|
||||
|
||||
void repeaterSamples(bool cos, q15_t* samples, const uint16_t* rssi, uint8_t length);
|
||||
void linkSamples(bool cos, q15_t* samples, uint8_t length);
|
||||
|
||||
void duplexStateMachine(bool validRFSignal, bool validExtSignal);
|
||||
void listeningStateDuplex(bool validRFSignal, bool validExtSignal);
|
||||
void kerchunkRFStateDuplex(bool validSignal);
|
||||
void relayingRFStateDuplex(bool validSignal);
|
||||
void relayingRFWaitStateDuplex(bool validSignal);
|
||||
void timeoutRFStateDuplex(bool validSignal);
|
||||
void timeoutRFWaitStateDuplex(bool validSignal);
|
||||
void kerchunkExtStateDuplex(bool validSignal);
|
||||
void relayingExtStateDuplex(bool validSignal);
|
||||
void relayingExtWaitStateDuplex(bool validSignal);
|
||||
void timeoutExtStateDuplex(bool validSignal);
|
||||
void timeoutExtWaitStateDuplex(bool validSignal);
|
||||
void hangStateDuplex(bool validRFSignal, bool validExtSignal);
|
||||
|
||||
void simplexStateMachine(bool validRFSignal, bool validExtSignal);
|
||||
void listeningStateSimplex(bool validRFSignal, bool validExtSignal);
|
||||
void relayingRFStateSimplex(bool validSignal);
|
||||
void relayingRFWaitStateSimplex(bool validSignal);
|
||||
void timeoutRFStateSimplex(bool validSignal);
|
||||
void timeoutRFWaitStateSimplex(bool validSignal);
|
||||
void relayingExtStateSimplex(bool validSignal);
|
||||
void relayingExtWaitStateSimplex(bool validSignal);
|
||||
void timeoutExtStateSimplex(bool validSignal);
|
||||
void timeoutExtWaitStateSimplex(bool validSignal);
|
||||
|
||||
void linkStateMachine(bool validRFSignal, bool validExtSignal);
|
||||
|
||||
void clock(uint8_t length);
|
||||
|
||||
@@ -106,3 +139,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FMBlanking.h"
|
||||
|
||||
@@ -80,3 +83,6 @@ q15_t CFMBlanking::process(q15_t sample)
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-2
@@ -16,11 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(FMBlanking_H)
|
||||
#define FMBlanking_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
class CFMBlanking {
|
||||
public:
|
||||
CFMBlanking();
|
||||
@@ -39,3 +41,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+16
-16
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FMCTCSSRX.h"
|
||||
|
||||
@@ -87,7 +90,7 @@ m_lowThreshold(0),
|
||||
m_count(0U),
|
||||
m_q0(0),
|
||||
m_q1(0),
|
||||
m_result(CTS_NONE)
|
||||
m_state(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -111,13 +114,11 @@ uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t highThreshold, uint8_t
|
||||
return 0U;
|
||||
}
|
||||
|
||||
uint8_t CFMCTCSSRX::process(q15_t sample)
|
||||
bool CFMCTCSSRX::process(q15_t sample)
|
||||
{
|
||||
//get more dynamic into the decoder by multiplying the sample by 1.5
|
||||
q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1);
|
||||
|
||||
m_result &= ~CTS_READY;
|
||||
|
||||
q31_t q2 = m_q1;
|
||||
m_q1 = m_q0;
|
||||
|
||||
@@ -149,33 +150,32 @@ uint8_t CFMCTCSSRX::process(q15_t sample)
|
||||
// value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2
|
||||
q31_t value = t2 + t4 - t9;
|
||||
|
||||
bool previousCTCSSValid = CTCSS_VALID(m_result);
|
||||
bool previousState = m_state;
|
||||
|
||||
q31_t threshold = m_highThreshold;
|
||||
if (previousCTCSSValid)
|
||||
if (previousState)
|
||||
threshold = m_lowThreshold;
|
||||
|
||||
m_result |= CTS_READY;
|
||||
if (value >= threshold)
|
||||
m_result |= CTS_VALID;
|
||||
else
|
||||
m_result &= ~CTS_VALID;
|
||||
m_state = value >= threshold;
|
||||
|
||||
if (previousCTCSSValid != CTCSS_VALID(m_result))
|
||||
DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, CTCSS_VALID(m_result));
|
||||
if (previousState != m_state)
|
||||
DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, m_state);
|
||||
|
||||
m_count = 0U;
|
||||
m_q0 = 0;
|
||||
m_q1 = 0;
|
||||
}
|
||||
|
||||
return m_result;
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void CFMCTCSSRX::reset()
|
||||
{
|
||||
m_q0 = 0;
|
||||
m_q1 = 0;
|
||||
m_result = CTS_NONE;
|
||||
m_count = 0U;
|
||||
m_state = false;
|
||||
m_count = 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+8
-12
@@ -16,19 +16,12 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(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;
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#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)
|
||||
#if !defined(FMCTCSSRX_H)
|
||||
#define FMCTCSSRX_H
|
||||
|
||||
class CFMCTCSSRX {
|
||||
public:
|
||||
@@ -36,7 +29,7 @@ public:
|
||||
|
||||
uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold);
|
||||
|
||||
uint8_t process(q15_t sample);
|
||||
bool process(q15_t sample);
|
||||
|
||||
void reset();
|
||||
|
||||
@@ -47,7 +40,10 @@ private:
|
||||
uint16_t m_count;
|
||||
q31_t m_q0;
|
||||
q31_t m_q1;
|
||||
uint8_t m_result;
|
||||
bool m_state;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+12
-3
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FMCTCSSTX.h"
|
||||
|
||||
@@ -115,11 +118,17 @@ uint8_t CFMCTCSSTX::setParams(uint8_t frequency, uint8_t level)
|
||||
return 0U;
|
||||
}
|
||||
|
||||
q15_t CFMCTCSSTX::getAudio()
|
||||
q15_t CFMCTCSSTX::getAudio(bool reverse)
|
||||
{
|
||||
q15_t sample = m_values[m_n++];
|
||||
if(m_n >= m_length)
|
||||
if (m_n >= m_length)
|
||||
m_n = 0U;
|
||||
|
||||
return sample;
|
||||
if (reverse)
|
||||
return -sample;
|
||||
else
|
||||
return sample;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+8
-3
@@ -16,18 +16,20 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(FMCTCSSTX_H)
|
||||
#define FMCTCSSTX_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
class CFMCTCSSTX {
|
||||
public:
|
||||
CFMCTCSSTX();
|
||||
|
||||
uint8_t setParams(uint8_t frequency, uint8_t level);
|
||||
|
||||
q15_t getAudio();
|
||||
q15_t getAudio(bool reverse);
|
||||
|
||||
private:
|
||||
q15_t* m_values;
|
||||
@@ -36,3 +38,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+15
-13
@@ -29,7 +29,11 @@ THE SOFTWARE.
|
||||
|
||||
// based on https://raw.githubusercontent.com/berndporr/iir_fixed_point/master/DirectFormI.h
|
||||
|
||||
#include "Globals.h"
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef DIRECTFORMI_H_
|
||||
#define DIRECTFORMI_H_
|
||||
@@ -38,8 +42,7 @@ class CFMDirectFormI
|
||||
public:
|
||||
|
||||
// convenience function which takes the a0 argument but ignores it!
|
||||
CFMDirectFormI(const q31_t b0, const q31_t b1, const q31_t b2,
|
||||
const q31_t, const q31_t a1, const q31_t a2)
|
||||
CFMDirectFormI(const q31_t b0, const q31_t b1, const q31_t b2, const q31_t, const q31_t a1, const q31_t a2)
|
||||
{
|
||||
// FIR coefficients
|
||||
c_b0 = b0;
|
||||
@@ -53,21 +56,21 @@ public:
|
||||
|
||||
CFMDirectFormI(const CFMDirectFormI &my)
|
||||
{
|
||||
// delay line
|
||||
// delay line
|
||||
m_x2 = my.m_x2; // x[n-2]
|
||||
m_y2 = my.m_y2; // y[n-2]
|
||||
m_x1 = my.m_x1; // x[n-1]
|
||||
m_y1 = my.m_y1; // y[n-1]
|
||||
|
||||
// coefficients
|
||||
// coefficients
|
||||
c_b0 = my.c_b0;
|
||||
c_b1 = my.c_b1;
|
||||
c_b2 = my.c_b2; // FIR
|
||||
c_a1 = my.c_a1;
|
||||
c_a2 = my.c_a2; // IIR
|
||||
}
|
||||
}
|
||||
|
||||
void reset ()
|
||||
void reset()
|
||||
{
|
||||
m_x1 = 0;
|
||||
m_x2 = 0;
|
||||
@@ -79,11 +82,7 @@ public:
|
||||
inline q15_t filter(const q15_t in)
|
||||
{
|
||||
// calculate the output
|
||||
register q31_t out_upscaled = c_b0 * in
|
||||
+ c_b1 * m_x1
|
||||
+ c_b2 * m_x2
|
||||
- c_a1 * m_y1
|
||||
- c_a2 * m_y2;
|
||||
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);
|
||||
|
||||
@@ -108,4 +107,7 @@ private:
|
||||
q31_t c_a1,c_a2; // IIR
|
||||
};
|
||||
|
||||
#endif /* DIRECTFORMI_H */
|
||||
#endif /* DIRECTFORMI_H */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "FMDownSampler.h"
|
||||
|
||||
CFMDownSampler::CFMDownSampler(uint16_t length) :
|
||||
m_ringBuffer(length),
|
||||
m_samplePack(0U),
|
||||
m_samplePackPointer(NULL),
|
||||
m_sampleIndex(0U)
|
||||
{
|
||||
m_samplePackPointer = (uint8_t*)&m_samplePack;
|
||||
}
|
||||
|
||||
void CFMDownSampler::addSample(q15_t sample)
|
||||
{
|
||||
uint32_t usample = uint32_t(int32_t(sample) + 2048);
|
||||
//only take one of three samples
|
||||
switch(m_sampleIndex){
|
||||
case 0:
|
||||
m_samplePack = usample << 12;
|
||||
break;
|
||||
case 3:{
|
||||
m_samplePack |= usample;
|
||||
|
||||
//we did not use MSB; skip it
|
||||
TSamplePairPack pair{m_samplePackPointer[0U], m_samplePackPointer[1U], m_samplePackPointer[2U]};
|
||||
|
||||
m_ringBuffer.put(pair);
|
||||
|
||||
m_samplePack = 0U;//reset the sample pack
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//Just skip this sample
|
||||
break;
|
||||
}
|
||||
|
||||
m_sampleIndex++;
|
||||
if (m_sampleIndex >= 6U)//did we pack two samples ?
|
||||
m_sampleIndex = 0U;
|
||||
}
|
||||
|
||||
bool CFMDownSampler::getPackedData(TSamplePairPack& data)
|
||||
{
|
||||
return m_ringBuffer.get(data);
|
||||
}
|
||||
|
||||
uint16_t CFMDownSampler::getData()
|
||||
{
|
||||
return m_ringBuffer.getData();
|
||||
}
|
||||
|
||||
void CFMDownSampler::reset()
|
||||
{
|
||||
m_sampleIndex = 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,27 +17,36 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(FMDOWNSAMPLER_H)
|
||||
#define FMDOWNSAMPLER_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "FMDownsampleRB.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "FMSamplePairPack.h"
|
||||
|
||||
class CFMDownsampler {
|
||||
class CFMDownSampler {
|
||||
public:
|
||||
CFMDownsampler(uint16_t length);
|
||||
CFMDownSampler(uint16_t length);
|
||||
|
||||
void addSample(q15_t sample);
|
||||
inline bool getPackedData(uint8_t& data){ return m_ringBuffer.get(data); };
|
||||
inline bool hasOverflowed() { return m_ringBuffer.hasOverflowed(); };
|
||||
|
||||
bool getPackedData(TSamplePairPack& data);
|
||||
|
||||
uint16_t getData();
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
CFMDownsampleRB m_ringBuffer;
|
||||
union {
|
||||
int32_t m_samplePack;
|
||||
int8_t m_samplePackBytes[4];
|
||||
};
|
||||
uint8_t m_packIndex;
|
||||
uint8_t m_downSampleIndex;
|
||||
CRingBuffer<TSamplePairPack> m_ringBuffer;
|
||||
uint32_t m_samplePack;
|
||||
uint8_t* m_samplePackPointer;
|
||||
uint8_t m_sampleIndex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
#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,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FMKeyer.h"
|
||||
|
||||
@@ -214,3 +217,6 @@ bool CFMKeyer::isRunning() const
|
||||
{
|
||||
return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(FMKeyer_H)
|
||||
#define FMKeyer_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
class CFMKeyer {
|
||||
public:
|
||||
CFMKeyer();
|
||||
@@ -52,3 +54,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FMNoiseSquelch.h"
|
||||
|
||||
// 4500Hz centre frequency
|
||||
const q31_t COEFF_DIV_TWO = 821806413;
|
||||
|
||||
// 400Hz bandwidth
|
||||
const uint16_t N = 24000U / 400U;
|
||||
|
||||
CFMNoiseSquelch::CFMNoiseSquelch() :
|
||||
m_highThreshold(0),
|
||||
m_lowThreshold(0),
|
||||
m_count(0U),
|
||||
m_q0(0),
|
||||
m_q1(0),
|
||||
m_state(false),
|
||||
m_validCount(0U)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CFMNoiseSquelch::setParams(uint8_t highThreshold, uint8_t lowThreshold)
|
||||
{
|
||||
m_highThreshold = q31_t(highThreshold);
|
||||
m_lowThreshold = q31_t(lowThreshold);
|
||||
}
|
||||
|
||||
bool CFMNoiseSquelch::process(q15_t sample)
|
||||
{
|
||||
//get more dynamic into the decoder by multiplying the sample by 64
|
||||
q31_t sample31 = q31_t(sample) << 6; //+ (q31_t(sample) >> 1);
|
||||
|
||||
q31_t q2 = m_q1;
|
||||
m_q1 = m_q0;
|
||||
|
||||
// Q31 multiplication, t3 = m_coeffDivTwo * 2 * m_q1
|
||||
q63_t t1 = COEFF_DIV_TWO * m_q1;
|
||||
q31_t t2 = __SSAT((t1 >> 31), 31);
|
||||
q31_t t3 = t2 * 2;
|
||||
|
||||
// m_q0 = m_coeffDivTwo * m_q1 * 2 - q2 + sample
|
||||
m_q0 = t3 - q2 + sample31;
|
||||
|
||||
m_count++;
|
||||
if (m_count == N) {
|
||||
// Q31 multiplication, t2 = m_q0 * m_q0
|
||||
q63_t t1 = q63_t(m_q0) * q63_t(m_q0);
|
||||
q31_t t2 = __SSAT((t1 >> 31), 31);
|
||||
|
||||
// Q31 multiplication, t4 = m_q0 * m_q0
|
||||
q63_t t3 = q63_t(m_q1) * q63_t(m_q1);
|
||||
q31_t t4 = __SSAT((t3 >> 31), 31);
|
||||
|
||||
// Q31 multiplication, t9 = m_q0 * m_q1 * m_coeffDivTwo * 2
|
||||
q63_t t5 = q63_t(m_q0) * q63_t(m_q1);
|
||||
q31_t t6 = __SSAT((t5 >> 31), 31);
|
||||
q63_t t7 = t6 * COEFF_DIV_TWO;
|
||||
q31_t t8 = __SSAT((t7 >> 31), 31);
|
||||
q31_t t9 = t8 * 2;
|
||||
|
||||
// value = m_q0 * m_q0 + m_q1 * m_q1 - m_q0 * m_q1 * m_coeffDivTwo * 2
|
||||
q31_t value = t2 + t4 - t9;
|
||||
|
||||
bool previousState = m_state;
|
||||
|
||||
q31_t threshold = m_highThreshold;
|
||||
if (previousState)
|
||||
threshold = m_lowThreshold;
|
||||
|
||||
if (!m_state) {
|
||||
if (value < threshold)
|
||||
m_validCount++;
|
||||
else
|
||||
m_validCount = 0U;
|
||||
}
|
||||
|
||||
if (m_state) {
|
||||
if (value >= threshold)
|
||||
m_invalidCount++;
|
||||
else
|
||||
m_invalidCount = 0U;
|
||||
}
|
||||
|
||||
m_state = m_validCount >= 10U && m_invalidCount < 10U;
|
||||
|
||||
if(previousState && !m_state)
|
||||
m_invalidCount = 0U;
|
||||
|
||||
if (previousState != m_state) {
|
||||
DEBUG4("Noise Squelch Value / Threshold / Valid", value, threshold, m_state);
|
||||
DEBUG3("Valid Count / Invalid Count", m_validCount, m_invalidCount);
|
||||
}
|
||||
|
||||
m_count = 0U;
|
||||
m_q0 = 0;
|
||||
m_q1 = 0;
|
||||
}
|
||||
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void CFMNoiseSquelch::reset()
|
||||
{
|
||||
m_q0 = 0;
|
||||
m_q1 = 0;
|
||||
m_state = false;
|
||||
m_count = 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(FMNOISESQUELCH_H)
|
||||
#define FMNOISESQUELCH_H
|
||||
|
||||
class CFMNoiseSquelch {
|
||||
public:
|
||||
CFMNoiseSquelch();
|
||||
|
||||
void setParams(uint8_t highThreshold, uint8_t lowThreshold);
|
||||
|
||||
bool process(q15_t sample);
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
q31_t m_highThreshold;
|
||||
q31_t m_lowThreshold;
|
||||
uint16_t m_count;
|
||||
q31_t m_q0;
|
||||
q31_t m_q1;
|
||||
bool m_state;
|
||||
uint8_t m_validCount;
|
||||
uint8_t m_invalidCount;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
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
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(TSAMPLEPACK_H)
|
||||
#define TSAMPLEPACK_H
|
||||
|
||||
struct TSamplePairPack {
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
uint8_t byte2;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+11
-7
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FMTimeout.h"
|
||||
|
||||
@@ -36,24 +39,22 @@ m_n(0U)
|
||||
|
||||
void CFMTimeout::setParams(uint8_t level)
|
||||
{
|
||||
m_level = q15_t(level * 128);
|
||||
m_level = q15_t(level * 5);
|
||||
}
|
||||
|
||||
q15_t CFMTimeout::getAudio()
|
||||
{
|
||||
q15_t sample = 0U;
|
||||
q15_t sample = 0;
|
||||
if (!m_running)
|
||||
return sample;
|
||||
|
||||
if (m_pos > 12000U) {
|
||||
q31_t sample = BUSY_AUDIO[m_n] * m_level;
|
||||
sample = q15_t(__SSAT((sample >> 15), 16));
|
||||
if (m_pos >= 12000U) {
|
||||
q31_t sample31 = BUSY_AUDIO[m_n] * m_level;
|
||||
sample = q15_t(__SSAT((sample31 >> 15), 16));
|
||||
|
||||
m_n++;
|
||||
if (m_n >= BUSY_AUDIO_LEN)
|
||||
m_n = 0U;
|
||||
} else {
|
||||
sample = 0U;
|
||||
}
|
||||
|
||||
m_pos++;
|
||||
@@ -74,3 +75,6 @@ void CFMTimeout::stop()
|
||||
{
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+7
-2
@@ -16,11 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(FMTimeout_H)
|
||||
#define FMTimeout_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
class CFMTimeout {
|
||||
public:
|
||||
CFMTimeout();
|
||||
@@ -40,3 +42,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "FMTimer.h"
|
||||
|
||||
@@ -68,3 +71,6 @@ bool CFMTimer::hasExpired() const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(FMTimer_H)
|
||||
#define FMTimer_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
class CFMTimer {
|
||||
public:
|
||||
CFMTimer();
|
||||
@@ -45,3 +47,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#include "FMUpSampler.h"
|
||||
|
||||
const uint32_t FM_UPSAMPLE_MASK = 0x00000FFFU;
|
||||
|
||||
CFMUpSampler::CFMUpSampler() :
|
||||
m_upSampleIndex(0),
|
||||
m_pack(0U),
|
||||
m_packPointer(NULL),
|
||||
m_samples(3600U), //300ms of 12 bit 8kHz audio
|
||||
m_running(false)
|
||||
{
|
||||
m_packPointer = (uint8_t*)&m_pack;
|
||||
}
|
||||
|
||||
void CFMUpSampler::reset()
|
||||
{
|
||||
m_upSampleIndex = 0U;
|
||||
m_pack = 0U;
|
||||
m_samples.reset();
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
void CFMUpSampler::addData(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
TSamplePairPack* packPointer = (TSamplePairPack*)data;
|
||||
TSamplePairPack* packPointerEnd = packPointer + (length / 3U);
|
||||
while(packPointer != packPointerEnd) {
|
||||
m_samples.put(*packPointer);
|
||||
packPointer++;
|
||||
}
|
||||
if(!m_running)
|
||||
m_running = m_samples.getData() > 300U;//75ms of audio
|
||||
}
|
||||
|
||||
bool CFMUpSampler::getSample(q15_t& sample)
|
||||
{
|
||||
if(!m_running)
|
||||
return false;
|
||||
|
||||
switch (m_upSampleIndex)
|
||||
{
|
||||
case 0: {
|
||||
TSamplePairPack pairPack;
|
||||
if(!m_samples.get(pairPack)) {
|
||||
m_running = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pack = 0U;
|
||||
m_packPointer = (uint8_t*)&m_pack;
|
||||
|
||||
m_packPointer[0U] = pairPack.byte0;
|
||||
m_packPointer[1U] = pairPack.byte1;
|
||||
m_packPointer[2U] = pairPack.byte2;
|
||||
|
||||
sample = q15_t(m_pack >> 12) - 2048;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
sample = q15_t(m_pack & FM_UPSAMPLE_MASK) - 2048;
|
||||
break;
|
||||
default:
|
||||
sample = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
m_upSampleIndex++;
|
||||
if(m_upSampleIndex >= 6U)
|
||||
m_upSampleIndex = 0U;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t CFMUpSampler::getSpace() const
|
||||
{
|
||||
//return available space in bytes
|
||||
return m_samples.getSpace() * sizeof(TSamplePairPack);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020 by Geoffrey Merck F4FXL - KC3FRA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_FM)
|
||||
|
||||
#if !defined(FMUPSAMPLER_H)
|
||||
#define FMUPSAMPLER_H
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include "FMSamplePairPack.h"
|
||||
|
||||
class CFMUpSampler {
|
||||
public:
|
||||
CFMUpSampler();
|
||||
|
||||
void reset();
|
||||
|
||||
void addData(const uint8_t* data, uint16_t length);
|
||||
|
||||
bool getSample(q15_t& sample);
|
||||
|
||||
uint16_t getSpace() const;
|
||||
|
||||
private:
|
||||
uint8_t m_upSampleIndex;
|
||||
uint32_t m_pack;
|
||||
uint8_t * m_packPointer;
|
||||
CRingBuffer<TSamplePairPack> m_samples;
|
||||
bool m_running;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,14 +23,12 @@
|
||||
#include "stm32f4xx.h"
|
||||
#elif defined(STM32F7XX)
|
||||
#include "stm32f7xx.h"
|
||||
#elif defined(STM32F105xC)
|
||||
#include "stm32f1xx.h"
|
||||
#include "STM32Utils.h"
|
||||
#else
|
||||
#include <Arduino.h>
|
||||
#undef PI //Undefine PI to get rid of annoying warning as it is also defined in arm_math.h.
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__) || defined(STM32F105xC)
|
||||
#if defined(__SAM3X8E__)
|
||||
#define ARM_MATH_CM3
|
||||
#elif defined(STM32F7XX)
|
||||
#define ARM_MATH_CM7
|
||||
@@ -109,7 +107,7 @@ const uint16_t RX_BLOCK_SIZE = 2U;
|
||||
const uint16_t TX_RINGBUFFER_SIZE = 500U;
|
||||
const uint16_t RX_RINGBUFFER_SIZE = 600U;
|
||||
|
||||
#if defined(STM32F105xC) || defined(__MK20DX256__)
|
||||
#if defined(__MK20DX256__)
|
||||
const uint16_t TX_BUFFER_LEN = 2000U;
|
||||
#else
|
||||
const uint16_t TX_BUFFER_LEN = 4000U;
|
||||
@@ -133,9 +131,15 @@ extern bool m_dcd;
|
||||
extern CSerialPort serial;
|
||||
extern CIO io;
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
extern CDStarRX dstarRX;
|
||||
extern CDStarTX dstarTX;
|
||||
|
||||
extern CCalDStarRX calDStarRX;
|
||||
extern CCalDStarTX calDStarTX;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
extern CDMRIdleRX dmrIdleRX;
|
||||
extern CDMRRX dmrRX;
|
||||
extern CDMRTX dmrTX;
|
||||
@@ -143,28 +147,41 @@ extern CDMRTX dmrTX;
|
||||
extern CDMRDMORX dmrDMORX;
|
||||
extern CDMRDMOTX dmrDMOTX;
|
||||
|
||||
extern CCalDMR calDMR;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
extern CYSFRX ysfRX;
|
||||
extern CYSFTX ysfTX;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
extern CP25RX p25RX;
|
||||
extern CP25TX p25TX;
|
||||
|
||||
extern CCalP25 calP25;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
extern CNXDNRX nxdnRX;
|
||||
extern CNXDNTX nxdnTX;
|
||||
|
||||
extern CPOCSAGTX pocsagTX;
|
||||
extern CCalNXDN calNXDN;
|
||||
#endif
|
||||
|
||||
extern CFM fm;
|
||||
#if defined(MODE_POCSAG)
|
||||
extern CPOCSAGTX pocsagTX;
|
||||
extern CCalPOCSAG calPOCSAG;
|
||||
#endif
|
||||
|
||||
extern CCalDStarRX calDStarRX;
|
||||
extern CCalDStarTX calDStarTX;
|
||||
extern CCalDMR calDMR;
|
||||
extern CCalFM calFM;
|
||||
extern CCalP25 calP25;
|
||||
extern CCalNXDN calNXDN;
|
||||
extern CCalPOCSAG calPOCSAG;
|
||||
extern CCalRSSI calRSSI;
|
||||
#if defined(MODE_FM)
|
||||
extern CFM fm;
|
||||
extern CCalFM calFM;
|
||||
#endif
|
||||
|
||||
extern CCalRSSI calRSSI;
|
||||
|
||||
extern CCWIdTX cwIdTX;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021,2023,2025,2026 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
@@ -22,16 +22,26 @@
|
||||
#include "Globals.h"
|
||||
#include "IO.h"
|
||||
|
||||
#if defined(USE_DCBLOCKER)
|
||||
// Generated using [b, a] = butter(1, 0.001) in MATLAB
|
||||
static q31_t DC_FILTER[] = {3367972, 0, 3367972, 0, 2140747704, 0}; // {b0, 0, b1, b2, -a1, -a2}
|
||||
const uint32_t DC_FILTER_STAGES = 1U; // One Biquad stage
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR) || defined(MODE_YSF)
|
||||
// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB
|
||||
static q15_t RRC_0_2_FILTER[] = {401, 104, -340, -731, -847, -553, 112, 909, 1472, 1450, 683, -675, -2144, -3040, -2706, -770, 2667, 6995,
|
||||
11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112,
|
||||
-553, -847, -731, -340, 104, 401, 0};
|
||||
const uint16_t RRC_0_2_FILTER_LEN = 42U;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
#if defined(USE_NXDN_BOXCAR)
|
||||
// One symbol boxcar filter
|
||||
static q15_t BOXCAR10_FILTER[] = {6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000, 6000};
|
||||
const uint16_t BOXCAR10_FILTER_LEN = 10U;
|
||||
#else
|
||||
// Generated using rcosdesign(0.2, 8, 10, 'sqrt') in MATLAB
|
||||
static q15_t NXDN_0_2_FILTER[] = {284, 198, 73, -78, -240, -393, -517, -590, -599, -533, -391, -181, 79, 364, 643, 880, 1041, 1097, 1026, 819,
|
||||
483, 39, -477, -1016, -1516, -1915, -2150, -2164, -1914, -1375, -545, 557, 1886, 3376, 4946, 6502, 7946, 9184,
|
||||
@@ -43,14 +53,20 @@ const uint16_t NXDN_0_2_FILTER_LEN = 82U;
|
||||
static q15_t NXDN_ISINC_FILTER[] = {790, -1085, -1073, -553, 747, 2341, 3156, 2152, -893, -4915, -7834, -7536, -3102, 4441, 12354, 17394, 17394,
|
||||
12354, 4441, -3102, -7536, -7834, -4915, -893, 2152, 3156, 2341, 747, -553, -1073, -1085, 790};
|
||||
const uint16_t NXDN_ISINC_FILTER_LEN = 32U;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
// Generated using gaussfir(0.5, 4, 5) in MATLAB
|
||||
static q15_t GAUSSIAN_0_5_FILTER[] = {8, 104, 760, 3158, 7421, 9866, 7421, 3158, 760, 104, 8, 0};
|
||||
const uint16_t GAUSSIAN_0_5_FILTER_LEN = 12U;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
// One symbol boxcar filter
|
||||
static q15_t BOXCAR_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0};
|
||||
const uint16_t BOXCAR_FILTER_LEN = 6U;
|
||||
static q15_t BOXCAR5_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0};
|
||||
const uint16_t BOXCAR5_FILTER_LEN = 6U;
|
||||
#endif
|
||||
|
||||
const uint16_t DC_OFFSET = 2048U;
|
||||
|
||||
@@ -59,18 +75,37 @@ m_started(false),
|
||||
m_rxBuffer(RX_RINGBUFFER_SIZE),
|
||||
m_txBuffer(TX_RINGBUFFER_SIZE),
|
||||
m_rssiBuffer(RX_RINGBUFFER_SIZE),
|
||||
#if defined(USE_DCBLOCKER)
|
||||
m_dcFilter(),
|
||||
m_dcState(),
|
||||
m_rrcFilter(),
|
||||
#endif
|
||||
#if defined(MODE_DSTAR)
|
||||
m_gaussianFilter(),
|
||||
m_boxcarFilter(),
|
||||
m_gaussianState(),
|
||||
#endif
|
||||
#if defined(MODE_DMR)
|
||||
m_rrc02Filter1(),
|
||||
m_rrc02State1(),
|
||||
#endif
|
||||
#if defined(MODE_YSF)
|
||||
m_rrc02Filter2(),
|
||||
m_rrc02State2(),
|
||||
#endif
|
||||
#if defined(MODE_P25)
|
||||
m_boxcar5Filter(),
|
||||
m_boxcar5State(),
|
||||
#endif
|
||||
#if defined(MODE_NXDN)
|
||||
#if defined(USE_NXDN_BOXCAR)
|
||||
m_boxcar10Filter(),
|
||||
m_boxcar10State(),
|
||||
#else
|
||||
m_nxdnFilter(),
|
||||
m_nxdnISincFilter(),
|
||||
m_rrcState(),
|
||||
m_gaussianState(),
|
||||
m_boxcarState(),
|
||||
m_nxdnState(),
|
||||
m_nxdnISincState(),
|
||||
#endif
|
||||
#endif
|
||||
m_pttInvert(false),
|
||||
m_rxLevel(128 * 128),
|
||||
m_cwIdTXLevel(128 * 128),
|
||||
@@ -83,6 +118,7 @@ m_pocsagTXLevel(128 * 128),
|
||||
m_fmTXLevel(128 * 128),
|
||||
m_rxDCOffset(DC_OFFSET),
|
||||
m_txDCOffset(DC_OFFSET),
|
||||
m_useCOSAsLockout(false),
|
||||
m_ledCount(0U),
|
||||
m_ledValue(true),
|
||||
m_detect(false),
|
||||
@@ -91,30 +127,52 @@ m_dacOverflow(0U),
|
||||
m_watchdog(0U),
|
||||
m_lockout(false)
|
||||
{
|
||||
::memset(m_rrcState, 0x00U, 70U * sizeof(q15_t));
|
||||
::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t));
|
||||
::memset(m_boxcarState, 0x00U, 30U * sizeof(q15_t));
|
||||
::memset(m_nxdnState, 0x00U, 110U * sizeof(q15_t));
|
||||
::memset(m_nxdnISincState, 0x00U, 60U * sizeof(q15_t));
|
||||
::memset(m_dcState, 0x00U, 4U * sizeof(q31_t));
|
||||
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::memset(m_dcState, 0x00U, 4U * sizeof(q31_t));
|
||||
m_dcFilter.numStages = DC_FILTER_STAGES;
|
||||
m_dcFilter.pState = m_dcState;
|
||||
m_dcFilter.pCoeffs = DC_FILTER;
|
||||
m_dcFilter.postShift = 0;
|
||||
#endif
|
||||
|
||||
m_rrcFilter.numTaps = RRC_0_2_FILTER_LEN;
|
||||
m_rrcFilter.pState = m_rrcState;
|
||||
m_rrcFilter.pCoeffs = RRC_0_2_FILTER;
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t));
|
||||
m_gaussianFilter.numTaps = GAUSSIAN_0_5_FILTER_LEN;
|
||||
m_gaussianFilter.pState = m_gaussianState;
|
||||
m_gaussianFilter.pCoeffs = GAUSSIAN_0_5_FILTER;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
::memset(m_rrc02State1, 0x00U, 70U * sizeof(q15_t));
|
||||
m_rrc02Filter1.numTaps = RRC_0_2_FILTER_LEN;
|
||||
m_rrc02Filter1.pState = m_rrc02State1;
|
||||
m_rrc02Filter1.pCoeffs = RRC_0_2_FILTER;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
::memset(m_rrc02State2, 0x00U, 70U * sizeof(q15_t));
|
||||
m_rrc02Filter2.numTaps = RRC_0_2_FILTER_LEN;
|
||||
m_rrc02Filter2.pState = m_rrc02State2;
|
||||
m_rrc02Filter2.pCoeffs = RRC_0_2_FILTER;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
::memset(m_boxcar5State, 0x00U, 30U * sizeof(q15_t));
|
||||
m_boxcar5Filter.numTaps = BOXCAR5_FILTER_LEN;
|
||||
m_boxcar5Filter.pState = m_boxcar5State;
|
||||
m_boxcar5Filter.pCoeffs = BOXCAR5_FILTER;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
#if defined(USE_NXDN_BOXCAR)
|
||||
::memset(m_boxcar10State, 0x00U, 40U * sizeof(q15_t));
|
||||
m_boxcar10Filter.numTaps = BOXCAR10_FILTER_LEN;
|
||||
m_boxcar10Filter.pState = m_boxcar10State;
|
||||
m_boxcar10Filter.pCoeffs = BOXCAR10_FILTER;
|
||||
#else
|
||||
::memset(m_nxdnState, 0x00U, 110U * sizeof(q15_t));
|
||||
::memset(m_nxdnISincState, 0x00U, 60U * sizeof(q15_t));
|
||||
|
||||
m_boxcarFilter.numTaps = BOXCAR_FILTER_LEN;
|
||||
m_boxcarFilter.pState = m_boxcarState;
|
||||
m_boxcarFilter.pCoeffs = BOXCAR_FILTER;
|
||||
|
||||
m_nxdnFilter.numTaps = NXDN_0_2_FILTER_LEN;
|
||||
m_nxdnFilter.pState = m_nxdnState;
|
||||
m_nxdnFilter.pCoeffs = NXDN_0_2_FILTER;
|
||||
@@ -122,6 +180,8 @@ m_lockout(false)
|
||||
m_nxdnISincFilter.numTaps = NXDN_ISINC_FILTER_LEN;
|
||||
m_nxdnISincFilter.pState = m_nxdnISincState;
|
||||
m_nxdnISincFilter.pCoeffs = NXDN_ISINC_FILTER;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
initInt();
|
||||
|
||||
@@ -132,7 +192,7 @@ void CIO::selfTest()
|
||||
{
|
||||
bool ledValue = false;
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
for (uint8_t i = 0U; i < 6U; i++) {
|
||||
ledValue = !ledValue;
|
||||
|
||||
// We exclude PTT to avoid trigger the transmitter
|
||||
@@ -143,21 +203,34 @@ void CIO::selfTest()
|
||||
setDMRInt(ledValue);
|
||||
setYSFInt(ledValue);
|
||||
setP25Int(ledValue);
|
||||
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||
setNXDNInt(ledValue);
|
||||
#endif
|
||||
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||
setPOCSAGInt(ledValue);
|
||||
#endif
|
||||
#if !defined(USE_ALTERNATE_FM_LEDS)
|
||||
setFMInt(ledValue);
|
||||
#endif
|
||||
#endif
|
||||
delayInt(250);
|
||||
}
|
||||
|
||||
#if defined(MODE_LEDS)
|
||||
setDStarInt(true);
|
||||
setDStarInt(false);
|
||||
setDMRInt(false);
|
||||
setYSFInt(false);
|
||||
setP25Int(false);
|
||||
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||
setNXDNInt(false);
|
||||
#endif
|
||||
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||
setPOCSAGInt(false);
|
||||
#endif
|
||||
#if !defined(USE_ALTERNATE_FM_LEDS)
|
||||
setFMInt(false);
|
||||
#endif
|
||||
setDStarInt(true);
|
||||
|
||||
delayInt(250);
|
||||
setDMRInt(true);
|
||||
@@ -219,7 +292,7 @@ void CIO::start()
|
||||
|
||||
m_started = true;
|
||||
|
||||
setMode();
|
||||
setMode(STATE_IDLE);
|
||||
}
|
||||
|
||||
void CIO::process()
|
||||
@@ -229,10 +302,11 @@ void CIO::process()
|
||||
// Two seconds timeout
|
||||
if (m_watchdog >= 48000U) {
|
||||
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN || m_modemState == STATE_POCSAG) {
|
||||
#if defined(MODE_DMR)
|
||||
if (m_modemState == STATE_DMR && m_tx)
|
||||
dmrTX.setStart(false);
|
||||
m_modemState = STATE_IDLE;
|
||||
setMode();
|
||||
#endif
|
||||
setMode(STATE_IDLE);
|
||||
}
|
||||
|
||||
m_watchdog = 0U;
|
||||
@@ -256,14 +330,14 @@ void CIO::process()
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(USE_COS_AS_LOCKOUT)
|
||||
m_lockout = getCOSInt();
|
||||
#endif
|
||||
if (m_useCOSAsLockout)
|
||||
m_lockout = getCOSInt();
|
||||
|
||||
// Switch off the transmitter if needed
|
||||
if (m_txBuffer.getData() == 0U && m_tx) {
|
||||
m_tx = false;
|
||||
setPTTInt(m_pttInvert ? true : false);
|
||||
DEBUG1("TX OFF");
|
||||
}
|
||||
|
||||
if (m_rxBuffer.getData() >= RX_BLOCK_SIZE) {
|
||||
@@ -272,15 +346,16 @@ void CIO::process()
|
||||
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]);
|
||||
TSample sample;
|
||||
m_rxBuffer.get(sample);
|
||||
control[i] = sample.control;
|
||||
m_rssiBuffer.get(rssi[i]);
|
||||
|
||||
// Detect ADC overflow
|
||||
if (m_detect && (sample == 0U || sample == 4095U))
|
||||
if (m_detect && (sample.sample == 0U || sample.sample == 4095U))
|
||||
m_adcOverflow++;
|
||||
|
||||
q15_t res1 = q15_t(sample) - m_rxDCOffset;
|
||||
q15_t res1 = q15_t(sample.sample) - m_rxDCOffset;
|
||||
q31_t res2 = res1 * m_rxLevel;
|
||||
samples[i] = q15_t(__SSAT((res2 >> 15), 16));
|
||||
}
|
||||
@@ -308,6 +383,7 @@ void CIO::process()
|
||||
#endif
|
||||
|
||||
if (m_modemState == STATE_IDLE) {
|
||||
#if defined(MODE_DSTAR)
|
||||
if (m_dstarEnable) {
|
||||
q15_t GMSKVals[RX_BLOCK_SIZE];
|
||||
#if defined(USE_DCBLOCKER)
|
||||
@@ -317,54 +393,80 @@ void CIO::process()
|
||||
#endif
|
||||
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
if (m_p25Enable) {
|
||||
q15_t P25Vals[RX_BLOCK_SIZE];
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, P25Vals, RX_BLOCK_SIZE);
|
||||
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, P25Vals, RX_BLOCK_SIZE);
|
||||
#else
|
||||
::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE);
|
||||
::arm_fir_fast_q15(&m_boxcar5Filter, samples, P25Vals, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
if (m_nxdnEnable) {
|
||||
q15_t NXDNVals[RX_BLOCK_SIZE];
|
||||
#if defined(USE_NXDN_BOXCAR)
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::arm_fir_fast_q15(&m_boxcar10Filter, dcSamples, NXDNVals, RX_BLOCK_SIZE);
|
||||
#else
|
||||
::arm_fir_fast_q15(&m_boxcar10Filter, samples, NXDNVals, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
#else
|
||||
q15_t NXDNValsTmp[RX_BLOCK_SIZE];
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNValsTmp, RX_BLOCK_SIZE);
|
||||
#else
|
||||
::arm_fir_fast_q15(&m_nxdnFilter, samples, NXDNValsTmp, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
q15_t NXDNVals[RX_BLOCK_SIZE];
|
||||
::arm_fir_fast_q15(&m_nxdnISincFilter, NXDNValsTmp, NXDNVals, RX_BLOCK_SIZE);
|
||||
|
||||
#endif
|
||||
nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_dmrEnable || m_ysfEnable) {
|
||||
q15_t RRCVals[RX_BLOCK_SIZE];
|
||||
::arm_fir_fast_q15(&m_rrcFilter, samples, RRCVals, RX_BLOCK_SIZE);
|
||||
#if defined(MODE_DMR)
|
||||
if (m_dmrEnable) {
|
||||
q15_t DMRVals[RX_BLOCK_SIZE];
|
||||
::arm_fir_fast_q15(&m_rrc02Filter1, samples, DMRVals, RX_BLOCK_SIZE);
|
||||
|
||||
if (m_ysfEnable)
|
||||
ysfRX.samples(RRCVals, rssi, RX_BLOCK_SIZE);
|
||||
|
||||
if (m_dmrEnable) {
|
||||
if (m_duplex)
|
||||
dmrIdleRX.samples(RRCVals, RX_BLOCK_SIZE);
|
||||
else
|
||||
dmrDMORX.samples(RRCVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
if (m_duplex)
|
||||
dmrIdleRX.samples(DMRVals, RX_BLOCK_SIZE);
|
||||
else
|
||||
dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
if (m_ysfEnable) {
|
||||
q15_t YSFVals[RX_BLOCK_SIZE];
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::arm_fir_fast_q15(&m_rrc02Filter2, dcSamples, YSFVals, RX_BLOCK_SIZE);
|
||||
#else
|
||||
::arm_fir_fast_q15(&m_rrc02Filter2, samples, YSFVals, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_FM)
|
||||
if (m_fmEnable) {
|
||||
bool cos = getCOSInt();
|
||||
#if defined(USE_DCBLOCKER)
|
||||
fm.samples(cos, dcSamples, RX_BLOCK_SIZE);
|
||||
fm.samples(cos, dcSamples, rssi, RX_BLOCK_SIZE);
|
||||
#else
|
||||
fm.samples(cos, samples, RX_BLOCK_SIZE);
|
||||
fm.samples(cos, samples, rssi, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
}
|
||||
} else if (m_modemState == STATE_DSTAR) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
else if (m_modemState == STATE_DSTAR) {
|
||||
if (m_dstarEnable) {
|
||||
q15_t GMSKVals[RX_BLOCK_SIZE];
|
||||
#if defined(USE_DCBLOCKER)
|
||||
@@ -374,10 +476,14 @@ void CIO::process()
|
||||
#endif
|
||||
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
} else if (m_modemState == STATE_DMR) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
else if (m_modemState == STATE_DMR) {
|
||||
if (m_dmrEnable) {
|
||||
q15_t DMRVals[RX_BLOCK_SIZE];
|
||||
::arm_fir_fast_q15(&m_rrcFilter, samples, DMRVals, RX_BLOCK_SIZE);
|
||||
::arm_fir_fast_q15(&m_rrc02Filter1, samples, DMRVals, RX_BLOCK_SIZE);
|
||||
|
||||
if (m_duplex) {
|
||||
// If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs
|
||||
@@ -389,52 +495,82 @@ void CIO::process()
|
||||
dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
} else if (m_modemState == STATE_YSF) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
else if (m_modemState == STATE_YSF) {
|
||||
if (m_ysfEnable) {
|
||||
q15_t YSFVals[RX_BLOCK_SIZE];
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::arm_fir_fast_q15(&m_rrcFilter, dcSamples, YSFVals, RX_BLOCK_SIZE);
|
||||
::arm_fir_fast_q15(&m_rrc02Filter2, dcSamples, YSFVals, RX_BLOCK_SIZE);
|
||||
#else
|
||||
::arm_fir_fast_q15(&m_rrcFilter, samples, YSFVals, RX_BLOCK_SIZE);
|
||||
::arm_fir_fast_q15(&m_rrc02Filter2, samples, YSFVals, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
} else if (m_modemState == STATE_P25) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
else if (m_modemState == STATE_P25) {
|
||||
if (m_p25Enable) {
|
||||
q15_t P25Vals[RX_BLOCK_SIZE];
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, P25Vals, RX_BLOCK_SIZE);
|
||||
::arm_fir_fast_q15(&m_boxcar5Filter, dcSamples, P25Vals, RX_BLOCK_SIZE);
|
||||
#else
|
||||
::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE);
|
||||
::arm_fir_fast_q15(&m_boxcar5Filter, samples, P25Vals, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
} else if (m_modemState == STATE_NXDN) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
else if (m_modemState == STATE_NXDN) {
|
||||
if (m_nxdnEnable) {
|
||||
q15_t NXDNVals[RX_BLOCK_SIZE];
|
||||
#if defined(USE_NXDN_BOXCAR)
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::arm_fir_fast_q15(&m_boxcar10Filter, dcSamples, NXDNVals, RX_BLOCK_SIZE);
|
||||
#else
|
||||
::arm_fir_fast_q15(&m_boxcar10Filter, samples, NXDNVals, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
#else
|
||||
q15_t NXDNValsTmp[RX_BLOCK_SIZE];
|
||||
#if defined(USE_DCBLOCKER)
|
||||
::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNValsTmp, RX_BLOCK_SIZE);
|
||||
#else
|
||||
::arm_fir_fast_q15(&m_nxdnFilter, samples, NXDNValsTmp, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
q15_t NXDNVals[RX_BLOCK_SIZE];
|
||||
::arm_fir_fast_q15(&m_nxdnISincFilter, NXDNValsTmp, NXDNVals, RX_BLOCK_SIZE);
|
||||
|
||||
#endif
|
||||
nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
} else if (m_modemState == STATE_FM) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_FM)
|
||||
else if (m_modemState == STATE_FM) {
|
||||
bool cos = getCOSInt();
|
||||
#if defined(USE_DCBLOCKER)
|
||||
fm.samples(cos, dcSamples, RX_BLOCK_SIZE);
|
||||
fm.samples(cos, dcSamples, rssi, RX_BLOCK_SIZE);
|
||||
#else
|
||||
fm.samples(cos, samples, RX_BLOCK_SIZE);
|
||||
fm.samples(cos, samples, rssi, RX_BLOCK_SIZE);
|
||||
#endif
|
||||
} else if (m_modemState == STATE_DSTARCAL) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
else if (m_modemState == STATE_DSTARCAL) {
|
||||
q15_t GMSKVals[RX_BLOCK_SIZE];
|
||||
::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE);
|
||||
|
||||
calDStarRX.samples(GMSKVals, RX_BLOCK_SIZE);
|
||||
} else if (m_modemState == STATE_RSSICAL) {
|
||||
}
|
||||
#endif
|
||||
|
||||
else if (m_modemState == STATE_RSSICAL) {
|
||||
calRSSI.samples(rssi, RX_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
@@ -452,6 +588,7 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
|
||||
if (!m_tx) {
|
||||
m_tx = true;
|
||||
setPTTInt(m_pttInvert ? false : true);
|
||||
DEBUG1("TX ON");
|
||||
}
|
||||
|
||||
q15_t txLevel = 0;
|
||||
@@ -492,9 +629,9 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
|
||||
m_dacOverflow++;
|
||||
|
||||
if (control == NULL)
|
||||
m_txBuffer.put(res3, MARK_NONE);
|
||||
m_txBuffer.put({res3, MARK_NONE});
|
||||
else
|
||||
m_txBuffer.put(res3, control[i]);
|
||||
m_txBuffer.put({res3, control[i]});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,20 +653,39 @@ void CIO::setADCDetection(bool detect)
|
||||
m_detect = detect;
|
||||
}
|
||||
|
||||
void CIO::setMode()
|
||||
void CIO::setMode(MMDVM_STATE state)
|
||||
{
|
||||
if (state == m_modemState)
|
||||
return;
|
||||
|
||||
#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);
|
||||
switch (m_modemState) {
|
||||
case STATE_DSTAR: setDStarInt(false); break;
|
||||
case STATE_DMR: setDMRInt(false); break;
|
||||
case STATE_YSF: setYSFInt(false); break;
|
||||
case STATE_P25: setP25Int(false); break;
|
||||
case STATE_NXDN: setNXDNInt(false); break;
|
||||
case STATE_POCSAG: setPOCSAGInt(false); break;
|
||||
case STATE_FM: setFMInt(false); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case STATE_DSTAR: setDStarInt(true); break;
|
||||
case STATE_DMR: setDMRInt(true); break;
|
||||
case STATE_YSF: setYSFInt(true); break;
|
||||
case STATE_P25: setP25Int(true); break;
|
||||
case STATE_NXDN: setNXDNInt(true); break;
|
||||
case STATE_POCSAG: setPOCSAGInt(true); break;
|
||||
case STATE_FM: setFMInt(true); break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_modemState = state;
|
||||
}
|
||||
|
||||
void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset)
|
||||
void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout)
|
||||
{
|
||||
m_pttInvert = pttInvert;
|
||||
|
||||
@@ -545,6 +701,8 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx
|
||||
|
||||
m_rxDCOffset = DC_OFFSET + rxDCOffset;
|
||||
m_txDCOffset = DC_OFFSET + txDCOffset;
|
||||
|
||||
m_useCOSAsLockout = useCOSAsLockout;
|
||||
|
||||
if (rxInvert)
|
||||
m_rxLevel = -m_rxLevel;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,8 +21,12 @@
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "SampleRB.h"
|
||||
#include "RSSIRB.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
struct TSample {
|
||||
volatile uint16_t sample;
|
||||
volatile uint8_t control;
|
||||
};
|
||||
|
||||
class CIO {
|
||||
public:
|
||||
@@ -38,11 +42,11 @@ public:
|
||||
|
||||
void setDecode(bool dcd);
|
||||
void setADCDetection(bool detect);
|
||||
void setMode();
|
||||
void setMode(MMDVM_STATE state);
|
||||
|
||||
void interrupt();
|
||||
|
||||
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset);
|
||||
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, uint8_t fmTXLevel, int16_t txDCOffset, int16_t rxDCOffset, bool useCOSAsLockout);
|
||||
|
||||
void getOverflow(bool& adcOverflow, bool& dacOverflow);
|
||||
|
||||
@@ -54,28 +58,55 @@ public:
|
||||
void resetWatchdog();
|
||||
uint32_t getWatchdog();
|
||||
|
||||
uint8_t getCPU() const;
|
||||
|
||||
void getUDID(uint8_t* buffer);
|
||||
|
||||
void selfTest();
|
||||
|
||||
private:
|
||||
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;
|
||||
q31_t m_dcState[4];
|
||||
#endif
|
||||
|
||||
arm_fir_instance_q15 m_rrcFilter;
|
||||
#if defined(MODE_DSTAR)
|
||||
arm_fir_instance_q15 m_gaussianFilter;
|
||||
arm_fir_instance_q15 m_boxcarFilter;
|
||||
q15_t m_gaussianState[40U]; // NoTaps + BlockSize - 1, 12 + 20 - 1 plus some spare
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
arm_fir_instance_q15 m_rrc02Filter1;
|
||||
q15_t m_rrc02State1[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
arm_fir_instance_q15 m_rrc02Filter2;
|
||||
q15_t m_rrc02State2[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
arm_fir_instance_q15 m_boxcar5Filter;
|
||||
q15_t m_boxcar5State[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
#if defined(USE_NXDN_BOXCAR)
|
||||
arm_fir_instance_q15 m_boxcar10Filter;
|
||||
q15_t m_boxcar10State[40U]; // NoTaps + BlockSize - 1, 10 + 20 - 1 plus some spare
|
||||
#else
|
||||
arm_fir_instance_q15 m_nxdnFilter;
|
||||
arm_fir_instance_q15 m_nxdnISincFilter;
|
||||
q15_t m_rrcState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
||||
q15_t m_gaussianState[40U]; // NoTaps + BlockSize - 1, 12 + 20 - 1 plus some spare
|
||||
q15_t m_boxcarState[30U]; // NoTaps + BlockSize - 1, 6 + 20 - 1 plus some spare
|
||||
q15_t m_nxdnState[110U]; // NoTaps + BlockSize - 1, 82 + 20 - 1 plus some spare
|
||||
q15_t m_nxdnISincState[60U]; // NoTaps + BlockSize - 1, 32 + 20 - 1 plus some spare
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool m_pttInvert;
|
||||
q15_t m_rxLevel;
|
||||
@@ -91,6 +122,8 @@ private:
|
||||
uint16_t m_rxDCOffset;
|
||||
uint16_t m_txDCOffset;
|
||||
|
||||
bool m_useCOSAsLockout;
|
||||
|
||||
uint32_t m_ledCount;
|
||||
bool m_ledValue;
|
||||
|
||||
@@ -125,3 +158,4 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2025 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
@@ -185,14 +185,13 @@ void CIO::startInt()
|
||||
void CIO::interrupt()
|
||||
{
|
||||
if ((ADC->ADC_ISR & ADC_ISR_EOC_Chan) == ADC_ISR_EOC_Chan) { // Ensure there was an End-of-Conversion and we read the ISR reg
|
||||
uint8_t control = MARK_NONE;
|
||||
uint16_t sample = DC_OFFSET;
|
||||
TSample sample = {DC_OFFSET, MARK_NONE};
|
||||
|
||||
m_txBuffer.get(sample, control);
|
||||
DACC->DACC_CDR = sample;
|
||||
m_txBuffer.get(sample);
|
||||
DACC->DACC_CDR = sample.sample;
|
||||
|
||||
sample = ADC->ADC_CDR[ADC_CDR_Chan];
|
||||
m_rxBuffer.put(sample, control);
|
||||
sample.sample = ADC->ADC_CDR[ADC_CDR_Chan];
|
||||
m_rxBuffer.put(sample);
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
m_rssiBuffer.put(ADC->ADC_CDR[RSSI_CDR_Chan]);
|
||||
@@ -279,4 +278,33 @@ void CIO::delayInt(unsigned int dly)
|
||||
delay(dly);
|
||||
}
|
||||
|
||||
uint8_t CIO::getCPU() const
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
|
||||
// Code taken from https://github.com/emagii/at91sam3s/blob/master/examples/eefc_uniqueid/main.c
|
||||
void CIO::getUDID(uint8_t* buffer)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
|
||||
do {
|
||||
status = EFC1->EEFC_FSR;
|
||||
} while ( (status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY );
|
||||
|
||||
for (uint8_t i = 0; i < 16; i+=4) {
|
||||
buffer[i + 0] = *(uint32_t *)(IFLASH1_ADDR + i) >> 24;
|
||||
buffer[i + 1] = *(uint32_t *)(IFLASH1_ADDR + i) >> 16;
|
||||
buffer[i + 2] = *(uint32_t *)(IFLASH1_ADDR + i) >> 8;
|
||||
buffer[i + 3] = *(uint32_t *)(IFLASH1_ADDR + i) >> 0;
|
||||
}
|
||||
|
||||
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI;
|
||||
do {
|
||||
status = EFC1->EEFC_FSR;
|
||||
} while ( (status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -59,12 +59,21 @@
|
||||
#elif defined(STM32F4_DVM)
|
||||
#include "pins/pins_f4_stm32dvm_v3.h"
|
||||
|
||||
#elif defined(STM32F7_DVM)
|
||||
#include "pins/pins_f7_stm32dvm_v5.h"
|
||||
|
||||
#elif defined(DRCC_DVM_NQF)
|
||||
#include "pins/pins_f4_drcc_nqf.h"
|
||||
|
||||
#elif defined(DRCC_DVM_HHP446)
|
||||
#include "pins/pins_f4_drcc_hhp446.h"
|
||||
|
||||
#elif defined(STM32F4_EDA_405) || defined(STM32F4_EDA_446)
|
||||
#include "pins/pins_f4_stm32eda.h"
|
||||
|
||||
#else
|
||||
#error "A valid board type macro need to be defined."
|
||||
|
||||
#endif
|
||||
|
||||
#endif //#ifndef _IO_PINS_H
|
||||
#endif //#ifndef _IO_PINS_H
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* 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) 2017,2018,2020,2023,2025 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2019,2020 by BG5HHP
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -326,35 +326,40 @@ void CIO::startInt()
|
||||
|
||||
void CIO::interrupt()
|
||||
{
|
||||
uint8_t control = MARK_NONE;
|
||||
uint16_t sample = DC_OFFSET;
|
||||
TSample sample = {DC_OFFSET, MARK_NONE};
|
||||
uint16_t rawRSSI = 0U;
|
||||
|
||||
m_txBuffer.get(sample, control);
|
||||
m_txBuffer.get(sample);
|
||||
|
||||
// Send the value to the DAC
|
||||
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
|
||||
DAC_SetChannel2Data(DAC_Align_12b_R, sample);
|
||||
DAC_SetChannel2Data(DAC_Align_12b_R, sample.sample);
|
||||
#else
|
||||
DAC_SetChannel1Data(DAC_Align_12b_R, sample);
|
||||
DAC_SetChannel1Data(DAC_Align_12b_R, sample.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;
|
||||
sample.sample = 0U;
|
||||
} else {
|
||||
sample = ADC_GetConversionValue(ADC1);
|
||||
sample.sample = ADC_GetConversionValue(ADC1);
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
rawRSSI = ADC_GetConversionValue(ADC2);
|
||||
#endif
|
||||
}
|
||||
|
||||
// trigger next ADC1
|
||||
// Trigger next ADC1
|
||||
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
|
||||
ADC_SoftwareStartConv(ADC1);
|
||||
|
||||
m_rxBuffer.put(sample, control);
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
// Trigger next ADC2
|
||||
ADC_ClearFlag(ADC2, ADC_FLAG_EOC);
|
||||
ADC_SoftwareStartConv(ADC2);
|
||||
#endif
|
||||
|
||||
m_rxBuffer.put(sample);
|
||||
m_rssiBuffer.put(rawRSSI);
|
||||
|
||||
m_watchdog++;
|
||||
@@ -509,4 +514,21 @@ void CIO::delayInt(unsigned int dly)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CIO::getCPU() const
|
||||
{
|
||||
return 2U;
|
||||
}
|
||||
|
||||
void CIO::getUDID(uint8_t* buffer)
|
||||
{
|
||||
#if defined(STM32F4XX)
|
||||
::memcpy(buffer, (void *)0x1FFF7A10, 12U);
|
||||
#elif defined(STM32F722xx)
|
||||
::memcpy(buffer, (void *)0x1FF07A10, 12U);
|
||||
#elif defined(STM32F767xx)
|
||||
::memcpy(buffer, (void *)0x1FF0F420, 12U);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
-476
@@ -1,476 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
RX PB0 analog input (ADC1_8)
|
||||
RSSI PB1 analog input (ADC2_9)
|
||||
TX PA4 analog output (DAC_OUT1)
|
||||
|
||||
EXT_CLK PA15 input (AF: TIM2_CH1_ETR)
|
||||
|
||||
USART1_TXD PA9 output (AF)
|
||||
USART1_RXD PA10 input (AF)
|
||||
|
||||
*/
|
||||
|
||||
#define PIN_PTT 12
|
||||
#define PORT_PTT GPIOB
|
||||
#define BB_PTT *((bitband_t)BITBAND_PERIPH(&PORT_PTT->ODR, PIN_PTT))
|
||||
#define PIN_COSLED 5
|
||||
#define PORT_COSLED GPIOB
|
||||
#define BB_COSLED *((bitband_t)BITBAND_PERIPH(&PORT_COSLED->ODR, PIN_COSLED))
|
||||
#define PIN_LED 4
|
||||
#define PORT_LED GPIOB
|
||||
#define BB_LED *((bitband_t)BITBAND_PERIPH(&PORT_LED->ODR, PIN_LED))
|
||||
#define PIN_COS 13
|
||||
#define PORT_COS GPIOB
|
||||
#define BB_COS *((bitband_t)BITBAND_PERIPH(&PORT_COS->IDR, PIN_COS))
|
||||
|
||||
#define PIN_DSTAR 7
|
||||
#define PORT_DSTAR GPIOB
|
||||
#define BB_DSTAR *((bitband_t)BITBAND_PERIPH(&PORT_DSTAR->ODR, PIN_DSTAR))
|
||||
#define PIN_DMR 6
|
||||
#define PORT_DMR GPIOB
|
||||
#define BB_DMR *((bitband_t)BITBAND_PERIPH(&PORT_DMR->ODR, PIN_DMR))
|
||||
#define PIN_YSF 8
|
||||
#define PORT_YSF GPIOB
|
||||
#define BB_YSF *((bitband_t)BITBAND_PERIPH(&PORT_YSF->ODR, PIN_YSF))
|
||||
#define PIN_P25 9
|
||||
#define PORT_P25 GPIOB
|
||||
#define BB_P25 *((bitband_t)BITBAND_PERIPH(&PORT_P25->ODR, PIN_P25))
|
||||
#define PIN_NXDN 10
|
||||
#define PORT_NXDN GPIOB
|
||||
#define BB_NXDN *((bitband_t)BITBAND_PERIPH(&PORT_NXDN->ODR, PIN_NXDN))
|
||||
#define PIN_POCSAG 11
|
||||
#define PORT_POCSAG GPIOB
|
||||
#define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG))
|
||||
|
||||
#define PIN_RX 0
|
||||
#define PIN_RX_ADC_CH 8
|
||||
#define PORT_RX GPIOB
|
||||
#define PIN_RSSI 1
|
||||
#define PIN_RSSI_ADC_CH 9
|
||||
#define PORT_RSSI GPIOB
|
||||
#define PIN_TX 4
|
||||
#define PIN_TX_DAC_CH 1
|
||||
#define PORT_TX GPIOA
|
||||
|
||||
#define PIN_EXT_CLK 15
|
||||
#define SRC_EXT_CLK 15
|
||||
#define PORT_EXT_CLK GPIOA
|
||||
|
||||
#define PIN_USART1_TXD 9
|
||||
#define PORT_USART1_TXD GPIOA
|
||||
#define PIN_USART1_RXD 10
|
||||
#define PORT_USART1_RXD GPIOA
|
||||
|
||||
#else // defined(STM32F1_POG)
|
||||
#error "Either STM32F1_POG, or sth need to be defined"
|
||||
#endif // defined(STM32F1_POG)
|
||||
|
||||
const uint16_t DC_OFFSET = 2048U;
|
||||
|
||||
// Sampling frequency
|
||||
#define SAMP_FREQ 24000
|
||||
|
||||
extern "C" {
|
||||
void TIM2_IRQHandler() {
|
||||
if ((TIM2->SR & TIM_SR_UIF) == TIM_SR_UIF) {
|
||||
TIM2->SR = ~TIM_SR_UIF; // clear UI flag
|
||||
io.interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void delay(uint32_t cnt)
|
||||
{
|
||||
while(cnt--)
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
// source: http://www.freddiechopin.info/
|
||||
void GPIOConfigPin(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value)
|
||||
{
|
||||
volatile uint32_t *cr_ptr;
|
||||
uint32_t cr_value;
|
||||
|
||||
cr_ptr = &port_ptr->CRL; // configuration of pins [0,7] is in CRL
|
||||
|
||||
if (pin >= 8) // is pin in [8; 15]?
|
||||
{ // configuration of pins [8,15] is in CRH
|
||||
cr_ptr++; // advance to next struct element CRL -> CRH
|
||||
pin -= 8; // crop the pin number
|
||||
}
|
||||
|
||||
cr_value = *cr_ptr; // localize the CRL / CRH value
|
||||
|
||||
cr_value &= ~(0xF << (pin * 4)); // clear the MODE and CNF fields (now that pin is an analog input)
|
||||
cr_value |= (mode_cnf_value << (pin * 4)); // save new MODE and CNF value for desired pin
|
||||
|
||||
*cr_ptr = cr_value; // save localized value to CRL / CRL
|
||||
}
|
||||
|
||||
#if defined(STM32F1_POG)
|
||||
void FancyLEDEffect()
|
||||
{
|
||||
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25};
|
||||
|
||||
for(int i=0; i<7; i++){
|
||||
*foo[i] = 0x01;
|
||||
}
|
||||
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1);
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||
delay(SystemCoreClock/1000*100);
|
||||
for(int i=0; i<7; i++){
|
||||
*foo[i] = 0x00;
|
||||
}
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||
delay(SystemCoreClock/1000*20);
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||
delay(SystemCoreClock/1000*10);
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||
|
||||
*foo[0] = 0x01;
|
||||
for(int i=1; i<7; i++){
|
||||
delay(SystemCoreClock/1000*10);
|
||||
*foo[i-1] = 0x00;
|
||||
*foo[i] = 0x01;
|
||||
}
|
||||
for(int i=5; i>=0; i--){
|
||||
delay(SystemCoreClock/1000*10);
|
||||
*foo[i+1] = 0x00;
|
||||
*foo[i] = 0x01;
|
||||
}
|
||||
delay(SystemCoreClock/1000*10);
|
||||
*foo[5+1-6] = 0x00;
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||
delay(SystemCoreClock/1000*10);
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
|
||||
delay(SystemCoreClock/1000*50);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void GPIOInit()
|
||||
{
|
||||
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN
|
||||
| RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN
|
||||
| RCC_APB2ENR_AFIOEN; // enable all GPIOs
|
||||
|
||||
// set all ports to input with pull-down
|
||||
GPIOA->CRL = 0x88888888;
|
||||
GPIOA->CRH = 0x88888888;
|
||||
GPIOA->ODR = 0;
|
||||
GPIOB->CRL = 0x88888888;
|
||||
GPIOB->CRH = 0x88888888;
|
||||
GPIOB->ODR = 0;
|
||||
GPIOC->CRL = 0x88888888;
|
||||
GPIOC->CRH = 0x88888888;
|
||||
GPIOC->ODR = 0;
|
||||
GPIOD->CRL = 0x88888888;
|
||||
GPIOD->CRH = 0x88888888;
|
||||
GPIOD->ODR = 0;
|
||||
|
||||
// configure ports
|
||||
GPIOConfigPin(PORT_PTT, PIN_PTT, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_COSLED, PIN_COSLED, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_LED, PIN_LED, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_COS, PIN_COS, GPIO_CRL_CNF0_1);
|
||||
|
||||
GPIOConfigPin(PORT_DSTAR, PIN_DSTAR, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_DMR, PIN_DMR, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_YSF, PIN_YSF, GPIO_CRL_MODE0_1);
|
||||
GPIOConfigPin(PORT_P25, PIN_P25, GPIO_CRL_MODE0_1);
|
||||
#if !defined(USE_ALTERNATE_NXDN_LEDS)
|
||||
GPIOConfigPin(PORT_NXDN, PIN_NXDN, GPIO_CRL_MODE0_1);
|
||||
#endif
|
||||
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||
GPIOConfigPin(PORT_POCSAG, PIN_POCSAG, GPIO_CRL_MODE0_1);
|
||||
#endif
|
||||
|
||||
GPIOConfigPin(PORT_RX, PIN_RX, 0);
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
GPIOConfigPin(PORT_RSSI, PIN_RSSI, 0);
|
||||
#endif
|
||||
GPIOConfigPin(PORT_TX, PIN_TX, 0);
|
||||
|
||||
#if defined(EXTERNAL_OSC)
|
||||
#if defined(STM32F1_POG)
|
||||
GPIOConfigPin(PORT_EXT_CLK, PIN_EXT_CLK, GPIO_CRL_CNF0_0);
|
||||
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_TIM2_REMAP) | AFIO_MAPR_TIM2_REMAP_0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
|
||||
GPIOConfigPin(PORT_USART1_RXD, PIN_USART1_RXD, GPIO_CRL_CNF0_0);
|
||||
|
||||
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_SWJ_CFG) | AFIO_MAPR_SWJ_CFG_1;
|
||||
}
|
||||
|
||||
|
||||
static inline void ADCInit()
|
||||
{
|
||||
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_ADCPRE_Msk)
|
||||
| RCC_CFGR_ADCPRE_DIV6; // ADC clock divided by 6 (72MHz/6 = 12MHz)
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADC2EN;
|
||||
#endif
|
||||
|
||||
// Init ADCs in dual mode (RSSI)
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
ADC1->CR1 = ADC_CR1_DUALMOD_1|ADC_CR1_DUALMOD_2; // Regular simultaneous mode
|
||||
#endif
|
||||
|
||||
// Set sampling time to 7.5 cycles
|
||||
if (PIN_RX_ADC_CH < 10) {
|
||||
ADC1->SMPR2 = ADC_SMPR2_SMP0_0 << (3*PIN_RX_ADC_CH);
|
||||
} else {
|
||||
ADC1->SMPR1 = ADC_SMPR1_SMP10_0 << (3*PIN_RX_ADC_CH);
|
||||
}
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
if (PIN_RSSI_ADC_CH < 10) {
|
||||
ADC2->SMPR2 = ADC_SMPR2_SMP0_0 << (3*PIN_RSSI_ADC_CH);
|
||||
} else {
|
||||
ADC2->SMPR1 = ADC_SMPR1_SMP10_0 << (3*PIN_RSSI_ADC_CH);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set conversion channel (single conversion)
|
||||
ADC1->SQR3 = PIN_RX_ADC_CH;
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
ADC2->SQR3 = PIN_RSSI_ADC_CH;
|
||||
#endif
|
||||
|
||||
// Enable ADC
|
||||
ADC1->CR2 |= ADC_CR2_ADON;
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
// Enable ADC2
|
||||
ADC2->CR2 |= ADC_CR2_ADON;
|
||||
#endif
|
||||
|
||||
// Start calibration
|
||||
delay(6*2);
|
||||
ADC1->CR2 |= ADC_CR2_CAL;
|
||||
while((ADC1->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL)
|
||||
;
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
ADC2->CR2 |= ADC_CR2_CAL;
|
||||
while((ADC2->CR2 & ADC_CR2_CAL) == ADC_CR2_CAL)
|
||||
;
|
||||
#endif
|
||||
|
||||
// Trigger first conversion
|
||||
ADC1->CR2 |= ADC_CR2_ADON;
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
ADC2->CR2 |= ADC_CR2_ADON;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline void DACInit()
|
||||
{
|
||||
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
|
||||
|
||||
DAC->CR = DAC_CR_EN1;
|
||||
}
|
||||
|
||||
|
||||
static inline void TimerInit()
|
||||
{
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||
|
||||
#if defined(EXTERNAL_OSC)
|
||||
// Enable external clock, prescaler /4
|
||||
TIM2->SMCR = TIM_SMCR_ECE | TIM_SMCR_ETPS_1;
|
||||
#endif
|
||||
|
||||
// TIM2 output frequency
|
||||
TIM2->PSC = 0;
|
||||
#if defined(EXTERNAL_OSC)
|
||||
// TimerCount = ExternalOsc
|
||||
// /4 (external clock prescaler)
|
||||
// /SAMP_FREQ
|
||||
TIM2->ARR = (uint16_t) ((EXTERNAL_OSC/(4*SAMP_FREQ)) - 1);
|
||||
#else
|
||||
TIM2->ARR = (uint16_t) ((SystemCoreClock/(SAMP_FREQ)) - 1);
|
||||
#endif
|
||||
|
||||
// Enable TIse 1%-tolerance comM2 interrupt
|
||||
TIM2->DIER = TIM_DIER_UIE;
|
||||
NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
// Enable TIM2
|
||||
TIM2->CR1 |= TIM_CR1_CEN;
|
||||
}
|
||||
|
||||
|
||||
void CIO::initInt()
|
||||
{
|
||||
GPIOInit();
|
||||
ADCInit();
|
||||
DACInit();
|
||||
#if defined(STM32F1_POG)
|
||||
FancyLEDEffect();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CIO::startInt()
|
||||
{
|
||||
TimerInit();
|
||||
|
||||
BB_COSLED = 0;
|
||||
BB_LED = 1;
|
||||
}
|
||||
|
||||
void CIO::interrupt()
|
||||
{
|
||||
uint8_t control = MARK_NONE;
|
||||
uint16_t sample = DC_OFFSET;
|
||||
#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;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CIO::delayInt(unsigned int dly)
|
||||
{
|
||||
delay(dly);
|
||||
}
|
||||
|
||||
#endif
|
||||
+17
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018,2020,2025 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -161,15 +161,14 @@ void CIO::startInt()
|
||||
|
||||
void CIO::interrupt()
|
||||
{
|
||||
uint8_t control = MARK_NONE;
|
||||
uint16_t sample = DC_OFFSET;
|
||||
TSample sample = {DC_OFFSET, MARK_NONE};
|
||||
|
||||
m_txBuffer.get(sample, control);
|
||||
*(int16_t *)&(DAC0_DAT0L) = sample;
|
||||
m_txBuffer.get(sample);
|
||||
*(int16_t *)&(DAC0_DAT0L) = sample.sample;
|
||||
|
||||
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
|
||||
sample = ADC0_RA;
|
||||
m_rxBuffer.put(sample, control);
|
||||
sample.sample = ADC0_RA;
|
||||
m_rxBuffer.put(sample);
|
||||
}
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
@@ -263,4 +262,15 @@ void CIO::delayInt(unsigned int dly)
|
||||
delay(dly);
|
||||
}
|
||||
|
||||
uint8_t CIO::getCPU() const
|
||||
{
|
||||
return 1U;
|
||||
}
|
||||
|
||||
void CIO::getUDID(uint8_t* buffer)
|
||||
{
|
||||
::memcpy(buffer, (void *)0x4058, 16U);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32F105xC)
|
||||
#if defined(STM32F4XX) || defined(STM32F7XX)
|
||||
|
||||
#include "Config.h"
|
||||
#include "Globals.h"
|
||||
@@ -39,37 +39,55 @@ 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;
|
||||
#if defined(MODE_DSTAR)
|
||||
CDStarRX dstarRX;
|
||||
CDStarTX dstarTX;
|
||||
|
||||
CCalDStarRX calDStarRX;
|
||||
CCalDStarTX calDStarTX;
|
||||
CCalDMR calDMR;
|
||||
CCalP25 calP25;
|
||||
CCalNXDN calNXDN;
|
||||
CCalFM calFM;
|
||||
CCalPOCSAG calPOCSAG;
|
||||
CCalRSSI calRSSI;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
CDMRIdleRX dmrIdleRX;
|
||||
CDMRRX dmrRX;
|
||||
CDMRTX dmrTX;
|
||||
|
||||
CDMRDMORX dmrDMORX;
|
||||
CDMRDMOTX dmrDMOTX;
|
||||
|
||||
CCalDMR calDMR;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
CYSFRX ysfRX;
|
||||
CYSFTX ysfTX;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
CP25RX p25RX;
|
||||
CP25TX p25TX;
|
||||
|
||||
CCalP25 calP25;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
CNXDNRX nxdnRX;
|
||||
CNXDNTX nxdnTX;
|
||||
|
||||
CCalNXDN calNXDN;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
CPOCSAGTX pocsagTX;
|
||||
CCalPOCSAG calPOCSAG;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_FM)
|
||||
CFM fm;
|
||||
CCalFM calFM;
|
||||
#endif
|
||||
|
||||
CCalRSSI calRSSI;
|
||||
|
||||
CCWIdTX cwIdTX;
|
||||
|
||||
@@ -88,48 +106,74 @@ void loop()
|
||||
io.process();
|
||||
|
||||
// The following is for transmitting
|
||||
#if defined(MODE_DSTAR)
|
||||
if (m_dstarEnable && m_modemState == STATE_DSTAR)
|
||||
dstarTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
if (m_dmrEnable && m_modemState == STATE_DMR) {
|
||||
if (m_duplex)
|
||||
dmrTX.process();
|
||||
else
|
||||
dmrDMOTX.process();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
if (m_ysfEnable && m_modemState == STATE_YSF)
|
||||
ysfTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
if (m_p25Enable && m_modemState == STATE_P25)
|
||||
p25TX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||
nxdnTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
|
||||
pocsagTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_FM)
|
||||
if (m_fmEnable && m_modemState == STATE_FM)
|
||||
fm.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
if (m_modemState == STATE_DSTARCAL)
|
||||
calDStarTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
||||
calDMR.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_FM)
|
||||
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K || m_modemState == STATE_FMCAL30K)
|
||||
calFM.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
if (m_modemState == STATE_P25CAL1K)
|
||||
calP25.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
if (m_modemState == STATE_NXDNCAL1K)
|
||||
calNXDN.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
if (m_modemState == STATE_POCSAGCAL)
|
||||
calPOCSAG.process();
|
||||
|
||||
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K ||m_modemState == STATE_FMCAL30K)
|
||||
calFM.process();
|
||||
#endif
|
||||
|
||||
if (m_modemState == STATE_IDLE)
|
||||
cwIdTX.process();
|
||||
@@ -144,3 +188,4 @@ int main()
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -36,37 +36,55 @@ 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;
|
||||
#if defined(MODE_DSTAR)
|
||||
CDStarRX dstarRX;
|
||||
CDStarTX dstarTX;
|
||||
|
||||
CCalDStarRX calDStarRX;
|
||||
CCalDStarTX calDStarTX;
|
||||
CCalDMR calDMR;
|
||||
CCalFM calFM;
|
||||
CCalP25 calP25;
|
||||
CCalNXDN calNXDN;
|
||||
CCalPOCSAG calPOCSAG;
|
||||
CCalRSSI calRSSI;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
CDMRIdleRX dmrIdleRX;
|
||||
CDMRRX dmrRX;
|
||||
CDMRTX dmrTX;
|
||||
|
||||
CDMRDMORX dmrDMORX;
|
||||
CDMRDMOTX dmrDMOTX;
|
||||
|
||||
CCalDMR calDMR;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
CYSFRX ysfRX;
|
||||
CYSFTX ysfTX;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
CP25RX p25RX;
|
||||
CP25TX p25TX;
|
||||
|
||||
CCalP25 calP25;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
CNXDNRX nxdnRX;
|
||||
CNXDNTX nxdnTX;
|
||||
|
||||
CCalNXDN calNXDN;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
CPOCSAGTX pocsagTX;
|
||||
CCalPOCSAG calPOCSAG;
|
||||
#endif
|
||||
|
||||
#if defined(MODE_FM)
|
||||
CFM fm;
|
||||
CCalFM calFM;
|
||||
#endif
|
||||
|
||||
CCalRSSI calRSSI;
|
||||
|
||||
CCWIdTX cwIdTX;
|
||||
|
||||
@@ -85,49 +103,76 @@ void loop()
|
||||
io.process();
|
||||
|
||||
// The following is for transmitting
|
||||
#if defined(MODE_DSTAR)
|
||||
if (m_dstarEnable && m_modemState == STATE_DSTAR)
|
||||
dstarTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
if (m_dmrEnable && m_modemState == STATE_DMR) {
|
||||
if (m_duplex)
|
||||
dmrTX.process();
|
||||
else
|
||||
dmrDMOTX.process();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
if (m_ysfEnable && m_modemState == STATE_YSF)
|
||||
ysfTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
if (m_p25Enable && m_modemState == STATE_P25)
|
||||
p25TX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||
nxdnTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
if (m_pocsagEnable && (m_modemState == STATE_POCSAG || pocsagTX.busy()))
|
||||
pocsagTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_FM)
|
||||
if (m_fmEnable && m_modemState == STATE_FM)
|
||||
fm.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
if (m_modemState == STATE_DSTARCAL)
|
||||
calDStarTX.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
||||
calDMR.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_FM)
|
||||
if (m_modemState == STATE_FMCAL10K || m_modemState == STATE_FMCAL12K || m_modemState == STATE_FMCAL15K || m_modemState == STATE_FMCAL20K || m_modemState == STATE_FMCAL25K || m_modemState == STATE_FMCAL30K)
|
||||
calFM.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_P25)
|
||||
if (m_modemState == STATE_P25CAL1K)
|
||||
calP25.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
if (m_modemState == STATE_NXDNCAL1K)
|
||||
calNXDN.process();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
if (m_modemState == STATE_POCSAGCAL)
|
||||
calPOCSAG.process();
|
||||
#endif
|
||||
|
||||
if (m_modemState == STATE_IDLE)
|
||||
cwIdTX.process();
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@@ -133,19 +133,25 @@ DEFS_PI_F722=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_PI -DHSE_VAL
|
||||
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:
|
||||
# RB STM32F4_DVM board:
|
||||
DEFS_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||
# RB STM32F7 DVM board:
|
||||
DEFS_DVM722=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F7_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||
# MMDVM_RPT_Hat BG4TGO, BG5HHP board:
|
||||
DEFS_RPT_HAT_TGO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_RPT_HAT_TGO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||
# DRCC_DVM BG7NQF board:
|
||||
DEFS_DRCC_DVM=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DDRCC_DVM -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||
# WA0EDA F405 MTR2K, MASTR3 board:
|
||||
DEFS_EDA_405=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_EDA_405 -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||
# WA0EDA F446 MTR2K, MASTR3 board:
|
||||
DEFS_EDA_446=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_EDA_446 -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||
|
||||
|
||||
# Build compiler flags
|
||||
CFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
|
||||
CXXFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
|
||||
CXXFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4) -std=c++11
|
||||
CFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7)
|
||||
CXXFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7)
|
||||
CXXFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7) -std=c++11
|
||||
|
||||
# Linker flags
|
||||
LDFLAGS_F4 =-T stm32f4xx_link.ld $(MCFLAGS_F4) --specs=nosys.specs $(INCLUDES_LIBS_F4)
|
||||
@@ -218,17 +224,41 @@ f767: LDFLAGS+=$(LDFLAGS_F767)
|
||||
f767: release_f7
|
||||
|
||||
dvm: GitVersion.h
|
||||
dvm: CFLAGS+=$(CFLAGS_F4) $(DEFS_DVM)
|
||||
dvm: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DVM)
|
||||
dvm: CFLAGS+=$(CFLAGS_F4) $(DEFS_DVM) -DDRCC_DVM_446
|
||||
dvm: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DVM) -DDRCC_DVM_446
|
||||
dvm: LDFLAGS+=$(LDFLAGS_F4)
|
||||
dvm: release_f4
|
||||
|
||||
dvm722: GitVersion.h
|
||||
dvm722: CFLAGS+=$(CFLAGS_F7) $(DEFS_DVM722) -DDRCC_DVM_722
|
||||
dvm722: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_DVM722) -DDRCC_DVM_722
|
||||
dvm722: LDFLAGS+=$(LDFLAGS_F722)
|
||||
dvm722: release_f7
|
||||
|
||||
drcc_nqf: GitVersion.h
|
||||
drcc_nqf: CFLAGS+=$(CFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_NQF
|
||||
drcc_nqf: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_NQF
|
||||
drcc_nqf: LDFLAGS+=$(LDFLAGS_F4)
|
||||
drcc_nqf: release_f4
|
||||
|
||||
hhp446: GitVersion.h
|
||||
hhp446: CFLAGS+=$(CFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_HHP446
|
||||
hhp446: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DRCC_DVM) -DDRCC_DVM_HHP446
|
||||
hhp446: LDFLAGS+=$(LDFLAGS_F4)
|
||||
hhp446: release_f4
|
||||
|
||||
eda405: GitVersion.h
|
||||
eda405: CFLAGS+=$(CFLAGS_F4) $(DEFS_EDA_405)
|
||||
eda405: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_EDA_405)
|
||||
eda405: LDFLAGS+=$(LDFLAGS_F4)
|
||||
eda405: release_f4
|
||||
|
||||
eda446: GitVersion.h
|
||||
eda446: CFLAGS+=$(CFLAGS_F4) $(DEFS_EDA_446)
|
||||
eda446: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_EDA_446)
|
||||
eda446: LDFLAGS+=$(LDFLAGS_F4)
|
||||
eda446: release_f4
|
||||
|
||||
release_f4: $(BINDIR)
|
||||
release_f4: $(OBJDIR_F4)
|
||||
release_f4: $(BINDIR)/$(BINHEX_F4)
|
||||
@@ -338,27 +368,27 @@ 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
|
||||
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R /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
|
||||
/usr/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R /dev/ttyAMA0
|
||||
endif
|
||||
|
||||
deploy-f4m: deploy-pi
|
||||
deploy-dvm: deploy-pi
|
||||
deploy-eda405: deploy-pi
|
||||
deploy-eda446: deploy-pi
|
||||
|
||||
deploy-pi-f7:
|
||||
ifneq ($(wildcard /usr/local/bin/stm32flash),)
|
||||
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
||||
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
|
||||
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R /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
|
||||
/usr/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R /dev/ttyAMA0
|
||||
endif
|
||||
|
||||
deploy-f7m: deploy-pi-f7
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/make
|
||||
# makefile for the arduino due (works with arduino IDE 1.6.11)
|
||||
# makefile for the arduino due (works with arduino IDE 1.6.12)
|
||||
#
|
||||
# The original file can be found at https://github.com/pauldreik/arduino-due-makefile
|
||||
#
|
||||
@@ -34,7 +34,7 @@ OBJCOPY:=$(ADIR)/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-n
|
||||
|
||||
C:=$(CC)
|
||||
#SAM:=arduino/sam/
|
||||
SAM:=$(ADIR)/packages/arduino/hardware/sam/1.6.11
|
||||
SAM:=$(ADIR)/packages/arduino/hardware/sam/1.6.12
|
||||
#CMSIS:=arduino/sam/system/CMSIS/
|
||||
#LIBSAM:=arduino/sam/system/libsam
|
||||
TMPDIR:=$(PWD)/build
|
||||
|
||||
-165
@@ -1,165 +0,0 @@
|
||||
# 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
|
||||
+6
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-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
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "NXDNRX.h"
|
||||
#include "Utils.h"
|
||||
@@ -403,3 +406,5 @@ void CNXDNRX::writeRSSIData(uint8_t* data)
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018 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
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +16,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
|
||||
#if !defined(NXDNRX_H)
|
||||
#define NXDNRX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "NXDNDefines.h"
|
||||
|
||||
enum NXDNRX_STATE {
|
||||
@@ -67,3 +70,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+10
-3
@@ -18,6 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "NXDNTX.h"
|
||||
|
||||
@@ -81,7 +84,8 @@ void CNXDNTX::process()
|
||||
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[2U];
|
||||
} else {
|
||||
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++) {
|
||||
uint8_t c = m_buffer.get();
|
||||
uint8_t c = 0U;
|
||||
m_buffer.get(c);
|
||||
m_poBuffer[m_poLen++] = c;
|
||||
}
|
||||
}
|
||||
@@ -122,7 +126,7 @@ void CNXDNTX::process()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CNXDNTX::writeData(const uint8_t* data, uint8_t length)
|
||||
uint8_t CNXDNTX::writeData(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
|
||||
return 4U;
|
||||
@@ -171,7 +175,7 @@ void CNXDNTX::writeByte(uint8_t c)
|
||||
|
||||
void CNXDNTX::writeSilence()
|
||||
{
|
||||
q15_t inBuffer[4U] = {0x00U, 0x00U, 0x00U, 0x00U};
|
||||
q15_t inBuffer[4U] = {0, 0, 0, 0};
|
||||
q15_t intBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
|
||||
q15_t outBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
|
||||
|
||||
@@ -199,3 +203,6 @@ void CNXDNTX::setParams(uint8_t txHang)
|
||||
{
|
||||
m_txHang = txHang * 600U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,18 +16,20 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_NXDN)
|
||||
|
||||
#if !defined(NXDNTX_H)
|
||||
#define NXDNTX_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "SerialRB.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
class CNXDNTX {
|
||||
public:
|
||||
CNXDNTX();
|
||||
|
||||
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
||||
|
||||
void process();
|
||||
|
||||
@@ -38,7 +40,7 @@ public:
|
||||
void setParams(uint8_t txHang);
|
||||
|
||||
private:
|
||||
CSerialRB m_buffer;
|
||||
CRingBuffer<uint8_t> m_buffer;
|
||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||
arm_fir_instance_q15 m_sincFilter;
|
||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||
@@ -55,3 +57,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -18,6 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_P25)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "P25RX.h"
|
||||
#include "Utils.h"
|
||||
@@ -535,3 +538,6 @@ void CP25RX::writeRSSILdu(uint8_t* ldu)
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,10 +17,13 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_P25)
|
||||
|
||||
#if !defined(P25RX_H)
|
||||
#define P25RX_H
|
||||
|
||||
#include "Config.h"
|
||||
#include "P25Defines.h"
|
||||
|
||||
enum P25RX_STATE {
|
||||
@@ -72,3 +75,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_P25)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "P25TX.h"
|
||||
|
||||
@@ -75,9 +78,11 @@ void CP25TX::process()
|
||||
for (uint16_t i = 0U; i < m_txDelay; i++)
|
||||
m_poBuffer[m_poLen++] = P25_START_SYNC;
|
||||
} else {
|
||||
uint8_t length = m_buffer.get();
|
||||
uint8_t length;
|
||||
m_buffer.get(length);
|
||||
for (uint8_t i = 0U; i < length; i++) {
|
||||
uint8_t c = m_buffer.get();
|
||||
uint8_t c = 0U;
|
||||
m_buffer.get(c);
|
||||
m_poBuffer[m_poLen++] = c;
|
||||
}
|
||||
}
|
||||
@@ -118,7 +123,7 @@ void CP25TX::process()
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CP25TX::writeData(const uint8_t* data, uint8_t length)
|
||||
uint8_t CP25TX::writeData(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length < (P25_TERM_FRAME_LENGTH_BYTES + 1U))
|
||||
return 4U;
|
||||
@@ -168,7 +173,7 @@ void CP25TX::writeByte(uint8_t c)
|
||||
|
||||
void CP25TX::writeSilence()
|
||||
{
|
||||
q15_t inBuffer[4U] = {0x00U, 0x00U, 0x00U, 0x00U};
|
||||
q15_t inBuffer[4U] = {0, 0, 0, 0};
|
||||
q15_t intBuffer[P25_RADIO_SYMBOL_LENGTH * 4U];
|
||||
q15_t outBuffer[P25_RADIO_SYMBOL_LENGTH * 4U];
|
||||
|
||||
@@ -196,3 +201,6 @@ void CP25TX::setParams(uint8_t txHang)
|
||||
{
|
||||
m_txHang = txHang * 1200U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -16,18 +16,20 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_P25)
|
||||
|
||||
#if !defined(P25TX_H)
|
||||
#define P25TX_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "SerialRB.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
class CP25TX {
|
||||
public:
|
||||
CP25TX();
|
||||
|
||||
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
||||
|
||||
void process();
|
||||
|
||||
@@ -38,7 +40,7 @@ public:
|
||||
void setParams(uint8_t txHang);
|
||||
|
||||
private:
|
||||
CSerialRB m_buffer;
|
||||
CRingBuffer<uint8_t> m_buffer;
|
||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||
arm_fir_instance_q15 m_lpFilter;
|
||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||
@@ -55,3 +57,6 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+9
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-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
|
||||
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "POCSAGTX.h"
|
||||
|
||||
@@ -61,7 +64,8 @@ void CPOCSAGTX::process()
|
||||
m_poBuffer[m_poLen++] = POCSAG_SYNC;
|
||||
} else {
|
||||
for (uint8_t i = 0U; i < POCSAG_FRAME_LENGTH_BYTES; i++) {
|
||||
uint8_t c = m_buffer.get();
|
||||
uint8_t c = 0U;
|
||||
m_buffer.get(c);
|
||||
m_poBuffer[m_poLen++] = c;
|
||||
}
|
||||
}
|
||||
@@ -95,7 +99,7 @@ bool CPOCSAGTX::busy()
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint8_t length)
|
||||
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
if (length != POCSAG_FRAME_LENGTH_BYTES)
|
||||
return 4U;
|
||||
@@ -147,3 +151,5 @@ uint8_t CPOCSAGTX::getSpace() const
|
||||
return m_buffer.getSpace() / POCSAG_FRAME_LENGTH_BYTES;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+10
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,18 +16,20 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_POCSAG)
|
||||
|
||||
#if !defined(POCSAGTX_H)
|
||||
#define POCSAGTX_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "SerialRB.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
class CPOCSAGTX {
|
||||
public:
|
||||
CPOCSAGTX();
|
||||
|
||||
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||
uint8_t writeData(const uint8_t* data, uint16_t length);
|
||||
|
||||
void writeByte(uint8_t c);
|
||||
|
||||
@@ -40,7 +42,7 @@ public:
|
||||
bool busy();
|
||||
|
||||
private:
|
||||
CSerialRB m_buffer;
|
||||
CRingBuffer<uint8_t> m_buffer;
|
||||
arm_fir_instance_q15 m_modFilter;
|
||||
q15_t m_modState[170U]; // NoTaps + BlockSize - 1, 6 + 160 - 1 plus some spare
|
||||
uint8_t m_poBuffer[200U];
|
||||
@@ -51,3 +53,5 @@ private:
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,17 +1,35 @@
|
||||
This is the source code of the MMDVM firmware that supports D-Star, DMR,
|
||||
System Fusion, P25, NXDN, POCSAG, and FM modes.
|
||||
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion, P25, NXDN, POCSAG, and FM modes.
|
||||
|
||||
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, M4, or M7 processors with a clock speed
|
||||
greater than 70 MHz, and access to at least one analogue to digital converter
|
||||
and one digital to analogue converter.
|
||||
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.
|
||||
|
||||
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 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 supplied via the ARM GCC compiler. The Teensy support uses Teensyduino.
|
||||
|
||||
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.
|
||||
This software is licenced under the GPL v2 and is primarily intended for amateur and educational use.
|
||||
|
||||
Portions of the ARM support code include the following copyright:
|
||||
|
||||
Copyright (c) 2011 - 2013 ARM LIMITED
|
||||
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-102
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
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
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020,2026 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
|
||||
@@ -16,21 +17,19 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(FMDOWNSAMPLERB_H)
|
||||
#define FMDOWNSAMPLERB_H
|
||||
#if !defined(RINGBUFFER_H)
|
||||
#define RINGBUFFER_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>
|
||||
#undef PI
|
||||
#endif
|
||||
|
||||
#if defined(__SAM3X8E__) || defined(STM32F105xC)
|
||||
#if defined(__SAM3X8E__)
|
||||
#define ARM_MATH_CM3
|
||||
#elif defined(STM32F7XX)
|
||||
#define ARM_MATH_CM7
|
||||
@@ -42,27 +41,34 @@
|
||||
|
||||
#include <arm_math.h>
|
||||
|
||||
class CFMDownsampleRB {
|
||||
template <typename TDATATYPE>
|
||||
class CRingBuffer {
|
||||
public:
|
||||
CFMDownsampleRB(uint16_t length);
|
||||
CRingBuffer(uint16_t length = 370U);
|
||||
|
||||
uint16_t getSpace() const;
|
||||
|
||||
uint16_t getData() const;
|
||||
|
||||
bool put(uint8_t sample);
|
||||
bool put(const TDATATYPE& item) volatile;
|
||||
|
||||
bool get(uint8_t& sample);
|
||||
bool get(TDATATYPE& item) volatile;
|
||||
|
||||
TDATATYPE peek() const;
|
||||
|
||||
bool hasOverflowed();
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
uint16_t m_length;
|
||||
volatile uint8_t* m_samples;
|
||||
volatile uint16_t m_head;
|
||||
volatile uint16_t m_tail;
|
||||
volatile bool m_full;
|
||||
bool m_overflow;
|
||||
uint16_t m_length;
|
||||
TDATATYPE* m_buffer;
|
||||
volatile uint16_t m_head;
|
||||
volatile uint16_t m_tail;
|
||||
volatile bool m_full;
|
||||
bool m_overflow;
|
||||
};
|
||||
|
||||
#include "RingBuffer.impl.h"
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020,2026 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
|
||||
@@ -16,20 +17,19 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "RingBuffer.h"
|
||||
|
||||
#include "FMDownsampleRB.h"
|
||||
|
||||
CFMDownsampleRB::CFMDownsampleRB(uint16_t length) :
|
||||
template <typename TDATATYPE> CRingBuffer<TDATATYPE>::CRingBuffer(uint16_t length) :
|
||||
m_length(length),
|
||||
m_head(0U),
|
||||
m_tail(0U),
|
||||
m_full(false),
|
||||
m_overflow(false)
|
||||
{
|
||||
m_samples = new uint8_t[length];
|
||||
m_buffer = new TDATATYPE[length];
|
||||
}
|
||||
|
||||
uint16_t CFMDownsampleRB::getSpace() const
|
||||
template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getSpace() const
|
||||
{
|
||||
uint16_t n = 0U;
|
||||
|
||||
@@ -46,7 +46,7 @@ uint16_t CFMDownsampleRB::getSpace() const
|
||||
return n;
|
||||
}
|
||||
|
||||
uint16_t CFMDownsampleRB::getData() const
|
||||
template <typename TDATATYPE> uint16_t CRingBuffer<TDATATYPE>::getData() const
|
||||
{
|
||||
if (m_tail == m_head)
|
||||
return m_full ? m_length : 0U;
|
||||
@@ -56,14 +56,14 @@ uint16_t CFMDownsampleRB::getData() const
|
||||
return m_length - m_tail + m_head;
|
||||
}
|
||||
|
||||
bool CFMDownsampleRB::put(uint8_t sample)
|
||||
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::put(const TDATATYPE& item) volatile
|
||||
{
|
||||
if (m_full) {
|
||||
m_overflow = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_samples[m_head] = sample;
|
||||
m_buffer[m_head] = item;
|
||||
|
||||
m_head++;
|
||||
if (m_head >= m_length)
|
||||
@@ -75,12 +75,17 @@ bool CFMDownsampleRB::put(uint8_t sample)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFMDownsampleRB::get(uint8_t& sample)
|
||||
template <typename TDATATYPE> TDATATYPE CRingBuffer<TDATATYPE>::peek() const
|
||||
{
|
||||
return m_buffer[m_tail];
|
||||
}
|
||||
|
||||
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::get(TDATATYPE& item) volatile
|
||||
{
|
||||
if (m_head == m_tail && !m_full)
|
||||
return false;
|
||||
|
||||
sample = m_samples[m_tail];
|
||||
item = m_buffer[m_tail];
|
||||
|
||||
m_full = false;
|
||||
|
||||
@@ -91,7 +96,7 @@ bool CFMDownsampleRB::get(uint8_t& sample)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFMDownsampleRB::hasOverflowed()
|
||||
template <typename TDATATYPE> bool CRingBuffer<TDATATYPE>::hasOverflowed()
|
||||
{
|
||||
bool overflow = m_overflow;
|
||||
|
||||
@@ -99,3 +104,11 @@ bool CFMDownsampleRB::hasOverflowed()
|
||||
|
||||
return overflow;
|
||||
}
|
||||
|
||||
template <typename TDATATYPE> void CRingBuffer<TDATATYPE>::reset()
|
||||
{
|
||||
m_head = 0U;
|
||||
m_tail = 0U;
|
||||
m_full = false;
|
||||
m_overflow = false;
|
||||
}
|
||||
Submodule STM32F10X_Lib deleted from 417e0c2f4a
+1
-1
Submodule STM32F4XX_Lib updated: bcd346f530...18aeb6ea3a
+1
-1
Submodule STM32F7XX_Lib updated: 2d5f4236fa...6241f7c05e
+3
-1
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
* source: http://mightydevices.com/?p=144
|
||||
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
|
||||
*
|
||||
* Source: http://mightydevices.com/?p=144
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (c) 2020 by Geoffrey Merck F4FXL - KC3FRA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if defined(STM32F4XX) || defined(STM32F7XX)
|
||||
|
||||
#include "STMUART.h"
|
||||
|
||||
CSTMUART::CSTMUART() :
|
||||
m_usart(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CSTMUART::init(USART_TypeDef* usart)
|
||||
{
|
||||
m_usart = usart;
|
||||
}
|
||||
|
||||
void CSTMUART::write(const uint8_t * data, uint16_t length)
|
||||
{
|
||||
if(length == 0U || m_usart == NULL)
|
||||
return;
|
||||
|
||||
|
||||
m_txFifo.put(data[0]);
|
||||
USART_ITConfig(m_usart, USART_IT_TXE, ENABLE);//switch TX IRQ is on
|
||||
|
||||
for(uint16_t i = 1U; i < length; i++) {
|
||||
m_txFifo.put(data[i]);
|
||||
}
|
||||
|
||||
USART_ITConfig(m_usart, USART_IT_TXE, ENABLE);//make sure TX IRQ is on
|
||||
}
|
||||
|
||||
uint8_t CSTMUART::read()
|
||||
{
|
||||
return m_rxFifo.get();
|
||||
}
|
||||
|
||||
void CSTMUART::handleIRQ()
|
||||
{
|
||||
if(m_usart == NULL)
|
||||
return;
|
||||
|
||||
if (USART_GetITStatus(m_usart, USART_IT_RXNE)) {
|
||||
if(!m_rxFifo.isFull())
|
||||
m_rxFifo.put((uint8_t) USART_ReceiveData(m_usart));
|
||||
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
|
||||
}
|
||||
|
||||
if (USART_GetITStatus(m_usart, USART_IT_TXE)) {
|
||||
if(!m_txFifo.isEmpty())
|
||||
USART_SendData(m_usart, m_txFifo.get());
|
||||
|
||||
USART_ClearITPendingBit(m_usart, USART_IT_TXE);
|
||||
|
||||
if (m_txFifo.isEmpty()) // if there's no more data to transmit then turn off TX interrupts
|
||||
USART_ITConfig(m_usart, USART_IT_TXE, DISABLE);
|
||||
}
|
||||
}
|
||||
|
||||
// Flushes the transmit shift register
|
||||
// warning: this call is blocking
|
||||
void CSTMUART::flush()
|
||||
{
|
||||
if(m_usart == NULL)
|
||||
return;
|
||||
|
||||
// wait until the TXE shows the shift register is empty
|
||||
while (USART_GetITStatus(m_usart, USART_FLAG_TXE))
|
||||
;
|
||||
}
|
||||
|
||||
uint16_t CSTMUART::available()
|
||||
{
|
||||
return m_rxFifo.isEmpty() ? 0U : 1U;
|
||||
}
|
||||
|
||||
uint16_t CSTMUART::availableForWrite()
|
||||
{
|
||||
return m_txFifo.isFull() ? 0U : 1U;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (c) 2020 by Geoffrey Merck F4FXL - KC3FRA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if defined(STM32F4XX) || defined(STM32F7XX)
|
||||
#if !defined(STMUART_H)
|
||||
#define STMUART_H
|
||||
|
||||
#if defined(STM32F4XX)
|
||||
#include "stm32f4xx.h"
|
||||
#elif defined(STM32F7XX)
|
||||
#include "stm32f7xx.h"
|
||||
#endif
|
||||
|
||||
const uint16_t BUFFER_SIZE = 2048U; //needs to be a power of 2 !
|
||||
const uint16_t BUFFER_MASK = BUFFER_SIZE - 1;
|
||||
|
||||
class CSTMUARTFIFO {
|
||||
public:
|
||||
CSTMUARTFIFO() :
|
||||
m_head(0U),
|
||||
m_tail(0U)
|
||||
{
|
||||
}
|
||||
|
||||
void put(uint8_t data)
|
||||
{
|
||||
m_buffer[BUFFER_MASK & (m_head++)] = data;
|
||||
}
|
||||
|
||||
uint8_t get()
|
||||
{
|
||||
return m_buffer[BUFFER_MASK & (m_tail++)];
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
m_tail = 0U;
|
||||
m_head = 0U;
|
||||
}
|
||||
|
||||
bool isEmpty()
|
||||
{
|
||||
return m_tail == m_head;
|
||||
}
|
||||
|
||||
bool isFull()
|
||||
{
|
||||
return ((m_head + 1U) & BUFFER_MASK) == (m_tail & BUFFER_MASK);
|
||||
}
|
||||
|
||||
private:
|
||||
volatile uint8_t m_buffer[BUFFER_SIZE];
|
||||
volatile uint16_t m_head;
|
||||
volatile uint16_t m_tail;
|
||||
};
|
||||
|
||||
class CSTMUART {
|
||||
public:
|
||||
CSTMUART();
|
||||
void init(USART_TypeDef* usart);
|
||||
void write(const uint8_t * data, uint16_t length);
|
||||
uint8_t read();
|
||||
void handleIRQ();
|
||||
void flush();
|
||||
uint16_t available();
|
||||
uint16_t availableForWrite();
|
||||
|
||||
private:
|
||||
USART_TypeDef * m_usart;
|
||||
CSTMUARTFIFO m_rxFifo;
|
||||
CSTMUARTFIFO m_txFifo;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user