mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[ion] Move the bench test in ion
Change-Id: I54b99678df969e6e3e86c2d3858d04088a40f047
This commit is contained in:
@@ -1,280 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <ion.h>
|
||||
#include <ion/src/device/backlight.h>
|
||||
#include <ion/src/device/display.h>
|
||||
#include <ion/src/device/led.h>
|
||||
#include <poincare.h>
|
||||
|
||||
typedef void (*CommandFunction)(const char * input);
|
||||
|
||||
void command_ping(const char * input);
|
||||
void command_mcu_serial(const char * input);
|
||||
|
||||
class CommandHandler {
|
||||
public:
|
||||
constexpr CommandHandler(const char * name, CommandFunction function) :
|
||||
m_name(name), m_function(function) {}
|
||||
bool valid() const;
|
||||
bool handle(const char * command) const;
|
||||
private:
|
||||
bool matches(const char * command) const;
|
||||
const char * m_name;
|
||||
CommandFunction m_function;
|
||||
};
|
||||
|
||||
bool CommandHandler::valid() const {
|
||||
return (m_name != nullptr && m_function != nullptr);
|
||||
}
|
||||
|
||||
bool CommandHandler::handle(const char * command) const {
|
||||
if (matches(command)) {
|
||||
size_t nameLength = strlen(m_name);
|
||||
if (command[nameLength] == '=') {
|
||||
m_function(command+nameLength+1); // Skip the "Equal character"
|
||||
} else {
|
||||
m_function(nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CommandHandler::matches(const char * command) const {
|
||||
const char * c = command;
|
||||
const char * n = m_name;
|
||||
while (true) {
|
||||
if (*n == NULL) {
|
||||
if (*c == NULL || *c == '=') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (*c != *n) {
|
||||
return false;
|
||||
}
|
||||
c++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
class CommandList {
|
||||
public:
|
||||
constexpr CommandList(const CommandHandler * handlers) : m_handlers(handlers) {}
|
||||
void dispatch(const char * command) const;
|
||||
private:
|
||||
const CommandHandler * m_handlers;
|
||||
};
|
||||
|
||||
void CommandList::dispatch(const char * command) const {
|
||||
const CommandHandler * handler = m_handlers;
|
||||
while (handler->valid()) {
|
||||
if (handler->handle(command)) {
|
||||
return;
|
||||
}
|
||||
handler++;
|
||||
}
|
||||
Ion::Console::writeLine("NOT_FOUND");
|
||||
}
|
||||
|
||||
static const char * sOK = "OK";
|
||||
static const char * sKO = "KO";
|
||||
static const char * sSyntaxError = "SYNTAX_ERROR";
|
||||
static const char * sON = "ON";
|
||||
static const char * sOFF = "OFF";
|
||||
|
||||
void command_ping(const char * input) {
|
||||
if (input != nullptr) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
Ion::Console::writeLine("PONG");
|
||||
}
|
||||
|
||||
void command_mcu_serial(const char * input) {
|
||||
if (input != nullptr) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
char response[11+24+1] = {'M', 'C', 'U', '_', 'S', 'E', 'R', 'I', 'A', 'L', '=', 0};
|
||||
strlcpy(response+11, Ion::serialNumber(), 25);
|
||||
Ion::Console::writeLine(response);
|
||||
}
|
||||
|
||||
static inline int8_t hexChar(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return (c - '0');
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return (c - 'A') + 0xA;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
static inline bool isHex(char c) { return hexChar(c) >= 0; }
|
||||
static inline uint32_t hexNumber(const char * s) {
|
||||
uint32_t result = 0;
|
||||
while (*s != NULL) {
|
||||
result = (result << 4) | hexChar(*s++);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void command_led(const char * input) {
|
||||
// Input must be of the form "0xAABBCC" or "ON" or "OFF"
|
||||
if (strcmp(input, sON) == 0) {
|
||||
Ion::LED::Device::init();
|
||||
Ion::Console::writeLine(sOK);
|
||||
return;
|
||||
}
|
||||
if (strcmp(input, sOFF) == 0) {
|
||||
Ion::LED::Device::shutdown();
|
||||
Ion::Console::writeLine(sOK);
|
||||
return;
|
||||
}
|
||||
if (input == nullptr || input[0] != '0' || input[1] != 'x' || !isHex(input[2]) ||!isHex(input[3]) || !isHex(input[4]) || !isHex(input[5]) || !isHex(input[6]) || !isHex(input[7]) || input[8] != NULL) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
uint32_t hexColor = hexNumber(input+2);
|
||||
KDColor ledColor = KDColor::RGB24(hexColor);
|
||||
Ion::LED::setColor(ledColor);
|
||||
Ion::Console::writeLine(sOK);
|
||||
}
|
||||
|
||||
void command_display(const char * input) {
|
||||
// Input must be of the form "0xAABBCC" or "ON" or "OFF"
|
||||
|
||||
if (strcmp(input, sON) == 0) {
|
||||
Ion::Display::Device::init();
|
||||
Ion::Console::writeLine(sOK);
|
||||
return;
|
||||
}
|
||||
if (strcmp(input, sOFF) == 0) {
|
||||
Ion::Display::Device::shutdown();
|
||||
Ion::Console::writeLine(sOK);
|
||||
return;
|
||||
}
|
||||
if (input == nullptr || input[0] != '0' || input[1] != 'x' || !isHex(input[2]) ||!isHex(input[3]) || !isHex(input[4]) || !isHex(input[5]) || !isHex(input[6]) || !isHex(input[7]) || input[8] != NULL) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We fill the screen with a color and return OK if we read that color back everywhere. */
|
||||
|
||||
KDColor c = KDColor::RGB24(hexNumber(input));
|
||||
|
||||
constexpr int stampHeight = 10;
|
||||
constexpr int stampWidth = 10;
|
||||
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
|
||||
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
|
||||
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
|
||||
|
||||
KDColor stamp[stampWidth*stampHeight];
|
||||
for (int i=0;i<stampWidth*stampHeight; i++) {
|
||||
stamp[i] = c;
|
||||
}
|
||||
|
||||
for (int i=0; i<Ion::Display::Width/stampWidth; i++) {
|
||||
for (int j=0; j<Ion::Display::Height/stampHeight; j++) {
|
||||
Ion::Display::pushRect(KDRect(i*stampWidth, j*stampHeight, stampWidth, stampHeight), stamp);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<Ion::Display::Width/stampWidth; i++) {
|
||||
for (int j=0; j<Ion::Display::Height/stampHeight; j++) {
|
||||
for (int i=0;i<stampWidth*stampHeight; i++) {
|
||||
stamp[i] = KDColorBlack;
|
||||
}
|
||||
Ion::Display::pullRect(KDRect(i*stampWidth, j*stampHeight, stampWidth, stampHeight), stamp);
|
||||
for (int i=0;i<stampWidth*stampHeight; i++) {
|
||||
if (stamp[i] != c) {
|
||||
Ion::Console::writeLine(sKO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ion::Console::writeLine(sOK);
|
||||
}
|
||||
|
||||
void command_backlight(const char * input) {
|
||||
// Input must be of the form "0xAA" or "ON" or "OFF"
|
||||
if (strcmp(input, sON) == 0) {
|
||||
Ion::Backlight::Device::init();
|
||||
Ion::Console::writeLine(sOK);
|
||||
return;
|
||||
}
|
||||
if (strcmp(input, sOFF) == 0) {
|
||||
Ion::Backlight::Device::shutdown();
|
||||
Ion::Console::writeLine(sOK);
|
||||
return;
|
||||
}
|
||||
if (input == nullptr || input[0] != '0' || input[1] != 'x' || !isHex(input[2]) ||!isHex(input[3]) || input[4] != NULL) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
uint32_t brightness = hexNumber(input+2);
|
||||
Ion::Backlight::setBrightness(brightness);
|
||||
Ion::Console::writeLine(sOK);
|
||||
}
|
||||
|
||||
void command_adc(const char * input) {
|
||||
if (input != nullptr) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
float result = Ion::Battery::voltage();
|
||||
constexpr int precision = 8;
|
||||
constexpr int bufferSize = Poincare::Complex::bufferSizeForFloatsWithPrecision(precision);
|
||||
char responseBuffer[bufferSize+4] = {'A', 'D', 'C', '='}; // ADC=
|
||||
Poincare::Complex::convertFloatToText(result, responseBuffer+4, bufferSize, precision);
|
||||
Ion::Console::writeLine(responseBuffer);
|
||||
}
|
||||
|
||||
void command_charge(const char * input) {
|
||||
if (input != nullptr) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
if (Ion::Battery::isCharging()) {
|
||||
Ion::Console::writeLine("CHARGE=ON");
|
||||
} else {
|
||||
Ion::Console::writeLine("CHARGE=OFF");
|
||||
}
|
||||
}
|
||||
|
||||
void command_keyboard(const char * input) {
|
||||
if (input != nullptr) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
char result[9+Ion::Keyboard::NumberOfKeys+1] = { 'K', 'E', 'Y', 'B', 'O', 'A', 'R', 'D', '=' };
|
||||
for (uint8_t i=0; i<Ion::Keyboard::NumberOfKeys; i++) {
|
||||
result[9+i] = Ion::Keyboard::keyDown((Ion::Keyboard::Key)i) ? '1' : '0';
|
||||
}
|
||||
result[9+Ion::Keyboard::NumberOfKeys] = 0;
|
||||
Ion::Console::writeLine(result);
|
||||
}
|
||||
|
||||
constexpr CommandHandler handles[] = {
|
||||
CommandHandler("PING", command_ping),
|
||||
CommandHandler("MCU_SERIAL", command_mcu_serial),
|
||||
CommandHandler("LED", command_led),
|
||||
CommandHandler("BACKLIGHT", command_backlight),
|
||||
CommandHandler("ADC", command_adc),
|
||||
CommandHandler("CHARGE", command_charge),
|
||||
CommandHandler("KEYBOARD", command_keyboard),
|
||||
CommandHandler("DISPLAY", command_display),
|
||||
CommandHandler(nullptr, nullptr)
|
||||
};
|
||||
constexpr const CommandList sCommandList = CommandList(handles);
|
||||
|
||||
constexpr int kMaxCommandLength = 255;
|
||||
|
||||
void ion_app() {
|
||||
char command[kMaxCommandLength];
|
||||
while (true) {
|
||||
Ion::Console::readLine(command, kMaxCommandLength);
|
||||
sCommandList.dispatch(command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
include ion/src/device/boot/Makefile
|
||||
include ion/src/device/bench/Makefile
|
||||
|
||||
objs += $(addprefix ion/src/shared/, \
|
||||
events_keyboard.o \
|
||||
|
||||
17
ion/src/device/bench/Makefile
Normal file
17
ion/src/device/bench/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
objs += $(addprefix ion/src/device/bench/, \
|
||||
bench.o \
|
||||
command_handler.o \
|
||||
command_list.o \
|
||||
)
|
||||
|
||||
objs += $(addprefix ion/src/device/bench/command/, \
|
||||
command.o \
|
||||
adc.o \
|
||||
backlight.o \
|
||||
charge.o \
|
||||
display.o \
|
||||
keyboard.o \
|
||||
led.o \
|
||||
mcu_serial.o \
|
||||
ping.o \
|
||||
)
|
||||
34
ion/src/device/bench/bench.cpp
Normal file
34
ion/src/device/bench/bench.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <ion.h>
|
||||
#include "command_list.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
|
||||
constexpr CommandHandler handles[] = {
|
||||
CommandHandler("ADC", Command::ADC),
|
||||
CommandHandler("BACKLIGHT", Command::Backlight),
|
||||
CommandHandler("CHARGE", Command::Charge),
|
||||
CommandHandler("DISPLAY", Command::Display),
|
||||
CommandHandler("KEYBOARD", Command::Keyboard),
|
||||
CommandHandler("LED", Command::LED),
|
||||
CommandHandler("MCU_SERIAL", Command::MCUSerial),
|
||||
CommandHandler("PING", Command::Ping),
|
||||
CommandHandler(nullptr, nullptr)
|
||||
};
|
||||
|
||||
constexpr const CommandList sCommandList = CommandList(handles);
|
||||
|
||||
constexpr int kMaxCommandLength = 255;
|
||||
|
||||
void run() {
|
||||
char command[kMaxCommandLength];
|
||||
while (true) {
|
||||
Ion::Console::readLine(command, kMaxCommandLength);
|
||||
sCommandList.dispatch(command);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
27
ion/src/device/bench/command/adc.cpp
Normal file
27
ion/src/device/bench/command/adc.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include "command.h"
|
||||
#include <ion.h>
|
||||
#include <poincare.h>
|
||||
#include <ion/src/device/led.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
void ADC(const char * input) {
|
||||
if (input != nullptr) {
|
||||
reply(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
float result = Ion::Battery::voltage();
|
||||
constexpr int precision = 8;
|
||||
constexpr int bufferSize = Poincare::Complex::bufferSizeForFloatsWithPrecision(precision);
|
||||
char responseBuffer[bufferSize+4] = {'A', 'D', 'C', '='}; // ADC=
|
||||
Poincare::Complex::convertFloatToText(result, responseBuffer+4, bufferSize, precision);
|
||||
reply(responseBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
ion/src/device/bench/command/backlight.cpp
Normal file
34
ion/src/device/bench/command/backlight.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include "command.h"
|
||||
#include <ion.h>
|
||||
#include <ion/src/device/backlight.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
void Backlight(const char * input) {
|
||||
// Input must be of the form "0xAA" or "ON" or "OFF"
|
||||
if (strcmp(input, sON) == 0) {
|
||||
Ion::Backlight::Device::init();
|
||||
reply(sOK);
|
||||
return;
|
||||
}
|
||||
if (strcmp(input, sOFF) == 0) {
|
||||
Ion::Backlight::Device::shutdown();
|
||||
reply(sOK);
|
||||
return;
|
||||
}
|
||||
if (input == nullptr || input[0] != '0' || input[1] != 'x' || !isHex(input[2]) ||!isHex(input[3]) || input[4] != NULL) {
|
||||
reply(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
uint32_t brightness = hexNumber(input+2);
|
||||
Ion::Backlight::setBrightness(brightness);
|
||||
reply(sOK);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
ion/src/device/bench/command/charge.cpp
Normal file
24
ion/src/device/bench/command/charge.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "command.h"
|
||||
#include <ion.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
void Charge(const char * input) {
|
||||
if (input != nullptr) {
|
||||
reply(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
if (Ion::Battery::isCharging()) {
|
||||
reply("CHARGE=ON");
|
||||
} else {
|
||||
reply("CHARGE=OFF");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
ion/src/device/bench/command/command.cpp
Normal file
45
ion/src/device/bench/command/command.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "command.h"
|
||||
#include <ion.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
const char * const sOK = "OK";
|
||||
const char * const sKO = "KO";
|
||||
const char * const sSyntaxError = "SYNTAX_ERROR";
|
||||
const char * const sON = "ON";
|
||||
const char * const sOFF = "OFF";
|
||||
|
||||
void reply(const char * s) {
|
||||
Console::writeLine(s);
|
||||
}
|
||||
|
||||
int8_t hexChar(char c) {
|
||||
if (c >= '0' && c <= '9') {
|
||||
return (c - '0');
|
||||
}
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
return (c - 'A') + 0xA;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool isHex(char c) {
|
||||
return hexChar(c) >= 0;
|
||||
}
|
||||
|
||||
uint32_t hexNumber(const char * s) {
|
||||
uint32_t result = 0;
|
||||
while (*s != NULL) {
|
||||
result = (result << 4) | hexChar(*s++);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
ion/src/device/bench/command/command.h
Normal file
38
ion/src/device/bench/command/command.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef ION_DEVICE_BENCH_COMMAND_COMMAND_H
|
||||
#define ION_DEVICE_BENCH_COMMAND_COMMAND_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
typedef void (*Function)(const char * input);
|
||||
|
||||
void ADC(const char * input);
|
||||
void Backlight(const char * input);
|
||||
void Charge(const char * input);
|
||||
void Display(const char * input);
|
||||
void Keyboard(const char * input);
|
||||
void LED(const char * input);
|
||||
void MCUSerial(const char * input);
|
||||
void Ping(const char * input);
|
||||
|
||||
extern const char * const sOK;
|
||||
extern const char * const sKO;
|
||||
extern const char * const sSyntaxError;
|
||||
extern const char * const sON;
|
||||
extern const char * const sOFF;
|
||||
|
||||
void reply(const char * s);
|
||||
int8_t hexChar(char c);
|
||||
bool isHex(char c);
|
||||
uint32_t hexNumber(const char * s);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
70
ion/src/device/bench/command/display.cpp
Normal file
70
ion/src/device/bench/command/display.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "command.h"
|
||||
#include <ion.h>
|
||||
#include <ion/src/device/display.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
// Input must be of the form "0xAABBCC" or "ON" or "OFF"
|
||||
void Display(const char * input) {
|
||||
|
||||
if (strcmp(input, sON) == 0) {
|
||||
Ion::Display::Device::init();
|
||||
reply(sOK);
|
||||
return;
|
||||
}
|
||||
if (strcmp(input, sOFF) == 0) {
|
||||
Ion::Display::Device::shutdown();
|
||||
reply(sOK);
|
||||
return;
|
||||
}
|
||||
if (input == nullptr || input[0] != '0' || input[1] != 'x' || !isHex(input[2]) ||!isHex(input[3]) || !isHex(input[4]) || !isHex(input[5]) || !isHex(input[6]) || !isHex(input[7]) || input[8] != NULL) {
|
||||
reply(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We fill the screen with a color and return OK if we read that color back everywhere. */
|
||||
|
||||
KDColor c = KDColor::RGB24(hexNumber(input));
|
||||
|
||||
constexpr int stampHeight = 10;
|
||||
constexpr int stampWidth = 10;
|
||||
static_assert(Ion::Display::Width % stampWidth == 0, "Stamps must tesselate the display");
|
||||
static_assert(Ion::Display::Height % stampHeight == 0, "Stamps must tesselate the display");
|
||||
static_assert(stampHeight % 2 == 0 || stampWidth % 2 == 0, "Even number of XOR needed.");
|
||||
|
||||
KDColor stamp[stampWidth*stampHeight];
|
||||
for (int i=0;i<stampWidth*stampHeight; i++) {
|
||||
stamp[i] = c;
|
||||
}
|
||||
|
||||
for (int i=0; i<Ion::Display::Width/stampWidth; i++) {
|
||||
for (int j=0; j<Ion::Display::Height/stampHeight; j++) {
|
||||
Ion::Display::pushRect(KDRect(i*stampWidth, j*stampHeight, stampWidth, stampHeight), stamp);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<Ion::Display::Width/stampWidth; i++) {
|
||||
for (int j=0; j<Ion::Display::Height/stampHeight; j++) {
|
||||
for (int i=0;i<stampWidth*stampHeight; i++) {
|
||||
stamp[i] = KDColorBlack;
|
||||
}
|
||||
Ion::Display::pullRect(KDRect(i*stampWidth, j*stampHeight, stampWidth, stampHeight), stamp);
|
||||
for (int i=0;i<stampWidth*stampHeight; i++) {
|
||||
if (stamp[i] != c) {
|
||||
reply(sKO);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reply(sOK);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
ion/src/device/bench/command/keyboard.cpp
Normal file
25
ion/src/device/bench/command/keyboard.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "command.h"
|
||||
#include <ion.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
void Keyboard(const char * input) {
|
||||
if (input != nullptr) {
|
||||
reply(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
char result[9+Ion::Keyboard::NumberOfKeys+1] = { 'K', 'E', 'Y', 'B', 'O', 'A', 'R', 'D', '=' };
|
||||
for (uint8_t i=0; i<Ion::Keyboard::NumberOfKeys; i++) {
|
||||
result[9+i] = Ion::Keyboard::keyDown((Ion::Keyboard::Key)i) ? '1' : '0';
|
||||
}
|
||||
result[9+Ion::Keyboard::NumberOfKeys] = 0;
|
||||
reply(result);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
ion/src/device/bench/command/led.cpp
Normal file
35
ion/src/device/bench/command/led.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "command.h"
|
||||
#include <ion.h>
|
||||
#include <ion/src/device/led.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
// Input must be of the form "0xAABBCC" or "ON" or "OFF"
|
||||
void LED(const char * input) {
|
||||
if (strcmp(input, sON) == 0) {
|
||||
Ion::LED::Device::init();
|
||||
Ion::Console::writeLine(sOK);
|
||||
return;
|
||||
}
|
||||
if (strcmp(input, sOFF) == 0) {
|
||||
Ion::LED::Device::shutdown();
|
||||
Ion::Console::writeLine(sOK);
|
||||
return;
|
||||
}
|
||||
if (input == nullptr || input[0] != '0' || input[1] != 'x' || !isHex(input[2]) ||!isHex(input[3]) || !isHex(input[4]) || !isHex(input[5]) || !isHex(input[6]) || !isHex(input[7]) || input[8] != NULL) {
|
||||
Ion::Console::writeLine(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
uint32_t hexColor = hexNumber(input+2);
|
||||
KDColor ledColor = KDColor::RGB24(hexColor);
|
||||
Ion::LED::setColor(ledColor);
|
||||
Ion::Console::writeLine(sOK);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
ion/src/device/bench/command/mcu_serial.cpp
Normal file
23
ion/src/device/bench/command/mcu_serial.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "command.h"
|
||||
#include <ion.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
void MCUSerial(const char * input) {
|
||||
if (input != nullptr) {
|
||||
reply(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
char response[11+24+1] = {'M', 'C', 'U', '_', 'S', 'E', 'R', 'I', 'A', 'L', '=', 0};
|
||||
strlcpy(response+11, Ion::serialNumber(), 25);
|
||||
reply(response);
|
||||
Ion::Console::writeLine(response);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
19
ion/src/device/bench/command/ping.cpp
Normal file
19
ion/src/device/bench/command/ping.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "command.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
namespace Command {
|
||||
|
||||
void Ping(const char * input) {
|
||||
if (input != nullptr) {
|
||||
reply(sSyntaxError);
|
||||
return;
|
||||
}
|
||||
reply("PONG");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
ion/src/device/bench/command_handler.cpp
Normal file
44
ion/src/device/bench/command_handler.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "command_handler.h"
|
||||
#include <string.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
|
||||
bool CommandHandler::valid() const {
|
||||
return (m_name != nullptr && m_function != nullptr);
|
||||
}
|
||||
|
||||
bool CommandHandler::handle(const char * command) const {
|
||||
if (matches(command)) {
|
||||
size_t nameLength = strlen(m_name);
|
||||
if (command[nameLength] == '=') {
|
||||
m_function(command+nameLength+1); // Skip the "Equal character"
|
||||
} else {
|
||||
m_function(nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CommandHandler::matches(const char * command) const {
|
||||
const char * c = command;
|
||||
const char * n = m_name;
|
||||
while (true) {
|
||||
if (*n == NULL) {
|
||||
if (*c == NULL || *c == '=') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (*c != *n) {
|
||||
return false;
|
||||
}
|
||||
c++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
26
ion/src/device/bench/command_handler.h
Normal file
26
ion/src/device/bench/command_handler.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef ION_DEVICE_BENCH_COMMAND_HANDLER_H
|
||||
#define ION_DEVICE_BENCH_COMMAND_HANDLER_H
|
||||
|
||||
#include "command/command.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
|
||||
class CommandHandler {
|
||||
public:
|
||||
constexpr CommandHandler(const char * name, Command::Function function) :
|
||||
m_name(name), m_function(function) {}
|
||||
bool valid() const;
|
||||
bool handle(const char * command) const;
|
||||
private:
|
||||
bool matches(const char * command) const;
|
||||
const char * m_name;
|
||||
Command::Function m_function;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
21
ion/src/device/bench/command_list.cpp
Normal file
21
ion/src/device/bench/command_list.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "command_list.h"
|
||||
#include <ion.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
|
||||
void CommandList::dispatch(const char * command) const {
|
||||
const CommandHandler * handler = m_handlers;
|
||||
while (handler->valid()) {
|
||||
if (handler->handle(command)) {
|
||||
return;
|
||||
}
|
||||
handler++;
|
||||
}
|
||||
Console::writeLine("NOT_FOUND");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
22
ion/src/device/bench/command_list.h
Normal file
22
ion/src/device/bench/command_list.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef ION_DEVICE_BENCH_COMMAND_LIST_H
|
||||
#define ION_DEVICE_BENCH_COMMAND_LIST_H
|
||||
|
||||
#include "command_handler.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
namespace Bench {
|
||||
|
||||
class CommandList {
|
||||
public:
|
||||
constexpr CommandList(const CommandHandler * handlers) : m_handlers(handlers) {}
|
||||
void dispatch(const char * command) const;
|
||||
private:
|
||||
const CommandHandler * m_handlers;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user