|
|
|
@ -10,6 +10,8 @@
|
|
|
|
|
|
|
|
|
|
#include "controller.hpp"
|
|
|
|
|
|
|
|
|
|
namespace detail {
|
|
|
|
|
|
|
|
|
|
GF(ENDL, "\r\n");
|
|
|
|
|
GF(HELP_CMD, "help");
|
|
|
|
|
GF(SHOW_CMD, "show");
|
|
|
|
@ -17,10 +19,23 @@ GF(CURVE_CMD, "curve");
|
|
|
|
|
GF(MONITOR_CMD, "monitor");
|
|
|
|
|
GF(BOOTLOADER_CMD, "bootloader");
|
|
|
|
|
GF(VERSION_CMD, "version");
|
|
|
|
|
GF(VERSION, "1.1");
|
|
|
|
|
GF(VERSION, "1.2");
|
|
|
|
|
|
|
|
|
|
constexpr auto BACKSPACE = uint8_t{0x7f};
|
|
|
|
|
constexpr auto CTRL_C = uint8_t{0x03};
|
|
|
|
|
static inline bool substringEquals(const char *str, const ::detail::FlashString *flashStr, const size_t &size)
|
|
|
|
|
{
|
|
|
|
|
return (strncmp_P(str, reinterpret_cast<const char *>(flashStr), size) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool stringEquals(const char *str, const ::detail::FlashString *flashStr, const size_t &size)
|
|
|
|
|
{
|
|
|
|
|
if (size == strlen_P(reinterpret_cast<const char *>(flashStr))) {
|
|
|
|
|
return substringEquals(str, flashStr, size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
|
|
template <class Uart>
|
|
|
|
|
class Terminal {
|
|
|
|
@ -29,9 +44,9 @@ class Terminal {
|
|
|
|
|
{
|
|
|
|
|
m_serial.init();
|
|
|
|
|
|
|
|
|
|
m_serial << ENDL;
|
|
|
|
|
m_serial << detail::ENDL;
|
|
|
|
|
printVersion();
|
|
|
|
|
m_serial << ENDL << F("$ ");
|
|
|
|
|
m_serial << detail::ENDL << F("$ ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void callback()
|
|
|
|
@ -45,7 +60,7 @@ class Terminal {
|
|
|
|
|
|
|
|
|
|
// Handle Ctrl + C
|
|
|
|
|
if (inputByte == CTRL_C) {
|
|
|
|
|
m_serial << F("^C") << ENDL;
|
|
|
|
|
m_serial << F("^C") << detail::ENDL;
|
|
|
|
|
handleInput = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -66,13 +81,13 @@ class Terminal {
|
|
|
|
|
if (m_serial.peek(inputByte) && (inputByte == '\r' || inputByte == '\n')) {
|
|
|
|
|
m_serial.rxByte(inputByte);
|
|
|
|
|
}
|
|
|
|
|
m_serial << ENDL;
|
|
|
|
|
m_serial << detail::ENDL;
|
|
|
|
|
handleInput = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_inputSize >= INPUT_BUFFER_SIZE) {
|
|
|
|
|
m_serial << ENDL << F("WARNING: Terminal input buffer overflow!") << ENDL;
|
|
|
|
|
m_serial << detail::ENDL << F("WARNING: Terminal input buffer overflow!") << detail::ENDL;
|
|
|
|
|
handleInput = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -80,16 +95,19 @@ class Terminal {
|
|
|
|
|
|
|
|
|
|
if (handleInput) {
|
|
|
|
|
parseInput();
|
|
|
|
|
m_inputSize = 0;
|
|
|
|
|
m_serial << F("$ ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_state == State::MONITOR)
|
|
|
|
|
if (m_state == State::MONITOR && --m_monitorDelayCounter == 0) {
|
|
|
|
|
showState();
|
|
|
|
|
m_monitorDelayCounter = MONITOR_DELAY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
static constexpr auto INPUT_BUFFER_SIZE = 128;
|
|
|
|
|
static constexpr auto BACKSPACE = uint8_t{0x7f};
|
|
|
|
|
static constexpr auto CTRL_C = uint8_t{0x03};
|
|
|
|
|
static constexpr auto MONITOR_DELAY = 60000;
|
|
|
|
|
|
|
|
|
|
enum class State {
|
|
|
|
|
NONE,
|
|
|
|
@ -100,45 +118,53 @@ class Terminal {
|
|
|
|
|
static char m_inputBuffer[INPUT_BUFFER_SIZE];
|
|
|
|
|
static uint16_t m_inputSize;
|
|
|
|
|
static State m_state;
|
|
|
|
|
static uint16_t m_monitorDelayCounter;
|
|
|
|
|
|
|
|
|
|
static void parseInput()
|
|
|
|
|
{
|
|
|
|
|
if (m_inputSize) {
|
|
|
|
|
if (m_inputBuffer[m_inputSize - 1] == CTRL_C) {
|
|
|
|
|
handleCtrlC();
|
|
|
|
|
} else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(HELP_CMD), m_inputSize) == 0) {
|
|
|
|
|
printHelp();
|
|
|
|
|
} else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(SHOW_CMD), m_inputSize) == 0) {
|
|
|
|
|
showState();
|
|
|
|
|
} else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(CURVE_CMD), m_inputSize) == 0) {
|
|
|
|
|
printCurve();
|
|
|
|
|
} else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(MONITOR_CMD), m_inputSize) == 0) {
|
|
|
|
|
m_state = State::MONITOR;
|
|
|
|
|
} else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(BOOTLOADER_CMD), m_inputSize) == 0) {
|
|
|
|
|
handleBootloader();
|
|
|
|
|
} else if (strncmp_P(m_inputBuffer, reinterpret_cast<const char *>(VERSION_CMD), m_inputSize) == 0) {
|
|
|
|
|
printVersion();
|
|
|
|
|
} else {
|
|
|
|
|
printUnknown();
|
|
|
|
|
} else if (m_state == State::NONE) {
|
|
|
|
|
if (substringEquals(m_inputBuffer, detail::HELP_CMD, m_inputSize)) {
|
|
|
|
|
printHelp();
|
|
|
|
|
} else if (substringEquals(m_inputBuffer, detail::SHOW_CMD, m_inputSize)) {
|
|
|
|
|
showState();
|
|
|
|
|
} else if (substringEquals(m_inputBuffer, detail::CURVE_CMD, m_inputSize)) {
|
|
|
|
|
printCurve();
|
|
|
|
|
} else if (substringEquals(m_inputBuffer, detail::MONITOR_CMD, m_inputSize)) {
|
|
|
|
|
m_state = State::MONITOR;
|
|
|
|
|
m_monitorDelayCounter = MONITOR_DELAY;
|
|
|
|
|
} else if (substringEquals(m_inputBuffer, detail::BOOTLOADER_CMD, m_inputSize)) {
|
|
|
|
|
handleBootloader();
|
|
|
|
|
} else if (substringEquals(m_inputBuffer, detail::VERSION_CMD, m_inputSize)) {
|
|
|
|
|
printVersion();
|
|
|
|
|
} else {
|
|
|
|
|
printUnknown();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_inputSize = 0;
|
|
|
|
|
if (m_state == State::NONE)
|
|
|
|
|
m_serial << F("$ ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void handleCtrlC()
|
|
|
|
|
{
|
|
|
|
|
m_serial << F("Abort!") << ENDL;
|
|
|
|
|
m_serial << F("Abort!") << detail::ENDL;
|
|
|
|
|
m_state = State::NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void printHelp()
|
|
|
|
|
{
|
|
|
|
|
m_serial << F("FanTemp command overview: ") << ENDL;
|
|
|
|
|
m_serial << HELP_CMD << F(" .......: print this help message") << ENDL;
|
|
|
|
|
m_serial << SHOW_CMD << F(" .......: shows current temperature and fan speed") << ENDL;
|
|
|
|
|
m_serial << CURVE_CMD << F(" ......: shows the curve used to map temperature to fan speed") << ENDL;
|
|
|
|
|
m_serial << MONITOR_CMD << F(" ....: loops the show command until Ctrl + C is pressed") << ENDL;
|
|
|
|
|
m_serial << BOOTLOADER_CMD << F(" .: enters the bootloader after 10 seconds") << ENDL;
|
|
|
|
|
m_serial << VERSION_CMD << F(" ....: displays firmware version") << ENDL;
|
|
|
|
|
m_serial << F("FanTemp command overview: ") << detail::ENDL;
|
|
|
|
|
m_serial << detail::HELP_CMD << F(" .......: print this help message") << detail::ENDL;
|
|
|
|
|
m_serial << detail::SHOW_CMD << F(" .......: shows current temperature and fan speed") << detail::ENDL;
|
|
|
|
|
m_serial << detail::CURVE_CMD << F(" ......: shows mapping from temperature to fan speed") << detail::ENDL;
|
|
|
|
|
m_serial << detail::MONITOR_CMD << F(" ....: loops the show command until Ctrl + C is pressed") << detail::ENDL;
|
|
|
|
|
m_serial << detail::BOOTLOADER_CMD << F(" .: enters the bootloader after 3 seconds") << detail::ENDL;
|
|
|
|
|
m_serial << detail::VERSION_CMD << F(" ....: displays firmware version") << detail::ENDL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void showState()
|
|
|
|
@ -146,12 +172,12 @@ class Terminal {
|
|
|
|
|
char floatBuffer[16];
|
|
|
|
|
|
|
|
|
|
sprintf(floatBuffer, "%.2f", Controller::m_adcSample);
|
|
|
|
|
m_serial << F("ADC value ...: ") << floatBuffer << F(" / 1023") << ENDL;
|
|
|
|
|
m_serial << F("ADC value ...: ") << floatBuffer << F(" / 1023") << detail::ENDL;
|
|
|
|
|
sprintf(floatBuffer, "%.2f", Controller::m_resistance);
|
|
|
|
|
m_serial << F("Resistance ..: ") << floatBuffer << F(" Ohm") << ENDL;
|
|
|
|
|
m_serial << F("Resistance ..: ") << floatBuffer << F(" Ohm") << detail::ENDL;
|
|
|
|
|
sprintf(floatBuffer, "%.2f", Controller::m_temperature);
|
|
|
|
|
m_serial << F("Temperature .: ") << floatBuffer << F(" C") << ENDL;
|
|
|
|
|
m_serial << F("Fan speed ...: ") << Controller::m_fanSpeed << F("%") << ENDL;
|
|
|
|
|
m_serial << F("Temperature .: ") << floatBuffer << F(" C") << detail::ENDL;
|
|
|
|
|
m_serial << F("Fan speed ...: ") << Controller::m_fanSpeed << F("%") << detail::ENDL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void printCurve()
|
|
|
|
@ -163,28 +189,23 @@ class Terminal {
|
|
|
|
|
for (uint8_t s = 0; s < Controller::mapTemperature(i); ++s) {
|
|
|
|
|
m_serial << "#";
|
|
|
|
|
}
|
|
|
|
|
m_serial << ENDL;
|
|
|
|
|
m_serial << detail::ENDL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void handleBootloader()
|
|
|
|
|
{
|
|
|
|
|
for (int8_t i = 10; i >= 0; --i) {
|
|
|
|
|
m_serial << i << ENDL;
|
|
|
|
|
_delay_ms(1000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_serial << F("Entering bootloader...") << ENDL;
|
|
|
|
|
m_serial << F("Entering bootloader...") << detail::ENDL;
|
|
|
|
|
m_serial.flushTx();
|
|
|
|
|
|
|
|
|
|
_delay_ms(1000);
|
|
|
|
|
_delay_ms(3000);
|
|
|
|
|
|
|
|
|
|
Bootloader::enter();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void printVersion()
|
|
|
|
|
{
|
|
|
|
|
m_serial << F("FanTemp v") << VERSION << ENDL;
|
|
|
|
|
m_serial << F("FanTemp v") << detail::VERSION << detail::ENDL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void printUnknown()
|
|
|
|
@ -192,7 +213,7 @@ class Terminal {
|
|
|
|
|
m_serial << F("Unknown command \"");
|
|
|
|
|
for (uint16_t i = 0; i < m_inputSize; ++i)
|
|
|
|
|
m_serial << static_cast<char>(m_inputBuffer[i]);
|
|
|
|
|
m_serial << F("\"") << ENDL;
|
|
|
|
|
m_serial << F("\"") << detail::ENDL;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -204,3 +225,6 @@ uint16_t Terminal<Uart>::m_inputSize = 0;
|
|
|
|
|
|
|
|
|
|
template <class Uart>
|
|
|
|
|
typename Terminal<Uart>::State Terminal<Uart>::m_state = State::NONE;
|
|
|
|
|
|
|
|
|
|
template <class Uart>
|
|
|
|
|
uint16_t Terminal<Uart>::m_monitorDelayCounter;
|
|
|
|
|