diff --git a/exercises/15_RAM/src/main.cpp b/exercises/15_RAM/src/main.cpp index 5f3c5a6..17eb519 100644 --- a/exercises/15_RAM/src/main.cpp +++ b/exercises/15_RAM/src/main.cpp @@ -21,6 +21,11 @@ static U8G2_SH1106_128X64_NONAME_F_HW_I2C g_oled(U8G2_R0, U8X8_PIN_NONE); +static const char *kTmpPath = "/tmp/volatile.txt"; +static const size_t kTmpFileCapacity = 4096; +static char g_tmpFileBuffer[kTmpFileCapacity]; +static size_t g_tmpFileSize = 0; + static void oledShowLines(const char *l1, const char *l2 = nullptr, const char *l3 = nullptr, @@ -65,6 +70,112 @@ static void printRamStatus() oledShowLines(line1, line2, line3, line4, line5); } +static void showHelp() +{ + Serial.println("RAM command list:"); + Serial.println(" help - show this menu"); + Serial.println(" stat - show /tmp file state"); + Serial.println(" read - read /tmp contents"); + Serial.println(" clear - clear /tmp contents"); + Serial.println(" write - write text to /tmp"); + Serial.println(" append - append text to /tmp"); +} + +static void printTmpFileStat() +{ + Serial.printf("Path: %s\r\n", kTmpPath); + Serial.printf("Size: %u bytes\r\n", (unsigned)g_tmpFileSize); + Serial.printf("Capacity: %u bytes\r\n", (unsigned)kTmpFileCapacity); +} + +static void printTmpFileContents() +{ + if (g_tmpFileSize == 0) { + Serial.println("/tmp file is empty"); + return; + } + + Serial.print("/tmp contents: "); + Serial.write((const uint8_t *)g_tmpFileBuffer, g_tmpFileSize); + if (g_tmpFileBuffer[g_tmpFileSize - 1] != '\n') + Serial.println(); +} + +static void setTmpFileContent(const char *text) +{ + if (!text) { + g_tmpFileSize = 0; + return; + } + const size_t newLen = strlen(text); + if (newLen > kTmpFileCapacity - 1) { + Serial.printf("Error: content too large (%u/%u)\r\n", (unsigned)newLen, (unsigned)kTmpFileCapacity); + return; + } + memcpy(g_tmpFileBuffer, text, newLen); + g_tmpFileSize = newLen; +} + +static void appendTmpFileContent(const char *text) +{ + if (!text || text[0] == '\0') return; + const size_t textLen = strlen(text); + if (g_tmpFileSize + textLen > kTmpFileCapacity - 1) { + Serial.printf("Error: append would exceed %u bytes\r\n", (unsigned)kTmpFileCapacity); + return; + } + memcpy(g_tmpFileBuffer + g_tmpFileSize, text, textLen); + g_tmpFileSize += textLen; +} + +static void processSerialCommand(const char *line) +{ + if (!line || line[0] == '\0') return; + + char tmp[384]; + strncpy(tmp, line, sizeof(tmp) - 1); + tmp[sizeof(tmp) - 1] = '\0'; + + char *cmd = strtok(tmp, " \t\r\n"); + if (!cmd) return; + + if (strcasecmp(cmd, "help") == 0) { + showHelp(); + return; + } + + if (strcasecmp(cmd, "stat") == 0) { + printTmpFileStat(); + return; + } + + if (strcasecmp(cmd, "read") == 0) { + printTmpFileContents(); + return; + } + + if (strcasecmp(cmd, "clear") == 0) { + g_tmpFileSize = 0; + Serial.println("/tmp cleared"); + return; + } + + if (strcasecmp(cmd, "write") == 0 || strcasecmp(cmd, "append") == 0) { + const char *payload = line + strlen(cmd); + while (*payload == ' ' || *payload == '\t') payload++; + if (strcasecmp(cmd, "write") == 0) + setTmpFileContent(payload); + else + appendTmpFileContent(payload); + + Serial.printf("%s: %u bytes\r\n", cmd, + (unsigned)g_tmpFileSize); + return; + } + + Serial.println("Unknown command (help for list)"); +} + void setup() { Serial.begin(115200); @@ -83,6 +194,25 @@ void loop() { static uint32_t lastMs = 0; const uint32_t now = millis(); + + // check serial commands at all times + static char rxLine[384]; + static size_t rxLen = 0; + + while (Serial.available()) { + int c = Serial.read(); + if (c <= 0) continue; + if (c == '\r' || c == '\n') { + if (rxLen > 0) { + rxLine[rxLen] = '\0'; + processSerialCommand(rxLine); + rxLen = 0; + } + } else if (rxLen + 1 < sizeof(rxLine)) { + rxLine[rxLen++] = (char)c; + } + } + if (now - lastMs < 1000) { delay(10); return;