/* * Copyright (C) 2009,2010,2012 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 "CCITTChecksumReverse.h" #include "SlowDataEncoder.h" #include "DStarDefines.h" const unsigned char SCRAMBLER_BYTE1 = 0x70; const unsigned char SCRAMBLER_BYTE2 = 0x4F; const unsigned char SCRAMBLER_BYTE3 = 0x93; CSlowDataEncoder::CSlowDataEncoder() : m_initial(), m_body(), m_it(), m_end(), m_header(), m_message(), // m_gpsMessage(), m_codeSquelch() { } CSlowDataEncoder::~CSlowDataEncoder() { } void CSlowDataEncoder::getData(unsigned char* data) { wxASSERT(data != NULL); // First time, we need to build the output data if (m_body.empty()) { buildData(); // Do we have any initial data to send? if (m_initial.empty()) { m_it = m_body.begin(); m_end = m_body.end(); } else { m_it = m_initial.begin(); m_end = m_initial.end(); } } // Create the sequence: initial, body, body, body, ... if (m_it == m_end) { m_it = m_body.begin(); m_end = m_body.end(); } // This assumes that the data is in three byte blocks and won't end half-way through // the loop. unsigned char buffer[DATA_FRAME_LENGTH_BYTES]; for (unsigned int n = 0U; m_it != m_end && n < DATA_FRAME_LENGTH_BYTES; ++m_it, n++) buffer[n] = *m_it; data[0U] = buffer[0U] ^ SCRAMBLER_BYTE1; data[1U] = buffer[1U] ^ SCRAMBLER_BYTE2; data[2U] = buffer[2U] ^ SCRAMBLER_BYTE3; } void CSlowDataEncoder::reset() { m_initial.clear(); m_body.clear(); m_header.clear(); m_message.clear(); // m_gpsMessage.clear(); m_codeSquelch.clear(); } void CSlowDataEncoder::setHeaderData(const CHeaderData& header) { CCCITTChecksumReverse cksum; unsigned char buffer[5U]; m_header.push_back(SLOW_DATA_TYPE_HEADER | 5U); m_header.push_back(buffer[0] = header.getFlag1()); m_header.push_back(buffer[1] = header.getFlag2()); m_header.push_back(buffer[2] = header.getFlag3()); m_header.push_back(buffer[3] = header.getRptCall1().GetChar(0)); m_header.push_back(buffer[4] = header.getRptCall1().GetChar(1)); cksum.update(buffer, 5U); m_header.push_back(SLOW_DATA_TYPE_HEADER | 5U); m_header.push_back(buffer[0] = header.getRptCall1().GetChar(2)); m_header.push_back(buffer[1] = header.getRptCall1().GetChar(3)); m_header.push_back(buffer[2] = header.getRptCall1().GetChar(4)); m_header.push_back(buffer[3] = header.getRptCall1().GetChar(5)); m_header.push_back(buffer[4] = header.getRptCall1().GetChar(6)); cksum.update(buffer, 5U); m_header.push_back(SLOW_DATA_TYPE_HEADER | 5U); m_header.push_back(buffer[0] = header.getRptCall1().GetChar(7)); m_header.push_back(buffer[1] = header.getRptCall2().GetChar(0)); m_header.push_back(buffer[2] = header.getRptCall2().GetChar(1)); m_header.push_back(buffer[3] = header.getRptCall2().GetChar(2)); m_header.push_back(buffer[4] = header.getRptCall2().GetChar(3)); cksum.update(buffer, 5U); m_header.push_back(SLOW_DATA_TYPE_HEADER | 5U); m_header.push_back(buffer[0] = header.getRptCall2().GetChar(4)); m_header.push_back(buffer[1] = header.getRptCall2().GetChar(5)); m_header.push_back(buffer[2] = header.getRptCall2().GetChar(6)); m_header.push_back(buffer[3] = header.getRptCall2().GetChar(7)); m_header.push_back(buffer[4] = header.getYourCall().GetChar(0)); cksum.update(buffer, 5U); m_header.push_back(SLOW_DATA_TYPE_HEADER | 5U); m_header.push_back(buffer[0] = header.getYourCall().GetChar(1)); m_header.push_back(buffer[1] = header.getYourCall().GetChar(2)); m_header.push_back(buffer[2] = header.getYourCall().GetChar(3)); m_header.push_back(buffer[3] = header.getYourCall().GetChar(4)); m_header.push_back(buffer[4] = header.getYourCall().GetChar(5)); cksum.update(buffer, 5U); m_header.push_back(SLOW_DATA_TYPE_HEADER | 5U); m_header.push_back(buffer[0] = header.getYourCall().GetChar(6)); m_header.push_back(buffer[1] = header.getYourCall().GetChar(7)); m_header.push_back(buffer[2] = header.getMyCall1().GetChar(0)); m_header.push_back(buffer[3] = header.getMyCall1().GetChar(1)); m_header.push_back(buffer[4] = header.getMyCall1().GetChar(2)); cksum.update(buffer, 5U); m_header.push_back(SLOW_DATA_TYPE_HEADER | 5U); m_header.push_back(buffer[0] = header.getMyCall1().GetChar(3)); m_header.push_back(buffer[1] = header.getMyCall1().GetChar(4)); m_header.push_back(buffer[2] = header.getMyCall1().GetChar(5)); m_header.push_back(buffer[3] = header.getMyCall1().GetChar(6)); m_header.push_back(buffer[4] = header.getMyCall1().GetChar(7)); cksum.update(buffer, 5U); m_header.push_back(SLOW_DATA_TYPE_HEADER | 5U); m_header.push_back(buffer[0] = header.getMyCall2().GetChar(0)); m_header.push_back(buffer[1] = header.getMyCall2().GetChar(1)); m_header.push_back(buffer[2] = header.getMyCall2().GetChar(2)); m_header.push_back(buffer[3] = header.getMyCall2().GetChar(3)); cksum.update(buffer, 4U); cksum.result(buffer); m_header.push_back(buffer[0]); m_header.push_back(SLOW_DATA_TYPE_HEADER | 1U); m_header.push_back(buffer[1]); m_header.push_back('f'); m_header.push_back('f'); m_header.push_back('f'); m_header.push_back('f'); } void CSlowDataEncoder::setMessageData(const wxString& message) { if (message.IsEmpty()) return; wxString text = message; text.Append(wxT(" ")); text.Truncate(MESSAGE_LENGTH); unsigned int n = 0U; for (unsigned int i = 0U; i < MESSAGE_LENGTH; i++) { if ((i % 5U) == 0U) { m_message.push_back(SLOW_DATA_TYPE_MESSAGE | n); n++; } m_message.push_back(text.GetChar(i)); } } /* void CSlowDataEncoder::setGPSMessageData(const CGPSMessageData& message) { if (message.getGPSMsgText().IsEmpty()) return; unsigned int n = 0U; unsigned int length = message.getGPSMsgText().Len(); for (unsigned int i = 0U; i < length; i++) { if ((i % 5U) == 0U) { m_gpsMessage.push_back(SLOW_DATA_TYPE_GPSDATA | n); n++; } m_gpsMessage.push_back(message.getGPSMsgText().GetChar(i)); } length %= 5U; for (unsigned int i = 0U; i < length; i++) m_gpsMessage.push_back('f'); } */ void CSlowDataEncoder::setCodeSquelch(unsigned char value) { // Convert decimal to hex, i.e. 99 = 0x99 unsigned char hexValue = (value / 10U) * 16U + (value % 10U); m_codeSquelch.push_back(SLOW_DATA_TYPE_SQUELCH | 2U); m_codeSquelch.push_back(hexValue); m_codeSquelch.push_back(hexValue); m_codeSquelch.push_back('f'); m_codeSquelch.push_back('f'); m_codeSquelch.push_back('f'); } void CSlowDataEncoder::buildData() { // Create the initial section, if needed if (!m_message.empty()) { if (m_codeSquelch.empty()) { // T T T T F F F F F F m_initial.insert(m_initial.begin(), m_message.begin(), m_message.end()); m_initial.insert(m_initial.end(), 12U * DATA_FRAME_LENGTH_BYTES, 'f'); } else { // C T T T T F F F F F m_initial.insert(m_initial.begin(), m_codeSquelch.begin(), m_codeSquelch.end()); m_initial.insert(m_initial.end(), m_message.begin(), m_message.end()); m_initial.insert(m_initial.end(), 10U * DATA_FRAME_LENGTH_BYTES, 'f'); } } // Create the body section if (!m_codeSquelch.empty()) { // C H H H H H H H H H m_body.insert(m_body.begin(), m_codeSquelch.begin(), m_codeSquelch.end()); m_body.insert(m_body.end(), m_header.begin(), m_header.end()); } else { // H H H H H H H H H F m_body.insert(m_body.begin(), m_header.begin(), m_header.end()); m_body.insert(m_body.end(), 2U * DATA_FRAME_LENGTH_BYTES, 'f'); } }