feat: working test
This commit is contained in:
parent
50cf3b3241
commit
4cd08211a3
186
prog/prog.ino
186
prog/prog.ino
@ -1,7 +1,42 @@
|
|||||||
#include <ESP32Servo.h>
|
#include <ESP32Servo.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include "Adafruit_VL53L0X.h"
|
#include "Adafruit_VL53L0X.h"
|
||||||
#include "PCF8574.h"
|
#include <Adafruit_PCF8574.h>
|
||||||
|
#include "terminal.hpp"
|
||||||
|
//
|
||||||
|
// ATTENTION : pour que les commandes se déclarent automatiquement au démarrage
|
||||||
|
// auprès du terminal, le fichier conteant la fonction setup() et loop() doit
|
||||||
|
// être mis en derniere position dans la liste des fichiers lors de l'édition
|
||||||
|
// des liens.
|
||||||
|
// Dans platformio, pour faire cela, il suffit de commencer le nom du fichier
|
||||||
|
// contenant les fonctions loop() et setup() par la lettre z.
|
||||||
|
// Par exemple : zzz_main.cpp.
|
||||||
|
//
|
||||||
|
|
||||||
|
extern terminal_n::Terminal terminal;
|
||||||
|
|
||||||
|
|
||||||
|
TERMINAL_PARAMETER_INT(
|
||||||
|
terminal,
|
||||||
|
power_mode, // variable name to declare
|
||||||
|
"power_mode", // EEPROM name (15 char. max),
|
||||||
|
// If you dont want to save in EEPROM, set ""
|
||||||
|
"the power mode", // description
|
||||||
|
0, // default constructor value
|
||||||
|
false, // auto save in eeprom after command modification
|
||||||
|
terminal_n::filter_nothing, // function to filter the value
|
||||||
|
terminal_n::do_nothing // function executed at the end of the command
|
||||||
|
);
|
||||||
|
|
||||||
|
TERMINAL_COMMAND(terminal, ping, "Print pong followoing by the received arguments")
|
||||||
|
{
|
||||||
|
terminal.print("pong");
|
||||||
|
for (uint32_t i=0; i<argc; i++) {
|
||||||
|
terminal.print(" ");
|
||||||
|
terminal.print(argv[i]);
|
||||||
|
}
|
||||||
|
terminal.println("");
|
||||||
|
}
|
||||||
|
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <AsyncTCP.h>
|
#include <AsyncTCP.h>
|
||||||
@ -29,8 +64,10 @@ struct tube {
|
|||||||
int id;
|
int id;
|
||||||
};
|
};
|
||||||
|
|
||||||
const int minHeight = 50;
|
struct tube all_tubes[6] = {0};
|
||||||
const int maxHeight = 445;
|
|
||||||
|
const float minHeight = 50;
|
||||||
|
const float maxHeight = 445;
|
||||||
|
|
||||||
int minServo = 0;
|
int minServo = 0;
|
||||||
int maxServo = 180;
|
int maxServo = 180;
|
||||||
@ -48,7 +85,7 @@ AsyncWebServer server(80);
|
|||||||
const char index_html[] PROGMEM = R"rawliteral(
|
const char index_html[] PROGMEM = R"rawliteral(
|
||||||
<!DOCTYPE HTML><html>
|
<!DOCTYPE HTML><html>
|
||||||
<head>
|
<head>
|
||||||
<title>ESP Web Server</title>
|
<title>Balle Ping Pong flottante</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="icon" href="data:,">
|
<link rel="icon" href="data:,">
|
||||||
<style>
|
<style>
|
||||||
@ -65,14 +102,14 @@ const char index_html[] PROGMEM = R"rawliteral(
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>ESP Web Server</h2>
|
<h2>Balle Ping Pong flottante</h2>
|
||||||
%BUTTONPLACEHOLDER%
|
%BUTTONPLACEHOLDER%
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function sendSliderValue(element) {
|
function sendSliderValue(id, element) {
|
||||||
var slider1 = document.getElementById("slider1");
|
var slider = document.getElementById(`slider${id}`);
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open("GET", "/update?output="+slider1.id+"&state=" + slider1.value, true);
|
xhr.open("GET", "/update?output="+id+"&state=" + slider.value, true);
|
||||||
xhr.send();
|
xhr.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,11 +123,11 @@ String processor(const String& var){
|
|||||||
//Serial.println(var);
|
//Serial.println(var);
|
||||||
if(var == "BUTTONPLACEHOLDER"){
|
if(var == "BUTTONPLACEHOLDER"){
|
||||||
String buttons = "";
|
String buttons = "";
|
||||||
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider1\" onchange=\"sendSliderValue(this.value)\"\"></div>";
|
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider0\" onchange=\"sendSliderValue(0, this.value)\"\"></div>";
|
||||||
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider2\" onchange=\"sendSliderValue(this.value)\"\"></div>";
|
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider1\" onchange=\"sendSliderValue(1, this.value)\"\"></div>";
|
||||||
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider3\" onchange=\"sendSliderValue(this.value)\"\"></div>";
|
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider2\" onchange=\"sendSliderValue(2, this.value)\"\"></div>";
|
||||||
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider4\" onchange=\"sendSliderValue(this.value)\"\"></div>";
|
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider3\" onchange=\"sendSliderValue(3, this.value)\"\"></div>";
|
||||||
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider5\" onchange=\"sendSliderValue(this.value)\"\"></div>";
|
buttons += "<div class=\"slidecontainer\"><input type=\"range\" min=\"20\" max=\"450\" value=\"250\" class=\"slider\" id=\"slider4\" onchange=\"sendSliderValue(4, this.value)\"\"></div>";
|
||||||
|
|
||||||
|
|
||||||
return buttons;
|
return buttons;
|
||||||
@ -98,27 +135,25 @@ String processor(const String& var){
|
|||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mesureHeight(Adafruit_VL53L0X lox){
|
auto mesureHeight(Adafruit_VL53L0X lox, struct tube *tube){
|
||||||
VL53L0X_RangingMeasurementData_t measure;
|
VL53L0X_RangingMeasurementData_t measure;
|
||||||
lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
|
lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
|
||||||
if (measure.RangeStatus != 4) { // phase failures have incorrect data
|
if (measure.RangeStatus != 4) { // phase failures have incorrect data
|
||||||
float height = measure.RangeMilliMeter;
|
float height = measure.RangeMilliMeter;
|
||||||
if (height < 1000){
|
if (height < 1000.0){
|
||||||
curHeight = height;
|
tube->height = height;
|
||||||
return height;
|
return height;
|
||||||
} else {
|
} else {
|
||||||
Serial.println("Incoherent measurement. Returning previous one.");
|
Serial.println("Incoherent measurement. Returning previous one.");
|
||||||
return curHeight;
|
return tube->height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Serial.println(" out of range ");
|
Serial.println(" out of range ");
|
||||||
return curHeight;
|
return tube->height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int requestedValue = 250;
|
|
||||||
|
|
||||||
void wifisetup() {
|
void wifisetup() {
|
||||||
Serial.print("Setting AP (Access Point)…");
|
Serial.print("Setting AP (Access Point)…");
|
||||||
WiFi.softAP(ssid);
|
WiFi.softAP(ssid);
|
||||||
@ -140,7 +175,7 @@ void wifisetup() {
|
|||||||
if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) {
|
if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) {
|
||||||
inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
|
inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
|
||||||
inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
|
inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
|
||||||
requestedValue = inputMessage2.toInt();
|
all_tubes[0].target = inputMessage2.toFloat();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
inputMessage1 = "No message sent";
|
inputMessage1 = "No message sent";
|
||||||
@ -157,49 +192,52 @@ void wifisetup() {
|
|||||||
server.begin();
|
server.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
PCF8574 pcf8574(0x20);
|
Adafruit_PCF8574 pcf8574;
|
||||||
|
|
||||||
void change_pin(struct pin pin, int state) {
|
void change_pin(struct pin pin, int state) {
|
||||||
if (pin.is_extender) {
|
if (pin.is_extender) {
|
||||||
pcf8574.digitalWrite(pin, state);
|
pcf8574.digitalWrite(pin.id, state);
|
||||||
} else {
|
} else {
|
||||||
digitalWrite(pin, state);
|
digitalWrite(pin.id, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tube all_tubes[6] = {0};
|
|
||||||
|
|
||||||
Adafruit_VL53L0X tofs_talk_through[6] = {Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X()};
|
Adafruit_VL53L0X tofs_talk_through[6] = {Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X(), Adafruit_VL53L0X()};
|
||||||
|
|
||||||
void init_tube(struct tube *tube, char id, struct pin servo_pin, struct pin gpio, struct pin xshut) {
|
void init_tube(struct tube *tube, char id, struct pin servo_pin, struct pin gpio, struct pin xshut) {
|
||||||
Serial.print(" Initialiazing tube #");
|
Serial.print(" Initialiazing tube #");
|
||||||
Serial.println(id);
|
Serial.println((int) id);
|
||||||
tube->id = id;
|
tube->id = id;
|
||||||
tube->servo.pin = servo_pin;
|
tube->servo.pin = servo_pin;
|
||||||
tube->tof.gpio = gpio;
|
tube->tof.gpio = gpio;
|
||||||
tube->tof.xshut = xshut;
|
tube->tof.xshut = xshut;
|
||||||
tube->height = 250.0;
|
tube->height = 250.0f;
|
||||||
tube->target = 250.0;
|
tube->target = 250.0f;
|
||||||
|
|
||||||
|
change_pin(gpio, HIGH);
|
||||||
change_pin(xshut, HIGH);
|
change_pin(xshut, HIGH);
|
||||||
|
change_pin(servo_pin, HIGH);
|
||||||
|
|
||||||
|
Serial.println("Beginning boot sequence VL53L0X");
|
||||||
if (!tofs_talk_through[id].begin(0x30 + id)) {
|
if (!tofs_talk_through[id].begin(0x30 + id)) {
|
||||||
Serial.println(F("Failed to boot VL53L0X"));
|
Serial.println(F("Failed to boot VL53L0X"));
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
tube->servo.hard.attach(tube->servo.pin);
|
tube->servo.hard.attach(tube->servo.pin.id);
|
||||||
tube->servo.hard.write(minServo);
|
tube->servo.hard.write(minServo);
|
||||||
delay(5000);
|
delay(5000);
|
||||||
Serial.println("Setuping downards");
|
Serial.println("Setuping downards");
|
||||||
float h = mesureHeight(tofs_talk_through[id]);
|
float h = mesureHeight(tofs_talk_through[id], tube);
|
||||||
int angle = minServo;
|
int angle = minServo;
|
||||||
while (h > maxHeight) {
|
while (h > maxHeight) {
|
||||||
++angle;
|
++angle;
|
||||||
tube->servo.hard.write(angle);
|
tube->servo.hard.write(angle);
|
||||||
delay(100);
|
delay(300);
|
||||||
h = mesureHeight(tofs_talk_through[id]);
|
h = mesureHeight(tofs_talk_through[id], tube);
|
||||||
}
|
}
|
||||||
angle -= 2;
|
angle -= 5;
|
||||||
tube->servo.hard.write(angle);
|
tube->servo.last_angle = angle;
|
||||||
|
tube->servo.hard.write(tube->servo.last_angle);
|
||||||
tube->servo.equilibrium = angle;
|
tube->servo.equilibrium = angle;
|
||||||
Serial.println("Done.");
|
Serial.println("Done.");
|
||||||
}
|
}
|
||||||
@ -207,23 +245,23 @@ void init_tube(struct tube *tube, char id, struct pin servo_pin, struct pin gpio
|
|||||||
const int ACTIVES = 1;
|
const int ACTIVES = 1;
|
||||||
|
|
||||||
void setup_all_tubes() {
|
void setup_all_tubes() {
|
||||||
const int all_xshuts[6] = {
|
const struct pin all_xshuts[6] = {
|
||||||
{.id = 17, .is_extender = 0},
|
{.id = 17, .is_extender = 0},
|
||||||
{.id = P2, .is_extender = 1},
|
{.id = 2, .is_extender = 1},
|
||||||
{.id = P3, .is_extender = 1},
|
{.id = 3, .is_extender = 1},
|
||||||
{.id = P5, .is_extender = 1},
|
{.id = 5, .is_extender = 1},
|
||||||
{.id = P7, .is_extender = 1},
|
{.id = 7, .is_extender = 1},
|
||||||
{.id = P1, .is_extender = 1}
|
{.id = 1, .is_extender = 1}
|
||||||
};
|
};
|
||||||
const int all_gpios[6] = {
|
const struct pin all_gpios[6] = {
|
||||||
{.id = 5, .is_extender = 0},
|
{.id = 5, .is_extender = 0},
|
||||||
{.id = 18, .is_extender = 0},
|
{.id = 18, .is_extender = 0},
|
||||||
{.id = 19, .is_extender = 0},
|
{.id = 19, .is_extender = 0},
|
||||||
{.id = P4, .is_extender = 1},
|
{.id = 4, .is_extender = 1},
|
||||||
{.id = P6, .is_extender = 1},
|
{.id = 6, .is_extender = 1},
|
||||||
{.id = P0, .is_extender = 1}
|
{.id = 0, .is_extender = 1}
|
||||||
};
|
};
|
||||||
const int all_servos[6] = {
|
const struct pin all_servos[6] = {
|
||||||
{.id = 32, .is_extender = 0},
|
{.id = 32, .is_extender = 0},
|
||||||
{.id = 33, .is_extender = 0},
|
{.id = 33, .is_extender = 0},
|
||||||
{.id = 23, .is_extender = 0},
|
{.id = 23, .is_extender = 0},
|
||||||
@ -247,18 +285,33 @@ void setup_all_tubes() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TERMINAL_ADD_DEFAULT_COMMANDS(terminal) // help, params, load_config, reset_config, echo ...
|
||||||
|
|
||||||
|
terminal_n::Terminal terminal("Pingpong flottant.\n\r\n\r");
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200); // Starts the serial communication
|
Serial.begin(115200); // Starts the serial communication
|
||||||
while (! Serial) {
|
while (! Serial) {
|
||||||
delay(1);
|
delay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Wire.begin();
|
if (!pcf8574.begin(0x38, &Wire)) {
|
||||||
pcf8574.begin();
|
Serial.println("Couldn't find PCF8574");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
for (uint8_t p=0; p<8; p++) {
|
||||||
|
pcf8574.pinMode(p, OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("PCF8574 seemks OK");
|
||||||
|
|
||||||
wifisetup();
|
wifisetup();
|
||||||
|
|
||||||
|
terminal.setup(&Serial);
|
||||||
|
|
||||||
setup_all_tubes();
|
setup_all_tubes();
|
||||||
|
|
||||||
Serial.println("Done setuping have funning");
|
Serial.println("Done setuping have funning");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,28 +325,41 @@ int servoPosition(float ratio){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
terminal.update();
|
||||||
for (int i = 0; i < ACTIVES; i++) {
|
for (int i = 0; i < ACTIVES; i++) {
|
||||||
struct tube tube = all_tubes[i];
|
struct tube *tube = all_tubes + i;
|
||||||
tube.height = mesureHeight(tofs_talk_through[tube.id]);
|
/*
|
||||||
|
Serial.print("Tube ");
|
||||||
|
Serial.println(tube->id);
|
||||||
|
*/
|
||||||
|
tube->height = mesureHeight(tofs_talk_through[tube->id], tube);
|
||||||
|
/*
|
||||||
Serial.print("Measure = ");
|
Serial.print("Measure = ");
|
||||||
Serial.println(tube.height);
|
Serial.println(tube->height);
|
||||||
|
*/
|
||||||
int angle = 0;
|
int angle = 0;
|
||||||
float diff = tube.height - tube.target;
|
float diff = tube->height - tube->target;
|
||||||
if (abs(diff) > 5.0f) {
|
if (abs(diff) > 5.0f) {
|
||||||
Serial.println("HEYEYEYEYEYEYEY");
|
angle = tube->servo.equilibrium + (diff * 1 / (7));
|
||||||
angle = tube.servo.equilibrium + (diff * 1 / (7));
|
|
||||||
} else if (abs(diff) > 2.0f) {
|
} else if (abs(diff) > 2.0f) {
|
||||||
angle = tube.servo.equilibrium + (diff * 1 / (7));
|
angle = tube->servo.equilibrium + (diff * 1 / (7));
|
||||||
} else {
|
} else {
|
||||||
error = 0;
|
angle = tube->servo.equilibrium;
|
||||||
angle = tube.servo.equilibrium;
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
Serial.print("angle = ");
|
Serial.print("angle = ");
|
||||||
Serial.print(angle);
|
Serial.print(angle);
|
||||||
Serial.print("; equilibrium = ");
|
Serial.print("; equilibrium = ");
|
||||||
Serial.println(tube.servo.equilibrium);
|
Serial.println(tube->servo.equilibrium);
|
||||||
tube.servo.last_angle = angle;
|
*/
|
||||||
tube.servo.hard.write(min(max(angle, minServo), maxServo));
|
tube->servo.last_angle = min(max(angle, minServo), maxServo);
|
||||||
|
/* Serial.print("Diff = ");
|
||||||
|
Serial.print(diff);
|
||||||
|
Serial.print("; Requested = ");
|
||||||
|
Serial.print(tube->target);
|
||||||
|
Serial.print("; Angle = ");
|
||||||
|
Serial.println(tube->servo.last_angle);
|
||||||
|
*/tube->servo.hard.write(tube->servo.last_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(1);
|
delay(1);
|
||||||
|
83
prog/serial_print.hpp
Normal file
83
prog/serial_print.hpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void serial_print(HardwareSerial* serial, T v){
|
||||||
|
serial->print(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void serial_println(HardwareSerial* serial, T v){
|
||||||
|
serial->println(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static inline char hex_conv(T val){
|
||||||
|
return val < 10 ? '0' + val : 'A' + (val-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char eol[3] = "\r\n";
|
||||||
|
inline void serial_print_eol(HardwareSerial* serial){
|
||||||
|
serial->write((const uint8_t*)eol, sizeof(eol));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void serial_print_hex(HardwareSerial* serial, int32_t n){
|
||||||
|
constexpr const int SIZE_BUFF_HEX = 2*4+2;
|
||||||
|
char buff[SIZE_BUFF_HEX];
|
||||||
|
buff[0] = '0';
|
||||||
|
buff[1] = 'x';
|
||||||
|
buff[2] = hex_conv((n & 0xF0000000) >> 7*4 );
|
||||||
|
buff[3] = hex_conv((n & 0x0F000000) >> 6*4 );
|
||||||
|
buff[4] = hex_conv((n & 0x00F00000) >> 5*4 );
|
||||||
|
buff[5] = hex_conv((n & 0x000F0000) >> 4*4 );
|
||||||
|
buff[6] = hex_conv((n & 0x0000F000) >> 3*4 );
|
||||||
|
buff[7] = hex_conv((n & 0x00000F00) >> 2*4 );
|
||||||
|
buff[8] = hex_conv((n & 0x000000F0) >> 1*4 );
|
||||||
|
buff[9] = hex_conv((n & 0x0000000F) );
|
||||||
|
serial->write((const uint8_t*)&buff, SIZE_BUFF_HEX);
|
||||||
|
}
|
||||||
|
inline void serial_print_hex(HardwareSerial* serial, int64_t n){
|
||||||
|
constexpr const int SIZE_BUFF_HEX = 4*4+2;
|
||||||
|
char buff[SIZE_BUFF_HEX];
|
||||||
|
buff[0] = '0';
|
||||||
|
buff[1] = 'x';
|
||||||
|
buff[2] = hex_conv((n & 0xF000000000000000) >> 15*4 );
|
||||||
|
buff[3] = hex_conv((n & 0x0F00000000000000) >> 14*4 );
|
||||||
|
buff[4] = hex_conv((n & 0x00F0000000000000) >> 13*4 );
|
||||||
|
buff[5] = hex_conv((n & 0x000F000000000000) >> 12*4 );
|
||||||
|
buff[6] = hex_conv((n & 0x0000F00000000000) >> 11*4 );
|
||||||
|
buff[7] = hex_conv((n & 0x00000F0000000000) >> 10*4 );
|
||||||
|
buff[8] = hex_conv((n & 0x000000F000000000) >> 9*4 );
|
||||||
|
buff[9] = hex_conv((n & 0x0000000F00000000) >> 8*4 );
|
||||||
|
buff[10] = hex_conv((n & 0x00000000F0000000) >> 7*4 );
|
||||||
|
buff[11] = hex_conv((n & 0x000000000F000000) >> 6*4 );
|
||||||
|
buff[12] = hex_conv((n & 0x0000000000F00000) >> 5*4 );
|
||||||
|
buff[13] = hex_conv((n & 0x00000000000F0000) >> 4*4 );
|
||||||
|
buff[14] = hex_conv((n & 0x000000000000F000) >> 3*4 );
|
||||||
|
buff[15] = hex_conv((n & 0x0000000000000F00) >> 2*4 );
|
||||||
|
buff[16] = hex_conv((n & 0x00000000000000F0) >> 1*4 );
|
||||||
|
buff[17] = hex_conv((n & 0x000000000000000F) );
|
||||||
|
serial->write((const uint8_t*)&buff, SIZE_BUFF_HEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void serial_println_hex(HardwareSerial* serial, int32_t n){
|
||||||
|
serial_print_hex(serial, n);
|
||||||
|
serial_print_eol(serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void serial_print_hex(HardwareSerial* serial, uint32_t number){
|
||||||
|
serial->print(number);
|
||||||
|
}
|
||||||
|
inline void serial_println_hex(HardwareSerial* serial, uint32_t number){
|
||||||
|
serial->println(number);
|
||||||
|
}
|
||||||
|
inline void serial_println_hex(HardwareSerial* serial, int64_t n){
|
||||||
|
serial_print_hex(serial, n);
|
||||||
|
serial_print_eol(serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void serial_print_hex(HardwareSerial* serial, uint64_t number){
|
||||||
|
serial->print(number);
|
||||||
|
}
|
||||||
|
inline void serial_println_hex(HardwareSerial* serial, uint64_t number){
|
||||||
|
serial->println(number);
|
||||||
|
}
|
647
prog/terminal.cpp
Normal file
647
prog/terminal.cpp
Normal file
@ -0,0 +1,647 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015-2019 Grégoire Passault <gregoire.passault@u-bordeaux.fr>
|
||||||
|
* Copyright (C) 2019-2025 Adrien Boussicault <adrien.boussicault@labri.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation, either
|
||||||
|
* version 3 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "terminal.hpp"
|
||||||
|
#include "serial_print.hpp"
|
||||||
|
#define STRINGIFY(x) #x
|
||||||
|
|
||||||
|
namespace terminal_n {
|
||||||
|
|
||||||
|
void Terminal::reset(){
|
||||||
|
terminal_pos = 0;
|
||||||
|
terminal_last_pos = 0;
|
||||||
|
terminal_buffer[0] = '\0';
|
||||||
|
terminal_last_ok = false;
|
||||||
|
print_prompt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the terminal
|
||||||
|
*/
|
||||||
|
void Terminal::disable(){
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::enable(){
|
||||||
|
terminal_last_ok = false;
|
||||||
|
disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the terminal prompt
|
||||||
|
*/
|
||||||
|
void Terminal::print_prompt(){
|
||||||
|
print(PROMPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::setup(HardwareSerial* serial){
|
||||||
|
io = serial;
|
||||||
|
if(terminal_command_count >= terminal_max_commands){
|
||||||
|
println("There are too many commands. Increase the number of commands.");
|
||||||
|
println("Define the macro TERMINAL_MAX_COMMANDS with a bigger number before including the terminal library.");
|
||||||
|
}
|
||||||
|
if(serial){
|
||||||
|
silent = false;
|
||||||
|
}else{
|
||||||
|
silent = true;
|
||||||
|
}
|
||||||
|
enable();
|
||||||
|
print_prompt();
|
||||||
|
check_eeprom_names();
|
||||||
|
load_config_from_eeprom();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Terminal::terminal_silent(bool silent)
|
||||||
|
{
|
||||||
|
silent = silent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const terminal_command *
|
||||||
|
Terminal::find_command(
|
||||||
|
char *command_name, uint32_t command_name_length
|
||||||
|
){
|
||||||
|
uint32_t i;
|
||||||
|
for(i=0; i<terminal_command_count; i++){
|
||||||
|
const terminal_command *command = terminal_commands[i];
|
||||||
|
if(
|
||||||
|
strlen(command->name) == command_name_length &&
|
||||||
|
strncmp(terminal_buffer, command->name, command_name_length) == 0
|
||||||
|
){
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Executes the given command with given parameters
|
||||||
|
*/
|
||||||
|
bool Terminal::terminal_execute(
|
||||||
|
char *command_name, uint32_t command_name_length, uint32_t argc, char **argv
|
||||||
|
){
|
||||||
|
uint32_t i;
|
||||||
|
const terminal_command *command;
|
||||||
|
|
||||||
|
// Try to find and execute the command
|
||||||
|
command = find_command(command_name, command_name_length);
|
||||||
|
if(command != NULL){
|
||||||
|
command->command(argc, argv);
|
||||||
|
if(command->auto_save_after_command){
|
||||||
|
save_value_to_eeprom(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it fails, try to parse the command as an allocation (a=b)
|
||||||
|
if (command == NULL) {
|
||||||
|
for(i=0; i<command_name_length; i++){
|
||||||
|
if(command_name[i] == '='){
|
||||||
|
command_name[i] = '\0';
|
||||||
|
command_name_length = strlen(command_name);
|
||||||
|
command = find_command(command_name, command_name_length);
|
||||||
|
|
||||||
|
if(command && command->parameter){
|
||||||
|
argv[0] = command_name+i+1;
|
||||||
|
argv[1] = NULL;
|
||||||
|
argc = 1;
|
||||||
|
command->command(argc, argv);
|
||||||
|
if(command->auto_save_after_command){
|
||||||
|
save_value_to_eeprom(command);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
command = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!command){
|
||||||
|
print("Unknown parameter: ");
|
||||||
|
write(command_name, command_name_length);
|
||||||
|
println("");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it fails again, display the "unknown command" message
|
||||||
|
if (command == NULL) {
|
||||||
|
print("Unknown command: ");
|
||||||
|
write(command_name, command_name_length);
|
||||||
|
println("");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Process the receive buffer to parse the command and executes it
|
||||||
|
*/
|
||||||
|
void Terminal::terminal_process(){
|
||||||
|
char *saveptr;
|
||||||
|
uint32_t command_name_length;
|
||||||
|
|
||||||
|
uint32_t argc = 0;
|
||||||
|
char* argv[terminal_max_arguments+1];
|
||||||
|
|
||||||
|
println("");
|
||||||
|
|
||||||
|
strtok_r(terminal_buffer, " ", &saveptr);
|
||||||
|
while (
|
||||||
|
(argv[argc] = strtok_r(NULL, " ", &saveptr)) != NULL &&
|
||||||
|
argc < terminal_max_arguments
|
||||||
|
){
|
||||||
|
*(argv[argc]-1) = '\0';
|
||||||
|
argc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(terminal_max_arguments == argc){
|
||||||
|
println("Nb. of parameters are limited.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveptr != NULL) {
|
||||||
|
*(saveptr - 1) = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
command_name_length = strlen(terminal_buffer);
|
||||||
|
|
||||||
|
if (command_name_length > 0) {
|
||||||
|
terminal_last_ok = terminal_execute(
|
||||||
|
terminal_buffer, command_name_length, argc, argv
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
terminal_last_ok = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal_last_pos = terminal_pos;
|
||||||
|
terminal_pos = 0;
|
||||||
|
print_prompt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ticking the terminal, this will cause lookup for characters
|
||||||
|
* and eventually a call to the process function on new lines
|
||||||
|
*/
|
||||||
|
void Terminal::update(){
|
||||||
|
if(disabled || !terminal_has_io()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char c;
|
||||||
|
uint8_t input;
|
||||||
|
|
||||||
|
while(io->available()){
|
||||||
|
input = io->read();
|
||||||
|
c = (char)input;
|
||||||
|
if(c == '\0'){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Return key
|
||||||
|
if(c == '\r' || c == '\n'){
|
||||||
|
if(terminal_pos == 0 && terminal_last_ok){
|
||||||
|
// If the user pressed no keys, restore the last
|
||||||
|
// command and run it again
|
||||||
|
uint32_t i;
|
||||||
|
for(i=0; i<terminal_last_pos; i++){
|
||||||
|
if(terminal_buffer[i] == '\0'){
|
||||||
|
terminal_buffer[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terminal_pos = terminal_last_pos;
|
||||||
|
}
|
||||||
|
terminal_buffer[terminal_pos] = '\0';
|
||||||
|
terminal_process();
|
||||||
|
//Back key
|
||||||
|
}else if(c == '\x7f'){
|
||||||
|
if(terminal_pos > 0){
|
||||||
|
terminal_pos--;
|
||||||
|
print("\x8 \x8");
|
||||||
|
}
|
||||||
|
//Special key
|
||||||
|
}else if(c == '\x1b'){
|
||||||
|
while(!io->available());
|
||||||
|
io->read();
|
||||||
|
while(!io->available());
|
||||||
|
io->read();
|
||||||
|
//Others
|
||||||
|
}else{
|
||||||
|
terminal_buffer[terminal_pos] = c;
|
||||||
|
if(terminal_echo_mode){
|
||||||
|
print(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(terminal_pos < terminal_buffer_size-1){
|
||||||
|
terminal_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a command
|
||||||
|
*/
|
||||||
|
void Terminal::register_command(struct terminal_command *command){
|
||||||
|
if(terminal_command_count >= terminal_max_commands) return;
|
||||||
|
terminal_commands[terminal_command_count] = command;
|
||||||
|
terminal_command_count = terminal_command_count + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::displayHelp(bool parameter){
|
||||||
|
char buffer[1000];
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if(parameter){
|
||||||
|
println("Available parameters:");
|
||||||
|
} else {
|
||||||
|
print(documentation);
|
||||||
|
println("Available commands:");
|
||||||
|
}
|
||||||
|
println("");
|
||||||
|
|
||||||
|
for(i=0; i<terminal_command_count; i++){
|
||||||
|
const struct terminal_command *command = terminal_commands[i];
|
||||||
|
|
||||||
|
if((command->parameter!=0) != parameter){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t namesize = strlen(command->name);
|
||||||
|
int32_t descsize = strlen(command->description);
|
||||||
|
int32_t typesize = (command->parameter_type == NULL) ? 0 : strlen(command->parameter_type);
|
||||||
|
|
||||||
|
memcpy(buffer, command->name, namesize);
|
||||||
|
buffer[namesize++] = ' ';
|
||||||
|
buffer[namesize++] = ' ';
|
||||||
|
buffer[namesize++] = ':';
|
||||||
|
buffer[namesize++] = ' ';
|
||||||
|
buffer[namesize++] = ' ';
|
||||||
|
// buffer[namesize++] = '\r';
|
||||||
|
//buffer[namesize++] = '\n';
|
||||||
|
//buffer[namesize++] = '\t';
|
||||||
|
memcpy(buffer+namesize, command->description, descsize);
|
||||||
|
if(typesize){
|
||||||
|
buffer[namesize+descsize++] = ' ';
|
||||||
|
buffer[namesize+descsize++] = '(';
|
||||||
|
memcpy(buffer+namesize+descsize, command->parameter_type, typesize);
|
||||||
|
buffer[namesize+descsize+typesize++] = ')';
|
||||||
|
}
|
||||||
|
buffer[namesize+descsize+typesize++] = '\r';
|
||||||
|
buffer[namesize+descsize+typesize++] = '\n';
|
||||||
|
write(buffer, namesize+descsize+typesize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::terminal_params_show(){
|
||||||
|
for(uint32_t i=0; i<terminal_command_count; i++){
|
||||||
|
const terminal_command *command = terminal_commands[i];
|
||||||
|
if (command->parameter) {
|
||||||
|
command->command(0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Terminal::echo_command(uint32_t argc, char *argv[]){
|
||||||
|
if(
|
||||||
|
(argc == 1 && strcmp("on", argv[0])==0)
|
||||||
|
||
|
||||||
|
(argc == 0 && terminal_echo_mode==false)
|
||||||
|
){
|
||||||
|
terminal_echo_mode = true;
|
||||||
|
println("Echo enabled");
|
||||||
|
}else{
|
||||||
|
terminal_echo_mode = false;
|
||||||
|
println("Echo disabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::params_command(uint32_t argc, char *argv[]){
|
||||||
|
if(argc && strcmp(argv[0], "show")==0){
|
||||||
|
terminal_params_show();
|
||||||
|
}else{
|
||||||
|
displayHelp(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Terminal::have_to_be_saved_in_eeprom(const terminal_command *command){
|
||||||
|
if(command->parameter == NONE_PARAMETER) return false;
|
||||||
|
if(command->eeprom_name[0] == '\0') return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::save_value_to_eeprom(const terminal_command *command){
|
||||||
|
if(!have_to_be_saved_in_eeprom(command)) return;
|
||||||
|
|
||||||
|
const constexpr bool read_only = false;
|
||||||
|
preferences.begin(
|
||||||
|
preferences_namespace, read_only, preferences_nvs_partition
|
||||||
|
);
|
||||||
|
switch(command->parameter){
|
||||||
|
case FLOAT_PARAMETER :
|
||||||
|
preferences.putFloat(command->eeprom_name, *static_cast<volatile const float*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case DOUBLE_PARAMETER :
|
||||||
|
preferences.putDouble(command->eeprom_name, *static_cast<volatile const double*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case INT_PARAMETER :
|
||||||
|
preferences.putInt(command->eeprom_name, *static_cast<volatile const int32_t*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case UINT_PARAMETER :
|
||||||
|
preferences.putUInt(command->eeprom_name, *static_cast<volatile const uint32_t*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case LONGINT_PARAMETER :
|
||||||
|
preferences.putLong64(command->eeprom_name, *static_cast<volatile const int64_t*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case LONGUINT_PARAMETER :
|
||||||
|
preferences.putULong64(command->eeprom_name, *static_cast<volatile const uint64_t*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case BOOL_PARAMETER :
|
||||||
|
preferences.putBool(command->eeprom_name, *static_cast<volatile const bool*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case NONE_PARAMETER :
|
||||||
|
default :
|
||||||
|
println("Error -- line:" STRINGIFY(__LINE__) ", file" __FILE__ );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
preferences.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::save_config_to_eeprom(){
|
||||||
|
for(uint32_t i=0; i<terminal_command_count; i++){
|
||||||
|
save_value_to_eeprom(terminal_commands[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Terminal::save_config_to_eeprom(const char* eeprom_name){
|
||||||
|
for(uint32_t i=0; i<terminal_command_count; i++){
|
||||||
|
if(
|
||||||
|
!strncmp(
|
||||||
|
terminal_commands[i]->eeprom_name, eeprom_name,
|
||||||
|
MAX_EEPROM_NAME_LENGTH
|
||||||
|
)
|
||||||
|
){
|
||||||
|
save_value_to_eeprom(terminal_commands[i]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::print_value_from_eeprom(const struct terminal_command *command){
|
||||||
|
if(!have_to_be_saved_in_eeprom(command)) return;
|
||||||
|
const constexpr bool read_only = true;
|
||||||
|
preferences.begin(
|
||||||
|
preferences_namespace, read_only, preferences_nvs_partition
|
||||||
|
);
|
||||||
|
if( preferences.isKey(command->eeprom_name) ){
|
||||||
|
print("\"");
|
||||||
|
print(command->eeprom_name);
|
||||||
|
print("\"");
|
||||||
|
print(" : ");
|
||||||
|
switch(command->parameter){
|
||||||
|
case FLOAT_PARAMETER :
|
||||||
|
print(preferences.getFloat(command->eeprom_name));
|
||||||
|
break;
|
||||||
|
case DOUBLE_PARAMETER :
|
||||||
|
print(preferences.getDouble(command->eeprom_name));
|
||||||
|
break;
|
||||||
|
case INT_PARAMETER :
|
||||||
|
print(preferences.getInt(command->eeprom_name));
|
||||||
|
break;
|
||||||
|
case UINT_PARAMETER :
|
||||||
|
print(preferences.getUInt(command->eeprom_name));
|
||||||
|
break;
|
||||||
|
case LONGINT_PARAMETER :
|
||||||
|
print(preferences.getLong64(command->eeprom_name));
|
||||||
|
break;
|
||||||
|
case LONGUINT_PARAMETER :
|
||||||
|
print(preferences.getULong64(command->eeprom_name));
|
||||||
|
break;
|
||||||
|
case BOOL_PARAMETER :
|
||||||
|
print(preferences.getBool(command->eeprom_name));
|
||||||
|
break;
|
||||||
|
case NONE_PARAMETER :
|
||||||
|
default :
|
||||||
|
println("Error -- line:" STRINGIFY(__LINE__) ", file" __FILE__ );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
println(";");
|
||||||
|
}
|
||||||
|
preferences.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::print_config_from_eeprom(){
|
||||||
|
println("{");
|
||||||
|
for (uint32_t i=0; i<terminal_command_count; i++) {
|
||||||
|
print_value_from_eeprom(terminal_commands[i]);
|
||||||
|
}
|
||||||
|
println("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Terminal::print_config_from_eeprom(const char* eeprom_name){
|
||||||
|
for(uint32_t i=0; i<terminal_command_count; i++){
|
||||||
|
if(
|
||||||
|
!strncmp(
|
||||||
|
terminal_commands[i]->eeprom_name, eeprom_name,
|
||||||
|
MAX_EEPROM_NAME_LENGTH
|
||||||
|
)
|
||||||
|
){
|
||||||
|
print_value_from_eeprom(terminal_commands[i]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::reset_to_constructor_config(){
|
||||||
|
print("Reseting to constructor configuration ... ");
|
||||||
|
const constexpr bool read_only = false;
|
||||||
|
preferences.begin(
|
||||||
|
preferences_namespace, read_only, preferences_nvs_partition
|
||||||
|
);
|
||||||
|
preferences.clear();
|
||||||
|
preferences.end();
|
||||||
|
println("Done.");
|
||||||
|
println("Please reset the card.");
|
||||||
|
}
|
||||||
|
bool Terminal::reset_to_constructor_config(const char* eeprom_name){
|
||||||
|
for(uint32_t i=0; i<terminal_command_count; i++){
|
||||||
|
if(
|
||||||
|
!strncmp(
|
||||||
|
terminal_commands[i]->eeprom_name, eeprom_name,
|
||||||
|
MAX_EEPROM_NAME_LENGTH
|
||||||
|
)
|
||||||
|
){
|
||||||
|
const constexpr bool read_only = false;
|
||||||
|
preferences.begin(
|
||||||
|
preferences_namespace, read_only, preferences_nvs_partition
|
||||||
|
);
|
||||||
|
if( preferences.isKey(eeprom_name) ){
|
||||||
|
preferences.remove(eeprom_name);
|
||||||
|
}
|
||||||
|
preferences.end();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::check_eeprom_names(){
|
||||||
|
for(int j=1; j<terminal_command_count; j++){
|
||||||
|
for(int i=0; i<j-1; i++){
|
||||||
|
if(
|
||||||
|
strncmp(terminal_commands[i]->eeprom_name, "", MAX_EEPROM_NAME_LENGTH)
|
||||||
|
&&
|
||||||
|
strncmp(terminal_commands[j]->eeprom_name, "", MAX_EEPROM_NAME_LENGTH)
|
||||||
|
&&
|
||||||
|
!strncmp(
|
||||||
|
terminal_commands[i]->eeprom_name, terminal_commands[j]->eeprom_name,
|
||||||
|
MAX_EEPROM_NAME_LENGTH
|
||||||
|
)
|
||||||
|
){
|
||||||
|
while(true){
|
||||||
|
print("Error : ");
|
||||||
|
print(terminal_commands[i]->name);
|
||||||
|
print(" and ");
|
||||||
|
print(terminal_commands[i]->name);
|
||||||
|
print(" have the same eeprom name : ");
|
||||||
|
println(terminal_commands[i]->eeprom_name);
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::print_saved_parameter(const terminal_command *command){
|
||||||
|
if(!have_to_be_saved_in_eeprom(command)) return;
|
||||||
|
print(command->name);
|
||||||
|
print(" : ");
|
||||||
|
switch(command->parameter){
|
||||||
|
case FLOAT_PARAMETER :
|
||||||
|
print(*static_cast<volatile float*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case DOUBLE_PARAMETER :
|
||||||
|
print(*static_cast<volatile double*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case INT_PARAMETER :
|
||||||
|
print(*static_cast<volatile int32_t*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case UINT_PARAMETER :
|
||||||
|
print(*static_cast<volatile uint32_t*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case LONGINT_PARAMETER :
|
||||||
|
print(*static_cast<volatile int64_t*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case LONGUINT_PARAMETER :
|
||||||
|
print(*static_cast<volatile uint64_t*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case BOOL_PARAMETER :
|
||||||
|
print(*static_cast<volatile bool*>(command->value_ptr));
|
||||||
|
break;
|
||||||
|
case NONE_PARAMETER :
|
||||||
|
default :
|
||||||
|
println("Error -- line:" STRINGIFY(__LINE__) ", file" __FILE__ );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::load_value_from_eeprom(
|
||||||
|
const terminal_command *command, bool enable_print
|
||||||
|
){
|
||||||
|
if(!have_to_be_saved_in_eeprom(command)) return;
|
||||||
|
const constexpr bool read_only = true;
|
||||||
|
preferences.begin(
|
||||||
|
preferences_namespace, read_only, preferences_nvs_partition
|
||||||
|
);
|
||||||
|
if( preferences.isKey(command->eeprom_name) ){
|
||||||
|
switch(command->parameter){
|
||||||
|
case FLOAT_PARAMETER :
|
||||||
|
*static_cast<volatile float*>(command->value_ptr) =
|
||||||
|
preferences.getFloat(command->eeprom_name);
|
||||||
|
break;
|
||||||
|
case DOUBLE_PARAMETER :
|
||||||
|
*static_cast<volatile double*>(command->value_ptr) =
|
||||||
|
preferences.getDouble(command->eeprom_name);
|
||||||
|
break;
|
||||||
|
case INT_PARAMETER :
|
||||||
|
*static_cast<volatile int32_t*>(command->value_ptr) =
|
||||||
|
preferences.getInt(command->eeprom_name);
|
||||||
|
break;
|
||||||
|
case UINT_PARAMETER :
|
||||||
|
*static_cast<volatile uint32_t*>(command->value_ptr) =
|
||||||
|
preferences.getUInt(command->eeprom_name);
|
||||||
|
break;
|
||||||
|
case LONGINT_PARAMETER :
|
||||||
|
*static_cast<volatile int64_t*>(command->value_ptr) =
|
||||||
|
preferences.getLong64(command->eeprom_name);
|
||||||
|
break;
|
||||||
|
case LONGUINT_PARAMETER :
|
||||||
|
*static_cast<volatile uint64_t*>(command->value_ptr) =
|
||||||
|
preferences.getULong64(command->eeprom_name);
|
||||||
|
break;
|
||||||
|
case BOOL_PARAMETER :
|
||||||
|
*static_cast<volatile bool*>(command->value_ptr) =
|
||||||
|
preferences.getBool(command->eeprom_name);
|
||||||
|
break;
|
||||||
|
case NONE_PARAMETER :
|
||||||
|
default :
|
||||||
|
println("Error -- line:" STRINGIFY(__LINE__) ", file" __FILE__ );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(enable_print){ print("(eeprom ) "); }
|
||||||
|
}else{
|
||||||
|
if(enable_print){ print("(construction) "); }
|
||||||
|
}
|
||||||
|
if(enable_print){ print_saved_parameter(command); println("");}
|
||||||
|
preferences.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Terminal::load_config_from_eeprom(bool enable_print){
|
||||||
|
if(enable_print){ println("Loading config :"); }
|
||||||
|
for (uint32_t i=0; i<terminal_command_count; i++) {
|
||||||
|
load_value_from_eeprom(terminal_commands[i], enable_print);
|
||||||
|
}
|
||||||
|
if(enable_print){ println("Config is Loaded."); }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Terminal::load_config_from_eeprom(
|
||||||
|
const char* eeprom_name, bool enable_print
|
||||||
|
){
|
||||||
|
for(uint32_t i=0; i<terminal_command_count; i++){
|
||||||
|
if(
|
||||||
|
!strncmp(
|
||||||
|
terminal_commands[i]->eeprom_name, eeprom_name,
|
||||||
|
MAX_EEPROM_NAME_LENGTH
|
||||||
|
)
|
||||||
|
){
|
||||||
|
load_value_from_eeprom(terminal_commands[i], enable_print);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
464
prog/terminal.hpp
Normal file
464
prog/terminal.hpp
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015-2019 Grégoire Passault <gregoire.passault@u-bordeaux.fr>
|
||||||
|
* Copyright (C) 2019-2025 Adrien Boussicault <adrien.boussicault@labri.fr>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation, either
|
||||||
|
* version 3 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Preferences.h>
|
||||||
|
#include "serial_print.hpp"
|
||||||
|
|
||||||
|
namespace terminal_n {
|
||||||
|
|
||||||
|
enum paramter_type {
|
||||||
|
NONE_PARAMETER,
|
||||||
|
FLOAT_PARAMETER,
|
||||||
|
DOUBLE_PARAMETER,
|
||||||
|
INT_PARAMETER,
|
||||||
|
UINT_PARAMETER,
|
||||||
|
LONGINT_PARAMETER,
|
||||||
|
LONGUINT_PARAMETER,
|
||||||
|
BOOL_PARAMETER
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* To defined a new command, use the MACRO
|
||||||
|
* TERMINAL_COMMAND(terminal, name, description)
|
||||||
|
*
|
||||||
|
* @param name : the name of the command, without space, without quotes
|
||||||
|
* @param description : the description of the command, with quote
|
||||||
|
*
|
||||||
|
* use terminal_print() to print on output
|
||||||
|
* use the variables arc and argv to get the string of given arguments
|
||||||
|
*
|
||||||
|
* If you declared the terminal in the following way, in another file :
|
||||||
|
*
|
||||||
|
* #include "terminal.hpp"
|
||||||
|
* terminal_n::Terminal terminal("The terminal\n\r");
|
||||||
|
*
|
||||||
|
* you can add that command in other file :
|
||||||
|
*
|
||||||
|
* #include "terminal.hpp"
|
||||||
|
* extern terminal_n::Terminal terminal;
|
||||||
|
*
|
||||||
|
* TERMINAL_COMMAND(terminal, hello, "Print a friendly warming welcoming message")
|
||||||
|
* {
|
||||||
|
* if (argc > 0) {
|
||||||
|
* terminal.print("Hello ");
|
||||||
|
* terminal.println(argv[0]);
|
||||||
|
* terminal.print("Other params: ");
|
||||||
|
* for (uint32_t i=1;i<argc;i++) {
|
||||||
|
* terminal.print(argv[i]);
|
||||||
|
* terminal.print(" ");
|
||||||
|
* }
|
||||||
|
* terminal.println("");
|
||||||
|
* } else {
|
||||||
|
* terminal.println("Hello world");
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* WARNING: In order for the commands to be automatically registered with the
|
||||||
|
* terminal at startup, the file containing the setup() and loop() functions
|
||||||
|
* must be placed last in the list of files during the linking stage.
|
||||||
|
*
|
||||||
|
* In PlatformIO, to do this, simply begin the name of the file containing the
|
||||||
|
* loop() and setup() functions with the letter z.
|
||||||
|
*
|
||||||
|
* For example: zzz_main.cpp.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const constexpr int MAX_EEPROM_NAME_LENGTH = 15;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prototype of a terminal command
|
||||||
|
*/
|
||||||
|
typedef void terminal_command_fn(uint32_t argc, char *argv[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command definition for the terminal
|
||||||
|
*/
|
||||||
|
struct terminal_command
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
char *description;
|
||||||
|
terminal_command_fn *command;
|
||||||
|
paramter_type parameter;
|
||||||
|
char *parameter_type;
|
||||||
|
bool auto_save_after_command;
|
||||||
|
volatile void* value_ptr;
|
||||||
|
char eeprom_name[MAX_EEPROM_NAME_LENGTH+1];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline float atof(char *str){
|
||||||
|
int32_t sign = (str[0]=='-') ? -1 : 1;
|
||||||
|
float f = atoi(str);
|
||||||
|
char *savePtr;
|
||||||
|
strtok_r(str, ".", &savePtr);
|
||||||
|
char *floatPart = strtok_r(NULL, ".", &savePtr);
|
||||||
|
if (floatPart != NULL) {
|
||||||
|
float divide = 1;
|
||||||
|
for (char *tmp=floatPart; *tmp!='\0'; tmp++) {
|
||||||
|
divide *= 10;
|
||||||
|
}
|
||||||
|
f += sign*atoi(floatPart)/divide;
|
||||||
|
}
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef PREFERENCES_NAMESPACE
|
||||||
|
#define PREFERENCES_NAMESPACE "terminal"
|
||||||
|
#endif
|
||||||
|
#ifndef PREFERENCES_NVS_PART
|
||||||
|
#define PREFERENCES_NVS_PARTITION "nvs"
|
||||||
|
#endif
|
||||||
|
#ifndef TERMINAL_BUFFER_SIZE
|
||||||
|
/**
|
||||||
|
* Maximum length of a command line
|
||||||
|
* and its argument
|
||||||
|
*/
|
||||||
|
#define TERMINAL_BUFFER_SIZE 64
|
||||||
|
#endif
|
||||||
|
#ifndef TERMINAL_MAX_ARGUMENTS
|
||||||
|
/**
|
||||||
|
* Maximum number of command arguments
|
||||||
|
*/
|
||||||
|
#define TERMINAL_MAX_ARGUMENTS 12
|
||||||
|
#endif
|
||||||
|
#ifndef TERMINAL_MAX_COMMANDS
|
||||||
|
/**
|
||||||
|
* Maximum number of commands
|
||||||
|
* which ca be registered
|
||||||
|
*/
|
||||||
|
#define TERMINAL_MAX_COMMANDS 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct Terminal {
|
||||||
|
const char* documentation;
|
||||||
|
Preferences preferences;
|
||||||
|
static const constexpr char* preferences_namespace = PREFERENCES_NAMESPACE;
|
||||||
|
static const constexpr char* preferences_nvs_partition = PREFERENCES_NVS_PARTITION;
|
||||||
|
|
||||||
|
static constexpr const int terminal_buffer_size = TERMINAL_BUFFER_SIZE;
|
||||||
|
static constexpr const int terminal_max_arguments = TERMINAL_MAX_ARGUMENTS;
|
||||||
|
static constexpr const int terminal_max_commands = TERMINAL_MAX_COMMANDS;
|
||||||
|
|
||||||
|
char terminal_buffer[terminal_buffer_size] = {0};
|
||||||
|
|
||||||
|
HardwareSerial* io = 0;
|
||||||
|
bool silent;
|
||||||
|
bool disabled = false;
|
||||||
|
bool terminal_last_ok = false;
|
||||||
|
uint32_t terminal_last_pos = 0;
|
||||||
|
uint32_t terminal_pos = 0;
|
||||||
|
bool terminal_echo_mode = true;
|
||||||
|
|
||||||
|
uint32_t terminal_command_count = 0;
|
||||||
|
const struct terminal_command *terminal_commands[terminal_max_commands];
|
||||||
|
|
||||||
|
static constexpr const char* PROMPT = "$ ";
|
||||||
|
|
||||||
|
Terminal(const char* documentation=""):
|
||||||
|
documentation(documentation)
|
||||||
|
{}
|
||||||
|
|
||||||
|
inline void write_char(char c){
|
||||||
|
if(!silent){ io->write(c); }
|
||||||
|
}
|
||||||
|
inline void write(const char* buf, uint32_t len){
|
||||||
|
if(!silent){ io->write((const uint8_t*)buf, len); }
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline void print(T v){
|
||||||
|
if(!silent){ serial_print(io, v); }
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline void println(T v){
|
||||||
|
if(!silent){ serial_println(io, v); }
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline void print_hex(T v){
|
||||||
|
if(!silent){ serial_print_hex(io, v); }
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
inline void println_hex(T v){
|
||||||
|
if(!silent){ serial_println_hex(io, v); }
|
||||||
|
}
|
||||||
|
inline bool terminal_has_io(){
|
||||||
|
return io;
|
||||||
|
}
|
||||||
|
inline void print_hexa(uint8_t* buf, uint32_t n){
|
||||||
|
uint8_t first=0, last=0;
|
||||||
|
for( uint32_t i=0; i<n; i++ ){
|
||||||
|
first = buf[i] >> 4;
|
||||||
|
last = buf[i] & 0x0F;
|
||||||
|
print( 'x' );
|
||||||
|
print( static_cast<char>( (first < 10 ? '0' : 'A'-10) + first ) );
|
||||||
|
print( static_cast<char>( (last < 10 ? '0' : 'A'-10) + last ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void println_hexa(uint8_t* buf, uint32_t n){
|
||||||
|
print_hexa(buf,1);
|
||||||
|
println("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the terminal
|
||||||
|
*/
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the terminal
|
||||||
|
*/
|
||||||
|
void enable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable the terminal
|
||||||
|
*/
|
||||||
|
void disable();
|
||||||
|
|
||||||
|
void print_prompt();
|
||||||
|
|
||||||
|
void setup(HardwareSerial* serial);
|
||||||
|
/**
|
||||||
|
* Terminal update
|
||||||
|
* Call this function in your main loop
|
||||||
|
* to fetch serial port and handle terminal
|
||||||
|
*/
|
||||||
|
void update();
|
||||||
|
|
||||||
|
const terminal_command * find_command(
|
||||||
|
char *command_name, uint32_t command_name_length
|
||||||
|
);
|
||||||
|
|
||||||
|
bool terminal_execute(
|
||||||
|
char *command_name, uint32_t command_name_length, uint32_t argc, char **argv
|
||||||
|
);
|
||||||
|
|
||||||
|
void terminal_process();
|
||||||
|
|
||||||
|
bool have_to_be_saved_in_eeprom(const terminal_command *command);
|
||||||
|
void check_eeprom_names();
|
||||||
|
void save_value_to_eeprom(const terminal_command *command);
|
||||||
|
bool save_config_to_eeprom(const char* eeprom_name);
|
||||||
|
void save_config_to_eeprom();
|
||||||
|
void load_config_from_eeprom(bool enable_print=true);
|
||||||
|
bool load_config_from_eeprom(const char* eeprom_name, bool enable_print);
|
||||||
|
void load_value_from_eeprom(
|
||||||
|
const terminal_command *command, bool enable_print=false
|
||||||
|
);
|
||||||
|
void print_saved_parameter(const terminal_command *command);
|
||||||
|
void print_value_from_eeprom(const struct terminal_command *command);
|
||||||
|
void print_config_from_eeprom();
|
||||||
|
bool print_config_from_eeprom(const char* eeprom_name);
|
||||||
|
void reset_to_constructor_config();
|
||||||
|
bool reset_to_constructor_config(const char* eeprom_name);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a command
|
||||||
|
*/
|
||||||
|
void register_command(struct terminal_command *command);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mute the terminal
|
||||||
|
*/
|
||||||
|
void terminal_silent(bool silent);
|
||||||
|
void displayHelp(bool parameter);
|
||||||
|
void terminal_params_show();
|
||||||
|
|
||||||
|
void echo_command(uint32_t argc, char *argv[]);
|
||||||
|
void params_command(uint32_t argc, char *argv[]);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define TERMINAL_COMMAND_INTERNAL(term, name, eeprom_name, description, parameter, parameterType, auto_save_after_command, value_ptr) terminal_n::terminal_command_fn terminal_command_ ## name; \
|
||||||
|
\
|
||||||
|
char terminal_command_name_ ## name [] = #name; \
|
||||||
|
char terminal_command_description_ ## name [] = description; \
|
||||||
|
\
|
||||||
|
struct terminal_n::terminal_command terminal_command_definition_ ## name = { \
|
||||||
|
terminal_command_name_ ## name , \
|
||||||
|
terminal_command_description_ ## name , \
|
||||||
|
terminal_command_ ## name, \
|
||||||
|
parameter, \
|
||||||
|
parameterType, \
|
||||||
|
auto_save_after_command, \
|
||||||
|
value_ptr, \
|
||||||
|
eeprom_name \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
__attribute__((constructor)) \
|
||||||
|
void terminal_command_init_ ## name () { \
|
||||||
|
term.register_command(&terminal_command_definition_ ## name ); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void terminal_command_ ## name (uint32_t argc, char *argv[])
|
||||||
|
|
||||||
|
#define TERMINAL_COMMAND(term, name, description) \
|
||||||
|
TERMINAL_COMMAND_INTERNAL(term, name, "", description, terminal_n::NONE_PARAMETER, NULL, false, NULL)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define TERMINAL_PARAMETER(term, name, eeprom_name, description, startValue, type, enum_type, conversion, auto_save_after_command, filter_function, finish_function) \
|
||||||
|
volatile static type name = startValue; \
|
||||||
|
char terminal_parameter_type_ ## name [] = #type; \
|
||||||
|
\
|
||||||
|
TERMINAL_COMMAND_INTERNAL(term, name, eeprom_name, description, enum_type, terminal_parameter_type_ ## name, auto_save_after_command, &name) \
|
||||||
|
{ \
|
||||||
|
type g; \
|
||||||
|
if (argc) { \
|
||||||
|
g = conversion(argv[0]); \
|
||||||
|
if( filter_function(g, name) ){ \
|
||||||
|
type old = name; \
|
||||||
|
name = g; \
|
||||||
|
finish_function(name, old); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
term.print( #name ); \
|
||||||
|
term.print("="); \
|
||||||
|
term.println( name ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline bool filter_nothing(T & new_value, T old_value){return true;}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void do_nothing(T new_value, T old_value){}
|
||||||
|
|
||||||
|
#define TERMINAL_PARAMETER_FLOAT(term, name, eeprom_name, description, startValue, auto_save_after_command, filter_function, finish_function) \
|
||||||
|
TERMINAL_PARAMETER(term, name, eeprom_name, description, startValue, float, terminal_n::FLOAT_PARAMETER, terminal_n::atof, auto_save_after_command, filter_function, finish_function)
|
||||||
|
|
||||||
|
#define TERMINAL_PARAMETER_DOUBLE(term, name, eeprom_name, description, startValue, auto_save_after_command, filter_function, finish_function) \
|
||||||
|
TERMINAL_PARAMETER(term, name, eeprom_name, description, startValue, double, terminal_n::DOUBLE_PARAMETER, terminal_n::atof, auto_save_after_command, filter_function, finish_function)
|
||||||
|
|
||||||
|
#define TERMINAL_PARAMETER_INT(term, name, eeprom_name, description, startValue, auto_save_after_command, filter_function, finish_function) \
|
||||||
|
TERMINAL_PARAMETER(term, name, eeprom_name, description, startValue, int32_t, terminal_n::INT_PARAMETER, atoi, auto_save_after_command, filter_function, finish_function)
|
||||||
|
|
||||||
|
|
||||||
|
#define TERMINAL_PARAMETER_UINT(term, name, eeprom_name, description, startValue, auto_save_after_command, filter_function, finish_function) \
|
||||||
|
TERMINAL_PARAMETER(term, name, eeprom_name, description, startValue, uint32_t, terminal_n::UINT_PARAMETER, atoi, auto_save_after_command, filter_function, finish_function)
|
||||||
|
|
||||||
|
#define TERMINAL_PARAMETER_LONGINT(term, name, eeprom_name, description, startValue, auto_save_after_command, filter_function, finish_function) \
|
||||||
|
TERMINAL_PARAMETER(term, name, eeprom_name, description, startValue, int64_t, terminal_n::LONGINT_PARAMETER, atoi, auto_save_after_command, filter_function, finish_function)
|
||||||
|
|
||||||
|
#define TERMINAL_PARAMETER_LONGUINT(term, name, eeprom_name, description, startValue, auto_save_after_command, filter_function, finish_function) \
|
||||||
|
TERMINAL_PARAMETER(term, name, eeprom_name, description, startValue, uint64_t, terminal_n::LONGUINT_PARAMETER, atoi, auto_save_after_command, filter_function, finish_function)
|
||||||
|
|
||||||
|
#define TERMINAL_PARAMETER_BOOL(term, name, eeprom_name, description, startValue, auto_save_after_command, filter_function, finish_function) \
|
||||||
|
TERMINAL_PARAMETER(term, name, eeprom_name, description, startValue, bool, terminal_n::BOOL_PARAMETER, (bool)atoi, auto_save_after_command, filter_function, finish_function)
|
||||||
|
|
||||||
|
#define TERMINAL_ADD_DEFAULT_COMMANDS(term) \
|
||||||
|
TERMINAL_COMMAND(term, save_config, "Save the config to EEPROM (save_config [eeprom_name])") \
|
||||||
|
{ \
|
||||||
|
if(argc !=0 and argc != 1){ term.println("Invalid parameters"); return; } \
|
||||||
|
if(argc == 0){ \
|
||||||
|
term.save_config_to_eeprom(); \
|
||||||
|
term.println("All is saved."); \
|
||||||
|
}else{ \
|
||||||
|
if( \
|
||||||
|
term.save_config_to_eeprom(argv[0]) \
|
||||||
|
){ \
|
||||||
|
term.println("Saved.");\
|
||||||
|
}else{ \
|
||||||
|
term.println("Failed.");\
|
||||||
|
}; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
TERMINAL_COMMAND(term, load_config, "Load config from EEPROM (load_config [eeprom_name])") \
|
||||||
|
{ \
|
||||||
|
bool print = true; \
|
||||||
|
if(argc !=0 and argc != 1){ term.println("Invalid parameters"); return; } \
|
||||||
|
if(argc == 0){ \
|
||||||
|
term.load_config_from_eeprom(print); \
|
||||||
|
}else{ \
|
||||||
|
if( \
|
||||||
|
! term.load_config_from_eeprom(argv[0], print) \
|
||||||
|
){ \
|
||||||
|
term.println("Failed.");\
|
||||||
|
}; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
TERMINAL_COMMAND(term, reset_config, "Reset to constructor configuration (reset_config [eeprom_name])") \
|
||||||
|
{ \
|
||||||
|
if(argc !=0 and argc != 1){ term.println("Invalid parameters"); return; } \
|
||||||
|
if(argc == 0){ \
|
||||||
|
term.reset_to_constructor_config(); \
|
||||||
|
term.println("All is reseted."); \
|
||||||
|
}else{ \
|
||||||
|
if( \
|
||||||
|
term.reset_to_constructor_config(argv[0]) \
|
||||||
|
){ \
|
||||||
|
term.println("Reseted.");\
|
||||||
|
}else{ \
|
||||||
|
term.println("Failed.");\
|
||||||
|
}; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
TERMINAL_COMMAND(term, print_config, "Print EEPROM configuration (print_config [eeprom_name])") \
|
||||||
|
{ \
|
||||||
|
if(argc !=0 and argc != 1){ term.println("Invalid parameters"); return; } \
|
||||||
|
if(argc == 0){ \
|
||||||
|
term.print_config_from_eeprom(); \
|
||||||
|
}else{ \
|
||||||
|
if( \
|
||||||
|
! term.print_config_from_eeprom(argv[0]) \
|
||||||
|
){ \
|
||||||
|
term.println("Failed.");\
|
||||||
|
}; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
TERMINAL_COMMAND(term, help, "Displays the help about commands") \
|
||||||
|
{ \
|
||||||
|
term.displayHelp(false); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
TERMINAL_COMMAND(term, params, "Displays the available parameters. Usage: params [show]") \
|
||||||
|
{ \
|
||||||
|
term.params_command(argc, argv); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
TERMINAL_COMMAND(term, echo, "Switch echo mode. Usage echo [on|off]") \
|
||||||
|
{ \
|
||||||
|
term.echo_command(argc, argv); \
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user