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.

144 lines
3.6 KiB

/*
* Copyright (C) 2009,2010,2014 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 "ExternalController.h"
#include "DStarDefines.h"
#include <chrono>
#include <thread>
CExternalController::CExternalController(IHardwareController* controller, bool pttInvert) :
m_controller(controller),
m_pttInvert(pttInvert),
m_disable(false),
m_heartbeat(false),
m_active(false),
m_radioTX(false),
m_out1(false),
m_out2(false),
m_out3(false),
m_out4(false),
m_kill(false),
m_thread()
{
// When PTT is active-low the idle state is high (i.e. inverted true), so
// pre-set m_radioTX accordingly before the thread starts writing to hardware.
if (m_pttInvert)
m_radioTX = true;
}
CExternalController::~CExternalController()
{
delete m_controller;
}
bool CExternalController::open()
{
bool res = m_controller->open();
if (!res)
return false;
m_thread = std::thread(&CExternalController::entry, this);
return true;
}
void CExternalController::entry()
{
bool dummy1, dummy2, dummy3, dummy4, disableIn;
// Poll the hardware at half the D-Star frame rate (every 10 ms).
// Apply desired output states, then latch the disable input for the repeater.
while (!m_kill) {
m_controller->setDigitalOutputs(m_radioTX, false, m_heartbeat, m_active, m_out1, m_out2, m_out3, m_out4);
m_controller->getDigitalInputs(dummy1, dummy2, dummy3, dummy4, disableIn);
m_disable = disableIn;
std::this_thread::sleep_for(std::chrono::milliseconds(DSTAR_FRAME_TIME_MS / 2U));
}
// Shutdown sequence: de-assert PTT (accounting for inversion), wait for the
// transmitter to drop (3 frame periods = 60 ms), then confirm the idle state
// a second time before closing the hardware device.
if (m_pttInvert)
m_controller->setDigitalOutputs(true, false, false, false, false, false, false, false);
else
m_controller->setDigitalOutputs(false, false, false, false, false, false, false, false);
m_controller->getDigitalInputs(dummy1, dummy2, dummy3, dummy4, disableIn);
m_disable = disableIn;
std::this_thread::sleep_for(std::chrono::milliseconds(DSTAR_FRAME_TIME_MS * 3U));
if (m_pttInvert)
m_controller->setDigitalOutputs(true, false, false, false, false, false, false, false);
else
m_controller->setDigitalOutputs(false, false, false, false, false, false, false, false);
m_controller->getDigitalInputs(dummy1, dummy2, dummy3, dummy4, disableIn);
m_disable = disableIn;
m_controller->close();
}
bool CExternalController::getDisable() const
{
return m_disable;
}
void CExternalController::setRadioTransmit(bool value)
{
if (m_pttInvert)
value = !value;
m_radioTX = value;
}
void CExternalController::setHeartbeat()
{
// Toggle on each call so any periodic caller drives a visible LED blink.
m_heartbeat = !m_heartbeat;
}
void CExternalController::setActive(bool value)
{
m_active = value;
}
void CExternalController::setOutput1(bool value)
{
m_out1 = value;
}
void CExternalController::setOutput2(bool value)
{
m_out2 = value;
}
void CExternalController::setOutput3(bool value)
{
m_out3 = value;
}
void CExternalController::setOutput4(bool value)
{
m_out4 = value;
}
void CExternalController::close()
{
m_kill = true;
if (m_thread.joinable())
m_thread.join();
}

Powered by TurnKey Linux.