#pragma once #include #include #include #include #include "flash/flash.hpp" #include "controller.hpp" GF(ENDL, "\r\n"); GF(HELP_CMD, "help"); GF(SHOW_CMD, "show"); GF(CURVE_CMD, "curve"); constexpr auto BACKSPACE = uint8_t{0x7f}; constexpr auto CTRL_C = uint8_t{0x03}; template class Terminal { public: static void init() { m_serial.init(); m_serial << ENDL << F("FanTemp Control Panel") << ENDL << ENDL << F("$ "); } static void callback() { uint8_t inputByte; bool handleInput = false; while (m_serial.rxByte(inputByte)) { if (isprint(inputByte) || inputByte == CTRL_C) { m_inputBuffer[m_inputSize++] = inputByte; // Handle Ctrl + C if (inputByte == CTRL_C) { m_serial << F("^C") << ENDL; handleInput = true; break; } // Echo else { m_serial << static_cast(inputByte); } } // Handle backspace if (inputByte == BACKSPACE && m_inputSize > 0) { m_serial << static_cast(BACKSPACE); --m_inputSize; } // Handle line terminator else if (inputByte == '\r' || inputByte == '\n') { // Consume possible second line terminator if (m_serial.peek(inputByte) && (inputByte == '\r' || inputByte == '\n')) { m_serial.rxByte(inputByte); } m_serial << ENDL; handleInput = true; break; } if (m_inputSize >= INPUT_BUFFER_SIZE) { m_serial << ENDL << F("WARNING: Terminal input buffer overflow!") << ENDL; handleInput = true; break; } } if (handleInput) { parseInput(); m_inputSize = 0; m_serial << F("$ "); } } private: static constexpr auto INPUT_BUFFER_SIZE = 128; static Uart m_serial; static char m_inputBuffer[INPUT_BUFFER_SIZE]; static uint16_t m_inputSize; static void parseInput() { if (m_inputSize) { if (m_inputBuffer[m_inputSize - 1] == CTRL_C) { handleCtrlC(); } else if (strncmp_P(m_inputBuffer, reinterpret_cast(HELP_CMD), m_inputSize) == 0) { printHelp(); } else if (strncmp_P(m_inputBuffer, reinterpret_cast(SHOW_CMD), m_inputSize) == 0) { showState(); } else if (strncmp_P(m_inputBuffer, reinterpret_cast(CURVE_CMD), m_inputSize) == 0) { printCurve(); } else { printUnknown(); } } } static void handleCtrlC() { m_serial << F("Abort!") << ENDL; } 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; } static void showState() { char floatBuffer[16]; sprintf(floatBuffer, "%.2f", Controller::m_adcSample); m_serial << F("ADC value ...: ") << floatBuffer << F(" / 1023") << ENDL; sprintf(floatBuffer, "%.2f", Controller::m_resistance); m_serial << F("Resistance ..: ") << floatBuffer << F(" Ohm") << 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; } static void printCurve() { for (uint8_t i = 10; i <= 60; ++i) { m_serial << i << F(" C = "); m_serial.template txNumber(Controller::mapTemperature(i)); m_serial << F("%\t"); for (uint8_t s = 0; s < Controller::mapTemperature(i); ++s) { m_serial << "#"; } m_serial << ENDL; } } static void printUnknown() { m_serial << F("Unknown command \""); for (uint16_t i = 0; i < m_inputSize; ++i) m_serial << static_cast(m_inputBuffer[i]); m_serial << F("\"") << ENDL; } }; template char Terminal::m_inputBuffer[INPUT_BUFFER_SIZE]; template uint16_t Terminal::m_inputSize = 0;