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
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();
|
|
}
|