mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-10-16 08:44:11 +02:00
Reorganise the source code.
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#if defined(MODE_AX25)
|
||||
|
||||
#include "Globals.h"
|
||||
#include "AX25TX.h"
|
||||
|
||||
#include "AX25Defines.h"
|
||||
#include "AX25Frame.h"
|
||||
|
||||
|
||||
const uint8_t START_FLAG[] = { AX25_FRAME_START };
|
||||
const uint8_t END_FLAG[] = { AX25_FRAME_END };
|
||||
|
||||
const uint8_t BIT_MASK_TABLE1[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE1[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE1[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7])
|
||||
|
||||
const uint8_t BIT_MASK_TABLE2[] = { 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U };
|
||||
|
||||
#define WRITE_BIT2(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE2[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE2[(i)&7])
|
||||
#define READ_BIT2(p,i) (p[(i)>>3] & BIT_MASK_TABLE2[(i)&7])
|
||||
|
||||
const uint16_t AUDIO_TABLE_LEN = 120U;
|
||||
|
||||
const q15_t AUDIO_TABLE_DATA[] = {
|
||||
0, 214, 428, 641, 851, 1060, 1265, 1468, 1666, 1859, 2048, 2230, 2407, 2577, 2740, 2896, 3043, 3182, 3313, 3434, 3546, 3649,
|
||||
3741, 3823, 3895, 3955, 4006, 4045, 4073, 4089, 4095, 4089, 4073, 4045, 4006, 3955, 3895, 3823, 3741, 3649, 3546, 3434, 3313,
|
||||
3182, 3043, 2896, 2740, 2577, 2407, 2230, 2048, 1859, 1666, 1468, 1265, 1060, 851, 641, 428, 214, 0, -214, -428, -641, -851,
|
||||
-1060, -1265, -1468, -1666, -1859, -2047, -2230, -2407, -2577, -2740, -2896, -3043, -3182, -3313, -3434, -3546, -3649, -3741,
|
||||
-3823, -3895, -3955, -4006, -4045, -4073, -4089, -4095, -4089, -4073, -4045, -4006, -3955, -3895, -3823, -3741, -3649, -3546,
|
||||
-3434, -3313, -3182, -3043, -2896, -2740, -2577, -2407, -2230, -2047, -1859, -1666, -1468, -1265, -1060, -851, -641, -428, -214
|
||||
};
|
||||
|
||||
CAX25TX::CAX25TX() :
|
||||
m_poBuffer(),
|
||||
m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_txDelay(360U),
|
||||
m_tablePtr(0U),
|
||||
m_nrzi(false)
|
||||
{
|
||||
}
|
||||
|
||||
void CAX25TX::process()
|
||||
{
|
||||
if (m_poLen == 0U)
|
||||
return;
|
||||
|
||||
if (!m_duplex) {
|
||||
if (m_poPtr == 0U) {
|
||||
bool tx = ax25RX.canTX();
|
||||
if (!tx)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t space = io.getSpace();
|
||||
|
||||
while (space > AX25_RADIO_SYMBOL_LENGTH) {
|
||||
bool b = READ_BIT1(m_poBuffer, m_poPtr) != 0U;
|
||||
m_poPtr++;
|
||||
|
||||
writeBit(b);
|
||||
|
||||
space -= AX25_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
if (m_poPtr >= m_poLen) {
|
||||
m_poPtr = 0U;
|
||||
m_poLen = 0U;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CAX25TX::writeData(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
CAX25Frame frame(data, length);
|
||||
frame.addCRC();
|
||||
|
||||
m_poLen = 0U;
|
||||
m_poPtr = 0U;
|
||||
m_nrzi = false;
|
||||
m_tablePtr = 0U;
|
||||
|
||||
// Add TX delay
|
||||
for (uint16_t i = 0U; i < m_txDelay; i++, m_poLen++) {
|
||||
bool preamble = NRZI(false);
|
||||
WRITE_BIT1(m_poBuffer, m_poLen, preamble);
|
||||
}
|
||||
|
||||
// Add the Start Flag
|
||||
for (uint16_t i = 0U; i < 8U; i++, m_poLen++) {
|
||||
bool b1 = READ_BIT1(START_FLAG, i) != 0U;
|
||||
bool b2 = NRZI(b1);
|
||||
WRITE_BIT1(m_poBuffer, m_poLen, b2);
|
||||
}
|
||||
|
||||
uint8_t ones = 0U;
|
||||
for (uint16_t i = 0U; i < (frame.m_length * 8U); i++) {
|
||||
bool b1 = READ_BIT2(frame.m_data, i) != 0U;
|
||||
bool b2 = NRZI(b1);
|
||||
WRITE_BIT1(m_poBuffer, m_poLen, b2);
|
||||
m_poLen++;
|
||||
|
||||
if (b1) {
|
||||
ones++;
|
||||
if (ones == AX25_MAX_ONES) {
|
||||
// Bit stuffing
|
||||
bool b = NRZI(false);
|
||||
WRITE_BIT1(m_poBuffer, m_poLen, b);
|
||||
m_poLen++;
|
||||
ones = 0U;
|
||||
}
|
||||
} else {
|
||||
ones = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the End Flag
|
||||
for (uint16_t i = 0U; i < 8U; i++, m_poLen++) {
|
||||
bool b1 = READ_BIT1(END_FLAG, i) != 0U;
|
||||
bool b2 = NRZI(b1);
|
||||
WRITE_BIT1(m_poBuffer, m_poLen, b2);
|
||||
}
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
void CAX25TX::writeBit(bool b)
|
||||
{
|
||||
q15_t buffer[AX25_RADIO_SYMBOL_LENGTH];
|
||||
for (uint8_t i = 0U; i < AX25_RADIO_SYMBOL_LENGTH; i++) {
|
||||
q15_t value = AUDIO_TABLE_DATA[m_tablePtr];
|
||||
|
||||
if (b) {
|
||||
// De-emphasise the lower frequency by 6dB
|
||||
value >>= 2;
|
||||
m_tablePtr += 6U;
|
||||
} else {
|
||||
m_tablePtr += 11U;
|
||||
}
|
||||
|
||||
buffer[i] = value >> 1;
|
||||
|
||||
if (m_tablePtr >= AUDIO_TABLE_LEN)
|
||||
m_tablePtr -= AUDIO_TABLE_LEN;
|
||||
}
|
||||
|
||||
io.write(STATE_AX25, buffer, AX25_RADIO_SYMBOL_LENGTH);
|
||||
}
|
||||
|
||||
void CAX25TX::setTXDelay(uint8_t delay)
|
||||
{
|
||||
m_txDelay = delay * 12U;
|
||||
}
|
||||
|
||||
uint8_t CAX25TX::getSpace() const
|
||||
{
|
||||
return m_poLen == 0U ? 255U : 0U;
|
||||
}
|
||||
|
||||
bool CAX25TX::NRZI(bool b)
|
||||
{
|
||||
if (!b)
|
||||
m_nrzi = !m_nrzi;
|
||||
|
||||
return m_nrzi;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user