From 7271ac0766c22e45579c1e1bfeaa9eefc00824c1 Mon Sep 17 00:00:00 2001 From: Rudy Hardeman Date: Sat, 7 May 2016 01:03:39 +0200 Subject: [PATCH] Initial version DMR works --- .gitignore | 2 + Conf.cpp | 33 +++++++- Conf.h | 9 +++ MMDVM.ini | 6 ++ MMDVMHost.cpp | 11 +++ Makefile.Pi.OLED | 25 ++++++ OLED.cpp | 201 +++++++++++++++++++++++++++++++++++++++++++++++ OLED.h | 111 ++++++++++++++++++++++++++ 8 files changed, 396 insertions(+), 2 deletions(-) create mode 100644 Makefile.Pi.OLED create mode 100644 OLED.cpp create mode 100644 OLED.h diff --git a/.gitignore b/.gitignore index bd2fceb..082aa4d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ Debug Release x64 +MMDVMHost +*.o *.opendb *.bak *.obj diff --git a/Conf.cpp b/Conf.cpp index 06fede0..12ee10f 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -41,7 +41,8 @@ enum SECTION { SECTION_FUSION_NETWORK, SECTION_TFTSERIAL, SECTION_HD44780, - SECTION_NEXTION + SECTION_NEXTION, + SECTION_OLED }; CConf::CConf(const std::string& file) : @@ -118,7 +119,10 @@ m_hd44780PWMBright(), m_hd44780PWMDim(), m_nextionSize("2.4"), m_nextionPort("/dev/ttyAMA0"), -m_nextionBrightness(50U) +m_nextionBrightness(50U), +m_oledType(3), +m_oledBrightness(0), +m_oledInvert(0) { } @@ -168,6 +172,8 @@ bool CConf::read() section = SECTION_HD44780; else if (::strncmp(buffer, "[Nextion]", 9U) == 0) section = SECTION_NEXTION; + else if (::strncmp(buffer, "[OLED]", 6U) == 0) + section = SECTION_OLED; else section = SECTION_NONE; @@ -373,7 +379,15 @@ bool CConf::read() m_nextionPort = value; else if (::strcmp(key, "Brightness") == 0) m_nextionBrightness = (unsigned int)::atoi(value); + } else if (section == SECTION_OLED) { + if (::strcmp(key, "Type") == 0) + m_oledType = (unsigned char)::atoi(value); + else if (::strcmp(key, "Port") == 0) + m_oledBrightness = (unsigned char)::atoi(value); + else if (::strcmp(key, "Brightness") == 0) + m_oledInvert = (unsigned char)::atoi(value); } + } ::fclose(fp); @@ -745,3 +759,18 @@ unsigned int CConf::getNextionBrightness() const { return m_nextionBrightness; } + +unsigned char CConf::getOLEDType() const +{ + return m_oledType; +} + +unsigned char CConf::getOLEDBrightness() const +{ + return m_oledBrightness; +} + +unsigned char CConf::getOLEDInvert() const +{ + return m_oledInvert; +} diff --git a/Conf.h b/Conf.h index 400440b..4ca0fb4 100644 --- a/Conf.h +++ b/Conf.h @@ -129,6 +129,11 @@ public: std::string getNextionPort() const; unsigned int getNextionBrightness() const; + // The OLED section + unsigned char getOLEDType() const; + unsigned char getOLEDBrightness() const; + unsigned char getOLEDInvert() const; + private: std::string m_file; std::string m_callsign; @@ -216,6 +221,10 @@ private: std::string m_nextionSize; std::string m_nextionPort; unsigned int m_nextionBrightness; + + unsigned char m_oledType; + unsigned char m_oledBrightness; + unsigned char m_oledInvert; }; #endif diff --git a/MMDVM.ini b/MMDVM.ini index 0151080..af9115a 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -102,3 +102,9 @@ PWMDim=16 Size=2.4 Port=/dev/ttyAMA0 Brightness=50 + +[OLED] +Type=3 +Brightness=0 +Invert=0 + diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index ee0fd0a..aac6021 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -32,6 +32,10 @@ #include "HD44780.h" #endif +#if defined(OLED) +#include "OLED.h" +#endif + #include #include @@ -747,6 +751,13 @@ void CMMDVMHost::createDisplay() m_display = new CHD44780(rows, columns, callsign, dmrid, pins, pwm, pwmPin, pwmBright, pwmDim, m_duplex); } +#endif +#if defined(OLED) + } else if (type == "OLED") { + unsigned char displayType = m_conf.getOLEDType(); + unsigned char displayBrightness = m_conf.getOLEDBrightness(); + unsigned char displayInvert = m_conf.getOLEDInvert(); + m_display = new COLED(displayType, displayBrightness, displayInvert); #endif } else { m_display = new CNullDisplay; diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED new file mode 100644 index 0000000..d894ce8 --- /dev/null +++ b/Makefile.Pi.OLED @@ -0,0 +1,25 @@ +# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed. + +CC = gcc +CXX = g++ +CFLAGS = -g -O3 -Wall -std=c++0x -DOLED -I/usr/local/include +LIBS = -lArduiPi_OLED +LDFLAGS = -g -L/usr/local/lib + +OBJECTS = \ + AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLookup.o DMRLC.o \ + DMRShortLC.o DMRSlot.o DMRSlotType.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o OLED.o Log.o MMDVMHost.o \ + Modem.o Nextion.o NullDisplay.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Timer.o UDPSocket.o Utils.o YSFControl.o \ + YSFConvolution.o YSFFICH.o YSFParrot.o YSFPayload.o + +all: MMDVMHost + +MMDVMHost: $(OBJECTS) + $(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost + +%.o: %.cpp + $(CXX) $(CFLAGS) -c -o $@ $< + +clean: + $(RM) MMDVMHost *.o *.d *.bak *~ + diff --git a/OLED.cpp b/OLED.cpp new file mode 100644 index 0000000..2fd85b1 --- /dev/null +++ b/OLED.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2016 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; 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 "OLED.h" + +COLED::COLED(unsigned char displayType, unsigned char displayBrightness, unsigned char displayInvert) : +m_displayType(displayType), +m_displayBrightness(displayBrightness), +m_displayInvert(displayInvert) +{ +} + +COLED::~COLED() +{ +} + +bool COLED::open() +{ + // SPI + if (display.oled_is_spi_proto(m_displayType)) + { + // SPI change parameters to fit to your LCD + if ( !display.init(OLED_SPI_DC,OLED_SPI_RESET,OLED_SPI_CS, m_displayType) ) + return false; + } + else + { + // I2C change parameters to fit to your LCD + if ( !display.init(OLED_I2C_RESET, m_displayType) ) + return false; + } + + display.begin(); + + display.invertDisplay(m_displayInvert); + if (m_displayBrightness > 0) + display.setBrightness(m_displayBrightness); + + // init done + display.clearDisplay(); // clears the screen buffer + display.display(); // display it (clear display) + + OLED_statusbar(); + display.setCursor(0,OLED_LINE1); + display.print("Startup"); + display.display(); + + return true; +} + +void COLED::setIdle() +{ + m_mode = MODE_IDLE; + + display.clearDisplay(); + OLED_statusbar(); + display.setCursor(0,display.height()/2); + display.setTextSize(3); + display.print("Idle"); + display.setTextSize(1); + display.display(); + display.startscrollright(0x02,0x0f); +} + +void COLED::setError(const char* text) +{ + m_mode = MODE_ERROR; + + display.clearDisplay(); + OLED_statusbar(); + display.setCursor(0,OLED_LINE1); + display.printf("%s\n", text); + display.display(); +} + +void COLED::setLockout() +{ + m_mode = MODE_LOCKOUT; + + display.clearDisplay(); + OLED_statusbar(); + display.setCursor(0,OLED_LINE1); + display.print("Lockout"); + display.display(); +} + +void COLED::writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) +{ + m_mode = MODE_DSTAR; +} + +void COLED::clearDStar() +{ + display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE1); + display.print("Listening"); + OLED_statusbar(); + display.display(); +} + +void COLED::writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) +{ + + if (m_mode != MODE_DMR) { + display.clearDisplay(); + m_mode = MODE_DMR; + if (slotNo == 1U) + { + display.fillRect(0, OLED_LINE3, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE3); + display.print("2 Listening"); + display.fillRect(0, OLED_LINE4, display.width(), 10, BLACK); + } + else + { + display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE1); + display.print("1 Listening"); + display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK); + } + } + + if (slotNo == 1U) { + display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE1); + display.printf("%i %s %s", slotNo, type, src.c_str()); + display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE2); + display.printf("%s%s", group ? "TG" : "", dst.c_str()); + } else { + display.fillRect(0, OLED_LINE3, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE3); + display.printf("%i %s %s", slotNo, type, src.c_str()); + display.fillRect(0, OLED_LINE4, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE4); + display.printf("%s%s", group ? "TG" : "", dst.c_str()); + } + OLED_statusbar(); + display.display(); +} + +void COLED::clearDMR(unsigned int slotNo) +{ + OLED_statusbar(); + if (slotNo == 1U) + { + display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE1); + display.print("1 Listening"); + display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK); + } + else + { + display.fillRect(0, OLED_LINE3, display.width(), 10, BLACK); + display.setCursor(0,OLED_LINE3); + display.print("2 Listening"); + display.fillRect(0, OLED_LINE4, display.width(), 10, BLACK); + } + display.display(); +} + +void COLED::writeFusion(const char* source, const char* dest) +{ + m_mode = MODE_YSF; +} + +void COLED::clearFusion() +{ +} + +void COLED::close() +{ + display.close(); +} + +void COLED::OLED_statusbar() +{ + display.stopscroll(); + display.fillRect(0, 0, display.width(), 16, BLACK); + display.setTextColor(WHITE); + display.setCursor(0,0); + if (m_mode == MODE_DMR) + display.drawBitmap(0, 0, logo_dmr_bmp, 48, 16, WHITE); + else + display.drawBitmap(0, 0, logo_glcd_bmp, 16, 15, WHITE); +} diff --git a/OLED.h b/OLED.h new file mode 100644 index 0000000..7c98c00 --- /dev/null +++ b/OLED.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2016 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; 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. + */ + +#if !defined(OLED_H) +#define OLED_H + +#define OLED_STATUSBAR 0 +#define OLED_LINE1 16 +#define OLED_LINE2 26 +#define OLED_LINE3 36 +#define OLED_LINE4 46 + +#include "Display.h" +#include "Defines.h" + +#include + +#include "ArduiPi_OLED_lib.h" +#include "Adafruit_GFX.h" +#include "ArduiPi_OLED.h" + +static unsigned char logo_glcd_bmp[] = + { 0b00101011, 0b11010100, + 0b01010111, 0b11101010, + 0b01010111, 0b11101010, + 0b00101011, 0b11010100, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000001, 0b10000000, + 0b00000000, 0b00000000 }; +//DMR 48x16 px +static unsigned char logo_dmr_bmp[] = + { 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, + 0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001, + 0b10111111, 0b11111000, 0b01111000, 0b00011110, 0b01111111, 0b11100001, + 0b10111111, 0b11111110, 0b01111100, 0b00111110, 0b01100000, 0b00011001, + 0b10110000, 0b00001110, 0b01100110, 0b01100110, 0b01100000, 0b00011001, + 0b10110000, 0b00000110, 0b01100011, 0b11000110, 0b01100000, 0b00011001, + 0b10110000, 0b00000110, 0b01100001, 0b10000110, 0b01100000, 0b00011001, + 0b10110000, 0b00000110, 0b01100000, 0b00000110, 0b01111111, 0b11111001, + 0b10110000, 0b00000110, 0b01100000, 0b00000110, 0b01111000, 0b00000001, + 0b10110000, 0b00000110, 0b01100000, 0b00000110, 0b01101100, 0b00000001, + 0b10110000, 0b00000110, 0b01100000, 0b00000110, 0b01100110, 0b00000001, + 0b10110000, 0b00001110, 0b01100000, 0b00000110, 0b01100011, 0b00000001, + 0b10111111, 0b11111110, 0b01100000, 0b00000110, 0b01100001, 0b10000001, + 0b10011111, 0b11111000, 0b01100000, 0b00000110, 0b01100000, 0b11000001, + 0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001, + 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111 + }; + +class COLED : public IDisplay +{ +public: + COLED(unsigned char displayType, unsigned char displayBrighness, unsigned char displayInvert); + virtual ~COLED(); + + virtual bool open(); + + virtual void setIdle(); + + virtual void setError(const char* text); + virtual void setLockout(); + + virtual void writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector); + virtual void clearDStar(); + + virtual void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); + virtual void clearDMR(unsigned int slotNo); + + virtual void writeFusion(const char* source, const char* dest); + virtual void clearFusion(); + + virtual void close(); + +private: + const char* m_slot1_state; + const char* m_slot2_state; + unsigned char m_mode; + unsigned char m_displayType; + unsigned char m_displayBrightness; + unsigned char m_displayInvert; + + + ArduiPi_OLED display; + void OLED_statusbar(); +}; + +#endif