From d715470b1ce1e38bc5a2effb96a295accb586f60 Mon Sep 17 00:00:00 2001 From: Shawn Chain Date: Mon, 30 Jul 2018 21:58:35 +0800 Subject: [PATCH] Extract I2C logic from SerialController to separate class --- IICController.cpp | 166 +++++++++++++++++++++++++++++++++++++++++++ IICController.h | 40 +++++++++++ MMDVMHost.cpp | 3 +- Makefile | 2 +- Modem.cpp | 74 +++++++++++-------- Modem.h | 5 +- SerialController.cpp | 51 +------------ SerialController.h | 6 +- 8 files changed, 259 insertions(+), 88 deletions(-) create mode 100644 IICController.cpp create mode 100644 IICController.h diff --git a/IICController.cpp b/IICController.cpp new file mode 100644 index 0000000..6704bac --- /dev/null +++ b/IICController.cpp @@ -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 +#include + +#include + +#if defined(_WIN32) || defined(_WIN64) +#include +#include +#else +#include +#include +#include +#include +#include +#include +#if !defined(__APPLE__) +#include +#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 diff --git a/IICController.h b/IICController.h new file mode 100644 index 0000000..dc99b01 --- /dev/null +++ b/IICController.h @@ -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 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 7cf19e7..8c1ea20 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -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); diff --git a/Makefile b/Makefile index 8e05915..ebda8a1 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/Modem.cpp b/Modem.cpp index bb82e47..92fd56a 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -26,6 +26,7 @@ #include "Modem.h" #include "Utils.h" #include "Log.h" +#include "IICController.h" #include #include @@ -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() diff --git a/Modem.h b/Modem.h index a80250d..437b0f4 100644 --- a/Modem.h +++ b/Modem.h @@ -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; diff --git a/SerialController.cpp b/SerialController.cpp index 9d05c2b..83cc104 100644 --- a/SerialController.cpp +++ b/SerialController.cpp @@ -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); diff --git a/SerialController.h b/SerialController.h index 9ff0001..6dfc461 100644 --- a/SerialController.h +++ b/SerialController.h @@ -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;