Extract I2C logic from SerialController to separate class

This commit is contained in:
Shawn Chain 2018-07-30 21:58:35 +08:00
parent 77aa470649
commit d715470b1c
8 changed files with 259 additions and 88 deletions

166
IICController.cpp Normal file
View File

@ -0,0 +1,166 @@
/*
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "IICController.h"
#include "Log.h"
#include <cstring>
#include <cassert>
#include <sys/types.h>
#if defined(_WIN32) || defined(_WIN64)
#include <setupapi.h>
#include <winioctl.h>
#else
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#if !defined(__APPLE__)
#include <linux/i2c-dev.h>
#endif
#endif
#if defined(_WIN32) || defined(_WIN64)
CIICController::CSerialController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
CSerialController(device,speed,assertRTS),
m_address(address)
{
}
CIICController::~CIICController()
{
}
bool CIICController::open()
{
return CSerialController::open();
}
int CIICController::read(unsigned char* buffer, unsigned int length)
{
return CSerialController::read(buffer,length);
}
int CIICController::write(const unsigned char* buffer, unsigned int length)
{
return CSerialController:;write(buffer,length);
}
#else
CIICController::CIICController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
CSerialController(device,speed,assertRTS),
m_address(address)
{
}
CIICController::~CIICController()
{
}
bool CIICController::open()
{
assert(m_fd == -1);
#if !defined(__APPLE__)
m_fd = ::open(m_device.c_str(), O_RDWR);
if (m_fd < 0) {
LogError("Cannot open device - %s", m_device.c_str());
return false;
}
if (::ioctl(m_fd, I2C_TENBIT, 0) < 0) {
LogError("CI2C: failed to set 7bitaddress");
::close(m_fd);
return false;
}
if (::ioctl(m_fd, I2C_SLAVE, m_address) < 0) {
LogError("CI2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
::close(m_fd);
return false;
}
#else
#warning "I2C controller does not support OSX"
#endif
return true;
}
int CIICController::read(unsigned char* buffer, unsigned int length)
{
assert(buffer != NULL);
assert(m_fd != -1);
if (length == 0U)
return 0;
unsigned int offset = 0U;
while (offset < length) {
#if !defined(__APPLE__)
ssize_t n = ::read(m_fd, buffer + offset, 1U);
if (n < 0) {
if (errno != EAGAIN) {
LogError("Error returned from read(), errno=%d", errno);
return -1;
}
}
if (n > 0)
offset += n;
#endif
}
return length;
}
int CIICController::write(const unsigned char* buffer, unsigned int length)
{
assert(buffer != NULL);
assert(m_fd != -1);
if (length == 0U)
return 0;
unsigned int ptr = 0U;
while (ptr < length) {
ssize_t n = 0U;
#if !defined(__APPLE__)
n = ::write(m_fd, buffer + ptr, 1U);
#endif
if (n < 0) {
if (errno != EAGAIN) {
LogError("Error returned from write(), errno=%d", errno);
return -1;
}
}
if (n > 0)
ptr += n;
}
return length;
}
#endif

40
IICController.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef IICController_H
#define IICController_H
#include "SerialController.h"
class CIICController : public CSerialController {
public:
CIICController(const std::string& device, SERIAL_SPEED speed, unsigned int address = 0x22U, bool assertRTS = false);
virtual ~CIICController();
virtual bool open();
virtual int read(unsigned char* buffer, unsigned int length);
virtual int write(const unsigned char* buffer, unsigned int length);
private:
unsigned int m_address;
};
#endif

View File

@ -1103,7 +1103,8 @@ bool CMMDVMHost::createModem()
LogInfo(" RX Frequency: %uHz (%uHz)", rxFrequency, rxFrequency + rxOffset);
LogInfo(" TX Frequency: %uHz (%uHz)", txFrequency, txFrequency + txOffset);
m_modem = new CModem(port, protocol, address, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, trace, debug);
m_modem = new CModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, trace, debug);
m_modem->setSerialParams(protocol,address);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled);
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel);
m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel, pocsagFrequency);

View File

@ -13,7 +13,7 @@ OBJECTS = \
NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o \
QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \
UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o IICController.o
all: MMDVMHost

View File

@ -26,6 +26,7 @@
#include "Modem.h"
#include "Utils.h"
#include "Log.h"
#include "IICController.h"
#include <cmath>
#include <cstdio>
@ -92,7 +93,7 @@ const unsigned int MAX_RESPONSES = 30U;
const unsigned int BUFFER_LENGTH = 2000U;
CModem::CModem(const std::string& port, const std::string& protocol, unsigned int address, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug) :
CModem::CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug) :
m_port(port),
m_dmrColorCode(0U),
m_ysfLoDev(false),
@ -124,7 +125,7 @@ m_nxdnEnabled(false),
m_pocsagEnabled(false),
m_rxDCOffset(0),
m_txDCOffset(0),
m_serial(port, SERIAL_115200, protocol, address, true),
m_serial(0),
m_buffer(NULL),
m_length(0U),
m_offset(0U),
@ -166,9 +167,20 @@ m_hwType(HWT_UNKNOWN)
CModem::~CModem()
{
if(m_serial)
delete m_serial;
delete[] m_buffer;
}
void CModem::setSerialParams(const std::string& protocol, unsigned int address)
{
//Create the serial controller instance according the protocol specified in conf.
if(protocol == "i2c")
m_serial = new CIICController(m_port, SERIAL_115200, address, true);
else
m_serial = new CSerialController(m_port, SERIAL_115200, true);
}
void CModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency)
{
m_rxFrequency = rxFrequency + rxOffset;
@ -218,13 +230,13 @@ bool CModem::open()
{
::LogMessage("Opening the MMDVM");
bool ret = m_serial.open();
bool ret = m_serial->open();
if (!ret)
return false;
ret = readVersion();
if (!ret) {
m_serial.close();
m_serial->close();
return false;
} else {
/* Stopping the inactivity timer here when a firmware version has been
@ -234,13 +246,13 @@ bool CModem::open()
ret = setFrequency();
if (!ret) {
m_serial.close();
m_serial->close();
return false;
}
ret = setConfig();
if (!ret) {
m_serial.close();
m_serial->close();
return false;
}
@ -599,7 +611,7 @@ void CModem::clock(unsigned int ms)
break;
}
int ret = m_serial.write(m_buffer, len);
int ret = m_serial->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing D-Star data to the MMDVM");
@ -615,7 +627,7 @@ void CModem::clock(unsigned int ms)
if (m_trace)
CUtils::dump(1U, "TX DMR Data 1", m_buffer, len);
int ret = m_serial.write(m_buffer, len);
int ret = m_serial->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing DMR data to the MMDVM");
@ -632,7 +644,7 @@ void CModem::clock(unsigned int ms)
if (m_trace)
CUtils::dump(1U, "TX DMR Data 2", m_buffer, len);
int ret = m_serial.write(m_buffer, len);
int ret = m_serial->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing DMR data to the MMDVM");
@ -649,7 +661,7 @@ void CModem::clock(unsigned int ms)
if (m_trace)
CUtils::dump(1U, "TX YSF Data", m_buffer, len);
int ret = m_serial.write(m_buffer, len);
int ret = m_serial->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing YSF data to the MMDVM");
@ -670,7 +682,7 @@ void CModem::clock(unsigned int ms)
CUtils::dump(1U, "TX P25 LDU", m_buffer, len);
}
int ret = m_serial.write(m_buffer, len);
int ret = m_serial->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing P25 data to the MMDVM");
@ -687,7 +699,7 @@ void CModem::clock(unsigned int ms)
if (m_trace)
CUtils::dump(1U, "TX NXDN Data", m_buffer, len);
int ret = m_serial.write(m_buffer, len);
int ret = m_serial->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing NXDN data to the MMDVM");
@ -704,7 +716,7 @@ void CModem::clock(unsigned int ms)
if (m_trace)
CUtils::dump(1U, "TX POCSAG Data", m_buffer, len);
int ret = m_serial.write(m_buffer, len);
int ret = m_serial->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing POCSAG data to the MMDVM");
@ -721,7 +733,7 @@ void CModem::clock(unsigned int ms)
if (m_trace)
CUtils::dump(1U, "TX Transparent Data", m_buffer, len);
int ret = m_serial.write(m_buffer, len);
int ret = m_serial->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing Transparent data to the MMDVM");
}
@ -731,7 +743,7 @@ void CModem::close()
{
::LogMessage("Closing the MMDVM");
m_serial.close();
m_serial->close();
}
unsigned int CModem::readDStarData(unsigned char* data)
@ -1092,7 +1104,7 @@ bool CModem::writeSerial(const unsigned char* data, unsigned int length)
::memcpy(buffer + 3U, data, length);
int ret = m_serial.write(buffer, length + 3U);
int ret = m_serial->write(buffer, length + 3U);
return ret != int(length + 3U);
}
@ -1130,12 +1142,12 @@ bool CModem::readVersion()
// CUtils::dump(1U, "Written", buffer, 3U);
int ret = m_serial.write(buffer, 3U);
int ret = m_serial->write(buffer, 3U);
if (ret != 3)
return false;
#if defined(__APPLE__)
m_serial.setNonblock(true);
m_serial->setNonblock(true);
#endif
for (unsigned int count = 0U; count < MAX_RESPONSES; count++) {
@ -1182,7 +1194,7 @@ bool CModem::readStatus()
// CUtils::dump(1U, "Written", buffer, 3U);
return m_serial.write(buffer, 3U) == 3;
return m_serial->write(buffer, 3U) == 3;
}
bool CModem::setConfig()
@ -1253,7 +1265,7 @@ bool CModem::setConfig()
// CUtils::dump(1U, "Written", buffer, 21U);
int ret = m_serial.write(buffer, 21U);
int ret = m_serial->write(buffer, 21U);
if (ret != 21)
return false;
@ -1322,7 +1334,7 @@ bool CModem::setFrequency()
// CUtils::dump(1U, "Written", buffer, len);
int ret = m_serial.write(buffer, len);
int ret = m_serial->write(buffer, len);
if (ret != len)
return false;
@ -1355,7 +1367,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
{
if (m_offset == 0U) {
// Get the start of the frame or nothing at all
int ret = m_serial.read(m_buffer + 0U, 1U);
int ret = m_serial->read(m_buffer + 0U, 1U);
if (ret < 0) {
LogError("Error when reading from the modem");
return RTM_ERROR;
@ -1372,7 +1384,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
if (m_offset == 1U) {
// Get the length of the frame
int ret = m_serial.read(m_buffer + 1U, 1U);
int ret = m_serial->read(m_buffer + 1U, 1U);
if (ret < 0) {
LogError("Error when reading from the modem");
m_offset = 0U;
@ -1394,7 +1406,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
if (m_offset == 2U) {
// Get the frame type
int ret = m_serial.read(m_buffer + 2U, 1U);
int ret = m_serial->read(m_buffer + 2U, 1U);
if (ret < 0) {
LogError("Error when reading from the modem");
m_offset = 0U;
@ -1410,7 +1422,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
if (m_offset >= 3U) {
// Use later two byte length field
if (m_length == 0U) {
int ret = m_serial.read(m_buffer + 3U, 2U);
int ret = m_serial->read(m_buffer + 3U, 2U);
if (ret < 0) {
LogError("Error when reading from the modem");
m_offset = 0U;
@ -1425,7 +1437,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
}
while (m_offset < m_length) {
int ret = m_serial.read(m_buffer + m_offset, m_length - m_offset);
int ret = m_serial->read(m_buffer + m_offset, m_length - m_offset);
if (ret < 0) {
LogError("Error when reading from the modem");
m_offset = 0U;
@ -1463,7 +1475,7 @@ bool CModem::setMode(unsigned char mode)
// CUtils::dump(1U, "Written", buffer, 4U);
return m_serial.write(buffer, 4U) == 4;
return m_serial->write(buffer, 4U) == 4;
}
bool CModem::sendCWId(const std::string& callsign)
@ -1483,7 +1495,7 @@ bool CModem::sendCWId(const std::string& callsign)
// CUtils::dump(1U, "Written", buffer, length + 3U);
return m_serial.write(buffer, length + 3U) == int(length + 3U);
return m_serial->write(buffer, length + 3U) == int(length + 3U);
}
bool CModem::writeDMRStart(bool tx)
@ -1502,7 +1514,7 @@ bool CModem::writeDMRStart(bool tx)
// CUtils::dump(1U, "Written", buffer, 4U);
return m_serial.write(buffer, 4U) == 4;
return m_serial->write(buffer, 4U) == 4;
}
bool CModem::writeDMRAbort(unsigned int slotNo)
@ -1521,7 +1533,7 @@ bool CModem::writeDMRAbort(unsigned int slotNo)
// CUtils::dump(1U, "Written", buffer, 4U);
return m_serial.write(buffer, 4U) == 4;
return m_serial->write(buffer, 4U) == 4;
}
bool CModem::writeDMRShortLC(const unsigned char* lc)
@ -1545,7 +1557,7 @@ bool CModem::writeDMRShortLC(const unsigned char* lc)
// CUtils::dump(1U, "Written", buffer, 12U);
return m_serial.write(buffer, 12U) == 12;
return m_serial->write(buffer, 12U) == 12;
}
void CModem::printDebug()

View File

@ -34,9 +34,10 @@ enum RESP_TYPE_MMDVM {
class CModem {
public:
CModem(const std::string& port, const std::string& protocol, unsigned int address, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug);
CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug);
~CModem();
void setSerialParams(const std::string& protocol, unsigned int address);
void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency);
void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled);
void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagLevel);
@ -127,7 +128,7 @@ private:
bool m_pocsagEnabled;
int m_rxDCOffset;
int m_txDCOffset;
CSerialController m_serial;
CSerialController *m_serial;
unsigned char* m_buffer;
unsigned int m_length;
unsigned int m_offset;

View File

@ -43,11 +43,9 @@
#if defined(_WIN32) || defined(_WIN64)
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, const std::string& protocol, unsigned int address, bool assertRTS) :
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS) :
m_device(device),
m_speed(speed),
m_protocol(protocol),
m_address(address),
m_assertRTS(assertRTS),
m_handle(INVALID_HANDLE_VALUE)
{
@ -226,11 +224,9 @@ void CSerialController::close()
#else
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, const std::string& protocol, unsigned int address, bool assertRTS) :
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS) :
m_device(device),
m_speed(speed),
m_protocol(protocol),
m_address(address),
m_assertRTS(assertRTS),
m_fd(-1)
{
@ -245,27 +241,6 @@ bool CSerialController::open()
{
assert(m_fd == -1);
if (m_protocol == "i2c"){
#if !defined(__APPLE__)
m_fd = ::open(m_device.c_str(), O_RDWR);
if (m_fd < 0) {
LogError("Cannot open device - %s", m_device.c_str());
return false;
}
if (::ioctl(m_fd, I2C_TENBIT, 0) < 0) {
LogError("CI2C: failed to set 7bitaddress");
::close(m_fd);
return false;
}
if (::ioctl(m_fd, I2C_SLAVE, m_address) < 0) {
LogError("CI2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
::close(m_fd);
return false;
}
#endif
} else {
#if defined(__APPLE__)
m_fd = ::open(m_device.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); /*open in block mode under OSX*/
#else
@ -380,7 +355,6 @@ bool CSerialController::open()
#if defined(__APPLE__)
setNonblock(false);
#endif
}
return true;
}
@ -410,20 +384,6 @@ int CSerialController::read(unsigned char* buffer, unsigned int length)
unsigned int offset = 0U;
while (offset < length) {
if (m_protocol == "i2c"){
#if !defined(__APPLE__)
ssize_t n = ::read(m_fd, buffer + offset, 1U);
if (n < 0) {
if (errno != EAGAIN) {
LogError("Error returned from read(), errno=%d", errno);
return -1;
}
}
if (n > 0)
offset += n;
#endif
} else {
fd_set fds;
FD_ZERO(&fds);
@ -457,7 +417,6 @@ int CSerialController::read(unsigned char* buffer, unsigned int length)
if (len > 0)
offset += len;
}
}
}
return length;
@ -494,14 +453,8 @@ int CSerialController::write(const unsigned char* buffer, unsigned int length)
unsigned int ptr = 0U;
while (ptr < length) {
ssize_t n = 0U;
if (m_protocol == "i2c"){
#if !defined(__APPLE__)
n = ::write(m_fd, buffer + ptr, 1U);
#endif
} else {
if (canWrite())
n = ::write(m_fd, buffer + ptr, length - ptr);
}
if (n < 0) {
if (errno != EAGAIN) {
LogError("Error returned from write(), errno=%d", errno);

View File

@ -42,7 +42,7 @@ enum SERIAL_SPEED {
class CSerialController : public ISerialPort {
public:
CSerialController(const std::string& device, SERIAL_SPEED speed, const std::string& protocol = "uart", unsigned int address = 0x22U, bool assertRTS = false);
CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS = false);
virtual ~CSerialController();
virtual bool open();
@ -57,11 +57,9 @@ public:
virtual int setNonblock(bool nonblock);
#endif
private:
protected:
std::string m_device;
SERIAL_SPEED m_speed;
std::string m_protocol;
unsigned int m_address;
bool m_assertRTS;
#if defined(_WIN32) || defined(_WIN64)
HANDLE m_handle;