From 897d14a54e6c87d510bafb80831ba409d002608e Mon Sep 17 00:00:00 2001 From: Bengt Martensson Date: Sun, 14 Feb 2021 13:48:04 +0100 Subject: [PATCH] More work on refactored command parsing, Resolves #55. Resolves # 56. Some work on preparing named commands, #37. Remove all uses of String (except some examples). --- Makefile | 9 +- examples/Girs/Girs.cpp | 89 ++- examples/Girs/Girs.cpp.fumble | 868 ----------------------- examples/Girs/Girs.cpp.fummel | 985 --------------------------- src/GirsLib/IrNamedRemoteSet.h | 29 + src/GirsLib/LedLcdManager.cpp | 3 +- src/GirsLib/LedLcdManager.cpp.fummel | 225 ------ src/GirsLib/LedLcdManager.h | 6 +- src/GirsLib/LedLcdManager.h.fummel | 180 ----- src/GirsLib/StreamParser.cpp | 51 +- src/GirsLib/StreamParser.h | 15 +- src/GirsLib/Tokenizer.cpp | 100 --- src/GirsLib/Tokenizer.h | 27 - 13 files changed, 141 insertions(+), 2446 deletions(-) delete mode 100644 examples/Girs/Girs.cpp.fumble delete mode 100644 examples/Girs/Girs.cpp.fummel create mode 100644 src/GirsLib/IrNamedRemoteSet.h delete mode 100644 src/GirsLib/LedLcdManager.cpp.fummel delete mode 100644 src/GirsLib/LedLcdManager.h.fummel delete mode 100644 src/GirsLib/Tokenizer.cpp delete mode 100644 src/GirsLib/Tokenizer.h diff --git a/Makefile b/Makefile index ee2cee4..e2c2a99 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,8 @@ BOARD=nano # sources are located. Only used for SIL test. INFRARED4ARDUINO_DIR=../Infrared4Arduino +INCLUDES=-I$(INFRARED4ARDUINO_DIR)/src -Isrc + # Get VERSION from the version in library.properties VERSION=$(subst version=,,$(shell grep version= library.properties)) ORIGINURL=$(shell git remote get-url origin) @@ -70,7 +72,12 @@ VPATH=src src/GirsLib examples/Girs #.PRECIOUS: test1 # TODO: compile Girs.o separately, in tests/Girs -OBJS=Girs.o GirsUtils.o LedLcdManager.o Tokenizer.o LiquidCrystal_I2C_bm.o +OBJS=\ +Girs.o \ +GirsUtils.o \ +LedLcdManager.o \ +LiquidCrystal_I2C_bm.o \ +StreamParser.o libGirs.a: $(OBJS) $(AR) rs $@ $(OBJS) diff --git a/examples/Girs/Girs.cpp b/examples/Girs/Girs.cpp index aa63611..d347bd7 100644 --- a/examples/Girs/Girs.cpp +++ b/examples/Girs/Girs.cpp @@ -76,6 +76,7 @@ this program. If not, see http://www.gnu.org/licenses/. #ifdef NAMED_COMMANDS #error NAMED_COMMANDS is presently not supported +#include "GirsLib/IrNamedRemoteSet.h" #endif #ifdef BEACON @@ -254,7 +255,7 @@ static bool receive(StreamParser& parser) { irReceiver->setEndingTimeout(receiveEndingTimeout); irReceiver->setBeginningTimeout(beginTimeout); irReceiver->setMarkExcess(IRRECEIVER_MARK_EXCESS); - //Stream& stream = parser.getStream(); + Stream& stream = parser.getStream(); #ifdef ARDUINO flushIn(parser.getStream()); #endif @@ -322,14 +323,14 @@ static bool capture(Stream& stream) { //#include "my_named_remotes.inc" extern const IrNamedRemoteSet remoteSet; -static bool sendNamedCommand(Stream& stream, String& remoteName, String& commandName, unsigned int noSends) { - const IrNamedRemote* remote = remoteSet.getIrNamedRemote(remoteName.c_str()); +static bool sendNamedCommand(Stream& stream, const char* remoteName, const char* commandName, unsigned int noSends) { + const IrNamedRemote* remote = remoteSet.getIrNamedRemote(remoteName); if (remote == nullptr) { stream.println(F("No such remote")); return false; } - const IrNamedCommand* command = remote->getIrNamedCommand(commandName.c_str()); + const IrNamedCommand* command = remote->getIrNamedCommand(commandName); if (command == nullptr) { stream.println(F("No such command")); return false; @@ -340,20 +341,20 @@ static bool sendNamedCommand(Stream& stream, String& remoteName, String& command return status; } -static void dumpRemote(Stream& stream, String& name) { - if (name.length() == 0) { - for (unsigned int i = 0; i < remoteSet.getNoIrNamedRemotes(); i++) { - stream.print(remoteSet.getIrNamedRemotes()[i]->getName()); +static void dumpRemote(Stream& stream, const char* name) { + if (name[0] != '\0') { + for (IrNamedRemote remote : remoteSet) { + stream.print(remote.getName()); stream.print(" "); } stream.println(); } else { - const IrNamedRemote* remote = remoteSet.getIrNamedRemote(name.c_str()); + const IrNamedRemote* remote = remoteSet.getIrNamedRemote(name); if (remote == nullptr) stream.println(F("No such remote")); else { - for (unsigned int i = 0; i < remote->getNoCommands(); i++) { - stream.print(remote->getAllCommands()[i]->getName()); + for (IrNamedCommand command : *remote) { + stream.print(command.getName()); stream.print(" "); } stream.println(); @@ -457,23 +458,22 @@ void info(Stream& stream) { } #endif -//static inline bool isPrefix(const String& cmd, const char *string) { -// return strncmp(cmd.c_str(), string, cmd.length()) == 0; -//} - +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" static bool isPrefix(const char *string, const char* cmd) { return strncmp(cmd, string, strlen(string)) == 0; } #ifdef ARDUINO bool isPrefix(const char* cmd, const __FlashStringHelper *pstring) { - return strncmp_PF(cmd, reinterpret_cast(pstring), strlen(cmd)) == 0; + return strncmp_PF(cmd, STRCPY_PF_CAST(reinterpret_cast(pstring)), strlen(cmd)) == 0; } bool isPrefix(const __FlashStringHelper *pstring, const char* cmd) { - return strncmp_PF(cmd, reinterpret_cast(pstring), strlen_PF(reinterpret_cast(pstring))) == 0; + return strncmp_PF(cmd, STRCPY_PF_CAST(reinterpret_cast(pstring)), strlen_PF(STRCPY_PF_CAST(reinterpret_cast(pstring)))) == 0; } #endif +#pragma GCC diagnostic pop static void readCommand(char* cmd, size_t cmdLength, StreamParser& parser) { #if defined(COMMANDLED) & defined(LED) @@ -488,21 +488,6 @@ static void readCommand(char* cmd, size_t cmdLength, StreamParser& parser) { parser.parseWord(cmd, cmdLength); -//#else -// LedLcdManager::checkTurnoff(); -// static char str[1000]; -// parser.getLine(str, 1000); -// if (std::cin.eof()) { -// std::cout << "Bye!" << std::endl; -// exit(0); -// } -// char *s = str; -// while (isspace(*s)) -// s++; -// while (isspace(s[strlen(s)-1])) -// s[strlen(s)-1] = '\0'; -// String line(s); -//#endif #if defined(DEBUG_CMD) LedLcdManager::lcdPrint(cmd, true, 0, 0); @@ -678,15 +663,18 @@ static bool processCommand(const char* cmd, StreamParser& parser) { #ifdef NAMED_COMMANDS if (cmd[0] == 'n') { uint16_t noSends = static_cast(parser.parseAbsInt()); - String remoteName = tokenizer.getToken(); - String commandName = tokenizer.getToken(); + char remoteName[cmdLength]; + parser.parseWord(remoteName, cmdLength); + char commandName[cmdLength]; + parser.parseWord(commandName, cmdLength); bool success = sendNamedCommand(stream, remoteName, commandName, noSends); if (success) stream.println(okString); } else if (isPrefix(cmd, "remote")) { - String name = tokenizer.getToken(); + char name[cmdLength]; + parser.parseWord(name, cmdLength); dumpRemote(stream, name); } else #endif @@ -748,16 +736,26 @@ static bool processCommand(const char* cmd, StreamParser& parser) { parser.parseWord(protocol, buflen); const IrSignal *irSignal = nullptr; if (isPrefix(protocol, F("nec1"))) { - unsigned int D = static_cast(parser.parseAbsInt()); - unsigned int S = static_cast(parser.parseAbsInt()); - unsigned int F = static_cast(parser.parseAbsInt()); - irSignal = (F == StreamParser::invalid) - ? Nec1Renderer::newIrSignal(D, S) - : Nec1Renderer::newIrSignal(D, S, F); + int D = static_cast(parser.parseAbsInt()); + int second = static_cast(parser.parseAbsInt()); + int third = static_cast(parser.parseAbsIntDefault(StreamParser::invalid)); + parser.flushLine(); + stream.println("NEC1 "); + stream.println(D); + stream.println(second); + stream.println(third); + irSignal = (third == StreamParser::invalid) + ? Nec1Renderer::newIrSignal(D, second) + : Nec1Renderer::newIrSignal(D, second, third); } else if (isPrefix(protocol, F("rc5"))) { - unsigned int D = static_cast(parser.parseAbsInt()); - unsigned int F = static_cast(parser.parseAbsInt()); - unsigned int T = static_cast(parser.parseAbsInt()); + int D = static_cast(parser.parseAbsInt()); + int F = static_cast(parser.parseAbsInt()); + int T = static_cast(parser.parseAbsIntDefault(StreamParser::invalid)); + parser.flushLine(); + stream.println("RC5 "); + stream.println(D); + stream.println(F); + stream.println(T); irSignal = (T == StreamParser::invalid) ? Rc5Renderer::newIrSignal(D, F) : Rc5Renderer::newIrSignal(D, F, T); @@ -818,7 +816,8 @@ static bool readProcessOneCommand( //parser.parseWord(cmd, cmdLength); readCommand(cmd, cmdLength, parser); #ifdef SERIAL_DEBUG - Serial.println("Command: " + cmd); + Serial.print(F("Command: ")); + Serial.println(cmd); delay(1000); #endif return processCommand(cmd, parser); diff --git a/examples/Girs/Girs.cpp.fumble b/examples/Girs/Girs.cpp.fumble deleted file mode 100644 index 7aef91b..0000000 --- a/examples/Girs/Girs.cpp.fumble +++ /dev/null @@ -1,868 +0,0 @@ -/* -Copyright (C) 2014,2015,2017 Bengt Martensson. - -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, see http://www.gnu.org/licenses/. -*/ - -#include "config.h" -#include "GirsLib/LedLcdManager.h" -#include "GirsLib/GirsUtils.h" -#ifdef ARDUINO -#include -#else -#define PROGMEM -#endif - -// Conditional includes -#if defined(ETHERNET) & !defined(ARDUINO) -#error not supported -#endif - -#ifdef ETHERNET -#include -#include -#endif // ETHERNET - -#ifdef LCD -#include -#endif - -#ifdef RECEIVE -#include -#endif - -#ifdef TRANSMIT -#include -#endif -#if defined(RECEIVE) -#include -#endif - -#ifdef CAPTURE -#include -#endif - -#ifdef NON_MOD -#include -#endif - -#ifdef DECODER -#ifndef RECEIVE -#error DECODER without RECEIVE is nonsensical, aborting. -#endif -#include -#endif - -#ifdef RENDERER -#ifndef TRANSMIT -#error RENDER without TRANSMIT is nonsensical, aborting. -#endif -#include -#include -#include -#endif - -#ifdef NAMED_COMMANDS -#error NAMED_COMMANDS is presently not supported -#endif - -#ifdef BEACON -#include -#endif - -#ifdef PRONTO -#include -#endif - -#ifdef ARDUINO -#else -#include // for strlen -#endif - -#if defined(CONFIGURABLE_LEDS) & (! defined(PARAMETERS) | !defined(LED)) -#error CONFIGURABLE_LEDS defined but not PARAMETERS and LED, aborting. -#endif - -#ifdef CONFIGURABLE_LEDS -#define LED_PARAMETER_CONST -#else -#define LED_PARAMETER_CONST const -#endif - -#ifdef PARAMETERS -#define PARAMETERS_NAME Parameters -#define PARAMETER_CONST -#else -#define PARAMETERS_NAME -#define PARAMETER_CONST const -#endif - -#ifdef LED -#ifdef TRANSMITLED -static LED_PARAMETER_CONST led_t transmitled = TRANSMITLED; -#endif - -#ifdef RECEIVELED -static LED_PARAMETER_CONST led_t receiveled = RECEIVELED; -#endif - -#ifdef CAPTURELED -static LED_PARAMETER_CONST led_t captureled = CAPTURELED; -#endif - -#ifdef COMMANDLED -static LED_PARAMETER_CONST led_t commandled = COMMANDLED; -#endif -#endif // LED - -#ifdef CAPTURE -static PARAMETER_CONST unsigned long captureEndingTimeout = DEFAULT_CAPTURE_ENDINGTIMEOUT; // milliseconds -static const unsigned sensorNo = 1; // presently, only one supported -#endif -#ifdef RECEIVE -static PARAMETER_CONST unsigned long receiveEndingTimeout = DEFAULT_RECEIVE_ENDINGTIMEOUT; // milliseconds -#endif -#if defined(RECEIVE) | defined(CAPTURE) -static PARAMETER_CONST unsigned long beginTimeout = DEFAULT_BEGINTIMEOUT; // milliseconds -static PARAMETER_CONST uint16_t captureSize = DEFAULT_CAPTURESIZE; -#endif - -#ifdef RECEIVE -#ifdef IRRECEIVER_2_PIN -static PARAMETER_CONST uint8_t receiverNo = 1; -#else -static const uint8_t receiverNo = 1; -#endif -#endif - -#ifdef ETHERNET -EthernetServer server(PORT); -#endif // ETHERNET - -#ifdef RESET -bool reset = false; -#endif - -#define modulesSupported EXPAND_AND_QUOTE(Base TRANSMIT_NAME CAPTURE_NAME RENDERER_NAME RECEIVE_NAME DECODER_NAME LED_NAME LCD_NAME PARAMETERS_NAME NAMED_COMMANDS_NAME PRONTO_NAME) -#ifndef PROGNAME -#define PROGNAME "AGirs" -#endif -#ifndef VERSION -#include "GirsLib/version.h" -#endif // VERSION -#define okString "OK" -#define errorString "ERROR" -#define timeoutString "." - -#ifdef TRANSMIT - -static bool sendIrSignal(const IrSignal &irSignal, unsigned int noSends=1) { - if (noSends == 0) - return false; -#ifdef TRANSMITLED - LedLcdManager::setLogicLed(transmitled, LedLcdManager::on); -#endif - IrSender *irSender = -#ifdef NON_MOD - (irSignal.getFrequency() == 0) ? (IrSender*) new IrSenderNonMod(NON_MOD_PIN) : -#endif - (IrSender*) IrSenderPwm::getInstance(true); - - irSender->sendIrSignal(irSignal, noSends); - -#ifdef NON_MOD - if (irSignal.getFrequency() == 0) - delete irSender; - else -#endif - IrSenderPwm::deleteInstance(); - -#ifdef TRANSMITLED - LedLcdManager::setLogicLed(transmitled, LedLcdManager::off); -#endif - return true; -} - -#endif // TRANSMIT - -# if defined(RECEIVE) | defined(CAPTURE) -static void flushIn(Stream &stream UNUSED) { -#ifdef ARDUINO - while (stream.available()) - stream.read(); -#endif -} -#endif - -#ifdef RECEIVE - -static void decodeOrDump(IrReader *irReader, Stream& stream) { -#ifdef DECODER - MultiDecoder multiDecoder(*irReader); -#ifdef LCD - if (multiDecoder.getType() > MultiDecoder::noise) { - LedLcdManager::lcdPrint(multiDecoder.getType() == MultiDecoder::nec_ditto - ? "." : multiDecoder.getDecode(), - multiDecoder.getType() != MultiDecoder::nec_ditto); - if (multiDecoder.getType() == MultiDecoder::nec) - LedLcdManager::lcdSetCursor(0, 1); // prepare for dittos - } -#endif - -#ifdef DECODELED - LedLcdManager::setLogicLed(DECODELED(multiDecoder.getType()), LedLcdManager::blink); -#endif -#endif - -#if defined(DECODER) & ! defined(DONT_REPORT_DECODES) // lircd does its own decoding - switch (multiDecoder.getType()) { - case MultiDecoder::noise: - // ignore - break; - case MultiDecoder::undecoded: - irReader->dump(stream); // report data of undecoded signals - break; - default: - stream.println(multiDecoder.getDecode()); // also for timeout - break; - } -#else // ! (defined(DECODER) & ! defined(DONT_REPORT_DECODES)) - if (irReader->isEmpty()) - stream.println(F(timeoutString)); - else - irReader->dump(stream); -#endif // !DECODER -} - -static bool receive(Stream& stream) { - IrReceiverSampler *irReceiver = IrReceiverSampler::getInstance(); - if (irReceiver == NULL) - irReceiver = IrReceiverSampler::newIrReceiverSampler(captureSize, - GirsUtils::receiverPin(receiverNo), GirsUtils::receiverPullup(receiverNo)); - if (irReceiver == NULL) - return false; - irReceiver->setEndingTimeout(receiveEndingTimeout); - irReceiver->setBeginningTimeout(beginTimeout); - irReceiver->setMarkExcess(IRRECEIVER_MARK_EXCESS); - flushIn(stream); -#ifdef RECEIVELED - LedLcdManager::setLogicLed(receiveled, LedLcdManager::on); -#endif - irReceiver->enable(); -#ifdef ARDUINO - while (!irReceiver->isReady() && stream.available() == 0) -#else - std::cout << "** Simulating timeout **" << std::endl; - delay(beginTimeout); -#endif - LedLcdManager::checkTurnoff(); - bool ready = irReceiver->isReady(); - irReceiver->disable(); -#ifdef RECEIVELED - LedLcdManager::setLogicLed(receiveled, LedLcdManager::off); -#endif - if (ready) - decodeOrDump(irReceiver, stream); - IrReceiverSampler::deleteInstance(); - return true; -} -#endif // RECEIVE - -#ifdef CAPTURE - -static bool capture(Stream& stream) { - IrWidget *irWidget = IrWidgetAggregating::newIrWidgetAggregating(captureSize, - GirsUtils::sensorPullup(sensorNo)); - if (irWidget == NULL) - stream.println(F("This cannot happen")); - irWidget->setEndingTimeout(captureEndingTimeout); - irWidget->setBeginningTimeout(beginTimeout); - irWidget->setMarkExcess(IRSENSOR_MARK_EXCESS); - irWidget->reset(); -#ifdef CAPTURELED - LedLcdManager::setLogicLed(captureled, LedLcdManager::on); -#endif - flushIn(stream); -#ifdef ARDUINO - irWidget->capture(); -#else - std::cout << "** Simulating timeout **" << std::endl; - delay(beginTimeout); -#endif - -#ifdef CAPTURELED - LedLcdManager::setLogicLed(captureled, LedLcdManager::off); -#endif - if (!irWidget->isEmpty()) { - // Trying to decode the capture does not make sense, - // that is what "receive" is for. - irWidget->dump(stream); - } else - stream.println(F(timeoutString)); - IrWidgetAggregating::deleteInstance(); - return true; -} -#endif // CAPTURE - -#ifdef NAMED_COMMANDS -// Defines a const IrNamedRemoteSet remoteSet with commands to be used. -//#include "my_named_remotes.inc" -extern const IrNamedRemoteSet remoteSet; - -static bool sendNamedCommand(Stream& stream, String& remoteName, String& commandName, unsigned int noSends) { - const IrNamedRemote* remote = remoteSet.getIrNamedRemote(remoteName.c_str()); - if (remote == NULL) { - stream.println(F("No such remote")); - return false; - } - - const IrNamedCommand* command = remote->getIrNamedCommand(commandName.c_str()); - if (command == NULL) { - stream.println(F("No such command")); - return false; - } - const IrSignal *irSignal = command->getIrSignal(); - bool status = sendIrSignal(*irSignal, noSends); // waits, blinks - delete irSignal; - return status; -} - -static void dumpRemote(Stream& stream, String& name) { - if (name.length() == 0) { - for (unsigned int i = 0; i < remoteSet.getNoIrNamedRemotes(); i++) { - stream.print(remoteSet.getIrNamedRemotes()[i]->getName()); - stream.print(" "); - } - stream.println(); - } else { - const IrNamedRemote* remote = remoteSet.getIrNamedRemote(name.c_str()); - if (remote == NULL) - stream.println(F("No such remote")); - else { - for (unsigned int i = 0; i < remote->getNoCommands(); i++) { - stream.print(remote->getAllCommands()[i]->getName()); - stream.print(" "); - } - stream.println(); - } - } -} -#endif - -void setup() { - LedLcdManager::setupLedGroundPins(); - GirsUtils::setupReceivers(); - GirsUtils::setupSensors(); -#if defined(TRANSMIT) - // Make sure that sender is quiet (if reset or such) - IrSenderPwm::getInstance(true)->mute(); -#endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - LedLcdManager::setup(LCD_I2C_ADDRESS, LCD_WIDTH, LCD_HEIGHT, - (const pin_t[]) {SIGNAL_LED_1, SIGNAL_LED_2, SIGNAL_LED_3, SIGNAL_LED_4, - SIGNAL_LED_5, SIGNAL_LED_6, SIGNAL_LED_7, SIGNAL_LED_8 }); - LedLcdManager::selfTest(PROGNAME "\n" VERSION); -#pragma GCC diagnostic pop -#ifdef LED - LedLcdManager::setupShouldTimeout(transmitled, false); - LedLcdManager::setupShouldTimeout(receiveled, false); - LedLcdManager::setupShouldTimeout(captureled, false); - LedLcdManager::setupShouldTimeout(commandled, false); -#endif -#ifdef LCD -#ifdef ETHERNET - LedLcdManager::lcdPrint("TCP", false, 0, 2); -#ifdef SERIAL_DEBUG - LedLcdManager::lcdPrint(",SerialDbg", false); -#endif -#else // ! ETHERNET - LedLcdManager::lcdPrint(F("Serial"), false, 0, 2); -#endif // ! ETHERNET -#endif // LCD - -#ifdef ETHERNET -#ifdef SDCARD_ON_ETHERSHIELD_PIN - // disable the SD card, as recommended in the doc - pinMode(SDCARD_ON_ETHERSHIELD_PIN, OUTPUT); - digitalWrite(SDCARD_ON_ETHERSHIELD_PIN, LOW); -#endif - byte mac[] = { MACADDRESS }; -#ifdef DHCP - Ethernet.begin(mac); -#else // !DHCP - Ethernet.begin(mac, IPAddress(IPADDRESS), IPAddress(DNSSERVER), IPAddress(GATEWAY), IPAddress(SUBNETMASK)); -#endif // !DHCP - char ipstring[16]; - sprintf(ipstring, "%d.%d.%d.%d", Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]); - LedLcdManager::lcdPrint(ipstring, false, 0, 3); - -#ifdef BEACON - Beacon::setup(PROGNAME, "DE-AD-BE-EF-FE-ED", "Utility", "www.harctoolbox.org", - "", "", "", "http://arduino/nosuchfile.html"); -#endif - - server.begin(); - -#endif // ETHERNET - -#if defined(ARDUINO) & !defined(ETHERNET) | defined(SERIAL_DEBUG) - - Serial.begin(SERIALBAUD); -#if defined(ARDUINO_AVR_LEONARDO) | defined(ARDUINO_AVR_MICRO) - while (!Serial) - ; // wait for serial port to connect. "Needed for Leonardo only" -#endif - Serial.println(F(PROGNAME " " VERSION)); - Serial.setTimeout(SERIALTIMEOUT); - -#ifdef ETHERNET - Serial.println(Ethernet.localIP()); -#endif -#endif // defined(ARDUINO) & !defined(ETHERNET) | defined(SERIAL_DEBUG) -} - -#ifdef INFO -void info(Stream& stream) { - stream.print("Board: "); -#ifdef ARDUINO_AVR_MEGA2560 - stream.print(F("Arduino Mega2560")); -#elif defined(ARDUINO_AVR_NANO) - stream.print(F("Arduino Nano")); -#elif defined(ARDUINO_AVR_LEONARDO) - stream.print(F("Arduino Leonardo")); -#elif defined(ARDUINO_AVR_MINI) - stream.print(F("Arduino Leonardo")); -#elif defined(ARDUINO_AVR_UNO) - stream.print(F("Arduino Uno")); -#else - stream.print(F("Unknown")); -#endif - - stream.print(F(", CPU frequency: " EXPAND_AND_QUOTE(F_CPU))); - - stream.println(); -} -#endif - -static inline bool isPrefix(const String& cmd, const char *string) { - return strncmp(cmd.c_str(), string, cmd.length()) == 0; -} - -static inline bool isPrefix(const char *string, const String& cmd) { - return strncmp(cmd.c_str(), string, strlen(string)) == 0; -} - -#ifdef ARDUINO -bool isPrefix(const String& cmd, const __FlashStringHelper *pstring) { - return strncmp_PF(cmd.c_str(), (uint_farptr_t) pstring, cmd.length()) == 0; -} - -bool isPrefix(const __FlashStringHelper *pstring, const String& cmd) { - return strncmp_PF(cmd.c_str(), (uint_farptr_t) pstring, strlen_PF((uint_farptr_t) pstring)) == 0; -} -#endif - -static String readCommand(Stream& stream) { -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::on); -#endif - -#ifdef ARDUINO - //flushIn(stream); - while (stream.available() == 0) { - LedLcdManager::checkTurnoff(); - } - - String line = stream.readStringUntil(EOLCHAR); - line.trim(); -#else - (void) stream; - LedLcdManager::checkTurnoff(); - static char str[1000]; - std::cin.getline(str, 1000); - if (std::cin.eof()) { - std::cout << "Bye!" << std::endl; - exit(0); - } - char *s = str; - while (isspace(*s)) - s++; - while (isspace(s[strlen(s)-1])) - s[strlen(s)-1] = '\0'; - String line(s); -#endif - -#if defined(DEBUG_CMD) - LedLcdManager::lcdPrint(line.c_str(), true, 0, 0); -#endif -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::off); -#endif - return line; -} - -static bool processCommand(const String& line, Stream& stream) { -#ifdef ETHERNET - bool quit = false; -#endif - Tokenizer tokenizer(line); - String cmd = tokenizer.getToken(); - - // Decode command - if (cmd.length() == 0) { - // empty command, do nothing - stream.println(F(okString)); - } else - -#ifdef CAPTURE - if (cmd[0] == 'a' || cmd[0] == 'c') { - capture(stream); - } else -#endif // CAPTURE - -#ifdef LCD - if (isPrefix(cmd, F("lcd"))) { //LCD - String rest = tokenizer.getRest(); - LedLcdManager::lcdPrint(rest.c_str()); - stream.println(F(okString)); - } else -#endif // LCD - -#ifdef LED - if (isPrefix(cmd, F("led"))) { - pin_t no = (pin_t) tokenizer.getInt(); - String value = tokenizer.getToken(); - bool success = LedLcdManager::setLogicLed(no, value.c_str()); - stream.println(success ? F(okString) : F(errorString)); - } else -#endif // LED - - if (isPrefix(cmd, F("modules"))) { - stream.println(F(modulesSupported)); - } else - -#ifdef FREEMEM - if (isPrefix(cmd, F("memory"))) { - stream.println(GirsUtils::freeRam()); - } else -#endif - -#ifdef INFO - if (isPrefix(cmd, F("info"))) { - info(stream); - } else -#endif - -#ifdef PARAMETERS - if (cmd[0] == 'p') { // parameter - String variableName = tokenizer.getToken(); - long value = tokenizer.getInt(); - unsigned long *variable32 = NULL; - uint16_t *variable16 = NULL; - uint8_t *variable8 = NULL; -#if defined(RECEIVE) || defined(CAPTURE) - if (isPrefix(F("beg"), variableName)) - variable32 = &beginTimeout; - else -#endif -#ifdef CAPTURE - if (isPrefix(F("capturee"), variableName)) - variable32 = &captureEndingTimeout; -#endif -#ifdef RECEIVE - if (isPrefix(F("receivee"), variableName)) - variable32 = &receiveEndingTimeout; - else -#endif -#if defined(RECEIVE) & defined(IRRECEIVER_2_PIN) - if (isPrefix(variableName, F("receiver"))) - variable8 = &receiverNo; - else -#endif -#ifdef CAPTURE - if (isPrefix(F("captures"), variableName)) { - // TODO: check evenness of value - variable16 = &captureSize; - } else -#endif -#ifdef LED -#ifdef CONFIGURABLE_LEDS -#ifdef TRANSMITLED - if (isPrefix(F("transmitl"), variableName)) - variable8 = &transmitled; - else -#endif -#ifdef CAPTURELED - if (isPrefix(F("capturel"), variableName)) - variable8 = &captureled; - else -#endif -#ifdef RECEIVELED - if (isPrefix(F("receivel"), variableName)) - variable8 = &receiveled; - else -#endif -#ifdef COMMANDLED - if (isPrefix(F("commandl"), variableName)) - variable8 = &commandled; - else -#endif -#endif - // TODO: handle blinkTime. This currently means either break encapsulation - // of LedLcdManager, or write a nasty special case :-~ -#endif - { - } - - if (variable32 != NULL) { - if (value != Tokenizer::invalid) - *variable32 = value; - - GirsUtils::printVariable(stream, variableName.c_str(), *variable32); - } else if (variable16 != NULL) { - if (value != Tokenizer::invalid) - *variable16 = (uint16_t) value; - - GirsUtils::printVariable(stream, variableName.c_str(), *variable16); - } else if (variable8 != NULL) { - if (value != Tokenizer::invalid) - *variable8 = (uint8_t) value; - - GirsUtils::printVariable(stream, variableName.c_str(), *variable8); - } else - stream.println(F("No such variable")); - } else -#endif // PARAMETERS - -#ifdef ETHERNET - if (cmd[0] == 'q') { // quit - quit = true; - } else -#endif - -#ifdef RECEIVE - // TODO: option for force decoding off - if (isPrefix(cmd, F("receive"))) { // receive - bool status = receive(stream); - if (!status) - stream.println(F(errorString)); - } else -#endif // RECEIVE - -#ifdef NAMED_COMMANDS - if (cmd[0] == 'n') { - uint16_t noSends = (uint16_t) tokenizer.getInt(); - String remoteName = tokenizer.getToken(); - String commandName = tokenizer.getToken(); - bool success = sendNamedCommand(stream, remoteName, commandName, noSends); - if (success) - stream.println(okString); - } else - - if (isPrefix(cmd, "remote")) { - String name = tokenizer.getToken(); - dumpRemote(stream, name); - } else -#endif - -#ifdef RESET - if (isPrefix(cmd, "reset")) { - reset = true; - } else -#endif - -#ifdef TRANSMIT - if (cmd[0] == 's') { // send - // TODO: handle unparsable data gracefully - uint16_t noSends = (uint16_t) tokenizer.getInt(); - frequency_t frequency = tokenizer.getFrequency(); - uint16_t introLength = (uint16_t) tokenizer.getInt(); - uint16_t repeatLength = (uint16_t) tokenizer.getInt(); - uint16_t endingLength = (uint16_t) tokenizer.getInt(); - microseconds_t intro[introLength]; - microseconds_t repeat[repeatLength]; - microseconds_t ending[endingLength]; - for (uint16_t i = 0; i < introLength; i++) - intro[i] = tokenizer.getMicroseconds(); - for (uint16_t i = 0; i < repeatLength; i++) - repeat[i] = tokenizer.getMicroseconds(); - for (uint16_t i = 0; i < endingLength; i++) - ending[i] = tokenizer.getMicroseconds(); - IrSignal irSignal(intro, introLength, repeat, repeatLength, ending, endingLength, frequency); - bool status = sendIrSignal(irSignal, noSends); // waits - stream.println(status ? F(okString) : F(errorString)); - } else -#endif // TRANSMIT - -#ifdef PRONTO - if (isPrefix(cmd, F("hex"))) { // pronto hex send - uint16_t noSends = (uint16_t) tokenizer.getInt(); - String rest = tokenizer.getRest(); - IrSignal *irSignal = Pronto::parse(rest.c_str()); - bool status = false; - if (irSignal != NULL) { - status = sendIrSignal(*irSignal, noSends); // waits - delete irSignal; - } - stream.println(status ? F(okString) : F(errorString)); - } else -#endif // PRONTO - -#ifdef RENDERER - if (cmd[0] == 't') { // transmit - // TODO: handle unparseable data gracefully - uint16_t noSends = (uint16_t) tokenizer.getInt(); - String protocol = tokenizer.getToken(); - const IrSignal *irSignal = NULL; - if (isPrefix(protocol, F("nec1"))) { - unsigned int D = (unsigned) tokenizer.getInt(); - unsigned int S = (unsigned) tokenizer.getInt(); - unsigned int F = (unsigned) tokenizer.getInt(); - irSignal = (F == Tokenizer::invalid) - ? Nec1Renderer::newIrSignal(D, S) - : Nec1Renderer::newIrSignal(D, S, F); - } else if (isPrefix(protocol, F("rc5"))) { - unsigned int D = (unsigned) tokenizer.getInt(); - unsigned int F = (unsigned) tokenizer.getInt(); - unsigned int T = (unsigned) tokenizer.getInt(); - irSignal = (T == Tokenizer::invalid) - ? Rc5Renderer::newIrSignal(D, F) - : Rc5Renderer::newIrSignal(D, F, T); - } else { - stream.print(F("no such protocol: ")); - stream.println(protocol); - } - bool status = false; - if (irSignal != NULL) { - status = sendIrSignal(*irSignal, noSends); // waits, blinks - delete irSignal; - } - stream.println(status ? F(okString) : F(errorString)); - } else -#endif // RENDERER - - if (cmd[0] == 'v') { // version - stream.println(F(PROGNAME " " VERSION)); - } else { - stream.println(F(errorString)); - } - - //flushIn(stream); -#ifdef RESET - if (reset) - return false; -#endif - -#ifdef ETHERNET - if (quit) - return false; -#endif - - return true; -} - -static bool readProcessOneCommand(Stream& stream) { - String line = readCommand(stream); -#ifdef SERIAL_DEBUG - Serial.println("Command: " + line); -#endif - return processCommand(line, stream); -} - -#if defined(ETHERNET) -bool readProcessOneTcpCommand(EthernetClient& client) { - while (client.available() == 0) { - LedLcdManager::checkTurnoff(); -#ifdef BEACON - Beacon::checkSend(); -#endif - if (!client.connected()) - return false; - } - return readProcessOneCommand(client); -} -#endif - -void loop() { - LedLcdManager::checkTurnoff(); -#ifdef ETHERNET -#ifdef BEACON - Beacon::checkSend(); -#endif - - EthernetClient client = server.available(); - if (!client) - return; - client.setTimeout(10000); -#ifdef LCD - LedLcdManager::lcdPrint("Connection from", true, 0, 0); - char ipstring[16]; - sprintf(ipstring, "%d.%d.%d.%d", Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]); - LedLcdManager::lcdPrint(ipstring, false, 0, 1); -#endif -#ifdef SERIAL_DEBUG - Serial.print(F("Connection from ")); - Serial.println(ipstring); -#endif -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::on); -#endif - - while (readProcessOneTcpCommand(client)) -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::on) -#endif - ; -#ifdef LCD - LedLcdManager::lcdPrint("Connection closed!", true, 0, 0); -#endif -#ifdef SERIAL_DEBUG - Serial.println(F("Connection closed!")); -#endif - client.println(F("Bye")); - -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::off); -#endif - - if (client.connected()) - client.flush(); - client.stop(); - -#else // ! ETHERNET - -#ifdef ARDUINO - Stream& stream = Serial; - #else - Stream stream(std::cout); -#endif - readProcessOneCommand(stream); -#endif // ! ETHERNET - -#ifdef RESET - if (reset) { - GirsUtils::reset(); - reset = false; // In case it does not work, do not keep trying - } -#endif -} - -#ifndef ARDUINO -int main() { - setup(); - while (true) - loop(); -} -#endif diff --git a/examples/Girs/Girs.cpp.fummel b/examples/Girs/Girs.cpp.fummel deleted file mode 100644 index 428bd9a..0000000 --- a/examples/Girs/Girs.cpp.fummel +++ /dev/null @@ -1,985 +0,0 @@ -/* -Copyright (C) 2014,2015,2017 Bengt Martensson. - -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, see http://www.gnu.org/licenses/. -*/ - -#include "config.h" -#include "GirsLib/LedLcdManager.h" -#include "GirsLib/GirsUtils.h" -//#include "GirsLib/Tokenizer.h" -#ifdef ARDUINO -#include -#else -#define PROGMEM -#endif - -// Conditional includes -#if defined(ETHERNET) & !defined(ARDUINO) -#error not supported -#endif - -#ifdef ETHERNET -#include -#include -#endif // ETHERNET - -#ifdef LCD -#include -#endif - -#ifdef RECEIVE -#include -#endif - -#ifdef TRANSMIT -#include -#endif -#if defined(RECEIVE) -#include -#endif - -#ifdef CAPTURE -#include -#endif - -#ifdef NON_MOD -#include -#endif - -#ifdef DECODER -#ifndef RECEIVE -#error DECODER without RECEIVE is nonsensical, aborting. -#endif -#include -#endif - -#ifdef RENDERER -#ifndef TRANSMIT -#error RENDER without TRANSMIT is nonsensical, aborting. -#endif -#include -#include -#include -#endif - -#ifdef NAMED_COMMANDS -#error NAMED_COMMANDS is presently not supported -#endif - -#ifdef BEACON -#include -#endif - -#ifdef PRONTO -#include -#endif - -#ifdef ARDUINO -#else -#include -#endif - -#if defined(CONFIGURABLE_LEDS) & (! defined(PARAMETERS) | !defined(LED)) -#error CONFIGURABLE_LEDS defined but not PARAMETERS and LED, aborting. -#endif - -#ifdef CONFIGURABLE_LEDS -#define LED_PARAMETER_CONST -#else -#define LED_PARAMETER_CONST const -#endif - -#ifdef PARAMETERS -#define PARAMETERS_NAME Parameters -#define PARAMETER_CONST -#else -#define PARAMETERS_NAME -#define PARAMETER_CONST const -#endif - -#ifdef LED -#ifdef TRANSMITLED -static LED_PARAMETER_CONST led_t transmitled = TRANSMITLED; -#endif - -#ifdef RECEIVELED -static LED_PARAMETER_CONST led_t receiveled = RECEIVELED; -#endif - -#ifdef CAPTURELED -static LED_PARAMETER_CONST led_t captureled = CAPTURELED; -#endif - -#ifdef COMMANDLED -static LED_PARAMETER_CONST led_t commandled = COMMANDLED; -#endif -#endif // LED - -#ifdef CAPTURE -static PARAMETER_CONST unsigned long captureEndingTimeout = DEFAULT_CAPTURE_ENDINGTIMEOUT; // milliseconds -static const unsigned sensorNo = 1; // presently, only one supported -#endif -#ifdef RECEIVE -static PARAMETER_CONST unsigned long receiveEndingTimeout = DEFAULT_RECEIVE_ENDINGTIMEOUT; // milliseconds -#endif -#if defined(RECEIVE) | defined(CAPTURE) -static PARAMETER_CONST unsigned long beginTimeout = DEFAULT_BEGINTIMEOUT; // milliseconds -static PARAMETER_CONST uint16_t captureSize = DEFAULT_CAPTURESIZE; -#endif - -#ifdef RECEIVE -#ifdef IRRECEIVER_2_PIN -static PARAMETER_CONST uint8_t receiverNo = 1; -#else -static const uint8_t receiverNo = 1; -#endif -#endif - -#ifdef ETHERNET -EthernetServer server(PORT); -#endif // ETHERNET - -#ifdef RESET -bool reset = false; -#endif - -#define modulesSupported EXPAND_AND_QUOTE(Base TRANSMIT_NAME CAPTURE_NAME RENDERER_NAME RECEIVE_NAME DECODER_NAME LED_NAME LCD_NAME PARAMETERS_NAME NAMED_COMMANDS_NAME PRONTO_NAME) -#ifndef PROGNAME -#define PROGNAME "AGirs" -#endif -#ifndef VERSION -#include "GirsLib/version.h" -#endif // VERSION -#define okString "OK" -#define errorString "ERROR" -#define timeoutString "." - -static constexpr size_t commandLength = 16U; -static constexpr int32_t invalidLong = INT32_MIN; - -#ifdef TRANSMIT - -static bool sendIrSignal(const IrSignal &irSignal, unsigned int noSends=1) { - if (noSends == 0) - return false; -#ifdef TRANSMITLED - LedLcdManager::setLogicLed(transmitled, LedLcdManager::on); -#endif - IrSender *irSender = -#ifdef NON_MOD - (irSignal.getFrequency() == 0) ? (IrSender*) new IrSenderNonMod(NON_MOD_PIN) : -#endif - (IrSender*) IrSenderPwm::getInstance(true); - - irSender->sendIrSignal(irSignal, noSends); - -#ifdef NON_MOD - if (irSignal.getFrequency() == 0) - delete irSender; - else -#endif - IrSenderPwm::deleteInstance(); - -#ifdef TRANSMITLED - LedLcdManager::setLogicLed(transmitled, LedLcdManager::off); -#endif - return true; -} - -#endif // TRANSMIT - -# if defined(RECEIVE) | defined(CAPTURE) -static void flushIn(Stream &stream UNUSED) { -#ifdef ARDUINO - while (stream.available()) - stream.read(); -#endif -} -#endif - -#ifdef RECEIVE - -static void decodeOrDump(IrReader *irReader, Stream& stream) { -#ifdef DECODER - MultiDecoder multiDecoder(*irReader); -#ifdef LCD - if (multiDecoder.getType() > MultiDecoder::noise) { - LedLcdManager::lcdPrint(multiDecoder.getType() == MultiDecoder::nec_ditto - ? "." : multiDecoder.getDecode(), - multiDecoder.getType() != MultiDecoder::nec_ditto); - if (multiDecoder.getType() == MultiDecoder::nec) - LedLcdManager::lcdSetCursor(0, 1); // prepare for dittos - } -#endif - -#ifdef DECODELED - LedLcdManager::setLogicLed(DECODELED(multiDecoder.getType()), LedLcdManager::blink); -#endif -#endif - -#if defined(DECODER) & ! defined(DONT_REPORT_DECODES) // lircd does its own decoding - switch (multiDecoder.getType()) { - case MultiDecoder::noise: - // ignore - break; - case MultiDecoder::undecoded: - irReader->dump(stream); // report data of undecoded signals - break; - default: - stream.println(multiDecoder.getDecode()); // also for timeout - break; - } -#else // ! (defined(DECODER) & ! defined(DONT_REPORT_DECODES)) - if (irReader->isEmpty()) - stream.println(F(timeoutString)); - else - irReader->dump(stream); -#endif // !DECODER -} - -static bool receive(Stream& stream) { - IrReceiverSampler *irReceiver = IrReceiverSampler::getInstance(); - if (irReceiver == nullptr) - irReceiver = IrReceiverSampler::newIrReceiverSampler(captureSize, - GirsUtils::receiverPin(receiverNo), GirsUtils::receiverPullup(receiverNo)); - if (irReceiver == nullptr) - return false; - irReceiver->setEndingTimeout(receiveEndingTimeout); - irReceiver->setBeginningTimeout(beginTimeout); - irReceiver->setMarkExcess(IRRECEIVER_MARK_EXCESS); - flushIn(stream); -#ifdef RECEIVELED - LedLcdManager::setLogicLed(receiveled, LedLcdManager::on); -#endif - irReceiver->enable(); -#ifdef ARDUINO - while (!irReceiver->isReady() && stream.available() == 0) -#else - std::cout << "** Simulating timeout **" << std::endl; - delay(beginTimeout); -#endif - LedLcdManager::checkTurnoff(); - bool ready = irReceiver->isReady(); - irReceiver->disable(); -#ifdef RECEIVELED - LedLcdManager::setLogicLed(receiveled, LedLcdManager::off); -#endif - if (ready) - decodeOrDump(irReceiver, stream); - IrReceiverSampler::deleteInstance(); - return true; -} -#endif // RECEIVE - -#ifdef CAPTURE - -static bool capture(Stream& stream) { - IrWidget *irWidget = IrWidgetAggregating::newIrWidgetAggregating(captureSize, - GirsUtils::sensorPullup(sensorNo)); - if (irWidget == nullptr) - stream.println(F("This cannot happen")); - irWidget->setEndingTimeout(captureEndingTimeout); - irWidget->setBeginningTimeout(beginTimeout); - irWidget->setMarkExcess(IRSENSOR_MARK_EXCESS); - irWidget->reset(); -#ifdef CAPTURELED - LedLcdManager::setLogicLed(captureled, LedLcdManager::on); -#endif - flushIn(stream); -#ifdef ARDUINO - irWidget->capture(); -#else - std::cout << "** Simulating timeout **" << std::endl; - delay(beginTimeout); -#endif - -#ifdef CAPTURELED - LedLcdManager::setLogicLed(captureled, LedLcdManager::off); -#endif - if (!irWidget->isEmpty()) { - // Trying to decode the capture does not make sense, - // that is what "receive" is for. - irWidget->dump(stream); - } else - stream.println(F(timeoutString)); - IrWidgetAggregating::deleteInstance(); - return true; -} -#endif // CAPTURE - -#ifdef NAMED_COMMANDS -// Defines a const IrNamedRemoteSet remoteSet with commands to be used. -//#include "my_named_remotes.inc" -extern const IrNamedRemoteSet remoteSet; - -static bool sendNamedCommand(Stream& stream, String& remoteName, String& commandName, unsigned int noSends) { - const IrNamedRemote* remote = remoteSet.getIrNamedRemote(remoteName.c_str()); - if (remote == nullptr) { - stream.println(F("No such remote")); - return false; - } - - const IrNamedCommand* command = remote->getIrNamedCommand(commandName.c_str()); - if (command == nullptr) { - stream.println(F("No such command")); - return false; - } - const IrSignal *irSignal = command->getIrSignal(); - bool status = sendIrSignal(*irSignal, noSends); // waits, blinks - delete irSignal; - return status; -} - -static void dumpRemote(Stream& stream, String& name) { - if (name.length() == 0) { - for (unsigned int i = 0; i < remoteSet.getNoIrNamedRemotes(); i++) { - stream.print(remoteSet.getIrNamedRemotes()[i]->getName()); - stream.print(" "); - } - stream.println(); - } else { - const IrNamedRemote* remote = remoteSet.getIrNamedRemote(name.c_str()); - if (remote == nullptr) - stream.println(F("No such remote")); - else { - for (unsigned int i = 0; i < remote->getNoCommands(); i++) { - stream.print(remote->getAllCommands()[i]->getName()); - stream.print(" "); - } - stream.println(); - } - } -} -#endif - -void setup() { - LedLcdManager::setupLedGroundPins(); - GirsUtils::setupReceivers(); - GirsUtils::setupSensors(); -#if defined(TRANSMIT) - // Make sure that sender is quiet (if reset or such) - IrSenderPwm::getInstance(true)->mute(); -#endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" - LedLcdManager::setup(LCD_I2C_ADDRESS, LCD_WIDTH, LCD_HEIGHT, - (const pin_t[]) {SIGNAL_LED_1, SIGNAL_LED_2, SIGNAL_LED_3, SIGNAL_LED_4, - SIGNAL_LED_5, SIGNAL_LED_6, SIGNAL_LED_7, SIGNAL_LED_8 }); - LedLcdManager::selfTest(PROGNAME "\n" VERSION); -#pragma GCC diagnostic pop -#ifdef LED - LedLcdManager::setupShouldTimeout(transmitled, false); - LedLcdManager::setupShouldTimeout(receiveled, false); - LedLcdManager::setupShouldTimeout(captureled, false); - LedLcdManager::setupShouldTimeout(commandled, false); -#endif -#ifdef LCD -#ifdef ETHERNET - LedLcdManager::lcdPrint(F("TCP"), false, 0, 2); -#ifdef SERIAL_DEBUG - LedLcdManager::lcdPrint(F(",SerialDbg"), false); -#endif -#else // ! ETHERNET - LedLcdManager::lcdPrint(F("Serial"), false, 0, 2); -#endif // ! ETHERNET -#endif // LCD - -#ifdef ETHERNET -#ifdef SDCARD_ON_ETHERSHIELD_PIN - // disable the SD card, as recommended in the doc - pinMode(SDCARD_ON_ETHERSHIELD_PIN, OUTPUT); - digitalWrite(SDCARD_ON_ETHERSHIELD_PIN, LOW); -#endif - byte mac[] = { MACADDRESS }; -#ifdef DHCP - Ethernet.begin(mac); -#else // !DHCP - Ethernet.begin(mac, IPAddress(IPADDRESS), IPAddress(DNSSERVER), IPAddress(GATEWAY), IPAddress(SUBNETMASK)); -#endif // !DHCP - - char ipstring[16]; - sprintf(ipstring, "%d.%d.%d.%d", Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]); -// GirsUtils::ip2string(ipstring, Ethernet.localIP()); - LedLcdManager::lcdPrint(ipstring, false, 0, 3); - -#ifdef BEACON - Beacon::setup(PROGNAME, "DE-AD-BE-EF-FE-ED", "Utility", "www.harctoolbox.org", - "", "", "", "http://arduino/nosuchfile.html"); -#endif - - server.begin(); - -#endif // ETHERNET - -#if defined(ARDUINO) & !defined(ETHERNET) | defined(SERIAL_DEBUG) - - Serial.begin(SERIALBAUD); -#if defined(ARDUINO_AVR_LEONARDO) | defined(ARDUINO_AVR_MICRO) - while (!Serial) - ; // wait for serial port to connect. "Needed for Leonardo only" -#endif - Serial.println(F(PROGNAME " " VERSION)); - Serial.setTimeout(SERIALTIMEOUT); - -#ifdef ETHERNET - Serial.println(Ethernet.localIP()); -#endif -#endif // defined(ARDUINO) & !defined(ETHERNET) | defined(SERIAL_DEBUG) -} - -#ifdef INFO -void info(Stream& stream) { - stream.print("Board: "); -#ifdef ARDUINO_AVR_MEGA2560 - stream.print(F("Arduino Mega2560")); -#elif defined(ARDUINO_AVR_NANO) - stream.print(F("Arduino Nano")); -#elif defined(ARDUINO_AVR_LEONARDO) - stream.print(F("Arduino Leonardo")); -#elif defined(ARDUINO_AVR_MINI) - stream.print(F("Arduino Leonardo")); -#elif defined(ARDUINO_AVR_UNO) - stream.print(F("Arduino Uno")); -#else - stream.print(F("Unknown")); -#endif - - stream.print(F(", CPU frequency: " EXPAND_AND_QUOTE(F_CPU))); - - stream.println(); -} -#endif - -//static inline bool isPrefix(const String& cmd, const char *string) { -// return strncmp(cmd.c_str(), string, cmd.length()) == 0; -//} - -static inline bool isPrefix(const char *string, const String& cmd) { - return strncmp(cmd.c_str(), string, strlen(string)) == 0; -} - -#ifdef ARDUINO -bool isPrefix(const char *cmd, const __FlashStringHelper *pstring) { - return strncmp_PF(cmd, reinterpret_cast(pstring), strlen(cmd)) == 0; -} - -bool isPrefix(const __FlashStringHelper *pstring, const char *cmd) { - return strncmp_PF(cmd, reinterpret_cast(pstring), strlen_PF(reinterpret_cast(pstring))) == 0; -} -#endif - -#ifdef ARDUINO -void gobbleToWhitespace(Stream &stream) { - char c; - do { - c = stream.read(); - } while (!isspace(c)); -} -#endif - -static const char *getLine(char *buf, size_t buflen, Stream& stream) { -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::on); -#endif - -#ifdef ARDUINO - //flushIn(stream); - while (stream.available() == 0) { - LedLcdManager::checkTurnoff(); - } - -// String line = stream.readStringUntil(EOLCHAR); -// line.trim(); - unsigned int noChars = 0; - while (true) { - char c = stream.read(); - if (c == -1) - continue; - if (isspace(c) && ! isblank(c)) { - if (noChars == 0) - continue; - else { - buf[noChars] = '\0'; - break; - } - } - buf[noChars] = c; - noChars++; - if (noChars == buflen - 1) { - buf[noChars] = '\0'; - gobbleToWhitespace(stream); - break; - } - } -#else - (void) stream; - LedLcdManager::checkTurnoff(); - //static char str[1000]; - std::cin.getline(buf, buflen); - if (std::cin.eof()) { - std::cout << "Bye!" << std::endl; - exit(0); - } - //char *s = str; - //while (isspace(*s)) - // s++; - while (isspace(buf[strlen(buf)-1])) - buf[strlen(buf)-1] = '\0'; -#endif - -#if defined(DEBUG_CMD) - LedLcdManager::lcdPrint(buf, true, 0, 0); -#endif -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::off); -#endif - return buf; -} - -static const char *getWord(char *buf, size_t buflen, Stream& stream) { -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::on); -#endif - -#ifdef ARDUINO - //flushIn(stream); - while (stream.available() == 0) { - LedLcdManager::checkTurnoff(); - } - -// String line = stream.readStringUntil(EOLCHAR); -// line.trim(); - unsigned int noChars = 0; - while (true) { - char c = stream.read(); - if (c == -1) - continue; - if (isspace(c)) { - if (noChars == 0) - continue; - else { - buf[noChars] = '\0'; - break; - } - } - buf[noChars] = c; - noChars++; - if (noChars == buflen - 1) { - buf[noChars] = '\0'; - gobbleToWhitespace(stream); - break; - } - } -#else - (void) stream; - LedLcdManager::checkTurnoff(); - //static char str[1000]; - std::cin.getline(buf, buflen); - if (std::cin.eof()) { - std::cout << "Bye!" << std::endl; - exit(0); - } - //char *s = str; - //while (isspace(*s)) - // s++; - while (isspace(buf[strlen(buf)-1])) - buf[strlen(buf)-1] = '\0'; -#endif - -#if defined(DEBUG_CMD) - LedLcdManager::lcdPrint(buf, true, 0, 0); -#endif -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::off); -#endif - return buf; -} - -static int32_t getInt(Stream &stream) { - constexpr size_t buflen = 16; - char buf[buflen]; - getWord(buf, buflen, stream); - - char *junk = nullptr; - long value = strtol(buf, &junk, 0); - return *junk == '\0' ? value : invalidLong; -} - -static void getMicrosecondsArray(microseconds_t *buf, size_t buflen, Stream &stream) { - for (unsigned int i = 0; i < buflen; i++) { - buf[i] = static_cast(getInt(stream)); - } -} - -static bool processCommand(const char *cmd, Stream& stream) { -#ifdef ETHERNET - bool quit = false; -#endif - //Tokenizer tokenizer(cmd); - //String cmd = tokenizer.getToken(); - - // Decode command - if (cmd[0] == '\0') { - // empty command, do nothing - stream.println(F(okString)); - } else - -#ifdef CAPTURE - if (cmd[0] == 'a' || cmd[0] == 'c') { - capture(stream); - } else -#endif // CAPTURE - -#ifdef LCD - if (isPrefix(cmd, F("lcd"))) { //LCD - constexpr size_t buflen = 40U; - char rest[buflen]; - getLine(rest, buflen, stream); - LedLcdManager::lcdPrint(rest); - stream.println(F(okString)); - } else -#endif // LCD - -#ifdef LED - if (isPrefix(cmd, F("led"))) { - pin_t no = static_cast(getInt(stream)); - constexpr size_t buflen = 8; - char value[buflen]; - getWord(value, buflen, stream); - bool success = LedLcdManager::setLogicLed(no, value); - stream.println(success ? F(okString) : F(errorString)); - } else -#endif // LED - - if (isPrefix(cmd, F("modules"))) { - stream.println(F(modulesSupported)); - } else - -#ifdef FREEMEM - if (isPrefix(cmd, F("memory"))) { - stream.println(GirsUtils::freeRam()); - } else -#endif - -#ifdef INFO - if (isPrefix(cmd, F("info"))) { - info(stream); - } else -#endif - -#ifdef PARAMETERS - if (cmd[0] == 'p') { // parameter - constexpr size_t buflen = 16; - char variableName[buflen]; - getWord(variableName, buflen, stream); - long value = getInt(stream); - unsigned long *variable32 = nullptr; - uint16_t *variable16 = nullptr; - uint8_t *variable8 = nullptr; -#if defined(RECEIVE) || defined(CAPTURE) - if (isPrefix(F("beg"), variableName)) - variable32 = &beginTimeout; - else -#endif -#ifdef CAPTURE - if (isPrefix(F("capturee"), variableName)) - variable32 = &captureEndingTimeout; -#endif -#ifdef RECEIVE - if (isPrefix(F("receivee"), variableName)) - variable32 = &receiveEndingTimeout; - else -#endif -#if defined(RECEIVE) & defined(IRRECEIVER_2_PIN) - if (isPrefix(variableName, F("receiver"))) - variable8 = &receiverNo; - else -#endif -#ifdef CAPTURE - if (isPrefix(F("captures"), variableName)) { - // TODO: check evenness of value - variable16 = &captureSize; - } else -#endif -#ifdef LED -#ifdef CONFIGURABLE_LEDS -#ifdef TRANSMITLED - if (isPrefix(F("transmitl"), variableName)) - variable8 = &transmitled; - else -#endif -#ifdef CAPTURELED - if (isPrefix(F("capturel"), variableName)) - variable8 = &captureled; - else -#endif -#ifdef RECEIVELED - if (isPrefix(F("receivel"), variableName)) - variable8 = &receiveled; - else -#endif -#ifdef COMMANDLED - if (isPrefix(F("commandl"), variableName)) - variable8 = &commandled; - else -#endif -#endif - // TODO: handle blinkTime. This currently means either break encapsulation - // of LedLcdManager, or write a nasty special case :-~ -#endif - { - } - - if (variable32 != nullptr) { - if (value != invalidLong) - *variable32 = value; - - GirsUtils::printVariable(stream, variableName, *variable32); - } else if (variable16 != nullptr) { - if (value != invalidLong) - *variable16 = static_cast(value); - - GirsUtils::printVariable(stream, variableName, *variable16); - } else if (variable8 != nullptr) { - if (value != invalidLong) - *variable8 = (uint8_t) value; - - GirsUtils::printVariable(stream, variableName, *variable8); - } else - stream.println(F("No such variable")); - } else -#endif // PARAMETERS - -#ifdef ETHERNET - if (cmd[0] == 'q') { // quit - quit = true; - } else -#endif - -#ifdef RECEIVE - // TODO: option for force decoding off - if (isPrefix(cmd, F("receive"))) { // receive - bool status = receive(stream); - if (!status) - stream.println(F(errorString)); - } else -#endif // RECEIVE - -#ifdef NAMED_COMMANDS - if (cmd[0] == 'n') { - uint16_t noSends = static_cast(getInt(stream)); - String remoteName = getToken(); - String commandName = tokenizer.getToken(); - bool success = sendNamedCommand(stream, remoteName, commandName, noSends); - if (success) - stream.println(okString); - } else - - if (isPrefix(cmd, "remote")) { - String name = tokenizer.getToken(); - dumpRemote(stream, name); - } else -#endif - -#ifdef RESET - if (isPrefix(cmd, "reset")) { - reset = true; - } else -#endif - -#ifdef TRANSMIT - if (cmd[0] == 's') { // send - // TODO: handle unparsable data gracefully - uint16_t noSends = static_cast(getInt(stream)); - frequency_t frequency = static_cast(getInt(stream)); - uint16_t introLength = static_cast(getInt(stream)); - uint16_t repeatLength = static_cast(getInt(stream)); - uint16_t endingLength = static_cast(getInt(stream)); - microseconds_t *intro = new microseconds_t[introLength]; - getMicrosecondsArray(intro, introLength, stream); - microseconds_t *repeat = new microseconds_t[repeatLength]; - getMicrosecondsArray(repeat, repeatLength, stream); - microseconds_t *ending = new microseconds_t[endingLength]; - getMicrosecondsArray(ending, endingLength, stream); - IrSignal irSignal(intro, introLength, repeat, repeatLength, ending, endingLength, frequency); - bool status = sendIrSignal(irSignal, noSends); // waits - stream.println(status ? F(okString) : F(errorString)); - } else -#endif // TRANSMIT - -#ifdef PRONTO -// if (isPrefix(cmd, F("hex"))) { // pronto hex send -// uint16_t noSends = static_cast(getInt(stream); -// String rest = tokenizer.getRest(); -// IrSignal *irSignal = Pronto::parse(rest.c_str()); -// bool status = false; -// if (irSignal != nullptr) { -// status = sendIrSignal(*irSignal, noSends); // waits -// delete irSignal; -// } -// stream.println(status ? F(okString) : F(errorString)); -// } else -#endif // PRONTO - -#ifdef RENDERER - if (cmd[0] == 't') { // transmit - // TODO: handle unparseable data gracefully - uint16_t noSends = static_cast(getInt(stream)); - constexpr size_t buflen = 20U; - char protocol[buflen]; - getWord(protocol, buflen, stream); - const IrSignal *irSignal = nullptr; - if (isPrefix(protocol, F("nec1"))) { - unsigned int D = static_cast(getInt(stream)); - unsigned int S = static_cast(getInt(stream)); - unsigned int F = static_cast(getInt(stream)); - irSignal = (F == invalidLong) - ? Nec1Renderer::newIrSignal(D, S) - : Nec1Renderer::newIrSignal(D, S, F); - } else if (isPrefix(protocol, F("rc5"))) { - unsigned int D = static_cast(getInt(stream)); - unsigned int F = static_cast(getInt(stream)); - unsigned int T = static_cast(getInt(stream)); - irSignal = (T == invalidLong) - ? Rc5Renderer::newIrSignal(D, F) - : Rc5Renderer::newIrSignal(D, F, T); - } else { - stream.print(F("no such protocol: ")); - stream.println(protocol); - } - bool status = false; - if (irSignal != nullptr) { - status = sendIrSignal(*irSignal, noSends); // waits, blinks - delete irSignal; - } - stream.println(status ? F(okString) : F(errorString)); - } else -#endif // RENDERER - - if (cmd[0] == 'v') { // version - stream.println(F(PROGNAME " " VERSION)); - } else { - stream.println(F(errorString)); - } - - //flushIn(stream); -#ifdef RESET - if (reset) - return false; -#endif - -#ifdef ETHERNET - if (quit) - return false; -#endif - - return true; -} - -static bool readProcessOneCommand(Stream& stream) { - char commandName[commandLength]; - getWord(commandName, commandLength, stream); -#ifdef SERIAL_DEBUG - Serial.println("Command: " + commandName); - delay(1000); -#endif - return processCommand(commandName, stream); -} - -#if defined(ETHERNET) -bool readProcessOneTcpCommand(EthernetClient& client) { - while (client.available() == 0) { - LedLcdManager::checkTurnoff(); -#ifdef BEACON - Beacon::checkSend(); -#endif - if (!client.connected()) - return false; - } - return readProcessOneCommand(client); -} -#endif - -void loop() { - LedLcdManager::checkTurnoff(); -#ifdef ETHERNET -#ifdef BEACON - Beacon::checkSend(); -#endif - - EthernetClient client = server.available(); - if (!client) - return; - client.setTimeout(10000); -#ifdef LCD - LedLcdManager::lcdPrint(F("Connection from"), true, 0, 0); - char ip[16]; - sprintf(ip, "%d.%d.%d.%d", Ethernet.localIP()[0], Ethernet.localIP()[1], Ethernet.localIP()[2], Ethernet.localIP()[3]); - LedLcdManager::lcdPrint(ip, false, 0, 1); -#endif -#ifdef SERIAL_DEBUG - Serial.print(F("Connection from ")); - Serial.println(ip); -#endif -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::on); -#endif - - while (readProcessOneTcpCommand(client)) -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::on) -#endif - ; -#ifdef LCD - LedLcdManager::lcdPrint(F("Connection closed!"), true, 0, 0); -#endif -#ifdef SERIAL_DEBUG - Serial.println(F("Connection closed!")); -#endif - client.println(F("Bye")); - -#if defined(COMMANDLED) & defined(LED) - LedLcdManager::setLogicLed(commandled, LedLcdManager::off); -#endif - - if (client.connected()) - client.flush(); - client.stop(); - -#else // ! ETHERNET - -#ifdef ARDUINO - Stream& stream = Serial; - #else - Stream stream(std::cout); -#endif - readProcessOneCommand(stream); -#endif // ! ETHERNET - -#ifdef RESET - if (reset) { - GirsUtils::reset(); - reset = false; // In case it does not work, do not keep trying - } -#endif -} - -#ifndef ARDUINO -int main() { - setup(); - while (true) - loop(); -} -#endif diff --git a/src/GirsLib/IrNamedRemoteSet.h b/src/GirsLib/IrNamedRemoteSet.h new file mode 100644 index 0000000..8938984 --- /dev/null +++ b/src/GirsLib/IrNamedRemoteSet.h @@ -0,0 +1,29 @@ +#pragma once + + + +/** + * For now, just a dummy skeleton. + */ +class IrNamedCommand { +public: + const char* getName() const; + const IrSignal* getIrSignal() const; +}; + +class IrNamedRemote { +public: + const char* getName() const; + const IrNamedCommand* getIrNamedCommand(const char*) const; + size_t size() const; + IrNamedCommand* begin() const; + IrNamedCommand* end() const; +}; + +class IrNamedRemoteSet { +public: + const IrNamedRemote* getIrNamedRemote(const char*) const; + size_t size() const; + IrNamedRemote* begin() const; + IrNamedRemote* end() const; +}; \ No newline at end of file diff --git a/src/GirsLib/LedLcdManager.cpp b/src/GirsLib/LedLcdManager.cpp index e590a7b..30841cc 100644 --- a/src/GirsLib/LedLcdManager.cpp +++ b/src/GirsLib/LedLcdManager.cpp @@ -10,7 +10,6 @@ #endif #include "LedLcdManager.h" -#include "Tokenizer.h" #include #ifdef ARDUINO @@ -241,7 +240,7 @@ void LedLcdManager::prepare(bool clear __attribute__((unused)), int x __attribut if (x >= 0 && y >= 0) { row = y; column = x; - if (row > (int) lcdRows - 1 || column > (int) lcdColumns - 1) // outside of display + if (row > (unsigned int) lcdRows - 1 || column > (unsigned int) lcdColumns - 1) // outside of display return; lcd->setCursor(column, row); } diff --git a/src/GirsLib/LedLcdManager.cpp.fummel b/src/GirsLib/LedLcdManager.cpp.fummel deleted file mode 100644 index 14276db..0000000 --- a/src/GirsLib/LedLcdManager.cpp.fummel +++ /dev/null @@ -1,225 +0,0 @@ -// Comment out if LCD is not wanted or needed. Except for needing some memory, -// it has otherwise no disadvantages. -// Remove for minimal memory footprint. - -// This should be taken from config.h, but the Arduino IDE does not seem -// to allow for this. User friendlyness taken to a new level... -// Adjust if needed -#if defined(ARDUINO) & ! defined(ARDUINO_AVR_MICRO) & ! defined(ARDUINO_AVR_NANO) -#define LCD -#endif - -#include "LedLcdManager.h" -#include "Tokenizer.h" -#include - -#ifdef LCD -LiquidCrystal_I2C *LedLcdManager::lcd; -#endif -milliseconds_t LedLcdManager::blinkTime = defaultBlinkTime; -unsigned long LedLcdManager::turnOffTime; -unsigned int LedLcdManager::lcdRows = 0; -unsigned int LedLcdManager::lcdColumns = 0; - -pin_t LedLcdManager::physicalLeds[maxLeds]; -led_t LedLcdManager::logicalLeds[maxLeds]; -bool LedLcdManager::shouldTimeOut[maxLeds]; - -void LedLcdManager::setup(int8_t i2cAddress, uint8_t columns, uint8_t rows, - const pin_t physicalLeds_[], const led_t logicalLeds_[], const bool shouldTimeOut_[]) { - setupLcdI2c(i2cAddress, columns, rows); - setupPhysicalLeds(physicalLeds_); - setupLogicLeds(logicalLeds_); - setupShouldTimeOut(shouldTimeOut_); - disableTurnOffTime(); -} - -bool LedLcdManager::setPhysicalLed(led_t physicalLed, LedState state) { - pin_t pin = physicalLeds[physicalLed-1]; - if (pin == invalidPin) - return false; - -#ifdef ARDUINO - digitalWrite(pin, state == off ? LOW : HIGH); -#else - std::cout << "setPhysicalLed: pin = " << (int) pin << ", " << (state == off ? "off" : "on") << std::endl; -#endif - if (state == blink) - updateTurnOffTime(); - return true; -} - -LedLcdManager::LedState LedLcdManager::onOffBlinkParse(const char *value) { - return value == NULL ? invalid - : strcmp(value, "on") == 0 ? on - : strcmp(value, "off") == 0 ? off - : strcmp(value, "blink") == 0 ? blink - : invalid; -} - -bool LedLcdManager::setLogicLed(led_t logicLed, LedState state) { - if (logicLed == invalidLed - || logicLed < 1 - || logicLed > maxLeds - || state == invalid ) - return false; - - led_t physicalLed = logicalLeds[logicLed - 1]; - if (physicalLed == invalidLed) - return false; - - return setPhysicalLed(physicalLed, state); -} - -bool LedLcdManager::setupLogicLed(led_t logicLed, led_t physicalLed) { - if (physicalLed == invalidLed) - return false; - - logicalLeds[logicLed-1] = physicalLed; - return true; -} - -bool LedLcdManager::setupLogicLeds(const led_t logicalLeds_[maxLeds]) { - for (int i = 0; i < maxLeds; i++) - logicalLeds[i] = logicalLeds_ == NULL ? i+1 : logicalLeds_[i]; - return true; -} - -void LedLcdManager::setupPhysicalLeds(const pin_t physicalLeds_[maxLeds]) { - for (int i = 0; i < maxLeds; i++) { - physicalLeds[i] = physicalLeds_ == NULL ? invalidPin : physicalLeds_[i]; - if (physicalLeds[i] != invalidPin) - pinMode(physicalLeds[i], OUTPUT); - } -} - -void LedLcdManager::setupShouldTimeOut(const bool shouldTimeOut_[maxLeds]) { - for (int i = 0; i < maxLeds; i++) - shouldTimeOut[i] = shouldTimeOut_ == NULL ? true : shouldTimeOut_[i]; -} - -void LedLcdManager::setupShouldTimeout(led_t logicLed, bool state) { - if (logicLed != invalidLed) - shouldTimeOut[logicLed-1] = state; -} - -void LedLcdManager::setupLcdI2c(int8_t i2cAddress __attribute__((unused)), - uint8_t columns __attribute__((unused)), - uint8_t rows __attribute__((unused))) { -#ifdef LCD - lcd = i2cAddress >= 0 ? new LiquidCrystal_I2C(static_cast(i2cAddress), columns, rows) : nullptr; - if (lcd) { - lcdRows = rows; - lcdColumns = columns; - lcd->init(); - } -#endif -} - -void LedLcdManager::updateTurnOffTime() { - turnOffTime = millis() + blinkTime; -} - -void LedLcdManager::selfTest(const char *text) { - lcdPrint(text); - for (led_t i = 1; i <= maxLeds; i++) - setLogicLed(i, on); - delay( -#ifdef LCD - lcd ? selftestTimeWithLCD : -#endif - selftestTimeWithoutLCD); - allOff(true); -} - -#if 0 //def ARDUINO -void LedLcdManager::selfTest(const __FlashStringHelper *text) { - lcdPrint(text); - for (led_t i = 1; i <= maxLeds; i++) - setLogicLed(i, on); - delay( -#ifdef LCD - lcd ? selftestTimeWithLCD : -#endif - selftestTimeWithoutLCD); - allOff(true); -} -#endif - -void LedLcdManager::checkTurnoff() { - if (millis() > turnOffTime) - allOff(false); -} - -void LedLcdManager::allOff(bool force) { -#ifdef LCD - if (lcd) { - lcd->noDisplay(); - lcd->noBacklight(); - } -#endif - for (led_t i = 1; i <= maxLeds; i++) - if (force || shouldTimeOut[i - 1]) - setLogicLed(i, off); - - disableTurnOffTime(); -} - -void LedLcdManager::disableTurnOffTime() { - turnOffTime = (unsigned long) -1; -} - -#if 0 //def ARDUINO - -void LedLcdManager::lcdPrint(const __FlashStringHelper *pstr __attribute__ ((unused)), bool clear __attribute__ ((unused)), - int x __attribute ((unused)), int y __attribute__ ((unused))) { - size_t len = strlen_PF(reinterpret_cast (pstr)); - char str[len + 1]; - strcpy_PF(str, reinterpret_cast (pstr)); - lcdPrint(str, clear, x, y); -} -#endif - -void LedLcdManager::lcdPrint(const char* str __attribute__ ((unused)), bool clear __attribute__ ((unused)), - int x __attribute ((unused)), int y __attribute__ ((unused))) { -#ifdef LCD - if (!lcd) - return; - - int row = (y < 0 && clear) ? 0 : y; - int column = x < 0 ? 0 : x; - if (row > (int) lcdRows - 1 || column > (int) lcdColumns - 1) // outside of display - return; - - if (clear) - lcd->clear(); - - bool didPrint = false; - //Tokenizer tokenizer(string); - const char *p = str; - while (true) { - const char* end = strchr(p, '\n'); - //String line = tokenizer.getLine(); - if (end == NULL) - break; - size_t length = end - p; - //if (length > lcdColumns) - // //line = line.substring(0, lcdColumns); - if (clear || y >= 0) { - lcd->setCursor(column, row); - row++; - column = 0; - } - char line[lcdColumns + 1]; - strncpy(line, p, min(length, lcdColumns)); - lcd->print(line); - didPrint = true; - p = end + 1; - } - if (didPrint) { - lcd->display(); - lcd->backlight(); - } - updateTurnOffTime(); -#endif -} diff --git a/src/GirsLib/LedLcdManager.h b/src/GirsLib/LedLcdManager.h index bf255aa..6d5144c 100644 --- a/src/GirsLib/LedLcdManager.h +++ b/src/GirsLib/LedLcdManager.h @@ -1,10 +1,9 @@ #pragma once -#include "Tokenizer.h" #include #include #ifdef LCD -#include "LiquidCrystal_I2C_bm.h" // https://github.com/marcoschwartz/LiquidCrystal_I2C +#include "LiquidCrystal_I2C_bm.h" #endif typedef uint8_t led_t; @@ -92,6 +91,9 @@ class LedLcdManager { pin_t led7 = invalidPin, pin_t led8 = invalidPin); void static lcdPrint(const char *str, bool clear = true, int x = invalidLine, int y = invalidLine); + void static lcdPrint(String& string, bool clear = true, int x = invalidLine, int y = invalidLine) { + lcdPrint(string.c_str(), clear, x, y); + } #ifdef ARDUINO void static lcdPrint(const __FlashStringHelper *pstr, bool clear = true, int x = 0, int y = invalidLine); diff --git a/src/GirsLib/LedLcdManager.h.fummel b/src/GirsLib/LedLcdManager.h.fummel deleted file mode 100644 index 0584d6c..0000000 --- a/src/GirsLib/LedLcdManager.h.fummel +++ /dev/null @@ -1,180 +0,0 @@ -#pragma once - -#include "Tokenizer.h" -#include -#include -#ifdef LCD -#include // https://github.com/marcoschwartz/LiquidCrystal_I2C -#endif - -typedef uint8_t led_t; - -class LedLcdManager { -public: - static constexpr int maxLeds = 8; - static constexpr int defaultLcdRows = 2; - static constexpr int defaultLcdColumns = 16; - - static constexpr int defaultBlinkTime = 2000; - static constexpr int selftestTimeWithoutLCD = 200; - static constexpr int selftestTimeWithLCD = 2000; - - enum LedState { - on, - off, - blink, - invalid - }; - - static constexpr led_t invalidLed = 255U; - -private: - /** This array maps physical LEDs to hardware pins. */ - static pin_t physicalLeds[maxLeds]; - - /** This array maps logical LEDs to physical LEDs. */ - static led_t logicalLeds[maxLeds]; - - /** Indicates which logical leds should time out. */ - static bool shouldTimeOut[maxLeds]; - - static milliseconds_t blinkTime; - - /** Time to turn of, in the semantic of millis(). */ - static unsigned long turnOffTime; - -#ifdef LCD - static LiquidCrystal_I2C *lcd; -#endif - - static unsigned int lcdRows; - static unsigned int lcdColumns; - - //static LedLcdManager instance; - - static void setupPhysicalLeds(const pin_t physicalLeds[maxLeds]); - static void setupShouldTimeOut(const bool shouldTimeOut[maxLeds]); - /*pin_t pled1, pin_t pled2 = invalidPin, - pin_t pled3 = invalidPin, pin_t pled4 = invalidPin, - pin_t pled5 = invalidPin, pin_t pled6 = invalidPin, - pin_t pled7 = invalidPin, pin_t pled8 = invalidPin);*/ - - static void setupLcdI2c(int8_t i2cAddress, uint8_t columns, uint8_t rows); - LedLcdManager(); - - //void initArray(char *array, uint8_t value); - - static void disableTurnOffTime(); - - static void groundPin(pin_t pin) { - pinMode(pin, OUTPUT); - digitalWrite(pin, LOW); - } - -public: - /** Sets up the instance, to be called before using the instance. */ - static void setup(int8_t i2cAddress = -1, uint8_t columns = defaultLcdColumns, uint8_t rows = defaultLcdRows, - const pin_t physicalLeds[maxLeds] = NULL, - const led_t logicalLeds[maxLeds] = NULL, - const bool shouldTimeOut[maxLeds] = NULL); - - static void setup(int8_t i2cAddress, uint8_t columns, uint8_t rows, - pin_t pled1, pin_t pled2 = invalidLed, - pin_t pled3 = invalidPin, pin_t pled4 = invalidPin, - pin_t pled5 = invalidPin, pin_t pled6 = invalidPin, - pin_t pled7 = invalidPin, pin_t pled8 = invalidPin); - - void setupPhysicalLeds(pin_t led1 = invalidPin, pin_t led2 = invalidPin, - pin_t led3 = invalidPin, pin_t led4 = invalidPin, - pin_t led5 = invalidPin, pin_t led6 = invalidPin, - pin_t led7 = invalidPin, pin_t led8 = invalidPin); - - void static lcdPrint(const char *str, bool clear = true, int x = 0, int y = -1); -#ifdef ARDUINO - //void static lcdPrint(const __FlashStringHelper *pstr, bool clear = true, int x = 0, int y = -1); -#endif - - //void static lcdPrint(const String& str); - - //LedLcdManager& getInstance() { - // return instance; - //}; - - //static LiquidCrystal_I2C& getLcd() { - // return *lcd; - //} - - static void lcdSetCursor(uint8_t x = 0, uint8_t y = 0) { -#ifdef LCD - lcd->setCursor(x, y); -#else - (void) x; - (void) y; -#endif - } - - static void allOff(bool force); - - static milliseconds_t getBlinkTime() { - return blinkTime; - }; - - static void setBlinkTime(milliseconds_t value) { - blinkTime = value; - } - - static void updateTurnOffTime(); - - /** Turn off if it is due. This has to be called periodically by the user. */ - static void checkTurnoff(); - - static void selfTest(const char *text); - -#ifdef ARDUINO - static void selfTest(const __FlashStringHelper *text); -#endif - - static bool setPhysicalLed(led_t physicalLed, LedState state); - - static bool setLogicLed(led_t logicLed, LedState state); - - static bool setLogicLed(led_t logicLed, const char *state) { - return setLogicLed(logicLed, onOffBlinkParse(state)); - }; - - static LedState onOffBlinkParse(const char *value); - - static void setupShouldTimeout(led_t logicLed, bool state); - - static bool setupLogicLed(led_t loginLed, led_t physicalLed); - - static bool setupLogicLeds(const led_t array[maxLeds]); - - static void setupLedGroundPins() { -#ifdef SIGNAL_LED_1_GND - groundPin(SIGNAL_LED_1_GND); -#endif -#ifdef SIGNAL_LED_2_GND - groundPin(SIGNAL_LED_2_GND); -#endif -#ifdef SIGNAL_LED_3_GND - groundPin(SIGNAL_LED_3_GND); -#endif -#ifdef SIGNAL_LED_4_GND - groundPin(SIGNAL_LED_4_GND); -#endif -#ifdef SIGNAL_LED_5_GND - groundPin(SIGNAL_LED_5_GND); -#endif -#ifdef SIGNAL_LED_6_GND - groundPin(SIGNAL_LED_6_GND); -#endif -#ifdef SIGNAL_LED_7_GND - groundPin(SIGNAL_LED_7_GND); -#endif -#ifdef SIGNAL_LED_8_GND - groundPin(SIGNAL_LED_8_GND); -#endif - - } -}; diff --git a/src/GirsLib/StreamParser.cpp b/src/GirsLib/StreamParser.cpp index ef41d32..24cb77e 100644 --- a/src/GirsLib/StreamParser.cpp +++ b/src/GirsLib/StreamParser.cpp @@ -103,37 +103,56 @@ const char* StreamParser::getLine(char* buf, size_t buflen) { #endif } +int32_t StreamParser::parseAbsIntDefault(int32_t fallback) { + char c; + do { + c = customReadChar(); + } while (c == ' ' || c == '\t' || c == '-' || c == '+'); + + if (c == '\r' || c == '\n') + return fallback; + + return parseAbsInt(c); +} + int32_t StreamParser::parseAbsInt() { char c; do { - c = readCharBlock(); + c = customReadChar(); } while (isspace(c) || c == '-' || c == '+'); - int32_t value = 0; + return parseAbsInt(c); +} + +int32_t StreamParser::parseAbsInt(char initial) { + char c = initial; + int32_t value = invalid; while (true) { if (isspace(c)) return value; int32_t n = static_cast (c) - static_cast ('0'); if (n < 0 || n > 9) { disposeUntilWhitespace(); - return invalid; + return value; } + if (value == invalid) + value = 0; value = value * 10 + n; - c = readCharBlock(); + c = customReadChar(); } } uint16_t StreamParser::parseProntoNumber() { char c; do { - c = readCharBlock(); + c = customReadChar(); } while (isspace(c)); int32_t value = 0; for (unsigned i = 0; i < Pronto::digitsInProntoNumber; i++) { int n = parseHex(c); value = value * 16 + n; - c = readCharBlock(); + c = customReadChar(); } return value; } @@ -165,17 +184,31 @@ unsigned int StreamParser::parseHex(char c) { : invalid; } -char StreamParser::readCharBlock() { +char StreamParser::customReadChar() { int c; #ifdef ARDUINO do { - c = stream.read(); // does not block + yield(); + c = stream.peek(); // does not block } while (c == invalid); #else c = stream.get(); #endif + if (c == '\r' || c == '\n') + return static_cast(c); + + stream.read(); + return static_cast(c); +} - return static_cast (c); +void StreamParser::flushLine() { + while (true) { + int c = stream.peek(); + if (isspace(c)) + stream.read(); + else + return; + } } void StreamParser::disposeUntilWhitespace() { diff --git a/src/GirsLib/StreamParser.h b/src/GirsLib/StreamParser.h index c9554e0..837a36d 100644 --- a/src/GirsLib/StreamParser.h +++ b/src/GirsLib/StreamParser.h @@ -3,6 +3,7 @@ * The reads are blocking. * To be used instead instead of parseInt() and such, * since they do not offer enough flexibility. + * This is not written to be used outside of the package. */ #pragma once @@ -51,10 +52,17 @@ class StreamParser { /** * Reads a number and returns it as 16 bit unsigned. Blocking. Signs are ignored. * @return int16_t - * @return */ int32_t parseAbsInt(); + /** + * Reads a number and returns it as 16 bit unsigned. Blocking. Signs are ignored. + * If no valid character remains before line end, return the fallback argument. + * @param fallback Default value + * @return int16_t + */ + int32_t parseAbsIntDefault(int32_t fallback); + /** * Returns a word (separated by whitespace). * @param buf @@ -67,6 +75,8 @@ class StreamParser { Stream& getStream() { return stream; } + void flushLine(); + /** * Convenience function: combines the constructor and parseIrSignal. Blocking. * @param stream @@ -84,7 +94,8 @@ class StreamParser { Stream &stream; microseconds_t* parseData(size_t length); - char readCharBlock(); + int32_t parseAbsInt(char initial); + char customReadChar(); void disposeUntilWhitespace(); static unsigned int parseHex(char c); /** diff --git a/src/GirsLib/Tokenizer.cpp b/src/GirsLib/Tokenizer.cpp deleted file mode 100644 index d50e60f..0000000 --- a/src/GirsLib/Tokenizer.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include "Tokenizer.h" - -#ifdef ARDUINO -#define TOKEN2INT(tok) tok.toInt() -#else -#include - -// Emulate Arduino moron-ness (returning 0 in the case of parse error...), -// although it hurts... -int TOKEN2INT(const String& tok) { - try { - return std::stoi(tok); - } catch (std::invalid_argument& ex) { - //std::cout << "Exception caugth!" << std::endl; - return 0; - } -} -#endif - -Tokenizer::Tokenizer(const String& str) : index(0), payload(str) { - trim(); -} - -//Tokenizer::Tokenizer(const char *str) : index(0),payload(String(str)) { -// trim(); -//} - -void Tokenizer::trim() { -#if 0 -#ifdef ARDUINO - payload.trim(); -#else - payload.erase(0, payload.find_first_not_of(" \t\n\r")); - payload.erase(payload.find_last_not_of(" \t\n\r")+1, payload.length() - payload.find_last_not_of(" \t\n\r")); -#endif -#endif -} - -Tokenizer::~Tokenizer() { -} - -String Tokenizer::getRest() { - String result = index == invalidIndex ? String("") : -#ifdef ARDUINO - payload.substring(index); -#else - payload.substr(index); -#endif - index = invalidIndex; - return result; -} - -String Tokenizer::getLine() { - if (index == invalidIndex) - return String(""); - - int i = payload.indexOf('\n', index); - String s = (i > 0) ? -#ifdef ARDUINO - payload.substring(index, i) : payload.substring(index); -#else - payload.substr(index, i - index) : payload.substr(index); -#endif - index = (i > 0) ? i+1 : invalidIndex; - return s; -} - -String Tokenizer::getToken() { - if (index < 0) - return String(""); - - int i = payload.indexOf(' ', index); - String s = (i > 0) ? -#ifdef ARDUINO - payload.substring(index, i) : payload.substring(index); -#else - payload.substr(index, i-index) : payload.substr(index); -#endif - index = (i > 0) ? i : invalidIndex; - if (index != invalidIndex) - while (payload.charAt(index) == ' ') - index++; - return s; -} - -long Tokenizer::getInt() { - String token = getToken(); - return token == "" ? (long) invalid : TOKEN2INT(token); -} - -microseconds_t Tokenizer::getMicroseconds() { - long t = TOKEN2INT(getToken()); - return (microseconds_t) ((t < MICROSECONDS_T_MAX) ? t : MICROSECONDS_T_MAX); -} - -frequency_t Tokenizer::getFrequency() { - long t = TOKEN2INT(getToken()); - return (frequency_t) t; -} diff --git a/src/GirsLib/Tokenizer.h b/src/GirsLib/Tokenizer.h deleted file mode 100644 index 08e9ea5..0000000 --- a/src/GirsLib/Tokenizer.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include - -class Tokenizer { -private: - static const int invalidIndex = -1; - - int index; // signed since invalidIndex is possible - const String& payload; - void trim(); - -public: - Tokenizer(const String &str); - //Tokenizer(const char *str); - virtual ~Tokenizer(); - - String getToken(); - String getRest(); - String getLine(); - long getInt(); - microseconds_t getMicroseconds(); - frequency_t getFrequency(); - - static const int invalid = INT_MAX; -};