160 lines
3.8 KiB
C++
160 lines
3.8 KiB
C++
#include "hdlcAfskTx.h"
|
|
|
|
const byte sinusTable[SIN_TABLE_SIZE] PROGMEM = { //idx 0=0deg, 1=7.5deg, 2=15deg, 3=22.5deg, etc.
|
|
0x80, 0x90, 0xa0, 0xb0, 0xbf, 0xcd, 0xda, 0xe5, 0xee, 0xf5, 0xfb, 0xfe, // 0.. 82.5deg
|
|
0xff, 0xfe, 0xfb, 0xf5, 0xee, 0xe5, 0xda, 0xcd, 0xbf, 0xb0, 0xa0, 0x90, // 90..172.5deg
|
|
0x80, 0x6f, 0x5f, 0x4f, 0x40, 0x32, 0x25, 0x1a, 0x11, 0x0a, 0x04, 0x01, // 180..262.5deg
|
|
0x00, 0x01, 0x04, 0x0a, 0x11, 0x1a, 0x25, 0x32, 0x40, 0x4f, 0x5f, 0x6f // 270..352.5deg
|
|
};
|
|
|
|
HdlcAfskTx::HdlcAfskTx(HdlcFrameBuffer* txBuffer) {
|
|
_txBuffer = txBuffer;
|
|
for (int idx=0; idx < AFSK_PIN_COUNT; idx++) {
|
|
pinMode(_pins[idx], OUTPUT);
|
|
}
|
|
}
|
|
|
|
byte HdlcAfskTx::encodeSample() {
|
|
if (_ready) { return ANALOG_ZERO; }
|
|
|
|
byte loopBackSample = ANALOG_ZERO;
|
|
if (loopbackTest) {
|
|
PORTD = (pgm_read_byte(&sinusTable[_n7_5degTest]) & AFSK_MASK) | (PORTD & NON_AFSK_MASK);
|
|
_n7_5degTest += MARK_SAMPLE_DEG_STEP;
|
|
if (_n7_5degTest >= SIN_TABLE_SIZE) {
|
|
_n7_5degTest -= SIN_TABLE_SIZE;
|
|
}
|
|
loopBackSample = pgm_read_byte(&sinusTable[_n7_5deg]);
|
|
}
|
|
else {
|
|
PORTD = (pgm_read_byte(&sinusTable[_n7_5deg]) & AFSK_MASK) | (PORTD & NON_AFSK_MASK);
|
|
}
|
|
|
|
if (_mark) {
|
|
_n7_5deg += MARK_SAMPLE_DEG_STEP;
|
|
}
|
|
else {
|
|
_n7_5deg += SPACE_SAMPLE_DEG_STEP;
|
|
}
|
|
if (_n7_5deg >= SIN_TABLE_SIZE) {
|
|
_n7_5deg -= SIN_TABLE_SIZE;
|
|
}
|
|
|
|
if (_runToZero) {
|
|
if (_n7_5deg < SPACE_SAMPLE_DEG_STEP) {
|
|
_n7_5deg = 0;
|
|
_runToZero = false;
|
|
_ready = true;
|
|
PORTD = ANALOG_ZERO;
|
|
loopBackSample = ANALOG_ZERO;
|
|
}
|
|
}
|
|
else {
|
|
_bitSampleCounter++;
|
|
if (_bitSampleCounter > MAX_BIT_SAMPLE_INDEX) {
|
|
_bitSampleCounter = 0;
|
|
if (getNextMark(&_mark)) {
|
|
_runToZero = true;
|
|
}
|
|
}
|
|
}
|
|
return loopBackSample;
|
|
}
|
|
|
|
void HdlcAfskTx::start() {
|
|
if (_ready) {
|
|
_mark = true;
|
|
_afskByte = HDLC_FLAG;
|
|
_afskBitMask = MASK_RESET_VALUE;
|
|
_afskBitPtr = 0;
|
|
_preampCountDown = _preambleCount;
|
|
_enableStuffBit = false;
|
|
_stuffBit = false;
|
|
_oneCounter = 0;
|
|
_ready = false;
|
|
}
|
|
}
|
|
|
|
boolean HdlcAfskTx::getReady() {
|
|
return _ready;
|
|
}
|
|
|
|
void HdlcAfskTx::setTxDelay(int val) {
|
|
_preambleCount = val * 12 / 80;
|
|
}
|
|
|
|
boolean HdlcAfskTx::getNextMark(boolean* current) {
|
|
if (_afskBitPtr == 0) {
|
|
boolean frameEnd=false;
|
|
switch (frameTxState) {
|
|
case TX_FRAME_PREAMBLE:
|
|
_afskByte = HDLC_FLAG;
|
|
_enableStuffBit = false;
|
|
_preampCountDown--;
|
|
if (_preampCountDown < 1) {
|
|
frameTxState = TX_FRAME_BEGIN;
|
|
}
|
|
break;
|
|
case TX_FRAME_BEGIN:
|
|
if (_txBuffer->more()) {
|
|
_afskByte = HDLC_FLAG;
|
|
_enableStuffBit = false;
|
|
frameTxState = TX_FRAME_DATA;
|
|
}
|
|
else {
|
|
frameTxState = TX_FRAME_PREAMBLE;
|
|
return true;
|
|
}
|
|
break;
|
|
case TX_FRAME_DATA:
|
|
if (_txBuffer->pop(&_afskByte, &frameEnd)) {
|
|
_enableStuffBit = true;
|
|
if (frameEnd) {
|
|
frameTxState = TX_FRAME_END;
|
|
}
|
|
}
|
|
else {
|
|
frameTxState = TX_FRAME_END;
|
|
}
|
|
break;
|
|
case TX_FRAME_END:
|
|
_afskByte = HDLC_FLAG;
|
|
_enableStuffBit = false;
|
|
frameTxState = TX_FRAME_BEGIN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
boolean nextBit;
|
|
if (_stuffBit) {
|
|
nextBit = false;
|
|
_stuffBit = false;
|
|
}
|
|
else {
|
|
nextBit = (_afskByte & _afskBitMask) != 0;
|
|
if (nextBit) {
|
|
_oneCounter++;
|
|
if (_oneCounter > MAX_ONES_WITHOUT_STUFFING) {
|
|
_oneCounter = 0;
|
|
_stuffBit = _enableStuffBit;
|
|
}
|
|
}
|
|
else {
|
|
_oneCounter = 0;
|
|
}
|
|
_afskBitPtr++;
|
|
_afskBitMask <<= 1;
|
|
if (_afskBitPtr > MAX_BIT_INDEX) {
|
|
_afskBitPtr = 0;
|
|
_afskBitMask = MASK_RESET_VALUE;
|
|
}
|
|
}
|
|
|
|
if (!nextBit) {
|
|
*current = !*current;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|