You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
6.8 KiB
309 lines
6.8 KiB
/*
|
|
* Copyright (C) 2009 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; version 2 of the License.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include "SlowDataDecoder.h"
|
|
#include "DStarDefines.h"
|
|
|
|
const unsigned char SCRAMBLER_BYTE1 = 0x70;
|
|
const unsigned char SCRAMBLER_BYTE2 = 0x4F;
|
|
const unsigned char SCRAMBLER_BYTE3 = 0x93;
|
|
|
|
CSlowDataDecoder::CSlowDataDecoder() :
|
|
m_buffer(NULL),
|
|
m_state(SDD_FIRST),
|
|
m_header(),
|
|
m_message(),
|
|
m_messageExp(0U),
|
|
// m_gpsMessage(),
|
|
m_headerData(NULL),
|
|
m_messageData(NULL),
|
|
// m_gpsMessageData(NULL),
|
|
m_codeSquelchData(0U),
|
|
m_hasCodeSquelch(false)
|
|
{
|
|
m_buffer = new unsigned char[6U];
|
|
}
|
|
|
|
CSlowDataDecoder::~CSlowDataDecoder()
|
|
{
|
|
delete[] m_buffer;
|
|
|
|
delete m_headerData;
|
|
delete m_messageData;
|
|
// delete m_gpsMessageData;
|
|
}
|
|
|
|
void CSlowDataDecoder::addData(const unsigned char* data)
|
|
{
|
|
wxASSERT(data != NULL);
|
|
|
|
switch (m_state) {
|
|
case SDD_FIRST:
|
|
m_buffer[0] = data[0] ^ SCRAMBLER_BYTE1;
|
|
m_buffer[1] = data[1] ^ SCRAMBLER_BYTE2;
|
|
m_buffer[2] = data[2] ^ SCRAMBLER_BYTE3;
|
|
m_state = SDD_SECOND;
|
|
return;
|
|
|
|
case SDD_SECOND:
|
|
m_buffer[3] = data[0] ^ SCRAMBLER_BYTE1;
|
|
m_buffer[4] = data[1] ^ SCRAMBLER_BYTE2;
|
|
m_buffer[5] = data[2] ^ SCRAMBLER_BYTE3;
|
|
m_state = SDD_FIRST;
|
|
break;
|
|
}
|
|
|
|
switch (m_buffer[0] & SLOW_DATA_TYPE_MASK) {
|
|
// case SLOW_DATA_TYPE_GPSDATA:
|
|
// processGPSMessage();
|
|
// break;
|
|
case SLOW_DATA_TYPE_MESSAGE:
|
|
processMessage();
|
|
break;
|
|
case SLOW_DATA_TYPE_HEADER:
|
|
processHeader();
|
|
break;
|
|
case SLOW_DATA_TYPE_SQUELCH:
|
|
processCodeSquelch();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
CGPSMessageData* CSlowDataDecoder::getGPSMessageData()
|
|
{
|
|
if (m_gpsMessageData == NULL)
|
|
return NULL;
|
|
|
|
CGPSMessageData* temp = new CGPSMessageData(*m_gpsMessageData);
|
|
|
|
delete m_gpsMessageData;
|
|
m_gpsMessageData = NULL;
|
|
|
|
m_gpsMessage.clear();
|
|
|
|
return temp;
|
|
}
|
|
*/
|
|
CMessageData* CSlowDataDecoder::getMessageData()
|
|
{
|
|
if (m_messageData == NULL)
|
|
return NULL;
|
|
|
|
CMessageData* temp = new CMessageData(*m_messageData);
|
|
|
|
delete m_messageData;
|
|
m_messageData = NULL;
|
|
|
|
m_message.clear();
|
|
|
|
return temp;
|
|
}
|
|
|
|
unsigned int CSlowDataDecoder::getHeader(unsigned char* data, unsigned int length)
|
|
{
|
|
wxASSERT(data != NULL);
|
|
wxASSERT(length == RADIO_HEADER_LENGTH_BYTES);
|
|
|
|
if (m_headerData == NULL)
|
|
return 0U;
|
|
|
|
unsigned int n = 0U;
|
|
for (vector<unsigned char>::const_iterator it = m_header.begin(); it != m_header.end(); ++it, n++)
|
|
data[n] = *it;
|
|
|
|
delete m_headerData;
|
|
m_headerData = NULL;
|
|
|
|
m_header.clear();
|
|
|
|
return RADIO_HEADER_LENGTH_BYTES;
|
|
}
|
|
|
|
CHeaderData* CSlowDataDecoder::getHeaderData()
|
|
{
|
|
if (m_headerData == NULL)
|
|
return NULL;
|
|
|
|
CHeaderData* temp = new CHeaderData(*m_headerData);
|
|
|
|
delete m_headerData;
|
|
m_headerData = NULL;
|
|
|
|
m_header.clear();
|
|
|
|
return temp;
|
|
}
|
|
|
|
bool CSlowDataDecoder::getCodeSquelchData(unsigned int& value)
|
|
{
|
|
value = m_codeSquelchData;
|
|
|
|
return m_hasCodeSquelch;
|
|
}
|
|
|
|
void CSlowDataDecoder::sync()
|
|
{
|
|
m_state = SDD_FIRST;
|
|
}
|
|
|
|
void CSlowDataDecoder::reset()
|
|
{
|
|
m_header.clear();
|
|
m_message.clear();
|
|
// m_gpsMessage.clear();
|
|
|
|
m_hasCodeSquelch = false;
|
|
|
|
m_state = SDD_FIRST;
|
|
|
|
delete m_headerData;
|
|
delete m_messageData;
|
|
// delete m_gpsMessageData;
|
|
|
|
m_headerData = NULL;
|
|
m_messageData = NULL;
|
|
// m_gpsMessageData = NULL;
|
|
|
|
m_messageExp = 0U;
|
|
m_codeSquelchData = 0U;
|
|
}
|
|
|
|
void CSlowDataDecoder::processHeader()
|
|
{
|
|
// Do we have a complete and valid header?
|
|
if (m_headerData != NULL)
|
|
return;
|
|
|
|
unsigned int length = m_buffer[0] & SLOW_DATA_LENGTH_MASK;
|
|
if (length > 5U)
|
|
return;
|
|
|
|
for (unsigned int i = 1U; i <= length; i++)
|
|
m_header.push_back(m_buffer[i]);
|
|
|
|
// Do we have a complete header?
|
|
if (m_header.size() < RADIO_HEADER_LENGTH_BYTES)
|
|
return;
|
|
|
|
// Something has been corrupted, discard
|
|
if (m_header.size() != RADIO_HEADER_LENGTH_BYTES) {
|
|
m_header.clear();
|
|
return;
|
|
}
|
|
|
|
// Convert the vector to an array
|
|
unsigned char buffer[RADIO_HEADER_LENGTH_BYTES];
|
|
unsigned int n = 0U;
|
|
for (vector<unsigned char>::iterator it = m_header.begin(); it != m_header.end(); ++it, n++)
|
|
buffer[n] = *it;
|
|
|
|
m_headerData = new CHeaderData(buffer, RADIO_HEADER_LENGTH_BYTES, true);
|
|
|
|
if (!m_headerData->isValid()) {
|
|
m_header.clear();
|
|
delete m_headerData;
|
|
m_headerData = NULL;
|
|
}
|
|
}
|
|
|
|
void CSlowDataDecoder::processMessage()
|
|
{
|
|
// Do we have a complete message?
|
|
if (m_messageData != NULL)
|
|
return;
|
|
|
|
unsigned int num = m_buffer[0] & SLOW_DATA_LENGTH_MASK;
|
|
if (num > 3U) // Sanity check
|
|
return;
|
|
|
|
// Handle any gaps in the received message
|
|
if (num > m_messageExp) {
|
|
for (; m_messageExp < num; m_messageExp++) {
|
|
m_message.push_back(' ');
|
|
m_message.push_back(' ');
|
|
m_message.push_back(' ');
|
|
m_message.push_back(' ');
|
|
m_message.push_back(' ');
|
|
}
|
|
|
|
m_messageExp = num;
|
|
} else {
|
|
m_messageExp++;
|
|
}
|
|
|
|
m_message.push_back(m_buffer[1U]);
|
|
m_message.push_back(m_buffer[2U]);
|
|
m_message.push_back(m_buffer[3U]);
|
|
m_message.push_back(m_buffer[4U]);
|
|
m_message.push_back(m_buffer[5U]);
|
|
|
|
// Do we have a complete message?
|
|
if (m_message.size() < MESSAGE_LENGTH)
|
|
return;
|
|
|
|
// Something has become corrupted
|
|
if (m_message.size() != MESSAGE_LENGTH) {
|
|
m_message.clear();
|
|
return;
|
|
}
|
|
|
|
// Convert the vector to an array
|
|
unsigned char buffer[MESSAGE_LENGTH];
|
|
unsigned int n = 0U;
|
|
for (vector<unsigned char>::iterator it = m_message.begin(); it != m_message.end(); ++it, n++)
|
|
buffer[n] = *it;
|
|
|
|
m_messageData = new CMessageData(buffer, MESSAGE_LENGTH);
|
|
}
|
|
/*
|
|
void CSlowDataDecoder::processGPSMessage()
|
|
{
|
|
if (m_gpsMessageData != NULL)
|
|
return;
|
|
|
|
unsigned int length = m_buffer[0] & SLOW_DATA_LENGTH_MASK;
|
|
if (length > 5U)
|
|
length = 5U;
|
|
|
|
for (unsigned int i = 0U; i < length; i++)
|
|
m_gpsMessage.push_back(m_buffer[i + 1U]);
|
|
|
|
// Do we have a complete message?
|
|
if (length == 5U)
|
|
return;
|
|
|
|
// Convert the vector to an array
|
|
length = m_gpsMessage.size();
|
|
unsigned char* buffer = new unsigned char[length];
|
|
unsigned int n = 0U;
|
|
for (vector<unsigned char>::iterator it = m_gpsMessage.begin(); it != m_gpsMessage.end(); ++it, n++)
|
|
buffer[n] = *it;
|
|
|
|
m_gpsMessageData = new CGPSMessageData(buffer, length);
|
|
|
|
delete[] buffer;
|
|
}
|
|
*/
|
|
void CSlowDataDecoder::processCodeSquelch()
|
|
{
|
|
bool ret = m_buffer[1] == m_buffer[2];
|
|
if (ret) {
|
|
// Convert the hex to decimal, i.e. 0x99 = 99
|
|
m_codeSquelchData = (m_buffer[1] / 16U) * 10U + (m_buffer[1] % 16U);
|
|
m_hasCodeSquelch = true;
|
|
}
|
|
}
|