void CDStarRepeaterTXRXThread::repeaterStateMachine() { if (m_watchdogTimer.isRunning() && m_watchdogTimer.hasExpired()) { wxLogMessage(wxT("Network watchdog has expired")); // Send end of transmission data to the radio m_networkQueue[m_writeNum]->addData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES, true); endOfNetworkData(); } }
void CSoundCardRepeaterTXRXThread::repeaterStateMachine() { if (m_watchdogTimer.isRunning() && m_watchdogTimer.hasExpired()) { wxLogMessage(wxT("Network watchdog has expired")); // Send end of transmission data to the radio m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); endOfNetworkData(); } }
void CDVAPNodeTRXThread::repeaterStateMachine() { switch (m_state) { case DSRS_VALID: if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) { wxLogMessage(wxT("User has timed out")); setRepeaterState(DSRS_TIMEOUT); } break; case DSRS_VALID_WAIT: if (m_ackTimer.hasExpired()) { transmitStatus(); setRepeaterState(DSRS_LISTENING); } break; case DSRS_INVALID_WAIT: if (m_ackTimer.hasExpired()) { transmitErrorStatus(); setRepeaterState(DSRS_LISTENING); } break; case DSRS_TIMEOUT_WAIT: if (m_ackTimer.hasExpired()) { transmitStatus(); setRepeaterState(DSRS_LISTENING); } break; case DSRS_NETWORK: if (m_watchdogTimer.hasExpired()) { wxLogMessage(wxT("Network watchdog has expired")); // Send end of transmission data to the radio m_networkQueue[m_writeNum]->addData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES, true); endOfNetworkData(); } break; default: break; } }
unsigned int CDVAPNodeTRXThread::processNetworkFrame(unsigned char* data, unsigned int length, unsigned char seqNo) { wxASSERT(data != NULL); wxASSERT(length > 0U); if (m_state != DSRS_NETWORK) return 0U; bool end = (seqNo & 0x40U) == 0x40U; if (end) { if (length > DV_FRAME_LENGTH_BYTES) { m_networkQueue[m_writeNum]->addData(data, DV_FRAME_LENGTH_BYTES, false); m_networkQueue[m_writeNum]->addData(data + DV_FRAME_LENGTH_BYTES, DV_FRAME_LENGTH_BYTES, true); } else { m_networkQueue[m_writeNum]->addData(data, DV_FRAME_LENGTH_BYTES, true); } endOfNetworkData(); return 1U; } // Mask out the control bits of the sequence number seqNo &= 0x1FU; // Count the number of silence frames to insert unsigned int tempSeqNo = m_networkSeqNo; unsigned int count = 0U; while (seqNo != tempSeqNo) { count++; tempSeqNo++; if (tempSeqNo >= 21U) tempSeqNo = 0U; } // If the number is too high, then it probably means an old out-of-order frame, ignore it if (count > 18U) return 0U; unsigned int packetCount = 0U; // Insert missing frames while (seqNo != m_networkSeqNo) { unsigned char buffer[DV_FRAME_LENGTH_BYTES]; if (count > SILENCE_THRESHOLD) { ::memcpy(buffer, NULL_FRAME_DATA_BYTES, DV_FRAME_LENGTH_BYTES); } else { ::memcpy(buffer, m_lastData, DV_FRAME_LENGTH_BYTES); m_ambe.regenerate(buffer); blankDTMF(buffer); } if (m_networkSeqNo == 0U) ::memcpy(buffer + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES); m_networkQueue[m_writeNum]->addData(buffer, DV_FRAME_LENGTH_BYTES, false); packetCount++; m_networkSeqNo++; m_packetSilence++; if (m_networkSeqNo >= 21U) m_networkSeqNo = 0U; } // Regenerate the sync bytes if (m_networkSeqNo == 0U) ::memcpy(data + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES); packetCount++; m_networkSeqNo++; if (m_networkSeqNo >= 21U) m_networkSeqNo = 0U; m_ambe.regenerate(data); blankDTMF(data); m_networkQueue[m_writeNum]->addData(data, DV_FRAME_LENGTH_BYTES, false); return packetCount; }
void CDVRPTRRepeaterTXThread::run() { // Wait here until we have the essentials to run while (!m_killed && (m_dvrptr == NULL || m_protocolHandler == NULL || m_rptCallsign.IsEmpty() || m_rptCallsign.IsSameAs(wxT(" ")))) ::wxMilliSleep(500UL); // 1/2 sec if (m_killed) return; m_stopped = false; m_pollTimer.start(); wxLogMessage(wxT("Starting the DV-RPTR transmitter thread")); wxStopWatch stopWatch; while (!m_killed) { stopWatch.Start(); // Remove any received data from the modem m_dvrptr->purgeRX(); receiveNetwork(); m_tx = m_dvrptr->getPTT(); if (m_state == DSRS_NETWORK) { if (m_watchdogTimer.hasExpired()) { wxLogMessage(wxT("Network watchdog has expired")); // Send end of transmission data to the radio m_networkQueue[m_writeNum]->addData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES, true); endOfNetworkData(); } } // Send the network poll if needed and restart the timer if (m_pollTimer.hasExpired()) { #if defined(__WINDOWS__) m_protocolHandler->writePoll(wxT("win_dvrptr-") + VERSION); #else m_protocolHandler->writePoll(wxT("linux_dvrptr-") + VERSION); #endif m_pollTimer.reset(); } if (m_networkQueue[m_readNum]->dataReady()) transmitNetworkData(); else if (m_networkQueue[m_readNum]->headerReady()) transmitNetworkHeader(); unsigned long ms = stopWatch.Time(); if (ms < CYCLE_TIME) { ::wxMilliSleep(CYCLE_TIME - ms); clock(CYCLE_TIME); } else { clock(ms); } } wxLogMessage(wxT("Stopping the DV-RPTR transmitter thread")); m_dvrptr->close(); m_protocolHandler->close(); delete m_protocolHandler; }
void* CSoundCardRepeaterTXThread::Entry() { // Wait here until we have the essentials to run while (!m_killed && (m_soundcard == NULL || m_protocolHandler == NULL || m_rptCallsign.IsEmpty() || m_rptCallsign.IsSameAs(wxT(" ")) || m_controller == NULL)) Sleep(500UL); // 1/2 sec if (m_killed) return NULL; m_controller->setActive(false); m_controller->setRadioTransmit(false); m_pollTimer.start(); wxLogMessage(wxT("Starting the sound card transmitter thread")); unsigned int count = 0U; wxStopWatch timer; while (!m_killed) { timer.Start(); // Process network traffic receiveNetwork(); if (m_rptState == DSRS_NETWORK) { if (m_watchdogTimer.hasExpired()) { wxLogMessage(wxT("Network watchdog has expired")); // Send end of transmission data to the radio m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); endOfNetworkData(); } } // Send the network poll if needed and restart the timer if (m_pollTimer.hasExpired()) { #if defined(__WINDOWS__) m_protocolHandler->writePoll(wxT("win_sound-") + VERSION); #else m_protocolHandler->writePoll(wxT("linux_sound-") + VERSION); #endif m_pollTimer.reset(); } // Clock the heartbeat output every one second count++; if (count == 50U) { m_controller->setHeartbeat(); count = 0U; } // Set the output state if (m_rptState == DSRS_NETWORK || (m_activeHangTimer.isRunning() && !m_activeHangTimer.hasExpired())) { m_controller->setActive(true); } else { m_controller->setActive(false); m_activeHangTimer.stop(); } // Send the output data if (m_networkStarted) transmitNetwork(); else if (m_networkRun >= NETWORK_RUN_FRAME_COUNT) transmitNetwork(); else transmit(); unsigned int ms = timer.Time(); clock(ms); } wxLogMessage(wxT("Stopping the sound card transmitter thread")); m_controller->setActive(false); m_controller->setRadioTransmit(false); m_controller->close(); delete m_controller; m_soundcard->close(); delete m_soundcard; delete m_audioDelay; delete m_pttDelay; m_protocolHandler->close(); delete m_protocolHandler; #if defined(TX_TO_WAV_FILE) if (m_writer != NULL) { m_writer->close(); delete m_writer; } #endif return NULL; }
unsigned int CSoundCardRepeaterTXThread::processNetworkFrame(unsigned char* data, unsigned int length, unsigned char seqNo) { wxASSERT(data != NULL); wxASSERT(length > 0U); bool end = (seqNo & 0x40U) == 0x40U; if (end) { // Convert the bytes to bits for transmission bool bits[DV_FRAME_LENGTH_BITS * 2U]; unsigned int n = 0U; for (unsigned int i = 0U; i < length; i++, n += 8U) CUtils::byteToBitsRev(data[i], bits + n); m_networkBuffer.addData(bits, length * 8U); m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); m_networkBuffer.addData(END_PATTERN_BITS, END_PATTERN_LENGTH_BITS); endOfNetworkData(); return 1U; } // Mask out the control bits of the sequence number seqNo &= 0x1FU; // Count the number of silence frames to insert unsigned int tempSeqNo = m_networkSeqNo; unsigned int count = 0U; while (seqNo != tempSeqNo) { count++; tempSeqNo++; if (tempSeqNo >= 21U) tempSeqNo = 0U; } // If the number is too high, then it probably means an out-of-order frame, ignore it if (count > 18U) return 0U; unsigned int packetCount = 0U; // Insert missing frames while (seqNo != m_networkSeqNo) { if (count > SILENCE_THRESHOLD) { m_networkBuffer.addData(NULL_AMBE_DATA_BITS, VOICE_FRAME_LENGTH_BITS); } else { unsigned char buffer[DV_FRAME_LENGTH_BYTES]; ::memcpy(buffer, m_lastData, DV_FRAME_LENGTH_BYTES); m_ambe.regenerate(buffer); blankDTMF(buffer); // Convert the bytes to bits for transmission bool bits[VOICE_FRAME_LENGTH_BITS * 2U]; unsigned int n = 0U; for (unsigned int i = 0U; i < VOICE_FRAME_LENGTH_BYTES; i++, n += 8U) CUtils::byteToBitsRev(buffer[i], bits + n); m_networkBuffer.addData(bits, VOICE_FRAME_LENGTH_BITS); } if (m_networkSeqNo == 0U) m_networkBuffer.addData(DATA_SYNC_BITS, DATA_FRAME_LENGTH_BITS); else m_networkBuffer.addData(NULL_SLOW_DATA_BITS, DATA_FRAME_LENGTH_BITS); packetCount++; m_networkRun++; m_networkSeqNo++; m_packetSilence++; if (m_networkSeqNo >= 21U) m_networkSeqNo = 0U; } // Regenerate the sync bytes if (m_networkSeqNo == 0U) ::memcpy(data + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES); packetCount++; m_networkRun++; m_networkSeqNo++; if (m_networkSeqNo >= 21U) m_networkSeqNo = 0U; m_ambe.regenerate(data); blankDTMF(data); // Convert the bytes to bits for transmission bool bits[DV_FRAME_LENGTH_BITS * 2U]; unsigned int n = 0U; for (unsigned int i = 0U; i < length; i++, n += 8U) CUtils::byteToBitsRev(data[i], bits + n); m_networkBuffer.addData(bits, length * 8U); return packetCount; }
void CGMSKRepeaterTXThread::run() { // Wait here until we have the essentials to run while (!m_killed && (m_modem == NULL || m_protocolHandler == NULL || m_rptCallsign.IsEmpty() || m_rptCallsign.IsSameAs(wxT(" ")))) ::wxMilliSleep(500UL); // 1/2 sec if (m_killed) return; m_stopped = false; m_pollTimer.start(); wxLogMessage(wxT("Starting the GMSK transmitter thread")); wxStopWatch stopWatch; while (!m_killed) { stopWatch.Start(); // Listen all the time on the network for status packets at least receiveNetwork(); if (m_state == DSRS_NETWORK) { if (m_watchdogTimer.hasExpired()) { wxLogMessage(wxT("Network watchdog has expired")); // Send end of transmission data to the radio m_networkQueue[m_writeNum]->addData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES, true); endOfNetworkData(); m_tx = false; } } // Send the network poll if needed and restart the timer if (m_pollTimer.hasExpired()) { #if defined(__WINDOWS__) m_protocolHandler->writePoll(wxT("win_gmsk-") + VERSION); #else m_protocolHandler->writePoll(wxT("linux_gmsk-") + VERSION); #endif m_pollTimer.reset(); } if (m_networkQueue[m_readNum]->dataReady()) { bool ret = transmitNetworkData(); if (!ret) reopenModem(); } else if (m_networkQueue[m_readNum]->headerReady()) { bool ret = transmitNetworkHeader(); if (!ret) reopenModem(); } unsigned long ms = stopWatch.Time(); if (ms < CYCLE_TIME) { ::wxMilliSleep(CYCLE_TIME - ms); ms = stopWatch.Time(); } // Catch up with the clock clock(ms); } wxLogMessage(wxT("Stopping the GMSK transmitter thread")); if (m_modem != NULL) { m_modem->close(); delete m_modem; } m_protocolHandler->close(); delete m_protocolHandler; }