#include "commands.h" #include "common.h" #include "parsing.h" #include "uart.h" #include "eeprom.h" #include #include #include #include #include // Mode: ASCII (false) or binary (true) bool binary_mode = false; // Execute a single parsed command void executeCommand(CommandLine cmdLine) { // Parse command if (strcmp(cmdLine.command, "INIT") == 0) { // INIT command: Initializes connection. commandInit(cmdLine.arg); } else if (strcmp(cmdLine.command, "HELP") == 0) { // HELP command: Print a list of supported commands. commandHelp(); } else if (strcmp(cmdLine.command, "READ") == 0) { // READ command: Takes a hex address range (or single address) as argument, // reads data and returns it in hexadecimal ASCII format. commandRead(cmdLine.arg); } else if (strcmp(cmdLine.command, "WRITE") == 0) { // WRITE command: Takes a hex address as argument, reads data from UART and writes it to the EEPROM. commandWrite(cmdLine.arg); } else if (strcmp(cmdLine.command, "ERASE") == 0) { // ERASE command: Takes a hex address range as argument and writes 0x00 bytes to the specified range. commandErase(cmdLine.arg); } else if (strcmp(cmdLine.command, "TESTREAD") == 0) { // TESTREAD command: for testing purposes, reads a few bytes and returns them in a human readable format. commandTestRead(); } else if (strcmp(cmdLine.command, "TESTWRITE") == 0) { // TESTWRITE command: for testing purposes, writes a few bytes commandTestWrite(cmdLine.arg); } else { // unknown command: return error message uartPutLine("ERROR invalid command"); } } void commandInit(char* arg) { // (Re-)initialize EEPROM functions eepromInit(); // Default mode: ASCII binary_mode = false; if (arg != NULL) { if (strcmp(arg, "BINARY") == 0) { binary_mode = true; } else if (strcmp(arg, "ASCII") == 0 || strcmp(arg, "TEXT") == 0) { binary_mode = false; } } if (binary_mode) { uartPutLine("OK (binary mode)"); } else { uartPutLine("OK (ASCII mode)"); } } void commandHelp() { uartPutLine("HELP - Supported commands:"); uartPutLine("HELP - HELP"); uartPutLine("HELP - INIT [BINARY|ASCII]"); uartPutLine("HELP - READ 0000:0FFF"); uartPutLine("HELP - WRITE 0000"); uartPutLine("HELP - ERASE 0000:0FFF"); // TODO remove those uartPutLine("HELP - TESTREAD (only for testing)"); uartPutLine("HELP - TESTWRITE (only for testing)"); uartPutLine("OK"); } void commandRead(char* arg) { if (arg == NULL) { uartPutLine("ERROR READ needs an address or address range"); return; } // Parse address(es) AddressRange range = parseAddressRange(arg); if (!range.isValid) { uartPutLine("ERROR invalid address format"); return; } uartPutLine("OK"); // Create data buffer DataBuffer buffer; do { buffer.bytes = 0; // Read a single block with up to DATA_BLOCK_SIZE bytes Address nextAddress = eepromReadBlock(range, &buffer); range.isValid = nextAddress.isValid; range.from = nextAddress.value; if (binary_mode) { // Send block as binary "package": // First the size of the package (1 byte) followed by the data bytes uartPutChar(buffer.bytes); for (uint8_t i = 0; i < buffer.bytes; i++) { uartPutChar(buffer.data[i]); } } else { // Fancy ASCII output uartPutString("<0x"); uartPutHexByte(buffer.bytes); uartPutChar('>'); for (uint8_t i = 0; i < buffer.bytes; i++) { uartPutChar(' '); uartPutHexByte(buffer.data[i]); } uartPutLine(NULL); } } while (buffer.bytes > 0); } void commandWrite(char* arg) { if (arg == NULL) { uartPutLine("ERROR WRITE needs a start address"); return; } // Parse address Address startAddress = parseSingleAddress(arg); if (!startAddress.isValid) { uartPutLine("ERROR invalid address format"); return; } // Only binary mode if (!binary_mode) { uartPutLine("ERROR WRITE in ASCII mode is not implemented"); return; } // "OK" indicates that data can be sent now. uartPutLine("OK START"); // Create data buffer DataBuffer buffer; Address currentAddress = startAddress; uint8_t block_length = 0; do { // Reset buffer buffer.bytes = 0; // Read and check block length block_length = uartGetChar(); if (block_length > DATA_BLOCK_SIZE) { uartPutLine("ERROR maximal block size is: " STR(DATA_BLOCK_SIZE)); return; } // Read data bytes while (buffer.bytes < block_length) { buffer.data[buffer.bytes++] = uartGetChar(); } // Write blocks to EEPROM until an "end block" (0 bytes) is received if (buffer.bytes > 0) { currentAddress = eepromWriteBlock(currentAddress, buffer); if (!currentAddress.isValid) { uartPutLine("ERROR reached end of EEPROM while writing block"); return; } else if (currentAddress.value == 0 || currentAddress.value >= HIGHEST_VALID_ADDRESS) { // Block was written completely, but reached end of EEPROM now. No further data allowed (except for 0 byte "end block"). currentAddress.isValid = false; uartPutLine("OK STOP (end of EEPROM)"); } else { // Next block of data can be sent now. uartPutLine("OK CONTINUE"); } } } while (block_length > 0); // WRITE completed uartPutLine("OK END"); } void commandErase(char* arg) { if (arg == NULL) { uartPutLine("ERROR ERASE needs a start address"); return; } // Parse address(es) AddressRange range = parseAddressRange(arg); if (!range.isValid || range.to < range.from) { uartPutLine("ERROR invalid address format"); return; } uint32_t bytesErased = eepromEraseBlock(range); if (bytesErased == 0) { uartPutLine("ERROR 0 bytes erased"); } else { char outBuffer[16]; snprintf(outBuffer, 16, "%lu", bytesErased); uartPutString("OK erased "); uartPutString(outBuffer); uartPutLine(" bytes"); } } // TESTREAD command: for testing purposes, reads a few bytes and returns them in a human readable format. void commandTestRead() { eepromSetReadMode(); for (uint8_t i = 0x00; i < 0x20; i++) { uartPutString("TESTREAD 0x"); uartPutHexByte(i); uartPutString(": "); uint8_t byte = eepromReadByte(i); if (byte >= 32 && byte <= 126) { uartPutChar(byte); } else { uartPutChar('?'); } uartPutString(" (0x"); uartPutHexByte(byte); uartPutLine(")"); } } // TESTWRITE command: for testing purposes, writes a few bytes void commandTestWrite(char* arg) { char str[] = "Ohai world"; address_t addr = 0x00; char* writeStr = str; if (arg != NULL) { writeStr = arg; } eepromSetWriteMode(); // write input line instead of static string for (char* p = writeStr; *p != '\0'; p++) { eepromWriteByte(addr, *p); //_delay_ms(100); addr++; } // TODO necessary? _delay_ms(100); uartPutLine("TESTWRITE success"); }