diff --git a/firmware/src/commands.c b/firmware/src/commands.c index ed8620a..5dcdc3c 100644 --- a/firmware/src/commands.c +++ b/firmware/src/commands.c @@ -6,7 +6,6 @@ #include #include -#include #include #include @@ -37,6 +36,14 @@ void executeCommand(CommandLine cmdLine) { // 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"); @@ -72,6 +79,11 @@ void commandHelp() { 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"); } @@ -90,12 +102,14 @@ void commandRead(char* arg) { uartPutLine("OK"); - // Create data buffer - DataBuffer buffer; + uint8_t byteBuffer[DATA_BLOCK_SIZE]; + DataBuffer buffer = { + .data = byteBuffer, + .maxSize = DATA_BLOCK_SIZE, + .bytes = 0 + }; do { - buffer.bytes = 0; - // Read a single block with up to DATA_BLOCK_SIZE bytes Address nextAddress = eepromReadBlock(range, &buffer); range.isValid = nextAddress.isValid; @@ -106,16 +120,16 @@ void commandRead(char* arg) { // 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++) { + for (int i = 0; i < buffer.bytes; i++) { uartPutChar(buffer.data[i]); } } else { // Fancy ASCII output - uartPutString("<0x"); - uartPutHexByte(buffer.bytes); + uartPutChar('<'); + uartPutInteger(buffer.bytes); uartPutChar('>'); - for (uint8_t i = 0; i < buffer.bytes; i++) { + for (int i = 0; i < buffer.bytes; i++) { uartPutChar(' '); uartPutHexByte(buffer.data[i]); } @@ -144,12 +158,17 @@ void commandWrite(char* arg) { return; } + // Create data buffer + uint8_t byteBuffer[DATA_BLOCK_SIZE]; + DataBuffer buffer = { + .data = byteBuffer, + .maxSize = DATA_BLOCK_SIZE, + .bytes = 0 + }; + // "OK" indicates that data can be sent now. uartPutLine("OK START"); - // Create data buffer - DataBuffer buffer; - Address currentAddress = startAddress; uint8_t block_length = 0; @@ -160,8 +179,10 @@ void commandWrite(char* arg) { // Read and check block length block_length = uartGetChar(); - if (block_length > DATA_BLOCK_SIZE) { - uartPutLine("ERROR maximal block size is: " STR(DATA_BLOCK_SIZE)); + if (block_length > buffer.maxSize) { + uartPutString("ERROR maximal block size is: "); + uartPutInteger(buffer.maxSize); + uartPutLine(NULL); return; } @@ -174,6 +195,9 @@ void commandWrite(char* arg) { if (buffer.bytes > 0) { currentAddress = eepromWriteBlock(currentAddress, buffer); + // TODO wait necessary? + //_delay_ms(100); + if (!currentAddress.isValid) { uartPutLine("ERROR reached end of EEPROM while writing block"); return; @@ -195,28 +219,54 @@ void commandWrite(char* arg) { uartPutLine("OK END"); } -void commandErase(char* arg) { - if (arg == NULL) { - uartPutLine("ERROR ERASE needs a start address"); - return; - } +void commandErase() { + uartPutLine("ERROR not implemented"); +} - // Parse address(es) - AddressRange range = parseAddressRange(arg); - if (!range.isValid || range.to < range.from) { - uartPutLine("ERROR invalid address format"); - return; - } +// TESTREAD command: for testing purposes, reads a few bytes and returns them in a human readable format. +void commandTestRead() { + eepromSetReadMode(); - uint32_t bytesErased = eepromEraseBlock(range); + for (uint8_t i = 0x00; i < 0x20; i++) { + uartPutString("TESTREAD 0x"); + uartPutHexByte(i); + uartPutString(": "); - if (bytesErased == 0) { - uartPutLine("ERROR 0 bytes erased"); - } else { - char outBuffer[16]; - snprintf(outBuffer, 16, "%lu", bytesErased); - uartPutString("OK erased "); - uartPutString(outBuffer); - uartPutLine(" bytes"); + 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"); +} diff --git a/firmware/src/commands.h b/firmware/src/commands.h index 1dd4ecf..f31a471 100644 --- a/firmware/src/commands.h +++ b/firmware/src/commands.h @@ -12,4 +12,8 @@ void commandRead(char* arg); void commandWrite(char* arg); void commandErase(); +// TODO commands only for testing +void commandTestRead(); +void commandTestWrite(char* arg); + #endif /* COMMANDS_H_ */ diff --git a/firmware/src/common.h b/firmware/src/common.h index 479a8af..d6cb0e7 100644 --- a/firmware/src/common.h +++ b/firmware/src/common.h @@ -8,10 +8,6 @@ // Define macro for NOP instruction #define _NOP() __asm__ __volatile__ ("nop"); -// Define macro to convert a preprocessor constant to a string literal -#define STR_(x) #x -#define STR(x) STR_(x) - // Define type for EEPROM addresses typedef uint16_t address_t; @@ -32,11 +28,12 @@ typedef struct { } AddressRange; // Define type for a block of data (bytes) -#define DATA_BLOCK_SIZE 64 - typedef struct { - uint8_t data[DATA_BLOCK_SIZE]; + uint8_t* data; + uint8_t maxSize; uint8_t bytes; } DataBuffer; +#define DATA_BLOCK_SIZE 64 + #endif /* COMMON_H_ */ diff --git a/firmware/src/eeprom.c b/firmware/src/eeprom.c index 9eb76ca..abe6e6b 100644 --- a/firmware/src/eeprom.c +++ b/firmware/src/eeprom.c @@ -132,7 +132,7 @@ Address eepromReadBlock(AddressRange addressRange, DataBuffer* buffer) { highestAddress = HIGHEST_VALID_ADDRESS; } - while (currentAddress <= highestAddress && buffer->bytes < DATA_BLOCK_SIZE) { + while (currentAddress <= highestAddress && buffer->bytes < buffer->maxSize) { buffer->data[buffer->bytes++] = eepromReadByte(currentAddress++); // Handle integer overflow @@ -172,34 +172,3 @@ Address eepromWriteBlock(Address startAddress, DataBuffer buffer) { return (Address) {true, currentAddress}; } - -// Erase block of data on the EEPROM -uint32_t eepromEraseBlock(AddressRange addressRange) { - // Set write mode - eepromSetWriteMode(); - - if (!addressRange.isValid) { - return 0; - } - - address_t currentAddress = addressRange.from; - address_t highestAddress = addressRange.to; - - if (highestAddress > HIGHEST_VALID_ADDRESS) { - highestAddress = HIGHEST_VALID_ADDRESS; - } - - uint32_t bytesErased = 0; - - while (currentAddress <= highestAddress) { - eepromWriteByte(currentAddress++, 0x00); - bytesErased++; - - // Handle integer overflow - if (currentAddress == 0) { - break; - } - } - - return bytesErased; -} diff --git a/firmware/src/eeprom.h b/firmware/src/eeprom.h index 84d9a42..0dfdffd 100644 --- a/firmware/src/eeprom.h +++ b/firmware/src/eeprom.h @@ -5,6 +5,10 @@ #include "common.h" #include +// Define address length +// TODO 15 or 16? +#define ADDRESS_LENGTH 15 + // Macros for IO pins #define EEP_ADDR_LOW_PORT PORTC #define EEP_ADDR_LOW_DDR DDRC @@ -42,7 +46,4 @@ Address eepromReadBlock(AddressRange addressRange, DataBuffer* buffer); // Write multiple bytes from a buffer to EEPROM Address eepromWriteBlock(Address startAddress, DataBuffer buffer); -// Erase block of data on the EEPROM -uint32_t eepromEraseBlock(AddressRange addressRange); - #endif /* EEPROM_H_ */ diff --git a/firmware/src/parsing.c b/firmware/src/parsing.c index c3b6f79..8316251 100644 --- a/firmware/src/parsing.c +++ b/firmware/src/parsing.c @@ -13,7 +13,7 @@ // Read and parse command line and dispatch command void parseNextCommand() { - const int bufferLength = 40; + const int bufferLength = 80; char buffer[bufferLength]; // Read next command diff --git a/firmware/src/uart.c b/firmware/src/uart.c index 5e84c97..e2dc588 100644 --- a/firmware/src/uart.c +++ b/firmware/src/uart.c @@ -4,15 +4,8 @@ #include #include #include -#include -#include #include -// Hexadecimal digit lookup table -static const char hexDigitLookupTable[] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' -}; - // Initialize UART void uartInit() { // Set Baud register @@ -63,12 +56,18 @@ void uartPutLine(char* data) { uartPutChar('\n'); } +// Convert an integer to decimal ASCII and transmit +void uartPutInteger(int value) { + char outBuffer[32]; + snprintf(outBuffer, 32, "%d", value); + uartPutString(outBuffer); +} + // Convert a byte to hexadecimal ASCII and transmit void uartPutHexByte(uint8_t byte) { - // First hex digit: most significant 4 bits - uartPutChar(hexDigitLookupTable[(byte >> 4) & 0x0f]); - // Second hex digit: least significant 4 bits - uartPutChar(hexDigitLookupTable[byte & 0x0f]); + char outBuffer[8]; + snprintf(outBuffer, 8, "%02hhX", byte); + uartPutString(outBuffer); } // Receive a single character (blocking) diff --git a/firmware/src/uart.h b/firmware/src/uart.h index d5be266..9065993 100644 --- a/firmware/src/uart.h +++ b/firmware/src/uart.h @@ -16,6 +16,9 @@ void uartPutString(char* data); // Transmit a string followed by a line break void uartPutLine(char* data); +// Convert an integer to decimal ASCII and transmit +void uartPutInteger(int value); + // Convert a byte to hexadecimal ASCII and transmit void uartPutHexByte(uint8_t byte);