bool CGMSKClientThread::setTransmit(bool transmit) { if (m_stopped) return false; if (transmit) { delete m_header; // The previous value, if any m_header = new CHeaderData(m_callsign1, m_callsign2, m_your, m_rpt1, m_rpt2); if (m_rpt1.IsEmpty() || m_rpt1.IsSameAs(wxT(" ")) || m_rpt1.IsSameAs(wxT("DIRECT "))) m_header->setRepeaterMode(false); else m_header->setRepeaterMode(true); m_slowDataEncoder.reset(); m_slowDataEncoder.setHeaderData(*m_header); if (!m_message.IsEmpty()) m_slowDataEncoder.setMessageData(m_message); m_transmit = CS_TRANSMIT; } else { resetReceiver(); m_transmit = CS_WANT_RECEIVE; m_tx = false; } return true; }
void CDummyRepeaterThread::checkController() { m_externalTX = m_controller->getRadioSquelch1(); if (m_externalTX && m_transmit != CLIENT_TRANSMIT) { m_transmit = CLIENT_TRANSMIT; } else if (!m_externalTX && m_transmit == CLIENT_TRANSMIT) { if (!m_localTX) { resetReceiver(); m_transmit = CLIENT_WANT_RECEIVE; } } m_controller->setRadioTransmit(m_busy); }
bool CDummyRepeaterThread::setTransmit(bool transmit) { if (m_stopped) return false; m_localTX = transmit; if (m_localTX && m_transmit != CLIENT_TRANSMIT) { m_transmit = CLIENT_TRANSMIT; } else if (!m_localTX && m_transmit == CLIENT_TRANSMIT) { if (!m_externalTX) { resetReceiver(); m_transmit = CLIENT_WANT_RECEIVE; } } return true; }
void CDExtraClientThread::receive() { // While receiving and not exitting while (m_transmit == CLIENT_RECEIVE && !m_killed) { // Get the audio from the RX NETWORK_TYPE type = m_protocol.read(); switch (type) { case NETWORK_NONE: break; case NETWORK_HEADER: { CHeaderData* header = m_protocol.readHeader(); if (header != NULL) processHeader(header); } break; case NETWORK_DATA: { unsigned char buffer[DV_FRAME_LENGTH_BYTES]; unsigned int length; bool sync, end; length = m_protocol.readData(buffer, DV_FRAME_LENGTH_BYTES, sync, end); processFrame(buffer, sync, end); } break; } if (m_watchdog.hasExpired()) { m_dongle->setMode(DVDMODE_IDLE); m_protocol.reset(); resetReceiver(); } if (m_squelchInvert) { if (!m_controller->getSquelch()) m_tx = transmit(true); } else { if (m_controller->getSquelch()) m_tx = transmit(true); } Sleep(FRAME_TIME_MS / 4UL); } }
void CDExtraClientThread::processFrame(const unsigned char* buffer, bool sync, bool end) { m_watchdog.reset(); if (m_recorder != NULL) m_recorder->writeFrame(buffer, DV_FRAME_LENGTH_BYTES); // Only process the slow data if this isn't a data sync frame if (!sync) processSlowData(buffer + VOICE_FRAME_LENGTH_BYTES); else m_slowDataDecoder.sync(); m_decodeData.addData(buffer, VOICE_FRAME_LENGTH_BYTES); if (end) { m_dongle->setMode(DVDMODE_IDLE); resetReceiver(); } }
bool CDExtraClientThread::transmit(bool transmit) { if (m_stopped) return false; if (transmit) { if (!m_protocol.isConnected()) return false; m_transmit = CLIENT_TRANSMIT; } else { resetReceiver(); m_transmit = CLIENT_WANT_RECEIVE; m_tx = false; } return true; }
void CDummyRepeaterThread::transmit() { m_encodeData.clear(); m_dongle->setMode(DVDMODE_ENCODE); // Pause until all the silence data has been processed by the AMBE2020 for (unsigned int startCount = 30U; startCount > 0U; startCount--) { unsigned char frame[DV_FRAME_LENGTH_BYTES]; unsigned int n = 0U; do { n += m_encodeData.getData(frame + n, VOICE_FRAME_LENGTH_BYTES - n); if (n < VOICE_FRAME_LENGTH_BYTES) Sleep(DSTAR_FRAME_TIME_MS / 4UL); } while (n < VOICE_FRAME_LENGTH_BYTES); serviceNetwork(); checkController(); } CHeaderData* header = new CHeaderData(m_callsign1, m_callsign2, m_your, m_rpt2, m_rpt1); wxLogMessage(wxT("Transmitting to - My: %s/%s Your: %s Rpt1: %s Rpt2: %s"), header->getMyCall1().c_str(), header->getMyCall2().c_str(), header->getYourCall().c_str(), header->getRptCall1().c_str(), header->getRptCall2().c_str()); m_slowDataEncoder.reset(); m_slowDataEncoder.setHeaderData(*header); serviceNetwork(); checkController(); if (!m_message.IsEmpty()) m_slowDataEncoder.setMessageData(m_message); m_protocol->writeHeader(*header); delete header; serviceNetwork(); checkController(); m_frameCount = 20U; unsigned int endCount = 30U; // While transmitting and not exiting for (;;) { unsigned char frame[DV_FRAME_LENGTH_BYTES]; unsigned int n = 0U; do { n += m_encodeData.getData(frame + n, VOICE_FRAME_LENGTH_BYTES - n); if (n < VOICE_FRAME_LENGTH_BYTES) Sleep(DSTAR_FRAME_TIME_MS / 4UL); } while (n < VOICE_FRAME_LENGTH_BYTES); serviceNetwork(); checkController(); if (m_frameCount == 20U) { // Put in the data resync pattern ::memcpy(frame + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES); m_frameCount = 0U; } else { // Tack the slow data on the end m_slowDataEncoder.getData(frame + VOICE_FRAME_LENGTH_BYTES); m_frameCount++; } if (m_transmit != CLIENT_TRANSMIT) endCount--; // Send the AMBE and slow data frame if (endCount == 0U || m_killed) { m_protocol->writeData(frame, DV_FRAME_LENGTH_BYTES, 0U, true); break; } else { m_protocol->writeData(frame, DV_FRAME_LENGTH_BYTES, 0U, false); } serviceNetwork(); checkController(); } m_dongle->setMode(DVDMODE_IDLE); resetReceiver(); m_transmit = CLIENT_RECEIVE; serviceNetwork(); checkController(); }
void CDummyRepeaterThread::receive() { m_clockCount = 0U; m_busy = false; unsigned int hangCount = 0U; // While receiving and not exitting while (m_transmit == CLIENT_RECEIVE && !m_killed) { // Get the audio from the RX NETWORK_TYPE type; for (;;) { type = m_protocol->read(); if (type == NETWORK_NONE) { break; } else if (type == NETWORK_HEADER) { CHeaderData* header = m_protocol->readHeader(); if (header != NULL) { processHeader(header); m_watchdog.start(); m_clockCount = 0U; hangCount = 0U; m_busy = true; } break; } else if (type == NETWORK_DATA) { unsigned char buffer[DV_FRAME_LENGTH_BYTES]; unsigned char seqNo; unsigned int length = m_protocol->readData(buffer, DV_FRAME_LENGTH_BYTES, seqNo); if (length != 0U) { bool end = processFrame(buffer, seqNo); if (end) hangCount = 30U; else hangCount = 0U; m_watchdog.reset(); m_clockCount = 0U; } break; } else if (type == NETWORK_TEXT) { wxString text, reflector; LINK_STATUS status; m_protocol->readText(text, status, reflector); ::wxGetApp().showSlowData(text); } else if (type == NETWORK_TEMPTEXT) { wxString text; m_protocol->readTempText(text); } else if (type == NETWORK_STATUS1) { wxString text = m_protocol->readStatus1(); ::wxGetApp().showStatus1(text); } else if (type == NETWORK_STATUS2) { wxString text = m_protocol->readStatus2(); ::wxGetApp().showStatus2(text); } else if (type == NETWORK_STATUS3) { wxString text = m_protocol->readStatus3(); ::wxGetApp().showStatus3(text); } else if (type == NETWORK_STATUS4) { wxString text = m_protocol->readStatus4(); ::wxGetApp().showStatus4(text); } else if (type == NETWORK_STATUS5) { wxString text = m_protocol->readStatus5(); ::wxGetApp().showStatus5(text); } } // Have we missed a data frame? if (type == NETWORK_NONE && m_busy) { m_clockCount++; if (m_clockCount == 8U) { // Create a silence frame unsigned char buffer[DV_FRAME_LENGTH_BYTES]; ::memcpy(buffer, NULL_FRAME_DATA_BYTES, DV_FRAME_LENGTH_BYTES); processFrame(buffer, m_networkSeqNo); m_clockCount = 0U; } } if (m_watchdog.isRunning() && m_watchdog.hasExpired()) { wxLogMessage(wxT("Network watchdog has expired")); m_dongle->setMode(DVDMODE_IDLE); m_protocol->reset(); resetReceiver(); } if (hangCount > 0U) { hangCount--; if (hangCount == 0U) { m_dongle->setMode(DVDMODE_IDLE); resetReceiver(); } } checkController(); Sleep(DSTAR_FRAME_TIME_MS / 4UL); } }
void CDExtraClientThread::transmit() { m_encodeData.clear(); m_dongle->setMode(DVDMODE_ENCODE); // Pause until all the silence data has been processed by the AMBE2020 unsigned int startCount = 30U; while (startCount > 0U) { unsigned char frame[DV_FRAME_LENGTH_BYTES]; unsigned int n = m_encodeData.getData(frame, VOICE_FRAME_LENGTH_BYTES); if (n > 0U) startCount--; Sleep(FRAME_TIME_MS / 4UL); } wxString rpt1 = m_reflector; rpt1.Append(wxT(" ")); rpt1.Truncate(LONG_CALLSIGN_LENGTH - 1U); rpt1.Append(m_module); wxString rpt2 = m_reflector; rpt2.Append(wxT(" ")); rpt2.Truncate(LONG_CALLSIGN_LENGTH - 1U); rpt2.Append(wxT('G')); CHeaderData* header = new CHeaderData(m_callsign, wxT("DNGL"), wxT("CQCQCQ "), rpt1, rpt2); m_slowDataEncoder.reset(); m_slowDataEncoder.setHeaderData(*header); #if defined(DUMP_AMBE) m_dumper = new CDVTOOLFileWriter; bool res = m_dumper->open(*header); if (!res) { delete m_dumper; m_dumper = NULL; } else { wxLogMessage(wxT("Dumping AMBE to %s"), m_dumper->getFileName().c_str()); m_dumper->writeHeader(*header); } #endif if (!m_message.IsEmpty()) m_slowDataEncoder.setMessageData(m_message); m_protocol.writeHeader(*header); delete header; m_frameCount = 20U; unsigned int endCount = 30U; // While transmitting and not exiting for (;;) { unsigned char frame[DV_FRAME_LENGTH_BYTES]; unsigned int n = m_encodeData.getData(frame, VOICE_FRAME_LENGTH_BYTES); if (n > 0U) { if (m_frameCount == 20U) { // Put in the data resync pattern ::memcpy(frame + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES); m_frameCount = 0U; } else { // Tack the slow data on the end m_slowDataEncoder.getData(frame + VOICE_FRAME_LENGTH_BYTES); m_frameCount++; } if (m_transmit != CLIENT_TRANSMIT) endCount--; #if defined(DUMP_AMBE) if (m_dumper != NULL) m_dumper->writeFrame(frame, DV_FRAME_LENGTH_BYTES); #endif // Send the AMBE and slow data frame if (endCount == 0U || m_killed) { m_protocol.writeData(frame, DV_FRAME_LENGTH_BYTES, true); break; } else { m_protocol.writeData(frame, DV_FRAME_LENGTH_BYTES, false); } if (m_tx) { if (m_squelchInvert) { if (m_controller->getSquelch()) { transmit(false); m_tx = false; } } else { if (!m_controller->getSquelch()) { transmit(false); m_tx = false; } } } } Sleep(FRAME_TIME_MS / 4UL); } m_dongle->setMode(DVDMODE_IDLE); #if defined(DUMP_AMBE) if (m_dumper != NULL) { m_dumper->close(); delete m_dumper; m_dumper = NULL; } #endif resetReceiver(); m_transmit = CLIENT_RECEIVE; }
void CGMSKClientThread::receive() { resetReceiver(); // While receiving and not exitting while (m_transmit == CS_RECEIVE && !m_killed) { switch (m_state) { case RXS_LISTENING: { CHeaderData* header = m_modem->readHeader(); if (header != NULL) { bool res = processHeader(header); if (!res) { // Either the checksum failed, or this is a DD packet // wxLogInfo(wxT("Radio header invalid")); setState(RXS_LISTENING); } else { // A valid header and is a DV packet // wxLogInfo(wxT("Found valid radio header")); setState(RXS_PROCESS_DATA); } } } break; case RXS_PROCESS_DATA: { unsigned char data[GMSK_MODEM_DATA_LENGTH]; bool end; int length = m_modem->readData(data, GMSK_MODEM_DATA_LENGTH, end); if (length == -1) break; if (end) { wxLogMessage(wxT("Found end sync")); setState(RXS_LISTENING); break; } for (int i = 0; i < length; i++) { m_ambeBuffer[m_ambeLength] = data[i]; m_ambeLength++; if (m_ambeLength >= DV_FRAME_LENGTH_BYTES) { m_ambeLength = 0U; bool res = ::memcmp(m_ambeBuffer + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES) == 0; if (res) { wxLogMessage(wxT("Found data sync at frame %u"), m_syncCount); m_syncCount = 0U; processFrame(m_ambeBuffer, true); } else if (m_syncCount == 20U) { wxLogMessage(wxT("Regenerating data sync")); m_syncCount = 0U; processFrame(m_ambeBuffer, true); } else { m_syncCount++; processFrame(m_ambeBuffer, false); } } } } break; default: break; } Sleep(FRAME_TIME_MS / 2UL); } }
void CDVAPClientThread::receive() { m_rxPollTimer.start(); resetReceiver(); // While receiving and not exitting while (m_transmit == CS_RECEIVE && !m_killed) { switch (m_state) { case RXS_LISTENING: { CHeaderData* header = m_dvap->readHeader(); if (header != NULL) { bool res = processHeader(header); if (!res) { // Either the checksum failed, or this is a DD packet // wxLogInfo(wxT("Radio header invalid")); setState(RXS_LISTENING); } else { // A valid header and is a DV packet // wxLogInfo(wxT("Found valid radio header")); setState(RXS_PROCESS_DATA); } } } break; case RXS_PROCESS_DATA: { unsigned char data[15U]; bool end; int length = m_dvap->readData(data, 15U, end); if (length == -1) break; if (end) { wxLogMessage(wxT("Found end sync")); setState(RXS_LISTENING); break; } bool res = ::memcmp(data + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES) == 0; if (res) { wxLogMessage(wxT("Found data sync at frame %u"), m_syncCount); m_syncCount = 0U; processFrame(data, true); } else if (m_syncCount == 20U) { wxLogMessage(wxT("Regenerating data sync")); m_syncCount = 0U; processFrame(data, true); } else { m_syncCount++; processFrame(data, false); } } break; default: break; } if (m_rxPollTimer.hasExpired()) { m_dvap->writePoll(); m_rxPollTimer.reset(); } Sleep(FRAME_TIME_MS / 2UL); m_rxPollTimer.clock(); } m_rxPollTimer.stop(); }