/* * 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::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::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::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::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; } }