From 9e3c0528300f79862cafee8148a0507d1494451f Mon Sep 17 00:00:00 2001 From: Romain Goyet Date: Thu, 16 Mar 2017 14:20:46 +0100 Subject: [PATCH] [ion] Move the bench test in ion Change-Id: I54b99678df969e6e3e86c2d3858d04088a40f047 --- apps/hwtest/lowlevel/lowlevel.cpp | 280 -------------------- ion/src/device/Makefile | 1 + ion/src/device/bench/Makefile | 17 ++ ion/src/device/bench/bench.cpp | 34 +++ ion/src/device/bench/command/adc.cpp | 27 ++ ion/src/device/bench/command/backlight.cpp | 34 +++ ion/src/device/bench/command/charge.cpp | 24 ++ ion/src/device/bench/command/command.cpp | 45 ++++ ion/src/device/bench/command/command.h | 38 +++ ion/src/device/bench/command/display.cpp | 70 +++++ ion/src/device/bench/command/keyboard.cpp | 25 ++ ion/src/device/bench/command/led.cpp | 35 +++ ion/src/device/bench/command/mcu_serial.cpp | 23 ++ ion/src/device/bench/command/ping.cpp | 19 ++ ion/src/device/bench/command_handler.cpp | 44 +++ ion/src/device/bench/command_handler.h | 26 ++ ion/src/device/bench/command_list.cpp | 21 ++ ion/src/device/bench/command_list.h | 22 ++ 18 files changed, 505 insertions(+), 280 deletions(-) delete mode 100644 apps/hwtest/lowlevel/lowlevel.cpp create mode 100644 ion/src/device/bench/Makefile create mode 100644 ion/src/device/bench/bench.cpp create mode 100644 ion/src/device/bench/command/adc.cpp create mode 100644 ion/src/device/bench/command/backlight.cpp create mode 100644 ion/src/device/bench/command/charge.cpp create mode 100644 ion/src/device/bench/command/command.cpp create mode 100644 ion/src/device/bench/command/command.h create mode 100644 ion/src/device/bench/command/display.cpp create mode 100644 ion/src/device/bench/command/keyboard.cpp create mode 100644 ion/src/device/bench/command/led.cpp create mode 100644 ion/src/device/bench/command/mcu_serial.cpp create mode 100644 ion/src/device/bench/command/ping.cpp create mode 100644 ion/src/device/bench/command_handler.cpp create mode 100644 ion/src/device/bench/command_handler.h create mode 100644 ion/src/device/bench/command_list.cpp create mode 100644 ion/src/device/bench/command_list.h diff --git a/apps/hwtest/lowlevel/lowlevel.cpp b/apps/hwtest/lowlevel/lowlevel.cpp deleted file mode 100644 index ca34027dc..000000000 --- a/apps/hwtest/lowlevel/lowlevel.cpp +++ /dev/null @@ -1,280 +0,0 @@ -#include -#include -#include -#include -#include -#include - -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 +#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); + } +} + +} +} +} diff --git a/ion/src/device/bench/command/adc.cpp b/ion/src/device/bench/command/adc.cpp new file mode 100644 index 000000000..b824405c7 --- /dev/null +++ b/ion/src/device/bench/command/adc.cpp @@ -0,0 +1,27 @@ +#include "command.h" +#include +#include +#include + +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); +} + +} +} +} +} diff --git a/ion/src/device/bench/command/backlight.cpp b/ion/src/device/bench/command/backlight.cpp new file mode 100644 index 000000000..b4a7f2d9f --- /dev/null +++ b/ion/src/device/bench/command/backlight.cpp @@ -0,0 +1,34 @@ +#include "command.h" +#include +#include + +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); +} + +} +} +} +} diff --git a/ion/src/device/bench/command/charge.cpp b/ion/src/device/bench/command/charge.cpp new file mode 100644 index 000000000..8aa14f536 --- /dev/null +++ b/ion/src/device/bench/command/charge.cpp @@ -0,0 +1,24 @@ +#include "command.h" +#include + +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"); + } +} + +} +} +} +} diff --git a/ion/src/device/bench/command/command.cpp b/ion/src/device/bench/command/command.cpp new file mode 100644 index 000000000..671072411 --- /dev/null +++ b/ion/src/device/bench/command/command.cpp @@ -0,0 +1,45 @@ +#include "command.h" +#include + +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; +} + + +} +} +} +} diff --git a/ion/src/device/bench/command/command.h b/ion/src/device/bench/command/command.h new file mode 100644 index 000000000..923a7fe02 --- /dev/null +++ b/ion/src/device/bench/command/command.h @@ -0,0 +1,38 @@ +#ifndef ION_DEVICE_BENCH_COMMAND_COMMAND_H +#define ION_DEVICE_BENCH_COMMAND_COMMAND_H + +#include + +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 diff --git a/ion/src/device/bench/command/display.cpp b/ion/src/device/bench/command/display.cpp new file mode 100644 index 000000000..98e536d54 --- /dev/null +++ b/ion/src/device/bench/command/display.cpp @@ -0,0 +1,70 @@ +#include "command.h" +#include +#include + +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 + +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 +#include + +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); +} + +} +} +} +} diff --git a/ion/src/device/bench/command/mcu_serial.cpp b/ion/src/device/bench/command/mcu_serial.cpp new file mode 100644 index 000000000..16c7a22f6 --- /dev/null +++ b/ion/src/device/bench/command/mcu_serial.cpp @@ -0,0 +1,23 @@ +#include "command.h" +#include + +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); +} + +} +} +} +} diff --git a/ion/src/device/bench/command/ping.cpp b/ion/src/device/bench/command/ping.cpp new file mode 100644 index 000000000..23649a7dc --- /dev/null +++ b/ion/src/device/bench/command/ping.cpp @@ -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"); +} + +} +} +} +} diff --git a/ion/src/device/bench/command_handler.cpp b/ion/src/device/bench/command_handler.cpp new file mode 100644 index 000000000..082d229a0 --- /dev/null +++ b/ion/src/device/bench/command_handler.cpp @@ -0,0 +1,44 @@ +#include "command_handler.h" +#include + +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++; + } +} + +} +} +} diff --git a/ion/src/device/bench/command_handler.h b/ion/src/device/bench/command_handler.h new file mode 100644 index 000000000..7c573f209 --- /dev/null +++ b/ion/src/device/bench/command_handler.h @@ -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 diff --git a/ion/src/device/bench/command_list.cpp b/ion/src/device/bench/command_list.cpp new file mode 100644 index 000000000..6cf08c183 --- /dev/null +++ b/ion/src/device/bench/command_list.cpp @@ -0,0 +1,21 @@ +#include "command_list.h" +#include + +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"); +} + +} +} +} diff --git a/ion/src/device/bench/command_list.h b/ion/src/device/bench/command_list.h new file mode 100644 index 000000000..3efbc8ca9 --- /dev/null +++ b/ion/src/device/bench/command_list.h @@ -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