mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-10-16 08:44:11 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9410e724b8 | ||
|
|
6f7b95a15c | ||
|
|
d5c2fe9280 | ||
|
|
450005d611 | ||
|
|
97a72f5b7f | ||
|
|
ce6d03ae13 | ||
|
|
23f7b6a750 | ||
|
|
36a4404c5c | ||
|
|
66241f2f1b | ||
|
|
e5aab0f165 | ||
|
|
14a4dc2bf9 | ||
|
|
42408d5a9a | ||
|
|
55cb3945df | ||
|
|
a4a95ba5d0 | ||
|
|
8a1ac05df2 | ||
|
|
78ae7f3b33 | ||
|
|
c783d6d101 | ||
|
|
3ea95ce53d | ||
|
|
16d978cea2 | ||
|
|
e43c992249 | ||
|
|
e78fc5b701 | ||
|
|
eebfc56013 | ||
|
|
1d4bd4e409 | ||
|
|
9f28d2f69a | ||
|
|
9c01a6328a | ||
|
|
46528127dc | ||
|
|
b34d3c3dbd | ||
|
|
2bc99deec2 | ||
|
|
a6b6219c6d | ||
|
|
caaf090b10 | ||
|
|
01b7641bd1 | ||
|
|
b42ddbbf42 | ||
|
|
f32b8dc4e8 | ||
|
|
9e6a4ca6df | ||
|
|
91e5d588b0 | ||
|
|
555c308749 | ||
|
|
7b88e883f9 | ||
|
|
e7b52023c6 | ||
|
|
e7a40343b1 | ||
|
|
dfc262bbcd | ||
|
|
615c705044 | ||
|
|
c59c32b350 | ||
|
|
d69df42de4 | ||
|
|
99dafe6327 | ||
|
|
5da3c9352d | ||
|
|
fdc15b355f | ||
|
|
4f49f65a1c | ||
|
|
d99e21f0f9 | ||
|
|
9b5bbee265 | ||
|
|
b5ca5e3839 | ||
|
|
b988750e78 | ||
|
|
78a51d416d | ||
|
|
3a539e1243 | ||
|
|
db133c819e | ||
|
|
02d5218baa | ||
|
|
394d0cbc6b | ||
|
|
b4456aed28 | ||
|
|
9e56268156 | ||
|
|
94e65ba6cc | ||
|
|
2ec02e53e3 | ||
|
|
c6e9227aee | ||
|
|
e1d1faea82 | ||
|
|
4871ad1210 | ||
|
|
7b03336469 | ||
|
|
b846e5a7f3 | ||
|
|
ee1d512132 | ||
|
|
628665175c | ||
|
|
a921df7335 | ||
|
|
6bbc716e4b | ||
|
|
cf448158cb | ||
|
|
6a6688ea8d | ||
|
|
c86ba51523 | ||
|
|
a8eae44209 | ||
|
|
efa407a579 | ||
|
|
b54dc34215 | ||
|
|
167296200d | ||
|
|
ca6601ca6d | ||
|
|
8d7b4ef84d | ||
|
|
2279162db5 | ||
|
|
9cfbdebc7b | ||
|
|
7583446380 | ||
|
|
94b4fe3fd6 | ||
|
|
d86b10fc1d | ||
|
|
7996a45125 | ||
|
|
655e7f8218 | ||
|
|
c2a3f83a9f | ||
|
|
0505e76422 | ||
|
|
265828b127 | ||
|
|
4134a656b0 | ||
|
|
cd0bd6e5c4 | ||
|
|
418ce895cb | ||
|
|
8a9510b48a | ||
|
|
b22ada3fa2 | ||
|
|
b4ac4838fd | ||
|
|
89000729d2 | ||
|
|
abea72b4d5 | ||
|
|
76c3e5786c | ||
|
|
793407fe16 | ||
|
|
990bf2a16a | ||
|
|
ea37f67b91 | ||
|
|
a805652f48 | ||
|
|
eb4cd221b2 | ||
|
|
a244b86f36 | ||
|
|
56a12a61c2 | ||
|
|
595f38b796 | ||
|
|
d6b7796c25 | ||
|
|
70e1fd4264 | ||
|
|
00bc8be152 | ||
|
|
cce2cc3cfc | ||
|
|
1f5a4f1ad7 | ||
|
|
a60059bc90 | ||
|
|
6c6b6c19fc | ||
|
|
5b1075f0f7 | ||
|
|
17007dd1e4 | ||
|
|
8f317fd332 | ||
|
|
1cee9e19c0 | ||
|
|
5b313b7cec | ||
|
|
8b52d372eb | ||
|
|
f4637585f6 | ||
|
|
3e03fcff8e | ||
|
|
74682e7ac0 | ||
|
|
20cf355e7e | ||
|
|
04ca97e5f8 | ||
|
|
669acb99e8 | ||
|
|
ba81fa7396 | ||
|
|
8540964097 | ||
|
|
9d1ebc0f8f | ||
|
|
786e57d043 | ||
|
|
902b079de2 | ||
|
|
54f54ab518 | ||
|
|
f8d767913e | ||
|
|
266db8bedb | ||
|
|
6c4496e034 | ||
|
|
8db83708ca | ||
|
|
7f45a0da83 | ||
|
|
ce03ad4ab7 | ||
|
|
ae9e35ccad | ||
|
|
9e5234539e | ||
|
|
dea7c714c0 | ||
|
|
4690186812 | ||
|
|
399b6e1d85 | ||
|
|
c2ed9d4ae7 | ||
|
|
1dc23a4aa6 | ||
|
|
61b05dd5af | ||
|
|
00a7f15011 | ||
|
|
8a5d5bc286 | ||
|
|
c80c6a7797 | ||
|
|
96c214c359 | ||
|
|
6d5f098e41 | ||
|
|
e53aec348e | ||
|
|
9722c85585 | ||
|
|
1a9c0d3ee7 |
+175
-1
@@ -21,20 +21,191 @@
|
|||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "CalDMR.h"
|
#include "CalDMR.h"
|
||||||
|
|
||||||
|
// Voice LC BS Header, CC: 1, srcID: 1, dstID: TG9
|
||||||
|
const uint8_t VH_1K[] = {0x00U,
|
||||||
|
0x00U, 0x20U, 0x08U, 0x08U, 0x02U, 0x38U, 0x15U, 0x00U, 0x2CU, 0xA0U, 0x14U,
|
||||||
|
0x60U, 0x84U, 0x6DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xDEU, 0x30U, 0x30U,
|
||||||
|
0x01U, 0x10U, 0x01U, 0x40U, 0x03U, 0xC0U, 0x13U, 0xC1U, 0x1EU, 0x80U, 0x6FU};
|
||||||
|
|
||||||
|
// Voice Term BS with LC, CC: 1, srcID: 1, dstID: TG9
|
||||||
|
const uint8_t VT_1K[] = {0x00U,
|
||||||
|
0x00U, 0x4FU, 0x08U, 0xDCU, 0x02U, 0x88U, 0x15U, 0x78U, 0x2CU, 0xD0U, 0x14U,
|
||||||
|
0xC0U, 0x84U, 0xADU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD9U, 0x65U, 0x24U,
|
||||||
|
0x02U, 0x28U, 0x06U, 0x20U, 0x0FU, 0x80U, 0x1BU, 0xC1U, 0x07U, 0x80U, 0x5CU};
|
||||||
|
|
||||||
|
// Voice LC MS Header, CC: 1, srcID: 1, dstID: TG9
|
||||||
|
const uint8_t VH_DMO1K[] = {0x00U,
|
||||||
|
0x00U, 0x20U, 0x08U, 0x08U, 0x02U, 0x38U, 0x15U, 0x00U, 0x2CU, 0xA0U, 0x14U,
|
||||||
|
0x60U, 0x84U, 0x6DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x7EU, 0x30U, 0x30U,
|
||||||
|
0x01U, 0x10U, 0x01U, 0x40U, 0x03U, 0xC0U, 0x13U, 0xC1U, 0x1EU, 0x80U, 0x6FU};
|
||||||
|
|
||||||
|
// Voice Term MS with LC, CC: 1, srcID: 1, dstID: TG9
|
||||||
|
const uint8_t VT_DMO1K[] = {0x00U,
|
||||||
|
0x00U, 0x4FU, 0x08U, 0xDCU, 0x02U, 0x88U, 0x15U, 0x78U, 0x2CU, 0xD0U, 0x14U,
|
||||||
|
0xC0U, 0x84U, 0xADU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x79U, 0x65U, 0x24U,
|
||||||
|
0x02U, 0x28U, 0x06U, 0x20U, 0x0FU, 0x80U, 0x1BU, 0xC1U, 0x07U, 0x80U, 0x5CU};
|
||||||
|
|
||||||
|
// Voice coding data + FEC, 1031 Hz Test Pattern
|
||||||
|
const uint8_t VOICE_1K[] = {0x00U,
|
||||||
|
0xCEU, 0xA8U, 0xFEU, 0x83U, 0xACU, 0xC4U, 0x58U, 0x20U, 0x0AU, 0xCEU, 0xA8U,
|
||||||
|
0xFEU, 0x83U, 0xA0U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x0CU, 0xC4U, 0x58U,
|
||||||
|
0x20U, 0x0AU, 0xCEU, 0xA8U, 0xFEU, 0x83U, 0xACU, 0xC4U, 0x58U, 0x20U, 0x0AU};
|
||||||
|
|
||||||
|
// Embedded LC BS: CC: 1, srcID: 1, dstID: TG9
|
||||||
|
const uint8_t SYNCEMB_1K[6][7] = {
|
||||||
|
{0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U}, // BS VOICE SYNC (audio seq 0)
|
||||||
|
{0x01U, 0x30U, 0x00U, 0x00U, 0x90U, 0x09U, 0x10U}, // EMB + Embedded LC1 (audio seq 1)
|
||||||
|
{0x01U, 0x70U, 0x00U, 0x90U, 0x00U, 0x07U, 0x40U}, // EMB + Embedded LC2 (audio seq 2)
|
||||||
|
{0x01U, 0x70U, 0x00U, 0x31U, 0x40U, 0x07U, 0x40U}, // EMB + Embedded LC3 (audio seq 3)
|
||||||
|
{0x01U, 0x50U, 0xA1U, 0x71U, 0xD1U, 0x70U, 0x70U}, // EMB + Embedded LC4 (audio seq 4)
|
||||||
|
{0x01U, 0x10U, 0x00U, 0x00U, 0x00U, 0x0EU, 0x20U}}; // EMB (audio seq 5)
|
||||||
|
|
||||||
|
// Embedded LC MS: CC: 1, srcID: 1, dstID: TG9
|
||||||
|
const uint8_t SYNCEMB_DMO1K[6][7] = {
|
||||||
|
{0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U}, // MS VOICE SYNC (audio seq 0)
|
||||||
|
{0x01U, 0x30U, 0x00U, 0x00U, 0x90U, 0x09U, 0x10U}, // EMB + Embedded LC1 (audio seq 1)
|
||||||
|
{0x01U, 0x70U, 0x00U, 0x90U, 0x00U, 0x07U, 0x40U}, // EMB + Embedded LC2 (audio seq 2)
|
||||||
|
{0x01U, 0x70U, 0x00U, 0x31U, 0x40U, 0x07U, 0x40U}, // EMB + Embedded LC3 (audio seq 3)
|
||||||
|
{0x01U, 0x50U, 0xA1U, 0x71U, 0xD1U, 0x70U, 0x70U}, // EMB + Embedded LC4 (audio seq 4)
|
||||||
|
{0x01U, 0x10U, 0x00U, 0x00U, 0x00U, 0x0EU, 0x20U}}; // EMB (audio seq 5)
|
||||||
|
|
||||||
|
// Short LC:
|
||||||
|
// TS1: dstID: 0, ACTIVITY_NONE
|
||||||
|
// TS2: dstID: TG9, ACTIVITY_VOICE
|
||||||
|
const uint8_t SHORTLC_1K[] = {0x33U, 0x3AU, 0xA0U, 0x30U, 0x00U, 0x55U, 0xA6U, 0x5FU, 0x50U};
|
||||||
|
|
||||||
CCalDMR::CCalDMR() :
|
CCalDMR::CCalDMR() :
|
||||||
m_transmit(false)
|
m_transmit(false),
|
||||||
|
m_state(DMRCAL1K_IDLE),
|
||||||
|
m_frame_start(0U),
|
||||||
|
m_dmr1k(),
|
||||||
|
m_audioSeq(0)
|
||||||
{
|
{
|
||||||
|
::memcpy(m_dmr1k, VOICE_1K, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCalDMR::process()
|
void CCalDMR::process()
|
||||||
{
|
{
|
||||||
|
switch (m_modemState) {
|
||||||
|
case STATE_DMRCAL:
|
||||||
|
case STATE_LFCAL:
|
||||||
if (m_transmit) {
|
if (m_transmit) {
|
||||||
dmrTX.setCal(true);
|
dmrTX.setCal(true);
|
||||||
dmrTX.process();
|
dmrTX.process();
|
||||||
} else {
|
} else {
|
||||||
dmrTX.setCal(false);
|
dmrTX.setCal(false);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case STATE_DMRCAL1K:
|
||||||
|
dmr1kcal();
|
||||||
|
break;
|
||||||
|
case STATE_DMRDMO1K:
|
||||||
|
dmrdmo1k();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCalDMR::createData1k(uint8_t n)
|
||||||
|
{
|
||||||
|
for(uint8_t i = 0; i < 5U; i++)
|
||||||
|
m_dmr1k[i + 15U] = SYNCEMB_1K[n][i + 1U];
|
||||||
|
|
||||||
|
m_dmr1k[14U] &= 0xF0U;
|
||||||
|
m_dmr1k[20U] &= 0x0FU;
|
||||||
|
m_dmr1k[14U] |= SYNCEMB_1K[n][0] & 0x0FU;
|
||||||
|
m_dmr1k[20U] |= SYNCEMB_1K[n][6] & 0xF0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCalDMR::createDataDMO1k(uint8_t n)
|
||||||
|
{
|
||||||
|
for(uint8_t i = 0; i < 5U; i++)
|
||||||
|
m_dmr1k[i + 15U] = SYNCEMB_DMO1K[n][i + 1U];
|
||||||
|
|
||||||
|
m_dmr1k[14U] &= 0xF0U;
|
||||||
|
m_dmr1k[20U] &= 0x0FU;
|
||||||
|
m_dmr1k[14U] |= SYNCEMB_DMO1K[n][0] & 0x0FU;
|
||||||
|
m_dmr1k[20U] |= SYNCEMB_DMO1K[n][6] & 0xF0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCalDMR::dmr1kcal()
|
||||||
|
{
|
||||||
|
dmrTX.process();
|
||||||
|
|
||||||
|
uint16_t space = dmrTX.getSpace2();
|
||||||
|
if (space < 1U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (m_state) {
|
||||||
|
case DMRCAL1K_VH:
|
||||||
|
dmrTX.setColorCode(1U);
|
||||||
|
dmrTX.writeShortLC(SHORTLC_1K, 9U);
|
||||||
|
dmrTX.writeData2(VH_1K, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
dmrTX.setStart(true);
|
||||||
|
m_state = DMRCAL1K_VOICE;
|
||||||
|
break;
|
||||||
|
case DMRCAL1K_VOICE:
|
||||||
|
createData1k(m_audioSeq);
|
||||||
|
dmrTX.writeData2(m_dmr1k, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
if(m_audioSeq == 5U) {
|
||||||
|
m_audioSeq = 0U;
|
||||||
|
if(!m_transmit)
|
||||||
|
m_state = DMRCAL1K_VT;
|
||||||
|
} else
|
||||||
|
m_audioSeq++;
|
||||||
|
break;
|
||||||
|
case DMRCAL1K_VT:
|
||||||
|
dmrTX.writeData2(VT_1K, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
m_frame_start = dmrTX.getFrameCount();
|
||||||
|
m_state = DMRCAL1K_WAIT;
|
||||||
|
break;
|
||||||
|
case DMRCAL1K_WAIT:
|
||||||
|
if (dmrTX.getFrameCount() > (m_frame_start + 30U)) {
|
||||||
|
dmrTX.setStart(false);
|
||||||
|
dmrTX.resetFifo2();
|
||||||
|
m_audioSeq = 0U;
|
||||||
|
m_state = DMRCAL1K_IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_state = DMRCAL1K_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCalDMR::dmrdmo1k()
|
||||||
|
{
|
||||||
|
dmrDMOTX.process();
|
||||||
|
|
||||||
|
uint16_t space = dmrDMOTX.getSpace();
|
||||||
|
if (space < 1U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (m_state) {
|
||||||
|
case DMRCAL1K_VH:
|
||||||
|
dmrDMOTX.writeData(VH_DMO1K, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
m_state = DMRCAL1K_VOICE;
|
||||||
|
break;
|
||||||
|
case DMRCAL1K_VOICE:
|
||||||
|
createDataDMO1k(m_audioSeq);
|
||||||
|
dmrDMOTX.writeData(m_dmr1k, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
if(m_audioSeq == 5U) {
|
||||||
|
m_audioSeq = 0U;
|
||||||
|
if(!m_transmit)
|
||||||
|
m_state = DMRCAL1K_VT;
|
||||||
|
} else
|
||||||
|
m_audioSeq++;
|
||||||
|
break;
|
||||||
|
case DMRCAL1K_VT:
|
||||||
|
dmrDMOTX.writeData(VT_DMO1K, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
m_state = DMRCAL1K_IDLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_state = DMRCAL1K_IDLE;
|
||||||
|
m_audioSeq = 0U;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
|
uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
|
||||||
@@ -44,6 +215,9 @@ uint8_t CCalDMR::write(const uint8_t* data, uint8_t length)
|
|||||||
|
|
||||||
m_transmit = data[0U] == 1U;
|
m_transmit = data[0U] == 1U;
|
||||||
|
|
||||||
|
if(m_transmit && m_state == DMRCAL1K_IDLE && (m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K))
|
||||||
|
m_state = DMRCAL1K_VH;
|
||||||
|
|
||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,16 +23,32 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "DMRDefines.h"
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
|
enum DMRCAL1K {
|
||||||
|
DMRCAL1K_IDLE,
|
||||||
|
DMRCAL1K_VH,
|
||||||
|
DMRCAL1K_VOICE,
|
||||||
|
DMRCAL1K_VT,
|
||||||
|
DMRCAL1K_WAIT
|
||||||
|
};
|
||||||
|
|
||||||
class CCalDMR {
|
class CCalDMR {
|
||||||
public:
|
public:
|
||||||
CCalDMR();
|
CCalDMR();
|
||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
void dmr1kcal();
|
||||||
|
void dmrdmo1k();
|
||||||
|
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, uint8_t length);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_transmit;
|
bool m_transmit;
|
||||||
|
DMRCAL1K m_state;
|
||||||
|
uint32_t m_frame_start;
|
||||||
|
uint8_t m_dmr1k[DMR_FRAME_LENGTH_BYTES + 1U];
|
||||||
|
uint8_t m_audioSeq;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "CalNXDN.h"
|
||||||
|
|
||||||
|
// NXDN 1031 Hz Test Pattern, RAN: 1, Unit ID: 1, Dst Group ID: 1, Outbound Direction
|
||||||
|
const uint8_t NXDN_CAL1K[4][49] = {
|
||||||
|
{0x00U,
|
||||||
|
0xCDU, 0xF5U, 0x9DU, 0x5DU, 0x7CU, 0xFAU, 0x0AU, 0x6EU, 0x8AU, 0x23U, 0x56U, 0xE8U,
|
||||||
|
0x4CU, 0xAAU, 0xDEU, 0x8BU, 0x26U, 0xE4U, 0xF2U, 0x82U, 0x88U,
|
||||||
|
0xC6U, 0x8AU, 0x74U, 0x29U, 0xA4U, 0xECU, 0xD0U, 0x08U, 0x22U,
|
||||||
|
0xCEU, 0xA2U, 0xFCU, 0x01U, 0x8CU, 0xECU, 0xDAU, 0x0AU, 0xA0U,
|
||||||
|
0xEEU, 0x8AU, 0x7EU, 0x2BU, 0x26U, 0xCCU, 0xF8U, 0x8AU, 0x08U},
|
||||||
|
|
||||||
|
{0x00U,
|
||||||
|
0xCDU, 0xF5U, 0x9DU, 0x5DU, 0x7CU, 0x6DU, 0xBBU, 0x0EU, 0xB3U, 0xA4U, 0x26U, 0xA8U,
|
||||||
|
0x4CU, 0xAAU, 0xDEU, 0x8BU, 0x26U, 0xE4U, 0xF2U, 0x82U, 0x88U,
|
||||||
|
0xC6U, 0x8AU, 0x74U, 0x29U, 0xA4U, 0xECU, 0xD0U, 0x08U, 0x22U,
|
||||||
|
0xCEU, 0xA2U, 0xFCU, 0x01U, 0x8CU, 0xECU, 0xDAU, 0x0AU, 0xA0U,
|
||||||
|
0xEEU, 0x8AU, 0x7EU, 0x2BU, 0x26U, 0xCCU, 0xF8U, 0x8AU, 0x08U},
|
||||||
|
|
||||||
|
{0x00U,
|
||||||
|
0xCDU, 0xF5U, 0x9DU, 0x5DU, 0x76U, 0x3AU, 0x1BU, 0x4AU, 0x81U, 0xA8U, 0xE2U, 0x80U,
|
||||||
|
0x4CU, 0xAAU, 0xDEU, 0x8BU, 0x26U, 0xE4U, 0xF2U, 0x82U, 0x88U,
|
||||||
|
0xC6U, 0x8AU, 0x74U, 0x29U, 0xA4U, 0xECU, 0xD0U, 0x08U, 0x22U,
|
||||||
|
0xCEU, 0xA2U, 0xFCU, 0x01U, 0x8CU, 0xECU, 0xDAU, 0x0AU, 0xA0U,
|
||||||
|
0xEEU, 0x8AU, 0x7EU, 0x2BU, 0x26U, 0xCCU, 0xF8U, 0x8AU, 0x08U},
|
||||||
|
|
||||||
|
{0x00U,
|
||||||
|
0xCDU, 0xF5U, 0x9DU, 0x5DU, 0x74U, 0x28U, 0x83U, 0x02U, 0xB0U, 0x2DU, 0x07U, 0xE2U,
|
||||||
|
0x4CU, 0xAAU, 0xDEU, 0x8BU, 0x26U, 0xE4U, 0xF2U, 0x82U, 0x88U,
|
||||||
|
0xC6U, 0x8AU, 0x74U, 0x29U, 0xA4U, 0xECU, 0xD0U, 0x08U, 0x22U,
|
||||||
|
0xCEU, 0xA2U, 0xFCU, 0x01U, 0x8CU, 0xECU, 0xDAU, 0x0AU, 0xA0U,
|
||||||
|
0xEEU, 0x8AU, 0x7EU, 0x2BU, 0x26U, 0xCCU, 0xF8U, 0x8AU, 0x08U}};
|
||||||
|
|
||||||
|
CCalNXDN::CCalNXDN() :
|
||||||
|
m_transmit(false),
|
||||||
|
m_state(NXDNCAL1K_IDLE),
|
||||||
|
m_audioSeq(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCalNXDN::process()
|
||||||
|
{
|
||||||
|
nxdnTX.process();
|
||||||
|
|
||||||
|
uint16_t space = nxdnTX.getSpace();
|
||||||
|
if (space < 1U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (m_state) {
|
||||||
|
case NXDNCAL1K_TX:
|
||||||
|
nxdnTX.writeData(NXDN_CAL1K[m_audioSeq], NXDN_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
m_audioSeq = (m_audioSeq + 1U) % 4U;
|
||||||
|
if(!m_transmit)
|
||||||
|
m_state = NXDNCAL1K_IDLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_state = NXDNCAL1K_IDLE;
|
||||||
|
m_audioSeq = 0U;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CCalNXDN::write(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length != 1U)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
m_transmit = data[0U] == 1U;
|
||||||
|
|
||||||
|
if(m_transmit && m_state == NXDNCAL1K_IDLE)
|
||||||
|
m_state = NXDNCAL1K_TX;
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(CALNXDN_H)
|
||||||
|
#define CALNXDN_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
enum NXDNCAL1K {
|
||||||
|
NXDNCAL1K_IDLE,
|
||||||
|
NXDNCAL1K_TX
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCalNXDN {
|
||||||
|
public:
|
||||||
|
CCalNXDN();
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_transmit;
|
||||||
|
NXDNCAL1K m_state;
|
||||||
|
uint8_t m_audioSeq;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "CalP25.h"
|
||||||
|
|
||||||
|
// Recommended 1011 Hz test pattern for P25 Phase 1 (ANSI/TIA-102.CAAA)
|
||||||
|
// NAC: 0x293, srcID: 1, dstID: TG1
|
||||||
|
unsigned char LDU1_1K[] = {0x00,
|
||||||
|
0x55, 0x75, 0xF5, 0xFF, 0x77, 0xFF, 0x29, 0x35, 0x54, 0x7B, 0xCB, 0x19, 0x4D, 0x0D, 0xCE, 0x24, 0xA1, 0x24,
|
||||||
|
0x0D, 0x43, 0x3C, 0x0B, 0xE1, 0xB9, 0x18, 0x44, 0xFC, 0xC1, 0x62, 0x96, 0x27, 0x60, 0xE4, 0xE2, 0x4A, 0x10,
|
||||||
|
0x90, 0xD4, 0x33, 0xC0, 0xBE, 0x1B, 0x91, 0x84, 0x4C, 0xFC, 0x16, 0x29, 0x62, 0x76, 0x0E, 0xC0, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0x89, 0x28, 0x49, 0x0D, 0x43, 0x3C, 0x02, 0xF8, 0x6E, 0x46, 0x11, 0x3F, 0xC1, 0x62, 0x94,
|
||||||
|
0x89, 0xD8, 0x39, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x38, 0x24, 0xA1, 0x24, 0x35, 0x0C, 0xF0, 0x2F, 0x86, 0xE4,
|
||||||
|
0x18, 0x44, 0xFF, 0x05, 0x8A, 0x58, 0x9D, 0x83, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x70, 0xE2, 0x4A, 0x12, 0x40,
|
||||||
|
0xD4, 0x33, 0xC0, 0xBE, 0x1B, 0x91, 0x84, 0x4F, 0xF0, 0x16, 0x29, 0x62, 0x76, 0x0E, 0x6D, 0xE5, 0xD5, 0x48,
|
||||||
|
0xAD, 0xE3, 0x89, 0x28, 0x49, 0x0D, 0x43, 0x3C, 0x08, 0xF8, 0x6E, 0x46, 0x11, 0x3F, 0xC1, 0x62, 0x96, 0x24,
|
||||||
|
0xD8, 0x3B, 0xA1, 0x41, 0xC2, 0xD2, 0xBA, 0x38, 0x90, 0xA1, 0x24, 0x35, 0x0C, 0xF0, 0x2F, 0x86, 0xE4, 0x60,
|
||||||
|
0x44, 0xFF, 0x05, 0x8A, 0x58, 0x9D, 0x83, 0x94, 0xC8, 0xFB, 0x02, 0x35, 0xA4, 0xE2, 0x4A, 0x12, 0x43, 0x50,
|
||||||
|
0x33, 0xC0, 0xBE, 0x1B, 0x91, 0x84, 0x4F, 0xF0, 0x58, 0x29, 0x62, 0x76, 0x0E, 0xC0, 0x00, 0x00, 0x00, 0x0C,
|
||||||
|
0x89, 0x28, 0x49, 0x0D, 0x43, 0x3C, 0x0B, 0xE1, 0xB8, 0x46, 0x11, 0x3F, 0xC1, 0x62, 0x96, 0x27, 0x60, 0xE4};
|
||||||
|
|
||||||
|
unsigned char LDU2_1K[] = {0x00,
|
||||||
|
0x55, 0x75, 0xF5, 0xFF, 0x77, 0xFF, 0x29, 0x3A, 0xB8, 0xA4, 0xEF, 0xB0, 0x9A, 0x8A, 0xCE, 0x24, 0xA1, 0x24,
|
||||||
|
0x0D, 0x43, 0x3C, 0x0B, 0xE1, 0xB9, 0x18, 0x44, 0xFC, 0xC1, 0x62, 0x96, 0x27, 0x60, 0xEC, 0xE2, 0x4A, 0x10,
|
||||||
|
0x90, 0xD4, 0x33, 0xC0, 0xBE, 0x1B, 0x91, 0x84, 0x4C, 0xFC, 0x16, 0x29, 0x62, 0x76, 0x0E, 0x40, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x03, 0x89, 0x28, 0x49, 0x0D, 0x43, 0x3C, 0x02, 0xF8, 0x6E, 0x46, 0x11, 0x3F, 0xC1, 0x62, 0x94,
|
||||||
|
0x89, 0xD8, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x24, 0xA1, 0x24, 0x35, 0x0C, 0xF0, 0x2F, 0x86, 0xE4,
|
||||||
|
0x18, 0x44, 0xFF, 0x05, 0x8A, 0x58, 0x9D, 0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x4A, 0x12, 0x40,
|
||||||
|
0xD4, 0x33, 0xC0, 0xBE, 0x1B, 0x91, 0x84, 0x4F, 0xF0, 0x16, 0x29, 0x62, 0x76, 0x0E, 0xE0, 0xE0, 0x00, 0x00,
|
||||||
|
0x00, 0x03, 0x89, 0x28, 0x49, 0x0D, 0x43, 0x3C, 0x08, 0xF8, 0x6E, 0x46, 0x11, 0x3F, 0xC1, 0x62, 0x96, 0x24,
|
||||||
|
0xD8, 0x39, 0xAE, 0x8B, 0x48, 0xB6, 0x49, 0x38, 0x90, 0xA1, 0x24, 0x35, 0x0C, 0xF0, 0x2F, 0x86, 0xE4, 0x60,
|
||||||
|
0x44, 0xFF, 0x05, 0x8A, 0x58, 0x9D, 0x83, 0xB9, 0xA8, 0xF4, 0xF1, 0xFD, 0x60, 0xE2, 0x4A, 0x12, 0x43, 0x50,
|
||||||
|
0x33, 0xC0, 0xBE, 0x1B, 0x91, 0x84, 0x4F, 0xF0, 0x58, 0x29, 0x62, 0x76, 0x0E, 0x40, 0x00, 0x00, 0x00, 0x0C,
|
||||||
|
0x89, 0x28, 0x49, 0x0D, 0x43, 0x3C, 0x0B, 0xE1, 0xB8, 0x46, 0x11, 0x3F, 0xC1, 0x62, 0x96, 0x27, 0x60, 0xEC};
|
||||||
|
|
||||||
|
CCalP25::CCalP25() :
|
||||||
|
m_transmit(false),
|
||||||
|
m_state(P25CAL1K_IDLE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCalP25::process()
|
||||||
|
{
|
||||||
|
p25TX.process();
|
||||||
|
|
||||||
|
uint16_t space = p25TX.getSpace();
|
||||||
|
if (space < 1U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (m_state) {
|
||||||
|
case P25CAL1K_LDU1:
|
||||||
|
p25TX.writeData(LDU1_1K, P25_LDU_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
m_state = P25CAL1K_LDU2;
|
||||||
|
break;
|
||||||
|
case P25CAL1K_LDU2:
|
||||||
|
p25TX.writeData(LDU2_1K, P25_LDU_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
if(!m_transmit)
|
||||||
|
m_state = P25CAL1K_IDLE;
|
||||||
|
else
|
||||||
|
m_state = P25CAL1K_LDU1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
m_state = P25CAL1K_IDLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CCalP25::write(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length != 1U)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
m_transmit = data[0U] == 1U;
|
||||||
|
|
||||||
|
if(m_transmit && m_state == P25CAL1K_IDLE)
|
||||||
|
m_state = P25CAL1K_LDU1;
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(CALP25_H)
|
||||||
|
#define CALP25_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "P25Defines.h"
|
||||||
|
|
||||||
|
enum P25CAL1K {
|
||||||
|
P25CAL1K_IDLE,
|
||||||
|
P25CAL1K_LDU1,
|
||||||
|
P25CAL1K_LDU2
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCalP25 {
|
||||||
|
public:
|
||||||
|
CCalP25();
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
uint8_t write(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_transmit;
|
||||||
|
P25CAL1K m_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
// Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable.
|
// Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable.
|
||||||
//
|
//
|
||||||
// For 12 MHz
|
// For 12 MHz
|
||||||
// #define EXTERNAL_OSC 12000000
|
#define EXTERNAL_OSC 12000000
|
||||||
// For 12.288 MHz
|
// For 12.288 MHz
|
||||||
// #define EXTERNAL_OSC 12288000
|
// #define EXTERNAL_OSC 12288000
|
||||||
// For 14.4 MHz
|
// For 14.4 MHz
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02
|
|||||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||||
|
|
||||||
const uint32_t STARTUP_COUNT = 20U;
|
const uint32_t STARTUP_COUNT = 20U;
|
||||||
|
const uint32_t ABORT_COUNT = 6U;
|
||||||
|
|
||||||
CDMRTX::CDMRTX() :
|
CDMRTX::CDMRTX() :
|
||||||
m_fifo(),
|
m_fifo(),
|
||||||
@@ -69,6 +70,7 @@ m_poBuffer(),
|
|||||||
m_poLen(0U),
|
m_poLen(0U),
|
||||||
m_poPtr(0U),
|
m_poPtr(0U),
|
||||||
m_frameCount(0U),
|
m_frameCount(0U),
|
||||||
|
m_abortCount(),
|
||||||
m_abort()
|
m_abort()
|
||||||
{
|
{
|
||||||
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
|
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
|
||||||
@@ -83,6 +85,9 @@ m_abort()
|
|||||||
|
|
||||||
m_abort[0U] = false;
|
m_abort[0U] = false;
|
||||||
m_abort[1U] = false;
|
m_abort[1U] = false;
|
||||||
|
|
||||||
|
m_abortCount[0U] = 0U;
|
||||||
|
m_abortCount[1U] = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDMRTX::process()
|
void CDMRTX::process()
|
||||||
@@ -210,10 +215,12 @@ uint8_t CDMRTX::writeAbort(const uint8_t* data, uint8_t length)
|
|||||||
|
|
||||||
switch (data[0U]) {
|
switch (data[0U]) {
|
||||||
case 1U:
|
case 1U:
|
||||||
|
m_abortCount[0U] = 0U;
|
||||||
m_abort[0U] = true;
|
m_abort[0U] = true;
|
||||||
return 0U;
|
return 0U;
|
||||||
|
|
||||||
case 2U:
|
case 2U:
|
||||||
|
m_abortCount[1U] = 0U;
|
||||||
m_abort[1U] = true;
|
m_abort[1U] = true;
|
||||||
return 0U;
|
return 0U;
|
||||||
|
|
||||||
@@ -227,6 +234,8 @@ void CDMRTX::setStart(bool start)
|
|||||||
m_state = start ? DMRTXSTATE_SLOT1 : DMRTXSTATE_IDLE;
|
m_state = start ? DMRTXSTATE_SLOT1 : DMRTXSTATE_IDLE;
|
||||||
|
|
||||||
m_frameCount = 0U;
|
m_frameCount = 0U;
|
||||||
|
m_abortCount[0U] = 0U;
|
||||||
|
m_abortCount[1U] = 0U;
|
||||||
|
|
||||||
m_abort[0U] = false;
|
m_abort[0U] = false;
|
||||||
m_abort[1U] = false;
|
m_abort[1U] = false;
|
||||||
@@ -282,7 +291,7 @@ uint8_t CDMRTX::getSpace2() const
|
|||||||
|
|
||||||
void CDMRTX::createData(uint8_t slotIndex)
|
void CDMRTX::createData(uint8_t slotIndex)
|
||||||
{
|
{
|
||||||
if (m_fifo[slotIndex].getData() > 0U && m_frameCount >= STARTUP_COUNT) {
|
if (m_fifo[slotIndex].getData() >= DMR_FRAME_LENGTH_BYTES && m_frameCount >= STARTUP_COUNT && m_abortCount[slotIndex] >= ABORT_COUNT) {
|
||||||
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
|
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
|
||||||
m_poBuffer[i] = m_fifo[slotIndex].get();
|
m_poBuffer[i] = m_fifo[slotIndex].get();
|
||||||
m_markBuffer[i] = MARK_NONE;
|
m_markBuffer[i] = MARK_NONE;
|
||||||
@@ -302,18 +311,41 @@ void CDMRTX::createData(uint8_t slotIndex)
|
|||||||
|
|
||||||
void CDMRTX::createCal()
|
void CDMRTX::createCal()
|
||||||
{
|
{
|
||||||
|
// 1.2 kHz sine wave generation
|
||||||
|
if (m_modemState == STATE_DMRCAL) {
|
||||||
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
|
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++) {
|
||||||
m_poBuffer[i] = 0x5FU; // +3, +3, -3, -3 pattern for deviation cal.
|
m_poBuffer[i] = 0x5FU; // +3, +3, -3, -3 pattern for deviation cal.
|
||||||
m_markBuffer[i] = MARK_NONE;
|
m_markBuffer[i] = MARK_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_poLen = DMR_FRAME_LENGTH_BYTES;
|
m_poLen = DMR_FRAME_LENGTH_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 80 Hz square wave generation
|
||||||
|
if (m_modemState == STATE_LFCAL) {
|
||||||
|
for (unsigned int i = 0U; i < 7U; i++) {
|
||||||
|
m_poBuffer[i] = 0x55U; // +3, +3, ... pattern
|
||||||
|
m_markBuffer[i] = MARK_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_poBuffer[7U] = 0x5FU; // +3, +3, -3, -3 pattern
|
||||||
|
|
||||||
|
for (unsigned int i = 8U; i < 15U; i++) {
|
||||||
|
m_poBuffer[i] = 0xFFU; // -3, -3, ... pattern
|
||||||
|
m_markBuffer[i] = MARK_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_poLen = 15U;
|
||||||
|
}
|
||||||
|
|
||||||
m_poPtr = 0U;
|
m_poPtr = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
|
void CDMRTX::createCACH(uint8_t txSlotIndex, uint8_t rxSlotIndex)
|
||||||
{
|
{
|
||||||
m_frameCount++;
|
m_frameCount++;
|
||||||
|
m_abortCount[0U]++;
|
||||||
|
m_abortCount[1U]++;
|
||||||
|
|
||||||
if (m_cachPtr >= 12U)
|
if (m_cachPtr >= 12U)
|
||||||
m_cachPtr = 0U;
|
m_cachPtr = 0U;
|
||||||
@@ -368,3 +400,17 @@ void CDMRTX::setColorCode(uint8_t colorCode)
|
|||||||
slotType.encode(colorCode, DT_IDLE, m_idle);
|
slotType.encode(colorCode, DT_IDLE, m_idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CDMRTX::resetFifo1()
|
||||||
|
{
|
||||||
|
m_fifo[0U].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRTX::resetFifo2()
|
||||||
|
{
|
||||||
|
m_fifo[1U].reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CDMRTX::getFrameCount()
|
||||||
|
{
|
||||||
|
return m_frameCount;
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ public:
|
|||||||
|
|
||||||
void process();
|
void process();
|
||||||
|
|
||||||
|
void resetFifo1();
|
||||||
|
void resetFifo2();
|
||||||
|
uint32_t getFrameCount();
|
||||||
|
|
||||||
uint8_t getSpace1() const;
|
uint8_t getSpace1() const;
|
||||||
uint8_t getSpace2() const;
|
uint8_t getSpace2() const;
|
||||||
|
|
||||||
@@ -68,6 +72,7 @@ private:
|
|||||||
uint16_t m_poLen;
|
uint16_t m_poLen;
|
||||||
uint16_t m_poPtr;
|
uint16_t m_poPtr;
|
||||||
uint32_t m_frameCount;
|
uint32_t m_frameCount;
|
||||||
|
uint32_t m_abortCount[2U];
|
||||||
bool m_abort[2U];
|
bool m_abort[2U];
|
||||||
|
|
||||||
void createData(uint8_t slotIndex);
|
void createData(uint8_t slotIndex);
|
||||||
|
|||||||
+11
-47
@@ -28,15 +28,7 @@ const uint32_t PLLMAX = 0x10000U;
|
|||||||
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
|
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
|
||||||
const uint32_t INC = PLLINC / 32U;
|
const uint32_t INC = PLLINC / 32U;
|
||||||
|
|
||||||
const unsigned int MAX_SYNC_BITS = 50U * DSTAR_DATA_LENGTH_BITS;
|
const unsigned int MAX_SYNC_BITS = 100U * DSTAR_DATA_LENGTH_BITS;
|
||||||
|
|
||||||
const unsigned int SYNC_POS = 21U * DSTAR_DATA_LENGTH_BITS;
|
|
||||||
const unsigned int SYNC_SCAN_START = SYNC_POS - 3U;
|
|
||||||
const unsigned int SYNC_SCAN_END = SYNC_POS + 3U;
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
|
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
|
||||||
const uint32_t FRAME_SYNC_DATA = 0x00557650U;
|
const uint32_t FRAME_SYNC_DATA = 0x00557650U;
|
||||||
@@ -51,7 +43,7 @@ const uint8_t DATA_SYNC_ERRS = 2U;
|
|||||||
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
|
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
|
||||||
const uint32_t END_SYNC_DATA = 0xAAAA135EU;
|
const uint32_t END_SYNC_DATA = 0xAAAA135EU;
|
||||||
const uint32_t END_SYNC_MASK = 0xFFFFFFFFU;
|
const uint32_t END_SYNC_MASK = 0xFFFFFFFFU;
|
||||||
const uint8_t END_SYNC_ERRS = 3U;
|
const uint8_t END_SYNC_ERRS = 1U;
|
||||||
|
|
||||||
const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
|
const uint8_t BIT_MASK_TABLE0[] = {0x7FU, 0xBFU, 0xDFU, 0xEFU, 0xF7U, 0xFBU, 0xFDU, 0xFEU};
|
||||||
const uint8_t BIT_MASK_TABLE1[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
const uint8_t BIT_MASK_TABLE1[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
||||||
@@ -261,16 +253,8 @@ m_pathMemory2(),
|
|||||||
m_pathMemory3(),
|
m_pathMemory3(),
|
||||||
m_fecOutput(),
|
m_fecOutput(),
|
||||||
m_rssiAccum(0U),
|
m_rssiAccum(0U),
|
||||||
m_rssiCount(0U),
|
m_rssiCount(0U)
|
||||||
m_dcFilter(),
|
|
||||||
m_dcState()
|
|
||||||
{
|
{
|
||||||
::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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDStarRX::reset()
|
void CDStarRX::reset()
|
||||||
@@ -287,23 +271,11 @@ void CDStarRX::reset()
|
|||||||
|
|
||||||
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
||||||
{
|
{
|
||||||
q31_t dc_level = 0;
|
|
||||||
q31_t dcVals[20];
|
|
||||||
q31_t intSamp[20];
|
|
||||||
|
|
||||||
::arm_q15_to_q31((q15_t*)samples, intSamp, length);
|
|
||||||
::arm_biquad_cascade_df1_q31(&m_dcFilter, intSamp, dcVals, length);
|
|
||||||
|
|
||||||
for (uint8_t i = 0U; i < length; i++)
|
|
||||||
dc_level += dcVals[i];
|
|
||||||
|
|
||||||
dc_level /= length;
|
|
||||||
|
|
||||||
for (uint16_t i = 0U; i < length; i++) {
|
for (uint16_t i = 0U; i < length; i++) {
|
||||||
m_rssiAccum += rssi[i];
|
m_rssiAccum += rssi[i];
|
||||||
m_rssiCount++;
|
m_rssiCount++;
|
||||||
|
|
||||||
bool bit = samples[i] < (q15_t) (dc_level >> 16);
|
bool bit = samples[i] < 0;
|
||||||
|
|
||||||
if (bit != m_prev) {
|
if (bit != m_prev) {
|
||||||
if (m_pll < (PLLMAX / 2U))
|
if (m_pll < (PLLMAX / 2U))
|
||||||
@@ -373,7 +345,7 @@ void CDStarRX::processNone(bool bit)
|
|||||||
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||||
m_rxBufferBits = 0U;
|
m_rxBufferBits = 0U;
|
||||||
|
|
||||||
m_dataBits = 0U;
|
m_dataBits = MAX_SYNC_BITS;
|
||||||
m_rxState = DSRXS_DATA;
|
m_rxState = DSRXS_DATA;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -403,7 +375,7 @@ void CDStarRX::processHeader(bool bit)
|
|||||||
m_rxBufferBits = 0U;
|
m_rxBufferBits = 0U;
|
||||||
|
|
||||||
m_rxState = DSRXS_DATA;
|
m_rxState = DSRXS_DATA;
|
||||||
m_dataBits = SYNC_POS - DSTAR_DATA_LENGTH_BITS + 1U;
|
m_dataBits = MAX_SYNC_BITS;
|
||||||
} else {
|
} else {
|
||||||
// The checksum failed, return to looking for syncs
|
// The checksum failed, return to looking for syncs
|
||||||
m_rxState = DSRXS_NONE;
|
m_rxState = DSRXS_NONE;
|
||||||
@@ -435,37 +407,29 @@ void CDStarRX::processData(bool bit)
|
|||||||
|
|
||||||
// Fuzzy matching of the data sync bit sequence
|
// Fuzzy matching of the data sync bit sequence
|
||||||
bool syncSeen = false;
|
bool syncSeen = false;
|
||||||
if (m_dataBits >= SYNC_SCAN_START && m_dataBits <= (SYNC_POS + 1U)) {
|
if (m_rxBufferBits >= (DSTAR_DATA_LENGTH_BITS - 3U)) {
|
||||||
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) {
|
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) {
|
||||||
if (m_dataBits < SYNC_POS)
|
|
||||||
DEBUG2("DStarRX: found data sync in Data, early", SYNC_POS - m_dataBits);
|
|
||||||
else
|
|
||||||
DEBUG1("DStarRX: found data sync in Data");
|
|
||||||
|
|
||||||
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS;
|
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS;
|
||||||
m_dataBits = 0U;
|
m_dataBits = MAX_SYNC_BITS;
|
||||||
syncSeen = true;
|
syncSeen = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if the sync is arriving late
|
// Check to see if the sync is arriving late
|
||||||
if (m_dataBits == SYNC_POS) {
|
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS && !syncSeen) {
|
||||||
for (uint8_t i = 1U; i <= 3U; i++) {
|
for (uint8_t i = 1U; i <= 3U; i++) {
|
||||||
uint32_t syncMask = DATA_SYNC_MASK >> i;
|
uint32_t syncMask = DATA_SYNC_MASK >> i;
|
||||||
uint32_t syncData = DATA_SYNC_DATA >> i;
|
uint32_t syncData = DATA_SYNC_DATA >> i;
|
||||||
if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) {
|
if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) {
|
||||||
DEBUG2("DStarRX: found data sync in Data, late", i);
|
|
||||||
m_rxBufferBits -= i;
|
m_rxBufferBits -= i;
|
||||||
m_dataBits -= i;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dataBits++;
|
m_dataBits--;
|
||||||
|
|
||||||
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
if (m_dataBits == 0U) {
|
||||||
if (m_dataBits >= MAX_SYNC_BITS) {
|
|
||||||
DEBUG1("DStarRX: data sync timed out, lost lock");
|
DEBUG1("DStarRX: data sync timed out, lost lock");
|
||||||
|
|
||||||
io.setDecode(false);
|
io.setDecode(false);
|
||||||
|
|||||||
@@ -53,8 +53,6 @@ private:
|
|||||||
uint8_t m_fecOutput[42U];
|
uint8_t m_fecOutput[42U];
|
||||||
uint32_t m_rssiAccum;
|
uint32_t m_rssiAccum;
|
||||||
uint16_t m_rssiCount;
|
uint16_t m_rssiCount;
|
||||||
arm_biquad_casd_df1_inst_q31 m_dcFilter;
|
|
||||||
q31_t m_dcState[4];
|
|
||||||
|
|
||||||
void processNone(bool bit);
|
void processNone(bool bit);
|
||||||
void processHeader(bool bit);
|
void processHeader(bool bit);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,8 +19,10 @@
|
|||||||
#if !defined(GLOBALS_H)
|
#if !defined(GLOBALS_H)
|
||||||
#define GLOBALS_H
|
#define GLOBALS_H
|
||||||
|
|
||||||
#if defined(STM32F4XX) || defined(STM32F4)
|
#if defined(STM32F4XX)
|
||||||
#include "stm32f4xx.h"
|
#include "stm32f4xx.h"
|
||||||
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
#elif defined(STM32F105xC)
|
#elif defined(STM32F105xC)
|
||||||
#include "stm32f1xx.h"
|
#include "stm32f1xx.h"
|
||||||
#include "STM32Utils.h"
|
#include "STM32Utils.h"
|
||||||
@@ -30,7 +32,9 @@
|
|||||||
|
|
||||||
#if defined(__SAM3X8E__) || defined(STM32F105xC)
|
#if defined(__SAM3X8E__) || defined(STM32F105xC)
|
||||||
#define ARM_MATH_CM3
|
#define ARM_MATH_CM3
|
||||||
#elif defined(STM32F4XX) || defined(STM32F4) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
#elif defined(STM32F7XX)
|
||||||
|
#define ARM_MATH_CM7
|
||||||
|
#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||||
#define ARM_MATH_CM4
|
#define ARM_MATH_CM4
|
||||||
#else
|
#else
|
||||||
#error "Unknown processor type"
|
#error "Unknown processor type"
|
||||||
@@ -44,8 +48,14 @@ enum MMDVM_STATE {
|
|||||||
STATE_DMR = 2,
|
STATE_DMR = 2,
|
||||||
STATE_YSF = 3,
|
STATE_YSF = 3,
|
||||||
STATE_P25 = 4,
|
STATE_P25 = 4,
|
||||||
|
STATE_NXDN = 5,
|
||||||
|
|
||||||
// Dummy states start at 90
|
// Dummy states start at 90
|
||||||
|
STATE_NXDNCAL1K = 91,
|
||||||
|
STATE_DMRDMO1K = 92,
|
||||||
|
STATE_P25CAL1K = 93,
|
||||||
|
STATE_DMRCAL1K = 94,
|
||||||
|
STATE_LFCAL = 95,
|
||||||
STATE_RSSICAL = 96,
|
STATE_RSSICAL = 96,
|
||||||
STATE_CWID = 97,
|
STATE_CWID = 97,
|
||||||
STATE_DMRCAL = 98,
|
STATE_DMRCAL = 98,
|
||||||
@@ -64,9 +74,13 @@ enum MMDVM_STATE {
|
|||||||
#include "YSFTX.h"
|
#include "YSFTX.h"
|
||||||
#include "P25RX.h"
|
#include "P25RX.h"
|
||||||
#include "P25TX.h"
|
#include "P25TX.h"
|
||||||
|
#include "NXDNRX.h"
|
||||||
|
#include "NXDNTX.h"
|
||||||
#include "CalDStarRX.h"
|
#include "CalDStarRX.h"
|
||||||
#include "CalDStarTX.h"
|
#include "CalDStarTX.h"
|
||||||
#include "CalDMR.h"
|
#include "CalDMR.h"
|
||||||
|
#include "CalP25.h"
|
||||||
|
#include "CalNXDN.h"
|
||||||
#include "CalRSSI.h"
|
#include "CalRSSI.h"
|
||||||
#include "CWIdTX.h"
|
#include "CWIdTX.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
@@ -87,6 +101,7 @@ extern bool m_dstarEnable;
|
|||||||
extern bool m_dmrEnable;
|
extern bool m_dmrEnable;
|
||||||
extern bool m_ysfEnable;
|
extern bool m_ysfEnable;
|
||||||
extern bool m_p25Enable;
|
extern bool m_p25Enable;
|
||||||
|
extern bool m_nxdnEnable;
|
||||||
|
|
||||||
extern bool m_duplex;
|
extern bool m_duplex;
|
||||||
|
|
||||||
@@ -112,9 +127,14 @@ extern CYSFTX ysfTX;
|
|||||||
extern CP25RX p25RX;
|
extern CP25RX p25RX;
|
||||||
extern CP25TX p25TX;
|
extern CP25TX p25TX;
|
||||||
|
|
||||||
|
extern CNXDNRX nxdnRX;
|
||||||
|
extern CNXDNTX nxdnTX;
|
||||||
|
|
||||||
extern CCalDStarRX calDStarRX;
|
extern CCalDStarRX calDStarRX;
|
||||||
extern CCalDStarTX calDStarTX;
|
extern CCalDStarTX calDStarTX;
|
||||||
extern CCalDMR calDMR;
|
extern CCalDMR calDMR;
|
||||||
|
extern CCalP25 calP25;
|
||||||
|
extern CCalNXDN calNXDN;
|
||||||
extern CCalRSSI calRSSI;
|
extern CCalRSSI calRSSI;
|
||||||
|
|
||||||
extern CCWIdTX cwIdTX;
|
extern CCWIdTX cwIdTX;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
@@ -22,18 +22,34 @@
|
|||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "IO.h"
|
#include "IO.h"
|
||||||
|
|
||||||
|
// Generated using [b, a] = butter(1, 0.001) in MATLAB
|
||||||
|
static q31_t DC_FILTER[] = {3367972, 0, 3367972, 0, 2140747704, 0}; // {b0, 0, b1, b2, -a1, -a2}
|
||||||
|
const uint32_t DC_FILTER_STAGES = 1U; // One Biquad stage
|
||||||
|
|
||||||
// Generated using rcosdesign(0.2, 8, 5, 'sqrt') in MATLAB
|
// 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,
|
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,
|
11237, 14331, 15464, 14331, 11237, 6995, 2667, -770, -2706, -3040, -2144, -675, 683, 1450, 1472, 909, 112,
|
||||||
-553, -847, -731, -340, 104, 401, 0};
|
-553, -847, -731, -340, 104, 401, 0};
|
||||||
const uint16_t RRC_0_2_FILTER_LEN = 42U;
|
const uint16_t RRC_0_2_FILTER_LEN = 42U;
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
10134, 10731, 10935, 10731, 10134, 9184, 7946, 6502, 4946, 3376, 1886, 557, -545, -1375, -1914, -2164, -2150,
|
||||||
|
-1915, -1516, -1016, -477, 39, 483, 819, 1026, 1097, 1041, 880, 643, 364, 79, -181, -391, -533, -599, -590,
|
||||||
|
-517, -393, -240, -78, 73, 198, 284, 0};
|
||||||
|
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;
|
||||||
|
|
||||||
// Generated using gaussfir(0.5, 4, 5) in MATLAB
|
// 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};
|
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;
|
const uint16_t GAUSSIAN_0_5_FILTER_LEN = 12U;
|
||||||
|
|
||||||
// One symbol boxcar filter
|
// One symbol boxcar filter
|
||||||
static q15_t BOXCAR_FILTER[] = {3000, 3000, 3000, 3000, 3000, 0};
|
static q15_t BOXCAR_FILTER[] = {12000, 12000, 12000, 12000, 12000, 0};
|
||||||
const uint16_t BOXCAR_FILTER_LEN = 6U;
|
const uint16_t BOXCAR_FILTER_LEN = 6U;
|
||||||
|
|
||||||
const uint16_t DC_OFFSET = 2048U;
|
const uint16_t DC_OFFSET = 2048U;
|
||||||
@@ -43,12 +59,20 @@ m_started(false),
|
|||||||
m_rxBuffer(RX_RINGBUFFER_SIZE),
|
m_rxBuffer(RX_RINGBUFFER_SIZE),
|
||||||
m_txBuffer(TX_RINGBUFFER_SIZE),
|
m_txBuffer(TX_RINGBUFFER_SIZE),
|
||||||
m_rssiBuffer(RX_RINGBUFFER_SIZE),
|
m_rssiBuffer(RX_RINGBUFFER_SIZE),
|
||||||
m_rrcFilter(),
|
m_dcFilter(),
|
||||||
|
m_dcState(),
|
||||||
|
m_dmrFilter(),
|
||||||
m_gaussianFilter(),
|
m_gaussianFilter(),
|
||||||
m_boxcarFilter(),
|
m_boxcarFilter(),
|
||||||
m_rrcState(),
|
m_nxdnFilter(),
|
||||||
|
m_nxdnISincFilter(),
|
||||||
|
m_ysfFilter(),
|
||||||
|
m_dmrState(),
|
||||||
m_gaussianState(),
|
m_gaussianState(),
|
||||||
m_boxcarState(),
|
m_boxcarState(),
|
||||||
|
m_nxdnState(),
|
||||||
|
m_nxdnISincState(),
|
||||||
|
m_ysfState(),
|
||||||
m_pttInvert(false),
|
m_pttInvert(false),
|
||||||
m_rxLevel(128 * 128),
|
m_rxLevel(128 * 128),
|
||||||
m_cwIdTXLevel(128 * 128),
|
m_cwIdTXLevel(128 * 128),
|
||||||
@@ -56,6 +80,9 @@ m_dstarTXLevel(128 * 128),
|
|||||||
m_dmrTXLevel(128 * 128),
|
m_dmrTXLevel(128 * 128),
|
||||||
m_ysfTXLevel(128 * 128),
|
m_ysfTXLevel(128 * 128),
|
||||||
m_p25TXLevel(128 * 128),
|
m_p25TXLevel(128 * 128),
|
||||||
|
m_nxdnTXLevel(128 * 128),
|
||||||
|
m_rxDCOffset(DC_OFFSET),
|
||||||
|
m_txDCOffset(DC_OFFSET),
|
||||||
m_ledCount(0U),
|
m_ledCount(0U),
|
||||||
m_ledValue(true),
|
m_ledValue(true),
|
||||||
m_detect(false),
|
m_detect(false),
|
||||||
@@ -64,13 +91,22 @@ m_dacOverflow(0U),
|
|||||||
m_watchdog(0U),
|
m_watchdog(0U),
|
||||||
m_lockout(false)
|
m_lockout(false)
|
||||||
{
|
{
|
||||||
::memset(m_rrcState, 0x00U, 70U * sizeof(q15_t));
|
::memset(m_dmrState, 0x00U, 70U * sizeof(q15_t));
|
||||||
::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t));
|
::memset(m_gaussianState, 0x00U, 40U * sizeof(q15_t));
|
||||||
::memset(m_boxcarState, 0x00U, 30U * 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_ysfState, 0x00U, 70U * sizeof(q15_t));
|
||||||
|
::memset(m_dcState, 0x00U, 4U * sizeof(q31_t));
|
||||||
|
|
||||||
m_rrcFilter.numTaps = RRC_0_2_FILTER_LEN;
|
m_dcFilter.numStages = DC_FILTER_STAGES;
|
||||||
m_rrcFilter.pState = m_rrcState;
|
m_dcFilter.pState = m_dcState;
|
||||||
m_rrcFilter.pCoeffs = RRC_0_2_FILTER;
|
m_dcFilter.pCoeffs = DC_FILTER;
|
||||||
|
m_dcFilter.postShift = 0;
|
||||||
|
|
||||||
|
m_dmrFilter.numTaps = RRC_0_2_FILTER_LEN;
|
||||||
|
m_dmrFilter.pState = m_dmrState;
|
||||||
|
m_dmrFilter.pCoeffs = RRC_0_2_FILTER;
|
||||||
|
|
||||||
m_gaussianFilter.numTaps = GAUSSIAN_0_5_FILTER_LEN;
|
m_gaussianFilter.numTaps = GAUSSIAN_0_5_FILTER_LEN;
|
||||||
m_gaussianFilter.pState = m_gaussianState;
|
m_gaussianFilter.pState = m_gaussianState;
|
||||||
@@ -80,7 +116,122 @@ m_lockout(false)
|
|||||||
m_boxcarFilter.pState = m_boxcarState;
|
m_boxcarFilter.pState = m_boxcarState;
|
||||||
m_boxcarFilter.pCoeffs = BOXCAR_FILTER;
|
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;
|
||||||
|
|
||||||
|
m_nxdnISincFilter.numTaps = NXDN_ISINC_FILTER_LEN;
|
||||||
|
m_nxdnISincFilter.pState = m_nxdnISincState;
|
||||||
|
m_nxdnISincFilter.pCoeffs = NXDN_ISINC_FILTER;
|
||||||
|
|
||||||
|
m_ysfFilter.numTaps = RRC_0_2_FILTER_LEN;
|
||||||
|
m_ysfFilter.pState = m_ysfState;
|
||||||
|
m_ysfFilter.pCoeffs = RRC_0_2_FILTER;
|
||||||
|
|
||||||
initInt();
|
initInt();
|
||||||
|
|
||||||
|
selfTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::selfTest()
|
||||||
|
{
|
||||||
|
bool ledValue = false;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 6; i++) {
|
||||||
|
ledValue = !ledValue;
|
||||||
|
|
||||||
|
// We exclude PTT to avoid trigger the transmitter
|
||||||
|
setLEDInt(ledValue);
|
||||||
|
setCOSInt(ledValue);
|
||||||
|
#if defined(ARDUINO_MODE_PINS)
|
||||||
|
setDStarInt(ledValue);
|
||||||
|
setDMRInt(ledValue);
|
||||||
|
setYSFInt(ledValue);
|
||||||
|
setP25Int(ledValue);
|
||||||
|
setNXDNInt(ledValue);
|
||||||
|
#endif
|
||||||
|
delayInt(250);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ARDUINO_MODE_PINS)
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(false);
|
||||||
|
setYSFInt(false);
|
||||||
|
setP25Int(false);
|
||||||
|
setNXDNInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(true);
|
||||||
|
setYSFInt(false);
|
||||||
|
setP25Int(false);
|
||||||
|
setNXDNInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(true);
|
||||||
|
setYSFInt(true);
|
||||||
|
setP25Int(false);
|
||||||
|
setNXDNInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(true);
|
||||||
|
setYSFInt(true);
|
||||||
|
setP25Int(true);
|
||||||
|
setNXDNInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(true);
|
||||||
|
setYSFInt(true);
|
||||||
|
setP25Int(true);
|
||||||
|
setNXDNInt(true);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(true);
|
||||||
|
setYSFInt(true);
|
||||||
|
setP25Int(true);
|
||||||
|
setNXDNInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(true);
|
||||||
|
setYSFInt(true);
|
||||||
|
setP25Int(false);
|
||||||
|
setNXDNInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(true);
|
||||||
|
setYSFInt(false);
|
||||||
|
setP25Int(false);
|
||||||
|
setNXDNInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(true);
|
||||||
|
setDMRInt(false);
|
||||||
|
setYSFInt(false);
|
||||||
|
setP25Int(false);
|
||||||
|
setNXDNInt(false);
|
||||||
|
|
||||||
|
delayInt(250);
|
||||||
|
|
||||||
|
setDStarInt(false);
|
||||||
|
setDMRInt(false);
|
||||||
|
setYSFInt(false);
|
||||||
|
setP25Int(false);
|
||||||
|
setNXDNInt(false);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIO::start()
|
void CIO::start()
|
||||||
@@ -101,7 +252,7 @@ void CIO::process()
|
|||||||
if (m_started) {
|
if (m_started) {
|
||||||
// Two seconds timeout
|
// Two seconds timeout
|
||||||
if (m_watchdog >= 48000U) {
|
if (m_watchdog >= 48000U) {
|
||||||
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF) {
|
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN) {
|
||||||
if (m_modemState == STATE_DMR && m_tx)
|
if (m_modemState == STATE_DMR && m_tx)
|
||||||
dmrTX.setStart(false);
|
dmrTX.setStart(false);
|
||||||
m_modemState = STATE_IDLE;
|
m_modemState = STATE_IDLE;
|
||||||
@@ -149,7 +300,7 @@ void CIO::process()
|
|||||||
if (m_detect && (sample == 0U || sample == 4095U))
|
if (m_detect && (sample == 0U || sample == 4095U))
|
||||||
m_adcOverflow++;
|
m_adcOverflow++;
|
||||||
|
|
||||||
q15_t res1 = q15_t(sample) - DC_OFFSET;
|
q15_t res1 = q15_t(sample) - m_rxDCOffset;
|
||||||
q31_t res2 = res1 * m_rxLevel;
|
q31_t res2 = res1 * m_rxLevel;
|
||||||
samples[i] = q15_t(__SSAT((res2 >> 15), 16));
|
samples[i] = q15_t(__SSAT((res2 >> 15), 16));
|
||||||
}
|
}
|
||||||
@@ -157,71 +308,108 @@ void CIO::process()
|
|||||||
if (m_lockout)
|
if (m_lockout)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
q31_t dcLevel = 0;
|
||||||
|
q31_t dcValues[RX_BLOCK_SIZE];
|
||||||
|
q31_t q31Samples[RX_BLOCK_SIZE];
|
||||||
|
|
||||||
|
::arm_q15_to_q31(samples, q31Samples, RX_BLOCK_SIZE);
|
||||||
|
::arm_biquad_cascade_df1_q31(&m_dcFilter, q31Samples, dcValues, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < RX_BLOCK_SIZE; i++)
|
||||||
|
dcLevel += dcValues[i];
|
||||||
|
dcLevel /= RX_BLOCK_SIZE;
|
||||||
|
|
||||||
|
q15_t offset = q15_t(__SSAT((dcLevel >> 16), 16));;
|
||||||
|
|
||||||
|
q15_t dcSamples[RX_BLOCK_SIZE];
|
||||||
|
for (uint8_t i = 0U; i < RX_BLOCK_SIZE; i++)
|
||||||
|
dcSamples[i] = samples[i] - offset;
|
||||||
|
|
||||||
if (m_modemState == STATE_IDLE) {
|
if (m_modemState == STATE_IDLE) {
|
||||||
if (m_dstarEnable) {
|
if (m_dstarEnable) {
|
||||||
q15_t GMSKVals[RX_BLOCK_SIZE];
|
q15_t GMSKVals[RX_BLOCK_SIZE];
|
||||||
::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE);
|
::arm_fir_fast_q15(&m_gaussianFilter, dcSamples, GMSKVals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
|
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_p25Enable) {
|
if (m_p25Enable) {
|
||||||
q15_t P25Vals[RX_BLOCK_SIZE];
|
q15_t P25Vals[RX_BLOCK_SIZE];
|
||||||
::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE);
|
::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, P25Vals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
|
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_dmrEnable || m_ysfEnable) {
|
if (m_nxdnEnable) {
|
||||||
q15_t C4FSKVals[RX_BLOCK_SIZE];
|
q15_t NXDNVals[RX_BLOCK_SIZE];
|
||||||
::arm_fir_fast_q15(&m_rrcFilter, samples, C4FSKVals, RX_BLOCK_SIZE);
|
q15_t NXDNValsTmp[RX_BLOCK_SIZE];
|
||||||
|
::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNValsTmp, RX_BLOCK_SIZE);
|
||||||
|
::arm_fir_fast_q15(&m_nxdnISincFilter, NXDNValsTmp, NXDNVals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
if (m_dmrEnable) {
|
nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE);
|
||||||
if (m_duplex)
|
|
||||||
dmrIdleRX.samples(C4FSKVals, RX_BLOCK_SIZE);
|
|
||||||
else
|
|
||||||
dmrDMORX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ysfEnable)
|
if (m_ysfEnable) {
|
||||||
ysfRX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE);
|
q15_t YSFVals[RX_BLOCK_SIZE];
|
||||||
|
::arm_fir_fast_q15(&m_ysfFilter, dcSamples, YSFVals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_dmrEnable) {
|
||||||
|
q15_t DMRVals[RX_BLOCK_SIZE];
|
||||||
|
::arm_fir_fast_q15(&m_dmrFilter, samples, DMRVals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
if (m_duplex)
|
||||||
|
dmrIdleRX.samples(DMRVals, RX_BLOCK_SIZE);
|
||||||
|
else
|
||||||
|
dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
} else if (m_modemState == STATE_DSTAR) {
|
} else if (m_modemState == STATE_DSTAR) {
|
||||||
if (m_dstarEnable) {
|
if (m_dstarEnable) {
|
||||||
q15_t GMSKVals[RX_BLOCK_SIZE];
|
q15_t GMSKVals[RX_BLOCK_SIZE];
|
||||||
::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE);
|
::arm_fir_fast_q15(&m_gaussianFilter, dcSamples, GMSKVals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
|
dstarRX.samples(GMSKVals, rssi, RX_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
} else if (m_modemState == STATE_DMR) {
|
} else if (m_modemState == STATE_DMR) {
|
||||||
if (m_dmrEnable) {
|
if (m_dmrEnable) {
|
||||||
q15_t C4FSKVals[RX_BLOCK_SIZE];
|
q15_t DMRVals[RX_BLOCK_SIZE];
|
||||||
::arm_fir_fast_q15(&m_rrcFilter, samples, C4FSKVals, RX_BLOCK_SIZE);
|
::arm_fir_fast_q15(&m_dmrFilter, samples, DMRVals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
if (m_duplex) {
|
if (m_duplex) {
|
||||||
// If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs
|
// If the transmitter isn't on, use the DMR idle RX to detect the wakeup CSBKs
|
||||||
if (m_tx)
|
if (m_tx)
|
||||||
dmrRX.samples(C4FSKVals, rssi, control, RX_BLOCK_SIZE);
|
dmrRX.samples(DMRVals, rssi, control, RX_BLOCK_SIZE);
|
||||||
else
|
else
|
||||||
dmrIdleRX.samples(C4FSKVals, RX_BLOCK_SIZE);
|
dmrIdleRX.samples(DMRVals, RX_BLOCK_SIZE);
|
||||||
} else {
|
} else {
|
||||||
dmrDMORX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE);
|
dmrDMORX.samples(DMRVals, rssi, RX_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (m_modemState == STATE_YSF) {
|
} else if (m_modemState == STATE_YSF) {
|
||||||
if (m_ysfEnable) {
|
if (m_ysfEnable) {
|
||||||
q15_t C4FSKVals[RX_BLOCK_SIZE];
|
q15_t YSFVals[RX_BLOCK_SIZE];
|
||||||
::arm_fir_fast_q15(&m_rrcFilter, samples, C4FSKVals, RX_BLOCK_SIZE);
|
::arm_fir_fast_q15(&m_ysfFilter, dcSamples, YSFVals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
ysfRX.samples(C4FSKVals, rssi, RX_BLOCK_SIZE);
|
ysfRX.samples(YSFVals, rssi, RX_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
} else if (m_modemState == STATE_P25) {
|
} else if (m_modemState == STATE_P25) {
|
||||||
if (m_p25Enable) {
|
if (m_p25Enable) {
|
||||||
q15_t P25Vals[RX_BLOCK_SIZE];
|
q15_t P25Vals[RX_BLOCK_SIZE];
|
||||||
::arm_fir_fast_q15(&m_boxcarFilter, samples, P25Vals, RX_BLOCK_SIZE);
|
::arm_fir_fast_q15(&m_boxcarFilter, dcSamples, P25Vals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
|
p25RX.samples(P25Vals, rssi, RX_BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
} else if (m_modemState == STATE_NXDN) {
|
||||||
|
if (m_nxdnEnable) {
|
||||||
|
q15_t NXDNVals[RX_BLOCK_SIZE];
|
||||||
|
q15_t NXDNValsTmp[RX_BLOCK_SIZE];
|
||||||
|
::arm_fir_fast_q15(&m_nxdnFilter, dcSamples, NXDNValsTmp, RX_BLOCK_SIZE);
|
||||||
|
::arm_fir_fast_q15(&m_nxdnISincFilter, NXDNValsTmp, NXDNVals, RX_BLOCK_SIZE);
|
||||||
|
|
||||||
|
nxdnRX.samples(NXDNVals, rssi, RX_BLOCK_SIZE);
|
||||||
|
}
|
||||||
} else if (m_modemState == STATE_DSTARCAL) {
|
} else if (m_modemState == STATE_DSTARCAL) {
|
||||||
q15_t GMSKVals[RX_BLOCK_SIZE];
|
q15_t GMSKVals[RX_BLOCK_SIZE];
|
||||||
::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE);
|
::arm_fir_fast_q15(&m_gaussianFilter, samples, GMSKVals, RX_BLOCK_SIZE);
|
||||||
@@ -261,6 +449,9 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
|
|||||||
case STATE_P25:
|
case STATE_P25:
|
||||||
txLevel = m_p25TXLevel;
|
txLevel = m_p25TXLevel;
|
||||||
break;
|
break;
|
||||||
|
case STATE_NXDN:
|
||||||
|
txLevel = m_nxdnTXLevel;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
txLevel = m_cwIdTXLevel;
|
txLevel = m_cwIdTXLevel;
|
||||||
break;
|
break;
|
||||||
@@ -269,7 +460,7 @@ void CIO::write(MMDVM_STATE mode, q15_t* samples, uint16_t length, const uint8_t
|
|||||||
for (uint16_t i = 0U; i < length; i++) {
|
for (uint16_t i = 0U; i < length; i++) {
|
||||||
q31_t res1 = samples[i] * txLevel;
|
q31_t res1 = samples[i] * txLevel;
|
||||||
q15_t res2 = q15_t(__SSAT((res1 >> 15), 16));
|
q15_t res2 = q15_t(__SSAT((res1 >> 15), 16));
|
||||||
uint16_t res3 = uint16_t(res2 + DC_OFFSET);
|
uint16_t res3 = uint16_t(res2 + m_txDCOffset);
|
||||||
|
|
||||||
// Detect DAC overflow
|
// Detect DAC overflow
|
||||||
if (res3 > 4095U)
|
if (res3 > 4095U)
|
||||||
@@ -307,10 +498,11 @@ void CIO::setMode()
|
|||||||
setDMRInt(m_modemState == STATE_DMR);
|
setDMRInt(m_modemState == STATE_DMR);
|
||||||
setYSFInt(m_modemState == STATE_YSF);
|
setYSFInt(m_modemState == STATE_YSF);
|
||||||
setP25Int(m_modemState == STATE_P25);
|
setP25Int(m_modemState == STATE_P25);
|
||||||
|
setNXDNInt(m_modemState == STATE_NXDN);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel)
|
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, int16_t txDCOffset, int16_t rxDCOffset)
|
||||||
{
|
{
|
||||||
m_pttInvert = pttInvert;
|
m_pttInvert = pttInvert;
|
||||||
|
|
||||||
@@ -320,6 +512,10 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx
|
|||||||
m_dmrTXLevel = q15_t(dmrTXLevel * 128);
|
m_dmrTXLevel = q15_t(dmrTXLevel * 128);
|
||||||
m_ysfTXLevel = q15_t(ysfTXLevel * 128);
|
m_ysfTXLevel = q15_t(ysfTXLevel * 128);
|
||||||
m_p25TXLevel = q15_t(p25TXLevel * 128);
|
m_p25TXLevel = q15_t(p25TXLevel * 128);
|
||||||
|
m_nxdnTXLevel = q15_t(nxdnTXLevel * 128);
|
||||||
|
|
||||||
|
m_rxDCOffset = DC_OFFSET + rxDCOffset;
|
||||||
|
m_txDCOffset = DC_OFFSET + txDCOffset;
|
||||||
|
|
||||||
if (rxInvert)
|
if (rxInvert)
|
||||||
m_rxLevel = -m_rxLevel;
|
m_rxLevel = -m_rxLevel;
|
||||||
@@ -329,6 +525,7 @@ void CIO::setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rx
|
|||||||
m_dmrTXLevel = -m_dmrTXLevel;
|
m_dmrTXLevel = -m_dmrTXLevel;
|
||||||
m_ysfTXLevel = -m_ysfTXLevel;
|
m_ysfTXLevel = -m_ysfTXLevel;
|
||||||
m_p25TXLevel = -m_p25TXLevel;
|
m_p25TXLevel = -m_p25TXLevel;
|
||||||
|
m_nxdnTXLevel = -m_nxdnTXLevel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,6 +553,11 @@ void CIO::resetWatchdog()
|
|||||||
m_watchdog = 0U;
|
m_watchdog = 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t CIO::getWatchdog()
|
||||||
|
{
|
||||||
|
return m_watchdog;
|
||||||
|
}
|
||||||
|
|
||||||
bool CIO::hasLockout() const
|
bool CIO::hasLockout() const
|
||||||
{
|
{
|
||||||
return m_lockout;
|
return m_lockout;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -42,7 +42,7 @@ public:
|
|||||||
|
|
||||||
void interrupt();
|
void interrupt();
|
||||||
|
|
||||||
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel);
|
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 nxdnLevel, int16_t txDCOffset, int16_t rxDCOffset);
|
||||||
|
|
||||||
void getOverflow(bool& adcOverflow, bool& dacOverflow);
|
void getOverflow(bool& adcOverflow, bool& dacOverflow);
|
||||||
|
|
||||||
@@ -52,6 +52,9 @@ public:
|
|||||||
bool hasLockout() const;
|
bool hasLockout() const;
|
||||||
|
|
||||||
void resetWatchdog();
|
void resetWatchdog();
|
||||||
|
uint32_t getWatchdog();
|
||||||
|
|
||||||
|
void selfTest();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_started;
|
bool m_started;
|
||||||
@@ -60,12 +63,21 @@ private:
|
|||||||
CSampleRB m_txBuffer;
|
CSampleRB m_txBuffer;
|
||||||
CRSSIRB m_rssiBuffer;
|
CRSSIRB m_rssiBuffer;
|
||||||
|
|
||||||
arm_fir_instance_q15 m_rrcFilter;
|
arm_biquad_casd_df1_inst_q31 m_dcFilter;
|
||||||
|
q31_t m_dcState[4];
|
||||||
|
|
||||||
|
arm_fir_instance_q15 m_dmrFilter;
|
||||||
arm_fir_instance_q15 m_gaussianFilter;
|
arm_fir_instance_q15 m_gaussianFilter;
|
||||||
arm_fir_instance_q15 m_boxcarFilter;
|
arm_fir_instance_q15 m_boxcarFilter;
|
||||||
q15_t m_rrcState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
arm_fir_instance_q15 m_nxdnFilter;
|
||||||
|
arm_fir_instance_q15 m_nxdnISincFilter;
|
||||||
|
arm_fir_instance_q15 m_ysfFilter;
|
||||||
|
q15_t m_dmrState[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_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_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
|
||||||
|
q15_t m_ysfState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
||||||
|
|
||||||
bool m_pttInvert;
|
bool m_pttInvert;
|
||||||
q15_t m_rxLevel;
|
q15_t m_rxLevel;
|
||||||
@@ -74,6 +86,10 @@ private:
|
|||||||
q15_t m_dmrTXLevel;
|
q15_t m_dmrTXLevel;
|
||||||
q15_t m_ysfTXLevel;
|
q15_t m_ysfTXLevel;
|
||||||
q15_t m_p25TXLevel;
|
q15_t m_p25TXLevel;
|
||||||
|
q15_t m_nxdnTXLevel;
|
||||||
|
|
||||||
|
uint16_t m_rxDCOffset;
|
||||||
|
uint16_t m_txDCOffset;
|
||||||
|
|
||||||
uint32_t m_ledCount;
|
uint32_t m_ledCount;
|
||||||
bool m_ledValue;
|
bool m_ledValue;
|
||||||
@@ -101,6 +117,9 @@ private:
|
|||||||
void setDMRInt(bool on);
|
void setDMRInt(bool on);
|
||||||
void setYSFInt(bool on);
|
void setYSFInt(bool on);
|
||||||
void setP25Int(bool on);
|
void setP25Int(bool on);
|
||||||
|
void setNXDNInt(bool on);
|
||||||
|
|
||||||
|
void delayInt(unsigned int dly);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
#define PIN_DMR 17
|
#define PIN_DMR 17
|
||||||
#define PIN_YSF 18
|
#define PIN_YSF 18
|
||||||
#define PIN_P25 19
|
#define PIN_P25 19
|
||||||
|
#define PIN_NXDN 20
|
||||||
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
|
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
|
||||||
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
|
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
|
||||||
#define ADC_CDR_Chan 7
|
#define ADC_CDR_Chan 7
|
||||||
@@ -46,6 +47,7 @@
|
|||||||
#define PIN_DMR 8
|
#define PIN_DMR 8
|
||||||
#define PIN_YSF 7
|
#define PIN_YSF 7
|
||||||
#define PIN_P25 6
|
#define PIN_P25 6
|
||||||
|
#define PIN_NXDN 5
|
||||||
#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13)
|
#define ADC_CHER_Chan (1<<13) // ADC on Due pin A11 - Due AD13 - (1 << 13)
|
||||||
#define ADC_ISR_EOC_Chan ADC_ISR_EOC13
|
#define ADC_ISR_EOC_Chan ADC_ISR_EOC13
|
||||||
#define ADC_CDR_Chan 13
|
#define ADC_CDR_Chan 13
|
||||||
@@ -61,6 +63,7 @@
|
|||||||
#define PIN_DMR 8
|
#define PIN_DMR 8
|
||||||
#define PIN_YSF 7
|
#define PIN_YSF 7
|
||||||
#define PIN_P25 6
|
#define PIN_P25 6
|
||||||
|
#define PIN_NXDN 5
|
||||||
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
|
#define ADC_CHER_Chan (1<<7) // ADC on Due pin A0 - Due AD7 - (1 << 7)
|
||||||
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
|
#define ADC_ISR_EOC_Chan ADC_ISR_EOC7
|
||||||
#define ADC_CDR_Chan 7
|
#define ADC_CDR_Chan 7
|
||||||
@@ -95,6 +98,7 @@ void CIO::initInt()
|
|||||||
pinMode(PIN_DMR, OUTPUT);
|
pinMode(PIN_DMR, OUTPUT);
|
||||||
pinMode(PIN_YSF, OUTPUT);
|
pinMode(PIN_YSF, OUTPUT);
|
||||||
pinMode(PIN_P25, OUTPUT);
|
pinMode(PIN_P25, OUTPUT);
|
||||||
|
pinMode(PIN_NXDN, OUTPUT);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,4 +230,15 @@ void CIO::setP25Int(bool on)
|
|||||||
digitalWrite(PIN_P25, on ? HIGH : LOW);
|
digitalWrite(PIN_P25, on ? HIGH : LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIO::setNXDNInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_NXDN, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::delayInt(unsigned int dly)
|
||||||
|
{
|
||||||
|
delay(dly);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
* Copyright (C) 2016, 2017 by Andy Uribe CA6JAU
|
* Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
|
||||||
* Copyright (C) 2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2017,2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -22,27 +22,28 @@
|
|||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "IO.h"
|
#include "IO.h"
|
||||||
|
|
||||||
#if defined(STM32F4XX) || defined(STM32F4)
|
#if defined(STM32F4XX) || defined(STM32F7XX)
|
||||||
|
|
||||||
#if defined(STM32F4_DISCOVERY)
|
#if defined(STM32F4_DISCOVERY)
|
||||||
/*
|
/*
|
||||||
Pin definitions for STM32F4 Discovery Board:
|
Pin definitions for STM32F4 Discovery Board:
|
||||||
|
|
||||||
PTT PB13 output
|
PTT PB13 output P1 Pin37
|
||||||
COSLED PA7 output
|
COSLED PA7 output P1 Pin17
|
||||||
LED PD15 output
|
LED PD15 output P1 Pin47
|
||||||
COS PA5 input
|
COS PA5 input P1 Pin15
|
||||||
|
|
||||||
DSTAR PD12 output
|
DSTAR PD12 output P1 Pin44
|
||||||
DMR PD13 output
|
DMR PD13 output P1 Pin45
|
||||||
YSF PD14 output
|
YSF PD14 output P1 Pin46
|
||||||
P25 PD11 output
|
P25 PD11 output P1 Pin43
|
||||||
|
NXDN PD10 output P1 Pin42
|
||||||
|
|
||||||
RX PA0 analog input
|
RX PA0 analog input P1 Pin12
|
||||||
RSSI PA1 analog input
|
RSSI PA1 analog input P1 Pin11
|
||||||
TX PA4 analog output
|
TX PA4 analog output P1 Pin16
|
||||||
|
|
||||||
EXT_CLK PA15 input
|
EXT_CLK PA15 input P2 Pin40
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PIN_COS GPIO_Pin_5
|
#define PIN_COS GPIO_Pin_5
|
||||||
@@ -65,6 +66,10 @@ EXT_CLK PA15 input
|
|||||||
#define PORT_P25 GPIOD
|
#define PORT_P25 GPIOD
|
||||||
#define RCC_Per_P25 RCC_AHB1Periph_GPIOD
|
#define RCC_Per_P25 RCC_AHB1Periph_GPIOD
|
||||||
|
|
||||||
|
#define PIN_NXDN GPIO_Pin_10
|
||||||
|
#define PORT_NXDN GPIOD
|
||||||
|
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOD
|
||||||
|
|
||||||
#define PIN_DSTAR GPIO_Pin_12
|
#define PIN_DSTAR GPIO_Pin_12
|
||||||
#define PORT_DSTAR GPIOD
|
#define PORT_DSTAR GPIOD
|
||||||
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOD
|
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOD
|
||||||
@@ -107,6 +112,7 @@ DSTAR PC7 output
|
|||||||
DMR PC8 output
|
DMR PC8 output
|
||||||
YSF PA8 output
|
YSF PA8 output
|
||||||
P25 PC9 output
|
P25 PC9 output
|
||||||
|
NXDN PB1 output
|
||||||
|
|
||||||
RX PA0 analog input
|
RX PA0 analog input
|
||||||
RSSI PA7 analog input
|
RSSI PA7 analog input
|
||||||
@@ -135,6 +141,160 @@ EXT_CLK PA15 input
|
|||||||
#define PORT_P25 GPIOC
|
#define PORT_P25 GPIOC
|
||||||
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
|
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_NXDN GPIO_Pin_1
|
||||||
|
#define PORT_NXDN GPIOB
|
||||||
|
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_DSTAR GPIO_Pin_7
|
||||||
|
#define PORT_DSTAR GPIOC
|
||||||
|
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_DMR GPIO_Pin_8
|
||||||
|
#define PORT_DMR GPIOC
|
||||||
|
#define RCC_Per_DMR RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_YSF GPIO_Pin_8
|
||||||
|
#define PORT_YSF GPIOA
|
||||||
|
#define RCC_Per_YSF RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_EXT_CLK GPIO_Pin_15
|
||||||
|
#define SRC_EXT_CLK GPIO_PinSource15
|
||||||
|
#define PORT_EXT_CLK GPIOA
|
||||||
|
|
||||||
|
#define PIN_RX GPIO_Pin_0
|
||||||
|
#define PIN_RX_CH ADC_Channel_0
|
||||||
|
#define PORT_RX GPIOA
|
||||||
|
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_RSSI GPIO_Pin_7
|
||||||
|
#define PIN_RSSI_CH ADC_Channel_7
|
||||||
|
#define PORT_RSSI GPIOA
|
||||||
|
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_TX GPIO_Pin_4
|
||||||
|
#define PIN_TX_CH DAC_Channel_1
|
||||||
|
|
||||||
|
#elif defined(STM32F722_PI)
|
||||||
|
/*
|
||||||
|
Pin definitions for STM32F722 Pi Board:
|
||||||
|
|
||||||
|
PTT PB13 output
|
||||||
|
COSLED PB14 output
|
||||||
|
LED PB15 output
|
||||||
|
COS PC0 input
|
||||||
|
|
||||||
|
DSTAR PC7 output
|
||||||
|
DMR PC8 output
|
||||||
|
YSF PA8 output
|
||||||
|
P25 PC9 output
|
||||||
|
NXDN PB1 output
|
||||||
|
|
||||||
|
RX PA0 analog input
|
||||||
|
RSSI PA7 analog input
|
||||||
|
TX PA4 analog output
|
||||||
|
|
||||||
|
EXT_CLK PA15 input
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PIN_COS GPIO_Pin_0
|
||||||
|
#define PORT_COS GPIOC
|
||||||
|
#define RCC_Per_COS RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_PTT GPIO_Pin_13
|
||||||
|
#define PORT_PTT GPIOB
|
||||||
|
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_COSLED GPIO_Pin_14
|
||||||
|
#define PORT_COSLED GPIOB
|
||||||
|
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_LED GPIO_Pin_15
|
||||||
|
#define PORT_LED GPIOB
|
||||||
|
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_P25 GPIO_Pin_9
|
||||||
|
#define PORT_P25 GPIOC
|
||||||
|
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_NXDN GPIO_Pin_1
|
||||||
|
#define PORT_NXDN GPIOB
|
||||||
|
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_DSTAR GPIO_Pin_7
|
||||||
|
#define PORT_DSTAR GPIOC
|
||||||
|
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_DMR GPIO_Pin_8
|
||||||
|
#define PORT_DMR GPIOC
|
||||||
|
#define RCC_Per_DMR RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_YSF GPIO_Pin_8
|
||||||
|
#define PORT_YSF GPIOA
|
||||||
|
#define RCC_Per_YSF RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_EXT_CLK GPIO_Pin_15
|
||||||
|
#define SRC_EXT_CLK GPIO_PinSource15
|
||||||
|
#define PORT_EXT_CLK GPIOA
|
||||||
|
|
||||||
|
#define PIN_RX GPIO_Pin_0
|
||||||
|
#define PIN_RX_CH ADC_Channel_0
|
||||||
|
#define PORT_RX GPIOA
|
||||||
|
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_RSSI GPIO_Pin_7
|
||||||
|
#define PIN_RSSI_CH ADC_Channel_7
|
||||||
|
#define PORT_RSSI GPIOA
|
||||||
|
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_TX GPIO_Pin_4
|
||||||
|
#define PIN_TX_CH DAC_Channel_1
|
||||||
|
|
||||||
|
#elif defined(STM32F4_F4M)
|
||||||
|
/*
|
||||||
|
Pin definitions for MMDVM-F4M Pi-Hat F0DEI board:
|
||||||
|
|
||||||
|
PTT PB13 output
|
||||||
|
COSLED PB14 output
|
||||||
|
LED PB15 output
|
||||||
|
COS PC0 input
|
||||||
|
|
||||||
|
DSTAR PC7 output
|
||||||
|
DMR PC8 output
|
||||||
|
YSF PA8 output
|
||||||
|
P25 PC9 output
|
||||||
|
NXDN PB1 output
|
||||||
|
|
||||||
|
RX PA0 analog input
|
||||||
|
RSSI PA7 analog input
|
||||||
|
TX PA4 analog output
|
||||||
|
|
||||||
|
EXT_CLK PA15 input
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PIN_COS GPIO_Pin_0
|
||||||
|
#define PORT_COS GPIOC
|
||||||
|
#define RCC_Per_COS RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_PTT GPIO_Pin_13
|
||||||
|
#define PORT_PTT GPIOB
|
||||||
|
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_COSLED GPIO_Pin_14
|
||||||
|
#define PORT_COSLED GPIOB
|
||||||
|
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_LED GPIO_Pin_15
|
||||||
|
#define PORT_LED GPIOB
|
||||||
|
#define RCC_Per_LED RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_P25 GPIO_Pin_9
|
||||||
|
#define PORT_P25 GPIOC
|
||||||
|
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_NXDN GPIO_Pin_1
|
||||||
|
#define PORT_NXDN GPIOB
|
||||||
|
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
#define PIN_DSTAR GPIO_Pin_7
|
#define PIN_DSTAR GPIO_Pin_7
|
||||||
#define PORT_DSTAR GPIOC
|
#define PORT_DSTAR GPIOC
|
||||||
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC
|
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOC
|
||||||
@@ -170,26 +330,28 @@ EXT_CLK PA15 input
|
|||||||
/*
|
/*
|
||||||
Pin definitions for STM32F4 Nucleo boards (ST Morpho header):
|
Pin definitions for STM32F4 Nucleo boards (ST Morpho header):
|
||||||
|
|
||||||
PTT PB13 output
|
PTT PB13 output CN10 Pin30
|
||||||
COSLED PB14 output
|
COSLED PB14 output CN10 Pin28
|
||||||
LED PA5 output
|
LED PA5 output CN10 Pin11
|
||||||
COS PB15 input
|
COS PB15 input CN10 Pin26
|
||||||
|
|
||||||
DSTAR PB10 output
|
DSTAR PB10 output CN10 Pin25
|
||||||
DMR PB4 output
|
DMR PB4 output CN10 Pin27
|
||||||
YSF PB5 output
|
YSF PB5 output CN10 Pin29
|
||||||
P25 PB3 output
|
P25 PB3 output CN10 Pin31
|
||||||
|
NXDN PA10 output CN10 Pin33
|
||||||
|
|
||||||
MDSTAR PC4 output
|
MDSTAR PC4 output CN10 Pin34
|
||||||
MDMR PC5 outout
|
MDMR PC5 output CN10 Pin6
|
||||||
MYSF PC2 output
|
MYSF PC2 output CN7 Pin35
|
||||||
MP25 PC3 output
|
MP25 PC3 output CN7 Pin37
|
||||||
|
MNXDN PC6 output CN10 Pin4
|
||||||
|
|
||||||
RX PA0 analog input
|
RX PA0 analog input CN7 Pin28
|
||||||
RSSI PA1 analog input
|
RSSI PA1 analog input CN7 Pin30
|
||||||
TX PA4 analog output
|
TX PA4 analog output CN7 Pin32
|
||||||
|
|
||||||
EXT_CLK PA15 input
|
EXT_CLK PA15 input CN7 Pin17
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PIN_COS GPIO_Pin_15
|
#define PIN_COS GPIO_Pin_15
|
||||||
@@ -212,6 +374,10 @@ EXT_CLK PA15 input
|
|||||||
#define PORT_P25 GPIOB
|
#define PORT_P25 GPIOB
|
||||||
#define RCC_Per_P25 RCC_AHB1Periph_GPIOB
|
#define RCC_Per_P25 RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_NXDN GPIO_Pin_10
|
||||||
|
#define PORT_NXDN GPIOA
|
||||||
|
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
#define PIN_DSTAR GPIO_Pin_10
|
#define PIN_DSTAR GPIO_Pin_10
|
||||||
#define PORT_DSTAR GPIOB
|
#define PORT_DSTAR GPIOB
|
||||||
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
|
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
|
||||||
@@ -229,6 +395,10 @@ EXT_CLK PA15 input
|
|||||||
#define PORT_MP25 GPIOC
|
#define PORT_MP25 GPIOC
|
||||||
#define RCC_Per_MP25 RCC_AHB1Periph_GPIOC
|
#define RCC_Per_MP25 RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_MNXDN GPIO_Pin_6
|
||||||
|
#define PORT_MNXDN GPIOC
|
||||||
|
#define RCC_Per_MNXDN RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
#define PIN_MDSTAR GPIO_Pin_4
|
#define PIN_MDSTAR GPIO_Pin_4
|
||||||
#define PORT_MDSTAR GPIOC
|
#define PORT_MDSTAR GPIOC
|
||||||
#define RCC_Per_MDSTAR RCC_AHB1Periph_GPIOC
|
#define RCC_Per_MDSTAR RCC_AHB1Periph_GPIOC
|
||||||
@@ -263,21 +433,22 @@ EXT_CLK PA15 input
|
|||||||
/*
|
/*
|
||||||
Pin definitions for STM32F4 Nucleo boards (Arduino header):
|
Pin definitions for STM32F4 Nucleo boards (Arduino header):
|
||||||
|
|
||||||
PTT PB10 output
|
PTT PB10 output CN9 Pin7
|
||||||
COSLED PB3 output
|
COSLED PB3 output CN9 Pin4
|
||||||
LED PB5 output
|
LED PB5 output CN9 Pin5
|
||||||
COS PB4 input
|
COS PB4 input CN9 Pin6
|
||||||
|
|
||||||
DSTAR PA1 output
|
DSTAR PA1 output CN8 Pin2
|
||||||
DMR PA4 output
|
DMR PA4 output CN8 Pin3
|
||||||
YSF PB0 output
|
YSF PB0 output CN8 Pin4
|
||||||
P25 PC1 output
|
P25 PC1 output CN8 Pin5
|
||||||
|
NXDN PC0 output CN8 Pin6
|
||||||
|
|
||||||
RX PA0 analog input
|
RX PA0 analog input CN8 Pin1
|
||||||
RSSI PC0 analog input
|
RSSI PC0 analog input CN8 Pin6
|
||||||
TX PA5 analog output
|
TX PA5 analog output CN5 Pin6
|
||||||
|
|
||||||
EXT_CLK PB8 input
|
EXT_CLK PB8 input CN5 Pin10
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PIN_COS GPIO_Pin_4
|
#define PIN_COS GPIO_Pin_4
|
||||||
@@ -300,6 +471,10 @@ EXT_CLK PB8 input
|
|||||||
#define PORT_P25 GPIOC
|
#define PORT_P25 GPIOC
|
||||||
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
|
#define RCC_Per_P25 RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_NXDN GPIO_Pin_0
|
||||||
|
#define PORT_NXDN GPIOC
|
||||||
|
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
#define PIN_DSTAR GPIO_Pin_1
|
#define PIN_DSTAR GPIO_Pin_1
|
||||||
#define PORT_DSTAR GPIOA
|
#define PORT_DSTAR GPIOA
|
||||||
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOA
|
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOA
|
||||||
@@ -333,8 +508,111 @@ EXT_CLK PB8 input
|
|||||||
#error "Either STM32F4_NUCLEO_MORPHO_HEADER or STM32F4_NUCLEO_ARDUINO_HEADER need to be defined in Config.h"
|
#error "Either STM32F4_NUCLEO_MORPHO_HEADER or STM32F4_NUCLEO_ARDUINO_HEADER need to be defined in Config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#elif defined(STM32F7_NUCLEO)
|
||||||
|
/*
|
||||||
|
Pin definitions for STM32F7 Nucleo boards (ST Morpho header):
|
||||||
|
|
||||||
|
PTT PB13 output CN12 Pin30
|
||||||
|
COSLED PB14 output CN12 Pin28
|
||||||
|
LED PA5 output CN12 Pin11
|
||||||
|
COS PB15 input CN12 Pin26
|
||||||
|
|
||||||
|
DSTAR PB10 output CN12 Pin25
|
||||||
|
DMR PB4 output CN12 Pin27
|
||||||
|
YSF PB5 output CN12 Pin29
|
||||||
|
P25 PB3 output CN12 Pin31
|
||||||
|
NXDN PA10 output CN12 Pin33
|
||||||
|
|
||||||
|
MDSTAR PC4 output CN12 Pin34
|
||||||
|
MDMR PC5 output CN12 Pin6
|
||||||
|
MYSF PC2 output CN11 Pin35
|
||||||
|
MP25 PC3 output CN11 Pin37
|
||||||
|
MNXDN PC6 output CN12 Pin4
|
||||||
|
|
||||||
|
RX PA0 analog input CN11 Pin28
|
||||||
|
RSSI PA1 analog input CN11 Pin30
|
||||||
|
TX PA4 analog output CN11 Pin32
|
||||||
|
|
||||||
|
EXT_CLK PA15 input CN11 Pin17
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PIN_COS GPIO_Pin_15
|
||||||
|
#define PORT_COS GPIOB
|
||||||
|
#define RCC_Per_COS RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_PTT GPIO_Pin_13
|
||||||
|
#define PORT_PTT GPIOB
|
||||||
|
#define RCC_Per_PTT RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_COSLED GPIO_Pin_14
|
||||||
|
#define PORT_COSLED GPIOB
|
||||||
|
#define RCC_Per_COSLED RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_LED GPIO_Pin_5
|
||||||
|
#define PORT_LED GPIOA
|
||||||
|
#define RCC_Per_LED RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_P25 GPIO_Pin_3
|
||||||
|
#define PORT_P25 GPIOB
|
||||||
|
#define RCC_Per_P25 RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_NXDN GPIO_Pin_10
|
||||||
|
#define PORT_NXDN GPIOA
|
||||||
|
#define RCC_Per_NXDN RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_DSTAR GPIO_Pin_10
|
||||||
|
#define PORT_DSTAR GPIOB
|
||||||
|
#define RCC_Per_DSTAR RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_DMR GPIO_Pin_4
|
||||||
|
#define PORT_DMR GPIOB
|
||||||
|
#define RCC_Per_DMR RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#define PIN_YSF GPIO_Pin_5
|
||||||
|
#define PORT_YSF GPIOB
|
||||||
|
#define RCC_Per_YSF RCC_AHB1Periph_GPIOB
|
||||||
|
|
||||||
|
#if defined(STM32F4_NUCLEO_MODE_PINS)
|
||||||
|
#define PIN_MP25 GPIO_Pin_3
|
||||||
|
#define PORT_MP25 GPIOC
|
||||||
|
#define RCC_Per_MP25 RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_MNXDN GPIO_Pin_6
|
||||||
|
#define PORT_MNXDN GPIOC
|
||||||
|
#define RCC_Per_MNXDN RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_MDSTAR GPIO_Pin_4
|
||||||
|
#define PORT_MDSTAR GPIOC
|
||||||
|
#define RCC_Per_MDSTAR RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_MDMR GPIO_Pin_5
|
||||||
|
#define PORT_MDMR GPIOC
|
||||||
|
#define RCC_Per_MDMR RCC_AHB1Periph_GPIOC
|
||||||
|
|
||||||
|
#define PIN_MYSF GPIO_Pin_2
|
||||||
|
#define PORT_MYSF GPIOC
|
||||||
|
#define RCC_Per_MYSF RCC_AHB1Periph_GPIOC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PIN_EXT_CLK GPIO_Pin_15
|
||||||
|
#define SRC_EXT_CLK GPIO_PinSource15
|
||||||
|
#define PORT_EXT_CLK GPIOA
|
||||||
|
|
||||||
|
#define PIN_RX GPIO_Pin_0
|
||||||
|
#define PIN_RX_CH ADC_Channel_0
|
||||||
|
#define PORT_RX GPIOA
|
||||||
|
#define RCC_Per_RX RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_RSSI GPIO_Pin_1
|
||||||
|
#define PIN_RSSI_CH ADC_Channel_1
|
||||||
|
#define PORT_RSSI GPIOA
|
||||||
|
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
|
||||||
|
|
||||||
|
#define PIN_TX GPIO_Pin_4
|
||||||
|
#define PIN_TX_CH DAC_Channel_1
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "Either STM32F4_DISCOVERY, STM32F4_PI or STM32F4_NUCLEO need to be defined"
|
#error "Either STM32F4_DISCOVERY, STM32F4_PI, STM32F722_PI, STM32F4_F4M, STM32F4_NUCLEO or STM32F7_NUCLEO need to be defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const uint16_t DC_OFFSET = 2048U;
|
const uint16_t DC_OFFSET = 2048U;
|
||||||
@@ -355,7 +633,7 @@ void CIO::initInt()
|
|||||||
{
|
{
|
||||||
GPIO_InitTypeDef GPIO_InitStruct;
|
GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
GPIO_StructInit(&GPIO_InitStruct);
|
GPIO_StructInit(&GPIO_InitStruct);
|
||||||
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed;
|
||||||
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
|
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
|
||||||
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
|
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
|
||||||
|
|
||||||
@@ -407,6 +685,12 @@ void CIO::initInt()
|
|||||||
GPIO_InitStruct.GPIO_Pin = PIN_P25;
|
GPIO_InitStruct.GPIO_Pin = PIN_P25;
|
||||||
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
GPIO_Init(PORT_P25, &GPIO_InitStruct);
|
GPIO_Init(PORT_P25, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// NXDN pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_NXDN, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_NXDN;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_NXDN, &GPIO_InitStruct);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(STM32F4_NUCLEO_MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && defined(STM32F4_NUCLEO)
|
#if defined(STM32F4_NUCLEO_MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && defined(STM32F4_NUCLEO)
|
||||||
@@ -433,6 +717,12 @@ void CIO::initInt()
|
|||||||
GPIO_InitStruct.GPIO_Pin = PIN_MP25;
|
GPIO_InitStruct.GPIO_Pin = PIN_MP25;
|
||||||
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
GPIO_Init(PORT_MP25, &GPIO_InitStruct);
|
GPIO_Init(PORT_MP25, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// NXDN mode pin
|
||||||
|
RCC_AHB1PeriphClockCmd(RCC_Per_MNXDN, ENABLE);
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_MNXDN;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
|
||||||
|
GPIO_Init(PORT_MNXDN, &GPIO_InitStruct);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,7 +825,7 @@ void CIO::startInt()
|
|||||||
// Init the timer
|
// Init the timer
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
||||||
|
|
||||||
#if defined(EXTERNAL_OSC)
|
#if defined(EXTERNAL_OSC) && !(defined(STM32F4_PI) || defined(STM32F722_PI))
|
||||||
// Configure a GPIO as external TIM2 clock source
|
// Configure a GPIO as external TIM2 clock source
|
||||||
GPIO_PinAFConfig(PORT_EXT_CLK, SRC_EXT_CLK, GPIO_AF_TIM2);
|
GPIO_PinAFConfig(PORT_EXT_CLK, SRC_EXT_CLK, GPIO_AF_TIM2);
|
||||||
GPIO_InitStruct.GPIO_Pin = PIN_EXT_CLK;
|
GPIO_InitStruct.GPIO_Pin = PIN_EXT_CLK;
|
||||||
@@ -547,19 +837,20 @@ void CIO::startInt()
|
|||||||
TIM_TimeBaseStructInit (&timerInitStructure);
|
TIM_TimeBaseStructInit (&timerInitStructure);
|
||||||
|
|
||||||
// TIM2 output frequency
|
// TIM2 output frequency
|
||||||
#if defined(EXTERNAL_OSC)
|
#if defined(EXTERNAL_OSC) && !(defined(STM32F4_PI) || defined(STM32F722_PI))
|
||||||
timerInitStructure.TIM_Prescaler = (uint16_t) ((EXTERNAL_OSC/(2*SAMP_FREQ)) - 1);
|
timerInitStructure.TIM_Prescaler = (uint16_t) ((EXTERNAL_OSC/(2*SAMP_FREQ)) - 1);
|
||||||
|
timerInitStructure.TIM_Period = 1;
|
||||||
#else
|
#else
|
||||||
timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(4*SAMP_FREQ)) - 1);
|
timerInitStructure.TIM_Prescaler = (uint16_t) ((SystemCoreClock/(6*SAMP_FREQ)) - 1);
|
||||||
|
timerInitStructure.TIM_Period = 2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||||
timerInitStructure.TIM_Period = 1;
|
|
||||||
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||||
timerInitStructure.TIM_RepetitionCounter = 0;
|
timerInitStructure.TIM_RepetitionCounter = 0;
|
||||||
TIM_TimeBaseInit(TIM2, &timerInitStructure);
|
TIM_TimeBaseInit(TIM2, &timerInitStructure);
|
||||||
|
|
||||||
#if defined(EXTERNAL_OSC)
|
#if defined(EXTERNAL_OSC) && !(defined(STM32F4_PI) || defined(STM32F722_PI))
|
||||||
// Enable external clock
|
// Enable external clock
|
||||||
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);
|
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);
|
||||||
#else
|
#else
|
||||||
@@ -621,7 +912,7 @@ void CIO::interrupt()
|
|||||||
|
|
||||||
bool CIO::getCOSInt()
|
bool CIO::getCOSInt()
|
||||||
{
|
{
|
||||||
return GPIO_ReadOutputDataBit(PORT_COS, PIN_COS) == Bit_SET;
|
return GPIO_ReadInputDataBit(PORT_COS, PIN_COS) == Bit_SET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIO::setLEDInt(bool on)
|
void CIO::setLEDInt(bool on)
|
||||||
@@ -671,4 +962,38 @@ void CIO::setP25Int(bool on)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIO::setNXDNInt(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_NXDN, PIN_NXDN, on ? Bit_SET : Bit_RESET);
|
||||||
|
#if defined(STM32F4_NUCLEO_MODE_PINS) && defined(STM32F4_NUCLEO_MORPHO_HEADER) && defined(STM32F4_NUCLEO)
|
||||||
|
GPIO_WriteBit(PORT_MNXDN, PIN_MNXDN, on ? Bit_SET : Bit_RESET);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple delay function for STM32
|
||||||
|
// Example from: http://thehackerworkshop.com/?p=1209
|
||||||
|
void CIO::delayInt(unsigned int dly)
|
||||||
|
{
|
||||||
|
#if defined(STM32F7XX)
|
||||||
|
unsigned int loopsPerMillisecond = (SystemCoreClock/1000);
|
||||||
|
#else
|
||||||
|
unsigned int loopsPerMillisecond = (SystemCoreClock/1000) / 3;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (; dly > 0; dly--)
|
||||||
|
{
|
||||||
|
asm volatile //this routine waits (approximately) one millisecond
|
||||||
|
(
|
||||||
|
"mov r3, %[loopsPerMillisecond] \n\t" //load the initial loop counter
|
||||||
|
"loop: \n\t"
|
||||||
|
"subs r3, #1 \n\t"
|
||||||
|
"bne loop \n\t"
|
||||||
|
|
||||||
|
: //empty output list
|
||||||
|
: [loopsPerMillisecond] "r" (loopsPerMillisecond) //input to the asm routine
|
||||||
|
: "r3", "cc" //clobber list
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+76
-9
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
* Copyright (C) 2016, 2017 by Andy Uribe CA6JAU
|
* Copyright (C) 2016, 2017 by Andy Uribe CA6JAU
|
||||||
* Copyright (C) 2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2017,2018 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
|
* Copyright (C) 2017 by Wojciech Krutnik N0CALL
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -39,6 +39,7 @@ DSTAR PB7 output
|
|||||||
DMR PB6 output
|
DMR PB6 output
|
||||||
YSF PB8 output
|
YSF PB8 output
|
||||||
P25 PB9 output
|
P25 PB9 output
|
||||||
|
NXDN PB10 output
|
||||||
|
|
||||||
RX PB0 analog input (ADC1_8)
|
RX PB0 analog input (ADC1_8)
|
||||||
RSSI PB1 analog input (ADC2_9)
|
RSSI PB1 analog input (ADC2_9)
|
||||||
@@ -46,8 +47,8 @@ TX PA4 analog output (DAC_OUT1)
|
|||||||
|
|
||||||
EXT_CLK PA15 input (AF: TIM2_CH1_ETR)
|
EXT_CLK PA15 input (AF: TIM2_CH1_ETR)
|
||||||
|
|
||||||
USART2_TXD PA2 output (AF)
|
USART1_TXD PA9 output (AF)
|
||||||
USART2_RXD PA3 input (AF)
|
USART1_RXD PA10 input (AF)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -76,6 +77,9 @@ USART2_RXD PA3 input (AF)
|
|||||||
#define PIN_P25 9
|
#define PIN_P25 9
|
||||||
#define PORT_P25 GPIOB
|
#define PORT_P25 GPIOB
|
||||||
#define BB_P25 *((bitband_t)BITBAND_PERIPH(&PORT_P25->ODR, PIN_P25))
|
#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_RX 0
|
#define PIN_RX 0
|
||||||
#define PIN_RX_ADC_CH 8
|
#define PIN_RX_ADC_CH 8
|
||||||
@@ -91,10 +95,10 @@ USART2_RXD PA3 input (AF)
|
|||||||
#define SRC_EXT_CLK 15
|
#define SRC_EXT_CLK 15
|
||||||
#define PORT_EXT_CLK GPIOA
|
#define PORT_EXT_CLK GPIOA
|
||||||
|
|
||||||
#define PIN_USART2_TXD 2
|
#define PIN_USART1_TXD 9
|
||||||
#define PORT_USART2_TXD GPIOA
|
#define PORT_USART1_TXD GPIOA
|
||||||
#define PIN_USART2_RXD 3
|
#define PIN_USART1_RXD 10
|
||||||
#define PORT_USART2_RXD GPIOA
|
#define PORT_USART1_RXD GPIOA
|
||||||
|
|
||||||
#else // defined(STM32F1_POG)
|
#else // defined(STM32F1_POG)
|
||||||
#error "Either STM32F1_POG, or sth need to be defined"
|
#error "Either STM32F1_POG, or sth need to be defined"
|
||||||
@@ -143,6 +147,46 @@ void GPIOConfigPin(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value
|
|||||||
*cr_ptr = cr_value; // save localized value to CRL / CRL
|
*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()
|
static inline void GPIOInit()
|
||||||
{
|
{
|
||||||
@@ -174,6 +218,7 @@ static inline void GPIOInit()
|
|||||||
GPIOConfigPin(PORT_DMR, PIN_DMR, GPIO_CRL_MODE0_1);
|
GPIOConfigPin(PORT_DMR, PIN_DMR, GPIO_CRL_MODE0_1);
|
||||||
GPIOConfigPin(PORT_YSF, PIN_YSF, GPIO_CRL_MODE0_1);
|
GPIOConfigPin(PORT_YSF, PIN_YSF, GPIO_CRL_MODE0_1);
|
||||||
GPIOConfigPin(PORT_P25, PIN_P25, GPIO_CRL_MODE0_1);
|
GPIOConfigPin(PORT_P25, PIN_P25, GPIO_CRL_MODE0_1);
|
||||||
|
GPIOConfigPin(PORT_NXDN, PIN_NXDN, GPIO_CRL_MODE0_1);
|
||||||
|
|
||||||
GPIOConfigPin(PORT_RX, PIN_RX, 0);
|
GPIOConfigPin(PORT_RX, PIN_RX, 0);
|
||||||
#if defined(SEND_RSSI_DATA)
|
#if defined(SEND_RSSI_DATA)
|
||||||
@@ -188,8 +233,8 @@ static inline void GPIOInit()
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GPIOConfigPin(PORT_USART2_TXD, PIN_USART2_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
|
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1|GPIO_CRL_CNF0_1);
|
||||||
GPIOConfigPin(PORT_USART2_RXD, PIN_USART2_RXD, GPIO_CRL_CNF0_0);
|
GPIOConfigPin(PORT_USART1_RXD, PIN_USART1_RXD, GPIO_CRL_CNF0_0);
|
||||||
|
|
||||||
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_SWJ_CFG) | AFIO_MAPR_SWJ_CFG_1;
|
AFIO->MAPR = (AFIO->MAPR & ~AFIO_MAPR_SWJ_CFG) | AFIO_MAPR_SWJ_CFG_1;
|
||||||
}
|
}
|
||||||
@@ -250,6 +295,9 @@ static inline void ADCInit()
|
|||||||
|
|
||||||
// Trigger first conversion
|
// Trigger first conversion
|
||||||
ADC1->CR2 |= ADC_CR2_ADON;
|
ADC1->CR2 |= ADC_CR2_ADON;
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
ADC2->CR2 |= ADC_CR2_ADON;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -295,6 +343,9 @@ void CIO::initInt()
|
|||||||
GPIOInit();
|
GPIOInit();
|
||||||
ADCInit();
|
ADCInit();
|
||||||
DACInit();
|
DACInit();
|
||||||
|
#if defined(STM32F1_POG)
|
||||||
|
FancyLEDEffect();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIO::startInt()
|
void CIO::startInt()
|
||||||
@@ -312,10 +363,16 @@ void CIO::interrupt()
|
|||||||
uint16_t rawRSSI = 0U;
|
uint16_t rawRSSI = 0U;
|
||||||
bitband_t eoc = (bitband_t)BITBAND_PERIPH(&ADC1->SR, ADC_SR_EOS_Pos);
|
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);
|
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) {
|
if (*eoc) {
|
||||||
// trigger next conversion
|
// trigger next conversion
|
||||||
*adon = 1;
|
*adon = 1;
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
*rssi_adon = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
m_txBuffer.get(sample, control);
|
m_txBuffer.get(sample, control);
|
||||||
DAC->DHR12R1 = sample; // Send the value to the DAC
|
DAC->DHR12R1 = sample; // Send the value to the DAC
|
||||||
@@ -372,4 +429,14 @@ void CIO::setP25Int(bool on)
|
|||||||
BB_P25 = !!on;
|
BB_P25 = !!on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIO::setNXDNInt(bool on)
|
||||||
|
{
|
||||||
|
BB_NXDN = !!on;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::delayInt(unsigned int dly)
|
||||||
|
{
|
||||||
|
delay(dly);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+13
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
#define PIN_DMR 10
|
#define PIN_DMR 10
|
||||||
#define PIN_YSF 11
|
#define PIN_YSF 11
|
||||||
#define PIN_P25 12
|
#define PIN_P25 12
|
||||||
|
#define PIN_NXDN 8
|
||||||
#define PIN_ADC 5 // A0, Pin 14
|
#define PIN_ADC 5 // A0, Pin 14
|
||||||
#define PIN_RSSI 4 // Teensy 3.5/3.6, A16, Pin 35. Teensy 3.1/3.2, A17, Pin 28
|
#define PIN_RSSI 4 // Teensy 3.5/3.6, A16, Pin 35. Teensy 3.1/3.2, A17, Pin 28
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ void CIO::initInt()
|
|||||||
pinMode(PIN_DMR, OUTPUT);
|
pinMode(PIN_DMR, OUTPUT);
|
||||||
pinMode(PIN_YSF, OUTPUT);
|
pinMode(PIN_YSF, OUTPUT);
|
||||||
pinMode(PIN_P25, OUTPUT);
|
pinMode(PIN_P25, OUTPUT);
|
||||||
|
pinMode(PIN_NXDN, OUTPUT);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,4 +212,14 @@ void CIO::setP25Int(bool on)
|
|||||||
digitalWrite(PIN_P25, on ? HIGH : LOW);
|
digitalWrite(PIN_P25, on ? HIGH : LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIO::setNXDNInt(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_NXDN, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::delayInt(unsigned int dly)
|
||||||
|
{
|
||||||
|
delay(dly);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
|
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(STM32F4XX) || defined(STM32F4) || defined(STM32F105xC)
|
#if defined(STM32F4XX) || defined(STM32F7XX) || defined(STM32F105xC)
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
@@ -30,6 +30,7 @@ bool m_dstarEnable = true;
|
|||||||
bool m_dmrEnable = true;
|
bool m_dmrEnable = true;
|
||||||
bool m_ysfEnable = true;
|
bool m_ysfEnable = true;
|
||||||
bool m_p25Enable = true;
|
bool m_p25Enable = true;
|
||||||
|
bool m_nxdnEnable = true;
|
||||||
|
|
||||||
bool m_duplex = true;
|
bool m_duplex = true;
|
||||||
|
|
||||||
@@ -52,9 +53,14 @@ CYSFTX ysfTX;
|
|||||||
CP25RX p25RX;
|
CP25RX p25RX;
|
||||||
CP25TX p25TX;
|
CP25TX p25TX;
|
||||||
|
|
||||||
|
CNXDNRX nxdnRX;
|
||||||
|
CNXDNTX nxdnTX;
|
||||||
|
|
||||||
CCalDStarRX calDStarRX;
|
CCalDStarRX calDStarRX;
|
||||||
CCalDStarTX calDStarTX;
|
CCalDStarTX calDStarTX;
|
||||||
CCalDMR calDMR;
|
CCalDMR calDMR;
|
||||||
|
CCalP25 calP25;
|
||||||
|
CCalNXDN calNXDN;
|
||||||
CCalRSSI calRSSI;
|
CCalRSSI calRSSI;
|
||||||
|
|
||||||
CCWIdTX cwIdTX;
|
CCWIdTX cwIdTX;
|
||||||
@@ -90,12 +96,21 @@ void loop()
|
|||||||
if (m_p25Enable && m_modemState == STATE_P25)
|
if (m_p25Enable && m_modemState == STATE_P25)
|
||||||
p25TX.process();
|
p25TX.process();
|
||||||
|
|
||||||
|
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||||
|
nxdnTX.process();
|
||||||
|
|
||||||
if (m_modemState == STATE_DSTARCAL)
|
if (m_modemState == STATE_DSTARCAL)
|
||||||
calDStarTX.process();
|
calDStarTX.process();
|
||||||
|
|
||||||
if (m_modemState == STATE_DMRCAL)
|
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
||||||
calDMR.process();
|
calDMR.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_P25CAL1K)
|
||||||
|
calP25.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_NXDNCAL1K)
|
||||||
|
calNXDN.process();
|
||||||
|
|
||||||
if (m_modemState == STATE_IDLE)
|
if (m_modemState == STATE_IDLE)
|
||||||
cwIdTX.process();
|
cwIdTX.process();
|
||||||
}
|
}
|
||||||
@@ -109,4 +124,3 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -27,6 +27,7 @@ bool m_dstarEnable = true;
|
|||||||
bool m_dmrEnable = true;
|
bool m_dmrEnable = true;
|
||||||
bool m_ysfEnable = true;
|
bool m_ysfEnable = true;
|
||||||
bool m_p25Enable = true;
|
bool m_p25Enable = true;
|
||||||
|
bool m_nxdnEnable = true;
|
||||||
|
|
||||||
bool m_duplex = true;
|
bool m_duplex = true;
|
||||||
|
|
||||||
@@ -49,9 +50,14 @@ CYSFTX ysfTX;
|
|||||||
CP25RX p25RX;
|
CP25RX p25RX;
|
||||||
CP25TX p25TX;
|
CP25TX p25TX;
|
||||||
|
|
||||||
|
CNXDNRX nxdnRX;
|
||||||
|
CNXDNTX nxdnTX;
|
||||||
|
|
||||||
CCalDStarRX calDStarRX;
|
CCalDStarRX calDStarRX;
|
||||||
CCalDStarTX calDStarTX;
|
CCalDStarTX calDStarTX;
|
||||||
CCalDMR calDMR;
|
CCalDMR calDMR;
|
||||||
|
CCalP25 calP25;
|
||||||
|
CCalNXDN calNXDN;
|
||||||
CCalRSSI calRSSI;
|
CCalRSSI calRSSI;
|
||||||
|
|
||||||
CCWIdTX cwIdTX;
|
CCWIdTX cwIdTX;
|
||||||
@@ -87,12 +93,21 @@ void loop()
|
|||||||
if (m_p25Enable && m_modemState == STATE_P25)
|
if (m_p25Enable && m_modemState == STATE_P25)
|
||||||
p25TX.process();
|
p25TX.process();
|
||||||
|
|
||||||
|
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||||
|
nxdnTX.process();
|
||||||
|
|
||||||
if (m_modemState == STATE_DSTARCAL)
|
if (m_modemState == STATE_DSTARCAL)
|
||||||
calDStarTX.process();
|
calDStarTX.process();
|
||||||
|
|
||||||
if (m_modemState == STATE_DMRCAL)
|
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
||||||
calDMR.process();
|
calDMR.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_P25CAL1K)
|
||||||
|
calP25.process();
|
||||||
|
|
||||||
|
if (m_modemState == STATE_NXDNCAL1K)
|
||||||
|
calNXDN.process();
|
||||||
|
|
||||||
if (m_modemState == STATE_IDLE)
|
if (m_modemState == STATE_IDLE)
|
||||||
cwIdTX.process();
|
cwIdTX.process();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,8 +98,6 @@
|
|||||||
<Define name="HSE_VALUE=12000000"/>
|
<Define name="HSE_VALUE=12000000"/>
|
||||||
<Define name="STM32F4_PI"/>
|
<Define name="STM32F4_PI"/>
|
||||||
<Define name="ARDUINO_MODE_PINS"/>
|
<Define name="ARDUINO_MODE_PINS"/>
|
||||||
<Define name="SEND_RSSI_DATA"/>
|
|
||||||
<Define name="SERIAL_REPEATER"/>
|
|
||||||
</DefinedSymbols>
|
</DefinedSymbols>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Link useDefault="0">
|
<Link useDefault="0">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2016 by Andy Uribe CA6JAU
|
# Copyright (C) 2016,2017 by Andy Uribe CA6JAU
|
||||||
# Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
# Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
@@ -15,6 +15,54 @@
|
|||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
# MMDVM source files
|
||||||
|
MMDVM_PATH=.
|
||||||
|
|
||||||
|
# STM32 library paths
|
||||||
|
F4_LIB_PATH=./STM32F4XX_Lib
|
||||||
|
F7_LIB_PATH=./STM32F7XX_Lib
|
||||||
|
|
||||||
|
# MCU external clock frequency (Hz)
|
||||||
|
CLK_MMDVM_PI=12000000
|
||||||
|
CLK_NUCLEO=8000000
|
||||||
|
|
||||||
|
# Directory Structure
|
||||||
|
BINDIR=bin
|
||||||
|
OBJDIR_F4=obj_f4
|
||||||
|
OBJDIR_F7=obj_f7
|
||||||
|
|
||||||
|
# Output files
|
||||||
|
BINELF_F4=mmdvm_f4.elf
|
||||||
|
BINHEX_F4=mmdvm_f4.hex
|
||||||
|
BINBIN_F4=mmdvm_f4.bin
|
||||||
|
BINELF_F7=mmdvm_f7.elf
|
||||||
|
BINHEX_F7=mmdvm_f7.hex
|
||||||
|
BINBIN_F7=mmdvm_f7.bin
|
||||||
|
|
||||||
|
# Header directories
|
||||||
|
INC_F4= . $(F4_LIB_PATH)/CMSIS/Include/ $(F4_LIB_PATH)/Device/ $(F4_LIB_PATH)/STM32F4xx_StdPeriph_Driver/include/
|
||||||
|
INCLUDES_F4=$(INC_F4:%=-I%)
|
||||||
|
INC_F7= . $(F7_LIB_PATH)/CMSIS/Include/ $(F7_LIB_PATH)/Device/ $(F7_LIB_PATH)/STM32F7xx_StdPeriph_Driver/inc/
|
||||||
|
INCLUDES_F7=$(INC_F7:%=-I%)
|
||||||
|
|
||||||
|
# CMSIS libraries
|
||||||
|
INCLUDES_LIBS_F4=$(F4_LIB_PATH)/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a
|
||||||
|
INCLUDES_LIBS_F7=$(F7_LIB_PATH)/CMSIS/Lib/GCC/libarm_cortexM7lfsp_math.a
|
||||||
|
|
||||||
|
# STM32F4 Standard Peripheral Libraries source path
|
||||||
|
STD_LIB_F4=$(F4_LIB_PATH)/STM32F4xx_StdPeriph_Driver/source
|
||||||
|
|
||||||
|
# STM32F7 Standard Peripheral Libraries source path
|
||||||
|
STD_LIB_F7=$(F7_LIB_PATH)/STM32F7xx_StdPeriph_Driver/src
|
||||||
|
|
||||||
|
# STM32F4 system source path
|
||||||
|
SYS_DIR_F4=$(F4_LIB_PATH)/Device
|
||||||
|
STARTUP_DIR_F4=$(F4_LIB_PATH)/Device/startup
|
||||||
|
|
||||||
|
# STM32F7 system source path
|
||||||
|
SYS_DIR_F7=$(F7_LIB_PATH)/Device
|
||||||
|
STARTUP_DIR_F7=$(F7_LIB_PATH)/Device/startup
|
||||||
|
|
||||||
# GNU ARM Embedded Toolchain
|
# GNU ARM Embedded Toolchain
|
||||||
CC=arm-none-eabi-gcc
|
CC=arm-none-eabi-gcc
|
||||||
CXX=arm-none-eabi-g++
|
CXX=arm-none-eabi-g++
|
||||||
@@ -27,163 +75,248 @@ NM=arm-none-eabi-nm
|
|||||||
SIZE=arm-none-eabi-size
|
SIZE=arm-none-eabi-size
|
||||||
A2L=arm-none-eabi-addr2line
|
A2L=arm-none-eabi-addr2line
|
||||||
|
|
||||||
# Directory Structure
|
|
||||||
BINDIR=bin
|
|
||||||
|
|
||||||
# Find source files
|
|
||||||
# "SystemRoot" is only defined in Windows
|
# "SystemRoot" is only defined in Windows
|
||||||
ifdef SYSTEMROOT
|
ifdef SYSTEMROOT
|
||||||
ASOURCES=$(shell dir /S /B *.s)
|
|
||||||
CSOURCES=$(shell dir /S /B *.c)
|
|
||||||
CXXSOURCES=$(shell dir /S /B *.cpp)
|
|
||||||
CLEANCMD=del /S *.o *.hex *.bin *.elf GitVersion.h
|
CLEANCMD=del /S *.o *.hex *.bin *.elf GitVersion.h
|
||||||
MDBIN=md $@
|
MDDIRS=md $@
|
||||||
else ifdef SystemRoot
|
else ifdef SystemRoot
|
||||||
ASOURCES=$(shell dir /S /B *.s)
|
|
||||||
CSOURCES=$(shell dir /S /B *.c)
|
|
||||||
CXXSOURCES=$(shell dir /S /B *.cpp)
|
|
||||||
CLEANCMD=del /S *.o *.hex *.bin *.elf GitVersion.h
|
CLEANCMD=del /S *.o *.hex *.bin *.elf GitVersion.h
|
||||||
MDBIN=md $@
|
MDDIRS=md $@
|
||||||
else
|
else
|
||||||
ASOURCES=$(shell find . -name '*.s')
|
CLEANCMD=rm -f $(OBJ_F4) $(OBJ_F7) $(BINDIR)/*.hex $(BINDIR)/*.bin $(BINDIR)/*.elf GitVersion.h
|
||||||
CSOURCES=$(shell find . -name '*.c')
|
MDDIRS=mkdir $@
|
||||||
CXXSOURCES=$(shell find . -name '*.cpp')
|
|
||||||
CLEANCMD=rm -f $(OBJECTS) $(BINDIR)/$(BINELF) $(BINDIR)/$(BINHEX) $(BINDIR)/$(BINBIN) GitVersion.h
|
|
||||||
MDBIN=mkdir $@
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Default reference oscillator frequencies
|
# Default reference oscillator frequencies
|
||||||
ifndef $(OSC)
|
ifndef $(OSC)
|
||||||
ifeq ($(MAKECMDGOALS),pi)
|
ifeq ($(MAKECMDGOALS),pi)
|
||||||
OSC=12000000
|
OSC=$(CLK_MMDVM_PI)
|
||||||
|
else ifeq ($(MAKECMDGOALS),pi-f722)
|
||||||
|
OSC=$(CLK_MMDVM_PI)
|
||||||
else
|
else
|
||||||
OSC=8000000
|
OSC=$(CLK_NUCLEO)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Find header directories
|
# Build object lists
|
||||||
INC= . STM32F4XX_Lib/CMSIS/Include/ STM32F4XX_Lib/Device/ STM32F4XX_Lib/STM32F4xx_StdPeriph_Driver/include/
|
CXXSRC=$(wildcard $(MMDVM_PATH)/*.cpp)
|
||||||
INCLUDES=$(INC:%=-I%)
|
CSRC_STD_F4=$(wildcard $(STD_LIB_F4)/*.c)
|
||||||
|
SYS_F4=$(wildcard $(SYS_DIR_F4)/*.c)
|
||||||
|
STARTUP_F4=$(wildcard $(STARTUP_DIR_F4)/*.c)
|
||||||
|
CSRC_STD_F7=$(wildcard $(STD_LIB_F7)/*.c)
|
||||||
|
SYS_F7=$(wildcard $(SYS_DIR_F7)/*.c)
|
||||||
|
STARTUP_F7=$(wildcard $(STARTUP_DIR_F7)/*.c)
|
||||||
|
OBJ_F4=$(CXXSRC:$(MMDVM_PATH)/%.cpp=$(OBJDIR_F4)/%.o) $(CSRC_STD_F4:$(STD_LIB_F4)/%.c=$(OBJDIR_F4)/%.o) $(SYS_F4:$(SYS_DIR_F4)/%.c=$(OBJDIR_F4)/%.o) $(STARTUP_F4:$(STARTUP_DIR_F4)/%.c=$(OBJDIR_F4)/%.o)
|
||||||
|
OBJ_F7=$(CXXSRC:$(MMDVM_PATH)/%.cpp=$(OBJDIR_F7)/%.o) $(CSRC_STD_F7:$(STD_LIB_F7)/%.c=$(OBJDIR_F7)/%.o) $(SYS_F7:$(SYS_DIR_F7)/%.c=$(OBJDIR_F7)/%.o) $(STARTUP_F7:$(STARTUP_DIR_F7)/%.c=$(OBJDIR_F7)/%.o)
|
||||||
|
|
||||||
# Find libraries
|
# MCU flags
|
||||||
INCLUDES_LIBS=STM32F4XX_Lib/CMSIS/Lib/GCC/libarm_cortexM4lf_math.a
|
MCFLAGS_F4=-mcpu=cortex-m4 -mthumb -mlittle-endian -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb-interwork
|
||||||
LINK_LIBS=
|
MCFLAGS_F7=-mcpu=cortex-m7 -mthumb -mlittle-endian -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb-interwork
|
||||||
|
|
||||||
# Create object list
|
# Compile flags
|
||||||
OBJECTS=$(ASOURCES:%.s=%.o)
|
|
||||||
OBJECTS+=$(CSOURCES:%.c=%.o)
|
|
||||||
OBJECTS+=$(CXXSOURCES:%.cpp=%.o)
|
|
||||||
|
|
||||||
# Define output files ELF & IHEX
|
|
||||||
BINELF=outp.elf
|
|
||||||
BINHEX=outp.hex
|
|
||||||
BINBIN=outp.bin
|
|
||||||
|
|
||||||
# MCU FLAGS
|
|
||||||
MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \
|
|
||||||
-mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb-interwork
|
|
||||||
|
|
||||||
# COMPILE FLAGS
|
|
||||||
# STM32F4 Discovery board:
|
# STM32F4 Discovery board:
|
||||||
DEFS_DIS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_DISCOVERY -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
DEFS_DIS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F40_41xxx -DSTM32F4_DISCOVERY -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
# Pi board:
|
# MMDVM-Pi board:
|
||||||
DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DARDUINO_MODE_PINS -DSEND_RSSI_DATA -DSERIAL_REPEATER -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
DEFS_PI=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_PI -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
# STM32F4 Nucleo 446 board:
|
# MMDVM-F4M F0DEI board:
|
||||||
|
DEFS_F4M=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_F4M -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# STM32F4 Nucleo-64 F446RE board:
|
||||||
DEFS_NUCLEO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_NUCLEO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
DEFS_NUCLEO=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX -DSTM32F446xx -DSTM32F4_NUCLEO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# STM32F7 Nucleo-144 F767ZI board:
|
||||||
|
DEFS_NUCLEO_F767=-DUSE_HAL_DRIVER -DSTM32F767xx -DSTM32F7XX -DSTM32F7_NUCLEO -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
# MMDVM-Pi F722 board:
|
||||||
|
DEFS_PI_F722=-DUSE_HAL_DRIVER -DSTM32F722xx -DSTM32F7XX -DSTM32F722_PI -DHSE_VALUE=$(OSC) -DMADEBYMAKEFILE
|
||||||
|
|
||||||
CFLAGS=-c $(MCFLAGS) $(INCLUDES)
|
# Build compiler flags
|
||||||
CXXFLAGS=-c $(MCFLAGS) $(INCLUDES)
|
CFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
|
||||||
|
CXXFLAGS_F4=-c $(MCFLAGS_F4) $(INCLUDES_F4)
|
||||||
|
CFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7)
|
||||||
|
CXXFLAGS_F7=-c $(MCFLAGS_F7) $(INCLUDES_F7)
|
||||||
|
|
||||||
# LINKER FLAGS
|
# Linker flags
|
||||||
LDSCRIPT=stm32f4xx_link.ld
|
LDFLAGS_F4 =-T stm32f4xx_link.ld $(MCFLAGS_F4) --specs=nosys.specs $(INCLUDES_LIBS_F4)
|
||||||
LDFLAGS =-T $(LDSCRIPT) $(MCFLAGS) --specs=nosys.specs $(INCLUDES_LIBS) $(LINK_LIBS)
|
LDFLAGS_F767 =-T stm32f767_link.ld $(MCFLAGS_F7) --specs=nosys.specs $(INCLUDES_LIBS_F7)
|
||||||
|
LDFLAGS_F722 =-T stm32f722_link.ld $(MCFLAGS_F7) --specs=nosys.specs $(INCLUDES_LIBS_F7)
|
||||||
|
|
||||||
|
# Common flags
|
||||||
|
CFLAGS=-Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
|
||||||
|
CXXFLAGS=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
|
||||||
|
LDFLAGS=-Os --specs=nano.specs
|
||||||
|
|
||||||
# Build Rules
|
# Build Rules
|
||||||
.PHONY: all release dis pi nucleo debug clean
|
.PHONY: all release dis pi pi_f722 f4m nucleo f767 clean
|
||||||
|
|
||||||
# Default target: STM32F4 Nucleo F446RE board
|
# Default target: Nucleo-64 F446RE board
|
||||||
all: nucleo
|
all: nucleo
|
||||||
|
|
||||||
pi: GitVersion.h
|
pi: GitVersion.h
|
||||||
pi: CFLAGS+=$(DEFS_PI) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
|
pi: CFLAGS+=$(CFLAGS_F4) $(DEFS_PI)
|
||||||
pi: CXXFLAGS+=$(DEFS_PI) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
|
pi: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_PI)
|
||||||
pi: LDFLAGS+=-Os --specs=nano.specs
|
pi: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
pi: release
|
pi: release_f4
|
||||||
|
|
||||||
|
pi-f722: GitVersion.h
|
||||||
|
pi-f722: CFLAGS+=$(CFLAGS_F7) $(DEFS_PI_F722)
|
||||||
|
pi-f722: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_PI_F722)
|
||||||
|
pi-f722: LDFLAGS+=$(LDFLAGS_F722)
|
||||||
|
pi-f722: release_f7
|
||||||
|
|
||||||
|
f4m: GitVersion.h
|
||||||
|
f4m: CFLAGS+=$(CFLAGS_F4) $(DEFS_F4M)
|
||||||
|
f4m: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_F4M)
|
||||||
|
f4m: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
|
f4m: release_f4
|
||||||
|
|
||||||
nucleo: GitVersion.h
|
nucleo: GitVersion.h
|
||||||
nucleo: CFLAGS+=$(DEFS_NUCLEO) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
|
nucleo: CFLAGS+=$(CFLAGS_F4) $(DEFS_NUCLEO)
|
||||||
nucleo: CXXFLAGS+=$(DEFS_NUCLEO) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
|
nucleo: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_NUCLEO)
|
||||||
nucleo: LDFLAGS+=-Os --specs=nano.specs
|
nucleo: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
nucleo: release
|
nucleo: release_f4
|
||||||
|
|
||||||
dis: GitVersion.h
|
dis: GitVersion.h
|
||||||
dis: CFLAGS+=$(DEFS_DIS) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
|
dis: CFLAGS+=$(CFLAGS_F4) $(DEFS_DIS)
|
||||||
dis: CXXFLAGS+=$(DEFS_DIS) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
|
dis: CXXFLAGS+=$(CXXFLAGS_F4) $(DEFS_DIS)
|
||||||
dis: LDFLAGS+=-Os --specs=nano.specs
|
dis: LDFLAGS+=$(LDFLAGS_F4)
|
||||||
dis: release
|
dis: release_f4
|
||||||
|
|
||||||
debug: CFLAGS+=-g
|
f767: GitVersion.h
|
||||||
debug: CXXFLAGS+=-g
|
f767: CFLAGS+=$(CFLAGS_F7) $(DEFS_NUCLEO_F767)
|
||||||
debug: LDFLAGS+=-g
|
f767: CXXFLAGS+=$(CXXFLAGS_F7) $(DEFS_NUCLEO_F767)
|
||||||
debug: release
|
f767: LDFLAGS+=$(LDFLAGS_F767)
|
||||||
|
f767: release_f7
|
||||||
|
|
||||||
release: $(BINDIR)
|
release_f4: $(BINDIR)
|
||||||
release: $(BINDIR)/$(BINHEX)
|
release_f4: $(OBJDIR_F4)
|
||||||
release: $(BINDIR)/$(BINBIN)
|
release_f4: $(BINDIR)/$(BINHEX_F4)
|
||||||
|
release_f4: $(BINDIR)/$(BINBIN_F4)
|
||||||
|
|
||||||
|
release_f7: $(BINDIR)
|
||||||
|
release_f7: $(OBJDIR_F7)
|
||||||
|
release_f7: $(BINDIR)/$(BINHEX_F7)
|
||||||
|
release_f7: $(BINDIR)/$(BINBIN_F7)
|
||||||
|
|
||||||
$(BINDIR):
|
$(BINDIR):
|
||||||
$(MDBIN)
|
$(MDDIRS)
|
||||||
|
|
||||||
$(BINDIR)/$(BINHEX): $(BINDIR)/$(BINELF)
|
$(OBJDIR_F4):
|
||||||
|
$(MDDIRS)
|
||||||
|
|
||||||
|
$(OBJDIR_F7):
|
||||||
|
$(MDDIRS)
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINHEX_F4): $(BINDIR)/$(BINELF_F4)
|
||||||
$(CP) -O ihex $< $@
|
$(CP) -O ihex $< $@
|
||||||
@echo "Objcopy from ELF to IHEX complete!\n"
|
@echo "Objcopy from ELF to IHEX complete!\n"
|
||||||
|
|
||||||
$(BINDIR)/$(BINBIN): $(BINDIR)/$(BINELF)
|
$(BINDIR)/$(BINBIN_F4): $(BINDIR)/$(BINELF_F4)
|
||||||
$(CP) -O binary $< $@
|
$(CP) -O binary $< $@
|
||||||
@echo "Objcopy from ELF to BINARY complete!\n"
|
@echo "Objcopy from ELF to BINARY complete!\n"
|
||||||
|
|
||||||
$(BINDIR)/$(BINELF): $(OBJECTS)
|
$(BINDIR)/$(BINELF_F4): $(OBJ_F4)
|
||||||
$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
|
$(CXX) $(OBJ_F4) $(LDFLAGS) -o $@
|
||||||
@echo "Linking complete!\n"
|
@echo "Linking complete!\n"
|
||||||
$(SIZE) $(BINDIR)/$(BINELF)
|
$(SIZE) $(BINDIR)/$(BINELF_F4)
|
||||||
|
|
||||||
%.o: %.cpp
|
$(BINDIR)/$(BINHEX_F7): $(BINDIR)/$(BINELF_F7)
|
||||||
|
$(CP) -O ihex $< $@
|
||||||
|
@echo "Objcopy from ELF to IHEX complete!\n"
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINBIN_F7): $(BINDIR)/$(BINELF_F7)
|
||||||
|
$(CP) -O binary $< $@
|
||||||
|
@echo "Objcopy from ELF to BINARY complete!\n"
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINELF_F7): $(OBJ_F7)
|
||||||
|
$(CXX) $(OBJ_F7) $(LDFLAGS) -o $@
|
||||||
|
@echo "Linking complete!\n"
|
||||||
|
$(SIZE) $(BINDIR)/$(BINELF_F7)
|
||||||
|
|
||||||
|
$(OBJDIR_F4)/%.o: $(MMDVM_PATH)/%.cpp
|
||||||
$(CXX) $(CXXFLAGS) $< -o $@
|
$(CXX) $(CXXFLAGS) $< -o $@
|
||||||
@echo "Compiled "$<"!\n"
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
%.o: %.c
|
$(OBJDIR_F7)/%.o: $(MMDVM_PATH)/%.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F4)/%.o: $(STD_LIB_F4)/%.c
|
||||||
$(CC) $(CFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
@echo "Compiled "$<"!\n"
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
%.o: %.s
|
$(OBJDIR_F7)/%.o: $(STD_LIB_F7)/%.c
|
||||||
$(CC) $(CFLAGS) $< -o $@
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
@echo "Assambled "$<"!\n"
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F4)/%.o: $(SYS_DIR_F4)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F4)/%.o: $(STARTUP_DIR_F4)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F7)/%.o: $(SYS_DIR_F7)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
$(OBJDIR_F7)/%.o: $(STARTUP_DIR_F7)/%.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(CLEANCMD)
|
$(CLEANCMD)
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
ifneq ($(wildcard /usr/bin/openocd),)
|
ifneq ($(wildcard /usr/bin/openocd),)
|
||||||
/usr/bin/openocd -f /usr/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/$(BINELF) verify reset exit"
|
/usr/bin/openocd -f /usr/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/share/openocd/scripts/target/stm32f4x.cfg -c "program bin/$(BINELF_F4) verify reset exit"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(wildcard /usr/local/bin/openocd),)
|
ifneq ($(wildcard /usr/local/bin/openocd),)
|
||||||
/usr/local/bin/openocd -f /usr/local/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/$(BINELF) verify reset exit"
|
/usr/local/bin/openocd -f /usr/local/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/local/share/openocd/scripts/target/stm32f4x.cfg -c "program bin/$(BINELF_F4) verify reset exit"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(wildcard /opt/openocd/bin/openocd),)
|
ifneq ($(wildcard /opt/openocd/bin/openocd),)
|
||||||
/opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/board/stm32f4discovery.cfg -c "program bin/$(BINELF) verify reset exit"
|
/opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/interface/stlink-v2-1.cfg -f /opt/openocd/share/openocd/scripts/target/stm32f4x.cfg -c "program bin/$(BINELF_F4) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
deploy-f7:
|
||||||
|
ifneq ($(wildcard /usr/bin/openocd),)
|
||||||
|
/usr/bin/openocd -f /usr/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/share/openocd/scripts/target/stm32f7x.cfg -c "program bin/$(BINELF_F7) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /usr/local/bin/openocd),)
|
||||||
|
/usr/local/bin/openocd -f /usr/local/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/local/share/openocd/scripts/target/stm32f7x.cfg -c "program bin/$(BINELF_F7) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /opt/openocd/bin/openocd),)
|
||||||
|
/opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/interface/stlink-v2-1.cfg -f /opt/openocd/share/openocd/scripts/target/stm32f7x.cfg -c "program bin/$(BINELF_F7) verify reset exit"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
deploy-pi:
|
deploy-pi:
|
||||||
ifneq ($(wildcard /usr/local/bin/stm32flash),)
|
ifneq ($(wildcard /usr/local/bin/stm32flash),)
|
||||||
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
-/usr/local/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
||||||
/usr/local/bin/stm32flash -v -w bin/outp.bin -g 0x0 -R -c /dev/ttyAMA0
|
-/usr/local/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F4)
|
||||||
|
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R -c /dev/ttyAMA0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(wildcard /usr/bin/stm32flash),)
|
ifneq ($(wildcard /usr/bin/stm32flash),)
|
||||||
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
||||||
/usr/bin/stm32flash -v -w bin/outp.bin -g 0x0 -R -c /dev/ttyAMA0
|
-/usr/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F4)
|
||||||
|
/usr/bin/stm32flash -v -w bin/$(BINBIN_F4) -g 0x0 -R -c /dev/ttyAMA0
|
||||||
|
endif
|
||||||
|
|
||||||
|
deploy-f4m: deploy-pi
|
||||||
|
|
||||||
|
deploy-pi-f7:
|
||||||
|
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_F7)
|
||||||
|
/usr/local/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /usr/bin/stm32flash),)
|
||||||
|
-/usr/bin/stm32flash -i 20,-21,21:-20,21 /dev/ttyAMA0
|
||||||
|
-/usr/bin/stm32ld /dev/ttyAMA0 57600 bin/$(BINBIN_F7)
|
||||||
|
/usr/bin/stm32flash -v -w bin/$(BINBIN_F7) -g 0x0 -R -c /dev/ttyAMA0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Export the current git version if the index file exists, else 000...
|
# Export the current git version if the index file exists, else 000...
|
||||||
|
|||||||
+2
-3
@@ -93,8 +93,7 @@ default:
|
|||||||
|
|
||||||
#This rule is good to just make sure stuff compiles, without having to wait
|
#This rule is good to just make sure stuff compiles, without having to wait
|
||||||
#for bossac.
|
#for bossac.
|
||||||
compile: GitVersion.h
|
compile: GitVersion.h $(TMPDIR)/$(PROJNAME).elf $(TMPDIR)/$(PROJNAME).bin
|
||||||
compile: $(TMPDIR)/$(PROJNAME).elf
|
|
||||||
|
|
||||||
#This is a make rule template to create object files from the source files.
|
#This is a make rule template to create object files from the source files.
|
||||||
# arg 1=src file
|
# arg 1=src file
|
||||||
@@ -175,7 +174,7 @@ $(TMPDIR)/$(PROJNAME).bin: $(TMPDIR)/$(PROJNAME).elf
|
|||||||
$(OBJCOPY) -O binary $< $@
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
#upload to the arduino by first resetting it (stty) and the running bossac
|
#upload to the arduino by first resetting it (stty) and the running bossac
|
||||||
upload: $(TMPDIR)/$(PROJNAME).bin
|
upload: compile
|
||||||
stty -F /dev/$(PORT) cs8 1200 hupcl
|
stty -F /dev/$(PORT) cs8 1200 hupcl
|
||||||
$(ADIR)/packages/arduino/tools/bossac/1.6.1-arduino/bossac -i --port=$(PORT) -U false -e -w $(VERIFY) -b $(TMPDIR)/$(PROJNAME).bin -R
|
$(ADIR)/packages/arduino/tools/bossac/1.6.1-arduino/bossac -i --port=$(PORT) -U false -e -w $(VERIFY) -b $(TMPDIR)/$(PROJNAME).bin -R
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -39,7 +39,7 @@ OBJDIR:=obj
|
|||||||
BINDIR:=bin
|
BINDIR:=bin
|
||||||
|
|
||||||
# Port definition for programming via bootloader (using stm32flash)
|
# Port definition for programming via bootloader (using stm32flash)
|
||||||
BL_PORT:=/dev/ttyUSB0
|
BL_PORT:=ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ program: $(HEX) $(ELF)
|
|||||||
|
|
||||||
.PHONY: program_bl
|
.PHONY: program_bl
|
||||||
program_bl: $(HEX) $(ELF)
|
program_bl: $(HEX) $(ELF)
|
||||||
stm32flash -w $(HEX) -v $(BL_PORT)
|
stm32flash -w $(HEX) -v /dev/$(BL_PORT)
|
||||||
$(SIZE) $(ELF)
|
$(SIZE) $(ELF)
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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(NXDNDEFINES_H)
|
||||||
|
#define NXDNDEFINES_H
|
||||||
|
|
||||||
|
const unsigned int NXDN_RADIO_SYMBOL_LENGTH = 10U; // At 24 kHz sample rate
|
||||||
|
|
||||||
|
const unsigned int NXDN_FRAME_LENGTH_BITS = 384U;
|
||||||
|
const unsigned int NXDN_FRAME_LENGTH_BYTES = NXDN_FRAME_LENGTH_BITS / 8U;
|
||||||
|
const unsigned int NXDN_FRAME_LENGTH_SYMBOLS = NXDN_FRAME_LENGTH_BITS / 2U;
|
||||||
|
const unsigned int NXDN_FRAME_LENGTH_SAMPLES = NXDN_FRAME_LENGTH_SYMBOLS * NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
|
||||||
|
const unsigned int NXDN_FSW_LENGTH_BITS = 20U;
|
||||||
|
const unsigned int NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
|
||||||
|
const unsigned int NXDN_FSW_LENGTH_SAMPLES = NXDN_FSW_LENGTH_SYMBOLS * NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
|
||||||
|
const uint8_t NXDN_FSW_BYTES[] = {0xCDU, 0xF5U, 0x90U};
|
||||||
|
const uint8_t NXDN_FSW_BYTES_MASK[] = {0xFFU, 0xFFU, 0xF0U};
|
||||||
|
const uint8_t NXDN_FSW_BYTES_LENGTH = 3U;
|
||||||
|
|
||||||
|
const uint32_t NXDN_FSW_BITS = 0x000CDF59U;
|
||||||
|
const uint32_t NXDN_FSW_BITS_MASK = 0x000FFFFFU;
|
||||||
|
|
||||||
|
// C D F 5 9
|
||||||
|
// 11 00 11 01 11 11 01 01 10 01
|
||||||
|
// -3 +1 -3 +3 -3 -3 +3 +3 -1 +3
|
||||||
|
|
||||||
|
const int8_t NXDN_FSW_SYMBOLS_VALUES[] = {-3, +1, -3, +3, -3, -3, +3, +3, -1, +3};
|
||||||
|
|
||||||
|
const uint16_t NXDN_FSW_SYMBOLS = 0x014DU;
|
||||||
|
const uint16_t NXDN_FSW_SYMBOLS_MASK = 0x03FFU;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
+405
@@ -0,0 +1,405 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* 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 "NXDNRX.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
const q15_t SCALING_FACTOR = 18750; // Q15(0.55)
|
||||||
|
|
||||||
|
const uint8_t MAX_FSW_BIT_START_ERRS = 1U;
|
||||||
|
const uint8_t MAX_FSW_BIT_RUN_ERRS = 3U;
|
||||||
|
|
||||||
|
const uint8_t MAX_FSW_SYMBOLS_ERRS = 2U;
|
||||||
|
|
||||||
|
const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
||||||
|
|
||||||
|
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||||
|
|
||||||
|
const uint8_t NOAVEPTR = 99U;
|
||||||
|
|
||||||
|
const uint16_t NOENDPTR = 9999U;
|
||||||
|
|
||||||
|
const unsigned int MAX_FSW_FRAMES = 5U + 1U;
|
||||||
|
|
||||||
|
CNXDNRX::CNXDNRX() :
|
||||||
|
m_state(NXDNRXS_NONE),
|
||||||
|
m_bitBuffer(),
|
||||||
|
m_buffer(),
|
||||||
|
m_bitPtr(0U),
|
||||||
|
m_dataPtr(0U),
|
||||||
|
m_startPtr(NOENDPTR),
|
||||||
|
m_endPtr(NOENDPTR),
|
||||||
|
m_fswPtr(NOENDPTR),
|
||||||
|
m_minFSWPtr(NOENDPTR),
|
||||||
|
m_maxFSWPtr(NOENDPTR),
|
||||||
|
m_maxCorr(0),
|
||||||
|
m_lostCount(0U),
|
||||||
|
m_countdown(0U),
|
||||||
|
m_centre(),
|
||||||
|
m_centreVal(0),
|
||||||
|
m_threshold(),
|
||||||
|
m_thresholdVal(0),
|
||||||
|
m_averagePtr(NOAVEPTR),
|
||||||
|
m_rssiAccum(0U),
|
||||||
|
m_rssiCount(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNRX::reset()
|
||||||
|
{
|
||||||
|
m_state = NXDNRXS_NONE;
|
||||||
|
m_dataPtr = 0U;
|
||||||
|
m_bitPtr = 0U;
|
||||||
|
m_maxCorr = 0;
|
||||||
|
m_averagePtr = NOAVEPTR;
|
||||||
|
m_startPtr = NOENDPTR;
|
||||||
|
m_endPtr = NOENDPTR;
|
||||||
|
m_fswPtr = NOENDPTR;
|
||||||
|
m_minFSWPtr = NOENDPTR;
|
||||||
|
m_maxFSWPtr = NOENDPTR;
|
||||||
|
m_centreVal = 0;
|
||||||
|
m_thresholdVal = 0;
|
||||||
|
m_lostCount = 0U;
|
||||||
|
m_countdown = 0U;
|
||||||
|
m_rssiAccum = 0U;
|
||||||
|
m_rssiCount = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNRX::samples(const q15_t* samples, uint16_t* rssi, uint8_t length)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0U; i < length; i++) {
|
||||||
|
q15_t sample = samples[i];
|
||||||
|
|
||||||
|
m_rssiAccum += rssi[i];
|
||||||
|
m_rssiCount++;
|
||||||
|
|
||||||
|
m_bitBuffer[m_bitPtr] <<= 1;
|
||||||
|
if (sample < 0)
|
||||||
|
m_bitBuffer[m_bitPtr] |= 0x01U;
|
||||||
|
|
||||||
|
m_buffer[m_dataPtr] = sample;
|
||||||
|
|
||||||
|
switch (m_state) {
|
||||||
|
case NXDNRXS_DATA:
|
||||||
|
processData(sample);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
processNone(sample);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dataPtr++;
|
||||||
|
if (m_dataPtr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
m_dataPtr = 0U;
|
||||||
|
|
||||||
|
m_bitPtr++;
|
||||||
|
if (m_bitPtr >= NXDN_RADIO_SYMBOL_LENGTH)
|
||||||
|
m_bitPtr = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNRX::processNone(q15_t sample)
|
||||||
|
{
|
||||||
|
bool ret = correlateFSW();
|
||||||
|
if (ret) {
|
||||||
|
// On the first sync, start the countdown to the state change
|
||||||
|
if (m_countdown == 0U) {
|
||||||
|
m_rssiAccum = 0U;
|
||||||
|
m_rssiCount = 0U;
|
||||||
|
|
||||||
|
io.setDecode(true);
|
||||||
|
io.setADCDetection(true);
|
||||||
|
|
||||||
|
m_averagePtr = NOAVEPTR;
|
||||||
|
|
||||||
|
m_countdown = 5U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_countdown > 0U)
|
||||||
|
m_countdown--;
|
||||||
|
|
||||||
|
if (m_countdown == 1U) {
|
||||||
|
m_minFSWPtr = m_fswPtr + NXDN_FRAME_LENGTH_SAMPLES - 1U;
|
||||||
|
if (m_minFSWPtr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
m_minFSWPtr -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
|
||||||
|
m_maxFSWPtr = m_fswPtr + 1U;
|
||||||
|
if (m_maxFSWPtr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
m_maxFSWPtr -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
|
||||||
|
m_state = NXDNRXS_DATA;
|
||||||
|
m_countdown = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNRX::processData(q15_t sample)
|
||||||
|
{
|
||||||
|
if (m_minFSWPtr < m_maxFSWPtr) {
|
||||||
|
if (m_dataPtr >= m_minFSWPtr && m_dataPtr <= m_maxFSWPtr)
|
||||||
|
correlateFSW();
|
||||||
|
} else {
|
||||||
|
if (m_dataPtr >= m_minFSWPtr || m_dataPtr <= m_maxFSWPtr)
|
||||||
|
correlateFSW();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_dataPtr == m_endPtr) {
|
||||||
|
// Only update the centre and threshold if they are from a good sync
|
||||||
|
if (m_lostCount == MAX_FSW_FRAMES) {
|
||||||
|
m_minFSWPtr = m_fswPtr + NXDN_FRAME_LENGTH_SAMPLES - 1U;
|
||||||
|
if (m_minFSWPtr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
m_minFSWPtr -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
|
||||||
|
m_maxFSWPtr = m_fswPtr + 1U;
|
||||||
|
if (m_maxFSWPtr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
m_maxFSWPtr -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateLevels(m_startPtr, NXDN_FRAME_LENGTH_SYMBOLS);
|
||||||
|
|
||||||
|
DEBUG4("NXDNRX: sync found pos/centre/threshold", m_fswPtr, m_centreVal, m_thresholdVal);
|
||||||
|
|
||||||
|
uint8_t frame[NXDN_FRAME_LENGTH_BYTES + 3U];
|
||||||
|
samplesToBits(m_startPtr, NXDN_FRAME_LENGTH_SYMBOLS, frame, 8U, m_centreVal, m_thresholdVal);
|
||||||
|
|
||||||
|
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
||||||
|
m_lostCount--;
|
||||||
|
if (m_lostCount == 0U) {
|
||||||
|
DEBUG1("NXDNRX: sync timed out, lost lock");
|
||||||
|
|
||||||
|
io.setDecode(false);
|
||||||
|
io.setADCDetection(false);
|
||||||
|
|
||||||
|
serial.writeNXDNLost();
|
||||||
|
|
||||||
|
m_state = NXDNRXS_NONE;
|
||||||
|
m_endPtr = NOENDPTR;
|
||||||
|
m_averagePtr = NOAVEPTR;
|
||||||
|
m_countdown = 0U;
|
||||||
|
m_maxCorr = 0;
|
||||||
|
} else {
|
||||||
|
frame[0U] = m_lostCount == (MAX_FSW_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||||
|
writeRSSIData(frame);
|
||||||
|
m_maxCorr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CNXDNRX::correlateFSW()
|
||||||
|
{
|
||||||
|
if (countBits32((m_bitBuffer[m_bitPtr] & NXDN_FSW_SYMBOLS_MASK) ^ NXDN_FSW_SYMBOLS) <= MAX_FSW_SYMBOLS_ERRS) {
|
||||||
|
uint16_t ptr = m_dataPtr + NXDN_FRAME_LENGTH_SAMPLES - NXDN_FSW_LENGTH_SAMPLES + NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
if (ptr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
ptr -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
|
||||||
|
q31_t corr = 0;
|
||||||
|
q15_t min = 16000;
|
||||||
|
q15_t max = -16000;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < NXDN_FSW_LENGTH_SYMBOLS; i++) {
|
||||||
|
q15_t val = m_buffer[ptr];
|
||||||
|
|
||||||
|
if (val > max)
|
||||||
|
max = val;
|
||||||
|
if (val < min)
|
||||||
|
min = val;
|
||||||
|
|
||||||
|
switch (NXDN_FSW_SYMBOLS_VALUES[i]) {
|
||||||
|
case +3:
|
||||||
|
corr -= (val + val + val);
|
||||||
|
break;
|
||||||
|
case +1:
|
||||||
|
corr -= val;
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
corr += val;
|
||||||
|
break;
|
||||||
|
default: // -3
|
||||||
|
corr += (val + val + val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
if (ptr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
ptr -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (corr > m_maxCorr) {
|
||||||
|
if (m_averagePtr == NOAVEPTR) {
|
||||||
|
m_centreVal = (max + min) >> 1;
|
||||||
|
|
||||||
|
q31_t v1 = (max - m_centreVal) * SCALING_FACTOR;
|
||||||
|
m_thresholdVal = q15_t(v1 >> 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t startPtr = m_dataPtr + NXDN_FRAME_LENGTH_SAMPLES - NXDN_FSW_LENGTH_SAMPLES + NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
if (startPtr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
startPtr -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
|
||||||
|
uint8_t sync[NXDN_FSW_BYTES_LENGTH];
|
||||||
|
samplesToBits(startPtr, NXDN_FSW_LENGTH_SYMBOLS, sync, 0U, m_centreVal, m_thresholdVal);
|
||||||
|
|
||||||
|
uint8_t maxErrs;
|
||||||
|
if (m_state == NXDNRXS_NONE)
|
||||||
|
maxErrs = MAX_FSW_BIT_START_ERRS;
|
||||||
|
else
|
||||||
|
maxErrs = MAX_FSW_BIT_RUN_ERRS;
|
||||||
|
|
||||||
|
uint8_t errs = 0U;
|
||||||
|
for (uint8_t i = 0U; i < NXDN_FSW_BYTES_LENGTH; i++)
|
||||||
|
errs += countBits8((sync[i] & NXDN_FSW_BYTES_MASK[i]) ^ NXDN_FSW_BYTES[i]);
|
||||||
|
|
||||||
|
if (errs <= maxErrs) {
|
||||||
|
m_maxCorr = corr;
|
||||||
|
m_lostCount = MAX_FSW_FRAMES;
|
||||||
|
m_fswPtr = m_dataPtr;
|
||||||
|
|
||||||
|
m_startPtr = startPtr;
|
||||||
|
|
||||||
|
m_endPtr = m_dataPtr + NXDN_FRAME_LENGTH_SAMPLES - NXDN_FSW_LENGTH_SAMPLES - 1U;
|
||||||
|
if (m_endPtr >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
m_endPtr -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNRX::calculateLevels(uint16_t start, uint16_t count)
|
||||||
|
{
|
||||||
|
q15_t maxPos = -16000;
|
||||||
|
q15_t minPos = 16000;
|
||||||
|
q15_t maxNeg = 16000;
|
||||||
|
q15_t minNeg = -16000;
|
||||||
|
|
||||||
|
for (uint16_t i = 0U; i < count; i++) {
|
||||||
|
q15_t sample = m_buffer[start];
|
||||||
|
|
||||||
|
if (sample > 0) {
|
||||||
|
if (sample > maxPos)
|
||||||
|
maxPos = sample;
|
||||||
|
if (sample < minPos)
|
||||||
|
minPos = sample;
|
||||||
|
} else {
|
||||||
|
if (sample < maxNeg)
|
||||||
|
maxNeg = sample;
|
||||||
|
if (sample > minNeg)
|
||||||
|
minNeg = sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
start += NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
if (start >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
start -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
}
|
||||||
|
|
||||||
|
q15_t posThresh = (maxPos + minPos) >> 1;
|
||||||
|
q15_t negThresh = (maxNeg + minNeg) >> 1;
|
||||||
|
|
||||||
|
q15_t centre = (posThresh + negThresh) >> 1;
|
||||||
|
|
||||||
|
q15_t threshold = posThresh - centre;
|
||||||
|
|
||||||
|
DEBUG5("NXDNRX: pos/neg/centre/threshold", posThresh, negThresh, centre, threshold);
|
||||||
|
|
||||||
|
if (m_averagePtr == NOAVEPTR) {
|
||||||
|
for (uint8_t i = 0U; i < 16U; i++) {
|
||||||
|
m_centre[i] = centre;
|
||||||
|
m_threshold[i] = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_averagePtr = 0U;
|
||||||
|
} else {
|
||||||
|
m_centre[m_averagePtr] = centre;
|
||||||
|
m_threshold[m_averagePtr] = threshold;
|
||||||
|
|
||||||
|
m_averagePtr++;
|
||||||
|
if (m_averagePtr >= 16U)
|
||||||
|
m_averagePtr = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_centreVal = 0;
|
||||||
|
m_thresholdVal = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < 16U; i++) {
|
||||||
|
m_centreVal += m_centre[i];
|
||||||
|
m_thresholdVal += m_threshold[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_centreVal >>= 4;
|
||||||
|
m_thresholdVal >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNRX::samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0U; i < count; i++) {
|
||||||
|
q15_t sample = m_buffer[start] - centre;
|
||||||
|
|
||||||
|
if (sample < -threshold) {
|
||||||
|
WRITE_BIT1(buffer, offset, false);
|
||||||
|
offset++;
|
||||||
|
WRITE_BIT1(buffer, offset, true);
|
||||||
|
offset++;
|
||||||
|
} else if (sample < 0) {
|
||||||
|
WRITE_BIT1(buffer, offset, false);
|
||||||
|
offset++;
|
||||||
|
WRITE_BIT1(buffer, offset, false);
|
||||||
|
offset++;
|
||||||
|
} else if (sample < threshold) {
|
||||||
|
WRITE_BIT1(buffer, offset, true);
|
||||||
|
offset++;
|
||||||
|
WRITE_BIT1(buffer, offset, false);
|
||||||
|
offset++;
|
||||||
|
} else {
|
||||||
|
WRITE_BIT1(buffer, offset, true);
|
||||||
|
offset++;
|
||||||
|
WRITE_BIT1(buffer, offset, true);
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
start += NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
if (start >= NXDN_FRAME_LENGTH_SAMPLES)
|
||||||
|
start -= NXDN_FRAME_LENGTH_SAMPLES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNRX::writeRSSIData(uint8_t* data)
|
||||||
|
{
|
||||||
|
#if defined(SEND_RSSI_DATA)
|
||||||
|
if (m_rssiCount > 0U) {
|
||||||
|
uint16_t rssi = m_rssiAccum / m_rssiCount;
|
||||||
|
|
||||||
|
data[49U] = (rssi >> 8) & 0xFFU;
|
||||||
|
data[50U] = (rssi >> 0) & 0xFFU;
|
||||||
|
|
||||||
|
serial.writeNXDNData(data, NXDN_FRAME_LENGTH_BYTES + 3U);
|
||||||
|
} else {
|
||||||
|
serial.writeNXDNData(data, NXDN_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
serial.writeNXDNData(data, NXDN_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_rssiAccum = 0U;
|
||||||
|
m_rssiCount = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* 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(NXDNRX_H)
|
||||||
|
#define NXDNRX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "NXDNDefines.h"
|
||||||
|
|
||||||
|
enum NXDNRX_STATE {
|
||||||
|
NXDNRXS_NONE,
|
||||||
|
NXDNRXS_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
class CNXDNRX {
|
||||||
|
public:
|
||||||
|
CNXDNRX();
|
||||||
|
|
||||||
|
void samples(const q15_t* samples, uint16_t* rssi, uint8_t length);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NXDNRX_STATE m_state;
|
||||||
|
uint16_t m_bitBuffer[NXDN_RADIO_SYMBOL_LENGTH];
|
||||||
|
q15_t m_buffer[NXDN_FRAME_LENGTH_SAMPLES];
|
||||||
|
uint16_t m_bitPtr;
|
||||||
|
uint16_t m_dataPtr;
|
||||||
|
uint16_t m_startPtr;
|
||||||
|
uint16_t m_endPtr;
|
||||||
|
uint16_t m_fswPtr;
|
||||||
|
uint16_t m_minFSWPtr;
|
||||||
|
uint16_t m_maxFSWPtr;
|
||||||
|
q31_t m_maxCorr;
|
||||||
|
uint16_t m_lostCount;
|
||||||
|
uint8_t m_countdown;
|
||||||
|
q15_t m_centre[16U];
|
||||||
|
q15_t m_centreVal;
|
||||||
|
q15_t m_threshold[16U];
|
||||||
|
q15_t m_thresholdVal;
|
||||||
|
uint8_t m_averagePtr;
|
||||||
|
uint32_t m_rssiAccum;
|
||||||
|
uint16_t m_rssiCount;
|
||||||
|
|
||||||
|
void processNone(q15_t sample);
|
||||||
|
void processData(q15_t sample);
|
||||||
|
bool correlateFSW();
|
||||||
|
void calculateLevels(uint16_t start, uint16_t count);
|
||||||
|
void samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold);
|
||||||
|
void writeRSSIData(uint8_t* data);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
+170
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* 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 "NXDNTX.h"
|
||||||
|
|
||||||
|
#include "NXDNDefines.h"
|
||||||
|
|
||||||
|
// Generated using rcosdesign(0.2, 8, 10, 'sqrt') in MATLAB
|
||||||
|
static q15_t RRC_0_2_FILTER[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 850, 592, 219, -234, -720, -1179, -1548, -1769, -1795, -1597, -1172,
|
||||||
|
-544, 237, 1092, 1927, 2637, 3120, 3286, 3073, 2454, 1447, 116, -1431, -3043, -4544, -5739, -6442,
|
||||||
|
-6483, -5735, -4121, -1633, 1669, 5651, 10118, 14822, 19484, 23810, 27520, 30367, 32156, 32767,
|
||||||
|
32156, 30367, 27520, 23810, 19484, 14822, 10118, 5651, 1669, -1633, -4121, -5735, -6483, -6442,
|
||||||
|
-5739, -4544, -3043, -1431, 116, 1447, 2454, 3073, 3286, 3120, 2637, 1927, 1092, 237, -544, -1172,
|
||||||
|
-1597, -1795, -1769, -1548, -1179, -720, -234, 219, 592, 850}; // numTaps = 90, L = 10
|
||||||
|
const uint16_t RRC_0_2_FILTER_PHASE_LEN = 9U; // phaseLength = numTaps/L
|
||||||
|
|
||||||
|
static q15_t NXDN_SINC_FILTER[] = {572, -1003, -253, 254, 740, 1290, 1902, 2527, 3090, 3517, 3747, 3747, 3517, 3090, 2527, 1902,
|
||||||
|
1290, 740, 254, -253, -1003, 572};
|
||||||
|
const uint16_t NXDN_SINC_FILTER_LEN = 22U;
|
||||||
|
|
||||||
|
const q15_t NXDN_LEVELA = 735;
|
||||||
|
const q15_t NXDN_LEVELB = 245;
|
||||||
|
const q15_t NXDN_LEVELC = -245;
|
||||||
|
const q15_t NXDN_LEVELD = -735;
|
||||||
|
|
||||||
|
const uint8_t NXDN_PREAMBLE[] = {0x57U, 0x75U, 0xFDU};
|
||||||
|
const uint8_t NXDN_SYNC = 0x5FU;
|
||||||
|
|
||||||
|
CNXDNTX::CNXDNTX() :
|
||||||
|
m_buffer(2000U),
|
||||||
|
m_modFilter(),
|
||||||
|
m_sincFilter(),
|
||||||
|
m_modState(),
|
||||||
|
m_sincState(),
|
||||||
|
m_poBuffer(),
|
||||||
|
m_poLen(0U),
|
||||||
|
m_poPtr(0U),
|
||||||
|
m_txDelay(240U) // 200ms
|
||||||
|
{
|
||||||
|
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
|
||||||
|
::memset(m_sincState, 0x00U, 70U * sizeof(q15_t));
|
||||||
|
|
||||||
|
m_modFilter.L = NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
m_modFilter.phaseLength = RRC_0_2_FILTER_PHASE_LEN;
|
||||||
|
m_modFilter.pCoeffs = RRC_0_2_FILTER;
|
||||||
|
m_modFilter.pState = m_modState;
|
||||||
|
|
||||||
|
m_sincFilter.numTaps = NXDN_SINC_FILTER_LEN;
|
||||||
|
m_sincFilter.pState = m_sincState;
|
||||||
|
m_sincFilter.pCoeffs = NXDN_SINC_FILTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNTX::process()
|
||||||
|
{
|
||||||
|
if (m_buffer.getData() == 0U && m_poLen == 0U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_poLen == 0U) {
|
||||||
|
if (!m_tx) {
|
||||||
|
for (uint16_t i = 0U; i < m_txDelay; i++)
|
||||||
|
m_poBuffer[m_poLen++] = NXDN_SYNC;
|
||||||
|
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[0U];
|
||||||
|
m_poBuffer[m_poLen++] = NXDN_PREAMBLE[1U];
|
||||||
|
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();
|
||||||
|
m_poBuffer[m_poLen++] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_poPtr = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_poLen > 0U) {
|
||||||
|
uint16_t space = io.getSpace();
|
||||||
|
|
||||||
|
while (space > (4U * NXDN_RADIO_SYMBOL_LENGTH)) {
|
||||||
|
uint8_t c = m_poBuffer[m_poPtr++];
|
||||||
|
writeByte(c);
|
||||||
|
|
||||||
|
space -= 4U * NXDN_RADIO_SYMBOL_LENGTH;
|
||||||
|
|
||||||
|
if (m_poPtr >= m_poLen) {
|
||||||
|
m_poPtr = 0U;
|
||||||
|
m_poLen = 0U;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CNXDNTX::writeData(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
uint16_t space = m_buffer.getSpace();
|
||||||
|
if (space < NXDN_FRAME_LENGTH_BYTES)
|
||||||
|
return 5U;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++)
|
||||||
|
m_buffer.put(data[i + 1U]);
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNTX::writeByte(uint8_t c)
|
||||||
|
{
|
||||||
|
q15_t inBuffer[4U];
|
||||||
|
q15_t intBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
|
||||||
|
q15_t outBuffer[NXDN_RADIO_SYMBOL_LENGTH * 4U];
|
||||||
|
|
||||||
|
const uint8_t MASK = 0xC0U;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < 4U; i++, c <<= 2) {
|
||||||
|
switch (c & MASK) {
|
||||||
|
case 0xC0U:
|
||||||
|
inBuffer[i] = NXDN_LEVELA;
|
||||||
|
break;
|
||||||
|
case 0x80U:
|
||||||
|
inBuffer[i] = NXDN_LEVELB;
|
||||||
|
break;
|
||||||
|
case 0x00U:
|
||||||
|
inBuffer[i] = NXDN_LEVELC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
inBuffer[i] = NXDN_LEVELD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, intBuffer, 4U);
|
||||||
|
|
||||||
|
::arm_fir_fast_q15(&m_sincFilter, intBuffer, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
|
||||||
|
|
||||||
|
io.write(STATE_NXDN, outBuffer, NXDN_RADIO_SYMBOL_LENGTH * 4U);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNXDNTX::setTXDelay(uint8_t delay)
|
||||||
|
{
|
||||||
|
m_txDelay = 300U + uint16_t(delay) * 6U; // 500ms + tx delay
|
||||||
|
|
||||||
|
if (m_txDelay > 1200U)
|
||||||
|
m_txDelay = 1200U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CNXDNTX::getSpace() const
|
||||||
|
{
|
||||||
|
return m_buffer.getSpace() / NXDN_FRAME_LENGTH_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* 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(NXDNTX_H)
|
||||||
|
#define NXDNTX_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
|
class CNXDNTX {
|
||||||
|
public:
|
||||||
|
CNXDNTX();
|
||||||
|
|
||||||
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setTXDelay(uint8_t delay);
|
||||||
|
|
||||||
|
uint8_t getSpace() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSerialRB m_buffer;
|
||||||
|
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
|
||||||
|
q15_t m_sincState[70U]; // NoTaps + BlockSize - 1, 22 + 40 - 1 plus some spare
|
||||||
|
uint8_t m_poBuffer[1200U];
|
||||||
|
uint16_t m_poLen;
|
||||||
|
uint16_t m_poPtr;
|
||||||
|
uint16_t m_txDelay;
|
||||||
|
|
||||||
|
void writeByte(uint8_t c);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -30,12 +30,10 @@ static q15_t RC_0_2_FILTER[] = {-897, -1636, -1840, -1278, 0, 1613, 2936, 3310,
|
|||||||
-3011, 0, 2315, 3310, 2936, 1613, 0, -1278, -1840, -1636, -897, 0}; // numTaps = 40, L = 5
|
-3011, 0, 2315, 3310, 2936, 1613, 0, -1278, -1840, -1636, -897, 0}; // numTaps = 40, L = 5
|
||||||
const uint16_t RC_0_2_FILTER_PHASE_LEN = 8U; // phaseLength = numTaps/L
|
const uint16_t RC_0_2_FILTER_PHASE_LEN = 8U; // phaseLength = numTaps/L
|
||||||
|
|
||||||
// Generated in MATLAB using the following commands, and then normalised for unity gain
|
static q15_t LOWPASS_FILTER[] = {124, -188, -682, 1262, 556, -621, -1912, -911, 2058, 3855, 1234, -4592, -7692, -2799,
|
||||||
// shape2 = 'Inverse-sinc Lowpass';
|
8556, 18133, 18133, 8556, -2799, -7692, -4592, 1234, 3855, 2058, -911, -1912, -621,
|
||||||
// d2 = fdesign.interpolator(1, shape2);
|
556, 1262, -682, -188, 124};
|
||||||
// h2 = design(d2, 'SystemObject', true);
|
const uint16_t LOWPASS_FILTER_LEN = 32U;
|
||||||
static q15_t LOWPASS_FILTER[] = {1376, -2393, 4584, -8933, 22325, 22325, -8933, 4584, -2393, 1376};
|
|
||||||
const uint16_t LOWPASS_FILTER_LEN = 10U;
|
|
||||||
|
|
||||||
const q15_t P25_LEVELA = 1260;
|
const q15_t P25_LEVELA = 1260;
|
||||||
const q15_t P25_LEVELB = 420;
|
const q15_t P25_LEVELB = 420;
|
||||||
@@ -56,7 +54,7 @@ m_poPtr(0U),
|
|||||||
m_txDelay(240U) // 200ms
|
m_txDelay(240U) // 200ms
|
||||||
{
|
{
|
||||||
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
|
::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
|
||||||
::memset(m_lpState, 0x00U, 70U * sizeof(q15_t));
|
::memset(m_lpState, 0x00U, 60U * sizeof(q15_t));
|
||||||
|
|
||||||
m_modFilter.L = P25_RADIO_SYMBOL_LENGTH;
|
m_modFilter.L = P25_RADIO_SYMBOL_LENGTH;
|
||||||
m_modFilter.phaseLength = RC_0_2_FILTER_PHASE_LEN;
|
m_modFilter.phaseLength = RC_0_2_FILTER_PHASE_LEN;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ private:
|
|||||||
arm_fir_interpolate_instance_q15 m_modFilter;
|
arm_fir_interpolate_instance_q15 m_modFilter;
|
||||||
arm_fir_instance_q15 m_lpFilter;
|
arm_fir_instance_q15 m_lpFilter;
|
||||||
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
q15_t m_modState[16U]; // blockSize + phaseLength - 1, 4 + 9 - 1 plus some spare
|
||||||
q15_t m_lpState[70U]; // NoTaps + BlockSize - 1, 44 + 20 - 1 plus some spare
|
q15_t m_lpState[60U]; // NoTaps + BlockSize - 1, 32 + 20 - 1 plus some spare
|
||||||
uint8_t m_poBuffer[1200U];
|
uint8_t m_poBuffer[1200U];
|
||||||
uint16_t m_poLen;
|
uint16_t m_poLen;
|
||||||
uint16_t m_poPtr;
|
uint16_t m_poPtr;
|
||||||
|
|||||||
@@ -21,9 +21,10 @@ Boston, MA 02110-1301, USA.
|
|||||||
#if !defined(RSSIRB_H)
|
#if !defined(RSSIRB_H)
|
||||||
#define RSSIRB_H
|
#define RSSIRB_H
|
||||||
|
|
||||||
#if defined(STM32F4XX) || defined(STM32F4)
|
#if defined(STM32F4XX)
|
||||||
#include "stm32f4xx.h"
|
#include "stm32f4xx.h"
|
||||||
#include <cstddef>
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
#elif defined(STM32F105xC)
|
#elif defined(STM32F105xC)
|
||||||
#include "stm32f1xx.h"
|
#include "stm32f1xx.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|||||||
+3
-2
@@ -21,9 +21,10 @@ Boston, MA 02110-1301, USA.
|
|||||||
#if !defined(SAMPLERB_H)
|
#if !defined(SAMPLERB_H)
|
||||||
#define SAMPLERB_H
|
#define SAMPLERB_H
|
||||||
|
|
||||||
#if defined(STM32F4XX) || defined(STM32F4)
|
#if defined(STM32F4XX)
|
||||||
#include "stm32f4xx.h"
|
#include "stm32f4xx.h"
|
||||||
#include <cstddef>
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
#elif defined(STM32F105xC)
|
#elif defined(STM32F105xC)
|
||||||
#include "stm32f1xx.h"
|
#include "stm32f1xx.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|||||||
+170
-9
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013,2015,2016,2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2013,2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -60,6 +60,9 @@ const uint8_t MMDVM_P25_HDR = 0x30U;
|
|||||||
const uint8_t MMDVM_P25_LDU = 0x31U;
|
const uint8_t MMDVM_P25_LDU = 0x31U;
|
||||||
const uint8_t MMDVM_P25_LOST = 0x32U;
|
const uint8_t MMDVM_P25_LOST = 0x32U;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_NXDN_DATA = 0x40U;
|
||||||
|
const uint8_t MMDVM_NXDN_LOST = 0x41U;
|
||||||
|
|
||||||
const uint8_t MMDVM_ACK = 0x70U;
|
const uint8_t MMDVM_ACK = 0x70U;
|
||||||
const uint8_t MMDVM_NAK = 0x7FU;
|
const uint8_t MMDVM_NAK = 0x7FU;
|
||||||
|
|
||||||
@@ -73,9 +76,9 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U;
|
|||||||
|
|
||||||
|
|
||||||
#if defined(EXTERNAL_OSC)
|
#if defined(EXTERNAL_OSC)
|
||||||
#define DESCRIPTION "MMDVM 20170406 TCXO (D-Star/DMR/System Fusion/P25/RSSI/CW Id)"
|
#define DESCRIPTION "MMDVM 20170501 TCXO (D-Star/DMR/System Fusion/P25/NXDN/RSSI/CW Id)"
|
||||||
#else
|
#else
|
||||||
#define DESCRIPTION "MMDVM 20170406 (D-Star/DMR/System Fusion/P25/RSSI/CW Id)"
|
#define DESCRIPTION "MMDVM 20170501 (D-Star/DMR/System Fusion/P25/NXDN/RSSI/CW Id)"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GITVERSION)
|
#if defined(GITVERSION)
|
||||||
@@ -143,6 +146,8 @@ void CSerialPort::getStatus()
|
|||||||
reply[3U] |= 0x04U;
|
reply[3U] |= 0x04U;
|
||||||
if (m_p25Enable)
|
if (m_p25Enable)
|
||||||
reply[3U] |= 0x08U;
|
reply[3U] |= 0x08U;
|
||||||
|
if (m_nxdnEnable)
|
||||||
|
reply[3U] |= 0x10U;
|
||||||
|
|
||||||
reply[4U] = uint8_t(m_modemState);
|
reply[4U] = uint8_t(m_modemState);
|
||||||
|
|
||||||
@@ -197,7 +202,12 @@ void CSerialPort::getStatus()
|
|||||||
else
|
else
|
||||||
reply[10U] = 0U;
|
reply[10U] = 0U;
|
||||||
|
|
||||||
writeInt(1U, reply, 11);
|
if (m_nxdnEnable)
|
||||||
|
reply[11U] = nxdnTX.getSpace();
|
||||||
|
else
|
||||||
|
reply[11U] = 0U;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSerialPort::getVersion()
|
void CSerialPort::getVersion()
|
||||||
@@ -221,7 +231,7 @@ void CSerialPort::getVersion()
|
|||||||
|
|
||||||
uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (length < 13U)
|
if (length < 16U)
|
||||||
return 4U;
|
return 4U;
|
||||||
|
|
||||||
bool rxInvert = (data[0U] & 0x01U) == 0x01U;
|
bool rxInvert = (data[0U] & 0x01U) == 0x01U;
|
||||||
@@ -236,6 +246,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||||||
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
|
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
|
||||||
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
|
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
|
||||||
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
||||||
|
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
|
||||||
|
|
||||||
uint8_t txDelay = data[2U];
|
uint8_t txDelay = data[2U];
|
||||||
if (txDelay > 50U)
|
if (txDelay > 50U)
|
||||||
@@ -243,7 +254,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||||||
|
|
||||||
MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
|
MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
|
||||||
|
|
||||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL)
|
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K)
|
||||||
return 4U;
|
return 4U;
|
||||||
if (modemState == STATE_DSTAR && !dstarEnable)
|
if (modemState == STATE_DSTAR && !dstarEnable)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -253,6 +264,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||||||
return 4U;
|
return 4U;
|
||||||
if (modemState == STATE_P25 && !p25Enable)
|
if (modemState == STATE_P25 && !p25Enable)
|
||||||
return 4U;
|
return 4U;
|
||||||
|
if (modemState == STATE_NXDN && !nxdnEnable)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
uint8_t rxLevel = data[4U];
|
uint8_t rxLevel = data[4U];
|
||||||
|
|
||||||
@@ -268,18 +281,25 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||||||
uint8_t ysfTXLevel = data[11U];
|
uint8_t ysfTXLevel = data[11U];
|
||||||
uint8_t p25TXLevel = data[12U];
|
uint8_t p25TXLevel = data[12U];
|
||||||
|
|
||||||
|
int16_t txDCOffset = int16_t(data[13U]) - 128;
|
||||||
|
int16_t rxDCOffset = int16_t(data[14U]) - 128;
|
||||||
|
|
||||||
|
uint8_t nxdnTXLevel = data[15U];
|
||||||
|
|
||||||
m_modemState = modemState;
|
m_modemState = modemState;
|
||||||
|
|
||||||
m_dstarEnable = dstarEnable;
|
m_dstarEnable = dstarEnable;
|
||||||
m_dmrEnable = dmrEnable;
|
m_dmrEnable = dmrEnable;
|
||||||
m_ysfEnable = ysfEnable;
|
m_ysfEnable = ysfEnable;
|
||||||
m_p25Enable = p25Enable;
|
m_p25Enable = p25Enable;
|
||||||
|
m_nxdnEnable = nxdnEnable;
|
||||||
m_duplex = !simplex;
|
m_duplex = !simplex;
|
||||||
|
|
||||||
dstarTX.setTXDelay(txDelay);
|
dstarTX.setTXDelay(txDelay);
|
||||||
ysfTX.setTXDelay(txDelay);
|
ysfTX.setTXDelay(txDelay);
|
||||||
p25TX.setTXDelay(txDelay);
|
p25TX.setTXDelay(txDelay);
|
||||||
dmrDMOTX.setTXDelay(txDelay);
|
dmrDMOTX.setTXDelay(txDelay);
|
||||||
|
nxdnTX.setTXDelay(txDelay);
|
||||||
|
|
||||||
dmrTX.setColorCode(colorCode);
|
dmrTX.setColorCode(colorCode);
|
||||||
dmrRX.setColorCode(colorCode);
|
dmrRX.setColorCode(colorCode);
|
||||||
@@ -289,7 +309,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||||||
|
|
||||||
ysfTX.setLoDev(ysfLoDev);
|
ysfTX.setLoDev(ysfLoDev);
|
||||||
|
|
||||||
io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel);
|
io.setParameters(rxInvert, txInvert, pttInvert, rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, txDCOffset, rxDCOffset);
|
||||||
|
|
||||||
io.start();
|
io.start();
|
||||||
|
|
||||||
@@ -306,7 +326,7 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
|||||||
if (modemState == m_modemState)
|
if (modemState == m_modemState)
|
||||||
return 0U;
|
return 0U;
|
||||||
|
|
||||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL)
|
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_RSSICAL && modemState != STATE_LFCAL && modemState != STATE_DMRCAL1K && modemState != STATE_P25CAL1K && modemState != STATE_DMRDMO1K && modemState != STATE_NXDNCAL1K)
|
||||||
return 4U;
|
return 4U;
|
||||||
if (modemState == STATE_DSTAR && !m_dstarEnable)
|
if (modemState == STATE_DSTAR && !m_dstarEnable)
|
||||||
return 4U;
|
return 4U;
|
||||||
@@ -316,6 +336,8 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
|||||||
return 4U;
|
return 4U;
|
||||||
if (modemState == STATE_P25 && !m_p25Enable)
|
if (modemState == STATE_P25 && !m_p25Enable)
|
||||||
return 4U;
|
return 4U;
|
||||||
|
if (modemState == STATE_NXDN && !m_nxdnEnable)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
setMode(modemState);
|
setMode(modemState);
|
||||||
|
|
||||||
@@ -330,6 +352,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||||||
dstarRX.reset();
|
dstarRX.reset();
|
||||||
ysfRX.reset();
|
ysfRX.reset();
|
||||||
p25RX.reset();
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
cwIdTX.reset();
|
cwIdTX.reset();
|
||||||
break;
|
break;
|
||||||
case STATE_DSTAR:
|
case STATE_DSTAR:
|
||||||
@@ -339,6 +362,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||||||
dmrRX.reset();
|
dmrRX.reset();
|
||||||
ysfRX.reset();
|
ysfRX.reset();
|
||||||
p25RX.reset();
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
cwIdTX.reset();
|
cwIdTX.reset();
|
||||||
break;
|
break;
|
||||||
case STATE_YSF:
|
case STATE_YSF:
|
||||||
@@ -348,6 +372,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||||||
dmrRX.reset();
|
dmrRX.reset();
|
||||||
dstarRX.reset();
|
dstarRX.reset();
|
||||||
p25RX.reset();
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
cwIdTX.reset();
|
cwIdTX.reset();
|
||||||
break;
|
break;
|
||||||
case STATE_P25:
|
case STATE_P25:
|
||||||
@@ -357,6 +382,17 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||||||
dmrRX.reset();
|
dmrRX.reset();
|
||||||
dstarRX.reset();
|
dstarRX.reset();
|
||||||
ysfRX.reset();
|
ysfRX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
|
cwIdTX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_NXDN:
|
||||||
|
DEBUG1("Mode set to NXDN");
|
||||||
|
dmrIdleRX.reset();
|
||||||
|
dmrDMORX.reset();
|
||||||
|
dmrRX.reset();
|
||||||
|
dstarRX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
cwIdTX.reset();
|
cwIdTX.reset();
|
||||||
break;
|
break;
|
||||||
case STATE_DSTARCAL:
|
case STATE_DSTARCAL:
|
||||||
@@ -367,6 +403,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||||||
dstarRX.reset();
|
dstarRX.reset();
|
||||||
ysfRX.reset();
|
ysfRX.reset();
|
||||||
p25RX.reset();
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
cwIdTX.reset();
|
cwIdTX.reset();
|
||||||
break;
|
break;
|
||||||
case STATE_DMRCAL:
|
case STATE_DMRCAL:
|
||||||
@@ -377,6 +414,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||||||
dstarRX.reset();
|
dstarRX.reset();
|
||||||
ysfRX.reset();
|
ysfRX.reset();
|
||||||
p25RX.reset();
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
cwIdTX.reset();
|
cwIdTX.reset();
|
||||||
break;
|
break;
|
||||||
case STATE_RSSICAL:
|
case STATE_RSSICAL:
|
||||||
@@ -387,6 +425,62 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||||||
dstarRX.reset();
|
dstarRX.reset();
|
||||||
ysfRX.reset();
|
ysfRX.reset();
|
||||||
p25RX.reset();
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
|
cwIdTX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_LFCAL:
|
||||||
|
DEBUG1("Mode set to 80 Hz Calibrate");
|
||||||
|
dmrIdleRX.reset();
|
||||||
|
dmrDMORX.reset();
|
||||||
|
dmrRX.reset();
|
||||||
|
dstarRX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
|
cwIdTX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_DMRCAL1K:
|
||||||
|
DEBUG1("Mode set to DMR BS 1031 Hz Calibrate");
|
||||||
|
dmrIdleRX.reset();
|
||||||
|
dmrDMORX.reset();
|
||||||
|
dmrRX.reset();
|
||||||
|
dstarRX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
|
cwIdTX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_P25CAL1K:
|
||||||
|
DEBUG1("Mode set to P25 1011 Hz Calibrate");
|
||||||
|
dmrIdleRX.reset();
|
||||||
|
dmrDMORX.reset();
|
||||||
|
dmrRX.reset();
|
||||||
|
dstarRX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
|
cwIdTX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_DMRDMO1K:
|
||||||
|
DEBUG1("Mode set to DMR MS 1031 Hz Calibrate");
|
||||||
|
dmrIdleRX.reset();
|
||||||
|
dmrDMORX.reset();
|
||||||
|
dmrRX.reset();
|
||||||
|
dstarRX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
|
cwIdTX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_NXDNCAL1K:
|
||||||
|
DEBUG1("Mode set to NXDN 1031 Hz Calibrate");
|
||||||
|
dmrIdleRX.reset();
|
||||||
|
dmrDMORX.reset();
|
||||||
|
dmrRX.reset();
|
||||||
|
dstarRX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
|
nxdnRX.reset();
|
||||||
cwIdTX.reset();
|
cwIdTX.reset();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -421,6 +515,10 @@ void CSerialPort::process()
|
|||||||
m_ptr = 1U;
|
m_ptr = 1U;
|
||||||
m_len = 0U;
|
m_len = 0U;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
m_ptr = 0U;
|
||||||
|
m_len = 0U;
|
||||||
|
}
|
||||||
} else if (m_ptr == 1U) {
|
} else if (m_ptr == 1U) {
|
||||||
// Handle the frame length
|
// Handle the frame length
|
||||||
m_len = m_buffer[m_ptr] = c;
|
m_len = m_buffer[m_ptr] = c;
|
||||||
@@ -466,8 +564,12 @@ void CSerialPort::process()
|
|||||||
case MMDVM_CAL_DATA:
|
case MMDVM_CAL_DATA:
|
||||||
if (m_modemState == STATE_DSTARCAL)
|
if (m_modemState == STATE_DSTARCAL)
|
||||||
err = calDStarTX.write(m_buffer + 3U, m_len - 3U);
|
err = calDStarTX.write(m_buffer + 3U, m_len - 3U);
|
||||||
if (m_modemState == STATE_DMRCAL)
|
if (m_modemState == STATE_DMRCAL || m_modemState == STATE_LFCAL || m_modemState == STATE_DMRCAL1K || m_modemState == STATE_DMRDMO1K)
|
||||||
err = calDMR.write(m_buffer + 3U, m_len - 3U);
|
err = calDMR.write(m_buffer + 3U, m_len - 3U);
|
||||||
|
if (m_modemState == STATE_P25CAL1K)
|
||||||
|
err = calP25.write(m_buffer + 3U, m_len - 3U);
|
||||||
|
if (m_modemState == STATE_NXDNCAL1K)
|
||||||
|
err = calNXDN.write(m_buffer + 3U, m_len - 3U);
|
||||||
if (err == 0U) {
|
if (err == 0U) {
|
||||||
sendACK();
|
sendACK();
|
||||||
} else {
|
} else {
|
||||||
@@ -643,6 +745,20 @@ void CSerialPort::process()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MMDVM_NXDN_DATA:
|
||||||
|
if (m_nxdnEnable) {
|
||||||
|
if (m_modemState == STATE_IDLE || m_modemState == STATE_NXDN)
|
||||||
|
err = nxdnTX.writeData(m_buffer + 3U, m_len - 3U);
|
||||||
|
}
|
||||||
|
if (err == 0U) {
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
setMode(STATE_NXDN);
|
||||||
|
} else {
|
||||||
|
DEBUG2("Received invalid NXDN data", err);
|
||||||
|
sendNAK(err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
#if defined(SERIAL_REPEATER)
|
#if defined(SERIAL_REPEATER)
|
||||||
case MMDVM_SERIAL: {
|
case MMDVM_SERIAL: {
|
||||||
for (uint8_t i = 3U; i < m_len; i++)
|
for (uint8_t i = 3U; i < m_len; i++)
|
||||||
@@ -663,6 +779,11 @@ void CSerialPort::process()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (io.getWatchdog() >= 48000U) {
|
||||||
|
m_ptr = 0U;
|
||||||
|
m_len = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(SERIAL_REPEATER)
|
#if defined(SERIAL_REPEATER)
|
||||||
// Write any outgoing serial data
|
// Write any outgoing serial data
|
||||||
uint16_t space = m_repeat.getData();
|
uint16_t space = m_repeat.getData();
|
||||||
@@ -905,6 +1026,46 @@ void CSerialPort::writeP25Lost()
|
|||||||
writeInt(1U, reply, 3);
|
writeInt(1U, reply, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeNXDNData(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_NXDN && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_nxdnEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[130U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_NXDN_DATA;
|
||||||
|
|
||||||
|
uint8_t count = 3U;
|
||||||
|
for (uint8_t i = 0U; i < length; i++, count++)
|
||||||
|
reply[count] = data[i];
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeNXDNLost()
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_NXDN && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_nxdnEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[3U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 3U;
|
||||||
|
reply[2U] = MMDVM_NXDN_LOST;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 3);
|
||||||
|
}
|
||||||
|
|
||||||
void CSerialPort::writeCalData(const uint8_t* data, uint8_t length)
|
void CSerialPort::writeCalData(const uint8_t* data, uint8_t length)
|
||||||
{
|
{
|
||||||
if (m_modemState != STATE_DSTARCAL)
|
if (m_modemState != STATE_DSTARCAL)
|
||||||
|
|||||||
+5
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -47,6 +47,9 @@ public:
|
|||||||
void writeP25Ldu(const uint8_t* data, uint8_t length);
|
void writeP25Ldu(const uint8_t* data, uint8_t length);
|
||||||
void writeP25Lost();
|
void writeP25Lost();
|
||||||
|
|
||||||
|
void writeNXDNData(const uint8_t* data, uint8_t length);
|
||||||
|
void writeNXDNLost();
|
||||||
|
|
||||||
void writeCalData(const uint8_t* data, uint8_t length);
|
void writeCalData(const uint8_t* data, uint8_t length);
|
||||||
void writeRSSIData(const uint8_t* data, uint8_t length);
|
void writeRSSIData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
@@ -80,3 +83,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -21,9 +21,10 @@ Boston, MA 02110-1301, USA.
|
|||||||
#if !defined(SERIALRB_H)
|
#if !defined(SERIALRB_H)
|
||||||
#define SERIALRB_H
|
#define SERIALRB_H
|
||||||
|
|
||||||
#if defined(STM32F4XX) || defined(STM32F4)
|
#if defined(STM32F4XX)
|
||||||
#include "stm32f4xx.h"
|
#include "stm32f4xx.h"
|
||||||
#include <cstddef>
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
#elif defined(STM32F105xC)
|
#elif defined(STM32F105xC)
|
||||||
#include "stm32f1xx.h"
|
#include "stm32f1xx.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|||||||
+44
-35
@@ -27,17 +27,17 @@
|
|||||||
Pin definitions:
|
Pin definitions:
|
||||||
|
|
||||||
- Host communication:
|
- Host communication:
|
||||||
USART1 - TXD PA9 - RXD PA10 (Pi board)
|
USART1 - TXD PA9 - RXD PA10 (MMDVM-Pi board, MMDVM-Pi F722 board, MMDVM-F4M board)
|
||||||
USART2 - TXD PA2 - RXD PA3 (Nucleo board)
|
USART2 - TXD PA2 - RXD PA3 (Nucleo64 F446RE board, Morpho or Arduino header)
|
||||||
USART3 - TXD PC10 - RXD PC11 (Discovery board)
|
USART3 - TXD PC10 - RXD PC11 (Discovery board)
|
||||||
|
USART3 - TXD PD8 - RXD PD9 (Nucleo144 F767ZI board)
|
||||||
|
|
||||||
- Serial repeater:
|
- Serial repeater:
|
||||||
USART1 - TXD PA9 - RXD PA10 (Nucleo with Arduino header)
|
USART1 - TXD PA9 - RXD PA10 (Nucleo with Arduino header)
|
||||||
UART5 - TXD PC12 - RXD PD2 (Discovery, Pi and Nucleo with Morpho header)
|
UART5 - TXD PC12 - RXD PD2 (Discovery, MMDVM-Pi, MMDVM-Pi F722 board, MMDVM-F4M board, Nucleo64 with Morpho header and Nucleo144 F767ZI)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(STM32F4XX) || defined(STM32F4)
|
#if defined(STM32F4XX) || defined(STM32F7XX)
|
||||||
|
|
||||||
#define TX_SERIAL_FIFO_SIZE 512U
|
#define TX_SERIAL_FIFO_SIZE 512U
|
||||||
#define RX_SERIAL_FIFO_SIZE 512U
|
#define RX_SERIAL_FIFO_SIZE 512U
|
||||||
@@ -50,9 +50,8 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ************* USART1 ***************** */
|
/* ************* USART1 ***************** */
|
||||||
#if defined(STM32F4_PI) || (defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER))
|
#if defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI) || (defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER))
|
||||||
|
|
||||||
volatile uint32_t intcount1;
|
|
||||||
volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE];
|
volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE];
|
||||||
volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE];
|
volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE];
|
||||||
volatile uint16_t TXSerialfifohead1, TXSerialfifotail1;
|
volatile uint16_t TXSerialfifohead1, TXSerialfifotail1;
|
||||||
@@ -139,7 +138,6 @@ void USART1_IRQHandler()
|
|||||||
}
|
}
|
||||||
|
|
||||||
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
|
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
|
||||||
intcount1++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (USART_GetITStatus(USART1, USART_IT_TXE)) {
|
if (USART_GetITStatus(USART1, USART_IT_TXE)) {
|
||||||
@@ -186,7 +184,7 @@ void InitUSART1(int speed)
|
|||||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // Tx | Rx
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // Tx | Rx
|
||||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;
|
||||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
// Configure USART baud rate
|
// Configure USART baud rate
|
||||||
@@ -245,7 +243,6 @@ void WriteUSART1(const uint8_t* data, uint16_t length)
|
|||||||
/* ************* USART2 ***************** */
|
/* ************* USART2 ***************** */
|
||||||
#if defined(STM32F4_NUCLEO)
|
#if defined(STM32F4_NUCLEO)
|
||||||
|
|
||||||
volatile uint32_t intcount2;
|
|
||||||
volatile uint8_t TXSerialfifo2[TX_SERIAL_FIFO_SIZE];
|
volatile uint8_t TXSerialfifo2[TX_SERIAL_FIFO_SIZE];
|
||||||
volatile uint8_t RXSerialfifo2[RX_SERIAL_FIFO_SIZE];
|
volatile uint8_t RXSerialfifo2[RX_SERIAL_FIFO_SIZE];
|
||||||
volatile uint16_t TXSerialfifohead2, TXSerialfifotail2;
|
volatile uint16_t TXSerialfifohead2, TXSerialfifotail2;
|
||||||
@@ -332,7 +329,6 @@ void USART2_IRQHandler()
|
|||||||
}
|
}
|
||||||
|
|
||||||
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
|
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
|
||||||
intcount2++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (USART_GetITStatus(USART2, USART_IT_TXE)) {
|
if (USART_GetITStatus(USART2, USART_IT_TXE)) {
|
||||||
@@ -379,7 +375,7 @@ void InitUSART2(int speed)
|
|||||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; // Tx | Rx
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; // Tx | Rx
|
||||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;
|
||||||
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
// Configure USART baud rate
|
// Configure USART baud rate
|
||||||
@@ -436,9 +432,8 @@ void WriteUSART2(const uint8_t* data, uint16_t length)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ************* USART3 ***************** */
|
/* ************* USART3 ***************** */
|
||||||
#if defined(STM32F4_DISCOVERY) || defined(STM32F4_PI)
|
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
|
||||||
|
|
||||||
volatile uint32_t intcount3;
|
|
||||||
volatile uint8_t TXSerialfifo3[TX_SERIAL_FIFO_SIZE];
|
volatile uint8_t TXSerialfifo3[TX_SERIAL_FIFO_SIZE];
|
||||||
volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE];
|
volatile uint8_t RXSerialfifo3[RX_SERIAL_FIFO_SIZE];
|
||||||
volatile uint16_t TXSerialfifohead3, TXSerialfifotail3;
|
volatile uint16_t TXSerialfifohead3, TXSerialfifotail3;
|
||||||
@@ -525,7 +520,6 @@ void USART3_IRQHandler()
|
|||||||
}
|
}
|
||||||
|
|
||||||
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
|
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
|
||||||
intcount3++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (USART_GetITStatus(USART3, USART_IT_TXE)) {
|
if (USART_GetITStatus(USART3, USART_IT_TXE)) {
|
||||||
@@ -547,17 +541,34 @@ void USART3_IRQHandler()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(STM32F7_NUCLEO)
|
||||||
|
// USART3 - TXD PD8 - RXD PD9
|
||||||
|
#define USART3_GPIO_PinSource_TX GPIO_PinSource8
|
||||||
|
#define USART3_GPIO_PinSource_RX GPIO_PinSource9
|
||||||
|
#define USART3_GPIO_Pin_TX GPIO_Pin_8
|
||||||
|
#define USART3_GPIO_Pin_RX GPIO_Pin_9
|
||||||
|
#define USART3_GPIO_PORT GPIOD
|
||||||
|
#define USART3_RCC_Periph RCC_AHB1Periph_GPIOD
|
||||||
|
#else
|
||||||
|
// USART3 - TXD PC10 - RXD PC11
|
||||||
|
#define USART3_GPIO_PinSource_TX GPIO_PinSource10
|
||||||
|
#define USART3_GPIO_PinSource_RX GPIO_PinSource11
|
||||||
|
#define USART3_GPIO_Pin_TX GPIO_Pin_10
|
||||||
|
#define USART3_GPIO_Pin_RX GPIO_Pin_11
|
||||||
|
#define USART3_GPIO_PORT GPIOC
|
||||||
|
#define USART3_RCC_Periph RCC_AHB1Periph_GPIOC
|
||||||
|
#endif
|
||||||
|
|
||||||
void InitUSART3(int speed)
|
void InitUSART3(int speed)
|
||||||
{
|
{
|
||||||
// USART3 - TXD PC10 - RXD PC11
|
|
||||||
GPIO_InitTypeDef GPIO_InitStructure;
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||||||
USART_InitTypeDef USART_InitStructure;
|
USART_InitTypeDef USART_InitStructure;
|
||||||
NVIC_InitTypeDef NVIC_InitStructure;
|
NVIC_InitTypeDef NVIC_InitStructure;
|
||||||
|
|
||||||
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
|
RCC_AHB1PeriphClockCmd(USART3_RCC_Periph, ENABLE);
|
||||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
|
||||||
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
|
GPIO_PinAFConfig(USART3_GPIO_PORT, USART3_GPIO_PinSource_TX, GPIO_AF_USART3);
|
||||||
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
|
GPIO_PinAFConfig(USART3_GPIO_PORT, USART3_GPIO_PinSource_RX, GPIO_AF_USART3);
|
||||||
|
|
||||||
// USART IRQ init
|
// USART IRQ init
|
||||||
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
|
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
|
||||||
@@ -571,9 +582,9 @@ void InitUSART3(int speed)
|
|||||||
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
||||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; // Tx | Rx
|
GPIO_InitStructure.GPIO_Pin = USART3_GPIO_Pin_TX | USART3_GPIO_Pin_RX; // Tx | Rx
|
||||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;
|
||||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
GPIO_Init(USART3_GPIO_PORT, &GPIO_InitStructure);
|
||||||
|
|
||||||
// Configure USART baud rate
|
// Configure USART baud rate
|
||||||
USART_StructInit(&USART_InitStructure);
|
USART_StructInit(&USART_InitStructure);
|
||||||
@@ -631,7 +642,6 @@ void WriteUSART3(const uint8_t* data, uint16_t length)
|
|||||||
/* ************* UART5 ***************** */
|
/* ************* UART5 ***************** */
|
||||||
#if !(defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER))
|
#if !(defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER))
|
||||||
|
|
||||||
volatile uint32_t intcount5;
|
|
||||||
volatile uint8_t TXSerialfifo5[TX_SERIAL_FIFO_SIZE];
|
volatile uint8_t TXSerialfifo5[TX_SERIAL_FIFO_SIZE];
|
||||||
volatile uint8_t RXSerialfifo5[RX_SERIAL_FIFO_SIZE];
|
volatile uint8_t RXSerialfifo5[RX_SERIAL_FIFO_SIZE];
|
||||||
volatile uint16_t TXSerialfifohead5, TXSerialfifotail5;
|
volatile uint16_t TXSerialfifohead5, TXSerialfifotail5;
|
||||||
@@ -718,7 +728,6 @@ void UART5_IRQHandler()
|
|||||||
}
|
}
|
||||||
|
|
||||||
USART_ClearITPendingBit(UART5, USART_IT_RXNE);
|
USART_ClearITPendingBit(UART5, USART_IT_RXNE);
|
||||||
intcount5++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (USART_GetITStatus(UART5, USART_IT_TXE)) {
|
if (USART_GetITStatus(UART5, USART_IT_TXE)) {
|
||||||
@@ -766,7 +775,7 @@ void InitUART5(int speed)
|
|||||||
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
|
||||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
||||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // Tx
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // Tx
|
||||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
GPIO_InitStructure.GPIO_Speed = GPIO_Fast_Speed;
|
||||||
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
GPIO_Init(GPIOC, &GPIO_InitStructure);
|
||||||
|
|
||||||
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // Rx
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // Rx
|
||||||
@@ -830,9 +839,9 @@ void CSerialPort::beginInt(uint8_t n, int speed)
|
|||||||
{
|
{
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
#if defined(STM32F4_DISCOVERY)
|
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
|
||||||
InitUSART3(speed);
|
InitUSART3(speed);
|
||||||
#elif defined(STM32F4_PI)
|
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI)
|
||||||
InitUSART1(speed);
|
InitUSART1(speed);
|
||||||
#elif defined(STM32F4_NUCLEO)
|
#elif defined(STM32F4_NUCLEO)
|
||||||
InitUSART2(speed);
|
InitUSART2(speed);
|
||||||
@@ -854,9 +863,9 @@ int CSerialPort::availableInt(uint8_t n)
|
|||||||
{
|
{
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
#if defined(STM32F4_DISCOVERY)
|
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
|
||||||
return AvailUSART3();
|
return AvailUSART3();
|
||||||
#elif defined(STM32F4_PI)
|
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI)
|
||||||
return AvailUSART1();
|
return AvailUSART1();
|
||||||
#elif defined(STM32F4_NUCLEO)
|
#elif defined(STM32F4_NUCLEO)
|
||||||
return AvailUSART2();
|
return AvailUSART2();
|
||||||
@@ -876,9 +885,9 @@ int CSerialPort::availableForWriteInt(uint8_t n)
|
|||||||
{
|
{
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
#if defined(STM32F4_DISCOVERY)
|
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
|
||||||
return AvailForWriteUSART3();
|
return AvailForWriteUSART3();
|
||||||
#elif defined(STM32F4_PI)
|
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI)
|
||||||
return AvailForWriteUSART1();
|
return AvailForWriteUSART1();
|
||||||
#elif defined(STM32F4_NUCLEO)
|
#elif defined(STM32F4_NUCLEO)
|
||||||
return AvailForWriteUSART2();
|
return AvailForWriteUSART2();
|
||||||
@@ -898,9 +907,9 @@ uint8_t CSerialPort::readInt(uint8_t n)
|
|||||||
{
|
{
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
#if defined(STM32F4_DISCOVERY)
|
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
|
||||||
return ReadUSART3();
|
return ReadUSART3();
|
||||||
#elif defined(STM32F4_PI)
|
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI)
|
||||||
return ReadUSART1();
|
return ReadUSART1();
|
||||||
#elif defined(STM32F4_NUCLEO)
|
#elif defined(STM32F4_NUCLEO)
|
||||||
return ReadUSART2();
|
return ReadUSART2();
|
||||||
@@ -920,11 +929,11 @@ void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool
|
|||||||
{
|
{
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
#if defined(STM32F4_DISCOVERY)
|
#if defined(STM32F4_DISCOVERY) || defined(STM32F7_NUCLEO)
|
||||||
WriteUSART3(data, length);
|
WriteUSART3(data, length);
|
||||||
if (flush)
|
if (flush)
|
||||||
TXSerialFlush3();
|
TXSerialFlush3();
|
||||||
#elif defined(STM32F4_PI)
|
#elif defined(STM32F4_PI) || defined(STM32F4_F4M) || defined(STM32F722_PI)
|
||||||
WriteUSART1(data, length);
|
WriteUSART1(data, length);
|
||||||
if (flush)
|
if (flush)
|
||||||
TXSerialFlush1();
|
TXSerialFlush1();
|
||||||
|
|||||||
+30
-29
@@ -26,10 +26,11 @@
|
|||||||
Pin definitions (configuration in IOSTM_CMSIS.c):
|
Pin definitions (configuration in IOSTM_CMSIS.c):
|
||||||
|
|
||||||
- Host communication:
|
- Host communication:
|
||||||
USART2 - TXD PA2 - RXD PA3
|
USART1 - TXD PA9 - RXD PA10
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#if defined(STM32F1)
|
#if defined(STM32F1)
|
||||||
|
|
||||||
// BaudRate calculator macro
|
// BaudRate calculator macro
|
||||||
@@ -42,22 +43,22 @@ USART2 - TXD PA2 - RXD PA3
|
|||||||
#define USART_BUFFER_SIZE 256U
|
#define USART_BUFFER_SIZE 256U
|
||||||
DECLARE_RINGBUFFER_TYPE(USARTBuffer, USART_BUFFER_SIZE);
|
DECLARE_RINGBUFFER_TYPE(USARTBuffer, USART_BUFFER_SIZE);
|
||||||
|
|
||||||
/* ************* USART2 ***************** */
|
/* ************* USART1 ***************** */
|
||||||
static volatile USARTBuffer_t txBuffer2={.size=USART_BUFFER_SIZE};
|
static volatile USARTBuffer_t txBuffer1={.size=USART_BUFFER_SIZE};
|
||||||
static volatile USARTBuffer_t rxBuffer2={.size=USART_BUFFER_SIZE};
|
static volatile USARTBuffer_t rxBuffer1={.size=USART_BUFFER_SIZE};
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
bitband_t txe = (bitband_t)BITBAND_PERIPH(&USART2->SR, USART_SR_TXE_Pos);
|
bitband_t txe = (bitband_t)BITBAND_PERIPH(&USART1->SR, USART_SR_TXE_Pos);
|
||||||
bitband_t rxne = (bitband_t)BITBAND_PERIPH(&USART2->SR, USART_SR_RXNE_Pos);
|
bitband_t rxne = (bitband_t)BITBAND_PERIPH(&USART1->SR, USART_SR_RXNE_Pos);
|
||||||
bitband_t txeie = (bitband_t)BITBAND_PERIPH(&USART2->CR1, USART_CR1_TXEIE_Pos);
|
bitband_t txeie = (bitband_t)BITBAND_PERIPH(&USART1->CR1, USART_CR1_TXEIE_Pos);
|
||||||
|
|
||||||
RAMFUNC void USART2_IRQHandler()
|
RAMFUNC void USART1_IRQHandler()
|
||||||
{
|
{
|
||||||
/* Transmitting data */
|
/* Transmitting data */
|
||||||
if(*txe){
|
if(*txe){
|
||||||
if(!(RINGBUFF_EMPTY(txBuffer2))){
|
if(!(RINGBUFF_EMPTY(txBuffer1))){
|
||||||
USART2->DR = RINGBUFF_READ(txBuffer2);
|
USART1->DR = RINGBUFF_READ(txBuffer1);
|
||||||
}else{ /* Buffer empty */
|
}else{ /* Buffer empty */
|
||||||
*txeie = 0; /* Don't send further data */
|
*txeie = 0; /* Don't send further data */
|
||||||
}
|
}
|
||||||
@@ -65,42 +66,42 @@ extern "C" {
|
|||||||
|
|
||||||
/* Receiving data */
|
/* Receiving data */
|
||||||
if(*rxne){
|
if(*rxne){
|
||||||
RINGBUFF_WRITE(rxBuffer2, USART2->DR);
|
RINGBUFF_WRITE(rxBuffer1, USART1->DR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void USART2Init(int speed)
|
void USART1Init(int speed)
|
||||||
{
|
{
|
||||||
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
|
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
|
||||||
|
|
||||||
USART2->BRR = USART_BRR(36000000UL, speed);
|
USART1->BRR = USART_BRR(72000000UL, speed);
|
||||||
|
|
||||||
USART2->CR1 = USART_CR1_UE | USART_CR1_TE |
|
USART1->CR1 = USART_CR1_UE | USART_CR1_TE |
|
||||||
USART_CR1_RE | USART_CR1_RXNEIE; // Enable USART and RX interrupt
|
USART_CR1_RE | USART_CR1_RXNEIE; // Enable USART and RX interrupt
|
||||||
NVIC_EnableIRQ(USART2_IRQn);
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
RAMFUNC void USART2TxData(const uint8_t* data, uint16_t length)
|
RAMFUNC void USART1TxData(const uint8_t* data, uint16_t length)
|
||||||
{
|
{
|
||||||
NVIC_DisableIRQ(USART2_IRQn);
|
NVIC_DisableIRQ(USART1_IRQn);
|
||||||
|
|
||||||
/* Check remaining space in buffer */
|
/* Check remaining space in buffer */
|
||||||
if(RINGBUFF_COUNT(txBuffer2) + length > RINGBUFF_SIZE(txBuffer2)){
|
if(RINGBUFF_COUNT(txBuffer1) + length > RINGBUFF_SIZE(txBuffer1)){
|
||||||
NVIC_EnableIRQ(USART2_IRQn);
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append data to buffer */
|
/* Append data to buffer */
|
||||||
while(length--){
|
while(length--){
|
||||||
RINGBUFF_WRITE(txBuffer2, *(data++));
|
RINGBUFF_WRITE(txBuffer1, *(data++));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start sending data */
|
/* Start sending data */
|
||||||
USART2->CR1 |= USART_CR1_TXEIE;
|
USART1->CR1 |= USART_CR1_TXEIE;
|
||||||
|
|
||||||
NVIC_EnableIRQ(USART2_IRQn);
|
NVIC_EnableIRQ(USART1_IRQn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -110,7 +111,7 @@ void CSerialPort::beginInt(uint8_t n, int speed)
|
|||||||
{
|
{
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
USART2Init(speed);
|
USART1Init(speed);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -121,7 +122,7 @@ int CSerialPort::availableInt(uint8_t n)
|
|||||||
{
|
{
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
return !RINGBUFF_EMPTY(rxBuffer2);
|
return !RINGBUFF_EMPTY(rxBuffer1);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -131,7 +132,7 @@ uint8_t CSerialPort::readInt(uint8_t n)
|
|||||||
{
|
{
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
return RINGBUFF_READ(rxBuffer2);
|
return RINGBUFF_READ(rxBuffer1);
|
||||||
default:
|
default:
|
||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
@@ -139,15 +140,15 @@ uint8_t CSerialPort::readInt(uint8_t n)
|
|||||||
|
|
||||||
void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush)
|
void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush)
|
||||||
{
|
{
|
||||||
bitband_t tc = (bitband_t)BITBAND_PERIPH(&USART2->SR, USART_SR_TC_Pos);
|
bitband_t tc = (bitband_t)BITBAND_PERIPH(&USART1->SR, USART_SR_TC_Pos);
|
||||||
|
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 1U:
|
case 1U:
|
||||||
USART2TxData(data, length);
|
USART1TxData(data, length);
|
||||||
*tc = 0;
|
*tc = 0;
|
||||||
|
|
||||||
if (flush) {
|
if (flush) {
|
||||||
while (!RINGBUFF_EMPTY(txBuffer2) || !tc)
|
while (!RINGBUFF_EMPTY(txBuffer1) || !tc)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -19,9 +19,10 @@
|
|||||||
#if !defined(UTILS_H)
|
#if !defined(UTILS_H)
|
||||||
#define UTILS_H
|
#define UTILS_H
|
||||||
|
|
||||||
#if defined(STM32F4XX) || defined(STM32F4)
|
#if defined(STM32F4XX)
|
||||||
#include "stm32f4xx.h"
|
#include "stm32f4xx.h"
|
||||||
#include <cstddef>
|
#elif defined(STM32F7XX)
|
||||||
|
#include "stm32f7xx.h"
|
||||||
#elif defined(STM32F105xC)
|
#elif defined(STM32F105xC)
|
||||||
#include "stm32f1xx.h"
|
#include "stm32f1xx.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ private:
|
|||||||
uint16_t m_dataPtr;
|
uint16_t m_dataPtr;
|
||||||
uint16_t m_startPtr;
|
uint16_t m_startPtr;
|
||||||
uint16_t m_endPtr;
|
uint16_t m_endPtr;
|
||||||
|
uint16_t m_syncPtr;
|
||||||
uint16_t m_minSyncPtr;
|
uint16_t m_minSyncPtr;
|
||||||
uint16_t m_maxSyncPtr;
|
uint16_t m_maxSyncPtr;
|
||||||
uint16_t m_syncPtr;
|
|
||||||
q31_t m_maxCorr;
|
q31_t m_maxCorr;
|
||||||
uint16_t m_lostCount;
|
uint16_t m_lostCount;
|
||||||
uint8_t m_countdown;
|
uint8_t m_countdown;
|
||||||
|
|||||||
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Required amount of heap and stack */
|
||||||
|
_min_heap_size = 0x1000;
|
||||||
|
_min_stack_size = 0x0800;
|
||||||
|
|
||||||
|
/* The entry point in the interrupt vector table */
|
||||||
|
ENTRY(Reset_Handler)
|
||||||
|
|
||||||
|
/* Memory areas */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* FLASH */
|
||||||
|
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K /* Main RAM */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stack start address (end of 256K RAM) */
|
||||||
|
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
/* The interrupt vector table */
|
||||||
|
. = ALIGN(4);
|
||||||
|
KEEP(*(.isr_vector .isr_vector.*))
|
||||||
|
|
||||||
|
/* The program code */
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.text .text*)
|
||||||
|
*(.rodata .rodata*)
|
||||||
|
|
||||||
|
/* ARM-Thumb code */
|
||||||
|
*(.glue_7) *(.glue_7t)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
KEEP(*(.init))
|
||||||
|
KEEP(*(.fini))
|
||||||
|
|
||||||
|
/* EABI C++ global constructors support */
|
||||||
|
. = ALIGN(4);
|
||||||
|
__preinit_array_start = .;
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
__preinit_array_end = .;
|
||||||
|
|
||||||
|
/* EABI C++ global constructors support */
|
||||||
|
. = ALIGN(4);
|
||||||
|
__init_array_start = .;
|
||||||
|
KEEP (*(SORT(.init_array.*)))
|
||||||
|
KEEP (*(.init_array))
|
||||||
|
__init_array_end = .;
|
||||||
|
|
||||||
|
/* EABI C++ global constructors support */
|
||||||
|
. = ALIGN(4);
|
||||||
|
__fini_array_start = .;
|
||||||
|
KEEP (*(.fini_array))
|
||||||
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
|
__fini_array_end = .;
|
||||||
|
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* ARM sections containing exception unwinding information */
|
||||||
|
.ARM.extab : {
|
||||||
|
__extab_start = .;
|
||||||
|
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||||
|
__extab_end = .;
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* ARM index entries for section unwinding */
|
||||||
|
.ARM.exidx : {
|
||||||
|
__exidx_start = .;
|
||||||
|
*(.ARM.exidx*)
|
||||||
|
__exidx_end = .;
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* Start address for the initialization values of the .data section */
|
||||||
|
_sidata = .;
|
||||||
|
|
||||||
|
/* The .data section (initialized data) */
|
||||||
|
.data : AT ( _sidata )
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sdata = . ; /* Start address for the .data section */
|
||||||
|
*(.data .data*)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
_edata = . ; /* End address for the .data section */
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
/* The .bss section (uninitialized data) */
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sbss = .; /* Start address for the .bss section */
|
||||||
|
__bss_start__ = _sbss;
|
||||||
|
*(.bss)
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ebss = . ; /* End address for the .bss section */
|
||||||
|
__bss_end__ = _ebss;
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
/* Space for heap and stack */
|
||||||
|
.heap_stack :
|
||||||
|
{
|
||||||
|
end = . ; /* 'end' symbol defines heap location */
|
||||||
|
_end = end ;
|
||||||
|
. = . + _min_heap_size; /* Additional space for heap and stack */
|
||||||
|
. = . + _min_stack_size;
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
/* Remove information from the standard libraries */
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
libc.a ( * )
|
||||||
|
libm.a ( * )
|
||||||
|
libgcc.a ( * )
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Required amount of heap and stack */
|
||||||
|
_min_heap_size = 0x1000;
|
||||||
|
_min_stack_size = 0x0800;
|
||||||
|
|
||||||
|
/* The entry point in the interrupt vector table */
|
||||||
|
ENTRY(Reset_Handler)
|
||||||
|
|
||||||
|
/* Memory areas */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ROM (rx) : ORIGIN = 0x08000000, LENGTH = 2048K /* FLASH */
|
||||||
|
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K /* Main RAM */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stack start address (end of 512K RAM) */
|
||||||
|
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
/* The interrupt vector table */
|
||||||
|
. = ALIGN(4);
|
||||||
|
KEEP(*(.isr_vector .isr_vector.*))
|
||||||
|
|
||||||
|
/* The program code */
|
||||||
|
. = ALIGN(4);
|
||||||
|
*(.text .text*)
|
||||||
|
*(.rodata .rodata*)
|
||||||
|
|
||||||
|
/* ARM-Thumb code */
|
||||||
|
*(.glue_7) *(.glue_7t)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
KEEP(*(.init))
|
||||||
|
KEEP(*(.fini))
|
||||||
|
|
||||||
|
/* EABI C++ global constructors support */
|
||||||
|
. = ALIGN(4);
|
||||||
|
__preinit_array_start = .;
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
__preinit_array_end = .;
|
||||||
|
|
||||||
|
/* EABI C++ global constructors support */
|
||||||
|
. = ALIGN(4);
|
||||||
|
__init_array_start = .;
|
||||||
|
KEEP (*(SORT(.init_array.*)))
|
||||||
|
KEEP (*(.init_array))
|
||||||
|
__init_array_end = .;
|
||||||
|
|
||||||
|
/* EABI C++ global constructors support */
|
||||||
|
. = ALIGN(4);
|
||||||
|
__fini_array_start = .;
|
||||||
|
KEEP (*(.fini_array))
|
||||||
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
|
__fini_array_end = .;
|
||||||
|
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* ARM sections containing exception unwinding information */
|
||||||
|
.ARM.extab : {
|
||||||
|
__extab_start = .;
|
||||||
|
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||||
|
__extab_end = .;
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* ARM index entries for section unwinding */
|
||||||
|
.ARM.exidx : {
|
||||||
|
__exidx_start = .;
|
||||||
|
*(.ARM.exidx*)
|
||||||
|
__exidx_end = .;
|
||||||
|
} > ROM
|
||||||
|
|
||||||
|
/* Start address for the initialization values of the .data section */
|
||||||
|
_sidata = .;
|
||||||
|
|
||||||
|
/* The .data section (initialized data) */
|
||||||
|
.data : AT ( _sidata )
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sdata = . ; /* Start address for the .data section */
|
||||||
|
*(.data .data*)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
_edata = . ; /* End address for the .data section */
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
/* The .bss section (uninitialized data) */
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_sbss = .; /* Start address for the .bss section */
|
||||||
|
__bss_start__ = _sbss;
|
||||||
|
*(.bss)
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
_ebss = . ; /* End address for the .bss section */
|
||||||
|
__bss_end__ = _ebss;
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
/* Space for heap and stack */
|
||||||
|
.heap_stack :
|
||||||
|
{
|
||||||
|
end = . ; /* 'end' symbol defines heap location */
|
||||||
|
_end = end ;
|
||||||
|
. = . + _min_heap_size; /* Additional space for heap and stack */
|
||||||
|
. = . + _min_stack_size;
|
||||||
|
} > RAM
|
||||||
|
|
||||||
|
/* Remove information from the standard libraries */
|
||||||
|
/DISCARD/ :
|
||||||
|
{
|
||||||
|
libc.a ( * )
|
||||||
|
libm.a ( * )
|
||||||
|
libgcc.a ( * )
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user