1
0

Compare commits

..

1 Commits

Author SHA1 Message Date
Jens Christian True
44cd1bd0c9 Drone secret for API key
All checks were successful
continuous-integration/drone/tag Build is passing
2019-10-08 15:37:20 +02:00
16 changed files with 282 additions and 409 deletions

@ -7,34 +7,13 @@ steps:
commands:
- pip install platformio
- pio run
- pio check --skip-packages --fail-on-defect medium > StaticCodeAnalysisReport.txt
- name: docs
image: corentinaltepe/doxygen
commands:
- doxygen
- name: release-dev
image: alpine
volumes:
- name: output
path: /output
commands:
- mkdir -p /output/dev/
- cp .pio/build/max7456board/firmware.hex /output/dev/firmware.hex
- cp -r docs/html/* /output/dev/docs/
- cp StaticCodeAnalysisReport.txt /output/dev/
- name: release-tag
image: alpine
volumes:
- name: output
path: /output
commands:
- cp -r /output/dev/ /output/${DRONE_SEMVER}/
- name: release
image: plugins/gitea-release
settings:
api_key:
from_secret: gitea_api_key
base_url: https://code.jcktrue.dk
files:
- .pio/build/max7456board/firmware.hex
when:
event:
- tag
volumes:
- name: output
host:
path: /home/jct/apps/http/share.jcktrue.dk/${DRONE_REPO_NAME}/
event: tag

1
.gitignore vendored

@ -1,7 +1,6 @@
.pio
.pioenvs
.piolibdeps
docs/
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json

67
.travis.yml Normal file

@ -0,0 +1,67 @@
# Continuous Integration (CI) is the practice, in software
# engineering, of merging all developer working copies with a shared mainline
# several times a day < https://docs.platformio.org/page/ci/index.html >
#
# Documentation:
#
# * Travis CI Embedded Builds with PlatformIO
# < https://docs.travis-ci.com/user/integration/platformio/ >
#
# * PlatformIO integration with Travis CI
# < https://docs.platformio.org/page/ci/travis.html >
#
# * User Guide for `platformio ci` command
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
#
#
# Please choose one of the following templates (proposed below) and uncomment
# it (remove "# " before each line) or use own configuration according to the
# Travis CI documentation (see above).
#
#
# Template #1: General project. Test it using existing `platformio.ini`.
#
# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# install:
# - pip install -U platformio
# - platformio update
#
# script:
# - platformio run
#
# Template #2: The project is intended to be used as a library with examples.
#
# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# env:
# - PLATFORMIO_CI_SRC=path/to/test/file.c
# - PLATFORMIO_CI_SRC=examples/file.ino
# - PLATFORMIO_CI_SRC=path/to/test/directory
#
# install:
# - pip install -U platformio
# - platformio update
#
# script:
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N

@ -1,7 +1,7 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}

@ -1,8 +0,0 @@
PROJECT_NAME = "MinimOSD-JSON"
OUTPUT_DIRECTORY = "docs/"
INPUT = "README.md" "src" "lib" "include"
EXTRACT_PRIVATE = YES
RECURSIVE = YES
WARNINGS = YES
GENERATE_LATEX = NO
USE_MDFILE_AS_MAINPAGE = README.md

@ -1,40 +0,0 @@
# MAX7456JSON
MAX7456JSON is an Arduino project for generating TUI interfaces on weird old school devices.
## Build
Use PlatFormIO [PlatformIO](https://platformio.org/) to build the project.
```bash
pip install platformio
git clone https://code.jcktrue.dk/jct/MAX7456JSON
pio run -t upload
```
## Usage
Send JSON commands over the serial port
```json
{"command":"write","x":1,"y":2,"text":"testing"}
```
# Documentation
Low level API documentation is auto generated and pushed to
[API docs](https://share.jcktrue.dk/MAX7456JSON/dev/docs/)
# Download
Ready made firmware images can be downloaded as HEX files.
- [Unstable](https://share.jcktrue.dk/MAX7456JSON/dev/)
- [Releases](https://share.jcktrue.dk/MAX7456JSON/)
## Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
## License
[MIT](https://choosealicense.com/licenses/mit/)

39
include/README Normal file

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

@ -1,38 +1,20 @@
/**
* @file config.h
* @author Jens True (jens.chr.true@gmail.com)
* @brief Global configuration
* @version 0.1
* @date 2021-11-10
*
* @copyright Copyright (c) 2021
*
*/
#ifndef CONFIG_H
#define CONFIG_H
/**
* Helper for joining strings
*/
#define STR_HELPER(x) #x
/**
* Stringify macro defines
*/
#define STR(x) STR_HELPER(x)
#define PROJECT_NAME "MinimOSD-JSON" /**< Project name */
#define VERSION_MAJOR 0 /**< Major version number */
#define VERSION_MINOR 1 /**< Minor version number */
#define VERSION_BUILD 1 /**< Build number */
#define PROJECT_NAME "MinimOSD-JSON"
#define VERSION_MAJOR 0
#define VERSION_MINOR 1
#define VERSION_BUILD 1
/**
* Semver style version number
*/
#define VERSION_STRING STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_BUILD)
#define VERSION_STRING STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_BUILD)
#define VERSION_DATE __DATE__
#define BAUDRATE 115200 /**< Serial baudrate */
#define DISP_OFFSET_X 49 /**< Display offset along the X-axis. Varies from display to display. */
#define DISP_OFFSET_Y 27 /**< Display offset along the Y-axis. Varies from display to display. */
#define BAUDRATE 115200
#define DISP_OFFSET_X 49
#define DISP_OFFSET_Y 27
#endif /* CONFIG_H */

@ -1,13 +1,3 @@
/**
* @file CommandHandler.cpp
* @author Jens True (jens.chr.true@gmail.com)
* @brief CommandHandler implementation
* @version 0.1
* @date 2021-11-10
*
* @copyright Copyright (c) 2021
*
*/
#include "CommandHandler.h"
#include "Arduino.h"
@ -18,12 +8,12 @@ CommandHandler::CommandHandler(DisplayProxy *display)
this->display = display;
}
bool CommandHandler::parseJSON(const char *cmd)
bool CommandHandler::parse(char *cmd)
{
debugSerial("parseJSON", cmd);
StaticJsonDocument<32> json;
DeserializationError error = deserializeJson(json, cmd);
Serial.print("Handling: ");
Serial.println(cmd);
StaticJsonDocument<32> doc;
DeserializationError error = deserializeJson(doc, cmd);
// Test if parsing succeeds.
if (error)
@ -33,14 +23,14 @@ bool CommandHandler::parseJSON(const char *cmd)
return false;
}
const char *command = json["cmd"];
if (strcmp("write", command) == 0 && json["text"].is<const char*>() && json["x"].is<int>() && json["y"].is<int>())
const char *command = doc["command"];
if (strcmp("write", command) == 0 && doc["text"].is<const char*>() && doc["x"].is<int>() && doc["y"].is<int>())
{
const char *text = json["text"];
int x = json["x"];
int y = json["y"];
const char *text = doc["text"];
int x = doc["x"];
int y = doc["y"];
this->debugSerial(command, text);
this->debugWrite(x, y, text);
this->display->write(x, y, text);
return true;
}
@ -48,28 +38,24 @@ bool CommandHandler::parseJSON(const char *cmd)
if (strcmp("clear", command) == 0)
{
this->display->clear();
return true;
}
if (strcmp("offset", command) == 0)
{
debugSerial("offset unhandled");
return false;
int x = doc["x"];
int y = doc["y"];
this->display->setOffset(x, y);
}
return false;
return true;
}
void CommandHandler::debugSerial(const char *text)
void CommandHandler::debugWrite(int x, int y, const char *text)
{
Serial.print(F("CommandHandler: "));
Serial.print(F("Writing ("));
Serial.print(x);
Serial.print(",");
Serial.print(y);
Serial.print("): ");
Serial.println(text);
}
void CommandHandler::debugSerial(const char *command, const char *text)
{
Serial.print(F("CommandHandler: "));
Serial.print(command);
Serial.print(" > ");
Serial.println(text);
}
}

@ -1,59 +1,14 @@
/**
* @file CommandHandler.h
* @author Jens True (jens.chr.true@gmail.com)
* @brief CommandHandler Header
* @version 0.1
* @date 2021-11-10
*
* @copyright Copyright (c) 2021
*
*/
#ifndef COMMANDHANDLER_H
#define COMMANDHANDLER_H
#include "DisplayProxy.h"
/**
* Parse a JSON command and convert it into display command(s).
*/
class CommandHandler
{
public:
/**
* Constructor.
*
* @param display Takes an implementation of DisplayProxy through polymorphism.
*/
explicit CommandHandler(DisplayProxy *display);
/**
* Parse a command in JSON format
* @code{.json}
* To display a string
*
* {"cmd":"write","x": 2, "y": 10, "text":"Hello World"}
*
* or to clear the display
*
* {"cmd":"clear"}
* @endcode
*
* @param cmd String to parse
* @return True if the input was parsed correctly.
*/
bool parseJSON(const char *cmd);
CommandHandler(DisplayProxy *display);
bool parse(char *cmd);
private:
/**
* Internal helper for printing debug strings
*/
void debugSerial(const char *text);
/**
* @overload
*/
void debugSerial(const char *command, const char *text);
/**
* Display instance
*/
void debugWrite(int x, int y, const char *text);
DisplayProxy *display;
};

@ -1,49 +1,10 @@
/**
* @file DisplayProxy.h
* @author Jens True (jens.chr.true@gmail.com)
* @brief DisplayProxy header
* @version 0.1
* @date 2021-11-10
*
* @copyright Copyright (c) 2021
*
*/
#ifndef DISPLAYPROXY_H
#define DISPLAYPROXY_H
/**
* Generic interface for a graphical display allowing for placement of text.
* Focused on TUI.
*/
class DisplayProxy
{
public:
/**
* Turn on the display.
* @return True if successful.
*/
virtual bool on() = 0;
/**
* Turn off the display.
* @return True if successful.
*/
virtual bool off() = 0;
/**
* Write a string to the display.
*
* @param x Horizontal starting position. From left to right. (0 indexed)
* @param y Vertical starting position. From top to bottom. (0 indexed)
* @param text String to write
* @return True if successful.
*/
virtual bool write(int x, int y, const char *text) = 0;
/**
* Clear the entire screen.
* @return True if successful.
*/
virtual bool clear() = 0;
virtual bool setOffset(int x, int y) = 0;
};
#endif

@ -1,37 +1,8 @@
/**
* @file DisplayProxyMAX7456.cpp
* @author Jens True (jens.chr.true@gmail.com)
* @brief DisplayProxyMAX7456 Implementation
* @version 0.1
* @date 2021-11-10
*
* @copyright Copyright (c) 2021
*
*/
#include "DisplayProxyMAX7456.h"
DisplayProxyMAX7456::DisplayProxyMAX7456()
DisplayProxyMAX7456::DisplayProxyMAX7456(Max7456 *osd)
{
this->osd = new Max7456();
this->osd->init(6);
clear();
this->osd->setBlinkParams(_8fields, _BT_3BT);
externalVideo(false);
onScreenDisplay(true);
}
bool DisplayProxyMAX7456::on()
{
onScreenDisplay(true);
return true;
}
bool DisplayProxyMAX7456::off()
{
externalVideo(false);
onScreenDisplay(false);
return true;
this->osd = osd;
}
bool DisplayProxyMAX7456::write(int x, int y, const char *text)
@ -50,16 +21,4 @@ bool DisplayProxyMAX7456::setOffset(int x, int y)
{
this->osd->setDisplayOffsets(x, y);
return true;
}
bool DisplayProxyMAX7456::externalVideo(bool enabled)
{
this->osd->activateExternalVideo(enabled);
return true;
}
bool DisplayProxyMAX7456::onScreenDisplay(bool enabled)
{
this->osd->activateOSD(enabled);
return true;
}

@ -1,81 +1,18 @@
/**
* @file DisplayProxyMAX7456.h
* @author Jens True (jens.chr.true@gmail.com)
* @brief DisplayProxyMAX7456 header
* @version 0.1
* @date 2021-11-10
*
* @copyright Copyright (c) 2021
*
*/
#ifndef DISPLAYPROXYMAX7456_H
#define DISPLAYPROXYMAX7456_H
#include "DisplayProxy.h"
#include "max7456.h"
/**
* Text-User-Interface on a MAX7456
*
* The MAX7456 provides On-Screen-Display rendering for composite video.
* (Think old school VCR menu overlay)
*
* To find the offical documentation for the part please refer to the Maxim page for the MAX7456.
* [Maxim Page](https://www.maximintegrated.com/en/products/analog/video-products/MAX7456.html)
*
*/
class DisplayProxyMAX7456 : public DisplayProxy
{
public:
/**
* Initalize a MAX7456 Style display
* - Initialize with CS on Pin 6.
* - Clear the display
* - Initialize blinking frequency.
* - Disable external video
* - Enable OSD.
*/
explicit DisplayProxyMAX7456();
DisplayProxyMAX7456(Max7456 *osd);
/**
* OSD on, external video left untouched.
*/
bool on() override;
/**
* OSD off, external video off.
*/
bool off() override;
/**
* Depending on the font loaded into the Max7456 the output might not be ASCII compatible.
*/
bool write(int x, int y, const char *text) override;
bool clear() override;
/**
* Adjust the display offset.
* Since the signal is analog the characters might be rendered outside the display area
*/
bool write(int x, int y, const char *text);
bool clear() ;
bool setOffset(int x, int y);
/**
* Turn off the external video feed
* If the external feed is disabled the background will be grey
* @param enabled True to turn on the external video input
*/
bool externalVideo(bool enabled);
/**
* Turn on the overlay
*
* @param enabled True to turn on the overlay
*/
bool onScreenDisplay(bool enabled);
private:
/**
* @brief Reference to the OSD instance.
*/
Max7456 *osd;
};

46
lib/README Normal file

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

@ -1,5 +1,15 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:max7456board]
platform = atmelavr
board = pro16MHzatmega328
platform = atmelavr
board = pro16MHzatmega328
framework = arduino
lib_deps = ArduinoJson@6.18.5, git+https://github.com/Avamander/max7456#4fec91e
lib_deps = ArduinoJson, git+https://github.com/Avamander/max7456

@ -1,74 +1,75 @@
/**
* @file main.cpp
* @author Jens True (jens.chr.true@gmail.com)
* @brief
* @version 0.1
* @date 2021-11-10
* @copyright Copyright (c) 2021
*
* Main application entry point.
* Arduino Style but still a .cpp file
*/
#include "Arduino.h"
#include <SPI.h>
#include "config.h"
#include "CommandHandler.h"
#include "DisplayProxyMAX7456.h"
#include "max7456.h"
Max7456 osd;
DisplayProxyMAX7456 proxy(&osd);
CommandHandler cmd_handler(&proxy);
/**
* @brief Instance of DisplayProxyMAX7456
*/
DisplayProxyMAX7456 display;
/**
* @brief The commandhandler needs a reference to a display instance
*
* @return CommandHandler
*/
CommandHandler cmd_handler(&display);
/**
* Setup handler (Arduino Style)
*
* Write some debug information to the serial port and initialize the display.
*/
// cppcheck-suppress unusedFunction
void setup()
void processSerial()
{
Serial.begin(BAUDRATE);
static byte ndx = 0;
char endMarker = '\n';
char rc;
Serial.println("================================================================================");
Serial.println("Firmware: " PROJECT_NAME);
Serial.println("Version: " VERSION_STRING);
Serial.println("Built: " __DATE__ ", " __TIME__);
Serial.println("================================================================================");
Serial.println("Initialize...");
const byte numChars = 128;
char receivedChars[numChars]; // an array to store the received data
display.setOffset(DISP_OFFSET_X, DISP_OFFSET_Y);
while (Serial.available() > 0)
{
rc = Serial.read();
display.write(0, 0, "==========================");
display.write(0, 1, "Firmware: " PROJECT_NAME);
display.write(0, 2, "Version: " VERSION_STRING);
display.write(0, 3, "Built: " __DATE__ ", " __TIME__);
display.write(0, 4, "==========================");
delay(3000);
display.clear();
Serial.println("Ready!");
if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
cmd_handler.parse(receivedChars);
}
}
}
void setup()
{
Serial.begin(BAUDRATE);
Serial.println("================================================================================");
Serial.println("Firmware: " PROJECT_NAME);
Serial.println("Version: " VERSION_STRING);
Serial.println("Built: " __DATE__ ", " __TIME__);
Serial.println("================================================================================");
Serial.println("Initialize...");
SPI.begin();
osd.init(6);
osd.clearScreen();
osd.setDisplayOffsets(DISP_OFFSET_X, DISP_OFFSET_Y);
osd.setBlinkParams(_8fields, _BT_3BT);
osd.activateOSD();
osd.activateExternalVideo(false);
osd.print("==========================", 0, 0);
osd.print("Firmware: " PROJECT_NAME, 0, 1);
osd.print("Version: " VERSION_STRING, 0, 2);
osd.print("Built: " __DATE__ ", " __TIME__, 0, 3);
osd.print("==========================", 0, 4);
delay(3000);
osd.clearScreen();
Serial.println("Ready!");
}
/**
* Loop handler (Arduino Style)
*
* Continously read the serial port if input is available. On line change send to the command handler.
*/
// cppcheck-suppress unusedFunction
void loop()
{
while (Serial.available() > 0)
{
String input = Serial.readStringUntil('\n');
cmd_handler.parseJSON(input.c_str());
}
processSerial();
}