diff --git a/MAPID-CP/MAPID-CP.ino b/MAPID-CP/MAPID-CP.ino new file mode 100644 index 0000000..386612d --- /dev/null +++ b/MAPID-CP/MAPID-CP.ino @@ -0,0 +1,205 @@ +/** + * MAPID/CP + * + * Malte's Arduino-Powered Info Display Control Program + */ +#include +#include +#include +#include + +#include "boards.h" +#include "config.h" +#include "readme.h" + +#ifndef README_PROGMEM +#pragma warning "README_PROGMEM not set. The command README will not work." +#endif + +SerialCommand SCmd; +serLCD lcd(PIN_LCD); +int line; + +void setup() { + pinMode(PIN_LED, OUTPUT); + digitalWrite(PIN_LED, LOW); + + Serial.begin(TTY_SPEED); + while (!Serial); + + Serial.print("Booting..."); + + // Generic + SCmd.addCommand("VER", showVersion); + SCmd.addCommand("GETTY", showGetty); + SCmd.addCommand("HELP", help); + // LED + SCmd.addCommand("ON", ledOn); + SCmd.addCommand("OFF", ledOff); + // LCD + SCmd.addCommand("ECHO", lcdEcho); + SCmd.addCommand("CLS", lcdClear); + SCmd.addCommand("LINE", lcdLine); + // Show README + SCmd.addCommand("README", showReadMe); + + SCmd.addDefaultHandler(commandNotFound); + + + Serial.println("Ready."); + Serial.print("Running "); + Serial.print(OS_NAME); + Serial.print(" v"); + Serial.println(OS_VERSION); + Serial.println("Connected to TTY"); + + Serial.println("[INFO] Commands are all uppercase!"); + line = 1; + lcd.clear(); + lcd.selectLine(line); + lcd.print("Welcome to"); + lcd.selectLine(2); + lcd.print(OS_NAME); + lcd.print(" v"); + lcd.print(OS_VERSION); + + // Show prompt + Serial.println(); + Serial.print(TTY_PROMPT); +} + +void loop() { + SCmd.readSerial(); +} + +void commandNotFound() { + Serial.println(""); + //Serial.println("[ERROR @ TTY:IN] COMMAND NOT FOUND!"); + Serial.println("[ERROR] COMMAND NOT FOUND!"); + + // Show prompt again + Serial.print(TTY_PROMPT); +} + + +void lcdEcho() { + Serial.println(""); + char *text; + + //lcd.clear(); + Serial.print(" [INFO] Writing text to LCD: "); + for (int i=0; i<16; i++) { + // Loop repeats once per token + //text = text = SCmd.next(); + text = SCmd.next(); + + if (text == NULL) + break; + + // Since tokens don't include SPACE, print it to debug OUTPUT + if (i > 0) + Serial.print(" "); + Serial.print(text); + + if (i > 0) + lcd.print(" "); + lcd.print(text); + } + + // Show prompt again + Serial.println(); + Serial.print(TTY_PROMPT); +} + +void lcdLine() { + Serial.println(""); + line = atoi(SCmd.next()); + Serial.print(" [INFO] Select line "); + Serial.print(line); + Serial.println(""); + lcd.selectLine(line); + + // Show prompt again + Serial.print(TTY_PROMPT); +} + +void lcdClear() { + Serial.println(""); + lcd.clear(); + + // Show prompt again + Serial.println(); + Serial.print(TTY_PROMPT); +} + +void showVersion() { + Serial.println(""); + Serial.print(OS_NAME); + Serial.print(" v"); + Serial.println(OS_VERSION); + Serial.print("Hardware: "); + Serial.println(BOARD); + + Serial.print(TTY_PROMPT); +} + +void showGetty() { + Serial.println(""); + lcd.clear(); + lcd.selectLine(1); + lcd.print("Welcome to"); + lcd.selectLine(2); + lcd.print(OS_NAME); + lcd.print(" v"); + lcd.print(OS_VERSION); + + // Show prompt again + Serial.print(TTY_PROMPT); +} + +void showReadMe() { + #ifdef README_PROGMEM + Serial.print(readme); + #else + Serial.println("Option README_PROGMEM not set in config.h!"); + #endif +} + +void help() { + Serial.println(); + Serial.println("Commands:"); + Serial.println(" VER"); + Serial.println(" GETTY"); + Serial.println(" HELP"); + Serial.println(" CLS"); + Serial.println(" ON"); + Serial.println(" OFF"); + Serial.println(" ECHO Text"); + Serial.println(" LINE i"); + + // Show prompt again + Serial.println(); + Serial.print(TTY_PROMPT); +} + +void ledOn() { + Serial.println(""); + Serial.println("Turning LED to *ON*"); + + //lcd.println("LED on"); + digitalWrite(PIN_LED, HIGH); + + // Show prompt again + Serial.print(TTY_PROMPT); +} + +void ledOff() { + Serial.println(""); + Serial.println("Turning LED to *OFF*"); + + //lcd.println("LED off"); + digitalWrite(PIN_LED, LOW); + + // Show prompt again + Serial.print(TTY_PROMPT); +} diff --git a/MAPID-CP/Makefile b/MAPID-CP/Makefile new file mode 100644 index 0000000..d1fb226 --- /dev/null +++ b/MAPID-CP/Makefile @@ -0,0 +1,169 @@ +# Makefile for Arduino based scketches +# +# Copyright 2020 Valerio Di Giampietro http://va.ler.io v@ler.io +# MIT License - see License.txt file +# +# This Makefile uses the arduino-cli, the Arduino command line interface +# and has been designed and tested to run on Linux, not on Windows. +# Probably it will run on a Mac, but it has not been tested. +# +# Please note that: +# +# 1. each sketch must reside in his own folder with this Makefile +# +# 2. the main make targets are: +# - all compiles and upload +# - compile compiles only +# - upload upload via serial port, compile if the binary file is +# not available +# - ota upload Over The Air, automatically find the device +# IP address using the IOT_NAME (device hostname) +# - clean clean the build directory +# - find find OTA updatable devices on the local subnet +# - requirements it the file "requirements.txt" exists it will +# install the libraries listed in this file +# +# default is "all" +# +# 3. it gets the name of the sketch using the wildcard make command; +# the name is *.ino; this means that you must have ONLY a file +# with .ino extension, otherwise this makefile will break. This +# also means that you can use this Makefile, almost unmodified, +# for any sketch as long as you keep a single .ino file in each +# folder +# +# 4. you can split your project in multiple files, if you wish, +# using a single .ino file and multiple .h files, that you can +# include in the .ino file with an '#include "myfile.h"' +# directive +# +# Optionally some environment variables can be set: +# +# FQBN Fully Qualified Board Name; if not set in the environment +# it will be assigned a value in this makefile +# +# SERIAL_DEV Serial device to upload the sketch; if not set in the +# environment it will be assigned: +# /dev/ttyUSB0 if it exists, or +# /dev/ttyACM0 if it exists, or +# unknown +# +# IOT_NAME Name of the IOT device; if not set in the environment +# it will be assigned a value in this makefile. This is +# very useful for OTA update, the device will be searched +# on the local subnet using this name +# +# OTA_PORT Port used by OTA update; if not set in the environment +# it will be assigned the default value of 8266 in this +# makefile +# +# OTA_PASS Password used for OTA update; if not set in the environment +# it will be assigned the default value of an empty string +# +# V verbose flag; can be 0 (quiet) or 1 (verbose); if not set +# in the environment it will be assigned a default value +# in this makefile + + +MAKE_DIR := $(PWD) +# +# ----- setup wor Wemos D1 mini ----- +#FQBN ?= esp8266:esp8266:d1_mini +#IOT_NAME ?= esp8266-meteo +#OTA_PORT ?= 8266 +#OTA_PASS ?= +# ----- setup for Arduino Uno +FQBN ?= arduino:avr:uno +# ----- --------------------- +V ?= 0 +VFLAG = + +ifeq "$(V)" "1" +VFLAG =-v +endif + +ifndef SERIAL_DEV + ifneq (,$(wildcard /dev/ttyUSB0)) + SERIAL_DEV = /dev/ttyUSB0 + else ifneq (,$(wildcard /dev/ttyACM0)) + SERIAL_DEV = /dev/ttyACM0 + else + SERIAL_DEV = unknown + endif +endif + +BUILD_DIR := $(subst :,.,build/$(FQBN)) + +SRC := $(wildcard *.ino) +HDRS := $(wildcard *.h) +BIN := $(BUILD_DIR)/$(SRC).bin +ELF := $(BUILD_DIR)/$(SRC).elf + +$(info FQBN is [${FQBN}]) +$(info IOT_NAME is [${IOT_NAME}]) +$(info OTA_PORT is [${OTA_PORT}]) +$(info OTA_PASS is [${OTA_PASS}]) +$(info V is [${V}]) +$(info VFLAG is [${VFLAG}]) +$(info MAKE_DIR is [${MAKE_DIR}]) +$(info BUILD_DIR is [${BUILD_DIR}]) +$(info SRC is [${SRC}]) +$(info HDRS is [${HDRS}]) +$(info BIN is [${BIN}]) +$(info SERIAL_DEV is [${SERIAL_DEV}]) + +all: $(ELF) upload +.PHONY: all + +compile: $(ELF) +.PHONY: compile + +$(ELF): $(SRC) $(HDRS) + arduino-cli compile -b $(FQBN) $(VFLAG) + @if which arduino-manifest.pl; \ + then echo "---> Generating manifest.txt"; \ + arduino-manifest.pl -b $(FQBN) $(SRC) $(HDRS) > manifest.txt; \ + else echo "---> If you want to generate manifest.txt, listing used libraries and their versions,"; \ + echo "---> please install arduino-manifest, see https://github.com/digiampietro/arduino-manifest"; \ + fi + +upload: + @if [ ! -c $(SERIAL_DEV) ] ; \ + then echo "---> ERROR: Serial Device not available, please set the SERIAL_DEV environment variable" ; \ + else echo "---> Uploading sketch\n"; \ + arduino-cli upload -b $(FQBN) -p $(SERIAL_DEV) $(VFLAG); \ + fi + +ota: + @PLAT_PATH=`arduino-cli compile -b $(FQBN) --show-properties | grep '^runtime.platform.path' | awk -F= '{print $$2}'` ; \ + PY_PATH=`arduino-cli compile -b $(FQBN) --show-properties | grep '^runtime.tools.python3.path' | awk -F= '{print $$2}'` ; \ + IOT_IP=`avahi-browse _arduino._tcp --resolve --parsable --terminate|grep -i ';$(IOT_NAME);'|grep ';$(OTA_PORT);'| awk -F\; '{print $$8}'|head -1`; \ + BINFILE=$(wildcard $(BUILD_DIR)/$(SRC)*bin); \ + echo "PLAT_PATH is [$$PLAT_PATH]" ; \ + echo "PY_PATH: is [$$PY_PATH]" ; \ + echo "IOT_IP: is [$$IOT_IP]" ; \ + echo "BINFILE: is [$$BINFILE]" ; \ + if [ "$$IOT_IP" = "" ] ; \ + then echo "Unable to find device IP. Check that the IOT_NAME environment variable is correctly set. Use 'make find' to search devices"; \ + else echo "---> Uploading Over The Air"; \ + $$PY_PATH/python3 $$PLAT_PATH/tools/espota.py -i $$IOT_IP -p $(OTA_PORT) --auth=$(OTA_PASS) -f $$BINFILE ;\ + fi + +clean: + @echo "---> Cleaning the build directory" + rm -rf build + +find: + avahi-browse _arduino._tcp --resolve --parsable --terminate + +requirements: + @if [ -e requirements.txt ]; \ + then while read -r i ; do echo ; \ + echo "---> Installing " '"'$$i'"' ; \ + arduino-cli lib install "$$i" ; \ + done < requirements.txt ; \ + else echo "---> MISSING requirements.txt file"; \ + fi + + + diff --git a/MAPID-CP/boards.h b/MAPID-CP/boards.h new file mode 100644 index 0000000..f0b3a21 --- /dev/null +++ b/MAPID-CP/boards.h @@ -0,0 +1,90 @@ +#ifndef _BOARDS_H_ +#define _BOARDS_H_ + +/* + * https://arduino.stackexchange.com/a/19894 + * https://arduino.stackexchange.com/a/21257 + */ +#if defined(TEENSYDUINO) + + // --------------- Teensy ----------------- + + #if defined(__AVR_ATmega32U4__) + #define BOARD "Teensy 2.0" + #elif defined(__AVR_AT90USB1286__) + #define BOARD "Teensy++ 2.0" + #elif defined(__MK20DX128__) + #define BOARD "Teensy 3.0" + #elif defined(__MK20DX256__) + #define BOARD "Teensy 3.2" // and Teensy 3.1 (obsolete) + #elif defined(__MKL26Z64__) + #define BOARD "Teensy LC" + #elif defined(__MK64FX512__) + #define BOARD "Teensy 3.5" + #elif defined(__MK66FX1M0__) + #define BOARD "Teensy 3.6" + #else + #error "Unknown board" + #endif + +#else // --------------- Arduino ------------------ + + #if defined(ARDUINO_AVR_ADK) + #define BOARD "Mega Adk" + #elif defined(ARDUINO_AVR_BT) // Bluetooth + #define BOARD "Bt" + #elif defined(ARDUINO_AVR_DUEMILANOVE) + #define BOARD "Duemilanove" + #elif defined(ARDUINO_AVR_ESPLORA) + #define BOARD "Esplora" + #elif defined(ARDUINO_AVR_ETHERNET) + #define BOARD "Ethernet" + #elif defined(ARDUINO_AVR_FIO) + #define BOARD "Fio" + #elif defined(ARDUINO_AVR_GEMMA) + #define BOARD "Gemma" + #elif defined(ARDUINO_AVR_LEONARDO) + #define BOARD "Leonardo" + #elif defined(ARDUINO_AVR_LILYPAD) + #define BOARD "Lilypad" + #elif defined(ARDUINO_AVR_LILYPAD_USB) + #define BOARD "Lilypad Usb" + #elif defined(ARDUINO_AVR_MEGA) + #define BOARD "Mega" + #elif defined(ARDUINO_AVR_MEGA2560) + #define BOARD "Mega 2560" + #elif defined(ARDUINO_AVR_MICRO) + #define BOARD "Micro" + #elif defined(ARDUINO_AVR_MINI) + #define BOARD "Mini" + #elif defined(ARDUINO_AVR_NANO) + #define BOARD "Nano" + #elif defined(ARDUINO_AVR_NG) + #define BOARD "NG" + #elif defined(ARDUINO_AVR_PRO) + #define BOARD "Pro" + #elif defined(ARDUINO_AVR_ROBOT_CONTROL) + #define BOARD "Robot Ctrl" + #elif defined(ARDUINO_AVR_ROBOT_MOTOR) + #define BOARD "Robot Motor" + #elif defined(ARDUINO_AVR_UNO) + #define BOARD "Uno" + #elif defined(ARDUINO_AVR_YUN) + #define BOARD "Yun" + + // These boards must be installed separately: + #elif defined(ARDUINO_SAM_DUE) + #define BOARD "Due" + #elif defined(ARDUINO_SAMD_ZERO) + #define BOARD "Zero" + #elif defined(ARDUINO_ARC32_TOOLS) + #define BOARD "101" + #else + #error "Unknown board" + #endif + +#endif + +const char boardName[]=BOARD; + +#endif diff --git a/MAPID-CP/config.h b/MAPID-CP/config.h new file mode 100644 index 0000000..8fb635d --- /dev/null +++ b/MAPID-CP/config.h @@ -0,0 +1,16 @@ +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +#define OS_NAME "MAPID/CP" +#define OS_VERSION 3 + +#define PIN_LED LED_BUILTIN +#define PIN_LCD 2 +#define TTY_SPEED 9600 +//#define TTY_SPEED 19200 +#define TTY_PROMPT "?" + +// Include Readme in PROGMEM, and allow access to it. +#define README_PROGMEM + +#endif diff --git a/MAPID-CP/readme.h b/MAPID-CP/readme.h new file mode 100644 index 0000000..51baf7f --- /dev/null +++ b/MAPID-CP/readme.h @@ -0,0 +1,75 @@ +#ifndef _README_H_ +#define _README_H_ + +#ifdef README_PROGMEM + +const char readme[] PROGMEM = { +" \n" +" .88b d88. .d8b. d8888b. d888888b d8888b. dD .o88b. d8888b. \n" +" 88'YbdP`88 d8' `8b 88 `8D `88' 88 `8D d8' d8P Y8 88 `8D \n" +" 88 88 88 88ooo88 88oodD' 88 88 88 d8' 8P 88oodD' \n" +" 88 88 88 88~~~88 88~~~ 88 88 88 d8' 8b 88~~~ \n" +" 88 88 88 88 88 88 .88. 88 .8D d8' Y8b d8 88 \n" +" YP YP YP YP YP 88 Y888888P Y8888D' C8' `Y88P' 88 \n" +" \n" +" \n" +" d8888b. d88888b .d8b. d8888b. .88b d88. d88888b \n" +" 88 `8D 88' d8' `8b 88 `8D 88'YbdP`88 88' \n" +" 88oobY' 88ooooo 88ooo88 88 88 88 88 88 88ooooo \n" +" 88`8b 88~~~~~ 88~~~88 88 88 88 88 88 88~~~~~ \n" +" 88 `88. 88. 88 88 88 .8D 88 88 88 88. \n" +" 88 YD Y88888P YP YP Y8888D' YP YP YP Y88888P \n" +" \n" +" \n" +" \n" +" \n" +" > Since the Arduino IDE doesn't allow adding text files to a sketch, the \n" +" > README is provided by this useless header file. \n" +" \n" +" \n" +"==> Requirements \n" +" \n" +"MAPID/CP depends on the following libraries: \n" +" \n" +" - SoftwareSerial \n" +" - serLCD \n" +" - SerialCommand \n" +" \n" +" \n" +"==> config.h Options \n" +" \n" +" ┏━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ \n" +" ┃ Macro name ┃ Default value ┃ Description ┃ \n" +" ┡━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ \n" +" │ OS_NAME │ MAPID/CP │ Shown on startup and by command GETTY │ \n" +" │ OS_VERSION │ 2 │ - same as above - │ \n" +" │ PIN_LED │ 13 │ PIN for the configurable LED │ \n" +" │ PIN_LCD │ 2 │ PIN for SerLCD RX │ \n" +" │ TTY_SPEED │ 9600 │ Terminal sped (baud) │ \n" +" │ TTY_PROMPT │ ? │ Shell Prompt │ \n" +" └──────────────┴─────────────────┴─────────────────────────────────────────┘ \n" +" \n" +" \n" +"==> To do \n" +" \n" +" [ ] Move static texts shown on the console to flash memory using PROGMEM: \n" +" https://www.arduino.cc/reference/en/language/variables/utilities/progmem/\n" +" \n" +" \n" +"-- \n" +"Malte Bublitz \n" +"https://malte70.de \n" +" \n" +"==> Appendix \n" +" \n" +"Unicode Box Drawing characters used for the config.h overview table: \n" +" https://en.wikipedia.org/wiki/Box_Drawing \n" +" \n" +}; + + +//#define README_HEADLINE_FIGLET_CMD "figlet -f basic -c -w 80 \"MAPID/CP\nReadMe\"" + + +#endif +#endif