mirror of
https://github.com/juribeparada/MMDVM_HS.git
synced 2025-12-06 07:12:08 +01:00
First commit
This commit is contained in:
commit
587fe63a47
254
ADF7021.cpp
Normal file
254
ADF7021.cpp
Normal file
|
|
@ -0,0 +1,254 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
* Copyright (C) 2016, 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"
|
||||||
|
|
||||||
|
#if defined(ADF7021)
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "IO.h"
|
||||||
|
#include "ADF7021.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
volatile uint32_t AD7021_control_byte;
|
||||||
|
volatile int AD7021_counter;
|
||||||
|
|
||||||
|
void dlybit(void)
|
||||||
|
{
|
||||||
|
volatile unsigned int delay;
|
||||||
|
for(delay = 0;delay<5;delay++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Send_AD7021_control()
|
||||||
|
{
|
||||||
|
for(AD7021_counter = 31; AD7021_counter >= 0; AD7021_counter--) {
|
||||||
|
if(bitRead(AD7021_control_byte, AD7021_counter) == HIGH)
|
||||||
|
io.SDATA_pin(HIGH);
|
||||||
|
else
|
||||||
|
io.SDATA_pin(LOW);
|
||||||
|
|
||||||
|
io.SCLK_pin(HIGH);
|
||||||
|
dlybit();
|
||||||
|
io.SCLK_pin(LOW);
|
||||||
|
dlybit();
|
||||||
|
}
|
||||||
|
|
||||||
|
io.SLE_pin(HIGH);
|
||||||
|
dlybit();
|
||||||
|
io.SLE_pin(LOW);
|
||||||
|
io.SDATA_pin(LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Send_REG0_RX()
|
||||||
|
{
|
||||||
|
uint32_t ADF7021_RX_REG0;
|
||||||
|
float divider;
|
||||||
|
uint8_t N_divider;
|
||||||
|
uint16_t F_divider;
|
||||||
|
|
||||||
|
divider = (m_frequency_rx - 100000) / (ADF7021_PFD / 2.0);
|
||||||
|
|
||||||
|
N_divider = floor(divider);
|
||||||
|
divider = (divider - N_divider) * 32768;
|
||||||
|
F_divider = floor(divider + 0.5);
|
||||||
|
|
||||||
|
ADF7021_RX_REG0 = (uint32_t)0b0000;
|
||||||
|
ADF7021_RX_REG0 |= (uint32_t)0b01011 << 27; // mux regulator/uart enabled/receive
|
||||||
|
ADF7021_RX_REG0 |= (uint32_t)N_divider << 19; //frequency;
|
||||||
|
ADF7021_RX_REG0 |= (uint32_t)F_divider << 4; //frequency;
|
||||||
|
|
||||||
|
AD7021_control_byte = ADF7021_RX_REG0;
|
||||||
|
Send_AD7021_control();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Send_REG0_TX()
|
||||||
|
{
|
||||||
|
uint32_t ADF7021_TX_REG0;
|
||||||
|
float divider;
|
||||||
|
uint8_t N_divider;
|
||||||
|
uint16_t F_divider;
|
||||||
|
|
||||||
|
divider = m_frequency_tx / (ADF7021_PFD / 2.0);
|
||||||
|
|
||||||
|
N_divider = floor(divider);
|
||||||
|
divider = (divider - N_divider) * 32768;
|
||||||
|
F_divider = floor(divider + 0.5);
|
||||||
|
|
||||||
|
ADF7021_TX_REG0 = (uint32_t)0b0000; // register 0
|
||||||
|
ADF7021_TX_REG0 |= (uint32_t)0b01010 << 27; // mux regulator/uart enabled/transmit
|
||||||
|
ADF7021_TX_REG0 |= (uint32_t)N_divider << 19; //frequency;
|
||||||
|
ADF7021_TX_REG0 |= (uint32_t)F_divider << 4; //frequency;
|
||||||
|
|
||||||
|
AD7021_control_byte = ADF7021_TX_REG0;
|
||||||
|
Send_AD7021_control();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::ifConf()
|
||||||
|
{
|
||||||
|
uint32_t ADF7021_REG2 = 0;
|
||||||
|
uint32_t ADF7021_REG3 = 0;
|
||||||
|
uint32_t ADF7021_REG4 = 0;
|
||||||
|
uint32_t ADF7021_REG13 = 0;
|
||||||
|
|
||||||
|
if (m_dstarEnable) {
|
||||||
|
// Dev: 1200 Hz, symb rate = 4800
|
||||||
|
|
||||||
|
ADF7021_REG3 = 0x2A4C4193;
|
||||||
|
ADF7021_REG4 = 0x00A82A94;
|
||||||
|
ADF7021_REG13 = 0x0000000D;
|
||||||
|
|
||||||
|
ADF7021_REG2 = (uint32_t)0b00 << 28; // clock normal
|
||||||
|
ADF7021_REG2 |= (uint32_t)0b000101010 << 19; // deviation
|
||||||
|
ADF7021_REG2 |= (uint32_t)0b001 << 4; // modulation (GMSK)
|
||||||
|
}
|
||||||
|
else if (m_dmrEnable) {
|
||||||
|
// Dev: +1 symb 648 Hz, symb rate = 4800
|
||||||
|
|
||||||
|
ADF7021_REG3 = 0x2A4C80D3;
|
||||||
|
|
||||||
|
// K=32
|
||||||
|
ADF7021_REG4 = (uint32_t)0b0100 << 0; // register 4
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b011 << 4; // mode, 4FSK
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b0 << 7;
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b11 << 8;
|
||||||
|
ADF7021_REG4 |= (uint32_t)393U << 10; // Disc BW
|
||||||
|
ADF7021_REG4 |= (uint32_t)65U << 20; // Post dem BW
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b10 << 30; // IF filter
|
||||||
|
|
||||||
|
ADF7021_REG13 = 0x0000033D;
|
||||||
|
|
||||||
|
ADF7021_REG2 = (uint32_t)0b10 << 28; // invert data
|
||||||
|
ADF7021_REG2 |= (uint32_t)24U << 19; // deviation
|
||||||
|
ADF7021_REG2 |= (uint32_t)0b111 << 4; // modulation (4FSK)
|
||||||
|
}
|
||||||
|
else if (m_ysfEnable) {
|
||||||
|
// Dev: +1 symb 900 Hz, symb rate = 4800
|
||||||
|
|
||||||
|
ADF7021_REG3 = 0x2A4C80D3;
|
||||||
|
|
||||||
|
// K=28
|
||||||
|
ADF7021_REG4 = (uint32_t)0b0100 << 0; // register 4
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b011 << 4; // mode, 4FSK
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b0 << 7;
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b11 << 8;
|
||||||
|
ADF7021_REG4 |= (uint32_t)344U << 10; // Disc BW
|
||||||
|
ADF7021_REG4 |= (uint32_t)65U << 20; // Post dem BW
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b10 << 30; // IF filter
|
||||||
|
|
||||||
|
ADF7021_REG13 = 0x000003BD;
|
||||||
|
|
||||||
|
ADF7021_REG2 = (uint32_t)0b10 << 28; // invert data
|
||||||
|
ADF7021_REG2 |= (uint32_t)32U << 19; // deviation
|
||||||
|
ADF7021_REG2 |= (uint32_t)0b111 << 4; // modulation (4FSK)
|
||||||
|
}
|
||||||
|
else if (m_p25Enable) {
|
||||||
|
// Dev: +1 symb 600 Hz, symb rate = 4800
|
||||||
|
|
||||||
|
ADF7021_REG3 = 0x2A4C80D3;
|
||||||
|
|
||||||
|
// K=32
|
||||||
|
ADF7021_REG4 = (uint32_t)0b0100 << 0; // register 4
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b011 << 4; // mode, 4FSK
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b0 << 7;
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b11 << 8;
|
||||||
|
ADF7021_REG4 |= (uint32_t)393U << 10; // Disc BW
|
||||||
|
ADF7021_REG4 |= (uint32_t)65U << 20; // Post dem BW
|
||||||
|
ADF7021_REG4 |= (uint32_t)0b10 << 30; // IF filter
|
||||||
|
|
||||||
|
ADF7021_REG13 = 0x000002DD;
|
||||||
|
|
||||||
|
ADF7021_REG2 = (uint32_t)0b10 << 28; // invert data
|
||||||
|
ADF7021_REG2 |= (uint32_t)22U << 19; // deviation
|
||||||
|
ADF7021_REG2 |= (uint32_t)0b111 << 4; // modulation (4FSK)
|
||||||
|
}
|
||||||
|
|
||||||
|
// VCO/OSCILLATOR (REG1)
|
||||||
|
if( (m_frequency_tx >= VHF_MIN) && (m_frequency_tx < VHF_MAX) )
|
||||||
|
AD7021_control_byte = 0x021F5041; // VHF, external VCO
|
||||||
|
else if( (m_frequency_tx >= UHF_MIN)&&(m_frequency_tx < UHF_MAX) )
|
||||||
|
AD7021_control_byte = 0x00575041; // UHF, internal VCO
|
||||||
|
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// TX/RX CLOCK (3)
|
||||||
|
AD7021_control_byte = ADF7021_REG3;
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// DEMOD (4)
|
||||||
|
AD7021_control_byte = ADF7021_REG4;
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// IF FILTER (5)
|
||||||
|
AD7021_control_byte = 0x000024F5;
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// MODULATION (2)
|
||||||
|
ADF7021_REG2 |= (uint32_t)0b0010; // register 2
|
||||||
|
ADF7021_REG2 |= (uint32_t)m_power << 13; // power level
|
||||||
|
ADF7021_REG2 |= (uint32_t)0b110001 << 7; // PA
|
||||||
|
AD7021_control_byte = ADF7021_REG2;
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// TEST MODE (disabled) (15)
|
||||||
|
AD7021_control_byte = 0x000E000F;
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// IF FINE CAL (fine cal, defaults) (6)
|
||||||
|
AD7021_control_byte = 0x05080B16;
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// AGC (auto, defaults) (9)
|
||||||
|
AD7021_control_byte = 0x000231E9; // auto
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// AFC (off, defaults) (10)
|
||||||
|
AD7021_control_byte = 0x3296472A; // off
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// SYNC WORD DET (11)
|
||||||
|
AD7021_control_byte = 0x0000003B;
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// SWD/THRESHOLD (12)
|
||||||
|
AD7021_control_byte = 0x0000010C;
|
||||||
|
Send_AD7021_control();
|
||||||
|
|
||||||
|
// 3FSK/4FSK DEMOD (13)
|
||||||
|
AD7021_control_byte = ADF7021_REG13;
|
||||||
|
Send_AD7021_control();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================================================================
|
||||||
|
void CIO::setTX()
|
||||||
|
{
|
||||||
|
PTT_pin(HIGH);
|
||||||
|
LED_pin(LOW);
|
||||||
|
Send_REG0_TX();
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================================================================
|
||||||
|
void CIO::setRX()
|
||||||
|
{
|
||||||
|
PTT_pin(LOW);
|
||||||
|
LED_pin(HIGH);
|
||||||
|
delay_rx();
|
||||||
|
Send_REG0_RX();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
38
ADF7021.h
Normal file
38
ADF7021.h
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
* Copyright (C) 2016, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(ADF7021_H)
|
||||||
|
#define ADF7021_H
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#if defined(ADF7021)
|
||||||
|
|
||||||
|
#define ADF7021_PFD 3686400.0
|
||||||
|
|
||||||
|
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
|
|
||||||
|
void dlybit(void);
|
||||||
|
void Send_AD7021_control(void);
|
||||||
|
void Send_REG0_RX(void);
|
||||||
|
void Send_REG0_TX(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
104
BitRB.cpp
Normal file
104
BitRB.cpp
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
TX fifo control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BitRB.h"
|
||||||
|
|
||||||
|
CBitRB::CBitRB(uint16_t length) :
|
||||||
|
m_length(length),
|
||||||
|
m_bits(NULL),
|
||||||
|
m_head(0U),
|
||||||
|
m_tail(0U),
|
||||||
|
m_full(false),
|
||||||
|
m_overflow(false)
|
||||||
|
{
|
||||||
|
m_bits = new uint8_t[length];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CBitRB::getSpace() const
|
||||||
|
{
|
||||||
|
uint16_t n = 0U;
|
||||||
|
|
||||||
|
if (m_tail == m_head)
|
||||||
|
n = m_full ? 0U : m_length;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
n = m_length - m_head + m_tail;
|
||||||
|
else
|
||||||
|
n = m_tail - m_head;
|
||||||
|
|
||||||
|
if (n > m_length)
|
||||||
|
n = 0U;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CBitRB::getData() const
|
||||||
|
{
|
||||||
|
if (m_tail == m_head)
|
||||||
|
return m_full ? m_length : 0U;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
return m_head - m_tail;
|
||||||
|
else
|
||||||
|
return m_length - m_tail + m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBitRB::put(uint8_t bit)
|
||||||
|
{
|
||||||
|
if (m_full) {
|
||||||
|
m_overflow = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bits[m_head] = bit;
|
||||||
|
|
||||||
|
m_head++;
|
||||||
|
if (m_head >= m_length)
|
||||||
|
m_head = 0U;
|
||||||
|
|
||||||
|
if (m_head == m_tail)
|
||||||
|
m_full = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBitRB::get(uint8_t& bit)
|
||||||
|
{
|
||||||
|
if (m_head == m_tail && !m_full)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bit = m_bits[m_tail];
|
||||||
|
|
||||||
|
m_full = false;
|
||||||
|
|
||||||
|
m_tail++;
|
||||||
|
if (m_tail >= m_length)
|
||||||
|
m_tail = 0U;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBitRB::hasOverflowed()
|
||||||
|
{
|
||||||
|
bool overflow = m_overflow;
|
||||||
|
|
||||||
|
m_overflow = false;
|
||||||
|
|
||||||
|
return overflow;
|
||||||
|
}
|
||||||
|
|
||||||
55
BitRB.h
Normal file
55
BitRB.h
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
Serial fifo control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(BITRB_H)
|
||||||
|
#define BITRB_H
|
||||||
|
|
||||||
|
#if defined(STM32F10X_MD)
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#else
|
||||||
|
#include <Arduino.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CBitRB {
|
||||||
|
public:
|
||||||
|
CBitRB(uint16_t length);
|
||||||
|
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
|
uint16_t getData() const;
|
||||||
|
|
||||||
|
bool put(uint8_t bit);
|
||||||
|
|
||||||
|
bool get(uint8_t& bit);
|
||||||
|
|
||||||
|
bool hasOverflowed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t m_length;
|
||||||
|
volatile uint8_t* m_bits;
|
||||||
|
volatile uint16_t m_head;
|
||||||
|
volatile uint16_t m_tail;
|
||||||
|
volatile bool m_full;
|
||||||
|
bool m_overflow;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
29
Config.h
Normal file
29
Config.h
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(CONFIG_H)
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#define ADF7021
|
||||||
|
|
||||||
|
//#define STM32_USART1_HOST
|
||||||
|
#define STM32_USB_HOST
|
||||||
|
|
||||||
|
//#define SERIAL_REPEATER
|
||||||
|
|
||||||
|
#endif
|
||||||
255
DMRDMORX.cpp
Normal file
255
DMRDMORX.cpp
Normal file
|
|
@ -0,0 +1,255 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "DMRDMORX.h"
|
||||||
|
#include "DMRSlotType.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
const uint8_t MAX_SYNC_BYTES_ERRS = 3U;
|
||||||
|
|
||||||
|
const uint8_t MAX_SYNC_LOST_FRAMES = 13U;
|
||||||
|
|
||||||
|
const uint16_t NOENDPTR = 9999U;
|
||||||
|
|
||||||
|
const uint8_t CONTROL_NONE = 0x00U;
|
||||||
|
const uint8_t CONTROL_VOICE = 0x20U;
|
||||||
|
const uint8_t CONTROL_DATA = 0x40U;
|
||||||
|
|
||||||
|
CDMRDMORX::CDMRDMORX() :
|
||||||
|
m_patternBuffer(0x00U),
|
||||||
|
m_dataPtr(0U),
|
||||||
|
m_syncPtr(0U),
|
||||||
|
m_startPtr(0U),
|
||||||
|
m_endPtr(NOENDPTR),
|
||||||
|
m_control(CONTROL_NONE),
|
||||||
|
m_syncCount(0U),
|
||||||
|
m_colorCode(0U),
|
||||||
|
m_state(DMORXS_NONE),
|
||||||
|
m_n(0U),
|
||||||
|
m_type(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRDMORX::reset()
|
||||||
|
{
|
||||||
|
m_syncPtr = 0U;
|
||||||
|
m_control = CONTROL_NONE;
|
||||||
|
m_syncCount = 0U;
|
||||||
|
m_state = DMORXS_NONE;
|
||||||
|
m_startPtr = 0U;
|
||||||
|
m_endPtr = NOENDPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRDMORX::databit(bool bit)
|
||||||
|
{
|
||||||
|
m_buffer[m_dataPtr] = bit;
|
||||||
|
|
||||||
|
m_patternBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_patternBuffer |= 0x01U;
|
||||||
|
|
||||||
|
if (m_state == DMORXS_NONE) {
|
||||||
|
correlateSync();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
uint16_t min = m_syncPtr + DMO_BUFFER_LENGTH_BITS - 2;
|
||||||
|
uint16_t max = m_syncPtr + 2;
|
||||||
|
|
||||||
|
if (min >= DMO_BUFFER_LENGTH_BITS)
|
||||||
|
min -= DMO_BUFFER_LENGTH_BITS;
|
||||||
|
if (max >= DMO_BUFFER_LENGTH_BITS)
|
||||||
|
max -= DMO_BUFFER_LENGTH_BITS;
|
||||||
|
|
||||||
|
if (min < max) {
|
||||||
|
if (m_dataPtr >= min && m_dataPtr <= max)
|
||||||
|
correlateSync();
|
||||||
|
} else {
|
||||||
|
if (m_dataPtr >= min || m_dataPtr <= max)
|
||||||
|
correlateSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_dataPtr == m_endPtr) {
|
||||||
|
frame[0U] = m_control;
|
||||||
|
|
||||||
|
bitsToBytes(m_startPtr, DMR_FRAME_LENGTH_BYTES, frame + 1U);
|
||||||
|
|
||||||
|
if (m_control == CONTROL_DATA) {
|
||||||
|
// Data sync
|
||||||
|
uint8_t colorCode;
|
||||||
|
uint8_t dataType;
|
||||||
|
CDMRSlotType slotType;
|
||||||
|
slotType.decode(frame + 1U, colorCode, dataType);
|
||||||
|
|
||||||
|
if (colorCode == m_colorCode) {
|
||||||
|
m_syncCount = 0U;
|
||||||
|
m_n = 0U;
|
||||||
|
|
||||||
|
frame[0U] |= dataType;
|
||||||
|
|
||||||
|
switch (dataType) {
|
||||||
|
case DT_DATA_HEADER:
|
||||||
|
DEBUG2("DMRDMORX: data header found pos", m_syncPtr);
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
m_state = DMORXS_DATA;
|
||||||
|
m_type = 0x00U;
|
||||||
|
break;
|
||||||
|
case DT_RATE_12_DATA:
|
||||||
|
case DT_RATE_34_DATA:
|
||||||
|
case DT_RATE_1_DATA:
|
||||||
|
if (m_state == DMORXS_DATA) {
|
||||||
|
DEBUG2("DMRDMORX: data payload found pos", m_syncPtr);
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
m_type = dataType;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_VOICE_LC_HEADER:
|
||||||
|
DEBUG2("DMRDMORX: voice header found pos", m_syncPtr);
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
m_state = DMORXS_VOICE;
|
||||||
|
break;
|
||||||
|
case DT_VOICE_PI_HEADER:
|
||||||
|
if (m_state == DMORXS_VOICE) {
|
||||||
|
DEBUG2("DMRDMORX: voice pi header found pos", m_syncPtr);
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
}
|
||||||
|
m_state = DMORXS_VOICE;
|
||||||
|
break;
|
||||||
|
case DT_TERMINATOR_WITH_LC:
|
||||||
|
if (m_state == DMORXS_VOICE) {
|
||||||
|
DEBUG2("DMRDMORX: voice terminator found pos", m_syncPtr);
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // DT_CSBK
|
||||||
|
DEBUG2("DMRDMORX: csbk found pos", m_syncPtr);
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
reset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (m_control == CONTROL_VOICE) {
|
||||||
|
// Voice sync
|
||||||
|
DEBUG2("DMRDMORX: voice sync found pos", m_syncPtr);
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
|
||||||
|
m_state = DMORXS_VOICE;
|
||||||
|
m_syncCount = 0U;
|
||||||
|
m_n = 0U;
|
||||||
|
} else {
|
||||||
|
if (m_state != DMORXS_NONE) {
|
||||||
|
m_syncCount++;
|
||||||
|
if (m_syncCount >= MAX_SYNC_LOST_FRAMES) {
|
||||||
|
serial.writeDMRLost(true);
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state == DMORXS_VOICE) {
|
||||||
|
if (m_n >= 5U) {
|
||||||
|
frame[0U] = CONTROL_VOICE;
|
||||||
|
m_n = 0U;
|
||||||
|
} else {
|
||||||
|
frame[0U] = ++m_n;
|
||||||
|
}
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
} else if (m_state == DMORXS_DATA) {
|
||||||
|
if (m_type != 0x00U) {
|
||||||
|
frame[0U] = CONTROL_DATA | m_type;
|
||||||
|
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of this slot, reset some items for the next slot.
|
||||||
|
m_control = CONTROL_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dataPtr++;
|
||||||
|
|
||||||
|
if (m_dataPtr >= DMO_BUFFER_LENGTH_BITS)
|
||||||
|
m_dataPtr = 0U;
|
||||||
|
|
||||||
|
io.setDecode(m_state != DMORXS_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRDMORX::correlateSync()
|
||||||
|
{
|
||||||
|
if ( (countBits64((m_patternBuffer & DMR_SYNC_BITS_MASK) ^ DMR_MS_DATA_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) || \
|
||||||
|
(countBits64((m_patternBuffer & DMR_SYNC_BITS_MASK) ^ DMR_S2_DATA_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) ) {
|
||||||
|
|
||||||
|
m_control = CONTROL_DATA;
|
||||||
|
m_syncPtr = m_dataPtr;
|
||||||
|
|
||||||
|
m_startPtr = m_dataPtr + DMO_BUFFER_LENGTH_BITS - DMR_SLOT_TYPE_LENGTH_BITS / 2U - DMR_INFO_LENGTH_BITS / 2U - DMR_SYNC_LENGTH_BITS + 1;
|
||||||
|
if (m_startPtr >= DMO_BUFFER_LENGTH_BITS)
|
||||||
|
m_startPtr -= DMO_BUFFER_LENGTH_BITS;
|
||||||
|
|
||||||
|
m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_BITS / 2U + DMR_INFO_LENGTH_BITS / 2U;
|
||||||
|
if (m_endPtr >= DMO_BUFFER_LENGTH_BITS)
|
||||||
|
m_endPtr -= DMO_BUFFER_LENGTH_BITS;
|
||||||
|
|
||||||
|
//DEBUG4("SYNC MS Data found pos/start/end:", m_dataPtr, m_startPtr, m_endPtr);
|
||||||
|
} else if ( (countBits64((m_patternBuffer & DMR_SYNC_BITS_MASK) ^ DMR_MS_VOICE_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) || \
|
||||||
|
(countBits64((m_patternBuffer & DMR_SYNC_BITS_MASK) ^ DMR_S2_VOICE_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) ) {
|
||||||
|
|
||||||
|
m_control = CONTROL_VOICE;
|
||||||
|
m_syncPtr = m_dataPtr;
|
||||||
|
|
||||||
|
m_startPtr = m_dataPtr + DMO_BUFFER_LENGTH_BITS - DMR_SLOT_TYPE_LENGTH_BITS / 2U - DMR_INFO_LENGTH_BITS / 2U - DMR_SYNC_LENGTH_BITS + 1;
|
||||||
|
if (m_startPtr >= DMO_BUFFER_LENGTH_BITS)
|
||||||
|
m_startPtr -= DMO_BUFFER_LENGTH_BITS;
|
||||||
|
|
||||||
|
m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_BITS / 2U + DMR_INFO_LENGTH_BITS / 2U;
|
||||||
|
if (m_endPtr >= DMO_BUFFER_LENGTH_BITS)
|
||||||
|
m_endPtr -= DMO_BUFFER_LENGTH_BITS;
|
||||||
|
|
||||||
|
//DEBUG4("SYNC MS Voice found pos/start/end: ", m_dataPtr, m_startPtr, m_endPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRDMORX::bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0U; i < count; i++) {
|
||||||
|
|
||||||
|
buffer[i] = 0U;
|
||||||
|
buffer[i] |= ((m_buffer[start + 0U] & 0x01) << 7);
|
||||||
|
buffer[i] |= ((m_buffer[start + 1U] & 0x01) << 6);
|
||||||
|
buffer[i] |= ((m_buffer[start + 2U] & 0x01) << 5);
|
||||||
|
buffer[i] |= ((m_buffer[start + 3U] & 0x01) << 4);
|
||||||
|
buffer[i] |= ((m_buffer[start + 4U] & 0x01) << 3);
|
||||||
|
buffer[i] |= ((m_buffer[start + 5U] & 0x01) << 2);
|
||||||
|
buffer[i] |= ((m_buffer[start + 6U] & 0x01) << 1);
|
||||||
|
buffer[i] |= ((m_buffer[start + 7U] & 0x01) << 0);
|
||||||
|
|
||||||
|
start += 8U;
|
||||||
|
|
||||||
|
if (start >= DMO_BUFFER_LENGTH_BITS)
|
||||||
|
start -= DMO_BUFFER_LENGTH_BITS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRDMORX::setColorCode(uint8_t colorCode)
|
||||||
|
{
|
||||||
|
m_colorCode = colorCode;
|
||||||
|
}
|
||||||
61
DMRDMORX.h
Normal file
61
DMRDMORX.h
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DMRDMORX_H)
|
||||||
|
#define DMRDMORX_H
|
||||||
|
|
||||||
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
|
const uint16_t DMO_BUFFER_LENGTH_BITS = 576U;
|
||||||
|
|
||||||
|
enum DMORX_STATE {
|
||||||
|
DMORXS_NONE,
|
||||||
|
DMORXS_VOICE,
|
||||||
|
DMORXS_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
class CDMRDMORX {
|
||||||
|
public:
|
||||||
|
CDMRDMORX();
|
||||||
|
|
||||||
|
void databit(bool bit);
|
||||||
|
void setColorCode(uint8_t colorCode);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t m_patternBuffer;
|
||||||
|
uint8_t m_buffer[DMO_BUFFER_LENGTH_BITS];
|
||||||
|
uint8_t frame[DMR_FRAME_LENGTH_BYTES + 3U];
|
||||||
|
uint16_t m_dataPtr;
|
||||||
|
uint16_t m_syncPtr;
|
||||||
|
uint16_t m_startPtr;
|
||||||
|
uint16_t m_endPtr;
|
||||||
|
uint8_t m_control;
|
||||||
|
uint8_t m_syncCount;
|
||||||
|
uint8_t m_colorCode;
|
||||||
|
DMORX_STATE m_state;
|
||||||
|
uint8_t m_n;
|
||||||
|
uint8_t m_type;
|
||||||
|
|
||||||
|
void correlateSync();
|
||||||
|
void bitsToBytes(uint16_t start, uint8_t count, uint8_t* buffer);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
114
DMRDMOTX.cpp
Normal file
114
DMRDMOTX.cpp
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
CDMRDMOTX::CDMRDMOTX() :
|
||||||
|
m_fifo(),
|
||||||
|
m_poBuffer(),
|
||||||
|
m_poLen(0U),
|
||||||
|
m_poPtr(0U),
|
||||||
|
m_txDelay(240U), // 200ms
|
||||||
|
m_count(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRDMOTX::process()
|
||||||
|
{
|
||||||
|
if (m_poLen == 0U && m_fifo.getData() > 0U) {
|
||||||
|
if (!m_tx) {
|
||||||
|
m_delay = true;
|
||||||
|
m_poLen = m_txDelay;
|
||||||
|
} else {
|
||||||
|
m_delay = false;
|
||||||
|
for (unsigned int i = 0U; i < 72U; i++)
|
||||||
|
m_poBuffer[m_poLen++] = 0x00U;
|
||||||
|
|
||||||
|
for (unsigned int i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++)
|
||||||
|
m_poBuffer[i] = m_fifo.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_poPtr = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_poLen > 0U) {
|
||||||
|
uint16_t space = io.getSpace();
|
||||||
|
|
||||||
|
while (space > 8U) {
|
||||||
|
if (m_delay) {
|
||||||
|
m_poPtr++;
|
||||||
|
writeByte(0U);
|
||||||
|
} else
|
||||||
|
writeByte(m_poBuffer[m_poPtr++]);
|
||||||
|
|
||||||
|
space -= 8U;
|
||||||
|
|
||||||
|
if (m_poPtr >= m_poLen) {
|
||||||
|
m_poPtr = 0U;
|
||||||
|
m_poLen = 0U;
|
||||||
|
m_delay = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CDMRDMOTX::writeData(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length != (DMR_FRAME_LENGTH_BYTES + 1U))
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
uint16_t space = m_fifo.getSpace();
|
||||||
|
if (space < DMR_FRAME_LENGTH_BYTES)
|
||||||
|
return 5U;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < DMR_FRAME_LENGTH_BYTES; i++)
|
||||||
|
m_fifo.put(data[i + 1U]);
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRDMOTX::writeByte(uint8_t c)
|
||||||
|
{
|
||||||
|
uint8_t bit;
|
||||||
|
uint8_t mask = 0x80U;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < 8U; i++, c <<= 1) {
|
||||||
|
if ((c & mask) == mask)
|
||||||
|
bit = 1U;
|
||||||
|
else
|
||||||
|
bit = 0U;
|
||||||
|
|
||||||
|
io.write(&bit, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CDMRDMOTX::getSpace() const
|
||||||
|
{
|
||||||
|
return m_fifo.getSpace() / (DMR_FRAME_LENGTH_BYTES + 2U);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRDMOTX::setTXDelay(uint8_t delay)
|
||||||
|
{
|
||||||
|
m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay
|
||||||
|
}
|
||||||
51
DMRDMOTX.h
Normal file
51
DMRDMOTX.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DMRDMOTX_H)
|
||||||
|
#define DMRDMOTX_H
|
||||||
|
|
||||||
|
#include "DMRDefines.h"
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
|
class CDMRDMOTX {
|
||||||
|
public:
|
||||||
|
CDMRDMOTX();
|
||||||
|
|
||||||
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setTXDelay(uint8_t delay);
|
||||||
|
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSerialRB m_fifo;
|
||||||
|
uint8_t m_poBuffer[80U];
|
||||||
|
uint16_t m_poLen;
|
||||||
|
uint16_t m_poPtr;
|
||||||
|
uint16_t m_txDelay;
|
||||||
|
uint32_t m_count;
|
||||||
|
bool m_delay;
|
||||||
|
|
||||||
|
void writeByte(uint8_t c);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
91
DMRDefines.h
Normal file
91
DMRDefines.h
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DMRDEFINES_H)
|
||||||
|
#define DMRDEFINES_H
|
||||||
|
|
||||||
|
const unsigned int DMR_FRAME_LENGTH_BYTES = 33U;
|
||||||
|
const unsigned int DMR_FRAME_LENGTH_BITS = DMR_FRAME_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int DMR_FRAME_LENGTH_SYMBOLS = DMR_FRAME_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int DMR_SYNC_LENGTH_BYTES = 6U;
|
||||||
|
const unsigned int DMR_SYNC_LENGTH_BITS = DMR_SYNC_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int DMR_SYNC_LENGTH_SYMBOLS = DMR_SYNC_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int DMR_EMB_LENGTH_BITS = 16U;
|
||||||
|
const unsigned int DMR_EMB_LENGTH_SYMBOLS = 8U;
|
||||||
|
|
||||||
|
const unsigned int DMR_EMBSIG_LENGTH_BITS = 32U;
|
||||||
|
const unsigned int DMR_EMBSIG_LENGTH_SYMBOLS = 16U;
|
||||||
|
|
||||||
|
const unsigned int DMR_SLOT_TYPE_LENGTH_BITS = 20U;
|
||||||
|
const unsigned int DMR_SLOT_TYPE_LENGTH_SYMBOLS = 10U;
|
||||||
|
|
||||||
|
const unsigned int DMR_INFO_LENGTH_BITS = 196U;
|
||||||
|
const unsigned int DMR_INFO_LENGTH_SYMBOLS = 98U;
|
||||||
|
|
||||||
|
const unsigned int DMR_AUDIO_LENGTH_BITS = 216U;
|
||||||
|
const unsigned int DMR_AUDIO_LENGTH_SYMBOLS = 108U;
|
||||||
|
|
||||||
|
const unsigned int DMR_CACH_LENGTH_BYTES = 3U;
|
||||||
|
const unsigned int DMR_CACH_LENGTH_BITS = DMR_CACH_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int DMR_CACH_LENGTH_SYMBOLS = DMR_CACH_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const uint8_t DMR_SYNC_BYTES_LENGTH = 7U;
|
||||||
|
const uint8_t DMR_MS_DATA_SYNC_BYTES[] = {0x0DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x70U};
|
||||||
|
const uint8_t DMR_MS_VOICE_SYNC_BYTES[] = {0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U};
|
||||||
|
const uint8_t DMR_BS_DATA_SYNC_BYTES[] = {0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U};
|
||||||
|
const uint8_t DMR_BS_VOICE_SYNC_BYTES[] = {0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U};
|
||||||
|
const uint8_t DMR_S1_DATA_SYNC_BYTES[] = {0x0FU, 0x7FU, 0xDDU, 0x5DU, 0xDFU, 0xD5U, 0x50U};
|
||||||
|
const uint8_t DMR_S1_VOICE_SYNC_BYTES[] = {0x05U, 0xD5U, 0x77U, 0xF7U, 0x75U, 0x7FU, 0xF0U};
|
||||||
|
const uint8_t DMR_S2_DATA_SYNC_BYTES[] = {0x0DU, 0x75U, 0x57U, 0xF5U, 0xFFU, 0x7FU, 0x50U};
|
||||||
|
const uint8_t DMR_S2_VOICE_SYNC_BYTES[] = {0x07U, 0xDFU, 0xFDU, 0x5FU, 0x55U, 0xD5U, 0xF0U};
|
||||||
|
const uint8_t DMR_SYNC_BYTES_MASK[] = {0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U};
|
||||||
|
|
||||||
|
const uint64_t DMR_MS_DATA_SYNC_BITS = 0x0000D5D7F77FD757U;
|
||||||
|
const uint64_t DMR_MS_VOICE_SYNC_BITS = 0x00007F7D5DD57DFDU;
|
||||||
|
const uint64_t DMR_BS_DATA_SYNC_BITS = 0x0000DFF57D75DF5DU;
|
||||||
|
const uint64_t DMR_BS_VOICE_SYNC_BITS = 0x0000755FD7DF75F7U;
|
||||||
|
const uint64_t DMR_S1_DATA_SYNC_BITS = 0x0000F7FDD5DDFD55U;
|
||||||
|
const uint64_t DMR_S1_VOICE_SYNC_BITS = 0x00005D577F7757FFU;
|
||||||
|
const uint64_t DMR_S2_DATA_SYNC_BITS = 0x0000D7557F5FF7F5U;
|
||||||
|
const uint64_t DMR_S2_VOICE_SYNC_BITS = 0x00007DFFD5F55D5FU;
|
||||||
|
const uint64_t DMR_SYNC_BITS_MASK = 0x0000FFFFFFFFFFFFU;
|
||||||
|
|
||||||
|
const uint32_t DMR_MS_DATA_SYNC_SYMBOLS = 0x0076286EU;
|
||||||
|
const uint32_t DMR_MS_VOICE_SYNC_SYMBOLS = 0x0089D791U;
|
||||||
|
const uint32_t DMR_BS_DATA_SYNC_SYMBOLS = 0x00439B4DU;
|
||||||
|
const uint32_t DMR_BS_VOICE_SYNC_SYMBOLS = 0x00BC64B2U;
|
||||||
|
const uint32_t DMR_S1_DATA_SYNC_SYMBOLS = 0x0021751FU;
|
||||||
|
const uint32_t DMR_S1_VOICE_SYNC_SYMBOLS = 0x00DE8AE0U;
|
||||||
|
const uint32_t DMR_S2_DATA_SYNC_SYMBOLS = 0x006F8C23U;
|
||||||
|
const uint32_t DMR_S2_VOICE_SYNC_SYMBOLS = 0x009073DCU;
|
||||||
|
const uint32_t DMR_SYNC_SYMBOLS_MASK = 0x00FFFFFFU;
|
||||||
|
|
||||||
|
const uint8_t DT_VOICE_PI_HEADER = 0U;
|
||||||
|
const uint8_t DT_VOICE_LC_HEADER = 1U;
|
||||||
|
const uint8_t DT_TERMINATOR_WITH_LC = 2U;
|
||||||
|
const uint8_t DT_CSBK = 3U;
|
||||||
|
const uint8_t DT_DATA_HEADER = 6U;
|
||||||
|
const uint8_t DT_RATE_12_DATA = 7U;
|
||||||
|
const uint8_t DT_RATE_34_DATA = 8U;
|
||||||
|
const uint8_t DT_IDLE = 9U;
|
||||||
|
const uint8_t DT_RATE_1_DATA = 10U;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
286
DMRSlotType.cpp
Normal file
286
DMRSlotType.cpp
Normal file
|
|
@ -0,0 +1,286 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "DMRSlotType.h"
|
||||||
|
|
||||||
|
const uint16_t ENCODING_TABLE_2087[] =
|
||||||
|
{0x0000U, 0xB08EU, 0xE093U, 0x501DU, 0x70A9U, 0xC027U, 0x903AU, 0x20B4U, 0x60DCU, 0xD052U, 0x804FU, 0x30C1U,
|
||||||
|
0x1075U, 0xA0FBU, 0xF0E6U, 0x4068U, 0x7036U, 0xC0B8U, 0x90A5U, 0x202BU, 0x009FU, 0xB011U, 0xE00CU, 0x5082U,
|
||||||
|
0x10EAU, 0xA064U, 0xF079U, 0x40F7U, 0x6043U, 0xD0CDU, 0x80D0U, 0x305EU, 0xD06CU, 0x60E2U, 0x30FFU, 0x8071U,
|
||||||
|
0xA0C5U, 0x104BU, 0x4056U, 0xF0D8U, 0xB0B0U, 0x003EU, 0x5023U, 0xE0ADU, 0xC019U, 0x7097U, 0x208AU, 0x9004U,
|
||||||
|
0xA05AU, 0x10D4U, 0x40C9U, 0xF047U, 0xD0F3U, 0x607DU, 0x3060U, 0x80EEU, 0xC086U, 0x7008U, 0x2015U, 0x909BU,
|
||||||
|
0xB02FU, 0x00A1U, 0x50BCU, 0xE032U, 0x90D9U, 0x2057U, 0x704AU, 0xC0C4U, 0xE070U, 0x50FEU, 0x00E3U, 0xB06DU,
|
||||||
|
0xF005U, 0x408BU, 0x1096U, 0xA018U, 0x80ACU, 0x3022U, 0x603FU, 0xD0B1U, 0xE0EFU, 0x5061U, 0x007CU, 0xB0F2U,
|
||||||
|
0x9046U, 0x20C8U, 0x70D5U, 0xC05BU, 0x8033U, 0x30BDU, 0x60A0U, 0xD02EU, 0xF09AU, 0x4014U, 0x1009U, 0xA087U,
|
||||||
|
0x40B5U, 0xF03BU, 0xA026U, 0x10A8U, 0x301CU, 0x8092U, 0xD08FU, 0x6001U, 0x2069U, 0x90E7U, 0xC0FAU, 0x7074U,
|
||||||
|
0x50C0U, 0xE04EU, 0xB053U, 0x00DDU, 0x3083U, 0x800DU, 0xD010U, 0x609EU, 0x402AU, 0xF0A4U, 0xA0B9U, 0x1037U,
|
||||||
|
0x505FU, 0xE0D1U, 0xB0CCU, 0x0042U, 0x20F6U, 0x9078U, 0xC065U, 0x70EBU, 0xA03DU, 0x10B3U, 0x40AEU, 0xF020U,
|
||||||
|
0xD094U, 0x601AU, 0x3007U, 0x8089U, 0xC0E1U, 0x706FU, 0x2072U, 0x90FCU, 0xB048U, 0x00C6U, 0x50DBU, 0xE055U,
|
||||||
|
0xD00BU, 0x6085U, 0x3098U, 0x8016U, 0xA0A2U, 0x102CU, 0x4031U, 0xF0BFU, 0xB0D7U, 0x0059U, 0x5044U, 0xE0CAU,
|
||||||
|
0xC07EU, 0x70F0U, 0x20EDU, 0x9063U, 0x7051U, 0xC0DFU, 0x90C2U, 0x204CU, 0x00F8U, 0xB076U, 0xE06BU, 0x50E5U,
|
||||||
|
0x108DU, 0xA003U, 0xF01EU, 0x4090U, 0x6024U, 0xD0AAU, 0x80B7U, 0x3039U, 0x0067U, 0xB0E9U, 0xE0F4U, 0x507AU,
|
||||||
|
0x70CEU, 0xC040U, 0x905DU, 0x20D3U, 0x60BBU, 0xD035U, 0x8028U, 0x30A6U, 0x1012U, 0xA09CU, 0xF081U, 0x400FU,
|
||||||
|
0x30E4U, 0x806AU, 0xD077U, 0x60F9U, 0x404DU, 0xF0C3U, 0xA0DEU, 0x1050U, 0x5038U, 0xE0B6U, 0xB0ABU, 0x0025U,
|
||||||
|
0x2091U, 0x901FU, 0xC002U, 0x708CU, 0x40D2U, 0xF05CU, 0xA041U, 0x10CFU, 0x307BU, 0x80F5U, 0xD0E8U, 0x6066U,
|
||||||
|
0x200EU, 0x9080U, 0xC09DU, 0x7013U, 0x50A7U, 0xE029U, 0xB034U, 0x00BAU, 0xE088U, 0x5006U, 0x001BU, 0xB095U,
|
||||||
|
0x9021U, 0x20AFU, 0x70B2U, 0xC03CU, 0x8054U, 0x30DAU, 0x60C7U, 0xD049U, 0xF0FDU, 0x4073U, 0x106EU, 0xA0E0U,
|
||||||
|
0x90BEU, 0x2030U, 0x702DU, 0xC0A3U, 0xE017U, 0x5099U, 0x0084U, 0xB00AU, 0xF062U, 0x40ECU, 0x10F1U, 0xA07FU,
|
||||||
|
0x80CBU, 0x3045U, 0x6058U, 0xD0D6U};
|
||||||
|
|
||||||
|
const uint32_t DECODING_TABLE_1987[] =
|
||||||
|
{0x00000U, 0x00001U, 0x00002U, 0x00003U, 0x00004U, 0x00005U, 0x00006U, 0x00007U, 0x00008U, 0x00009U, 0x0000AU, 0x0000BU, 0x0000CU,
|
||||||
|
0x0000DU, 0x0000EU, 0x24020U, 0x00010U, 0x00011U, 0x00012U, 0x00013U, 0x00014U, 0x00015U, 0x00016U, 0x00017U, 0x00018U, 0x00019U,
|
||||||
|
0x0001AU, 0x0001BU, 0x0001CU, 0x0001DU, 0x48040U, 0x01480U, 0x00020U, 0x00021U, 0x00022U, 0x00023U, 0x00024U, 0x00025U, 0x00026U,
|
||||||
|
0x24008U, 0x00028U, 0x00029U, 0x0002AU, 0x24004U, 0x0002CU, 0x24002U, 0x24001U, 0x24000U, 0x00030U, 0x00031U, 0x00032U, 0x08180U,
|
||||||
|
0x00034U, 0x00C40U, 0x00036U, 0x00C42U, 0x00038U, 0x43000U, 0x0003AU, 0x43002U, 0x02902U, 0x24012U, 0x02900U, 0x24010U, 0x00040U,
|
||||||
|
0x00041U, 0x00042U, 0x00043U, 0x00044U, 0x00045U, 0x00046U, 0x00047U, 0x00048U, 0x00049U, 0x0004AU, 0x02500U, 0x0004CU, 0x0004DU,
|
||||||
|
0x48010U, 0x48011U, 0x00050U, 0x00051U, 0x00052U, 0x21200U, 0x00054U, 0x00C20U, 0x48008U, 0x48009U, 0x00058U, 0x00059U, 0x48004U,
|
||||||
|
0x48005U, 0x48002U, 0x48003U, 0x48000U, 0x48001U, 0x00060U, 0x00061U, 0x00062U, 0x00063U, 0x00064U, 0x00C10U, 0x10300U, 0x0B000U,
|
||||||
|
0x00068U, 0x00069U, 0x01880U, 0x01881U, 0x40181U, 0x40180U, 0x24041U, 0x24040U, 0x00070U, 0x00C04U, 0x00072U, 0x00C06U, 0x00C01U,
|
||||||
|
0x00C00U, 0x00C03U, 0x00C02U, 0x05204U, 0x00C0CU, 0x48024U, 0x48025U, 0x05200U, 0x00C08U, 0x48020U, 0x48021U, 0x00080U, 0x00081U,
|
||||||
|
0x00082U, 0x00083U, 0x00084U, 0x00085U, 0x00086U, 0x00087U, 0x00088U, 0x00089U, 0x0008AU, 0x50200U, 0x0008CU, 0x0A800U, 0x01411U,
|
||||||
|
0x01410U, 0x00090U, 0x00091U, 0x00092U, 0x08120U, 0x00094U, 0x00095U, 0x04A00U, 0x01408U, 0x00098U, 0x00099U, 0x01405U, 0x01404U,
|
||||||
|
0x01403U, 0x01402U, 0x01401U, 0x01400U, 0x000A0U, 0x000A1U, 0x000A2U, 0x08110U, 0x000A4U, 0x000A5U, 0x42400U, 0x42401U, 0x000A8U,
|
||||||
|
0x000A9U, 0x01840U, 0x01841U, 0x40141U, 0x40140U, 0x24081U, 0x24080U, 0x000B0U, 0x08102U, 0x08101U, 0x08100U, 0x000B4U, 0x08106U,
|
||||||
|
0x08105U, 0x08104U, 0x20A01U, 0x20A00U, 0x08109U, 0x08108U, 0x01423U, 0x01422U, 0x01421U, 0x01420U, 0x000C0U, 0x000C1U, 0x000C2U,
|
||||||
|
0x000C3U, 0x000C4U, 0x000C5U, 0x000C6U, 0x000C7U, 0x000C8U, 0x000C9U, 0x01820U, 0x01821U, 0x20600U, 0x40120U, 0x16000U, 0x16001U,
|
||||||
|
0x000D0U, 0x000D1U, 0x42801U, 0x42800U, 0x03100U, 0x18200U, 0x03102U, 0x18202U, 0x000D8U, 0x000D9U, 0x48084U, 0x01444U, 0x48082U,
|
||||||
|
0x01442U, 0x48080U, 0x01440U, 0x000E0U, 0x32000U, 0x01808U, 0x04600U, 0x40109U, 0x40108U, 0x0180CU, 0x4010AU, 0x01802U, 0x40104U,
|
||||||
|
0x01800U, 0x01801U, 0x40101U, 0x40100U, 0x01804U, 0x40102U, 0x0A408U, 0x08142U, 0x08141U, 0x08140U, 0x00C81U, 0x00C80U, 0x00C83U,
|
||||||
|
0x00C82U, 0x0A400U, 0x0A401U, 0x01810U, 0x01811U, 0x40111U, 0x40110U, 0x01814U, 0x40112U, 0x00100U, 0x00101U, 0x00102U, 0x00103U,
|
||||||
|
0x00104U, 0x00105U, 0x00106U, 0x41800U, 0x00108U, 0x00109U, 0x0010AU, 0x02440U, 0x0010CU, 0x0010DU, 0x0010EU, 0x02444U, 0x00110U,
|
||||||
|
0x00111U, 0x00112U, 0x080A0U, 0x00114U, 0x00115U, 0x00116U, 0x080A4U, 0x00118U, 0x00119U, 0x15000U, 0x15001U, 0x02822U, 0x02823U,
|
||||||
|
0x02820U, 0x02821U, 0x00120U, 0x00121U, 0x00122U, 0x08090U, 0x00124U, 0x00125U, 0x10240U, 0x10241U, 0x00128U, 0x00129U, 0x0012AU,
|
||||||
|
0x24104U, 0x09400U, 0x400C0U, 0x02810U, 0x24100U, 0x00130U, 0x08082U, 0x08081U, 0x08080U, 0x31001U, 0x31000U, 0x02808U, 0x08084U,
|
||||||
|
0x02806U, 0x0808AU, 0x02804U, 0x08088U, 0x02802U, 0x02803U, 0x02800U, 0x02801U, 0x00140U, 0x00141U, 0x00142U, 0x02408U, 0x00144U,
|
||||||
|
0x00145U, 0x10220U, 0x10221U, 0x00148U, 0x02402U, 0x02401U, 0x02400U, 0x400A1U, 0x400A0U, 0x02405U, 0x02404U, 0x00150U, 0x00151U,
|
||||||
|
0x00152U, 0x02418U, 0x03080U, 0x03081U, 0x03082U, 0x03083U, 0x09801U, 0x09800U, 0x02411U, 0x02410U, 0x48102U, 0x09804U, 0x48100U,
|
||||||
|
0x48101U, 0x00160U, 0x00161U, 0x10204U, 0x10205U, 0x10202U, 0x40088U, 0x10200U, 0x10201U, 0x40085U, 0x40084U, 0x02421U, 0x02420U,
|
||||||
|
0x40081U, 0x40080U, 0x10208U, 0x40082U, 0x41402U, 0x080C2U, 0x41400U, 0x080C0U, 0x00D01U, 0x00D00U, 0x10210U, 0x10211U, 0x40095U,
|
||||||
|
0x40094U, 0x02844U, 0x080C8U, 0x40091U, 0x40090U, 0x02840U, 0x02841U, 0x00180U, 0x00181U, 0x00182U, 0x08030U, 0x00184U, 0x14400U,
|
||||||
|
0x22201U, 0x22200U, 0x00188U, 0x00189U, 0x0018AU, 0x08038U, 0x40061U, 0x40060U, 0x40063U, 0x40062U, 0x00190U, 0x08022U, 0x08021U,
|
||||||
|
0x08020U, 0x03040U, 0x03041U, 0x08025U, 0x08024U, 0x40C00U, 0x40C01U, 0x08029U, 0x08028U, 0x2C000U, 0x2C001U, 0x01501U, 0x01500U,
|
||||||
|
0x001A0U, 0x08012U, 0x08011U, 0x08010U, 0x40049U, 0x40048U, 0x08015U, 0x08014U, 0x06200U, 0x40044U, 0x30400U, 0x08018U, 0x40041U,
|
||||||
|
0x40040U, 0x40043U, 0x40042U, 0x08003U, 0x08002U, 0x08001U, 0x08000U, 0x08007U, 0x08006U, 0x08005U, 0x08004U, 0x0800BU, 0x0800AU,
|
||||||
|
0x08009U, 0x08008U, 0x40051U, 0x40050U, 0x02880U, 0x0800CU, 0x001C0U, 0x001C1U, 0x64000U, 0x64001U, 0x03010U, 0x40028U, 0x08C00U,
|
||||||
|
0x08C01U, 0x40025U, 0x40024U, 0x02481U, 0x02480U, 0x40021U, 0x40020U, 0x40023U, 0x40022U, 0x03004U, 0x03005U, 0x08061U, 0x08060U,
|
||||||
|
0x03000U, 0x03001U, 0x03002U, 0x03003U, 0x0300CU, 0x40034U, 0x30805U, 0x30804U, 0x03008U, 0x40030U, 0x30801U, 0x30800U, 0x4000DU,
|
||||||
|
0x4000CU, 0x08051U, 0x08050U, 0x40009U, 0x40008U, 0x10280U, 0x4000AU, 0x40005U, 0x40004U, 0x01900U, 0x40006U, 0x40001U, 0x40000U,
|
||||||
|
0x40003U, 0x40002U, 0x14800U, 0x08042U, 0x08041U, 0x08040U, 0x03020U, 0x40018U, 0x08045U, 0x08044U, 0x40015U, 0x40014U, 0x08049U,
|
||||||
|
0x08048U, 0x40011U, 0x40010U, 0x40013U, 0x40012U, 0x00200U, 0x00201U, 0x00202U, 0x00203U, 0x00204U, 0x00205U, 0x00206U, 0x00207U,
|
||||||
|
0x00208U, 0x00209U, 0x0020AU, 0x50080U, 0x0020CU, 0x0020DU, 0x0020EU, 0x50084U, 0x00210U, 0x00211U, 0x00212U, 0x21040U, 0x00214U,
|
||||||
|
0x00215U, 0x04880U, 0x04881U, 0x00218U, 0x00219U, 0x0E001U, 0x0E000U, 0x0021CU, 0x0021DU, 0x04888U, 0x0E004U, 0x00220U, 0x00221U,
|
||||||
|
0x00222U, 0x00223U, 0x00224U, 0x00225U, 0x10140U, 0x10141U, 0x00228U, 0x00229U, 0x0022AU, 0x24204U, 0x12401U, 0x12400U, 0x24201U,
|
||||||
|
0x24200U, 0x00230U, 0x00231U, 0x00232U, 0x21060U, 0x2A000U, 0x2A001U, 0x2A002U, 0x2A003U, 0x20881U, 0x20880U, 0x20883U, 0x20882U,
|
||||||
|
0x05040U, 0x05041U, 0x05042U, 0x24210U, 0x00240U, 0x00241U, 0x00242U, 0x21010U, 0x00244U, 0x46000U, 0x10120U, 0x10121U, 0x00248U,
|
||||||
|
0x00249U, 0x0024AU, 0x21018U, 0x20480U, 0x20481U, 0x20482U, 0x20483U, 0x00250U, 0x21002U, 0x21001U, 0x21000U, 0x18081U, 0x18080U,
|
||||||
|
0x21005U, 0x21004U, 0x12800U, 0x12801U, 0x21009U, 0x21008U, 0x05020U, 0x05021U, 0x48200U, 0x48201U, 0x00260U, 0x00261U, 0x10104U,
|
||||||
|
0x04480U, 0x10102U, 0x10103U, 0x10100U, 0x10101U, 0x62002U, 0x62003U, 0x62000U, 0x62001U, 0x05010U, 0x05011U, 0x10108U, 0x10109U,
|
||||||
|
0x0500CU, 0x21022U, 0x21021U, 0x21020U, 0x05008U, 0x00E00U, 0x10110U, 0x10111U, 0x05004U, 0x05005U, 0x05006U, 0x21028U, 0x05000U,
|
||||||
|
0x05001U, 0x05002U, 0x05003U, 0x00280U, 0x00281U, 0x00282U, 0x50008U, 0x00284U, 0x00285U, 0x04810U, 0x22100U, 0x00288U, 0x50002U,
|
||||||
|
0x50001U, 0x50000U, 0x20440U, 0x20441U, 0x50005U, 0x50004U, 0x00290U, 0x00291U, 0x04804U, 0x04805U, 0x04802U, 0x18040U, 0x04800U,
|
||||||
|
0x04801U, 0x20821U, 0x20820U, 0x50011U, 0x50010U, 0x0480AU, 0x01602U, 0x04808U, 0x01600U, 0x002A0U, 0x002A1U, 0x04441U, 0x04440U,
|
||||||
|
0x002A4U, 0x002A5U, 0x04830U, 0x04444U, 0x06100U, 0x20810U, 0x50021U, 0x50020U, 0x06104U, 0x20814U, 0x50025U, 0x50024U, 0x20809U,
|
||||||
|
0x20808U, 0x13000U, 0x08300U, 0x04822U, 0x2080CU, 0x04820U, 0x04821U, 0x20801U, 0x20800U, 0x20803U, 0x20802U, 0x20805U, 0x20804U,
|
||||||
|
0x04828U, 0x20806U, 0x002C0U, 0x002C1U, 0x04421U, 0x04420U, 0x20408U, 0x18010U, 0x2040AU, 0x18012U, 0x20404U, 0x20405U, 0x50041U,
|
||||||
|
0x50040U, 0x20400U, 0x20401U, 0x20402U, 0x20403U, 0x18005U, 0x18004U, 0x21081U, 0x21080U, 0x18001U, 0x18000U, 0x04840U, 0x18002U,
|
||||||
|
0x20414U, 0x1800CU, 0x21089U, 0x21088U, 0x20410U, 0x18008U, 0x20412U, 0x1800AU, 0x04403U, 0x04402U, 0x04401U, 0x04400U, 0x10182U,
|
||||||
|
0x04406U, 0x10180U, 0x04404U, 0x01A02U, 0x0440AU, 0x01A00U, 0x04408U, 0x20420U, 0x40300U, 0x20422U, 0x40302U, 0x04413U, 0x04412U,
|
||||||
|
0x04411U, 0x04410U, 0x18021U, 0x18020U, 0x10190U, 0x18022U, 0x20841U, 0x20840U, 0x01A10U, 0x20842U, 0x05080U, 0x05081U, 0x05082U,
|
||||||
|
0x05083U, 0x00300U, 0x00301U, 0x00302U, 0x00303U, 0x00304U, 0x00305U, 0x10060U, 0x22080U, 0x00308U, 0x00309U, 0x28800U, 0x28801U,
|
||||||
|
0x44402U, 0x44403U, 0x44400U, 0x44401U, 0x00310U, 0x00311U, 0x10C01U, 0x10C00U, 0x00314U, 0x00315U, 0x10070U, 0x10C04U, 0x00318U,
|
||||||
|
0x00319U, 0x28810U, 0x10C08U, 0x44412U, 0x00000U, 0x44410U, 0x44411U, 0x00320U, 0x60400U, 0x10044U, 0x10045U, 0x10042U, 0x0C800U,
|
||||||
|
0x10040U, 0x10041U, 0x06080U, 0x06081U, 0x06082U, 0x06083U, 0x1004AU, 0x0C808U, 0x10048U, 0x10049U, 0x58008U, 0x08282U, 0x08281U,
|
||||||
|
0x08280U, 0x10052U, 0x0C810U, 0x10050U, 0x10051U, 0x58000U, 0x58001U, 0x58002U, 0x08288U, 0x02A02U, 0x02A03U, 0x02A00U, 0x02A01U,
|
||||||
|
0x00340U, 0x00341U, 0x10024U, 0x10025U, 0x10022U, 0x10023U, 0x10020U, 0x10021U, 0x34001U, 0x34000U, 0x02601U, 0x02600U, 0x1002AU,
|
||||||
|
0x34004U, 0x10028U, 0x10029U, 0x0C400U, 0x0C401U, 0x21101U, 0x21100U, 0x60800U, 0x60801U, 0x10030U, 0x10031U, 0x0C408U, 0x34010U,
|
||||||
|
0x21109U, 0x21108U, 0x60808U, 0x60809U, 0x10038U, 0x28420U, 0x10006U, 0x10007U, 0x10004U, 0x10005U, 0x10002U, 0x10003U, 0x10000U,
|
||||||
|
0x10001U, 0x1000EU, 0x40284U, 0x1000CU, 0x1000DU, 0x1000AU, 0x40280U, 0x10008U, 0x10009U, 0x10016U, 0x10017U, 0x10014U, 0x10015U,
|
||||||
|
0x10012U, 0x10013U, 0x10010U, 0x10011U, 0x05104U, 0x44802U, 0x44801U, 0x44800U, 0x05100U, 0x05101U, 0x10018U, 0x28400U, 0x00380U,
|
||||||
|
0x00381U, 0x22005U, 0x22004U, 0x22003U, 0x22002U, 0x22001U, 0x22000U, 0x06020U, 0x06021U, 0x50101U, 0x50100U, 0x11800U, 0x11801U,
|
||||||
|
0x22009U, 0x22008U, 0x45001U, 0x45000U, 0x08221U, 0x08220U, 0x04902U, 0x22012U, 0x04900U, 0x22010U, 0x06030U, 0x45008U, 0x08229U,
|
||||||
|
0x08228U, 0x11810U, 0x11811U, 0x04908U, 0x22018U, 0x06008U, 0x06009U, 0x08211U, 0x08210U, 0x100C2U, 0x22022U, 0x100C0U, 0x22020U,
|
||||||
|
0x06000U, 0x06001U, 0x06002U, 0x06003U, 0x06004U, 0x40240U, 0x06006U, 0x40242U, 0x08203U, 0x08202U, 0x08201U, 0x08200U, 0x08207U,
|
||||||
|
0x08206U, 0x08205U, 0x08204U, 0x06010U, 0x20900U, 0x08209U, 0x08208U, 0x61002U, 0x20904U, 0x61000U, 0x61001U, 0x29020U, 0x29021U,
|
||||||
|
0x100A4U, 0x22044U, 0x100A2U, 0x22042U, 0x100A0U, 0x22040U, 0x20504U, 0x40224U, 0x0D005U, 0x0D004U, 0x20500U, 0x40220U, 0x0D001U,
|
||||||
|
0x0D000U, 0x03204U, 0x18104U, 0x08261U, 0x08260U, 0x03200U, 0x18100U, 0x03202U, 0x18102U, 0x11421U, 0x11420U, 0x00000U, 0x11422U,
|
||||||
|
0x03208U, 0x18108U, 0x0D011U, 0x0D010U, 0x29000U, 0x29001U, 0x10084U, 0x04500U, 0x10082U, 0x40208U, 0x10080U, 0x10081U, 0x06040U,
|
||||||
|
0x40204U, 0x06042U, 0x40206U, 0x40201U, 0x40200U, 0x10088U, 0x40202U, 0x29010U, 0x08242U, 0x08241U, 0x08240U, 0x10092U, 0x40218U,
|
||||||
|
0x10090U, 0x10091U, 0x11401U, 0x11400U, 0x11403U, 0x11402U, 0x40211U, 0x40210U, 0x10098U, 0x40212U, 0x00400U, 0x00401U, 0x00402U,
|
||||||
|
0x00403U, 0x00404U, 0x00405U, 0x00406U, 0x00407U, 0x00408U, 0x00409U, 0x0040AU, 0x02140U, 0x0040CU, 0x0040DU, 0x01091U, 0x01090U,
|
||||||
|
0x00410U, 0x00411U, 0x00412U, 0x00413U, 0x00414U, 0x00860U, 0x01089U, 0x01088U, 0x00418U, 0x38000U, 0x01085U, 0x01084U, 0x01083U,
|
||||||
|
0x01082U, 0x01081U, 0x01080U, 0x00420U, 0x00421U, 0x00422U, 0x00423U, 0x00424U, 0x00850U, 0x42080U, 0x42081U, 0x00428U, 0x00429U,
|
||||||
|
0x48801U, 0x48800U, 0x09100U, 0x12200U, 0x24401U, 0x24400U, 0x00430U, 0x00844U, 0x00432U, 0x00846U, 0x00841U, 0x00840U, 0x1C000U,
|
||||||
|
0x00842U, 0x00438U, 0x0084CU, 0x010A5U, 0x010A4U, 0x00849U, 0x00848U, 0x010A1U, 0x010A0U, 0x00440U, 0x00441U, 0x00442U, 0x02108U,
|
||||||
|
0x00444U, 0x00830U, 0x70001U, 0x70000U, 0x00448U, 0x02102U, 0x02101U, 0x02100U, 0x20280U, 0x20281U, 0x02105U, 0x02104U, 0x00450U,
|
||||||
|
0x00824U, 0x00452U, 0x00826U, 0x00821U, 0x00820U, 0x00823U, 0x00822U, 0x24802U, 0x02112U, 0x24800U, 0x02110U, 0x00829U, 0x00828U,
|
||||||
|
0x48400U, 0x010C0U, 0x00460U, 0x00814U, 0x04281U, 0x04280U, 0x00811U, 0x00810U, 0x00813U, 0x00812U, 0x54000U, 0x54001U, 0x02121U,
|
||||||
|
0x02120U, 0x00819U, 0x00818U, 0x0081BU, 0x0081AU, 0x00805U, 0x00804U, 0x41100U, 0x00806U, 0x00801U, 0x00800U, 0x00803U, 0x00802U,
|
||||||
|
0x0A080U, 0x0080CU, 0x0A082U, 0x0080EU, 0x00809U, 0x00808U, 0x0080BU, 0x0080AU, 0x00480U, 0x00481U, 0x00482U, 0x00483U, 0x00484U,
|
||||||
|
0x14100U, 0x42020U, 0x01018U, 0x00488U, 0x00489U, 0x01015U, 0x01014U, 0x20240U, 0x01012U, 0x01011U, 0x01010U, 0x00490U, 0x00491U,
|
||||||
|
0x0100DU, 0x0100CU, 0x0100BU, 0x0100AU, 0x01009U, 0x01008U, 0x40900U, 0x01006U, 0x01005U, 0x01004U, 0x01003U, 0x01002U, 0x01001U,
|
||||||
|
0x01000U, 0x004A0U, 0x004A1U, 0x42004U, 0x04240U, 0x42002U, 0x42003U, 0x42000U, 0x42001U, 0x30102U, 0x30103U, 0x30100U, 0x30101U,
|
||||||
|
0x4200AU, 0x01032U, 0x42008U, 0x01030U, 0x25000U, 0x25001U, 0x08501U, 0x08500U, 0x008C1U, 0x008C0U, 0x42010U, 0x01028U, 0x0A040U,
|
||||||
|
0x0A041U, 0x01025U, 0x01024U, 0x01023U, 0x01022U, 0x01021U, 0x01020U, 0x004C0U, 0x49000U, 0x04221U, 0x04220U, 0x20208U, 0x20209U,
|
||||||
|
0x08900U, 0x08901U, 0x20204U, 0x20205U, 0x02181U, 0x02180U, 0x20200U, 0x20201U, 0x20202U, 0x01050U, 0x0A028U, 0x008A4U, 0x0104DU,
|
||||||
|
0x0104CU, 0x008A1U, 0x008A0U, 0x01049U, 0x01048U, 0x0A020U, 0x0A021U, 0x01045U, 0x01044U, 0x20210U, 0x01042U, 0x01041U, 0x01040U,
|
||||||
|
0x04203U, 0x04202U, 0x04201U, 0x04200U, 0x00891U, 0x00890U, 0x42040U, 0x04204U, 0x0A010U, 0x0A011U, 0x01C00U, 0x04208U, 0x20220U,
|
||||||
|
0x40500U, 0x20222U, 0x40502U, 0x0A008U, 0x00884U, 0x04211U, 0x04210U, 0x00881U, 0x00880U, 0x00883U, 0x00882U, 0x0A000U, 0x0A001U,
|
||||||
|
0x0A002U, 0x0A003U, 0x0A004U, 0x00888U, 0x01061U, 0x01060U, 0x00500U, 0x00501U, 0x00502U, 0x02048U, 0x00504U, 0x14080U, 0x00506U,
|
||||||
|
0x14082U, 0x00508U, 0x02042U, 0x02041U, 0x02040U, 0x09020U, 0x09021U, 0x44200U, 0x02044U, 0x00510U, 0x00511U, 0x10A01U, 0x10A00U,
|
||||||
|
0x4A001U, 0x4A000U, 0x4A003U, 0x4A002U, 0x40880U, 0x40881U, 0x02051U, 0x02050U, 0x40884U, 0x01182U, 0x01181U, 0x01180U, 0x00520U,
|
||||||
|
0x60200U, 0x00522U, 0x60202U, 0x09008U, 0x09009U, 0x0900AU, 0x0900BU, 0x09004U, 0x09005U, 0x30080U, 0x02060U, 0x09000U, 0x09001U,
|
||||||
|
0x09002U, 0x09003U, 0x41042U, 0x08482U, 0x41040U, 0x08480U, 0x00941U, 0x00940U, 0x41044U, 0x00942U, 0x09014U, 0x09015U, 0x02C04U,
|
||||||
|
0x08488U, 0x09010U, 0x09011U, 0x02C00U, 0x02C01U, 0x00540U, 0x0200AU, 0x02009U, 0x02008U, 0x08882U, 0x0200EU, 0x08880U, 0x0200CU,
|
||||||
|
0x02003U, 0x02002U, 0x02001U, 0x02000U, 0x02007U, 0x02006U, 0x02005U, 0x02004U, 0x0C200U, 0x0C201U, 0x41020U, 0x02018U, 0x00921U,
|
||||||
|
0x00920U, 0x41024U, 0x00922U, 0x02013U, 0x02012U, 0x02011U, 0x02010U, 0x02017U, 0x02016U, 0x02015U, 0x02014U, 0x41012U, 0x0202AU,
|
||||||
|
0x41010U, 0x02028U, 0x26000U, 0x00910U, 0x10600U, 0x10601U, 0x02023U, 0x02022U, 0x02021U, 0x02020U, 0x09040U, 0x40480U, 0x02025U,
|
||||||
|
0x02024U, 0x41002U, 0x00904U, 0x41000U, 0x41001U, 0x00901U, 0x00900U, 0x41004U, 0x00902U, 0x4100AU, 0x02032U, 0x41008U, 0x02030U,
|
||||||
|
0x00909U, 0x00908U, 0x28201U, 0x28200U, 0x00580U, 0x14004U, 0x00582U, 0x14006U, 0x14001U, 0x14000U, 0x08840U, 0x14002U, 0x40810U,
|
||||||
|
0x40811U, 0x30020U, 0x020C0U, 0x14009U, 0x14008U, 0x01111U, 0x01110U, 0x40808U, 0x40809U, 0x08421U, 0x08420U, 0x14011U, 0x14010U,
|
||||||
|
0x01109U, 0x01108U, 0x40800U, 0x40801U, 0x40802U, 0x01104U, 0x40804U, 0x01102U, 0x01101U, 0x01100U, 0x03801U, 0x03800U, 0x30008U,
|
||||||
|
0x08410U, 0x14021U, 0x14020U, 0x42100U, 0x42101U, 0x30002U, 0x30003U, 0x30000U, 0x30001U, 0x09080U, 0x40440U, 0x30004U, 0x30005U,
|
||||||
|
0x08403U, 0x08402U, 0x08401U, 0x08400U, 0x08407U, 0x08406U, 0x08405U, 0x08404U, 0x40820U, 0x40821U, 0x30010U, 0x08408U, 0x40824U,
|
||||||
|
0x01122U, 0x01121U, 0x01120U, 0x08806U, 0x0208AU, 0x08804U, 0x02088U, 0x08802U, 0x14040U, 0x08800U, 0x08801U, 0x02083U, 0x02082U,
|
||||||
|
0x02081U, 0x02080U, 0x20300U, 0x40420U, 0x08808U, 0x02084U, 0x03404U, 0x03405U, 0x08814U, 0x02098U, 0x03400U, 0x03401U, 0x08810U,
|
||||||
|
0x08811U, 0x40840U, 0x40841U, 0x02091U, 0x02090U, 0x40844U, 0x01142U, 0x01141U, 0x01140U, 0x04303U, 0x04302U, 0x04301U, 0x04300U,
|
||||||
|
0x40409U, 0x40408U, 0x08820U, 0x08821U, 0x40405U, 0x40404U, 0x30040U, 0x020A0U, 0x40401U, 0x40400U, 0x40403U, 0x40402U, 0x41082U,
|
||||||
|
0x08442U, 0x41080U, 0x08440U, 0x00981U, 0x00980U, 0x41084U, 0x00982U, 0x0A100U, 0x11200U, 0x0A102U, 0x11202U, 0x40411U, 0x40410U,
|
||||||
|
0x40413U, 0x40412U, 0x00600U, 0x00601U, 0x00602U, 0x00603U, 0x00604U, 0x00605U, 0x00606U, 0x00607U, 0x00608U, 0x05800U, 0x0060AU,
|
||||||
|
0x05802U, 0x200C0U, 0x12020U, 0x44100U, 0x44101U, 0x00610U, 0x00611U, 0x10901U, 0x10900U, 0x51000U, 0x51001U, 0x51002U, 0x10904U,
|
||||||
|
0x00618U, 0x05810U, 0x01285U, 0x01284U, 0x51008U, 0x01282U, 0x01281U, 0x01280U, 0x00620U, 0x60100U, 0x040C1U, 0x040C0U, 0x12009U,
|
||||||
|
0x12008U, 0x21800U, 0x21801U, 0x12005U, 0x12004U, 0x12007U, 0x12006U, 0x12001U, 0x12000U, 0x12003U, 0x12002U, 0x00630U, 0x00A44U,
|
||||||
|
0x040D1U, 0x040D0U, 0x00A41U, 0x00A40U, 0x21810U, 0x00A42U, 0x12015U, 0x12014U, 0x00000U, 0x12016U, 0x12011U, 0x12010U, 0x12013U,
|
||||||
|
0x12012U, 0x00640U, 0x00641U, 0x040A1U, 0x040A0U, 0x20088U, 0x20089U, 0x2008AU, 0x040A4U, 0x20084U, 0x20085U, 0x19000U, 0x02300U,
|
||||||
|
0x20080U, 0x20081U, 0x20082U, 0x20083U, 0x0C100U, 0x0C101U, 0x21401U, 0x21400U, 0x00A21U, 0x00A20U, 0x00A23U, 0x00A22U, 0x20094U,
|
||||||
|
0x20095U, 0x19010U, 0x21408U, 0x20090U, 0x20091U, 0x20092U, 0x28120U, 0x04083U, 0x04082U, 0x04081U, 0x04080U, 0x00A11U, 0x00A10U,
|
||||||
|
0x10500U, 0x04084U, 0x200A4U, 0x0408AU, 0x04089U, 0x04088U, 0x200A0U, 0x12040U, 0x200A2U, 0x12042U, 0x00A05U, 0x00A04U, 0x04091U,
|
||||||
|
0x04090U, 0x00A01U, 0x00A00U, 0x00A03U, 0x00A02U, 0x05404U, 0x00A0CU, 0x28105U, 0x28104U, 0x05400U, 0x00A08U, 0x28101U, 0x28100U,
|
||||||
|
0x00680U, 0x00681U, 0x04061U, 0x04060U, 0x20048U, 0x20049U, 0x2004AU, 0x04064U, 0x20044U, 0x20045U, 0x50401U, 0x50400U, 0x20040U,
|
||||||
|
0x20041U, 0x20042U, 0x01210U, 0x68002U, 0x68003U, 0x68000U, 0x68001U, 0x04C02U, 0x0120AU, 0x04C00U, 0x01208U, 0x20054U, 0x01206U,
|
||||||
|
0x01205U, 0x01204U, 0x20050U, 0x01202U, 0x01201U, 0x01200U, 0x18800U, 0x04042U, 0x04041U, 0x04040U, 0x42202U, 0x04046U, 0x42200U,
|
||||||
|
0x04044U, 0x20064U, 0x0404AU, 0x04049U, 0x04048U, 0x20060U, 0x12080U, 0x20062U, 0x12082U, 0x18810U, 0x04052U, 0x04051U, 0x04050U,
|
||||||
|
0x4C009U, 0x4C008U, 0x42210U, 0x04054U, 0x20C01U, 0x20C00U, 0x20C03U, 0x20C02U, 0x4C001U, 0x4C000U, 0x01221U, 0x01220U, 0x2000CU,
|
||||||
|
0x04022U, 0x04021U, 0x04020U, 0x20008U, 0x20009U, 0x2000AU, 0x04024U, 0x20004U, 0x20005U, 0x20006U, 0x04028U, 0x20000U, 0x20001U,
|
||||||
|
0x20002U, 0x20003U, 0x2001CU, 0x04032U, 0x04031U, 0x04030U, 0x20018U, 0x18400U, 0x2001AU, 0x18402U, 0x20014U, 0x20015U, 0x20016U,
|
||||||
|
0x01244U, 0x20010U, 0x20011U, 0x20012U, 0x01240U, 0x04003U, 0x04002U, 0x04001U, 0x04000U, 0x20028U, 0x04006U, 0x04005U, 0x04004U,
|
||||||
|
0x20024U, 0x0400AU, 0x04009U, 0x04008U, 0x20020U, 0x20021U, 0x20022U, 0x0400CU, 0x04013U, 0x04012U, 0x04011U, 0x04010U, 0x00A81U,
|
||||||
|
0x00A80U, 0x04015U, 0x04014U, 0x0A200U, 0x11100U, 0x04019U, 0x04018U, 0x20030U, 0x20031U, 0x50800U, 0x50801U, 0x00700U, 0x60020U,
|
||||||
|
0x10811U, 0x10810U, 0x4400AU, 0x60024U, 0x44008U, 0x44009U, 0x44006U, 0x02242U, 0x44004U, 0x02240U, 0x44002U, 0x44003U, 0x44000U,
|
||||||
|
0x44001U, 0x0C040U, 0x10802U, 0x10801U, 0x10800U, 0x0C044U, 0x10806U, 0x10805U, 0x10804U, 0x23000U, 0x23001U, 0x10809U, 0x10808U,
|
||||||
|
0x44012U, 0x44013U, 0x44010U, 0x44011U, 0x60001U, 0x60000U, 0x60003U, 0x60002U, 0x60005U, 0x60004U, 0x10440U, 0x10441U, 0x60009U,
|
||||||
|
0x60008U, 0x44024U, 0x6000AU, 0x09200U, 0x12100U, 0x44020U, 0x44021U, 0x60011U, 0x60010U, 0x10821U, 0x10820U, 0x07003U, 0x07002U,
|
||||||
|
0x07001U, 0x07000U, 0x23020U, 0x60018U, 0x28045U, 0x28044U, 0x09210U, 0x28042U, 0x28041U, 0x28040U, 0x0C010U, 0x0C011U, 0x02209U,
|
||||||
|
0x02208U, 0x10422U, 0x10423U, 0x10420U, 0x10421U, 0x02203U, 0x02202U, 0x02201U, 0x02200U, 0x20180U, 0x20181U, 0x44040U, 0x02204U,
|
||||||
|
0x0C000U, 0x0C001U, 0x0C002U, 0x10840U, 0x0C004U, 0x0C005U, 0x0C006U, 0x10844U, 0x0C008U, 0x0C009U, 0x02211U, 0x02210U, 0x0C00CU,
|
||||||
|
0x28022U, 0x28021U, 0x28020U, 0x60041U, 0x60040U, 0x10404U, 0x04180U, 0x10402U, 0x10403U, 0x10400U, 0x10401U, 0x02223U, 0x02222U,
|
||||||
|
0x02221U, 0x02220U, 0x1040AU, 0x28012U, 0x10408U, 0x28010U, 0x0C020U, 0x0C021U, 0x41200U, 0x41201U, 0x00B01U, 0x00B00U, 0x10410U,
|
||||||
|
0x28008U, 0x11081U, 0x11080U, 0x28005U, 0x28004U, 0x28003U, 0x28002U, 0x28001U, 0x28000U, 0x52040U, 0x14204U, 0x22405U, 0x22404U,
|
||||||
|
0x14201U, 0x14200U, 0x22401U, 0x22400U, 0x20144U, 0x20145U, 0x44084U, 0x022C0U, 0x20140U, 0x20141U, 0x44080U, 0x44081U, 0x40A08U,
|
||||||
|
0x10882U, 0x10881U, 0x10880U, 0x14211U, 0x14210U, 0x1A008U, 0x10884U, 0x40A00U, 0x40A01U, 0x40A02U, 0x01304U, 0x1A002U, 0x01302U,
|
||||||
|
0x1A000U, 0x01300U, 0x60081U, 0x60080U, 0x04141U, 0x04140U, 0x60085U, 0x60084U, 0x104C0U, 0x04144U, 0x06400U, 0x06401U, 0x30200U,
|
||||||
|
0x30201U, 0x06404U, 0x40640U, 0x30204U, 0x30205U, 0x08603U, 0x08602U, 0x08601U, 0x08600U, 0x00000U, 0x08606U, 0x08605U, 0x08604U,
|
||||||
|
0x11041U, 0x11040U, 0x30210U, 0x11042U, 0x11045U, 0x11044U, 0x1A020U, 0x01320U, 0x52000U, 0x52001U, 0x04121U, 0x04120U, 0x20108U,
|
||||||
|
0x20109U, 0x08A00U, 0x08A01U, 0x20104U, 0x20105U, 0x02281U, 0x02280U, 0x20100U, 0x20101U, 0x20102U, 0x20103U, 0x0C080U, 0x0C081U,
|
||||||
|
0x0C082U, 0x04130U, 0x0C084U, 0x06808U, 0x08A10U, 0x08A11U, 0x11021U, 0x11020U, 0x11023U, 0x11022U, 0x20110U, 0x06800U, 0x20112U,
|
||||||
|
0x06802U, 0x04103U, 0x04102U, 0x04101U, 0x04100U, 0x10482U, 0x04106U, 0x10480U, 0x04104U, 0x11011U, 0x11010U, 0x04109U, 0x04108U,
|
||||||
|
0x20120U, 0x40600U, 0x20122U, 0x40602U, 0x11009U, 0x11008U, 0x22800U, 0x04110U, 0x1100DU, 0x1100CU, 0x22804U, 0x04114U, 0x11001U,
|
||||||
|
0x11000U, 0x11003U, 0x11002U, 0x11005U, 0x11004U, 0x28081U, 0x28080U};
|
||||||
|
|
||||||
|
#define X18 0x00040000 /* vector representation of X^{18} */
|
||||||
|
#define X11 0x00000800 /* vector representation of X^{11} */
|
||||||
|
#define MASK8 0xfffff800 /* auxiliary vector for testing */
|
||||||
|
#define GENPOL 0x00000c75 /* generator polinomial, g(x) */
|
||||||
|
|
||||||
|
CDMRSlotType::CDMRSlotType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t CDMRSlotType::getSyndrome1987(uint32_t pattern) const
|
||||||
|
/*
|
||||||
|
* Compute the syndrome corresponding to the given pattern, i.e., the
|
||||||
|
* remainder after dividing the pattern (when considering it as the vector
|
||||||
|
* representation of a polynomial) by the generator polynomial, GENPOL.
|
||||||
|
* In the program this pattern has several meanings: (1) pattern = infomation
|
||||||
|
* bits, when constructing the encoding table; (2) pattern = error pattern,
|
||||||
|
* when constructing the decoding table; and (3) pattern = received vector, to
|
||||||
|
* obtain its syndrome in decoding.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned int aux = X18;
|
||||||
|
|
||||||
|
if (pattern >= X11) {
|
||||||
|
while (pattern & MASK8) {
|
||||||
|
while (!(aux & pattern))
|
||||||
|
aux = aux >> 1;
|
||||||
|
|
||||||
|
pattern ^= (aux / X11) * GENPOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CDMRSlotType::decode2087(const uint8_t* data) const
|
||||||
|
{
|
||||||
|
uint32_t code = (data[0U] << 11) + (data[1U] << 3) + (data[2U] >> 5);
|
||||||
|
uint32_t syndrome = getSyndrome1987(code);
|
||||||
|
uint32_t error_pattern = DECODING_TABLE_1987[syndrome];
|
||||||
|
|
||||||
|
if (error_pattern != 0x00U)
|
||||||
|
code ^= error_pattern;
|
||||||
|
|
||||||
|
return code >> 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRSlotType::decode(const uint8_t* frame, uint8_t& colorCode, uint8_t& dataType) const
|
||||||
|
{
|
||||||
|
uint8_t slotType[3U];
|
||||||
|
slotType[0U] = (frame[12U] << 2) & 0xFCU;
|
||||||
|
slotType[0U] |= (frame[13U] >> 6) & 0x03U;
|
||||||
|
|
||||||
|
slotType[1U] = (frame[13U] << 2) & 0xC0U;
|
||||||
|
slotType[1U] |= (frame[19U] << 2) & 0x3CU;
|
||||||
|
slotType[1U] |= (frame[20U] >> 6) & 0x03U;
|
||||||
|
|
||||||
|
slotType[2U] = (frame[20U] << 2) & 0xF0U;
|
||||||
|
|
||||||
|
uint8_t code = decode2087(slotType);
|
||||||
|
|
||||||
|
colorCode = (code >> 4) & 0x0FU;
|
||||||
|
dataType = (code >> 0) & 0x0FU;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDMRSlotType::encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) const
|
||||||
|
{
|
||||||
|
uint8_t slotType[3U];
|
||||||
|
slotType[0U] = (colorCode << 4) & 0xF0U;
|
||||||
|
slotType[0U] |= (dataType << 0) & 0x0FU;
|
||||||
|
|
||||||
|
uint16_t cksum = ENCODING_TABLE_2087[slotType[0U]];
|
||||||
|
|
||||||
|
slotType[1U] = (cksum >> 0) & 0xFFU;
|
||||||
|
slotType[2U] = (cksum >> 8) & 0xFFU;
|
||||||
|
|
||||||
|
frame[12U] = (frame[12U] & 0xC0U) | ((slotType[0U] >> 2) & 0x3FU);
|
||||||
|
frame[13U] = (frame[13U] & 0x0FU) | ((slotType[0U] << 6) & 0xC0U) | ((slotType[1U] >> 2) & 0x30U);
|
||||||
|
frame[19U] = (frame[19U] & 0xF0U) | ((slotType[1U] >> 2) & 0x0FU);
|
||||||
|
frame[20U] = (frame[20U] & 0x03U) | ((slotType[1U] << 6) & 0xC0U) | ((slotType[2U] >> 2) & 0x3CU);
|
||||||
|
}
|
||||||
|
|
||||||
37
DMRSlotType.h
Normal file
37
DMRSlotType.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DMRSLOTTYPE_H)
|
||||||
|
#define DMRSLOTTYPE_H
|
||||||
|
|
||||||
|
class CDMRSlotType {
|
||||||
|
public:
|
||||||
|
CDMRSlotType();
|
||||||
|
|
||||||
|
void decode(const uint8_t* frame, uint8_t& colorCode, uint8_t& dataType) const;
|
||||||
|
|
||||||
|
void encode(uint8_t colorCode, uint8_t dataType, uint8_t* frame) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint8_t decode2087(const uint8_t* data) const;
|
||||||
|
uint32_t getSyndrome1987(uint32_t pattern) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
45
DStarDefines.h
Normal file
45
DStarDefines.h
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DSTARDEFINES_H)
|
||||||
|
#define DSTARDEFINES_H
|
||||||
|
|
||||||
|
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
|
||||||
|
const unsigned int DSTAR_HEADER_LENGTH_BITS = DSTAR_HEADER_LENGTH_BYTES * 8U;
|
||||||
|
|
||||||
|
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
|
||||||
|
const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U;
|
||||||
|
|
||||||
|
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
|
||||||
|
const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U;
|
||||||
|
|
||||||
|
const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
|
const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U;
|
||||||
|
const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U;
|
||||||
|
|
||||||
|
const uint8_t DSTAR_DATA_SYNC_LENGTH_BYTES = 3U;
|
||||||
|
const uint8_t DSTAR_DATA_SYNC_LENGTH_BITS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
|
||||||
|
|
||||||
|
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
|
||||||
|
|
||||||
|
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
|
||||||
|
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
|
||||||
|
|
||||||
|
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
|
||||||
|
|
||||||
|
#endif
|
||||||
640
DStarRX.cpp
Normal file
640
DStarRX.cpp
Normal file
|
|
@ -0,0 +1,640 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "DStarRX.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
const unsigned int MAX_SYNC_BITS = 50U * 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;
|
||||||
|
|
||||||
|
// D-Star bit order version of 0x55 0x55 0x6E 0x0A
|
||||||
|
const uint32_t FRAME_SYNC_DATA = 0x00557650U;
|
||||||
|
const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU;
|
||||||
|
const uint8_t FRAME_SYNC_ERRS = 2U;
|
||||||
|
|
||||||
|
// D-Star bit order version of 0x55 0x2D 0x16
|
||||||
|
const uint32_t DATA_SYNC_DATA = 0x00AAB468U;
|
||||||
|
const uint32_t DATA_SYNC_MASK = 0x00FFFFFFU;
|
||||||
|
const uint8_t DATA_SYNC_ERRS = 2U;
|
||||||
|
|
||||||
|
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
|
||||||
|
const uint32_t END_SYNC_DATA = 0xAAAA135EU;
|
||||||
|
const uint32_t END_SYNC_MASK = 0xFFFFFFFFU;
|
||||||
|
const uint8_t END_SYNC_ERRS = 3U;
|
||||||
|
|
||||||
|
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_TABLE2[] = {0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU};
|
||||||
|
const uint8_t BIT_MASK_TABLE3[] = {0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U};
|
||||||
|
|
||||||
|
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE1[(i)&7]) : (p[(i)>>3] & BIT_MASK_TABLE0[(i)&7])
|
||||||
|
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7])
|
||||||
|
|
||||||
|
#define WRITE_BIT2(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE3[(i)&7]) : (p[(i)>>3] & BIT_MASK_TABLE2[(i)&7])
|
||||||
|
#define READ_BIT2(p,i) (p[(i)>>3] & BIT_MASK_TABLE3[(i)&7])
|
||||||
|
|
||||||
|
const uint8_t INTERLEAVE_TABLE_RX[] = {
|
||||||
|
0x00U, 0x00U, 0x03U, 0x00U, 0x06U, 0x00U, 0x09U, 0x00U, 0x0CU, 0x00U,
|
||||||
|
0x0FU, 0x00U, 0x12U, 0x00U, 0x15U, 0x00U, 0x18U, 0x00U, 0x1BU, 0x00U,
|
||||||
|
0x1EU, 0x00U, 0x21U, 0x00U, 0x24U, 0x00U, 0x27U, 0x00U, 0x2AU, 0x00U,
|
||||||
|
0x2DU, 0x00U, 0x30U, 0x00U, 0x33U, 0x00U, 0x36U, 0x00U, 0x39U, 0x00U,
|
||||||
|
0x3CU, 0x00U, 0x3FU, 0x00U, 0x42U, 0x00U, 0x45U, 0x00U, 0x48U, 0x00U,
|
||||||
|
0x4BU, 0x00U, 0x4EU, 0x00U, 0x51U, 0x00U, 0x00U, 0x01U, 0x03U, 0x01U,
|
||||||
|
0x06U, 0x01U, 0x09U, 0x01U, 0x0CU, 0x01U, 0x0FU, 0x01U, 0x12U, 0x01U,
|
||||||
|
0x15U, 0x01U, 0x18U, 0x01U, 0x1BU, 0x01U, 0x1EU, 0x01U, 0x21U, 0x01U,
|
||||||
|
0x24U, 0x01U, 0x27U, 0x01U, 0x2AU, 0x01U, 0x2DU, 0x01U, 0x30U, 0x01U,
|
||||||
|
0x33U, 0x01U, 0x36U, 0x01U, 0x39U, 0x01U, 0x3CU, 0x01U, 0x3FU, 0x01U,
|
||||||
|
0x42U, 0x01U, 0x45U, 0x01U, 0x48U, 0x01U, 0x4BU, 0x01U, 0x4EU, 0x01U,
|
||||||
|
0x51U, 0x01U, 0x00U, 0x02U, 0x03U, 0x02U, 0x06U, 0x02U, 0x09U, 0x02U,
|
||||||
|
0x0CU, 0x02U, 0x0FU, 0x02U, 0x12U, 0x02U, 0x15U, 0x02U, 0x18U, 0x02U,
|
||||||
|
0x1BU, 0x02U, 0x1EU, 0x02U, 0x21U, 0x02U, 0x24U, 0x02U, 0x27U, 0x02U,
|
||||||
|
0x2AU, 0x02U, 0x2DU, 0x02U, 0x30U, 0x02U, 0x33U, 0x02U, 0x36U, 0x02U,
|
||||||
|
0x39U, 0x02U, 0x3CU, 0x02U, 0x3FU, 0x02U, 0x42U, 0x02U, 0x45U, 0x02U,
|
||||||
|
0x48U, 0x02U, 0x4BU, 0x02U, 0x4EU, 0x02U, 0x51U, 0x02U, 0x00U, 0x03U,
|
||||||
|
0x03U, 0x03U, 0x06U, 0x03U, 0x09U, 0x03U, 0x0CU, 0x03U, 0x0FU, 0x03U,
|
||||||
|
0x12U, 0x03U, 0x15U, 0x03U, 0x18U, 0x03U, 0x1BU, 0x03U, 0x1EU, 0x03U,
|
||||||
|
0x21U, 0x03U, 0x24U, 0x03U, 0x27U, 0x03U, 0x2AU, 0x03U, 0x2DU, 0x03U,
|
||||||
|
0x30U, 0x03U, 0x33U, 0x03U, 0x36U, 0x03U, 0x39U, 0x03U, 0x3CU, 0x03U,
|
||||||
|
0x3FU, 0x03U, 0x42U, 0x03U, 0x45U, 0x03U, 0x48U, 0x03U, 0x4BU, 0x03U,
|
||||||
|
0x4EU, 0x03U, 0x51U, 0x03U, 0x00U, 0x04U, 0x03U, 0x04U, 0x06U, 0x04U,
|
||||||
|
0x09U, 0x04U, 0x0CU, 0x04U, 0x0FU, 0x04U, 0x12U, 0x04U, 0x15U, 0x04U,
|
||||||
|
0x18U, 0x04U, 0x1BU, 0x04U, 0x1EU, 0x04U, 0x21U, 0x04U, 0x24U, 0x04U,
|
||||||
|
0x27U, 0x04U, 0x2AU, 0x04U, 0x2DU, 0x04U, 0x30U, 0x04U, 0x33U, 0x04U,
|
||||||
|
0x36U, 0x04U, 0x39U, 0x04U, 0x3CU, 0x04U, 0x3FU, 0x04U, 0x42U, 0x04U,
|
||||||
|
0x45U, 0x04U, 0x48U, 0x04U, 0x4BU, 0x04U, 0x4EU, 0x04U, 0x51U, 0x04U,
|
||||||
|
0x00U, 0x05U, 0x03U, 0x05U, 0x06U, 0x05U, 0x09U, 0x05U, 0x0CU, 0x05U,
|
||||||
|
0x0FU, 0x05U, 0x12U, 0x05U, 0x15U, 0x05U, 0x18U, 0x05U, 0x1BU, 0x05U,
|
||||||
|
0x1EU, 0x05U, 0x21U, 0x05U, 0x24U, 0x05U, 0x27U, 0x05U, 0x2AU, 0x05U,
|
||||||
|
0x2DU, 0x05U, 0x30U, 0x05U, 0x33U, 0x05U, 0x36U, 0x05U, 0x39U, 0x05U,
|
||||||
|
0x3CU, 0x05U, 0x3FU, 0x05U, 0x42U, 0x05U, 0x45U, 0x05U, 0x48U, 0x05U,
|
||||||
|
0x4BU, 0x05U, 0x4EU, 0x05U, 0x51U, 0x05U, 0x00U, 0x06U, 0x03U, 0x06U,
|
||||||
|
0x06U, 0x06U, 0x09U, 0x06U, 0x0CU, 0x06U, 0x0FU, 0x06U, 0x12U, 0x06U,
|
||||||
|
0x15U, 0x06U, 0x18U, 0x06U, 0x1BU, 0x06U, 0x1EU, 0x06U, 0x21U, 0x06U,
|
||||||
|
0x24U, 0x06U, 0x27U, 0x06U, 0x2AU, 0x06U, 0x2DU, 0x06U, 0x30U, 0x06U,
|
||||||
|
0x33U, 0x06U, 0x36U, 0x06U, 0x39U, 0x06U, 0x3CU, 0x06U, 0x3FU, 0x06U,
|
||||||
|
0x42U, 0x06U, 0x45U, 0x06U, 0x48U, 0x06U, 0x4BU, 0x06U, 0x4EU, 0x06U,
|
||||||
|
0x51U, 0x06U, 0x00U, 0x07U, 0x03U, 0x07U, 0x06U, 0x07U, 0x09U, 0x07U,
|
||||||
|
0x0CU, 0x07U, 0x0FU, 0x07U, 0x12U, 0x07U, 0x15U, 0x07U, 0x18U, 0x07U,
|
||||||
|
0x1BU, 0x07U, 0x1EU, 0x07U, 0x21U, 0x07U, 0x24U, 0x07U, 0x27U, 0x07U,
|
||||||
|
0x2AU, 0x07U, 0x2DU, 0x07U, 0x30U, 0x07U, 0x33U, 0x07U, 0x36U, 0x07U,
|
||||||
|
0x39U, 0x07U, 0x3CU, 0x07U, 0x3FU, 0x07U, 0x42U, 0x07U, 0x45U, 0x07U,
|
||||||
|
0x48U, 0x07U, 0x4BU, 0x07U, 0x4EU, 0x07U, 0x51U, 0x07U, 0x01U, 0x00U,
|
||||||
|
0x04U, 0x00U, 0x07U, 0x00U, 0x0AU, 0x00U, 0x0DU, 0x00U, 0x10U, 0x00U,
|
||||||
|
0x13U, 0x00U, 0x16U, 0x00U, 0x19U, 0x00U, 0x1CU, 0x00U, 0x1FU, 0x00U,
|
||||||
|
0x22U, 0x00U, 0x25U, 0x00U, 0x28U, 0x00U, 0x2BU, 0x00U, 0x2EU, 0x00U,
|
||||||
|
0x31U, 0x00U, 0x34U, 0x00U, 0x37U, 0x00U, 0x3AU, 0x00U, 0x3DU, 0x00U,
|
||||||
|
0x40U, 0x00U, 0x43U, 0x00U, 0x46U, 0x00U, 0x49U, 0x00U, 0x4CU, 0x00U,
|
||||||
|
0x4FU, 0x00U, 0x52U, 0x00U, 0x01U, 0x01U, 0x04U, 0x01U, 0x07U, 0x01U,
|
||||||
|
0x0AU, 0x01U, 0x0DU, 0x01U, 0x10U, 0x01U, 0x13U, 0x01U, 0x16U, 0x01U,
|
||||||
|
0x19U, 0x01U, 0x1CU, 0x01U, 0x1FU, 0x01U, 0x22U, 0x01U, 0x25U, 0x01U,
|
||||||
|
0x28U, 0x01U, 0x2BU, 0x01U, 0x2EU, 0x01U, 0x31U, 0x01U, 0x34U, 0x01U,
|
||||||
|
0x37U, 0x01U, 0x3AU, 0x01U, 0x3DU, 0x01U, 0x40U, 0x01U, 0x43U, 0x01U,
|
||||||
|
0x46U, 0x01U, 0x49U, 0x01U, 0x4CU, 0x01U, 0x4FU, 0x01U, 0x52U, 0x01U,
|
||||||
|
0x01U, 0x02U, 0x04U, 0x02U, 0x07U, 0x02U, 0x0AU, 0x02U, 0x0DU, 0x02U,
|
||||||
|
0x10U, 0x02U, 0x13U, 0x02U, 0x16U, 0x02U, 0x19U, 0x02U, 0x1CU, 0x02U,
|
||||||
|
0x1FU, 0x02U, 0x22U, 0x02U, 0x25U, 0x02U, 0x28U, 0x02U, 0x2BU, 0x02U,
|
||||||
|
0x2EU, 0x02U, 0x31U, 0x02U, 0x34U, 0x02U, 0x37U, 0x02U, 0x3AU, 0x02U,
|
||||||
|
0x3DU, 0x02U, 0x40U, 0x02U, 0x43U, 0x02U, 0x46U, 0x02U, 0x49U, 0x02U,
|
||||||
|
0x4CU, 0x02U, 0x4FU, 0x02U, 0x52U, 0x02U, 0x01U, 0x03U, 0x04U, 0x03U,
|
||||||
|
0x07U, 0x03U, 0x0AU, 0x03U, 0x0DU, 0x03U, 0x10U, 0x03U, 0x13U, 0x03U,
|
||||||
|
0x16U, 0x03U, 0x19U, 0x03U, 0x1CU, 0x03U, 0x1FU, 0x03U, 0x22U, 0x03U,
|
||||||
|
0x25U, 0x03U, 0x28U, 0x03U, 0x2BU, 0x03U, 0x2EU, 0x03U, 0x31U, 0x03U,
|
||||||
|
0x34U, 0x03U, 0x37U, 0x03U, 0x3AU, 0x03U, 0x3DU, 0x03U, 0x40U, 0x03U,
|
||||||
|
0x43U, 0x03U, 0x46U, 0x03U, 0x49U, 0x03U, 0x4CU, 0x03U, 0x4FU, 0x03U,
|
||||||
|
0x52U, 0x03U, 0x01U, 0x04U, 0x04U, 0x04U, 0x07U, 0x04U, 0x0AU, 0x04U,
|
||||||
|
0x0DU, 0x04U, 0x10U, 0x04U, 0x13U, 0x04U, 0x16U, 0x04U, 0x19U, 0x04U,
|
||||||
|
0x1CU, 0x04U, 0x1FU, 0x04U, 0x22U, 0x04U, 0x25U, 0x04U, 0x28U, 0x04U,
|
||||||
|
0x2BU, 0x04U, 0x2EU, 0x04U, 0x31U, 0x04U, 0x34U, 0x04U, 0x37U, 0x04U,
|
||||||
|
0x3AU, 0x04U, 0x3DU, 0x04U, 0x40U, 0x04U, 0x43U, 0x04U, 0x46U, 0x04U,
|
||||||
|
0x49U, 0x04U, 0x4CU, 0x04U, 0x4FU, 0x04U, 0x01U, 0x05U, 0x04U, 0x05U,
|
||||||
|
0x07U, 0x05U, 0x0AU, 0x05U, 0x0DU, 0x05U, 0x10U, 0x05U, 0x13U, 0x05U,
|
||||||
|
0x16U, 0x05U, 0x19U, 0x05U, 0x1CU, 0x05U, 0x1FU, 0x05U, 0x22U, 0x05U,
|
||||||
|
0x25U, 0x05U, 0x28U, 0x05U, 0x2BU, 0x05U, 0x2EU, 0x05U, 0x31U, 0x05U,
|
||||||
|
0x34U, 0x05U, 0x37U, 0x05U, 0x3AU, 0x05U, 0x3DU, 0x05U, 0x40U, 0x05U,
|
||||||
|
0x43U, 0x05U, 0x46U, 0x05U, 0x49U, 0x05U, 0x4CU, 0x05U, 0x4FU, 0x05U,
|
||||||
|
0x01U, 0x06U, 0x04U, 0x06U, 0x07U, 0x06U, 0x0AU, 0x06U, 0x0DU, 0x06U,
|
||||||
|
0x10U, 0x06U, 0x13U, 0x06U, 0x16U, 0x06U, 0x19U, 0x06U, 0x1CU, 0x06U,
|
||||||
|
0x1FU, 0x06U, 0x22U, 0x06U, 0x25U, 0x06U, 0x28U, 0x06U, 0x2BU, 0x06U,
|
||||||
|
0x2EU, 0x06U, 0x31U, 0x06U, 0x34U, 0x06U, 0x37U, 0x06U, 0x3AU, 0x06U,
|
||||||
|
0x3DU, 0x06U, 0x40U, 0x06U, 0x43U, 0x06U, 0x46U, 0x06U, 0x49U, 0x06U,
|
||||||
|
0x4CU, 0x06U, 0x4FU, 0x06U, 0x01U, 0x07U, 0x04U, 0x07U, 0x07U, 0x07U,
|
||||||
|
0x0AU, 0x07U, 0x0DU, 0x07U, 0x10U, 0x07U, 0x13U, 0x07U, 0x16U, 0x07U,
|
||||||
|
0x19U, 0x07U, 0x1CU, 0x07U, 0x1FU, 0x07U, 0x22U, 0x07U, 0x25U, 0x07U,
|
||||||
|
0x28U, 0x07U, 0x2BU, 0x07U, 0x2EU, 0x07U, 0x31U, 0x07U, 0x34U, 0x07U,
|
||||||
|
0x37U, 0x07U, 0x3AU, 0x07U, 0x3DU, 0x07U, 0x40U, 0x07U, 0x43U, 0x07U,
|
||||||
|
0x46U, 0x07U, 0x49U, 0x07U, 0x4CU, 0x07U, 0x4FU, 0x07U, 0x02U, 0x00U,
|
||||||
|
0x05U, 0x00U, 0x08U, 0x00U, 0x0BU, 0x00U, 0x0EU, 0x00U, 0x11U, 0x00U,
|
||||||
|
0x14U, 0x00U, 0x17U, 0x00U, 0x1AU, 0x00U, 0x1DU, 0x00U, 0x20U, 0x00U,
|
||||||
|
0x23U, 0x00U, 0x26U, 0x00U, 0x29U, 0x00U, 0x2CU, 0x00U, 0x2FU, 0x00U,
|
||||||
|
0x32U, 0x00U, 0x35U, 0x00U, 0x38U, 0x00U, 0x3BU, 0x00U, 0x3EU, 0x00U,
|
||||||
|
0x41U, 0x00U, 0x44U, 0x00U, 0x47U, 0x00U, 0x4AU, 0x00U, 0x4DU, 0x00U,
|
||||||
|
0x50U, 0x00U, 0x02U, 0x01U, 0x05U, 0x01U, 0x08U, 0x01U, 0x0BU, 0x01U,
|
||||||
|
0x0EU, 0x01U, 0x11U, 0x01U, 0x14U, 0x01U, 0x17U, 0x01U, 0x1AU, 0x01U,
|
||||||
|
0x1DU, 0x01U, 0x20U, 0x01U, 0x23U, 0x01U, 0x26U, 0x01U, 0x29U, 0x01U,
|
||||||
|
0x2CU, 0x01U, 0x2FU, 0x01U, 0x32U, 0x01U, 0x35U, 0x01U, 0x38U, 0x01U,
|
||||||
|
0x3BU, 0x01U, 0x3EU, 0x01U, 0x41U, 0x01U, 0x44U, 0x01U, 0x47U, 0x01U,
|
||||||
|
0x4AU, 0x01U, 0x4DU, 0x01U, 0x50U, 0x01U, 0x02U, 0x02U, 0x05U, 0x02U,
|
||||||
|
0x08U, 0x02U, 0x0BU, 0x02U, 0x0EU, 0x02U, 0x11U, 0x02U, 0x14U, 0x02U,
|
||||||
|
0x17U, 0x02U, 0x1AU, 0x02U, 0x1DU, 0x02U, 0x20U, 0x02U, 0x23U, 0x02U,
|
||||||
|
0x26U, 0x02U, 0x29U, 0x02U, 0x2CU, 0x02U, 0x2FU, 0x02U, 0x32U, 0x02U,
|
||||||
|
0x35U, 0x02U, 0x38U, 0x02U, 0x3BU, 0x02U, 0x3EU, 0x02U, 0x41U, 0x02U,
|
||||||
|
0x44U, 0x02U, 0x47U, 0x02U, 0x4AU, 0x02U, 0x4DU, 0x02U, 0x50U, 0x02U,
|
||||||
|
0x02U, 0x03U, 0x05U, 0x03U, 0x08U, 0x03U, 0x0BU, 0x03U, 0x0EU, 0x03U,
|
||||||
|
0x11U, 0x03U, 0x14U, 0x03U, 0x17U, 0x03U, 0x1AU, 0x03U, 0x1DU, 0x03U,
|
||||||
|
0x20U, 0x03U, 0x23U, 0x03U, 0x26U, 0x03U, 0x29U, 0x03U, 0x2CU, 0x03U,
|
||||||
|
0x2FU, 0x03U, 0x32U, 0x03U, 0x35U, 0x03U, 0x38U, 0x03U, 0x3BU, 0x03U,
|
||||||
|
0x3EU, 0x03U, 0x41U, 0x03U, 0x44U, 0x03U, 0x47U, 0x03U, 0x4AU, 0x03U,
|
||||||
|
0x4DU, 0x03U, 0x50U, 0x03U, 0x02U, 0x04U, 0x05U, 0x04U, 0x08U, 0x04U,
|
||||||
|
0x0BU, 0x04U, 0x0EU, 0x04U, 0x11U, 0x04U, 0x14U, 0x04U, 0x17U, 0x04U,
|
||||||
|
0x1AU, 0x04U, 0x1DU, 0x04U, 0x20U, 0x04U, 0x23U, 0x04U, 0x26U, 0x04U,
|
||||||
|
0x29U, 0x04U, 0x2CU, 0x04U, 0x2FU, 0x04U, 0x32U, 0x04U, 0x35U, 0x04U,
|
||||||
|
0x38U, 0x04U, 0x3BU, 0x04U, 0x3EU, 0x04U, 0x41U, 0x04U, 0x44U, 0x04U,
|
||||||
|
0x47U, 0x04U, 0x4AU, 0x04U, 0x4DU, 0x04U, 0x50U, 0x04U, 0x02U, 0x05U,
|
||||||
|
0x05U, 0x05U, 0x08U, 0x05U, 0x0BU, 0x05U, 0x0EU, 0x05U, 0x11U, 0x05U,
|
||||||
|
0x14U, 0x05U, 0x17U, 0x05U, 0x1AU, 0x05U, 0x1DU, 0x05U, 0x20U, 0x05U,
|
||||||
|
0x23U, 0x05U, 0x26U, 0x05U, 0x29U, 0x05U, 0x2CU, 0x05U, 0x2FU, 0x05U,
|
||||||
|
0x32U, 0x05U, 0x35U, 0x05U, 0x38U, 0x05U, 0x3BU, 0x05U, 0x3EU, 0x05U,
|
||||||
|
0x41U, 0x05U, 0x44U, 0x05U, 0x47U, 0x05U, 0x4AU, 0x05U, 0x4DU, 0x05U,
|
||||||
|
0x50U, 0x05U, 0x02U, 0x06U, 0x05U, 0x06U, 0x08U, 0x06U, 0x0BU, 0x06U,
|
||||||
|
0x0EU, 0x06U, 0x11U, 0x06U, 0x14U, 0x06U, 0x17U, 0x06U, 0x1AU, 0x06U,
|
||||||
|
0x1DU, 0x06U, 0x20U, 0x06U, 0x23U, 0x06U, 0x26U, 0x06U, 0x29U, 0x06U,
|
||||||
|
0x2CU, 0x06U, 0x2FU, 0x06U, 0x32U, 0x06U, 0x35U, 0x06U, 0x38U, 0x06U,
|
||||||
|
0x3BU, 0x06U, 0x3EU, 0x06U, 0x41U, 0x06U, 0x44U, 0x06U, 0x47U, 0x06U,
|
||||||
|
0x4AU, 0x06U, 0x4DU, 0x06U, 0x50U, 0x06U, 0x02U, 0x07U, 0x05U, 0x07U,
|
||||||
|
0x08U, 0x07U, 0x0BU, 0x07U, 0x0EU, 0x07U, 0x11U, 0x07U, 0x14U, 0x07U,
|
||||||
|
0x17U, 0x07U, 0x1AU, 0x07U, 0x1DU, 0x07U, 0x20U, 0x07U, 0x23U, 0x07U,
|
||||||
|
0x26U, 0x07U, 0x29U, 0x07U, 0x2CU, 0x07U, 0x2FU, 0x07U, 0x32U, 0x07U,
|
||||||
|
0x35U, 0x07U, 0x38U, 0x07U, 0x3BU, 0x07U, 0x3EU, 0x07U, 0x41U, 0x07U,
|
||||||
|
0x44U, 0x07U, 0x47U, 0x07U, 0x4AU, 0x07U, 0x4DU, 0x07U, 0x50U, 0x07U,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t SCRAMBLE_TABLE_RX[] = {
|
||||||
|
0x70U, 0x4FU, 0x93U, 0x40U, 0x64U, 0x74U, 0x6DU, 0x30U, 0x2BU, 0xE7U,
|
||||||
|
0x2DU, 0x54U, 0x5FU, 0x8AU, 0x1DU, 0x7FU, 0xB8U, 0xA7U, 0x49U, 0x20U,
|
||||||
|
0x32U, 0xBAU, 0x36U, 0x98U, 0x95U, 0xF3U, 0x16U, 0xAAU, 0x2FU, 0xC5U,
|
||||||
|
0x8EU, 0x3FU, 0xDCU, 0xD3U, 0x24U, 0x10U, 0x19U, 0x5DU, 0x1BU, 0xCCU,
|
||||||
|
0xCAU, 0x79U, 0x0BU, 0xD5U, 0x97U, 0x62U, 0xC7U, 0x1FU, 0xEEU, 0x69U,
|
||||||
|
0x12U, 0x88U, 0x8CU, 0xAEU, 0x0DU, 0x66U, 0xE5U, 0xBCU, 0x85U, 0xEAU,
|
||||||
|
0x4BU, 0xB1U, 0xE3U, 0x0FU, 0xF7U, 0x34U, 0x09U, 0x44U, 0x46U, 0xD7U,
|
||||||
|
0x06U, 0xB3U, 0x72U, 0xDEU, 0x42U, 0xF5U, 0xA5U, 0xD8U, 0xF1U, 0x87U,
|
||||||
|
0x7BU, 0x9AU, 0x04U, 0x22U, 0xA3U, 0x6BU, 0x83U, 0x59U, 0x39U, 0x6FU,
|
||||||
|
0x00U};
|
||||||
|
|
||||||
|
const uint16_t CCITT_TABLE[] = {
|
||||||
|
0x0000U, 0x1189U, 0x2312U, 0x329bU, 0x4624U, 0x57adU, 0x6536U, 0x74bfU,
|
||||||
|
0x8c48U, 0x9dc1U, 0xaf5aU, 0xbed3U, 0xca6cU, 0xdbe5U, 0xe97eU, 0xf8f7U,
|
||||||
|
0x1081U, 0x0108U, 0x3393U, 0x221aU, 0x56a5U, 0x472cU, 0x75b7U, 0x643eU,
|
||||||
|
0x9cc9U, 0x8d40U, 0xbfdbU, 0xae52U, 0xdaedU, 0xcb64U, 0xf9ffU, 0xe876U,
|
||||||
|
0x2102U, 0x308bU, 0x0210U, 0x1399U, 0x6726U, 0x76afU, 0x4434U, 0x55bdU,
|
||||||
|
0xad4aU, 0xbcc3U, 0x8e58U, 0x9fd1U, 0xeb6eU, 0xfae7U, 0xc87cU, 0xd9f5U,
|
||||||
|
0x3183U, 0x200aU, 0x1291U, 0x0318U, 0x77a7U, 0x662eU, 0x54b5U, 0x453cU,
|
||||||
|
0xbdcbU, 0xac42U, 0x9ed9U, 0x8f50U, 0xfbefU, 0xea66U, 0xd8fdU, 0xc974U,
|
||||||
|
0x4204U, 0x538dU, 0x6116U, 0x709fU, 0x0420U, 0x15a9U, 0x2732U, 0x36bbU,
|
||||||
|
0xce4cU, 0xdfc5U, 0xed5eU, 0xfcd7U, 0x8868U, 0x99e1U, 0xab7aU, 0xbaf3U,
|
||||||
|
0x5285U, 0x430cU, 0x7197U, 0x601eU, 0x14a1U, 0x0528U, 0x37b3U, 0x263aU,
|
||||||
|
0xdecdU, 0xcf44U, 0xfddfU, 0xec56U, 0x98e9U, 0x8960U, 0xbbfbU, 0xaa72U,
|
||||||
|
0x6306U, 0x728fU, 0x4014U, 0x519dU, 0x2522U, 0x34abU, 0x0630U, 0x17b9U,
|
||||||
|
0xef4eU, 0xfec7U, 0xcc5cU, 0xddd5U, 0xa96aU, 0xb8e3U, 0x8a78U, 0x9bf1U,
|
||||||
|
0x7387U, 0x620eU, 0x5095U, 0x411cU, 0x35a3U, 0x242aU, 0x16b1U, 0x0738U,
|
||||||
|
0xffcfU, 0xee46U, 0xdcddU, 0xcd54U, 0xb9ebU, 0xa862U, 0x9af9U, 0x8b70U,
|
||||||
|
0x8408U, 0x9581U, 0xa71aU, 0xb693U, 0xc22cU, 0xd3a5U, 0xe13eU, 0xf0b7U,
|
||||||
|
0x0840U, 0x19c9U, 0x2b52U, 0x3adbU, 0x4e64U, 0x5fedU, 0x6d76U, 0x7cffU,
|
||||||
|
0x9489U, 0x8500U, 0xb79bU, 0xa612U, 0xd2adU, 0xc324U, 0xf1bfU, 0xe036U,
|
||||||
|
0x18c1U, 0x0948U, 0x3bd3U, 0x2a5aU, 0x5ee5U, 0x4f6cU, 0x7df7U, 0x6c7eU,
|
||||||
|
0xa50aU, 0xb483U, 0x8618U, 0x9791U, 0xe32eU, 0xf2a7U, 0xc03cU, 0xd1b5U,
|
||||||
|
0x2942U, 0x38cbU, 0x0a50U, 0x1bd9U, 0x6f66U, 0x7eefU, 0x4c74U, 0x5dfdU,
|
||||||
|
0xb58bU, 0xa402U, 0x9699U, 0x8710U, 0xf3afU, 0xe226U, 0xd0bdU, 0xc134U,
|
||||||
|
0x39c3U, 0x284aU, 0x1ad1U, 0x0b58U, 0x7fe7U, 0x6e6eU, 0x5cf5U, 0x4d7cU,
|
||||||
|
0xc60cU, 0xd785U, 0xe51eU, 0xf497U, 0x8028U, 0x91a1U, 0xa33aU, 0xb2b3U,
|
||||||
|
0x4a44U, 0x5bcdU, 0x6956U, 0x78dfU, 0x0c60U, 0x1de9U, 0x2f72U, 0x3efbU,
|
||||||
|
0xd68dU, 0xc704U, 0xf59fU, 0xe416U, 0x90a9U, 0x8120U, 0xb3bbU, 0xa232U,
|
||||||
|
0x5ac5U, 0x4b4cU, 0x79d7U, 0x685eU, 0x1ce1U, 0x0d68U, 0x3ff3U, 0x2e7aU,
|
||||||
|
0xe70eU, 0xf687U, 0xc41cU, 0xd595U, 0xa12aU, 0xb0a3U, 0x8238U, 0x93b1U,
|
||||||
|
0x6b46U, 0x7acfU, 0x4854U, 0x59ddU, 0x2d62U, 0x3cebU, 0x0e70U, 0x1ff9U,
|
||||||
|
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
|
||||||
|
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U};
|
||||||
|
|
||||||
|
CDStarRX::CDStarRX() :
|
||||||
|
m_rxState(DSRXS_NONE),
|
||||||
|
m_patternBuffer(0x00U),
|
||||||
|
m_rxBuffer(),
|
||||||
|
m_rxBufferBits(0U),
|
||||||
|
m_dataBits(0U),
|
||||||
|
m_mar(0U),
|
||||||
|
m_pathMetric(),
|
||||||
|
m_pathMemory0(),
|
||||||
|
m_pathMemory1(),
|
||||||
|
m_pathMemory2(),
|
||||||
|
m_pathMemory3(),
|
||||||
|
m_fecOutput()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarRX::reset()
|
||||||
|
{
|
||||||
|
m_rxState = DSRXS_NONE;
|
||||||
|
m_patternBuffer = 0x00U;
|
||||||
|
m_rxBufferBits = 0U;
|
||||||
|
m_dataBits = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarRX::databit(bool bit)
|
||||||
|
{
|
||||||
|
switch (m_rxState) {
|
||||||
|
case DSRXS_NONE:
|
||||||
|
processNone(bit);
|
||||||
|
break;
|
||||||
|
case DSRXS_HEADER:
|
||||||
|
processHeader(bit);
|
||||||
|
break;
|
||||||
|
case DSRXS_DATA:
|
||||||
|
processData(bit);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarRX::processNone(bool bit)
|
||||||
|
{
|
||||||
|
m_patternBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_patternBuffer |= 0x01U;
|
||||||
|
|
||||||
|
// Fuzzy matching of the frame sync sequence
|
||||||
|
if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
|
||||||
|
DEBUG1("DStarRX: found frame sync in None");
|
||||||
|
|
||||||
|
::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES);
|
||||||
|
m_rxBufferBits = 0U;
|
||||||
|
|
||||||
|
m_rxState = DSRXS_HEADER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exact matching of the data sync bit sequence
|
||||||
|
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) {
|
||||||
|
DEBUG1("DStarRX: found data sync in None");
|
||||||
|
|
||||||
|
io.setDecode(true);
|
||||||
|
|
||||||
|
serial.writeDStarData(DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES);
|
||||||
|
|
||||||
|
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||||
|
m_rxBufferBits = 0U;
|
||||||
|
|
||||||
|
m_dataBits = 0U;
|
||||||
|
m_rxState = DSRXS_DATA;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarRX::processHeader(bool bit)
|
||||||
|
{
|
||||||
|
m_patternBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_patternBuffer |= 0x01U;
|
||||||
|
|
||||||
|
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
||||||
|
m_rxBufferBits++;
|
||||||
|
|
||||||
|
// A full FEC header
|
||||||
|
if (m_rxBufferBits == DSTAR_FEC_SECTION_LENGTH_BITS) {
|
||||||
|
// Process the scrambling, interleaving and FEC, then return if the chcksum was correct
|
||||||
|
unsigned char header[DSTAR_HEADER_LENGTH_BYTES];
|
||||||
|
bool ok = rxHeader(m_rxBuffer, header);
|
||||||
|
if (ok) {
|
||||||
|
io.setDecode(true);
|
||||||
|
|
||||||
|
serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES);
|
||||||
|
|
||||||
|
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||||
|
m_rxBufferBits = 0U;
|
||||||
|
|
||||||
|
m_rxState = DSRXS_DATA;
|
||||||
|
m_dataBits = SYNC_POS - DSTAR_DATA_LENGTH_BITS + 1U;
|
||||||
|
} else {
|
||||||
|
// The checksum failed, return to looking for syncs
|
||||||
|
m_rxState = DSRXS_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarRX::processData(bool bit)
|
||||||
|
{
|
||||||
|
m_patternBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_patternBuffer |= 0x01U;
|
||||||
|
|
||||||
|
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
||||||
|
m_rxBufferBits++;
|
||||||
|
|
||||||
|
// Fuzzy matching of the end frame sequences
|
||||||
|
if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) {
|
||||||
|
DEBUG1("DStarRX: Found end sync in Data");
|
||||||
|
io.setDecode(false);
|
||||||
|
|
||||||
|
serial.writeDStarEOT();
|
||||||
|
|
||||||
|
m_rxState = DSRXS_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fuzzy matching of the data sync bit sequence
|
||||||
|
bool syncSeen = false;
|
||||||
|
if (m_dataBits >= SYNC_SCAN_START && m_dataBits <= (SYNC_POS + 1U)) {
|
||||||
|
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) {
|
||||||
|
#if defined(WANT_DEBUG)
|
||||||
|
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");
|
||||||
|
#endif
|
||||||
|
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS;
|
||||||
|
m_dataBits = 0U;
|
||||||
|
syncSeen = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check to see if the sync is arriving late
|
||||||
|
if (m_dataBits == SYNC_POS) {
|
||||||
|
for (uint8_t i = 1U; i <= 3U; i++) {
|
||||||
|
uint32_t syncMask = DATA_SYNC_MASK >> i;
|
||||||
|
uint32_t syncData = DATA_SYNC_DATA >> i;
|
||||||
|
if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) {
|
||||||
|
DEBUG2("DStarRX: found data sync in Data, late", i);
|
||||||
|
m_rxBufferBits -= i;
|
||||||
|
m_dataBits -= i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dataBits++;
|
||||||
|
|
||||||
|
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
||||||
|
if (m_dataBits >= MAX_SYNC_BITS) {
|
||||||
|
DEBUG1("DStarRX: data sync timed out, lost lock");
|
||||||
|
io.setDecode(false);
|
||||||
|
|
||||||
|
serial.writeDStarLost();
|
||||||
|
|
||||||
|
m_rxState = DSRXS_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen
|
||||||
|
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) {
|
||||||
|
if (syncSeen) {
|
||||||
|
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
|
||||||
|
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
|
||||||
|
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
|
||||||
|
}
|
||||||
|
io.setDecode(true);
|
||||||
|
|
||||||
|
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
|
||||||
|
|
||||||
|
// Start the next frame
|
||||||
|
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||||
|
m_rxBufferBits = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Descramble the header
|
||||||
|
for (i = 0; i < int(DSTAR_FEC_SECTION_LENGTH_BYTES); i++)
|
||||||
|
in[i] ^= SCRAMBLE_TABLE_RX[i];
|
||||||
|
|
||||||
|
unsigned char intermediate[84U];
|
||||||
|
for (i = 0; i < 84; i++)
|
||||||
|
intermediate[i] = 0x00U;
|
||||||
|
|
||||||
|
// Deinterleave the header
|
||||||
|
i = 0;
|
||||||
|
while (i < 660) {
|
||||||
|
unsigned char d = in[i / 8];
|
||||||
|
|
||||||
|
if (d & 0x01U)
|
||||||
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x02U)
|
||||||
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x04U)
|
||||||
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x08U)
|
||||||
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (i < 660) {
|
||||||
|
if (d & 0x10U)
|
||||||
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x20U)
|
||||||
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x40U)
|
||||||
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x80U)
|
||||||
|
intermediate[INTERLEAVE_TABLE_RX[i * 2U]] |= (0x80U >> INTERLEAVE_TABLE_RX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
m_pathMetric[i] = 0;
|
||||||
|
|
||||||
|
int decodeData[2U];
|
||||||
|
|
||||||
|
m_mar = 0U;
|
||||||
|
for (i = 0; i < 660; i += 2) {
|
||||||
|
if (intermediate[i >> 3] & (0x80U >> (i & 7)))
|
||||||
|
decodeData[1U] = 1U;
|
||||||
|
else
|
||||||
|
decodeData[1U] = 0U;
|
||||||
|
|
||||||
|
if (intermediate[i >> 3] & (0x40U >> (i & 7)))
|
||||||
|
decodeData[0U] = 1U;
|
||||||
|
else
|
||||||
|
decodeData[0U] = 0U;
|
||||||
|
|
||||||
|
viterbiDecode(decodeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
traceBack();
|
||||||
|
|
||||||
|
for (i = 0; i < int(DSTAR_HEADER_LENGTH_BYTES); i++)
|
||||||
|
out[i] = 0x00U;
|
||||||
|
|
||||||
|
unsigned int j = 0;
|
||||||
|
for (i = 329; i >= 0; i--) {
|
||||||
|
if (READ_BIT1(m_fecOutput, i))
|
||||||
|
out[j >> 3] |= (0x01U << (j & 7));
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return checksum(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarRX::acs(int* metric)
|
||||||
|
{
|
||||||
|
int tempMetric[4U];
|
||||||
|
|
||||||
|
unsigned int j = m_mar >> 3;
|
||||||
|
unsigned int k = m_mar & 7;
|
||||||
|
|
||||||
|
// Pres. state = S0, Prev. state = S0 & S2
|
||||||
|
int m1 = metric[0U] + m_pathMetric[0U];
|
||||||
|
int m2 = metric[4U] + m_pathMetric[2U];
|
||||||
|
tempMetric[0U] = m1 < m2 ? m1 : m2;
|
||||||
|
if (m1 < m2)
|
||||||
|
m_pathMemory0[j] &= BIT_MASK_TABLE0[k];
|
||||||
|
else
|
||||||
|
m_pathMemory0[j] |= BIT_MASK_TABLE1[k];
|
||||||
|
|
||||||
|
// Pres. state = S1, Prev. state = S0 & S2
|
||||||
|
m1 = metric[1U] + m_pathMetric[0U];
|
||||||
|
m2 = metric[5U] + m_pathMetric[2U];
|
||||||
|
tempMetric[1U] = m1 < m2 ? m1 : m2;
|
||||||
|
if (m1 < m2)
|
||||||
|
m_pathMemory1[j] &= BIT_MASK_TABLE0[k];
|
||||||
|
else
|
||||||
|
m_pathMemory1[j] |= BIT_MASK_TABLE1[k];
|
||||||
|
|
||||||
|
// Pres. state = S2, Prev. state = S2 & S3
|
||||||
|
m1 = metric[2U] + m_pathMetric[1U];
|
||||||
|
m2 = metric[6U] + m_pathMetric[3U];
|
||||||
|
tempMetric[2U] = m1 < m2 ? m1 : m2;
|
||||||
|
if (m1 < m2)
|
||||||
|
m_pathMemory2[j] &= BIT_MASK_TABLE0[k];
|
||||||
|
else
|
||||||
|
m_pathMemory2[j] |= BIT_MASK_TABLE1[k];
|
||||||
|
|
||||||
|
// Pres. state = S3, Prev. state = S1 & S3
|
||||||
|
m1 = metric[3U] + m_pathMetric[1U];
|
||||||
|
m2 = metric[7U] + m_pathMetric[3U];
|
||||||
|
tempMetric[3U] = m1 < m2 ? m1 : m2;
|
||||||
|
if (m1 < m2)
|
||||||
|
m_pathMemory3[j] &= BIT_MASK_TABLE0[k];
|
||||||
|
else
|
||||||
|
m_pathMemory3[j] |= BIT_MASK_TABLE1[k];
|
||||||
|
|
||||||
|
for (unsigned int i = 0U; i < 4U; i++)
|
||||||
|
m_pathMetric[i] = tempMetric[i];
|
||||||
|
|
||||||
|
m_mar++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarRX::viterbiDecode(int* data)
|
||||||
|
{
|
||||||
|
int metric[8U];
|
||||||
|
|
||||||
|
metric[0] = (data[1] ^ 0) + (data[0] ^ 0);
|
||||||
|
metric[1] = (data[1] ^ 1) + (data[0] ^ 1);
|
||||||
|
metric[2] = (data[1] ^ 1) + (data[0] ^ 0);
|
||||||
|
metric[3] = (data[1] ^ 0) + (data[0] ^ 1);
|
||||||
|
metric[4] = (data[1] ^ 1) + (data[0] ^ 1);
|
||||||
|
metric[5] = (data[1] ^ 0) + (data[0] ^ 0);
|
||||||
|
metric[6] = (data[1] ^ 0) + (data[0] ^ 1);
|
||||||
|
metric[7] = (data[1] ^ 1) + (data[0] ^ 0);
|
||||||
|
|
||||||
|
acs(metric);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarRX::traceBack()
|
||||||
|
{
|
||||||
|
// Start from the S0, t=31
|
||||||
|
unsigned int j = 0U;
|
||||||
|
unsigned int k = 0U;
|
||||||
|
for (int i = 329; i >= 0; i--) {
|
||||||
|
switch (j) {
|
||||||
|
case 0U: // if state = S0
|
||||||
|
if (!READ_BIT1(m_pathMemory0, i))
|
||||||
|
j = 0U;
|
||||||
|
else
|
||||||
|
j = 2U;
|
||||||
|
WRITE_BIT1(m_fecOutput, k, false);
|
||||||
|
k++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 1U: // if state = S1
|
||||||
|
if (!READ_BIT1(m_pathMemory1, i))
|
||||||
|
j = 0U;
|
||||||
|
else
|
||||||
|
j = 2U;
|
||||||
|
WRITE_BIT1(m_fecOutput, k, true);
|
||||||
|
k++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2U: // if state = S1
|
||||||
|
if (!READ_BIT1(m_pathMemory2, i))
|
||||||
|
j = 1U;
|
||||||
|
else
|
||||||
|
j = 3U;
|
||||||
|
WRITE_BIT1(m_fecOutput, k, false);
|
||||||
|
k++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3U: // if state = S1
|
||||||
|
if (!READ_BIT1(m_pathMemory3, i))
|
||||||
|
j = 1U;
|
||||||
|
else
|
||||||
|
j = 3U;
|
||||||
|
WRITE_BIT1(m_fecOutput, k, true);
|
||||||
|
k++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CDStarRX::checksum(const uint8_t* header) const
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint16_t crc16;
|
||||||
|
uint8_t crc8[2U];
|
||||||
|
};
|
||||||
|
|
||||||
|
crc16 = 0xFFFFU;
|
||||||
|
for (uint8_t i = 0U; i < (DSTAR_HEADER_LENGTH_BYTES - 2U); i++)
|
||||||
|
crc16 = uint16_t(crc8[1U]) ^ CCITT_TABLE[crc8[0U] ^ header[i]];
|
||||||
|
|
||||||
|
crc16 = ~crc16;
|
||||||
|
|
||||||
|
return crc8[0U] == header[DSTAR_HEADER_LENGTH_BYTES - 2U] && crc8[1U] == header[DSTAR_HEADER_LENGTH_BYTES - 1U];
|
||||||
|
}
|
||||||
|
|
||||||
62
DStarRX.h
Normal file
62
DStarRX.h
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DSTARRX_H)
|
||||||
|
#define DSTARRX_H
|
||||||
|
|
||||||
|
#include "DStarDefines.h"
|
||||||
|
|
||||||
|
enum DSRX_STATE {
|
||||||
|
DSRXS_NONE,
|
||||||
|
DSRXS_HEADER,
|
||||||
|
DSRXS_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
class CDStarRX {
|
||||||
|
public:
|
||||||
|
CDStarRX();
|
||||||
|
|
||||||
|
void databit(bool bit);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
DSRX_STATE m_rxState;
|
||||||
|
uint32_t m_patternBuffer;
|
||||||
|
uint8_t m_rxBuffer[100U];
|
||||||
|
unsigned int m_rxBufferBits;
|
||||||
|
unsigned int m_dataBits;
|
||||||
|
unsigned int m_mar;
|
||||||
|
int m_pathMetric[4U];
|
||||||
|
unsigned int m_pathMemory0[42U];
|
||||||
|
unsigned int m_pathMemory1[42U];
|
||||||
|
unsigned int m_pathMemory2[42U];
|
||||||
|
unsigned int m_pathMemory3[42U];
|
||||||
|
uint8_t m_fecOutput[42U];
|
||||||
|
|
||||||
|
void processNone(bool bit);
|
||||||
|
void processHeader(bool bit);
|
||||||
|
void processData(bool bit);
|
||||||
|
bool rxHeader(uint8_t* in, uint8_t* out);
|
||||||
|
void acs(int* metric);
|
||||||
|
void viterbiDecode(int* data);
|
||||||
|
void traceBack();
|
||||||
|
bool checksum(const uint8_t* header) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
437
DStarTX.cpp
Normal file
437
DStarTX.cpp
Normal file
|
|
@ -0,0 +1,437 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "DStarTX.h"
|
||||||
|
|
||||||
|
#include "DStarDefines.h"
|
||||||
|
|
||||||
|
const uint8_t BIT_SYNC = 0xAAU;
|
||||||
|
|
||||||
|
const uint8_t FRAME_SYNC[] = {0xEAU, 0xA6U, 0x00U};
|
||||||
|
|
||||||
|
const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
||||||
|
|
||||||
|
const uint8_t INTERLEAVE_TABLE_TX[] = {
|
||||||
|
0x00U, 0x04U, 0x04U, 0x00U, 0x07U, 0x04U, 0x0BU, 0x00U, 0x0EU, 0x04U,
|
||||||
|
0x12U, 0x00U, 0x15U, 0x04U, 0x19U, 0x00U, 0x1CU, 0x04U, 0x20U, 0x00U,
|
||||||
|
0x23U, 0x04U, 0x27U, 0x00U, 0x2AU, 0x04U, 0x2DU, 0x07U, 0x31U, 0x02U,
|
||||||
|
0x34U, 0x05U, 0x38U, 0x00U, 0x3BU, 0x03U, 0x3EU, 0x06U, 0x42U, 0x01U,
|
||||||
|
0x45U, 0x04U, 0x48U, 0x07U, 0x4CU, 0x02U, 0x4FU, 0x05U, 0x00U, 0x05U,
|
||||||
|
0x04U, 0x01U, 0x07U, 0x05U, 0x0BU, 0x01U, 0x0EU, 0x05U, 0x12U, 0x01U,
|
||||||
|
0x15U, 0x05U, 0x19U, 0x01U, 0x1CU, 0x05U, 0x20U, 0x01U, 0x23U, 0x05U,
|
||||||
|
0x27U, 0x01U, 0x2AU, 0x05U, 0x2EU, 0x00U, 0x31U, 0x03U, 0x34U, 0x06U,
|
||||||
|
0x38U, 0x01U, 0x3BU, 0x04U, 0x3EU, 0x07U, 0x42U, 0x02U, 0x45U, 0x05U,
|
||||||
|
0x49U, 0x00U, 0x4CU, 0x03U, 0x4FU, 0x06U, 0x00U, 0x06U, 0x04U, 0x02U,
|
||||||
|
0x07U, 0x06U, 0x0BU, 0x02U, 0x0EU, 0x06U, 0x12U, 0x02U, 0x15U, 0x06U,
|
||||||
|
0x19U, 0x02U, 0x1CU, 0x06U, 0x20U, 0x02U, 0x23U, 0x06U, 0x27U, 0x02U,
|
||||||
|
0x2AU, 0x06U, 0x2EU, 0x01U, 0x31U, 0x04U, 0x34U, 0x07U, 0x38U, 0x02U,
|
||||||
|
0x3BU, 0x05U, 0x3FU, 0x00U, 0x42U, 0x03U, 0x45U, 0x06U, 0x49U, 0x01U,
|
||||||
|
0x4CU, 0x04U, 0x4FU, 0x07U, 0x00U, 0x07U, 0x04U, 0x03U, 0x07U, 0x07U,
|
||||||
|
0x0BU, 0x03U, 0x0EU, 0x07U, 0x12U, 0x03U, 0x15U, 0x07U, 0x19U, 0x03U,
|
||||||
|
0x1CU, 0x07U, 0x20U, 0x03U, 0x23U, 0x07U, 0x27U, 0x03U, 0x2AU, 0x07U,
|
||||||
|
0x2EU, 0x02U, 0x31U, 0x05U, 0x35U, 0x00U, 0x38U, 0x03U, 0x3BU, 0x06U,
|
||||||
|
0x3FU, 0x01U, 0x42U, 0x04U, 0x45U, 0x07U, 0x49U, 0x02U, 0x4CU, 0x05U,
|
||||||
|
0x50U, 0x00U, 0x01U, 0x00U, 0x04U, 0x04U, 0x08U, 0x00U, 0x0BU, 0x04U,
|
||||||
|
0x0FU, 0x00U, 0x12U, 0x04U, 0x16U, 0x00U, 0x19U, 0x04U, 0x1DU, 0x00U,
|
||||||
|
0x20U, 0x04U, 0x24U, 0x00U, 0x27U, 0x04U, 0x2BU, 0x00U, 0x2EU, 0x03U,
|
||||||
|
0x31U, 0x06U, 0x35U, 0x01U, 0x38U, 0x04U, 0x3BU, 0x07U, 0x3FU, 0x02U,
|
||||||
|
0x42U, 0x05U, 0x46U, 0x00U, 0x49U, 0x03U, 0x4CU, 0x06U, 0x50U, 0x01U,
|
||||||
|
0x01U, 0x01U, 0x04U, 0x05U, 0x08U, 0x01U, 0x0BU, 0x05U, 0x0FU, 0x01U,
|
||||||
|
0x12U, 0x05U, 0x16U, 0x01U, 0x19U, 0x05U, 0x1DU, 0x01U, 0x20U, 0x05U,
|
||||||
|
0x24U, 0x01U, 0x27U, 0x05U, 0x2BU, 0x01U, 0x2EU, 0x04U, 0x31U, 0x07U,
|
||||||
|
0x35U, 0x02U, 0x38U, 0x05U, 0x3CU, 0x00U, 0x3FU, 0x03U, 0x42U, 0x06U,
|
||||||
|
0x46U, 0x01U, 0x49U, 0x04U, 0x4CU, 0x07U, 0x50U, 0x02U, 0x01U, 0x02U,
|
||||||
|
0x04U, 0x06U, 0x08U, 0x02U, 0x0BU, 0x06U, 0x0FU, 0x02U, 0x12U, 0x06U,
|
||||||
|
0x16U, 0x02U, 0x19U, 0x06U, 0x1DU, 0x02U, 0x20U, 0x06U, 0x24U, 0x02U,
|
||||||
|
0x27U, 0x06U, 0x2BU, 0x02U, 0x2EU, 0x05U, 0x32U, 0x00U, 0x35U, 0x03U,
|
||||||
|
0x38U, 0x06U, 0x3CU, 0x01U, 0x3FU, 0x04U, 0x42U, 0x07U, 0x46U, 0x02U,
|
||||||
|
0x49U, 0x05U, 0x4DU, 0x00U, 0x50U, 0x03U, 0x01U, 0x03U, 0x04U, 0x07U,
|
||||||
|
0x08U, 0x03U, 0x0BU, 0x07U, 0x0FU, 0x03U, 0x12U, 0x07U, 0x16U, 0x03U,
|
||||||
|
0x19U, 0x07U, 0x1DU, 0x03U, 0x20U, 0x07U, 0x24U, 0x03U, 0x27U, 0x07U,
|
||||||
|
0x2BU, 0x03U, 0x2EU, 0x06U, 0x32U, 0x01U, 0x35U, 0x04U, 0x38U, 0x07U,
|
||||||
|
0x3CU, 0x02U, 0x3FU, 0x05U, 0x43U, 0x00U, 0x46U, 0x03U, 0x49U, 0x06U,
|
||||||
|
0x4DU, 0x01U, 0x50U, 0x04U, 0x01U, 0x04U, 0x05U, 0x00U, 0x08U, 0x04U,
|
||||||
|
0x0CU, 0x00U, 0x0FU, 0x04U, 0x13U, 0x00U, 0x16U, 0x04U, 0x1AU, 0x00U,
|
||||||
|
0x1DU, 0x04U, 0x21U, 0x00U, 0x24U, 0x04U, 0x28U, 0x00U, 0x2BU, 0x04U,
|
||||||
|
0x2EU, 0x07U, 0x32U, 0x02U, 0x35U, 0x05U, 0x39U, 0x00U, 0x3CU, 0x03U,
|
||||||
|
0x3FU, 0x06U, 0x43U, 0x01U, 0x46U, 0x04U, 0x49U, 0x07U, 0x4DU, 0x02U,
|
||||||
|
0x50U, 0x05U, 0x01U, 0x05U, 0x05U, 0x01U, 0x08U, 0x05U, 0x0CU, 0x01U,
|
||||||
|
0x0FU, 0x05U, 0x13U, 0x01U, 0x16U, 0x05U, 0x1AU, 0x01U, 0x1DU, 0x05U,
|
||||||
|
0x21U, 0x01U, 0x24U, 0x05U, 0x28U, 0x01U, 0x2BU, 0x05U, 0x2FU, 0x00U,
|
||||||
|
0x32U, 0x03U, 0x35U, 0x06U, 0x39U, 0x01U, 0x3CU, 0x04U, 0x3FU, 0x07U,
|
||||||
|
0x43U, 0x02U, 0x46U, 0x05U, 0x4AU, 0x00U, 0x4DU, 0x03U, 0x50U, 0x06U,
|
||||||
|
0x01U, 0x06U, 0x05U, 0x02U, 0x08U, 0x06U, 0x0CU, 0x02U, 0x0FU, 0x06U,
|
||||||
|
0x13U, 0x02U, 0x16U, 0x06U, 0x1AU, 0x02U, 0x1DU, 0x06U, 0x21U, 0x02U,
|
||||||
|
0x24U, 0x06U, 0x28U, 0x02U, 0x2BU, 0x06U, 0x2FU, 0x01U, 0x32U, 0x04U,
|
||||||
|
0x35U, 0x07U, 0x39U, 0x02U, 0x3CU, 0x05U, 0x40U, 0x00U, 0x43U, 0x03U,
|
||||||
|
0x46U, 0x06U, 0x4AU, 0x01U, 0x4DU, 0x04U, 0x50U, 0x07U, 0x01U, 0x07U,
|
||||||
|
0x05U, 0x03U, 0x08U, 0x07U, 0x0CU, 0x03U, 0x0FU, 0x07U, 0x13U, 0x03U,
|
||||||
|
0x16U, 0x07U, 0x1AU, 0x03U, 0x1DU, 0x07U, 0x21U, 0x03U, 0x24U, 0x07U,
|
||||||
|
0x28U, 0x03U, 0x2BU, 0x07U, 0x2FU, 0x02U, 0x32U, 0x05U, 0x36U, 0x00U,
|
||||||
|
0x39U, 0x03U, 0x3CU, 0x06U, 0x40U, 0x01U, 0x43U, 0x04U, 0x46U, 0x07U,
|
||||||
|
0x4AU, 0x02U, 0x4DU, 0x05U, 0x51U, 0x00U, 0x02U, 0x00U, 0x05U, 0x04U,
|
||||||
|
0x09U, 0x00U, 0x0CU, 0x04U, 0x10U, 0x00U, 0x13U, 0x04U, 0x17U, 0x00U,
|
||||||
|
0x1AU, 0x04U, 0x1EU, 0x00U, 0x21U, 0x04U, 0x25U, 0x00U, 0x28U, 0x04U,
|
||||||
|
0x2CU, 0x00U, 0x2FU, 0x03U, 0x32U, 0x06U, 0x36U, 0x01U, 0x39U, 0x04U,
|
||||||
|
0x3CU, 0x07U, 0x40U, 0x02U, 0x43U, 0x05U, 0x47U, 0x00U, 0x4AU, 0x03U,
|
||||||
|
0x4DU, 0x06U, 0x51U, 0x01U, 0x02U, 0x01U, 0x05U, 0x05U, 0x09U, 0x01U,
|
||||||
|
0x0CU, 0x05U, 0x10U, 0x01U, 0x13U, 0x05U, 0x17U, 0x01U, 0x1AU, 0x05U,
|
||||||
|
0x1EU, 0x01U, 0x21U, 0x05U, 0x25U, 0x01U, 0x28U, 0x05U, 0x2CU, 0x01U,
|
||||||
|
0x2FU, 0x04U, 0x32U, 0x07U, 0x36U, 0x02U, 0x39U, 0x05U, 0x3DU, 0x00U,
|
||||||
|
0x40U, 0x03U, 0x43U, 0x06U, 0x47U, 0x01U, 0x4AU, 0x04U, 0x4DU, 0x07U,
|
||||||
|
0x51U, 0x02U, 0x02U, 0x02U, 0x05U, 0x06U, 0x09U, 0x02U, 0x0CU, 0x06U,
|
||||||
|
0x10U, 0x02U, 0x13U, 0x06U, 0x17U, 0x02U, 0x1AU, 0x06U, 0x1EU, 0x02U,
|
||||||
|
0x21U, 0x06U, 0x25U, 0x02U, 0x28U, 0x06U, 0x2CU, 0x02U, 0x2FU, 0x05U,
|
||||||
|
0x33U, 0x00U, 0x36U, 0x03U, 0x39U, 0x06U, 0x3DU, 0x01U, 0x40U, 0x04U,
|
||||||
|
0x43U, 0x07U, 0x47U, 0x02U, 0x4AU, 0x05U, 0x4EU, 0x00U, 0x51U, 0x03U,
|
||||||
|
0x02U, 0x03U, 0x05U, 0x07U, 0x09U, 0x03U, 0x0CU, 0x07U, 0x10U, 0x03U,
|
||||||
|
0x13U, 0x07U, 0x17U, 0x03U, 0x1AU, 0x07U, 0x1EU, 0x03U, 0x21U, 0x07U,
|
||||||
|
0x25U, 0x03U, 0x28U, 0x07U, 0x2CU, 0x03U, 0x2FU, 0x06U, 0x33U, 0x01U,
|
||||||
|
0x36U, 0x04U, 0x39U, 0x07U, 0x3DU, 0x02U, 0x40U, 0x05U, 0x44U, 0x00U,
|
||||||
|
0x47U, 0x03U, 0x4AU, 0x06U, 0x4EU, 0x01U, 0x51U, 0x04U, 0x02U, 0x04U,
|
||||||
|
0x06U, 0x00U, 0x09U, 0x04U, 0x0DU, 0x00U, 0x10U, 0x04U, 0x14U, 0x00U,
|
||||||
|
0x17U, 0x04U, 0x1BU, 0x00U, 0x1EU, 0x04U, 0x22U, 0x00U, 0x25U, 0x04U,
|
||||||
|
0x29U, 0x00U, 0x2CU, 0x04U, 0x2FU, 0x07U, 0x33U, 0x02U, 0x36U, 0x05U,
|
||||||
|
0x3AU, 0x00U, 0x3DU, 0x03U, 0x40U, 0x06U, 0x44U, 0x01U, 0x47U, 0x04U,
|
||||||
|
0x4AU, 0x07U, 0x4EU, 0x02U, 0x51U, 0x05U, 0x02U, 0x05U, 0x06U, 0x01U,
|
||||||
|
0x09U, 0x05U, 0x0DU, 0x01U, 0x10U, 0x05U, 0x14U, 0x01U, 0x17U, 0x05U,
|
||||||
|
0x1BU, 0x01U, 0x1EU, 0x05U, 0x22U, 0x01U, 0x25U, 0x05U, 0x29U, 0x01U,
|
||||||
|
0x2CU, 0x05U, 0x30U, 0x00U, 0x33U, 0x03U, 0x36U, 0x06U, 0x3AU, 0x01U,
|
||||||
|
0x3DU, 0x04U, 0x40U, 0x07U, 0x44U, 0x02U, 0x47U, 0x05U, 0x4BU, 0x00U,
|
||||||
|
0x4EU, 0x03U, 0x51U, 0x06U, 0x02U, 0x06U, 0x06U, 0x02U, 0x09U, 0x06U,
|
||||||
|
0x0DU, 0x02U, 0x10U, 0x06U, 0x14U, 0x02U, 0x17U, 0x06U, 0x1BU, 0x02U,
|
||||||
|
0x1EU, 0x06U, 0x22U, 0x02U, 0x25U, 0x06U, 0x29U, 0x02U, 0x2CU, 0x06U,
|
||||||
|
0x30U, 0x01U, 0x33U, 0x04U, 0x36U, 0x07U, 0x3AU, 0x02U, 0x3DU, 0x05U,
|
||||||
|
0x41U, 0x00U, 0x44U, 0x03U, 0x47U, 0x06U, 0x4BU, 0x01U, 0x4EU, 0x04U,
|
||||||
|
0x51U, 0x07U, 0x02U, 0x07U, 0x06U, 0x03U, 0x09U, 0x07U, 0x0DU, 0x03U,
|
||||||
|
0x10U, 0x07U, 0x14U, 0x03U, 0x17U, 0x07U, 0x1BU, 0x03U, 0x1EU, 0x07U,
|
||||||
|
0x22U, 0x03U, 0x25U, 0x07U, 0x29U, 0x03U, 0x2CU, 0x07U, 0x30U, 0x02U,
|
||||||
|
0x33U, 0x05U, 0x37U, 0x00U, 0x3AU, 0x03U, 0x3DU, 0x06U, 0x41U, 0x01U,
|
||||||
|
0x44U, 0x04U, 0x47U, 0x07U, 0x4BU, 0x02U, 0x4EU, 0x05U, 0x52U, 0x00U,
|
||||||
|
0x03U, 0x00U, 0x06U, 0x04U, 0x0AU, 0x00U, 0x0DU, 0x04U, 0x11U, 0x00U,
|
||||||
|
0x14U, 0x04U, 0x18U, 0x00U, 0x1BU, 0x04U, 0x1FU, 0x00U, 0x22U, 0x04U,
|
||||||
|
0x26U, 0x00U, 0x29U, 0x04U, 0x2DU, 0x00U, 0x30U, 0x03U, 0x33U, 0x06U,
|
||||||
|
0x37U, 0x01U, 0x3AU, 0x04U, 0x3DU, 0x07U, 0x41U, 0x02U, 0x44U, 0x05U,
|
||||||
|
0x48U, 0x00U, 0x4BU, 0x03U, 0x4EU, 0x06U, 0x52U, 0x01U, 0x03U, 0x01U,
|
||||||
|
0x06U, 0x05U, 0x0AU, 0x01U, 0x0DU, 0x05U, 0x11U, 0x01U, 0x14U, 0x05U,
|
||||||
|
0x18U, 0x01U, 0x1BU, 0x05U, 0x1FU, 0x01U, 0x22U, 0x05U, 0x26U, 0x01U,
|
||||||
|
0x29U, 0x05U, 0x2DU, 0x01U, 0x30U, 0x04U, 0x33U, 0x07U, 0x37U, 0x02U,
|
||||||
|
0x3AU, 0x05U, 0x3EU, 0x00U, 0x41U, 0x03U, 0x44U, 0x06U, 0x48U, 0x01U,
|
||||||
|
0x4BU, 0x04U, 0x4EU, 0x07U, 0x52U, 0x02U, 0x03U, 0x02U, 0x06U, 0x06U,
|
||||||
|
0x0AU, 0x02U, 0x0DU, 0x06U, 0x11U, 0x02U, 0x14U, 0x06U, 0x18U, 0x02U,
|
||||||
|
0x1BU, 0x06U, 0x1FU, 0x02U, 0x22U, 0x06U, 0x26U, 0x02U, 0x29U, 0x06U,
|
||||||
|
0x2DU, 0x02U, 0x30U, 0x05U, 0x34U, 0x00U, 0x37U, 0x03U, 0x3AU, 0x06U,
|
||||||
|
0x3EU, 0x01U, 0x41U, 0x04U, 0x44U, 0x07U, 0x48U, 0x02U, 0x4BU, 0x05U,
|
||||||
|
0x4FU, 0x00U, 0x52U, 0x03U, 0x03U, 0x03U, 0x06U, 0x07U, 0x0AU, 0x03U,
|
||||||
|
0x0DU, 0x07U, 0x11U, 0x03U, 0x14U, 0x07U, 0x18U, 0x03U, 0x1BU, 0x07U,
|
||||||
|
0x1FU, 0x03U, 0x22U, 0x07U, 0x26U, 0x03U, 0x29U, 0x07U, 0x2DU, 0x03U,
|
||||||
|
0x30U, 0x06U, 0x34U, 0x01U, 0x37U, 0x04U, 0x3AU, 0x07U, 0x3EU, 0x02U,
|
||||||
|
0x41U, 0x05U, 0x45U, 0x00U, 0x48U, 0x03U, 0x4BU, 0x06U, 0x4FU, 0x01U,
|
||||||
|
0x52U, 0x04U, 0x03U, 0x04U, 0x07U, 0x00U, 0x0AU, 0x04U, 0x0EU, 0x00U,
|
||||||
|
0x11U, 0x04U, 0x15U, 0x00U, 0x18U, 0x04U, 0x1CU, 0x00U, 0x1FU, 0x04U,
|
||||||
|
0x23U, 0x00U, 0x26U, 0x04U, 0x2AU, 0x00U, 0x2DU, 0x04U, 0x30U, 0x07U,
|
||||||
|
0x34U, 0x02U, 0x37U, 0x05U, 0x3BU, 0x00U, 0x3EU, 0x03U, 0x41U, 0x06U,
|
||||||
|
0x45U, 0x01U, 0x48U, 0x04U, 0x4BU, 0x07U, 0x4FU, 0x02U, 0x52U, 0x05U,
|
||||||
|
0x03U, 0x05U, 0x07U, 0x01U, 0x0AU, 0x05U, 0x0EU, 0x01U, 0x11U, 0x05U,
|
||||||
|
0x15U, 0x01U, 0x18U, 0x05U, 0x1CU, 0x01U, 0x1FU, 0x05U, 0x23U, 0x01U,
|
||||||
|
0x26U, 0x05U, 0x2AU, 0x01U, 0x2DU, 0x05U, 0x31U, 0x00U, 0x34U, 0x03U,
|
||||||
|
0x37U, 0x06U, 0x3BU, 0x01U, 0x3EU, 0x04U, 0x41U, 0x07U, 0x45U, 0x02U,
|
||||||
|
0x48U, 0x05U, 0x4CU, 0x00U, 0x4FU, 0x03U, 0x52U, 0x06U, 0x03U, 0x06U,
|
||||||
|
0x07U, 0x02U, 0x0AU, 0x06U, 0x0EU, 0x02U, 0x11U, 0x06U, 0x15U, 0x02U,
|
||||||
|
0x18U, 0x06U, 0x1CU, 0x02U, 0x1FU, 0x06U, 0x23U, 0x02U, 0x26U, 0x06U,
|
||||||
|
0x2AU, 0x02U, 0x2DU, 0x06U, 0x31U, 0x01U, 0x34U, 0x04U, 0x37U, 0x07U,
|
||||||
|
0x3BU, 0x02U, 0x3EU, 0x05U, 0x42U, 0x00U, 0x45U, 0x03U, 0x48U, 0x06U,
|
||||||
|
0x4CU, 0x01U, 0x4FU, 0x04U, 0x52U, 0x07U, 0x03U, 0x07U, 0x07U, 0x03U,
|
||||||
|
0x0AU, 0x07U, 0x0EU, 0x03U, 0x11U, 0x07U, 0x15U, 0x03U, 0x18U, 0x07U,
|
||||||
|
0x1CU, 0x03U, 0x1FU, 0x07U, 0x23U, 0x03U, 0x26U, 0x07U, 0x2AU, 0x03U
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t SCRAMBLE_TABLE_TX[] = {
|
||||||
|
0x00U, 0xF7U, 0x34U, 0x09U, 0x44U, 0x46U, 0xD7U, 0x06U, 0xB3U, 0x72U,
|
||||||
|
0xDEU, 0x42U, 0xF5U, 0xA5U, 0xD8U, 0xF1U, 0x87U, 0x7BU, 0x9AU, 0x04U,
|
||||||
|
0x22U, 0xA3U, 0x6BU, 0x83U, 0x59U, 0x39U, 0x6FU, 0xA1U, 0xFAU, 0x52U,
|
||||||
|
0xECU, 0xF8U, 0xC3U, 0x3DU, 0x4DU, 0x02U, 0x91U, 0xD1U, 0xB5U, 0xC1U,
|
||||||
|
0xACU, 0x9CU, 0xB7U, 0x50U, 0x7DU, 0x29U, 0x76U, 0xFCU, 0xE1U, 0x9EU,
|
||||||
|
0x26U, 0x81U, 0xC8U, 0xE8U, 0xDAU, 0x60U, 0x56U, 0xCEU, 0x5BU, 0xA8U,
|
||||||
|
0xBEU, 0x14U, 0x3BU, 0xFEU, 0x70U, 0x4FU, 0x93U, 0x40U, 0x64U, 0x74U,
|
||||||
|
0x6DU, 0x30U, 0x2BU, 0xE7U, 0x2DU, 0x54U, 0x5FU, 0x8AU, 0x1DU, 0x7FU,
|
||||||
|
0xB8U, 0xA7U, 0x49U, 0x20U, 0x32U, 0xBAU, 0x36U, 0x98U, 0x95U, 0xF3U,
|
||||||
|
0x06U};
|
||||||
|
|
||||||
|
const uint8_t DSTAR_HEADER = 0x00U;
|
||||||
|
const uint8_t DSTAR_DATA = 0x01U;
|
||||||
|
const uint8_t DSTAR_EOT = 0x02U;
|
||||||
|
|
||||||
|
CDStarTX::CDStarTX() :
|
||||||
|
m_buffer(),
|
||||||
|
m_poBuffer(),
|
||||||
|
m_poLen(0U),
|
||||||
|
m_poPtr(0U),
|
||||||
|
m_txDelay(60U), // 100ms
|
||||||
|
m_count(0U)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarTX::process()
|
||||||
|
{
|
||||||
|
if (m_buffer.getData() == 0U && m_poLen == 0U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t type = m_buffer.peek();
|
||||||
|
|
||||||
|
if (type == DSTAR_HEADER && m_poLen == 0U) {
|
||||||
|
if (!m_tx) {
|
||||||
|
m_delay = true;
|
||||||
|
m_count = 0U;
|
||||||
|
m_poLen = m_txDelay;
|
||||||
|
} else {
|
||||||
|
m_delay = false;
|
||||||
|
// Pop the type byte off
|
||||||
|
m_buffer.get();
|
||||||
|
|
||||||
|
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
|
||||||
|
for (uint8_t i = 0U; i < DSTAR_HEADER_LENGTH_BYTES; i++)
|
||||||
|
header[i] = m_buffer.get();
|
||||||
|
|
||||||
|
uint8_t buffer[86U];
|
||||||
|
txHeader(header, buffer + 2U);
|
||||||
|
|
||||||
|
buffer[0U] = FRAME_SYNC[0U];
|
||||||
|
buffer[1U] = FRAME_SYNC[1U];
|
||||||
|
buffer[2U] |= FRAME_SYNC[2U];
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < 85U; i++)
|
||||||
|
m_poBuffer[m_poLen++] = buffer[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_poPtr = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == DSTAR_DATA && m_poLen == 0U) {
|
||||||
|
m_delay = false;
|
||||||
|
if (!m_tx)
|
||||||
|
m_count = 0U;
|
||||||
|
|
||||||
|
// Pop the type byte off
|
||||||
|
m_buffer.get();
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < DSTAR_DATA_LENGTH_BYTES; i++)
|
||||||
|
m_poBuffer[m_poLen++] = m_buffer.get();
|
||||||
|
|
||||||
|
m_poPtr = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == DSTAR_EOT && m_poLen == 0U) {
|
||||||
|
m_delay = false;
|
||||||
|
// Pop the type byte off
|
||||||
|
m_buffer.get();
|
||||||
|
|
||||||
|
for (uint8_t j = 0U; j < 3U; j++) {
|
||||||
|
for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++)
|
||||||
|
m_poBuffer[m_poLen++] = DSTAR_EOT_BYTES[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
m_poPtr = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_poLen > 0U) {
|
||||||
|
uint16_t space = io.getSpace();
|
||||||
|
|
||||||
|
while (space > 8U) {
|
||||||
|
if (m_delay) {
|
||||||
|
m_poPtr++;
|
||||||
|
writeByte(BIT_SYNC);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
writeByte(m_poBuffer[m_poPtr++]);
|
||||||
|
|
||||||
|
space -= 8U;
|
||||||
|
|
||||||
|
if (m_poPtr >= m_poLen) {
|
||||||
|
m_poPtr = 0U;
|
||||||
|
m_poLen = 0U;
|
||||||
|
m_delay = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CDStarTX::writeHeader(const uint8_t* header, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length != DSTAR_HEADER_LENGTH_BYTES)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
uint16_t space = m_buffer.getSpace();
|
||||||
|
if (space < (DSTAR_HEADER_LENGTH_BYTES + 1U)) {
|
||||||
|
DEBUG2("DStarTX: header space available", space);
|
||||||
|
return 5U;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffer.put(DSTAR_HEADER);
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < DSTAR_HEADER_LENGTH_BYTES; i++)
|
||||||
|
m_buffer.put(header[i]);
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CDStarTX::writeData(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length != DSTAR_DATA_LENGTH_BYTES)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
uint16_t space = m_buffer.getSpace();
|
||||||
|
if (space < (DSTAR_DATA_LENGTH_BYTES + 1U)) {
|
||||||
|
DEBUG2("DStarTX: data space available", space);
|
||||||
|
return 5U;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffer.put(DSTAR_DATA);
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < DSTAR_DATA_LENGTH_BYTES; i++)
|
||||||
|
m_buffer.put(data[i]);
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CDStarTX::writeEOT()
|
||||||
|
{
|
||||||
|
uint16_t space = m_buffer.getSpace();
|
||||||
|
if (space < 1U) {
|
||||||
|
DEBUG2("DStarTX: EOT space available", space);
|
||||||
|
return 5U;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_buffer.put(DSTAR_EOT);
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const
|
||||||
|
{
|
||||||
|
uint8_t intermediate[84U];
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for (i = 0U; i < 83U; i++) {
|
||||||
|
intermediate[i] = 0x00U;
|
||||||
|
out[i] = 0x00U;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convolve the header
|
||||||
|
uint8_t d, d1 = 0U, d2 = 0U, g0, g1;
|
||||||
|
uint32_t k = 0U;
|
||||||
|
for (i = 0U; i < 42U; i++) {
|
||||||
|
for (uint8_t j = 0U; j < 8U; j++) {
|
||||||
|
uint8_t mask = (0x01U << j);
|
||||||
|
d = 0U;
|
||||||
|
|
||||||
|
if (in[i] & mask)
|
||||||
|
d = 1U;
|
||||||
|
|
||||||
|
g0 = (d + d2) & 1;
|
||||||
|
g1 = (d + d1 + d2) & 1;
|
||||||
|
d2 = d1;
|
||||||
|
d1 = d;
|
||||||
|
|
||||||
|
if (g1)
|
||||||
|
intermediate[k >> 3] |= BIT_MASK_TABLE[k & 7];
|
||||||
|
k++;
|
||||||
|
|
||||||
|
if (g0)
|
||||||
|
intermediate[k >> 3] |= BIT_MASK_TABLE[k & 7];
|
||||||
|
k++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interleave the header
|
||||||
|
i = 0U;
|
||||||
|
while (i < 660U) {
|
||||||
|
unsigned char d = intermediate[i >> 3];
|
||||||
|
|
||||||
|
if (d & 0x80U)
|
||||||
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x40U)
|
||||||
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x20U)
|
||||||
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x10U)
|
||||||
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (i < 660U) {
|
||||||
|
if (d & 0x08U)
|
||||||
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x04U)
|
||||||
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x02U)
|
||||||
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (d & 0x01U)
|
||||||
|
out[INTERLEAVE_TABLE_TX[i * 2U]] |= (0x01U << INTERLEAVE_TABLE_TX[i * 2U + 1U]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scramble the header
|
||||||
|
for (i = 0U; i < 83U; i++)
|
||||||
|
out[i] ^= SCRAMBLE_TABLE_TX[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarTX::writeByte(uint8_t c)
|
||||||
|
{
|
||||||
|
uint8_t bit;
|
||||||
|
uint8_t mask = 0x01U;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < 8U; i++) {
|
||||||
|
if ((c & mask) == mask)
|
||||||
|
bit = 1U;
|
||||||
|
else
|
||||||
|
bit = 0U;
|
||||||
|
|
||||||
|
io.write(&bit, 1);
|
||||||
|
mask <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDStarTX::setTXDelay(uint8_t delay)
|
||||||
|
{
|
||||||
|
m_txDelay = 150U + uint16_t(delay) * 6U; // 250ms + tx delay
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CDStarTX::getSpace() const
|
||||||
|
{
|
||||||
|
return m_buffer.getSpace() / (DSTAR_DATA_LENGTH_BYTES + 1U);
|
||||||
|
}
|
||||||
51
DStarTX.h
Normal file
51
DStarTX.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DSTARTX_H)
|
||||||
|
#define DSTARTX_H
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
|
class CDStarTX {
|
||||||
|
public:
|
||||||
|
CDStarTX();
|
||||||
|
|
||||||
|
uint8_t writeHeader(const uint8_t* header, uint8_t length);
|
||||||
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
uint8_t writeEOT();
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setTXDelay(uint8_t delay);
|
||||||
|
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSerialRB m_buffer;
|
||||||
|
uint8_t m_poBuffer[90U];
|
||||||
|
uint16_t m_poLen;
|
||||||
|
uint16_t m_poPtr;
|
||||||
|
uint16_t m_txDelay; // In bytes
|
||||||
|
uint32_t m_count;
|
||||||
|
bool m_delay;
|
||||||
|
|
||||||
|
void txHeader(const uint8_t* in, uint8_t* out) const;
|
||||||
|
void writeByte(uint8_t c);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
45
Debug.h
Normal file
45
Debug.h
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(DEBUG_H)
|
||||||
|
#define DEBUG_H
|
||||||
|
|
||||||
|
#if defined(WANT_DEBUG)
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#define DEBUG1(a) serial.writeDebug((a))
|
||||||
|
#define DEBUG2(a,b) serial.writeDebug((a),(b))
|
||||||
|
#define DEBUG3(a,b,c) serial.writeDebug((a),(b),(c))
|
||||||
|
#define DEBUG4(a,b,c,d) serial.writeDebug((a),(b),(c),(d))
|
||||||
|
#define DEBUG5(a,b,c,d,e) serial.writeDebug((a),(b),(c),(d),(e))
|
||||||
|
#define ASSERT(a) serial.writeAssert((a),#a,__FILE__,__LINE__)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define DEBUG1(a)
|
||||||
|
#define DEBUG2(a,b)
|
||||||
|
#define DEBUG3(a,b,c)
|
||||||
|
#define DEBUG4(a,b,c,d)
|
||||||
|
#define DEBUG5(a,b,c,d,e)
|
||||||
|
#define ASSERT(a)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
78
Globals.h
Normal file
78
Globals.h
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(GLOBALS_H)
|
||||||
|
#define GLOBALS_H
|
||||||
|
|
||||||
|
#if defined(STM32F10X_MD)
|
||||||
|
#include <stm32f10x.h>
|
||||||
|
#include "string.h"
|
||||||
|
#else
|
||||||
|
#include <Arduino.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum MMDVM_STATE {
|
||||||
|
STATE_IDLE = 0,
|
||||||
|
STATE_DSTAR = 1,
|
||||||
|
STATE_DMR = 2,
|
||||||
|
STATE_YSF = 3,
|
||||||
|
STATE_P25 = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "IO.h"
|
||||||
|
#include "SerialPort.h"
|
||||||
|
#include "DMRDMORX.h"
|
||||||
|
#include "DMRDMOTX.h"
|
||||||
|
#include "DStarRX.h"
|
||||||
|
#include "DStarTX.h"
|
||||||
|
#include "YSFRX.h"
|
||||||
|
#include "YSFTX.h"
|
||||||
|
#include "P25RX.h"
|
||||||
|
#include "P25TX.h"
|
||||||
|
#include "Debug.h"
|
||||||
|
|
||||||
|
const uint16_t TX_RINGBUFFER_SIZE = 100U;
|
||||||
|
const uint16_t RX_RINGBUFFER_SIZE = 120U;
|
||||||
|
|
||||||
|
extern MMDVM_STATE m_modemState;
|
||||||
|
|
||||||
|
extern bool m_dstarEnable;
|
||||||
|
extern bool m_dmrEnable;
|
||||||
|
extern bool m_ysfEnable;
|
||||||
|
extern bool m_p25Enable;
|
||||||
|
|
||||||
|
extern bool m_tx;
|
||||||
|
extern bool m_dcd;
|
||||||
|
|
||||||
|
extern CIO io;
|
||||||
|
extern CSerialPort serial;
|
||||||
|
|
||||||
|
extern CDStarRX dstarRX;
|
||||||
|
extern CDStarTX dstarTX;
|
||||||
|
|
||||||
|
extern CDMRDMORX dmrDMORX;
|
||||||
|
extern CDMRDMOTX dmrDMOTX;
|
||||||
|
|
||||||
|
extern CYSFRX ysfRX;
|
||||||
|
extern CYSFTX ysfTX;
|
||||||
|
|
||||||
|
extern CP25RX p25RX;
|
||||||
|
extern CP25TX p25TX;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
161
IO.cpp
Normal file
161
IO.cpp
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015, 2016 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016, 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 "IO.h"
|
||||||
|
|
||||||
|
#if defined(ADF7021)
|
||||||
|
#include "ADF7021.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t m_frequency_rx;
|
||||||
|
uint32_t m_frequency_tx;
|
||||||
|
uint8_t m_power;
|
||||||
|
|
||||||
|
CIO::CIO():
|
||||||
|
m_started(false),
|
||||||
|
m_rxBuffer(RX_RINGBUFFER_SIZE),
|
||||||
|
m_txBuffer(TX_RINGBUFFER_SIZE)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
|
||||||
|
LED_pin(HIGH);
|
||||||
|
PTT_pin(LOW);
|
||||||
|
DSTAR_pin(LOW);
|
||||||
|
DMR_pin(LOW);
|
||||||
|
YSF_pin(LOW);
|
||||||
|
P25_pin(LOW);
|
||||||
|
COS_pin(LOW);
|
||||||
|
DEB_pin(LOW);
|
||||||
|
|
||||||
|
TXD_pin(LOW);
|
||||||
|
SCLK_pin(LOW);
|
||||||
|
SDATA_pin(LOW);
|
||||||
|
SLE_pin(LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::process()
|
||||||
|
{
|
||||||
|
uint8_t bit;
|
||||||
|
|
||||||
|
// Switch off the transmitter if needed
|
||||||
|
if (m_txBuffer.getData() == 0U && m_tx) {
|
||||||
|
m_tx = false;
|
||||||
|
setRX();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_rxBuffer.getData() >= 1U) {
|
||||||
|
m_rxBuffer.get(bit);
|
||||||
|
|
||||||
|
if(m_dstarEnable)
|
||||||
|
dstarRX.databit(bit);
|
||||||
|
else if(m_dmrEnable)
|
||||||
|
dmrDMORX.databit(bit);
|
||||||
|
else if(m_ysfEnable)
|
||||||
|
ysfRX.databit(bit);
|
||||||
|
else if(m_p25Enable)
|
||||||
|
p25RX.databit(bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::interrupt()
|
||||||
|
{
|
||||||
|
uint8_t bit = 0;
|
||||||
|
|
||||||
|
if(m_tx) {
|
||||||
|
m_txBuffer.get(bit);
|
||||||
|
|
||||||
|
if(bit)
|
||||||
|
TXD_pin(HIGH);
|
||||||
|
else
|
||||||
|
TXD_pin(LOW);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(RXD_pin())
|
||||||
|
bit = 1;
|
||||||
|
else
|
||||||
|
bit = 0;
|
||||||
|
|
||||||
|
m_rxBuffer.put(bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::write(uint8_t* data, uint16_t length)
|
||||||
|
{
|
||||||
|
if (!m_started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (uint16_t i = 0U; i < length; i++)
|
||||||
|
m_txBuffer.put(data[i]);
|
||||||
|
|
||||||
|
// Switch the transmitter on if needed
|
||||||
|
if (!m_tx) {
|
||||||
|
setTX();
|
||||||
|
m_tx = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CIO::getSpace() const
|
||||||
|
{
|
||||||
|
return m_txBuffer.getSpace();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::hasTXOverflow()
|
||||||
|
{
|
||||||
|
return m_txBuffer.hasOverflowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::hasRXOverflow()
|
||||||
|
{
|
||||||
|
return m_rxBuffer.hasOverflowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CIO::setFreq(uint32_t frequency_rx, uint32_t frequency_tx)
|
||||||
|
{
|
||||||
|
// power level
|
||||||
|
m_power = 0x20;
|
||||||
|
|
||||||
|
if( !( ((frequency_rx >= VHF_MIN)&&(frequency_rx < VHF_MAX)) || ((frequency_tx >= VHF_MIN)&&(frequency_tx < VHF_MAX)) || \
|
||||||
|
((frequency_rx >= UHF_MIN)&&(frequency_rx < UHF_MAX)) || ((frequency_tx >= UHF_MIN)&&(frequency_tx < UHF_MAX)) ) )
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
m_frequency_rx = frequency_rx;
|
||||||
|
m_frequency_tx = frequency_tx;
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setMode()
|
||||||
|
{
|
||||||
|
DSTAR_pin(m_modemState == STATE_DSTAR);
|
||||||
|
DMR_pin(m_modemState == STATE_DMR);
|
||||||
|
YSF_pin(m_modemState == STATE_YSF);
|
||||||
|
P25_pin(m_modemState == STATE_P25);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::setDecode(bool dcd)
|
||||||
|
{
|
||||||
|
if (dcd != m_dcd)
|
||||||
|
COS_pin(dcd ? true : false);
|
||||||
|
|
||||||
|
m_dcd = dcd;
|
||||||
|
}
|
||||||
85
IO.h
Normal file
85
IO.h
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015, 2016 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(CIO_H)
|
||||||
|
#define CIO_H
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "BitRB.h"
|
||||||
|
|
||||||
|
#define LOW 0
|
||||||
|
#define HIGH 1
|
||||||
|
|
||||||
|
#define VHF_MIN 144000000
|
||||||
|
#define VHF_MAX 148000000
|
||||||
|
#define UHF_MIN 430000000
|
||||||
|
#define UHF_MAX 450000000
|
||||||
|
|
||||||
|
extern uint32_t m_frequency_rx;
|
||||||
|
extern uint32_t m_frequency_tx;
|
||||||
|
extern uint8_t m_power;
|
||||||
|
|
||||||
|
class CIO {
|
||||||
|
|
||||||
|
public:
|
||||||
|
CIO();
|
||||||
|
|
||||||
|
// Platform API
|
||||||
|
void Init(void);
|
||||||
|
void SCLK_pin(bool on);
|
||||||
|
void SDATA_pin(bool on);
|
||||||
|
void SLE_pin(bool on);
|
||||||
|
bool RXD_pin();
|
||||||
|
void TXD_pin(bool on);
|
||||||
|
void PTT_pin(bool on);
|
||||||
|
void LED_pin(bool on);
|
||||||
|
void DEB_pin(bool on);
|
||||||
|
void DSTAR_pin(bool on);
|
||||||
|
void DMR_pin(bool on);
|
||||||
|
void YSF_pin(bool on);
|
||||||
|
void P25_pin(bool on);
|
||||||
|
void COS_pin(bool on);
|
||||||
|
void interrupt(void);
|
||||||
|
|
||||||
|
// IO API
|
||||||
|
void write(uint8_t* data, uint16_t length);
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
void process();
|
||||||
|
bool hasTXOverflow();
|
||||||
|
bool hasRXOverflow();
|
||||||
|
uint8_t setFreq(uint32_t frequency_rx, uint32_t frequency_tx);
|
||||||
|
void setMode();
|
||||||
|
void setDecode(bool dcd);
|
||||||
|
|
||||||
|
// RF interface API
|
||||||
|
void setTX();
|
||||||
|
void setRX();
|
||||||
|
void ifConf();
|
||||||
|
void ifInit();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_started;
|
||||||
|
CBitRB m_rxBuffer;
|
||||||
|
CBitRB m_txBuffer;
|
||||||
|
|
||||||
|
void delay_rx(void);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
178
IOArduino.cpp
Normal file
178
IOArduino.cpp
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015, 2016 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016, 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 "IO.h"
|
||||||
|
|
||||||
|
#if defined(ARDUINO)
|
||||||
|
|
||||||
|
#if defined (__STM32F1__)
|
||||||
|
|
||||||
|
// STM32F1 pin definitions, using STM32duino
|
||||||
|
#define PIN_SCLK PB5
|
||||||
|
#define PIN_SREAD PB7
|
||||||
|
#define PIN_SDATA PB6
|
||||||
|
#define PIN_SLE PB8
|
||||||
|
#define PIN_RXD PB4
|
||||||
|
#define PIN_TXD PB3
|
||||||
|
#define PIN_TXRX_CLK PA15
|
||||||
|
#define PIN_LED PC13
|
||||||
|
#define PIN_DEB PB9
|
||||||
|
#define PIN_DSTAR_LED PB12
|
||||||
|
#define PIN_DMR_LED PB13
|
||||||
|
#define PIN_YSF_LED PB1
|
||||||
|
#define PIN_P25_LED PB0
|
||||||
|
#define PIN_PTT_LED PB14
|
||||||
|
#define PIN_COS_LED PB15
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Arduino pin definitions (Due and Zero)
|
||||||
|
#define PIN_SCLK 3
|
||||||
|
#define PIN_SDATA 4 // 2 in Arduino Zero Pro
|
||||||
|
#define PIN_SREAD 5
|
||||||
|
#define PIN_SLE 6
|
||||||
|
#define PIN_RXD 7
|
||||||
|
#define PIN_TXD 8
|
||||||
|
#define PIN_TXRX_CLK 2 // 4 in Arduino Zero Pro
|
||||||
|
#define PIN_LED 13
|
||||||
|
#define PIN_DEB 11
|
||||||
|
#define PIN_DSTAR_LED 14
|
||||||
|
#define PIN_DMR_LED 15
|
||||||
|
#define PIN_YSF_LED 16
|
||||||
|
#define PIN_P25_LED 17
|
||||||
|
#define PIN_PTT_LED 9
|
||||||
|
#define PIN_COS_LED 10
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void EXT_IRQHandler(void) {
|
||||||
|
io.interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::delay_rx() {
|
||||||
|
delayMicroseconds(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::Init()
|
||||||
|
{
|
||||||
|
#if defined (__STM32F1__)
|
||||||
|
afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pinMode(PIN_SCLK, OUTPUT);
|
||||||
|
pinMode(PIN_SDATA, OUTPUT);
|
||||||
|
pinMode(PIN_SLE, OUTPUT);
|
||||||
|
pinMode(PIN_RXD, INPUT);
|
||||||
|
pinMode(PIN_TXD, OUTPUT);
|
||||||
|
pinMode(PIN_TXRX_CLK, INPUT);
|
||||||
|
pinMode(PIN_LED, OUTPUT);
|
||||||
|
pinMode(PIN_DEB, OUTPUT);
|
||||||
|
pinMode(PIN_DSTAR_LED, OUTPUT);
|
||||||
|
pinMode(PIN_DMR_LED, OUTPUT);
|
||||||
|
pinMode(PIN_YSF_LED, OUTPUT);
|
||||||
|
pinMode(PIN_P25_LED, OUTPUT);
|
||||||
|
pinMode(PIN_PTT_LED, OUTPUT);
|
||||||
|
pinMode(PIN_COS_LED, OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::ifInit()
|
||||||
|
{
|
||||||
|
m_started = true;
|
||||||
|
|
||||||
|
#if defined (__STM32F1__)
|
||||||
|
attachInterrupt(PIN_TXRX_CLK, EXT_IRQHandler, RISING);
|
||||||
|
#else
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIN_TXRX_CLK), EXT_IRQHandler, RISING);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ifConf();
|
||||||
|
delay_rx();;
|
||||||
|
setRX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::SCLK_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_SCLK, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::SDATA_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_SDATA, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::SLE_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_SLE, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::RXD_pin()
|
||||||
|
{
|
||||||
|
return digitalRead(PIN_RXD) == HIGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::TXD_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_TXD, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::LED_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::DEB_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_DEB, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::DSTAR_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_DSTAR_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::DMR_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_DMR_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::YSF_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_YSF_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::P25_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_P25_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::PTT_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_PTT_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::COS_pin(bool on)
|
||||||
|
{
|
||||||
|
digitalWrite(PIN_COS_LED, on ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
294
IOSTM.cpp
Normal file
294
IOSTM.cpp
Normal file
|
|
@ -0,0 +1,294 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
* Copyright (C) 2016, 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"
|
||||||
|
|
||||||
|
#if defined(STM32F10X_MD)
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "IO.h"
|
||||||
|
|
||||||
|
#define PIN_SCLK GPIO_Pin_5
|
||||||
|
#define PORT_SCLK GPIOB
|
||||||
|
|
||||||
|
#define PIN_SREAD GPIO_Pin_7
|
||||||
|
#define PORT_SREAD GPIOB
|
||||||
|
|
||||||
|
#define PIN_SDATA GPIO_Pin_6
|
||||||
|
#define PORT_SDATA GPIOB
|
||||||
|
|
||||||
|
#define PIN_SLE GPIO_Pin_8
|
||||||
|
#define PORT_SLE GPIOB
|
||||||
|
|
||||||
|
#define PIN_RXD GPIO_Pin_4
|
||||||
|
#define PORT_RXD GPIOB
|
||||||
|
|
||||||
|
#define PIN_TXD GPIO_Pin_3
|
||||||
|
#define PORT_TXD GPIOB
|
||||||
|
|
||||||
|
#define PIN_TXRX_CLK GPIO_Pin_15
|
||||||
|
#define PORT_TXRX_CLK GPIOA
|
||||||
|
#define PIN_TXRX_CLK_INT GPIO_PinSource15
|
||||||
|
#define PORT_TXRX_CLK_INT GPIO_PortSourceGPIOA
|
||||||
|
|
||||||
|
#define PIN_LED GPIO_Pin_13
|
||||||
|
#define PORT_LED GPIOC
|
||||||
|
|
||||||
|
#define PIN_DEB GPIO_Pin_9
|
||||||
|
#define PORT_DEB GPIOB
|
||||||
|
|
||||||
|
#define PIN_DSTAR_LED GPIO_Pin_12
|
||||||
|
#define PORT_DSTAR_LED GPIOB
|
||||||
|
|
||||||
|
#define PIN_DMR_LED GPIO_Pin_13
|
||||||
|
#define PORT_DMR_LED GPIOB
|
||||||
|
|
||||||
|
#define PIN_YSF_LED GPIO_Pin_1
|
||||||
|
#define PORT_YSF_LED GPIOB
|
||||||
|
|
||||||
|
#define PIN_P25_LED GPIO_Pin_0
|
||||||
|
#define PORT_P25_LED GPIOB
|
||||||
|
|
||||||
|
#define PIN_PTT_LED GPIO_Pin_14
|
||||||
|
#define PORT_PTT_LED GPIOB
|
||||||
|
|
||||||
|
#define PIN_COS_LED GPIO_Pin_15
|
||||||
|
#define PORT_COS_LED GPIOB
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void EXTI15_10_IRQHandler(void) {
|
||||||
|
if(EXTI_GetITStatus(EXTI_Line15)!=RESET) {
|
||||||
|
io.interrupt();
|
||||||
|
EXTI_ClearITPendingBit(EXTI_Line15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::delay_rx() {
|
||||||
|
volatile unsigned int delay;
|
||||||
|
for(delay = 0;delay<512;delay++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::Init()
|
||||||
|
{
|
||||||
|
// USB Conf IO:
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
|
||||||
|
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
|
||||||
|
|
||||||
|
RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5);
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
|
||||||
|
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
|
||||||
|
|
||||||
|
GPIO_InitTypeDef GPIO_InitStruct;
|
||||||
|
GPIO_StructInit(&GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin PA12 = LOW, USB Reset in generic boards
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
GPIO_WriteBit(GPIOA, GPIO_Pin_12, Bit_RESET);
|
||||||
|
|
||||||
|
volatile unsigned int delay;
|
||||||
|
for(delay = 0;delay<512;delay++);
|
||||||
|
|
||||||
|
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||||
|
GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin SCLK
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_SCLK;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_SCLK, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin SDATA
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_SDATA;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_SDATA, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin SLE
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_SLE;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_SLE, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin RXD
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_RXD;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||||
|
GPIO_Init(PORT_RXD, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin TXD
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_TXD;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_TXD, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin TXRX_CLK
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_TXRX_CLK;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||||
|
GPIO_Init(PORT_TXRX_CLK, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin LED
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_LED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_LED, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// Pin Debug
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_DEB;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_DEB, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// D-Star LED
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_DSTAR_LED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_DSTAR_LED, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// DMR LED
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_DMR_LED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_DMR_LED, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// YSF LED
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_YSF_LED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_YSF_LED, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// P25 LED
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_P25_LED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_P25_LED, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// PTT LED
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_PTT_LED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_PTT_LED, &GPIO_InitStruct);
|
||||||
|
|
||||||
|
// COS LED
|
||||||
|
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_InitStruct.GPIO_Pin = PIN_COS_LED;
|
||||||
|
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||||
|
GPIO_Init(PORT_COS_LED, &GPIO_InitStruct);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::ifInit()
|
||||||
|
{
|
||||||
|
EXTI_InitTypeDef EXTI_InitStructure;
|
||||||
|
NVIC_InitTypeDef NVIC_InitStructure;
|
||||||
|
|
||||||
|
m_started = true;
|
||||||
|
|
||||||
|
// Connect EXTI15 Line
|
||||||
|
GPIO_EXTILineConfig(PORT_TXRX_CLK_INT, PIN_TXRX_CLK_INT);
|
||||||
|
|
||||||
|
// Configure EXTI15 line
|
||||||
|
EXTI_InitStructure.EXTI_Line = EXTI_Line15;
|
||||||
|
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
|
||||||
|
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
|
||||||
|
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
|
||||||
|
EXTI_Init(&EXTI_InitStructure);
|
||||||
|
|
||||||
|
// Enable and set EXTI15 Interrupt
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||||
|
NVIC_Init(&NVIC_InitStructure);
|
||||||
|
|
||||||
|
ifConf();
|
||||||
|
delay_rx();;
|
||||||
|
setRX();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::SCLK_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_SCLK, PIN_SCLK, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::SDATA_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_SDATA, PIN_SDATA, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::SLE_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_SLE, PIN_SLE, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIO::RXD_pin()
|
||||||
|
{
|
||||||
|
return GPIO_ReadInputDataBit(PORT_RXD, PIN_RXD) == Bit_SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::TXD_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_TXD, PIN_TXD, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::LED_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_LED, PIN_LED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::DEB_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_DEB, PIN_DEB, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::DSTAR_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_DSTAR_LED, PIN_DSTAR_LED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::DMR_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_DMR_LED, PIN_DMR_LED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::YSF_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_YSF_LED, PIN_YSF_LED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::P25_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_P25_LED, PIN_P25_LED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::PTT_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_PTT_LED, PIN_PTT_LED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIO::COS_pin(bool on)
|
||||||
|
{
|
||||||
|
GPIO_WriteBit(PORT_COS_LED, PIN_COS_LED, on ? Bit_SET : Bit_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
340
LICENCE
Normal file
340
LICENCE
Normal file
|
|
@ -0,0 +1,340 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
||||||
87
MMDVM_HS.cpp
Normal file
87
MMDVM_HS.cpp
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016 by Mathis Schmieder DB9MAT
|
||||||
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#if defined(STM32F10X_MD)
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
MMDVM_STATE m_modemState = STATE_IDLE;
|
||||||
|
|
||||||
|
bool m_dstarEnable = true;
|
||||||
|
bool m_dmrEnable = true;
|
||||||
|
bool m_ysfEnable = true;
|
||||||
|
bool m_p25Enable = true;
|
||||||
|
|
||||||
|
bool m_tx = false;
|
||||||
|
bool m_dcd = false;
|
||||||
|
|
||||||
|
CDStarRX dstarRX;
|
||||||
|
CDStarTX dstarTX;
|
||||||
|
|
||||||
|
CDMRDMORX dmrDMORX;
|
||||||
|
CDMRDMOTX dmrDMOTX;
|
||||||
|
|
||||||
|
CYSFRX ysfRX;
|
||||||
|
CYSFTX ysfTX;
|
||||||
|
|
||||||
|
CP25RX p25RX;
|
||||||
|
CP25TX p25TX;
|
||||||
|
|
||||||
|
CSerialPort serial;
|
||||||
|
CIO io;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
serial.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
io.process();
|
||||||
|
|
||||||
|
serial.process();
|
||||||
|
|
||||||
|
// The following is for transmitting
|
||||||
|
if (m_dstarEnable && m_modemState == STATE_DSTAR)
|
||||||
|
dstarTX.process();
|
||||||
|
|
||||||
|
if (m_dmrEnable && m_modemState == STATE_DMR)
|
||||||
|
dmrDMOTX.process();
|
||||||
|
|
||||||
|
if (m_ysfEnable && m_modemState == STATE_YSF)
|
||||||
|
ysfTX.process();
|
||||||
|
|
||||||
|
if (m_p25Enable && m_modemState == STATE_P25)
|
||||||
|
p25TX.process();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
setup();
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
72
MMDVM_HS.ino
Normal file
72
MMDVM_HS.ino
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
MMDVM_STATE m_modemState = STATE_IDLE;
|
||||||
|
|
||||||
|
bool m_dstarEnable = true;
|
||||||
|
bool m_dmrEnable = true;
|
||||||
|
bool m_ysfEnable = true;
|
||||||
|
bool m_p25Enable = true;
|
||||||
|
|
||||||
|
bool m_tx = false;
|
||||||
|
bool m_dcd = false;
|
||||||
|
|
||||||
|
CDStarRX dstarRX;
|
||||||
|
CDStarTX dstarTX;
|
||||||
|
|
||||||
|
CDMRDMORX dmrDMORX;
|
||||||
|
CDMRDMOTX dmrDMOTX;
|
||||||
|
|
||||||
|
CYSFRX ysfRX;
|
||||||
|
CYSFTX ysfTX;
|
||||||
|
|
||||||
|
CP25RX p25RX;
|
||||||
|
CP25TX p25TX;
|
||||||
|
|
||||||
|
CSerialPort serial;
|
||||||
|
CIO io;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
serial.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
serial.process();
|
||||||
|
io.process();
|
||||||
|
|
||||||
|
// The following is for transmitting
|
||||||
|
if (m_dstarEnable && m_modemState == STATE_DSTAR)
|
||||||
|
dstarTX.process();
|
||||||
|
|
||||||
|
if (m_dmrEnable && m_modemState == STATE_DMR)
|
||||||
|
dmrDMOTX.process();
|
||||||
|
|
||||||
|
if (m_ysfEnable && m_modemState == STATE_YSF)
|
||||||
|
ysfTX.process();
|
||||||
|
|
||||||
|
if (m_p25Enable && m_modemState == STATE_P25)
|
||||||
|
p25TX.process();
|
||||||
|
|
||||||
|
}
|
||||||
157
Makefile
Normal file
157
Makefile
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
# Copyright (C) 2016 by Andy Uribe CA6JAU
|
||||||
|
# Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
# GNU ARM Embedded Toolchain
|
||||||
|
CC=arm-none-eabi-gcc
|
||||||
|
CXX=arm-none-eabi-g++
|
||||||
|
LD=arm-none-eabi-ld
|
||||||
|
AR=arm-none-eabi-ar
|
||||||
|
AS=arm-none-eabi-as
|
||||||
|
CP=arm-none-eabi-objcopy
|
||||||
|
OD=arm-none-eabi-objdump
|
||||||
|
NM=arm-none-eabi-nm
|
||||||
|
SIZE=arm-none-eabi-size
|
||||||
|
A2L=arm-none-eabi-addr2line
|
||||||
|
|
||||||
|
# Directory Structure
|
||||||
|
BINDIR=bin
|
||||||
|
|
||||||
|
# Find source files
|
||||||
|
# "SystemRoot" is only defined in Windows
|
||||||
|
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
|
||||||
|
MDBIN=md $@
|
||||||
|
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
|
||||||
|
MDBIN=md $@
|
||||||
|
else
|
||||||
|
ASOURCES=$(shell find . -name '*.s')
|
||||||
|
CSOURCES=$(shell find . -name '*.c')
|
||||||
|
CXXSOURCES=$(shell find . -name '*.cpp')
|
||||||
|
CLEANCMD=rm -f $(OBJECTS) $(BINDIR)/$(BINELF) $(BINDIR)/$(BINHEX) $(BINDIR)/$(BINBIN)
|
||||||
|
MDBIN=mkdir $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Default reference oscillator frequencies
|
||||||
|
ifndef $(OSC)
|
||||||
|
OSC=8000000
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Find header directories
|
||||||
|
INC= . STM32F10X_Lib/CMSIS/ STM32F10X_Lib/Device/ STM32F10X_Lib/STM32F10x_StdPeriph_Driver/inc/ STM32F10X_Lib/usb/inc/
|
||||||
|
INCLUDES=$(INC:%=-I%)
|
||||||
|
|
||||||
|
# Find libraries
|
||||||
|
INCLUDES_LIBS=
|
||||||
|
LINK_LIBS=
|
||||||
|
|
||||||
|
# Create object list
|
||||||
|
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-m3 -mthumb -Wall
|
||||||
|
|
||||||
|
# COMPILE FLAGS
|
||||||
|
DEFS_HS=-DUSE_STDPERIPH_DRIVER -DSTM32F10X_MD -DHSE_VALUE=$(OSC)
|
||||||
|
|
||||||
|
CFLAGS=-c $(MCFLAGS) $(INCLUDES)
|
||||||
|
CXXFLAGS=-c $(MCFLAGS) $(INCLUDES)
|
||||||
|
|
||||||
|
# LINKER FLAGS
|
||||||
|
LDSCRIPT=stm32f10x_link.ld
|
||||||
|
LDFLAGS =-T $(LDSCRIPT) $(MCFLAGS) --specs=nosys.specs $(INCLUDES_LIBS) $(LINK_LIBS)
|
||||||
|
|
||||||
|
# Build Rules
|
||||||
|
.PHONY: all release hs debug clean
|
||||||
|
|
||||||
|
all: hs
|
||||||
|
|
||||||
|
hs: CFLAGS+=$(DEFS_HS) -Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
|
||||||
|
hs: CXXFLAGS+=$(DEFS_HS) -Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
|
||||||
|
hs: LDFLAGS+=-Os --specs=nano.specs
|
||||||
|
hs: release
|
||||||
|
|
||||||
|
debug: CFLAGS+=-g
|
||||||
|
debug: CXXFLAGS+=-g
|
||||||
|
debug: LDFLAGS+=-g
|
||||||
|
debug: release
|
||||||
|
|
||||||
|
release: $(BINDIR)
|
||||||
|
release: $(BINDIR)/$(BINHEX)
|
||||||
|
release: $(BINDIR)/$(BINBIN)
|
||||||
|
|
||||||
|
$(BINDIR):
|
||||||
|
$(MDBIN)
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINHEX): $(BINDIR)/$(BINELF)
|
||||||
|
$(CP) -O ihex $< $@
|
||||||
|
@echo "Objcopy from ELF to IHEX complete!\n"
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINBIN): $(BINDIR)/$(BINELF)
|
||||||
|
$(CP) -O binary $< $@
|
||||||
|
@echo "Objcopy from ELF to BINARY complete!\n"
|
||||||
|
|
||||||
|
$(BINDIR)/$(BINELF): $(OBJECTS)
|
||||||
|
$(CXX) $(OBJECTS) $(LDFLAGS) -o $@
|
||||||
|
@echo "Linking complete!\n"
|
||||||
|
$(SIZE) $(BINDIR)/$(BINELF)
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Compiled "$<"!\n"
|
||||||
|
|
||||||
|
%.o: %.s
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
@echo "Assambled "$<"!\n"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(CLEANCMD)
|
||||||
|
|
||||||
|
stlink:
|
||||||
|
ifneq ($(wildcard /usr/bin/openocd),)
|
||||||
|
/usr/bin/openocd -f /usr/share/openocd/scripts/interface/stlink-v2-1.cfg -f /usr/share/openocd/scripts/target/stm32f1x.cfg -c "program bin/$(BINELF) 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/stm32f1x.cfg -c "program bin/$(BINELF) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(wildcard /opt/openocd/bin/openocd),)
|
||||||
|
/opt/openocd/bin/openocd -f /opt/openocd/scripts/interface/stlink-v2-1.cfg -f /opt/openocd/share/openocd/scripts/target/stm32f1x.cfg -c "program bin/$(BINELF) verify reset exit"
|
||||||
|
endif
|
||||||
|
|
||||||
|
serial:
|
||||||
|
ifneq ($(wildcard /usr/local/bin/stm32flash),)
|
||||||
|
/usr/local/bin/stm32flash -w bin/$(BINBIN) -g 0x0 $(devser)
|
||||||
|
endif
|
||||||
58
P25Defines.h
Normal file
58
P25Defines.h
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(P25DEFINES_H)
|
||||||
|
#define P25DEFINES_H
|
||||||
|
|
||||||
|
const unsigned int P25_HDR_FRAME_LENGTH_BYTES = 99U;
|
||||||
|
const unsigned int P25_HDR_FRAME_LENGTH_BITS = P25_HDR_FRAME_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int P25_HDR_FRAME_LENGTH_SYMBOLS = P25_HDR_FRAME_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int P25_LDU_FRAME_LENGTH_BYTES = 216U;
|
||||||
|
const unsigned int P25_LDU_FRAME_LENGTH_BITS = P25_LDU_FRAME_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int P25_LDU_FRAME_LENGTH_SYMBOLS = P25_LDU_FRAME_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int P25_TERMLC_FRAME_LENGTH_BYTES = 54U;
|
||||||
|
const unsigned int P25_TERMLC_FRAME_LENGTH_BITS = P25_TERMLC_FRAME_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int P25_TERMLC_FRAME_LENGTH_SYMBOLS = P25_TERMLC_FRAME_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int P25_TERM_FRAME_LENGTH_BYTES = 18U;
|
||||||
|
const unsigned int P25_TERM_FRAME_LENGTH_BITS = P25_TERM_FRAME_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int P25_TERM_FRAME_LENGTH_SYMBOLS = P25_TERM_FRAME_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int P25_SYNC_LENGTH_BYTES = 6U;
|
||||||
|
const unsigned int P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int P25_SYNC_LENGTH_SYMBOLS = P25_SYNC_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int P25_NID_LENGTH_BITS = 64U;
|
||||||
|
const unsigned int P25_NID_LENGTH_SYMBOLS = 32U;
|
||||||
|
|
||||||
|
const uint8_t P25_SYNC_BYTES[] = {0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU};
|
||||||
|
const uint8_t P25_SYNC_BYTES_LENGTH = 6U;
|
||||||
|
|
||||||
|
const uint64_t P25_SYNC_BITS = 0x00005575F5FF77FFU;
|
||||||
|
const uint64_t P25_SYNC_BITS_MASK = 0x0000FFFFFFFFFFFFU;
|
||||||
|
|
||||||
|
// 5 5 7 5 F 5 F F 7 7 F F
|
||||||
|
// 01 01 01 01 01 11 01 01 11 11 01 01 11 11 11 11 01 11 01 11 11 11 11 11
|
||||||
|
// +3 +3 +3 +3 +3 -3 +3 +3 -3 -3 +3 +3 -3 -3 -3 -3 +3 -3 +3 -3 -3 -3 -3 -3
|
||||||
|
|
||||||
|
const uint32_t P25_SYNC_SYMBOLS = 0x00FB30A0U;
|
||||||
|
const uint32_t P25_SYNC_SYMBOLS_MASK = 0x00FFFFFFU;
|
||||||
|
|
||||||
|
#endif
|
||||||
143
P25RX.cpp
Normal file
143
P25RX.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016,2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "P25RX.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
const uint8_t SYNC_BIT_START_ERRS = 2U;
|
||||||
|
const uint8_t SYNC_BIT_RUN_ERRS = 4U;
|
||||||
|
|
||||||
|
const unsigned int MAX_SYNC_FRAMES = 3U + 1U;
|
||||||
|
|
||||||
|
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])
|
||||||
|
|
||||||
|
CP25RX::CP25RX() :
|
||||||
|
m_prev(false),
|
||||||
|
m_state(P25RXS_NONE),
|
||||||
|
m_bitBuffer(0x00U),
|
||||||
|
m_outBuffer(),
|
||||||
|
m_buffer(NULL),
|
||||||
|
m_bufferPtr(0U),
|
||||||
|
m_lostCount(0U)
|
||||||
|
{
|
||||||
|
m_buffer = m_outBuffer + 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25RX::reset()
|
||||||
|
{
|
||||||
|
m_prev = false;
|
||||||
|
m_state = P25RXS_NONE;
|
||||||
|
m_bitBuffer = 0x00U;
|
||||||
|
m_bufferPtr = 0U;
|
||||||
|
m_lostCount = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25RX::databit(bool bit)
|
||||||
|
{
|
||||||
|
if (m_state == P25RXS_NONE)
|
||||||
|
processNone(bit);
|
||||||
|
else
|
||||||
|
processData(bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25RX::processNone(bool bit)
|
||||||
|
{
|
||||||
|
m_bitBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_bitBuffer |= 0x01U;
|
||||||
|
|
||||||
|
// Fuzzy matching of the data sync bit sequence
|
||||||
|
if (countBits64((m_bitBuffer & P25_SYNC_BITS_MASK) ^ P25_SYNC_BITS) <= SYNC_BIT_START_ERRS) {
|
||||||
|
DEBUG1("P25RX: sync found in None");
|
||||||
|
for (uint8_t i = 0U; i < P25_SYNC_LENGTH_BYTES; i++)
|
||||||
|
m_buffer[i] = P25_SYNC_BYTES[i];
|
||||||
|
|
||||||
|
m_lostCount = MAX_SYNC_FRAMES;
|
||||||
|
m_bufferPtr = P25_SYNC_LENGTH_BITS;
|
||||||
|
m_state = P25RXS_DATA;
|
||||||
|
|
||||||
|
io.setDecode(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25RX::processData(bool bit)
|
||||||
|
{
|
||||||
|
m_bitBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_bitBuffer |= 0x01U;
|
||||||
|
|
||||||
|
WRITE_BIT1(m_buffer, m_bufferPtr, bit);
|
||||||
|
m_bufferPtr++;
|
||||||
|
|
||||||
|
// Search for an early sync to indicate an LDU following a header
|
||||||
|
if (m_bufferPtr >= (P25_HDR_FRAME_LENGTH_BITS + P25_SYNC_LENGTH_BITS - 1U) && m_bufferPtr <= (P25_HDR_FRAME_LENGTH_BITS + P25_SYNC_LENGTH_BITS + 1U)) {
|
||||||
|
// Fuzzy matching of the data sync bit sequence
|
||||||
|
if (countBits64((m_bitBuffer & P25_SYNC_BITS_MASK) ^ P25_SYNC_BITS) <= SYNC_BIT_RUN_ERRS) {
|
||||||
|
DEBUG2("P25RX: found LDU sync in Data, pos", m_bufferPtr - P25_SYNC_LENGTH_BITS);
|
||||||
|
|
||||||
|
m_outBuffer[0U] = 0x01U;
|
||||||
|
serial.writeP25Hdr(m_outBuffer, P25_HDR_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
|
||||||
|
// Restore the sync that's now in the wrong place
|
||||||
|
for (uint8_t i = 0U; i < P25_SYNC_LENGTH_BYTES; i++)
|
||||||
|
m_buffer[i] = P25_SYNC_BYTES[i];
|
||||||
|
|
||||||
|
m_lostCount = MAX_SYNC_FRAMES;
|
||||||
|
m_bufferPtr = P25_SYNC_LENGTH_BITS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only search for a sync in the right place +-2 symbols
|
||||||
|
if (m_bufferPtr >= (P25_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (P25_SYNC_LENGTH_BITS + 2U)) {
|
||||||
|
// Fuzzy matching of the data sync bit sequence
|
||||||
|
if (countBits64((m_bitBuffer & P25_SYNC_BITS_MASK) ^ P25_SYNC_BITS) <= SYNC_BIT_RUN_ERRS) {
|
||||||
|
DEBUG2("P25RX: found sync in Data, pos", m_bufferPtr - P25_SYNC_LENGTH_BITS);
|
||||||
|
m_lostCount = MAX_SYNC_FRAMES;
|
||||||
|
m_bufferPtr = P25_SYNC_LENGTH_BITS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a data frame to the host if the required number of bits have been received
|
||||||
|
if (m_bufferPtr == P25_LDU_FRAME_LENGTH_BITS) {
|
||||||
|
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
||||||
|
m_lostCount--;
|
||||||
|
if (m_lostCount == 0U) {
|
||||||
|
DEBUG1("P25RX: sync timed out, lost lock");
|
||||||
|
io.setDecode(false);
|
||||||
|
|
||||||
|
serial.writeP25Lost();
|
||||||
|
|
||||||
|
m_state = P25RXS_NONE;
|
||||||
|
} else {
|
||||||
|
m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||||
|
|
||||||
|
serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
|
||||||
|
// Start the next frame
|
||||||
|
::memset(m_outBuffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U);
|
||||||
|
m_bufferPtr = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
52
P25RX.h
Normal file
52
P25RX.h
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017 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(P25RX_H)
|
||||||
|
#define P25RX_H
|
||||||
|
|
||||||
|
#include "P25Defines.h"
|
||||||
|
|
||||||
|
enum P25RX_STATE {
|
||||||
|
P25RXS_NONE,
|
||||||
|
P25RXS_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
class CP25RX {
|
||||||
|
public:
|
||||||
|
CP25RX();
|
||||||
|
|
||||||
|
void databit(bool bit);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_prev;
|
||||||
|
P25RX_STATE m_state;
|
||||||
|
uint64_t m_bitBuffer;
|
||||||
|
uint8_t m_outBuffer[P25_LDU_FRAME_LENGTH_BYTES + 3U];
|
||||||
|
uint8_t* m_buffer;
|
||||||
|
uint16_t m_bufferPtr;
|
||||||
|
uint16_t m_lostCount;
|
||||||
|
|
||||||
|
void processNone(bool bit);
|
||||||
|
void processData(bool bit);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
122
P25TX.cpp
Normal file
122
P25TX.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "P25TX.h"
|
||||||
|
|
||||||
|
#include "P25Defines.h"
|
||||||
|
|
||||||
|
const uint8_t P25_START_SYNC = 0x77U;
|
||||||
|
|
||||||
|
CP25TX::CP25TX() :
|
||||||
|
m_buffer(1500U),
|
||||||
|
m_poBuffer(),
|
||||||
|
m_poLen(0U),
|
||||||
|
m_poPtr(0U),
|
||||||
|
m_txDelay(240U), // 200ms
|
||||||
|
m_count(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25TX::process()
|
||||||
|
{
|
||||||
|
if (m_buffer.getData() == 0U && m_poLen == 0U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_poLen == 0U) {
|
||||||
|
if (!m_tx) {
|
||||||
|
m_delay = true;
|
||||||
|
m_count = 0U;
|
||||||
|
m_poLen = m_txDelay;
|
||||||
|
} else {
|
||||||
|
uint8_t length = m_buffer.get();
|
||||||
|
m_delay = false;
|
||||||
|
for (uint8_t i = 0U; i < length; i++) {
|
||||||
|
m_poBuffer[m_poLen++] = m_buffer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_poPtr = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_poLen > 0U) {
|
||||||
|
uint16_t space = io.getSpace();
|
||||||
|
|
||||||
|
while (space > 8U) {
|
||||||
|
if (m_delay) {
|
||||||
|
m_poPtr++;
|
||||||
|
writeByte(P25_START_SYNC);
|
||||||
|
} else
|
||||||
|
writeByte(m_poBuffer[m_poPtr++]);
|
||||||
|
|
||||||
|
space -= 8U;
|
||||||
|
|
||||||
|
if (m_poPtr >= m_poLen) {
|
||||||
|
m_poPtr = 0U;
|
||||||
|
m_poLen = 0U;
|
||||||
|
m_delay = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CP25TX::writeData(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length < (P25_TERM_FRAME_LENGTH_BYTES + 1U))
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
uint16_t space = m_buffer.getSpace();
|
||||||
|
if (space < length)
|
||||||
|
return 5U;
|
||||||
|
|
||||||
|
m_buffer.put(length - 1U);
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < (length - 1U); i++)
|
||||||
|
m_buffer.put(data[i + 1U]);
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25TX::writeByte(uint8_t c)
|
||||||
|
{
|
||||||
|
uint8_t bit;
|
||||||
|
uint8_t mask = 0x80U;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < 8U; i++, c <<= 1) {
|
||||||
|
if ((c & mask) == mask)
|
||||||
|
bit = 1U;
|
||||||
|
else
|
||||||
|
bit = 0U;
|
||||||
|
|
||||||
|
io.write(&bit, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25TX::setTXDelay(uint8_t delay)
|
||||||
|
{
|
||||||
|
m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CP25TX::getSpace() const
|
||||||
|
{
|
||||||
|
return m_buffer.getSpace() / P25_LDU_FRAME_LENGTH_BYTES;
|
||||||
|
}
|
||||||
49
P25TX.h
Normal file
49
P25TX.h
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016,2017 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(P25TX_H)
|
||||||
|
#define P25TX_H
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
|
class CP25TX {
|
||||||
|
public:
|
||||||
|
CP25TX();
|
||||||
|
|
||||||
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setTXDelay(uint8_t delay);
|
||||||
|
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSerialRB m_buffer;
|
||||||
|
uint8_t m_poBuffer[250U];
|
||||||
|
uint16_t m_poLen;
|
||||||
|
uint16_t m_poPtr;
|
||||||
|
uint16_t m_txDelay;
|
||||||
|
uint32_t m_count;
|
||||||
|
bool m_delay;
|
||||||
|
|
||||||
|
void writeByte(uint8_t c);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
95
SerialArduino.cpp
Executable file
95
SerialArduino.cpp
Executable file
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#include "SerialPort.h"
|
||||||
|
|
||||||
|
#if defined(ARDUINO)
|
||||||
|
|
||||||
|
void CSerialPort::beginInt(uint8_t n, int speed)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
Serial.begin(speed);
|
||||||
|
break;
|
||||||
|
/* case 2U:
|
||||||
|
Serial2.begin(speed);
|
||||||
|
break;
|
||||||
|
case 3U:
|
||||||
|
Serial3.begin(speed);
|
||||||
|
break;*/
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSerialPort::availableInt(uint8_t n)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
return Serial.available();
|
||||||
|
/* case 2U:
|
||||||
|
return Serial2.available();
|
||||||
|
case 3U:
|
||||||
|
return Serial3.available();*/
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSerialPort::readInt(uint8_t n)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
return Serial.read();
|
||||||
|
/* case 2U:
|
||||||
|
return Serial2.read();
|
||||||
|
case 3U:
|
||||||
|
return Serial3.read();*/
|
||||||
|
default:
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
Serial.write(data, length);
|
||||||
|
if (flush)
|
||||||
|
Serial.flush();
|
||||||
|
break;
|
||||||
|
/* case 2U:
|
||||||
|
Serial2.write(data, length);
|
||||||
|
if (flush)
|
||||||
|
Serial2.flush();
|
||||||
|
break;
|
||||||
|
case 3U:
|
||||||
|
Serial3.write(data, length);
|
||||||
|
if (flush)
|
||||||
|
Serial3.flush();
|
||||||
|
break;*/
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
892
SerialPort.cpp
Normal file
892
SerialPort.cpp
Normal file
|
|
@ -0,0 +1,892 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013,2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
#include "SerialPort.h"
|
||||||
|
|
||||||
|
const uint8_t MMDVM_FRAME_START = 0xE0U;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_GET_VERSION = 0x00U;
|
||||||
|
const uint8_t MMDVM_GET_STATUS = 0x01U;
|
||||||
|
const uint8_t MMDVM_SET_CONFIG = 0x02U;
|
||||||
|
const uint8_t MMDVM_SET_MODE = 0x03U;
|
||||||
|
const uint8_t MMDVM_SET_FREQ = 0x04U;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_CAL_DATA = 0x08U;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_SEND_CWID = 0x0AU;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_DSTAR_HEADER = 0x10U;
|
||||||
|
const uint8_t MMDVM_DSTAR_DATA = 0x11U;
|
||||||
|
const uint8_t MMDVM_DSTAR_LOST = 0x12U;
|
||||||
|
const uint8_t MMDVM_DSTAR_EOT = 0x13U;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_DMR_DATA1 = 0x18U;
|
||||||
|
const uint8_t MMDVM_DMR_LOST1 = 0x19U;
|
||||||
|
const uint8_t MMDVM_DMR_DATA2 = 0x1AU;
|
||||||
|
const uint8_t MMDVM_DMR_LOST2 = 0x1BU;
|
||||||
|
const uint8_t MMDVM_DMR_SHORTLC = 0x1CU;
|
||||||
|
const uint8_t MMDVM_DMR_START = 0x1DU;
|
||||||
|
const uint8_t MMDVM_DMR_ABORT = 0x1EU;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_YSF_DATA = 0x20U;
|
||||||
|
const uint8_t MMDVM_YSF_LOST = 0x21U;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_P25_HDR = 0x30U;
|
||||||
|
const uint8_t MMDVM_P25_LDU = 0x31U;
|
||||||
|
const uint8_t MMDVM_P25_LOST = 0x32U;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_ACK = 0x70U;
|
||||||
|
const uint8_t MMDVM_NAK = 0x7FU;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_SERIAL = 0x80U;
|
||||||
|
|
||||||
|
const uint8_t MMDVM_DEBUG1 = 0xF1U;
|
||||||
|
const uint8_t MMDVM_DEBUG2 = 0xF2U;
|
||||||
|
const uint8_t MMDVM_DEBUG3 = 0xF3U;
|
||||||
|
const uint8_t MMDVM_DEBUG4 = 0xF4U;
|
||||||
|
const uint8_t MMDVM_DEBUG5 = 0xF5U;
|
||||||
|
|
||||||
|
const uint8_t HARDWARE[] = "MMDVM 20161213-HS (D-Star/DMR/YSF/P25)";
|
||||||
|
|
||||||
|
const uint8_t PROTOCOL_VERSION = 1U;
|
||||||
|
|
||||||
|
|
||||||
|
CSerialPort::CSerialPort() :
|
||||||
|
m_buffer(),
|
||||||
|
m_ptr(0U),
|
||||||
|
m_len(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::sendACK()
|
||||||
|
{
|
||||||
|
uint8_t reply[4U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 4U;
|
||||||
|
reply[2U] = MMDVM_ACK;
|
||||||
|
reply[3U] = m_buffer[2U];
|
||||||
|
|
||||||
|
writeInt(1U, reply, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::sendNAK(uint8_t err)
|
||||||
|
{
|
||||||
|
uint8_t reply[5U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 5U;
|
||||||
|
reply[2U] = MMDVM_NAK;
|
||||||
|
reply[3U] = m_buffer[2U];
|
||||||
|
reply[4U] = err;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::getStatus()
|
||||||
|
{
|
||||||
|
//io.resetWatchdog();
|
||||||
|
|
||||||
|
uint8_t reply[15U];
|
||||||
|
|
||||||
|
// Send all sorts of interesting internal values
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 11U;
|
||||||
|
reply[2U] = MMDVM_GET_STATUS;
|
||||||
|
|
||||||
|
reply[3U] = 0x00U;
|
||||||
|
if (m_dstarEnable)
|
||||||
|
reply[3U] |= 0x01U;
|
||||||
|
if (m_dmrEnable)
|
||||||
|
reply[3U] |= 0x02U;
|
||||||
|
if (m_ysfEnable)
|
||||||
|
reply[3U] |= 0x04U;
|
||||||
|
if (m_p25Enable)
|
||||||
|
reply[3U] |= 0x08U;
|
||||||
|
|
||||||
|
reply[4U] = uint8_t(m_modemState);
|
||||||
|
|
||||||
|
reply[5U] = m_tx ? 0x01U : 0x00U;
|
||||||
|
|
||||||
|
if (io.hasRXOverflow())
|
||||||
|
reply[5U] |= 0x04U;
|
||||||
|
|
||||||
|
if (io.hasTXOverflow())
|
||||||
|
reply[5U] |= 0x08U;
|
||||||
|
|
||||||
|
if (m_dstarEnable)
|
||||||
|
reply[6U] = dstarTX.getSpace();
|
||||||
|
else
|
||||||
|
reply[6U] = 0U;
|
||||||
|
|
||||||
|
if (m_dmrEnable) {
|
||||||
|
reply[7U] = 10U;
|
||||||
|
reply[8U] = dmrDMOTX.getSpace();
|
||||||
|
} else {
|
||||||
|
reply[7U] = 0U;
|
||||||
|
reply[8U] = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_ysfEnable)
|
||||||
|
reply[9U] = ysfTX.getSpace();
|
||||||
|
else
|
||||||
|
reply[9U] = 0U;
|
||||||
|
|
||||||
|
if (m_p25Enable)
|
||||||
|
reply[10U] = p25TX.getSpace();
|
||||||
|
else
|
||||||
|
reply[10U] = 0U;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::getVersion()
|
||||||
|
{
|
||||||
|
uint8_t reply[100U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_GET_VERSION;
|
||||||
|
|
||||||
|
reply[3U] = PROTOCOL_VERSION;
|
||||||
|
|
||||||
|
uint8_t count = 4U;
|
||||||
|
for (uint8_t i = 0U; HARDWARE[i] != 0x00U; i++, count++)
|
||||||
|
reply[count] = HARDWARE[i];
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length < 13U)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
bool dstarEnable = (data[1U] & 0x01U) == 0x01U;
|
||||||
|
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
|
||||||
|
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
|
||||||
|
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
||||||
|
|
||||||
|
uint8_t txDelay = data[2U];
|
||||||
|
if (txDelay > 50U)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
|
||||||
|
|
||||||
|
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25)
|
||||||
|
return 4U;
|
||||||
|
if (modemState == STATE_DSTAR && !dstarEnable)
|
||||||
|
return 4U;
|
||||||
|
if (modemState == STATE_DMR && !dmrEnable)
|
||||||
|
return 4U;
|
||||||
|
if (modemState == STATE_YSF && !ysfEnable)
|
||||||
|
return 4U;
|
||||||
|
if (modemState == STATE_P25 && !p25Enable)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
uint8_t colorCode = data[6U];
|
||||||
|
if (colorCode > 15U)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
// uint8_t dmrDelay = data[7U];
|
||||||
|
|
||||||
|
m_modemState = modemState;
|
||||||
|
|
||||||
|
m_dstarEnable = dstarEnable;
|
||||||
|
m_dmrEnable = dmrEnable;
|
||||||
|
m_ysfEnable = ysfEnable;
|
||||||
|
m_p25Enable = p25Enable;
|
||||||
|
|
||||||
|
dstarTX.setTXDelay(txDelay);
|
||||||
|
ysfTX.setTXDelay(txDelay);
|
||||||
|
p25TX.setTXDelay(txDelay);
|
||||||
|
dmrDMOTX.setTXDelay(txDelay);
|
||||||
|
|
||||||
|
dmrDMORX.setColorCode(colorCode);
|
||||||
|
|
||||||
|
io.ifInit();
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length < 1U)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
MMDVM_STATE modemState = MMDVM_STATE(data[0U]);
|
||||||
|
|
||||||
|
if (modemState == m_modemState)
|
||||||
|
return 0U;
|
||||||
|
|
||||||
|
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25)
|
||||||
|
return 4U;
|
||||||
|
if (modemState == STATE_DSTAR && !m_dstarEnable)
|
||||||
|
return 4U;
|
||||||
|
if (modemState == STATE_DMR && !m_dmrEnable)
|
||||||
|
return 4U;
|
||||||
|
if (modemState == STATE_YSF && !m_ysfEnable)
|
||||||
|
return 4U;
|
||||||
|
if (modemState == STATE_P25 && !m_p25Enable)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
setMode(modemState);
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSerialPort::setFreq(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
uint32_t freq_rx, freq_tx;
|
||||||
|
|
||||||
|
if (length < 9U)
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
freq_rx = data[1] * 1;
|
||||||
|
freq_rx += data[2] * 256;
|
||||||
|
freq_rx += data[3] * 65536;
|
||||||
|
freq_rx += data[4] * 16777216;
|
||||||
|
|
||||||
|
freq_tx = data[5] * 1;
|
||||||
|
freq_tx += data[6] * 256;
|
||||||
|
freq_tx += data[7] * 65536;
|
||||||
|
freq_tx += data[8] * 16777216;
|
||||||
|
|
||||||
|
return io.setFreq(freq_rx, freq_tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::setMode(MMDVM_STATE modemState)
|
||||||
|
{
|
||||||
|
switch (modemState) {
|
||||||
|
case STATE_DMR:
|
||||||
|
DEBUG1("Mode set to DMR");
|
||||||
|
dstarRX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_DSTAR:
|
||||||
|
DEBUG1("Mode set to D-Star");
|
||||||
|
dmrDMORX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_YSF:
|
||||||
|
DEBUG1("Mode set to System Fusion");
|
||||||
|
dmrDMORX.reset();
|
||||||
|
dstarRX.reset();
|
||||||
|
p25RX.reset();
|
||||||
|
break;
|
||||||
|
case STATE_P25:
|
||||||
|
DEBUG1("Mode set to P25");
|
||||||
|
dmrDMORX.reset();
|
||||||
|
dstarRX.reset();
|
||||||
|
ysfRX.reset();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG1("Mode set to Idle");
|
||||||
|
// STATE_IDLE
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_modemState = modemState;
|
||||||
|
|
||||||
|
io.setMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::start()
|
||||||
|
{
|
||||||
|
beginInt(1U, 115200);
|
||||||
|
|
||||||
|
#if defined(SERIAL_REPEATER)
|
||||||
|
beginInt(3U, 9600);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::process()
|
||||||
|
{
|
||||||
|
while (availableInt(1U)) {
|
||||||
|
uint8_t c = readInt(1U);
|
||||||
|
|
||||||
|
if (m_ptr == 0U) {
|
||||||
|
if (c == MMDVM_FRAME_START) {
|
||||||
|
// Handle the frame start correctly
|
||||||
|
m_buffer[0U] = c;
|
||||||
|
m_ptr = 1U;
|
||||||
|
m_len = 0U;
|
||||||
|
}
|
||||||
|
} else if (m_ptr == 1U) {
|
||||||
|
// Handle the frame length
|
||||||
|
m_len = m_buffer[m_ptr] = c;
|
||||||
|
m_ptr = 2U;
|
||||||
|
} else {
|
||||||
|
// Any other bytes are added to the buffer
|
||||||
|
m_buffer[m_ptr] = c;
|
||||||
|
m_ptr++;
|
||||||
|
|
||||||
|
// The full packet has been received, process it
|
||||||
|
if (m_ptr == m_len) {
|
||||||
|
uint8_t err = 2U;
|
||||||
|
|
||||||
|
switch (m_buffer[2U]) {
|
||||||
|
case MMDVM_GET_STATUS:
|
||||||
|
getStatus();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_GET_VERSION:
|
||||||
|
getVersion();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_SET_CONFIG:
|
||||||
|
err = setConfig(m_buffer + 3U, m_len - 3U);
|
||||||
|
if (err == 0U)
|
||||||
|
sendACK();
|
||||||
|
else
|
||||||
|
sendNAK(err);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_SET_MODE:
|
||||||
|
err = setMode(m_buffer + 3U, m_len - 3U);
|
||||||
|
if (err == 0U)
|
||||||
|
sendACK();
|
||||||
|
else
|
||||||
|
sendNAK(err);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_SET_FREQ:
|
||||||
|
err = setFreq(m_buffer + 3U, m_len - 3U);
|
||||||
|
if (err == 0U)
|
||||||
|
sendACK();
|
||||||
|
else
|
||||||
|
sendNAK(err);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_CAL_DATA:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_SEND_CWID:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_DSTAR_HEADER:
|
||||||
|
if (m_dstarEnable) {
|
||||||
|
if (m_modemState == STATE_IDLE || m_modemState == STATE_DSTAR)
|
||||||
|
err = dstarTX.writeHeader(m_buffer + 3U, m_len - 3U);
|
||||||
|
}
|
||||||
|
if (err == 0U) {
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
setMode(STATE_DSTAR);
|
||||||
|
} else {
|
||||||
|
DEBUG2("Received invalid D-Star header", err);
|
||||||
|
sendNAK(err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_DSTAR_DATA:
|
||||||
|
if (m_dstarEnable) {
|
||||||
|
if (m_modemState == STATE_IDLE || m_modemState == STATE_DSTAR)
|
||||||
|
err = dstarTX.writeData(m_buffer + 3U, m_len - 3U);
|
||||||
|
}
|
||||||
|
if (err == 0U) {
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
setMode(STATE_DSTAR);
|
||||||
|
} else {
|
||||||
|
DEBUG2("Received invalid D-Star data", err);
|
||||||
|
sendNAK(err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_DSTAR_EOT:
|
||||||
|
if (m_dstarEnable) {
|
||||||
|
if (m_modemState == STATE_IDLE || m_modemState == STATE_DSTAR)
|
||||||
|
err = dstarTX.writeEOT();
|
||||||
|
}
|
||||||
|
if (err == 0U) {
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
setMode(STATE_DSTAR);
|
||||||
|
} else {
|
||||||
|
DEBUG2("Received invalid D-Star EOT", err);
|
||||||
|
sendNAK(err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_DMR_DATA1:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_DMR_DATA2:
|
||||||
|
if (m_dmrEnable) {
|
||||||
|
if (m_modemState == STATE_IDLE || m_modemState == STATE_DMR) {
|
||||||
|
err = dmrDMOTX.writeData(m_buffer + 3U, m_len - 3U);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (err == 0U) {
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
setMode(STATE_DMR);
|
||||||
|
} else {
|
||||||
|
DEBUG2("Received invalid DMR data", err);
|
||||||
|
sendNAK(err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_DMR_START:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_DMR_SHORTLC:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_DMR_ABORT:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_YSF_DATA:
|
||||||
|
if (m_ysfEnable) {
|
||||||
|
if (m_modemState == STATE_IDLE || m_modemState == STATE_YSF)
|
||||||
|
err = ysfTX.writeData(m_buffer + 3U, m_len - 3U);
|
||||||
|
}
|
||||||
|
if (err == 0U) {
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
setMode(STATE_YSF);
|
||||||
|
} else {
|
||||||
|
DEBUG2("Received invalid System Fusion data", err);
|
||||||
|
sendNAK(err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_P25_HDR:
|
||||||
|
if (m_p25Enable) {
|
||||||
|
if (m_modemState == STATE_IDLE || m_modemState == STATE_P25)
|
||||||
|
err = p25TX.writeData(m_buffer + 3U, m_len - 3U);
|
||||||
|
}
|
||||||
|
if (err == 0U) {
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
setMode(STATE_P25);
|
||||||
|
} else {
|
||||||
|
DEBUG2("Received invalid P25 header", err);
|
||||||
|
sendNAK(err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMDVM_P25_LDU:
|
||||||
|
if (m_p25Enable) {
|
||||||
|
if (m_modemState == STATE_IDLE || m_modemState == STATE_P25)
|
||||||
|
err = p25TX.writeData(m_buffer + 3U, m_len - 3U);
|
||||||
|
}
|
||||||
|
if (err == 0U) {
|
||||||
|
if (m_modemState == STATE_IDLE)
|
||||||
|
setMode(STATE_P25);
|
||||||
|
} else {
|
||||||
|
DEBUG2("Received invalid P25 LDU", err);
|
||||||
|
sendNAK(err);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if defined(SERIAL_REPEATER)
|
||||||
|
case MMDVM_SERIAL:
|
||||||
|
writeInt(3U, m_buffer + 3U, m_len - 3U);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Handle this, send a NAK back
|
||||||
|
sendNAK(1U);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ptr = 0U;
|
||||||
|
m_len = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(SERIAL_REPEATER)
|
||||||
|
// Drain any incoming serial data
|
||||||
|
while (availableInt(3U))
|
||||||
|
readInt(3U);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDStarHeader(const uint8_t* header, uint8_t length)
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_DSTAR && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_dstarEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[50U];
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_DSTAR_HEADER;
|
||||||
|
|
||||||
|
uint8_t count = 3U;
|
||||||
|
for (uint8_t i = 0U; i < length; i++, count++)
|
||||||
|
reply[count] = header[i];
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDStarData(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_DSTAR && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_dstarEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[20U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_DSTAR_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::writeDStarLost()
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_DSTAR && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_dstarEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[3U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 3U;
|
||||||
|
reply[2U] = MMDVM_DSTAR_LOST;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDStarEOT()
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_DSTAR && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_dstarEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[3U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 3U;
|
||||||
|
reply[2U] = MMDVM_DSTAR_EOT;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDMRData(bool slot, const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_DMR && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_dmrEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[40U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = slot ? MMDVM_DMR_DATA2 : MMDVM_DMR_DATA1;
|
||||||
|
|
||||||
|
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::writeDMRLost(bool slot)
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_DMR && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_dmrEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[3U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 3U;
|
||||||
|
reply[2U] = slot ? MMDVM_DMR_LOST2 : MMDVM_DMR_LOST1;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeYSFData(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_YSF && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_ysfEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[130U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_YSF_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::writeYSFLost()
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_YSF && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_ysfEnable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[3U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 3U;
|
||||||
|
reply[2U] = MMDVM_YSF_LOST;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeP25Hdr(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_p25Enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[120U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_P25_HDR;
|
||||||
|
|
||||||
|
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::writeP25Ldu(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_p25Enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[250U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_P25_LDU;
|
||||||
|
|
||||||
|
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::writeP25Lost()
|
||||||
|
{
|
||||||
|
if (m_modemState != STATE_P25 && m_modemState != STATE_IDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_p25Enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[3U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 3U;
|
||||||
|
reply[2U] = MMDVM_P25_LOST;
|
||||||
|
|
||||||
|
writeInt(1U, reply, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDebug(const char* text)
|
||||||
|
{
|
||||||
|
uint8_t reply[130U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_DEBUG1;
|
||||||
|
|
||||||
|
uint8_t count = 3U;
|
||||||
|
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
|
||||||
|
reply[count] = text[i];
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDebug(const char* text, int16_t n1)
|
||||||
|
{
|
||||||
|
uint8_t reply[130U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_DEBUG2;
|
||||||
|
|
||||||
|
uint8_t count = 3U;
|
||||||
|
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
|
||||||
|
reply[count] = text[i];
|
||||||
|
|
||||||
|
reply[count++] = (n1 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n1 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2)
|
||||||
|
{
|
||||||
|
uint8_t reply[130U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_DEBUG3;
|
||||||
|
|
||||||
|
uint8_t count = 3U;
|
||||||
|
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
|
||||||
|
reply[count] = text[i];
|
||||||
|
|
||||||
|
reply[count++] = (n1 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n1 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[count++] = (n2 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n2 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3)
|
||||||
|
{
|
||||||
|
uint8_t reply[130U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_DEBUG4;
|
||||||
|
|
||||||
|
uint8_t count = 3U;
|
||||||
|
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
|
||||||
|
reply[count] = text[i];
|
||||||
|
|
||||||
|
reply[count++] = (n1 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n1 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[count++] = (n2 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n2 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[count++] = (n3 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n3 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3, int16_t n4)
|
||||||
|
{
|
||||||
|
uint8_t reply[130U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_DEBUG5;
|
||||||
|
|
||||||
|
uint8_t count = 3U;
|
||||||
|
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
|
||||||
|
reply[count] = text[i];
|
||||||
|
|
||||||
|
reply[count++] = (n1 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n1 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[count++] = (n2 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n2 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[count++] = (n3 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n3 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[count++] = (n4 >> 8) & 0xFF;
|
||||||
|
reply[count++] = (n4 >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeAssert(bool cond, const char* text, const char* file, long line)
|
||||||
|
{
|
||||||
|
if (cond)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint8_t reply[200U];
|
||||||
|
|
||||||
|
reply[0U] = MMDVM_FRAME_START;
|
||||||
|
reply[1U] = 0U;
|
||||||
|
reply[2U] = MMDVM_DEBUG2;
|
||||||
|
|
||||||
|
uint8_t count = 3U;
|
||||||
|
for (uint8_t i = 0U; text[i] != '\0'; i++, count++)
|
||||||
|
reply[count] = text[i];
|
||||||
|
|
||||||
|
reply[count++] = ' ';
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; file[i] != '\0'; i++, count++)
|
||||||
|
reply[count] = file[i];
|
||||||
|
|
||||||
|
reply[count++] = (line >> 8) & 0xFF;
|
||||||
|
reply[count++] = (line >> 0) & 0xFF;
|
||||||
|
|
||||||
|
reply[1U] = count;
|
||||||
|
|
||||||
|
writeInt(1U, reply, count, true);
|
||||||
|
}
|
||||||
|
|
||||||
77
SerialPort.h
Normal file
77
SerialPort.h
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(SERIALPORT_H)
|
||||||
|
#define SERIALPORT_H
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
|
||||||
|
class CSerialPort {
|
||||||
|
public:
|
||||||
|
CSerialPort();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void writeDStarHeader(const uint8_t* header, uint8_t length);
|
||||||
|
void writeDStarData(const uint8_t* data, uint8_t length);
|
||||||
|
void writeDStarLost();
|
||||||
|
void writeDStarEOT();
|
||||||
|
|
||||||
|
void writeDMRData(bool slot, const uint8_t* data, uint8_t length);
|
||||||
|
void writeDMRLost(bool slot);
|
||||||
|
|
||||||
|
void writeYSFData(const uint8_t* data, uint8_t length);
|
||||||
|
void writeYSFLost();
|
||||||
|
|
||||||
|
void writeP25Hdr(const uint8_t* data, uint8_t length);
|
||||||
|
void writeP25Ldu(const uint8_t* data, uint8_t length);
|
||||||
|
void writeP25Lost();
|
||||||
|
|
||||||
|
void writeDebug(const char* text);
|
||||||
|
void writeDebug(const char* text, int16_t n1);
|
||||||
|
void writeDebug(const char* text, int16_t n1, int16_t n2);
|
||||||
|
void writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3);
|
||||||
|
void writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3, int16_t n4);
|
||||||
|
|
||||||
|
void writeAssert(bool cond, const char* text, const char* file, long line);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t m_buffer[256U];
|
||||||
|
uint8_t m_ptr;
|
||||||
|
uint8_t m_len;
|
||||||
|
|
||||||
|
void sendACK();
|
||||||
|
void sendNAK(uint8_t err);
|
||||||
|
void getStatus();
|
||||||
|
void getVersion();
|
||||||
|
uint8_t setConfig(const uint8_t* data, uint8_t length);
|
||||||
|
uint8_t setMode(const uint8_t* data, uint8_t length);
|
||||||
|
void setMode(MMDVM_STATE modemState);
|
||||||
|
uint8_t setFreq(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
|
// Hardware versions
|
||||||
|
void beginInt(uint8_t n, int speed);
|
||||||
|
int availableInt(uint8_t n);
|
||||||
|
uint8_t readInt(uint8_t n);
|
||||||
|
void writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush = false);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
101
SerialRB.cpp
Normal file
101
SerialRB.cpp
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
Serial RB control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
|
CSerialRB::CSerialRB(uint16_t length) :
|
||||||
|
m_length(length),
|
||||||
|
m_buffer(NULL),
|
||||||
|
m_head(0U),
|
||||||
|
m_tail(0U),
|
||||||
|
m_full(false)
|
||||||
|
{
|
||||||
|
m_buffer = new uint8_t[length];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialRB::reset()
|
||||||
|
{
|
||||||
|
m_head = 0U;
|
||||||
|
m_tail = 0U;
|
||||||
|
m_full = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CSerialRB::getSpace() const
|
||||||
|
{
|
||||||
|
uint16_t n = 0U;
|
||||||
|
|
||||||
|
if (m_tail == m_head)
|
||||||
|
n = m_full ? 0U : m_length;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
n = m_length - m_head + m_tail;
|
||||||
|
else
|
||||||
|
n = m_tail - m_head;
|
||||||
|
|
||||||
|
if (n > m_length)
|
||||||
|
n = 0U;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CSerialRB::getData() const
|
||||||
|
{
|
||||||
|
if (m_tail == m_head)
|
||||||
|
return m_full ? m_length : 0U;
|
||||||
|
else if (m_tail < m_head)
|
||||||
|
return m_head - m_tail;
|
||||||
|
else
|
||||||
|
return m_length - m_tail + m_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSerialRB::put(uint8_t c)
|
||||||
|
{
|
||||||
|
if (m_full)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_buffer[m_head] = c;
|
||||||
|
|
||||||
|
m_head++;
|
||||||
|
if (m_head >= m_length)
|
||||||
|
m_head = 0U;
|
||||||
|
|
||||||
|
if (m_head == m_tail)
|
||||||
|
m_full = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSerialRB::peek() const
|
||||||
|
{
|
||||||
|
return m_buffer[m_tail];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSerialRB::get()
|
||||||
|
{
|
||||||
|
uint8_t value = m_buffer[m_tail];
|
||||||
|
|
||||||
|
m_full = false;
|
||||||
|
|
||||||
|
m_tail++;
|
||||||
|
if (m_tail >= m_length)
|
||||||
|
m_tail = 0U;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
58
SerialRB.h
Normal file
58
SerialRB.h
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
Serial fifo control - Copyright (C) KI6ZUM 2015
|
||||||
|
Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the
|
||||||
|
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||||
|
Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(SERIALRB_H)
|
||||||
|
#define SERIALRB_H
|
||||||
|
|
||||||
|
#if defined(STM32F10X_MD)
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#else
|
||||||
|
#include <Arduino.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const uint16_t SERIAL_RINGBUFFER_SIZE = 370U;
|
||||||
|
|
||||||
|
class CSerialRB {
|
||||||
|
public:
|
||||||
|
CSerialRB(uint16_t length = SERIAL_RINGBUFFER_SIZE);
|
||||||
|
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
|
uint16_t getData() const;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
bool put(uint8_t c);
|
||||||
|
|
||||||
|
uint8_t peek() const;
|
||||||
|
|
||||||
|
uint8_t get();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint16_t m_length;
|
||||||
|
volatile uint8_t* m_buffer;
|
||||||
|
volatile uint16_t m_head;
|
||||||
|
volatile uint16_t m_tail;
|
||||||
|
volatile bool m_full;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
513
SerialSTM.cpp
Normal file
513
SerialSTM.cpp
Normal file
|
|
@ -0,0 +1,513 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||||
|
* Copyright (C) 2016 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"
|
||||||
|
|
||||||
|
#if defined(STM32F10X_MD)
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "SerialPort.h"
|
||||||
|
|
||||||
|
#if defined(STM32_USB_HOST)
|
||||||
|
#include <usb_serial.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pin definitions:
|
||||||
|
|
||||||
|
- Host communication:
|
||||||
|
USART1 - TXD PA9 - RXD PA10
|
||||||
|
or
|
||||||
|
USB VCOM
|
||||||
|
|
||||||
|
- Serial repeater
|
||||||
|
USART2 - TXD PA2 - RXD PA3
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(STM32_USART1_HOST)
|
||||||
|
|
||||||
|
#define TX_SERIAL_FIFO_SIZE 256U
|
||||||
|
#define RX_SERIAL_FIFO_SIZE 256U
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
void USART1_IRQHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************* USART1 ***************** */
|
||||||
|
|
||||||
|
volatile uint32_t intcount1;
|
||||||
|
volatile uint8_t TXSerialfifo1[TX_SERIAL_FIFO_SIZE];
|
||||||
|
volatile uint8_t RXSerialfifo1[RX_SERIAL_FIFO_SIZE];
|
||||||
|
volatile uint16_t TXSerialfifohead1, TXSerialfifotail1;
|
||||||
|
volatile uint16_t RXSerialfifohead1, RXSerialfifotail1;
|
||||||
|
|
||||||
|
// Init queues
|
||||||
|
void TXSerialfifoinit1()
|
||||||
|
{
|
||||||
|
TXSerialfifohead1 = 0U;
|
||||||
|
TXSerialfifotail1 = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RXSerialfifoinit1()
|
||||||
|
{
|
||||||
|
RXSerialfifohead1 = 0U;
|
||||||
|
RXSerialfifotail1 = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
// How full is queue
|
||||||
|
// TODO decide if how full or how empty is preferred info to return
|
||||||
|
uint16_t TXSerialfifolevel1()
|
||||||
|
{
|
||||||
|
uint32_t tail = TXSerialfifotail1;
|
||||||
|
uint32_t head = TXSerialfifohead1;
|
||||||
|
|
||||||
|
if (tail > head)
|
||||||
|
return TX_SERIAL_FIFO_SIZE + head - tail;
|
||||||
|
else
|
||||||
|
return head - tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t RXSerialfifolevel1()
|
||||||
|
{
|
||||||
|
uint32_t tail = RXSerialfifotail1;
|
||||||
|
uint32_t head = RXSerialfifohead1;
|
||||||
|
|
||||||
|
if (tail > head)
|
||||||
|
return RX_SERIAL_FIFO_SIZE + head - tail;
|
||||||
|
else
|
||||||
|
return head - tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flushes the transmit shift register
|
||||||
|
// warning: this call is blocking
|
||||||
|
void TXSerialFlush1()
|
||||||
|
{
|
||||||
|
// wait until the TXE shows the shift register is empty
|
||||||
|
while (USART_GetITStatus(USART1, USART_FLAG_TXE))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TXSerialfifoput1(uint8_t next)
|
||||||
|
{
|
||||||
|
if (TXSerialfifolevel1() < TX_SERIAL_FIFO_SIZE) {
|
||||||
|
TXSerialfifo1[TXSerialfifohead1] = next;
|
||||||
|
|
||||||
|
TXSerialfifohead1++;
|
||||||
|
if (TXSerialfifohead1 >= TX_SERIAL_FIFO_SIZE)
|
||||||
|
TXSerialfifohead1 = 0U;
|
||||||
|
|
||||||
|
// make sure transmit interrupts are enabled as long as there is data to send
|
||||||
|
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
|
||||||
|
return 1U;
|
||||||
|
} else {
|
||||||
|
return 0U; // signal an overflow occurred by returning a zero count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART1_IRQHandler()
|
||||||
|
{
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
if (USART_GetITStatus(USART1, USART_IT_RXNE)) {
|
||||||
|
c = (uint8_t) USART_ReceiveData(USART1);
|
||||||
|
|
||||||
|
if (RXSerialfifolevel1() < RX_SERIAL_FIFO_SIZE) {
|
||||||
|
RXSerialfifo1[RXSerialfifohead1] = c;
|
||||||
|
|
||||||
|
RXSerialfifohead1++;
|
||||||
|
if (RXSerialfifohead1 >= RX_SERIAL_FIFO_SIZE)
|
||||||
|
RXSerialfifohead1 = 0U;
|
||||||
|
} else {
|
||||||
|
// TODO - do something if rx fifo is full?
|
||||||
|
}
|
||||||
|
|
||||||
|
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
|
||||||
|
intcount1++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (USART_GetITStatus(USART1, USART_IT_TXE)) {
|
||||||
|
c = 0U;
|
||||||
|
|
||||||
|
if (TXSerialfifohead1 != TXSerialfifotail1) { // if the fifo is not empty
|
||||||
|
c = TXSerialfifo1[TXSerialfifotail1];
|
||||||
|
|
||||||
|
TXSerialfifotail1++;
|
||||||
|
if (TXSerialfifotail1 >= TX_SERIAL_FIFO_SIZE)
|
||||||
|
TXSerialfifotail1 = 0U;
|
||||||
|
|
||||||
|
USART_SendData(USART1, c);
|
||||||
|
} else { // if there's no more data to transmit then turn off TX interrupts
|
||||||
|
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
USART_ClearITPendingBit(USART1, USART_IT_TXE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitUSART1(int speed)
|
||||||
|
{
|
||||||
|
// USART1 - TXD PA9 - RXD PA10
|
||||||
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||||||
|
USART_InitTypeDef USART_InitStructure;
|
||||||
|
NVIC_InitTypeDef NVIC_InitStructure;
|
||||||
|
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
|
||||||
|
|
||||||
|
// USART IRQ init
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
|
||||||
|
NVIC_Init(&NVIC_InitStructure);
|
||||||
|
|
||||||
|
// Configure USART as alternate function
|
||||||
|
GPIO_StructInit(&GPIO_InitStructure);
|
||||||
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // Tx
|
||||||
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // Rx
|
||||||
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
// Configure USART baud rate
|
||||||
|
USART_StructInit(&USART_InitStructure);
|
||||||
|
USART_InitStructure.USART_BaudRate = speed;
|
||||||
|
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||||
|
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||||
|
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||||
|
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||||
|
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||||
|
USART_Init(USART1, &USART_InitStructure);
|
||||||
|
|
||||||
|
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
|
||||||
|
|
||||||
|
USART_Cmd(USART1, ENABLE);
|
||||||
|
|
||||||
|
// initialize the fifos
|
||||||
|
TXSerialfifoinit1();
|
||||||
|
RXSerialfifoinit1();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t AvailUSART1(void)
|
||||||
|
{
|
||||||
|
if (RXSerialfifolevel1() > 0U)
|
||||||
|
return 1U;
|
||||||
|
else
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadUSART1(void)
|
||||||
|
{
|
||||||
|
uint8_t data_c = RXSerialfifo1[RXSerialfifotail1];
|
||||||
|
|
||||||
|
RXSerialfifotail1++;
|
||||||
|
if (RXSerialfifotail1 >= RX_SERIAL_FIFO_SIZE)
|
||||||
|
RXSerialfifotail1 = 0U;
|
||||||
|
|
||||||
|
return data_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteUSART1(const uint8_t* data, uint16_t length)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0U; i < length; i++)
|
||||||
|
TXSerialfifoput1(data[i]);
|
||||||
|
|
||||||
|
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(SERIAL_REPEATER)
|
||||||
|
/* ************* USART2 ***************** */
|
||||||
|
|
||||||
|
volatile uint32_t intcount2;
|
||||||
|
volatile uint8_t TXSerialfifo2[TX_SERIAL_FIFO_SIZE];
|
||||||
|
volatile uint8_t RXSerialfifo2[RX_SERIAL_FIFO_SIZE];
|
||||||
|
volatile uint16_t TXSerialfifohead2, TXSerialfifotail2;
|
||||||
|
volatile uint16_t RXSerialfifohead2, RXSerialfifotail2;
|
||||||
|
|
||||||
|
// Init queues
|
||||||
|
void TXSerialfifoinit2()
|
||||||
|
{
|
||||||
|
TXSerialfifohead2 = 0U;
|
||||||
|
TXSerialfifotail2 = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RXSerialfifoinit2()
|
||||||
|
{
|
||||||
|
RXSerialfifohead2 = 0U;
|
||||||
|
RXSerialfifotail2 = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
// How full is queue
|
||||||
|
// TODO decide if how full or how empty is preferred info to return
|
||||||
|
uint16_t TXSerialfifolevel2()
|
||||||
|
{
|
||||||
|
uint32_t tail = TXSerialfifotail2;
|
||||||
|
uint32_t head = TXSerialfifohead2;
|
||||||
|
|
||||||
|
if (tail > head)
|
||||||
|
return TX_SERIAL_FIFO_SIZE + head - tail;
|
||||||
|
else
|
||||||
|
return head - tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t RXSerialfifolevel2()
|
||||||
|
{
|
||||||
|
uint32_t tail = RXSerialfifotail2;
|
||||||
|
uint32_t head = RXSerialfifohead2;
|
||||||
|
|
||||||
|
if (tail > head)
|
||||||
|
return RX_SERIAL_FIFO_SIZE + head - tail;
|
||||||
|
else
|
||||||
|
return head - tail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flushes the transmit shift register
|
||||||
|
// warning: this call is blocking
|
||||||
|
void TXSerialFlush2()
|
||||||
|
{
|
||||||
|
// wait until the TXE shows the shift register is empty
|
||||||
|
while (USART_GetITStatus(USART2, USART_FLAG_TXE))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TXSerialfifoput2(uint8_t next)
|
||||||
|
{
|
||||||
|
if (TXSerialfifolevel2() < TX_SERIAL_FIFO_SIZE) {
|
||||||
|
TXSerialfifo2[TXSerialfifohead2] = next;
|
||||||
|
|
||||||
|
TXSerialfifohead2++;
|
||||||
|
if (TXSerialfifohead2 >= TX_SERIAL_FIFO_SIZE)
|
||||||
|
TXSerialfifohead2 = 0U;
|
||||||
|
|
||||||
|
// make sure transmit interrupts are enabled as long as there is data to send
|
||||||
|
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
|
||||||
|
return 1U;
|
||||||
|
} else {
|
||||||
|
return 0U; // signal an overflow occurred by returning a zero count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void USART2_IRQHandler()
|
||||||
|
{
|
||||||
|
uint8_t c;
|
||||||
|
|
||||||
|
if (USART_GetITStatus(USART2, USART_IT_RXNE)) {
|
||||||
|
c = (uint8_t) USART_ReceiveData(USART2);
|
||||||
|
|
||||||
|
if (RXSerialfifolevel2() < RX_SERIAL_FIFO_SIZE) {
|
||||||
|
RXSerialfifo2[RXSerialfifohead2] = c;
|
||||||
|
|
||||||
|
RXSerialfifohead2++;
|
||||||
|
if (RXSerialfifohead2 >= RX_SERIAL_FIFO_SIZE)
|
||||||
|
RXSerialfifohead2 = 0U;
|
||||||
|
} else {
|
||||||
|
// TODO - do something if rx fifo is full?
|
||||||
|
}
|
||||||
|
|
||||||
|
USART_ClearITPendingBit(USART2, USART_IT_RXNE);
|
||||||
|
intcount2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (USART_GetITStatus(USART2, USART_IT_TXE)) {
|
||||||
|
c = 0U;
|
||||||
|
|
||||||
|
if (TXSerialfifohead2 != TXSerialfifotail2) { // if the fifo is not empty
|
||||||
|
c = TXSerialfifo2[TXSerialfifotail2];
|
||||||
|
|
||||||
|
TXSerialfifotail2++;
|
||||||
|
if (TXSerialfifotail2 >= TX_SERIAL_FIFO_SIZE)
|
||||||
|
TXSerialfifotail2 = 0U;
|
||||||
|
|
||||||
|
USART_SendData(USART2, c);
|
||||||
|
} else { // if there's no more data to transmit then turn off TX interrupts
|
||||||
|
USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
USART_ClearITPendingBit(USART2, USART_IT_TXE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitUSART2(int speed)
|
||||||
|
{
|
||||||
|
|
||||||
|
// USART2 - TXD PA2 - RXD PA3
|
||||||
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||||||
|
USART_InitTypeDef USART_InitStructure;
|
||||||
|
NVIC_InitTypeDef NVIC_InitStructure;
|
||||||
|
|
||||||
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
|
||||||
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
|
||||||
|
|
||||||
|
// USART IRQ init
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
|
||||||
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
|
||||||
|
NVIC_Init(&NVIC_InitStructure);
|
||||||
|
|
||||||
|
// Configure USART as alternate function
|
||||||
|
GPIO_StructInit(&GPIO_InitStructure);
|
||||||
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
||||||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; // Tx
|
||||||
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||||
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
||||||
|
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; // Rx
|
||||||
|
GPIO_Init(GPIOA, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
// Configure USART baud rate
|
||||||
|
USART_StructInit(&USART_InitStructure);
|
||||||
|
USART_InitStructure.USART_BaudRate = speed;
|
||||||
|
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
|
||||||
|
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
||||||
|
USART_InitStructure.USART_Parity = USART_Parity_No;
|
||||||
|
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
||||||
|
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
|
||||||
|
USART_Init(USART2, &USART_InitStructure);
|
||||||
|
|
||||||
|
USART_Cmd(USART2, ENABLE);
|
||||||
|
|
||||||
|
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
|
||||||
|
|
||||||
|
// initialize the fifos
|
||||||
|
TXSerialfifoinit2();
|
||||||
|
RXSerialfifoinit2();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t AvailUSART2(void)
|
||||||
|
{
|
||||||
|
if (RXSerialfifolevel2() > 0U)
|
||||||
|
return 1U;
|
||||||
|
else
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ReadUSART2(void)
|
||||||
|
{
|
||||||
|
uint8_t data_c = RXSerialfifo2[RXSerialfifotail2];
|
||||||
|
|
||||||
|
RXSerialfifotail2++;
|
||||||
|
if (RXSerialfifotail2 >= RX_SERIAL_FIFO_SIZE)
|
||||||
|
RXSerialfifotail2 = 0U;
|
||||||
|
|
||||||
|
return data_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteUSART2(const uint8_t* data, uint16_t length)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0U; i < length; i++)
|
||||||
|
TXSerialfifoput2(data[i]);
|
||||||
|
|
||||||
|
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void CSerialPort::beginInt(uint8_t n, int speed)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
#if defined(STM32_USART1_HOST)
|
||||||
|
InitUSART1(speed);
|
||||||
|
#elif defined(STM32_USB_HOST)
|
||||||
|
usbserial.begin();
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
#if defined(SERIAL_REPEATER)
|
||||||
|
case 3U:
|
||||||
|
InitUSART2(speed);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSerialPort::availableInt(uint8_t n)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
#if defined(STM32_USART1_HOST)
|
||||||
|
return AvailUSART1();
|
||||||
|
#elif defined(STM32_USB_HOST)
|
||||||
|
return usbserial.available();
|
||||||
|
#endif
|
||||||
|
#if defined(SERIAL_REPEATER)
|
||||||
|
case 3U:
|
||||||
|
return AvailUSART2();
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CSerialPort::readInt(uint8_t n)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
#if defined(STM32_USART1_HOST)
|
||||||
|
return ReadUSART1();
|
||||||
|
#elif defined(STM32_USB_HOST)
|
||||||
|
return usbserial.read();
|
||||||
|
#endif
|
||||||
|
#if defined(SERIAL_REPEATER)
|
||||||
|
case 3U:
|
||||||
|
return ReadUSART2();
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSerialPort::writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
case 1U:
|
||||||
|
#if defined(STM32_USART1_HOST)
|
||||||
|
WriteUSART1(data, length);
|
||||||
|
if (flush)
|
||||||
|
TXSerialFlush1();
|
||||||
|
#elif defined(STM32_USB_HOST)
|
||||||
|
usbserial.write(data, length);
|
||||||
|
if (flush)
|
||||||
|
usbserial.flush();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(SERIAL_REPEATER)
|
||||||
|
case 3U:
|
||||||
|
WriteUSART2(data, length);
|
||||||
|
if (flush)
|
||||||
|
TXSerialFlush2();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
59
Utils.cpp
Normal file
59
Utils.cpp
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
const uint8_t BITS_TABLE[] = {
|
||||||
|
# define B2(n) n, n+1, n+1, n+2
|
||||||
|
# define B4(n) B2(n), B2(n+1), B2(n+1), B2(n+2)
|
||||||
|
# define B6(n) B4(n), B4(n+1), B4(n+1), B4(n+2)
|
||||||
|
B6(0), B6(1), B6(1), B6(2)
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t countBits8(uint8_t bits)
|
||||||
|
{
|
||||||
|
return BITS_TABLE[bits];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t countBits32(uint32_t bits)
|
||||||
|
{
|
||||||
|
uint8_t* p = (uint8_t*)&bits;
|
||||||
|
uint8_t n = 0U;
|
||||||
|
n += BITS_TABLE[p[0U]];
|
||||||
|
n += BITS_TABLE[p[1U]];
|
||||||
|
n += BITS_TABLE[p[2U]];
|
||||||
|
n += BITS_TABLE[p[3U]];
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t countBits64(uint64_t bits)
|
||||||
|
{
|
||||||
|
uint8_t* p = (uint8_t*)&bits;
|
||||||
|
uint8_t n = 0U;
|
||||||
|
n += BITS_TABLE[p[0U]];
|
||||||
|
n += BITS_TABLE[p[1U]];
|
||||||
|
n += BITS_TABLE[p[2U]];
|
||||||
|
n += BITS_TABLE[p[3U]];
|
||||||
|
n += BITS_TABLE[p[4U]];
|
||||||
|
n += BITS_TABLE[p[5U]];
|
||||||
|
n += BITS_TABLE[p[6U]];
|
||||||
|
n += BITS_TABLE[p[7U]];
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
36
Utils.h
Normal file
36
Utils.h
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(UTILS_H)
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
#if defined(STM32F10X_MD)
|
||||||
|
#include "stm32f10x.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#else
|
||||||
|
#include <Arduino.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t countBits8(uint8_t bits);
|
||||||
|
|
||||||
|
uint8_t countBits32(uint32_t bits);
|
||||||
|
|
||||||
|
uint8_t countBits64(uint64_t bits);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
46
YSFDefines.h
Normal file
46
YSFDefines.h
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(YSFDEFINES_H)
|
||||||
|
#define YSFDEFINES_H
|
||||||
|
|
||||||
|
const unsigned int YSF_FRAME_LENGTH_BYTES = 120U;
|
||||||
|
const unsigned int YSF_FRAME_LENGTH_BITS = YSF_FRAME_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int YSF_FRAME_LENGTH_SYMBOLS = YSF_FRAME_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int YSF_SYNC_LENGTH_BYTES = 5U;
|
||||||
|
const unsigned int YSF_SYNC_LENGTH_BITS = YSF_SYNC_LENGTH_BYTES * 8U;
|
||||||
|
const unsigned int YSF_SYNC_LENGTH_SYMBOLS = YSF_SYNC_LENGTH_BYTES * 4U;
|
||||||
|
|
||||||
|
const unsigned int YSF_FICH_LENGTH_BITS = 200U;
|
||||||
|
const unsigned int YSF_FICH_LENGTH_SYMBOLS = 100U;
|
||||||
|
|
||||||
|
const uint8_t YSF_SYNC_BYTES[] = {0xD4U, 0x71U, 0xC9U, 0x63U, 0x4DU};
|
||||||
|
const uint8_t YSF_SYNC_BYTES_LENGTH = 5U;
|
||||||
|
|
||||||
|
const uint64_t YSF_SYNC_BITS = 0x000000D471C9634DU;
|
||||||
|
const uint64_t YSF_SYNC_BITS_MASK = 0x000000FFFFFFFFFFU;
|
||||||
|
|
||||||
|
// D 4 7 1 C 9 6 3 4 D
|
||||||
|
// 11 01 01 00 01 11 00 01 11 00 10 01 01 10 00 11 01 00 11 01
|
||||||
|
// -3 +3 +3 +1 +3 -3 +1 +3 -3 +1 -1 +3 +3 -1 +3 -3 +3 +1 -3 +3
|
||||||
|
const uint32_t YSF_SYNC_SYMBOLS = 0x0007B5ADU;
|
||||||
|
const uint32_t YSF_SYNC_SYMBOLS_MASK = 0x000FFFFFU;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
127
YSFRX.cpp
Normal file
127
YSFRX.cpp
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2017 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "YSFRX.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
const uint8_t SYNC_BIT_START_ERRS = 2U;
|
||||||
|
const uint8_t SYNC_BIT_RUN_ERRS = 4U;
|
||||||
|
|
||||||
|
const unsigned int MAX_SYNC_FRAMES = 4U + 1U;
|
||||||
|
|
||||||
|
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])
|
||||||
|
|
||||||
|
CYSFRX::CYSFRX() :
|
||||||
|
m_prev(false),
|
||||||
|
m_state(YSFRXS_NONE),
|
||||||
|
m_bitBuffer(0x00U),
|
||||||
|
m_outBuffer(),
|
||||||
|
m_buffer(NULL),
|
||||||
|
m_bufferPtr(0U),
|
||||||
|
m_lostCount(0U)
|
||||||
|
{
|
||||||
|
m_buffer = m_outBuffer + 1U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CYSFRX::reset()
|
||||||
|
{
|
||||||
|
m_prev = false;
|
||||||
|
m_state = YSFRXS_NONE;
|
||||||
|
m_bitBuffer = 0x00U;
|
||||||
|
m_bufferPtr = 0U;
|
||||||
|
m_lostCount = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CYSFRX::databit(bool bit)
|
||||||
|
{
|
||||||
|
if (m_state == YSFRXS_NONE)
|
||||||
|
processNone(bit);
|
||||||
|
else
|
||||||
|
processData(bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CYSFRX::processNone(bool bit)
|
||||||
|
{
|
||||||
|
m_bitBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_bitBuffer |= 0x01U;
|
||||||
|
|
||||||
|
// Fuzzy matching of the data sync bit sequence
|
||||||
|
if (countBits64((m_bitBuffer & YSF_SYNC_BITS_MASK) ^ YSF_SYNC_BITS) <= SYNC_BIT_START_ERRS) {
|
||||||
|
DEBUG1("YSFRX: sync found in None");
|
||||||
|
for (uint8_t i = 0U; i < YSF_SYNC_LENGTH_BYTES; i++)
|
||||||
|
m_buffer[i] = YSF_SYNC_BYTES[i];
|
||||||
|
|
||||||
|
m_lostCount = MAX_SYNC_FRAMES;
|
||||||
|
m_bufferPtr = YSF_SYNC_LENGTH_BITS;
|
||||||
|
m_state = YSFRXS_DATA;
|
||||||
|
|
||||||
|
io.setDecode(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CYSFRX::processData(bool bit)
|
||||||
|
{
|
||||||
|
m_bitBuffer <<= 1;
|
||||||
|
if (bit)
|
||||||
|
m_bitBuffer |= 0x01U;
|
||||||
|
|
||||||
|
WRITE_BIT1(m_buffer, m_bufferPtr, bit);
|
||||||
|
m_bufferPtr++;
|
||||||
|
|
||||||
|
// Only search for a sync in the right place +-2 symbols
|
||||||
|
if (m_bufferPtr >= (YSF_SYNC_LENGTH_BITS - 2U) && m_bufferPtr <= (YSF_SYNC_LENGTH_BITS + 2U)) {
|
||||||
|
// Fuzzy matching of the data sync bit sequence
|
||||||
|
if (countBits64((m_bitBuffer & YSF_SYNC_BITS_MASK) ^ YSF_SYNC_BITS) <= SYNC_BIT_RUN_ERRS) {
|
||||||
|
DEBUG2("YSFRX: found sync in Data, pos", m_bufferPtr - YSF_SYNC_LENGTH_BITS);
|
||||||
|
m_lostCount = MAX_SYNC_FRAMES;
|
||||||
|
m_bufferPtr = YSF_SYNC_LENGTH_BITS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a data frame to the host if the required number of bits have been received
|
||||||
|
if (m_bufferPtr == YSF_FRAME_LENGTH_BITS) {
|
||||||
|
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
||||||
|
m_lostCount--;
|
||||||
|
if (m_lostCount == 0U) {
|
||||||
|
DEBUG1("YSFRX: sync timed out, lost lock");
|
||||||
|
io.setDecode(false);
|
||||||
|
|
||||||
|
serial.writeYSFLost();
|
||||||
|
|
||||||
|
m_state = YSFRXS_NONE;
|
||||||
|
} else {
|
||||||
|
m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||||
|
|
||||||
|
serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U);
|
||||||
|
|
||||||
|
// Start the next frame
|
||||||
|
::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U);
|
||||||
|
m_bufferPtr = 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
51
YSFRX.h
Normal file
51
YSFRX.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017 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(YSFRX_H)
|
||||||
|
#define YSFRX_H
|
||||||
|
|
||||||
|
#include "YSFDefines.h"
|
||||||
|
|
||||||
|
enum YSFRX_STATE {
|
||||||
|
YSFRXS_NONE,
|
||||||
|
YSFRXS_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
class CYSFRX {
|
||||||
|
public:
|
||||||
|
CYSFRX();
|
||||||
|
|
||||||
|
void databit(bool bit);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_prev;
|
||||||
|
YSFRX_STATE m_state;
|
||||||
|
uint64_t m_bitBuffer;
|
||||||
|
uint8_t m_outBuffer[YSF_FRAME_LENGTH_BYTES + 3U];
|
||||||
|
uint8_t* m_buffer;
|
||||||
|
uint16_t m_bufferPtr;
|
||||||
|
uint16_t m_lostCount;
|
||||||
|
|
||||||
|
void processNone(bool bit);
|
||||||
|
void processData(bool bit);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
121
YSFTX.cpp
Normal file
121
YSFTX.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #define WANT_DEBUG
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "YSFTX.h"
|
||||||
|
|
||||||
|
#include "YSFDefines.h"
|
||||||
|
|
||||||
|
const uint8_t YSF_START_SYNC = 0x77U;
|
||||||
|
const uint8_t YSF_END_SYNC = 0xFFU;
|
||||||
|
|
||||||
|
CYSFTX::CYSFTX() :
|
||||||
|
m_buffer(1500U),
|
||||||
|
m_poBuffer(),
|
||||||
|
m_poLen(0U),
|
||||||
|
m_poPtr(0U),
|
||||||
|
m_txDelay(240U), // 200ms
|
||||||
|
m_count(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CYSFTX::process()
|
||||||
|
{
|
||||||
|
if (m_buffer.getData() == 0U && m_poLen == 0U)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_poLen == 0U) {
|
||||||
|
if (!m_tx) {
|
||||||
|
m_delay = true;
|
||||||
|
m_count = 0U;
|
||||||
|
m_poLen = m_txDelay;
|
||||||
|
} else {
|
||||||
|
m_delay = false;
|
||||||
|
for (uint8_t i = 0U; i < YSF_FRAME_LENGTH_BYTES; i++)
|
||||||
|
m_poBuffer[m_poLen++] = m_buffer.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_poPtr = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_poLen > 0U) {
|
||||||
|
uint16_t space = io.getSpace();
|
||||||
|
|
||||||
|
while (space > 8U) {
|
||||||
|
if (m_delay) {
|
||||||
|
m_poPtr++;
|
||||||
|
writeByte(YSF_START_SYNC);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
writeByte(m_poBuffer[m_poPtr++]);
|
||||||
|
|
||||||
|
space -= 8U;
|
||||||
|
|
||||||
|
if (m_poPtr >= m_poLen) {
|
||||||
|
m_poPtr = 0U;
|
||||||
|
m_poLen = 0U;
|
||||||
|
m_delay = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CYSFTX::writeData(const uint8_t* data, uint8_t length)
|
||||||
|
{
|
||||||
|
if (length != (YSF_FRAME_LENGTH_BYTES + 1U))
|
||||||
|
return 4U;
|
||||||
|
|
||||||
|
uint16_t space = m_buffer.getSpace();
|
||||||
|
if (space < YSF_FRAME_LENGTH_BYTES)
|
||||||
|
return 5U;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < YSF_FRAME_LENGTH_BYTES; i++)
|
||||||
|
m_buffer.put(data[i + 1U]);
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CYSFTX::writeByte(uint8_t c)
|
||||||
|
{
|
||||||
|
uint8_t bit;
|
||||||
|
uint8_t mask = 0x80U;
|
||||||
|
|
||||||
|
for (uint8_t i = 0U; i < 8U; i++, c <<= 1) {
|
||||||
|
if ((c & mask) == mask)
|
||||||
|
bit = 1U;
|
||||||
|
else
|
||||||
|
bit = 0U;
|
||||||
|
|
||||||
|
io.write(&bit, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CYSFTX::setTXDelay(uint8_t delay)
|
||||||
|
{
|
||||||
|
m_txDelay = 600U + uint16_t(delay) * 12U; // 500ms + tx delay
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t CYSFTX::getSpace() const
|
||||||
|
{
|
||||||
|
return m_buffer.getSpace() / YSF_FRAME_LENGTH_BYTES;
|
||||||
|
}
|
||||||
|
|
||||||
49
YSFTX.h
Normal file
49
YSFTX.h
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015,2016,2017 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(YSFTX_H)
|
||||||
|
#define YSFTX_H
|
||||||
|
|
||||||
|
#include "SerialRB.h"
|
||||||
|
|
||||||
|
class CYSFTX {
|
||||||
|
public:
|
||||||
|
CYSFTX();
|
||||||
|
|
||||||
|
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||||
|
|
||||||
|
void process();
|
||||||
|
|
||||||
|
void setTXDelay(uint8_t delay);
|
||||||
|
|
||||||
|
uint16_t getSpace() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CSerialRB m_buffer;
|
||||||
|
uint8_t m_poBuffer[130U];
|
||||||
|
uint16_t m_poLen;
|
||||||
|
uint16_t m_poPtr;
|
||||||
|
uint16_t m_txDelay;
|
||||||
|
uint32_t m_count;
|
||||||
|
bool m_delay;
|
||||||
|
|
||||||
|
void writeByte(uint8_t c);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
137
stm32f10x_link.ld
Normal file
137
stm32f10x_link.ld
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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 = 64K /* FLASH */
|
||||||
|
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K /* Main RAM */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stack start address (end of 20K 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 ( * )
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue