From 3e45f251a25063980b1d764ac069ba39b3ff9f06 Mon Sep 17 00:00:00 2001 From: Tony Corbett G0WFV Date: Thu, 17 Nov 2016 20:01:18 +0200 Subject: [PATCH 01/22] Allow lesser Arduinos to communicate with the Nextion display --- UMP/UMP.ino | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/UMP/UMP.ino b/UMP/UMP.ino index 679a37b..bc416d5 100644 --- a/UMP/UMP.ino +++ b/UMP/UMP.ino @@ -16,20 +16,28 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) +#include +#endif + #if !defined(PIN_LED) #define PIN_LED 13 #endif -#define PIN_DSTAR 2 -#define PIN_DMR 3 -#define PIN_YSF 4 -#define PIN_P25 5 +#define PIN_DSTAR 2 +#define PIN_DMR 3 +#define PIN_YSF 4 +#define PIN_P25 5 -#define PIN_TX 6 +#define PIN_TX 6 +#define PIN_CD 7 -#define PIN_CD 7 +#define PIN_LOCKOUT 8 -#define PIN_LOCKOUT 8 +#if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) +#define SOFT_SERIAL_TX 9 +#define SOFT_SERIAL_RX 10 +#endif // Use the LOCKOUT function on the UMP // #define USE_LOCKOUT @@ -40,6 +48,9 @@ void setup() #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) Serial1.begin(9600); +#else + SoftwareSerial mySerial(SOFT_SERIAL_RX, SOFT_SERIAL_TX); // RX, TX + mySerial.begin(9600); #endif pinMode(PIN_LED, OUTPUT); @@ -121,11 +132,13 @@ void loop() case UMP_SET_CD: digitalWrite(PIN_CD, m_buffer[3U] == 0x01U ? HIGH : LOW); break; -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) case UMP_WRITE_SERIAL: +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) Serial1.write(m_buffer + 3U, m_length - 3U); - break; +#else + mySerial.write(m_buffer + 3U, m_length - 3U); #endif + break; default: break; } @@ -154,6 +167,9 @@ void loop() #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) while (Serial1.available()) Serial1.read(); +#else + while (mySerial.available()) + mySerial.read(); #endif m_count++; From d4fdd420e462d87b4e504e63dff85b46d2f0db4d Mon Sep 17 00:00:00 2001 From: Tony Corbett G0WFV Date: Thu, 17 Nov 2016 20:12:05 +0200 Subject: [PATCH 02/22] Fix schoolboy scope error --- UMP/UMP.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UMP/UMP.ino b/UMP/UMP.ino index bc416d5..cb784af 100644 --- a/UMP/UMP.ino +++ b/UMP/UMP.ino @@ -37,6 +37,8 @@ #if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) #define SOFT_SERIAL_TX 9 #define SOFT_SERIAL_RX 10 + +SoftwareSerial mySerial(SOFT_SERIAL_RX, SOFT_SERIAL_TX); // RX, TX #endif // Use the LOCKOUT function on the UMP @@ -49,7 +51,6 @@ void setup() #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) Serial1.begin(9600); #else - SoftwareSerial mySerial(SOFT_SERIAL_RX, SOFT_SERIAL_TX); // RX, TX mySerial.begin(9600); #endif From f176b54e1a0aa12f5fa0d750a594a51c1cc170a1 Mon Sep 17 00:00:00 2001 From: Tony Corbett G0WFV Date: Thu, 17 Nov 2016 20:42:10 +0200 Subject: [PATCH 03/22] Fix tabulation --- UMP/UMP.ino | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/UMP/UMP.ino b/UMP/UMP.ino index cb784af..52cf5f2 100644 --- a/UMP/UMP.ino +++ b/UMP/UMP.ino @@ -51,7 +51,7 @@ void setup() #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) Serial1.begin(9600); #else - mySerial.begin(9600); + mySerial.begin(9600); #endif pinMode(PIN_LED, OUTPUT); @@ -137,7 +137,7 @@ void loop() #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega32U4__) || defined(__SAM3X8E__) Serial1.write(m_buffer + 3U, m_length - 3U); #else - mySerial.write(m_buffer + 3U, m_length - 3U); + mySerial.write(m_buffer + 3U, m_length - 3U); #endif break; default: @@ -169,8 +169,8 @@ void loop() while (Serial1.available()) Serial1.read(); #else - while (mySerial.available()) - mySerial.read(); + while (mySerial.available()) + mySerial.read(); #endif m_count++; @@ -188,4 +188,3 @@ void loop() } } } - From cea8f0e1e6a6c6149d9a9a8f84da4959bb66e461 Mon Sep 17 00:00:00 2001 From: Tony Corbett G0WFV Date: Fri, 18 Nov 2016 19:09:05 +0200 Subject: [PATCH 04/22] Add extra if !defined statement for Teensy 3.1/3.2 and tidy up --- UMP/UMP.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/UMP/UMP.ino b/UMP/UMP.ino index 3163ff9..55f5c86 100644 --- a/UMP/UMP.ino +++ b/UMP/UMP.ino @@ -16,7 +16,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) +#if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) && !defined(__MK20DX256__) #include #endif @@ -45,7 +45,8 @@ #define PIN_LOCKOUT 8 #endif -#if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) + +#if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) && !defined(__MK20DX256__) #define SOFT_SERIAL_TX 9 #define SOFT_SERIAL_RX 10 From 5a5d73a121e3a58bfd9233c948c9b05d450de45a Mon Sep 17 00:00:00 2001 From: CT2JAY Date: Sat, 19 Nov 2016 00:38:39 +0000 Subject: [PATCH 05/22] Fix TG rewrite code for groups with 6 numbers --- DMRAccessControl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DMRAccessControl.cpp b/DMRAccessControl.cpp index 89f59f1..4fed8de 100644 --- a/DMRAccessControl.cpp +++ b/DMRAccessControl.cpp @@ -232,12 +232,12 @@ unsigned int CDMRAccessControl::dstIdRewrite(unsigned int did, unsigned int sid, } else if (m_bmAutoRewrite && did == 9U && m_dstRewriteID[slot - 1U] != 9U && m_dstRewriteID[slot - 1U] != 0U && (m_time[slot - 1U] + m_callHang) > currenttime && dmrLC->getFLCO() == FLCO_GROUP) { LogMessage("DMR Slot %u, Rewrite DST ID (TG) of outbound network traffic from %u to %u (return traffic during CallHang)", slot, did, m_dstRewriteID[slot - 1U]); return m_dstRewriteID[slot - 1U]; - } else if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did != 9U && did != 9990U && did < 99999U && dmrLC->getFLCO() == FLCO_USER_USER) { + } else if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did != 9U && did != 9990U && did < 999999U && dmrLC->getFLCO() == FLCO_USER_USER) { m_dstRewriteID[slot - 1U] = did; dmrLC->setFLCO(FLCO_GROUP); LogMessage("DMR Slot %u, Rewrite outbound private call to %u Group Call (Connect talkgroup by private call)", slot, did); return did; - } else if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did != 9U && did != 9990U && did > 99999U) { + } else if (m_bmAutoRewrite && (did < 4000U || did > 5000U) && did > 0U && did != 9U && did != 9990U && did > 999999U) { m_dstRewriteID[slot - 1U] = did; } From 2aa7018e1d6ebcea5dfd9fcadf56c76e73e107f5 Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Sat, 19 Nov 2016 10:18:03 -0300 Subject: [PATCH 06/22] Fix ADC overflow message --- Modem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modem.cpp b/Modem.cpp index 8efcb9e..5882316 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -422,7 +422,7 @@ void CModem::clock(unsigned int ms) // CUtils::dump(1U, "GET_STATUS", m_buffer, m_length); m_tx = (m_buffer[5U] & 0x01U) == 0x01U; - m_cd = (m_buffer[5U] & 0x02U) == 0x02U; + m_cd = (m_buffer[5U] & 0x40U) == 0x40U; bool adcOverflow = (m_buffer[5U] & 0x02U) == 0x02U; if (adcOverflow) From b71c2ad39fb1980bde6d20220be081d3c3b1c7cd Mon Sep 17 00:00:00 2001 From: Andy CA6JAU Date: Sat, 19 Nov 2016 10:53:49 -0300 Subject: [PATCH 07/22] Fix ADC overflow message --- Modem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modem.cpp b/Modem.cpp index 5882316..990b526 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -422,7 +422,6 @@ void CModem::clock(unsigned int ms) // CUtils::dump(1U, "GET_STATUS", m_buffer, m_length); m_tx = (m_buffer[5U] & 0x01U) == 0x01U; - m_cd = (m_buffer[5U] & 0x40U) == 0x40U; bool adcOverflow = (m_buffer[5U] & 0x02U) == 0x02U; if (adcOverflow) @@ -441,6 +440,8 @@ void CModem::clock(unsigned int ms) bool dacOverflow = (m_buffer[5U] & 0x20U) == 0x20U; if (dacOverflow) LogError("MMDVM DAC levels have overflowed"); + + m_cd = (m_buffer[5U] & 0x40U) == 0x40U; m_dstarSpace = m_buffer[6U]; m_dmrSpace1 = m_buffer[7U]; From 49706d319bb8d8ab91edf42c6a519205d25b63c4 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 20 Nov 2016 13:39:08 +0000 Subject: [PATCH 08/22] Relabel YSF VW mode audio as IMBE. --- YSFControl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/YSFControl.cpp b/YSFControl.cpp index c0a3ea7..5d23a69 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -254,7 +254,7 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) unsigned int errors = m_rfPayload.processVoiceFRModeAudio(data + 2U); m_rfErrs += errors; m_rfBits += 720U; - LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 7.2F); + LogDebug("YSF, V Mode 3, seq %u, IMBE FEC %u/720 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 7.2F); } valid = false; break; @@ -525,7 +525,7 @@ void CYSFControl::writeNetwork() // if (send) { m_netErrs += errors; m_netBits += 720U; - LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", n, errors, float(errors) / 7.2F); + LogDebug("YSF, V Mode 3, seq %u, IMBE FEC %u/720 (%.1f%%)", n, errors, float(errors) / 7.2F); // } } break; From 17b9e7e287eafee2571b30c656ddf2f23d8f0edd Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Sun, 20 Nov 2016 14:00:07 +0000 Subject: [PATCH 09/22] Rework YSF AMBE repetition FEC. --- YSFPayload.cpp | 109 +++++++++++++++++++++++++++++-------------------- YSFPayload.h | 2 + 2 files changed, 66 insertions(+), 45 deletions(-) diff --git a/YSFPayload.cpp b/YSFPayload.cpp index 253b35e..c74d7d6 100644 --- a/YSFPayload.cpp +++ b/YSFPayload.cpp @@ -393,51 +393,11 @@ unsigned int CYSFPayload::processVDMode2Audio(unsigned char* data) data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; unsigned int errors = 0U; - unsigned int offset = 40U; // DCH(0) - - // We have a total of 5 VCH sections, iterate through each - for (unsigned int j = 0U; j < 5U; j++, offset += 144U) { - unsigned char vch[13U]; - - // Deinterleave - for (unsigned int i = 0U; i < 104U; i++) { - unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT1(data, offset + n) != 0x00U; - WRITE_BIT1(vch, i, s); - } - - // "Un-whiten" (descramble) - for (unsigned int i = 0U; i < 13U; i++) - vch[i] ^= WHITENING_DATA[i]; - - // errors += READ_BIT1(vch, 103); // Padding bit must be zero but apparently it is not... - - for (unsigned int i = 0U; i < 81U; i += 3) { - uint8_t vote = bool(READ_BIT1(vch, i)) + bool(READ_BIT1(vch, i + 1)) + bool(READ_BIT1(vch, i + 2)); - if (vote == 1 || vote == 2) { - bool decision = vote / 2; // exploit integer division: 1/2 == 0, 2/2 == 1. - WRITE_BIT1(vch, i, decision); - WRITE_BIT1(vch, i + 1, decision); - WRITE_BIT1(vch, i + 2, decision); - errors++; - } - } - - // Reconstruct only if we have bit errors. Technically we could even - // constrain it individually to the 5 VCH sections. - if (errors > 0U) { - // Scramble - for (unsigned int i = 0U; i < 13U; i++) - vch[i] ^= WHITENING_DATA[i]; - - // Interleave - for (unsigned int i = 0U; i < 104U; i++) { - unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT1(vch, i); - WRITE_BIT1(data, offset + n, s); - } - } - } + errors += processVDMode2AudioBlock(data + 5U); + errors += processVDMode2AudioBlock(data + 23U); + errors += processVDMode2AudioBlock(data + 41U); + errors += processVDMode2AudioBlock(data + 59U); + errors += processVDMode2AudioBlock(data + 77U); // "errors" is the number of triplets that were recognized to be corrupted // and that were corrected. There are 27 of those per VCH and 5 VCH per CC, @@ -447,6 +407,65 @@ unsigned int CYSFPayload::processVDMode2Audio(unsigned char* data) return errors; } +unsigned int CYSFPayload::processVDMode2AudioBlock(unsigned char* data) +{ + assert(data != NULL); + + unsigned int errors = 0U; + unsigned char vch[13U]; + + // Deinterleave + for (unsigned int i = 0U; i < 104U; i++) { + unsigned int n = INTERLEAVE_TABLE_26_4[i]; + bool s = READ_BIT1(data, n); + WRITE_BIT1(vch, i, s); + } + + // "Un-whiten" (descramble) + for (unsigned int i = 0U; i < 13U; i++) + vch[i] ^= WHITENING_DATA[i]; + + for (unsigned int i = 0U; i < 81U; i += 3U) { + unsigned int n = i; + bool bit1 = READ_BIT1(vch, n); + n++; + bool bit2 = READ_BIT1(vch, n); + n++; + bool bit3 = READ_BIT1(vch, n); + + if ((bit1 && bit2 && !bit3) || (bit1 && !bit2 && bit3) || (!bit1 && bit2 && bit3)) { + unsigned int n = i; + WRITE_BIT1(vch, n, true); + n++; + WRITE_BIT1(vch, n, true); + n++; + WRITE_BIT1(vch, n, true); + errors++; + } else if ((!bit1 && !bit2 && bit3) || (!bit1 && bit2 && !bit3) || (bit1 && !bit2 && !bit3)) { + unsigned int n = i; + WRITE_BIT1(vch, n, false); + n++; + WRITE_BIT1(vch, n, false); + n++; + WRITE_BIT1(vch, n, false); + errors++; + } + } + + // Scramble + for (unsigned int i = 0U; i < 13U; i++) + vch[i] ^= WHITENING_DATA[i]; + + // Interleave + for (unsigned int i = 0U; i < 104U; i++) { + unsigned int n = INTERLEAVE_TABLE_26_4[i]; + bool s = READ_BIT1(vch, i); + WRITE_BIT1(data, n, s); + } + + return errors; +} + bool CYSFPayload::processVDMode2Data(unsigned char* data, unsigned char fn, bool gateway) { assert(data != NULL); diff --git a/YSFPayload.h b/YSFPayload.h index 8fc5061..ba14889 100644 --- a/YSFPayload.h +++ b/YSFPayload.h @@ -54,6 +54,8 @@ private: unsigned char* m_source; unsigned char* m_dest; CAMBEFEC m_fec; + + unsigned int processVDMode2AudioBlock(unsigned char* data); }; #endif From 96fd4697dda551c2f8e4de0feeae52a2e310d933 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 21 Nov 2016 17:31:32 +0000 Subject: [PATCH 10/22] Simplify repetition FEC code handling. --- YSFPayload.cpp | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/YSFPayload.cpp b/YSFPayload.cpp index c74d7d6..e6f4238 100644 --- a/YSFPayload.cpp +++ b/YSFPayload.cpp @@ -417,7 +417,7 @@ unsigned int CYSFPayload::processVDMode2AudioBlock(unsigned char* data) // Deinterleave for (unsigned int i = 0U; i < 104U; i++) { unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT1(data, n); + bool s = READ_BIT1(data, n) != 0x00U; WRITE_BIT1(vch, i, s); } @@ -426,29 +426,35 @@ unsigned int CYSFPayload::processVDMode2AudioBlock(unsigned char* data) vch[i] ^= WHITENING_DATA[i]; for (unsigned int i = 0U; i < 81U; i += 3U) { - unsigned int n = i; - bool bit1 = READ_BIT1(vch, n); - n++; - bool bit2 = READ_BIT1(vch, n); - n++; - bool bit3 = READ_BIT1(vch, n); + unsigned int n1 = i + 0U; + unsigned int n2 = i + 1U; + unsigned int n3 = i + 2U; - if ((bit1 && bit2 && !bit3) || (bit1 && !bit2 && bit3) || (!bit1 && bit2 && bit3)) { - unsigned int n = i; - WRITE_BIT1(vch, n, true); - n++; - WRITE_BIT1(vch, n, true); - n++; - WRITE_BIT1(vch, n, true); + unsigned char code = READ_BIT1(vch, n1) ? 1U : 0U + + READ_BIT1(vch, n2) ? 2U : 0U + + READ_BIT1(vch, n3) ? 4U : 0U; + + switch (code) { + case 3U: + case 5U: + case 6U: + WRITE_BIT1(vch, n1, true); + WRITE_BIT1(vch, n2, true); + WRITE_BIT1(vch, n3, true); errors++; - } else if ((!bit1 && !bit2 && bit3) || (!bit1 && bit2 && !bit3) || (bit1 && !bit2 && !bit3)) { - unsigned int n = i; - WRITE_BIT1(vch, n, false); - n++; - WRITE_BIT1(vch, n, false); - n++; - WRITE_BIT1(vch, n, false); + break; + case 1U: + case 2U: + case 4U: + WRITE_BIT1(vch, n1, false); + WRITE_BIT1(vch, n2, false); + WRITE_BIT1(vch, n3, false); errors++; + break; + // case 0U: + // case 7U: + default: + break; } } @@ -459,7 +465,7 @@ unsigned int CYSFPayload::processVDMode2AudioBlock(unsigned char* data) // Interleave for (unsigned int i = 0U; i < 104U; i++) { unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT1(vch, i); + bool s = READ_BIT1(vch, i) != 0x00U; WRITE_BIT1(data, n, s); } From 1b7fbf719731d675985c2ea5935383a6e81a91ce Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 21 Nov 2016 17:32:01 +0000 Subject: [PATCH 11/22] Fix MD-390 GPS data block count. --- DMRDataHeader.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/DMRDataHeader.cpp b/DMRDataHeader.cpp index ef0922d..246ba4e 100644 --- a/DMRDataHeader.cpp +++ b/DMRDataHeader.cpp @@ -29,6 +29,8 @@ #include #include +const unsigned char UDTF_NMEA = 0x05U; + CDMRDataHeader::CDMRDataHeader() : m_data(NULL), m_GI(false), @@ -78,13 +80,13 @@ bool CDMRDataHeader::put(const unsigned char* bytes) switch (dpf) { case DPF_UNCONFIRMED_DATA: - CUtils::dump(1U, "Unconfirmed Data Header", m_data, 12U); + CUtils::dump(1U, "DMR, Unconfirmed Data Header", m_data, 12U); m_F = (m_data[8U] & 0x80U) == 0x80U; m_blocks = m_data[8U] & 0x7FU; break; case DPF_CONFIRMED_DATA: - CUtils::dump(1U, "Confirmed Data Header", m_data, 12U); + CUtils::dump(1U, "DMR, Confirmed Data Header", m_data, 12U); m_F = (m_data[8U] & 0x80U) == 0x80U; m_blocks = m_data[8U] & 0x7FU; m_S = (m_data[9U] & 0x80U) == 0x80U; @@ -92,38 +94,46 @@ bool CDMRDataHeader::put(const unsigned char* bytes) break; case DPF_RESPONSE: - CUtils::dump(1U, "Response Data Header", m_data, 12U); + CUtils::dump(1U, "DMR, Response Data Header", m_data, 12U); m_blocks = m_data[8U] & 0x7FU; break; case DPF_PROPRIETARY: - CUtils::dump(1U, "Proprietary Data Header", m_data, 12U); + CUtils::dump(1U, "DMR, Proprietary Data Header", m_data, 12U); break; case DPF_DEFINED_RAW: - CUtils::dump(1U, "Raw or Status/Precoded Short Data Header", m_data, 12U); + CUtils::dump(1U, "DMR, Raw or Status/Precoded Short Data Header", m_data, 12U); m_blocks = (m_data[0U] & 0x30U) + (m_data[1U] & 0x0FU); m_F = (m_data[8U] & 0x01U) == 0x01U; m_S = (m_data[8U] & 0x02U) == 0x02U; break; case DPF_DEFINED_SHORT: - CUtils::dump(1U, "Defined Short Data Header", m_data, 12U); + CUtils::dump(1U, "DMR, Defined Short Data Header", m_data, 12U); m_blocks = (m_data[0U] & 0x30U) + (m_data[1U] & 0x0FU); m_F = (m_data[8U] & 0x01U) == 0x01U; m_S = (m_data[8U] & 0x02U) == 0x02U; break; case DPF_UDT: - CUtils::dump(1U, "Unified Data Transport Header", m_data, 12U); + CUtils::dump(1U, "DMR, Unified Data Transport Header", m_data, 12U); m_blocks = m_data[8U] & 0x03U; break; default: - CUtils::dump("Unknown Data Header", m_data, 12U); + CUtils::dump("DMR, Unknown Data Header", m_data, 12U); break; } + if (dpf == DPF_UDT && m_blocks == 0U) { + unsigned char format = m_data[1U] & 0x0FU; + if (format == UDTF_NMEA) { + LogDebug("DMR, fixing broken Tytera MD-390 GPS data block count"); + m_blocks = 2U; + } + } + return true; } From 69a61ae4dc35901f10a8222e327a0619beaac65b Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 21 Nov 2016 21:38:15 +0000 Subject: [PATCH 12/22] Tweak the UMP for the Teensy 3.1/3.2 --- UMP/UMP.ino | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/UMP/UMP.ino b/UMP/UMP.ino index 501737b..3b4b0d6 100644 --- a/UMP/UMP.ino +++ b/UMP/UMP.ino @@ -21,15 +21,17 @@ #endif #if defined(__MK20DX256__) -#define PIN_DSTAR 2 -#define PIN_DMR 3 -#define PIN_YSF 4 -#define PIN_P25 5 +#define PIN_DSTAR 3 +#define PIN_DMR 4 +#define PIN_YSF 5 +#define PIN_P25 6 #define PIN_TX 10 #define PIN_CD 11 #define PIN_LOCKOUT 12 + +#define FLASH_DELAY 200000U #else #define PIN_DSTAR 2 #define PIN_DMR 3 @@ -40,6 +42,8 @@ #define PIN_CD 7 #define PIN_LOCKOUT 8 + +#define FLASH_DELAY 3200U #endif // Use the LOCKOUT function on the UMP @@ -169,13 +173,13 @@ void loop() m_count++; if (m_started) { - if (m_count > 3200U) { + if (m_count > FLASH_DELAY) { digitalWrite(PIN_LED, m_led ? LOW : HIGH); m_led = !m_led; m_count = 0U; } } else { - if (m_count > 32000U) { + if (m_count > (FLASH_DELAY * 3U)) { digitalWrite(PIN_LED, m_led ? LOW : HIGH); m_led = !m_led; m_count = 0U; From 56487dd5292ac0070ca318be68424c2d94546b19 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 21 Nov 2016 23:37:05 +0000 Subject: [PATCH 13/22] Increase number of data blocks for MD-390 GPS data. --- DMRDataHeader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DMRDataHeader.cpp b/DMRDataHeader.cpp index 246ba4e..d1864a5 100644 --- a/DMRDataHeader.cpp +++ b/DMRDataHeader.cpp @@ -130,7 +130,7 @@ bool CDMRDataHeader::put(const unsigned char* bytes) unsigned char format = m_data[1U] & 0x0FU; if (format == UDTF_NMEA) { LogDebug("DMR, fixing broken Tytera MD-390 GPS data block count"); - m_blocks = 2U; + m_blocks = 3U; } } From beb9a7d5453265968da44e3433f2ddd9c1671436 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 22 Nov 2016 07:52:47 +0000 Subject: [PATCH 14/22] Handle failed displays more gracefully. --- MMDVMHost.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index b2faa0d..6b495db 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -1144,6 +1144,12 @@ void CMMDVMHost::createDisplay() m_display = new CNullDisplay; } + if (m_display == NULL) { + LogWarning("No valid display found, disabling"); + m_display = new CNullDisplay; + return; + } + bool ret = m_display->open(); if (!ret) { delete m_display; From 93dd989eb176e8493e04cef72a124a41f6f43cdc Mon Sep 17 00:00:00 2001 From: Tony Corbett G0WFV Date: Tue, 22 Nov 2016 23:14:03 +0200 Subject: [PATCH 15/22] Try another software serial library ... --- UMP/UMP.ino | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/UMP/UMP.ino b/UMP/UMP.ino index 607d653..8e0f595 100644 --- a/UMP/UMP.ino +++ b/UMP/UMP.ino @@ -17,7 +17,7 @@ */ #if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) && !defined(__MK20DX256__) -#include +#include #endif #if !defined(PIN_LED) @@ -45,16 +45,13 @@ #define PIN_TX 6 #define PIN_CD 7 -#define PIN_LOCKOUT 8 +#define PIN_LOCKOUT 10 #define FLASH_DELAY 3200U #endif #if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(__AVR_ATmega32U4__) && !defined(__SAM3X8E__) && !defined(__MK20DX256__) -#define SOFT_SERIAL_TX 9 -#define SOFT_SERIAL_RX 10 - -SoftwareSerial mySerial(SOFT_SERIAL_RX, SOFT_SERIAL_TX); // RX, TX +AltSoftSerial mySerial; #endif // Use the LOCKOUT function on the UMP From 11e75abf86506710a36c1dd791b5df03dd869c52 Mon Sep 17 00:00:00 2001 From: Tony Corbett G0WFV Date: Tue, 22 Nov 2016 23:35:37 +0200 Subject: [PATCH 16/22] Move LOCKOUT to pin 12 to accommodate the AltSoftSerial Library --- UMP/UMP.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UMP/UMP.ino b/UMP/UMP.ino index 8e0f595..a0c99aa 100644 --- a/UMP/UMP.ino +++ b/UMP/UMP.ino @@ -45,7 +45,7 @@ #define PIN_TX 6 #define PIN_CD 7 -#define PIN_LOCKOUT 10 +#define PIN_LOCKOUT 12 #define FLASH_DELAY 3200U #endif From f364eda0a498f6428a850b462c5d4552fa39a25a Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 22 Nov 2016 21:50:59 +0000 Subject: [PATCH 17/22] Revert "Simplify repetition FEC code handling." This reverts commit 96fd4697dda551c2f8e4de0feeae52a2e310d933. --- YSFPayload.cpp | 50 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/YSFPayload.cpp b/YSFPayload.cpp index e6f4238..c74d7d6 100644 --- a/YSFPayload.cpp +++ b/YSFPayload.cpp @@ -417,7 +417,7 @@ unsigned int CYSFPayload::processVDMode2AudioBlock(unsigned char* data) // Deinterleave for (unsigned int i = 0U; i < 104U; i++) { unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT1(data, n) != 0x00U; + bool s = READ_BIT1(data, n); WRITE_BIT1(vch, i, s); } @@ -426,35 +426,29 @@ unsigned int CYSFPayload::processVDMode2AudioBlock(unsigned char* data) vch[i] ^= WHITENING_DATA[i]; for (unsigned int i = 0U; i < 81U; i += 3U) { - unsigned int n1 = i + 0U; - unsigned int n2 = i + 1U; - unsigned int n3 = i + 2U; + unsigned int n = i; + bool bit1 = READ_BIT1(vch, n); + n++; + bool bit2 = READ_BIT1(vch, n); + n++; + bool bit3 = READ_BIT1(vch, n); - unsigned char code = READ_BIT1(vch, n1) ? 1U : 0U + - READ_BIT1(vch, n2) ? 2U : 0U + - READ_BIT1(vch, n3) ? 4U : 0U; - - switch (code) { - case 3U: - case 5U: - case 6U: - WRITE_BIT1(vch, n1, true); - WRITE_BIT1(vch, n2, true); - WRITE_BIT1(vch, n3, true); + if ((bit1 && bit2 && !bit3) || (bit1 && !bit2 && bit3) || (!bit1 && bit2 && bit3)) { + unsigned int n = i; + WRITE_BIT1(vch, n, true); + n++; + WRITE_BIT1(vch, n, true); + n++; + WRITE_BIT1(vch, n, true); errors++; - break; - case 1U: - case 2U: - case 4U: - WRITE_BIT1(vch, n1, false); - WRITE_BIT1(vch, n2, false); - WRITE_BIT1(vch, n3, false); + } else if ((!bit1 && !bit2 && bit3) || (!bit1 && bit2 && !bit3) || (bit1 && !bit2 && !bit3)) { + unsigned int n = i; + WRITE_BIT1(vch, n, false); + n++; + WRITE_BIT1(vch, n, false); + n++; + WRITE_BIT1(vch, n, false); errors++; - break; - // case 0U: - // case 7U: - default: - break; } } @@ -465,7 +459,7 @@ unsigned int CYSFPayload::processVDMode2AudioBlock(unsigned char* data) // Interleave for (unsigned int i = 0U; i < 104U; i++) { unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT1(vch, i) != 0x00U; + bool s = READ_BIT1(vch, i); WRITE_BIT1(data, n, s); } From fee3cf561ced0ef5f2d8021be3cf7b237f6f1e25 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 22 Nov 2016 21:51:40 +0000 Subject: [PATCH 18/22] Revert "Rework YSF AMBE repetition FEC." This reverts commit 17b9e7e287eafee2571b30c656ddf2f23d8f0edd. --- YSFPayload.cpp | 109 ++++++++++++++++++++----------------------------- YSFPayload.h | 2 - 2 files changed, 45 insertions(+), 66 deletions(-) diff --git a/YSFPayload.cpp b/YSFPayload.cpp index c74d7d6..253b35e 100644 --- a/YSFPayload.cpp +++ b/YSFPayload.cpp @@ -393,11 +393,51 @@ unsigned int CYSFPayload::processVDMode2Audio(unsigned char* data) data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; unsigned int errors = 0U; - errors += processVDMode2AudioBlock(data + 5U); - errors += processVDMode2AudioBlock(data + 23U); - errors += processVDMode2AudioBlock(data + 41U); - errors += processVDMode2AudioBlock(data + 59U); - errors += processVDMode2AudioBlock(data + 77U); + unsigned int offset = 40U; // DCH(0) + + // We have a total of 5 VCH sections, iterate through each + for (unsigned int j = 0U; j < 5U; j++, offset += 144U) { + unsigned char vch[13U]; + + // Deinterleave + for (unsigned int i = 0U; i < 104U; i++) { + unsigned int n = INTERLEAVE_TABLE_26_4[i]; + bool s = READ_BIT1(data, offset + n) != 0x00U; + WRITE_BIT1(vch, i, s); + } + + // "Un-whiten" (descramble) + for (unsigned int i = 0U; i < 13U; i++) + vch[i] ^= WHITENING_DATA[i]; + + // errors += READ_BIT1(vch, 103); // Padding bit must be zero but apparently it is not... + + for (unsigned int i = 0U; i < 81U; i += 3) { + uint8_t vote = bool(READ_BIT1(vch, i)) + bool(READ_BIT1(vch, i + 1)) + bool(READ_BIT1(vch, i + 2)); + if (vote == 1 || vote == 2) { + bool decision = vote / 2; // exploit integer division: 1/2 == 0, 2/2 == 1. + WRITE_BIT1(vch, i, decision); + WRITE_BIT1(vch, i + 1, decision); + WRITE_BIT1(vch, i + 2, decision); + errors++; + } + } + + // Reconstruct only if we have bit errors. Technically we could even + // constrain it individually to the 5 VCH sections. + if (errors > 0U) { + // Scramble + for (unsigned int i = 0U; i < 13U; i++) + vch[i] ^= WHITENING_DATA[i]; + + // Interleave + for (unsigned int i = 0U; i < 104U; i++) { + unsigned int n = INTERLEAVE_TABLE_26_4[i]; + bool s = READ_BIT1(vch, i); + WRITE_BIT1(data, offset + n, s); + } + } + } // "errors" is the number of triplets that were recognized to be corrupted // and that were corrected. There are 27 of those per VCH and 5 VCH per CC, @@ -407,65 +447,6 @@ unsigned int CYSFPayload::processVDMode2Audio(unsigned char* data) return errors; } -unsigned int CYSFPayload::processVDMode2AudioBlock(unsigned char* data) -{ - assert(data != NULL); - - unsigned int errors = 0U; - unsigned char vch[13U]; - - // Deinterleave - for (unsigned int i = 0U; i < 104U; i++) { - unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT1(data, n); - WRITE_BIT1(vch, i, s); - } - - // "Un-whiten" (descramble) - for (unsigned int i = 0U; i < 13U; i++) - vch[i] ^= WHITENING_DATA[i]; - - for (unsigned int i = 0U; i < 81U; i += 3U) { - unsigned int n = i; - bool bit1 = READ_BIT1(vch, n); - n++; - bool bit2 = READ_BIT1(vch, n); - n++; - bool bit3 = READ_BIT1(vch, n); - - if ((bit1 && bit2 && !bit3) || (bit1 && !bit2 && bit3) || (!bit1 && bit2 && bit3)) { - unsigned int n = i; - WRITE_BIT1(vch, n, true); - n++; - WRITE_BIT1(vch, n, true); - n++; - WRITE_BIT1(vch, n, true); - errors++; - } else if ((!bit1 && !bit2 && bit3) || (!bit1 && bit2 && !bit3) || (bit1 && !bit2 && !bit3)) { - unsigned int n = i; - WRITE_BIT1(vch, n, false); - n++; - WRITE_BIT1(vch, n, false); - n++; - WRITE_BIT1(vch, n, false); - errors++; - } - } - - // Scramble - for (unsigned int i = 0U; i < 13U; i++) - vch[i] ^= WHITENING_DATA[i]; - - // Interleave - for (unsigned int i = 0U; i < 104U; i++) { - unsigned int n = INTERLEAVE_TABLE_26_4[i]; - bool s = READ_BIT1(vch, i); - WRITE_BIT1(data, n, s); - } - - return errors; -} - bool CYSFPayload::processVDMode2Data(unsigned char* data, unsigned char fn, bool gateway) { assert(data != NULL); diff --git a/YSFPayload.h b/YSFPayload.h index ba14889..8fc5061 100644 --- a/YSFPayload.h +++ b/YSFPayload.h @@ -54,8 +54,6 @@ private: unsigned char* m_source; unsigned char* m_dest; CAMBEFEC m_fec; - - unsigned int processVDMode2AudioBlock(unsigned char* data); }; #endif From 7a57992275ab3b1ead10527aeb2aa8d65e1e60c1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 24 Nov 2016 10:18:28 +0000 Subject: [PATCH 19/22] Cap the height and power so that the config message isn't corrupted. --- DMRNetwork.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/DMRNetwork.cpp b/DMRNetwork.cpp index f902d2f..1bd016a 100644 --- a/DMRNetwork.cpp +++ b/DMRNetwork.cpp @@ -522,8 +522,16 @@ bool CDMRNetwork::writeConfig() char longitude[20U]; ::sprintf(longitude, "%09f", m_longitude); + unsigned int power = m_power; + if (power > 99U) + power = 99U; + + int height = m_height; + if (height > 999U) + height = 99U; + ::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(), - m_rxFrequency, m_txFrequency, m_power, m_colorCode, latitude, longitude, m_height, m_location.c_str(), + m_rxFrequency, m_txFrequency, power, m_colorCode, latitude, longitude, height, m_location.c_str(), m_description.c_str(), slots, m_url.c_str(), m_version, software); return write((unsigned char*)buffer, 302U); From af33f1d7571bc1e7e02bcaf8a0394203deba0380 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 24 Nov 2016 10:20:04 +0000 Subject: [PATCH 20/22] Mistake in the height capping. --- DMRNetwork.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DMRNetwork.cpp b/DMRNetwork.cpp index 1bd016a..6bb182f 100644 --- a/DMRNetwork.cpp +++ b/DMRNetwork.cpp @@ -527,8 +527,8 @@ bool CDMRNetwork::writeConfig() power = 99U; int height = m_height; - if (height > 999U) - height = 99U; + if (height > 999) + height = 999; ::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(), m_rxFrequency, m_txFrequency, power, m_colorCode, latitude, longitude, height, m_location.c_str(), From 98d6330597deea33d7a42d6b66c647eb8cc70bea Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 24 Nov 2016 16:00:04 +0000 Subject: [PATCH 21/22] VW mode isn't IMBE, it's AMBE, change messages accordingly. --- YSFControl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/YSFControl.cpp b/YSFControl.cpp index 5d23a69..c0a3ea7 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -254,7 +254,7 @@ bool CYSFControl::writeModem(unsigned char *data, unsigned int len) unsigned int errors = m_rfPayload.processVoiceFRModeAudio(data + 2U); m_rfErrs += errors; m_rfBits += 720U; - LogDebug("YSF, V Mode 3, seq %u, IMBE FEC %u/720 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 7.2F); + LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 7.2F); } valid = false; break; @@ -525,7 +525,7 @@ void CYSFControl::writeNetwork() // if (send) { m_netErrs += errors; m_netBits += 720U; - LogDebug("YSF, V Mode 3, seq %u, IMBE FEC %u/720 (%.1f%%)", n, errors, float(errors) / 7.2F); + LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/720 (%.1f%%)", n, errors, float(errors) / 7.2F); // } } break; From 8a52564f5e7a8351b0454d8fd163846d89543acf Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 24 Nov 2016 17:47:53 +0000 Subject: [PATCH 22/22] Bump the version date. --- Version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Version.h b/Version.h index 865c176..3bce33e 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20161021"; +const char* VERSION = "20161124"; #endif