diff --git a/firmware/Makefile b/firmware/Makefile index 6ee8916..1020d16 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -7,7 +7,7 @@ OBJCOPY = avr-objcopy AVRDUDE ?= avrdude # Compiler and linker flags -CFLAGS = -Wall -pedantic -std=c11 -Os +CFLAGS = -Wall -std=c11 -Os LDFLAGS = # Target platform and programmer diff --git a/firmware/src/BitIO.h b/firmware/src/BitIO.h index 4c5630c..13f6605 100644 --- a/firmware/src/BitIO.h +++ b/firmware/src/BitIO.h @@ -16,19 +16,19 @@ static inline void BIT_SET(volatile uint8_t *target, uint8_t bit) __attribute__((always_inline)); static inline void BIT_SET(volatile uint8_t *target, uint8_t bit){ *target |= (1<'); + uartPrintf("<%d>", buffer.bytes); for (int i = 0; i < buffer.bytes; i++) { - uartPutChar(' '); - uartPutHexByte(buffer.data[i]); + uartPrintf(" %02X", buffer.data[i]); } uartPutLine(NULL); } @@ -141,96 +136,38 @@ void commandRead(char* arg) { void commandWrite(char* arg) { if (arg == NULL) { - uartPutLine("ERROR WRITE needs a start address"); + uartPutLine("ERR WRITE needs a start address"); return; } // Parse address - Address startAddress = parseSingleAddress(arg); - if (!startAddress.isValid) { - uartPutLine("ERROR invalid address format"); + AddressRange range = parseSingleAddress(arg); + if (!range.isValid) { + uartPutLine("ERR invalid address format"); return; } // Only binary mode if (!binary_mode) { - uartPutLine("ERROR WRITE in ASCII mode is not implemented"); + uartPutLine("ERR WRITE in ASCII mode is not implemented"); 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"); - - 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 > buffer.maxSize) { - uartPutString("ERROR maximal block size is: "); - uartPutInteger(buffer.maxSize); - uartPutLine(NULL); - 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); - - // TODO wait necessary? - //_delay_ms(100); - - 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"); + // TODO read data from input and write to EEPROM + uartPutLine("ERR not implemented"); } void commandErase() { - uartPutLine("ERROR not implemented"); + // TODO + uartPutLine("ERR not implemented"); } // 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(": "); + for (int i = 0x00; i < 0x20; i++) { + uartPrintf("TESTREAD 0x%02X: ", i); uint8_t byte = eepromReadByte(i); @@ -240,9 +177,7 @@ void commandTestRead() { uartPutChar('?'); } - uartPutString(" (0x"); - uartPutHexByte(byte); - uartPutLine(")"); + uartPrintf(" (0x%02X)\n"); } } diff --git a/firmware/src/common.h b/firmware/src/common.h index d6cb0e7..ba6e843 100644 --- a/firmware/src/common.h +++ b/firmware/src/common.h @@ -14,12 +14,6 @@ typedef uint16_t address_t; // Define highest valid address for the EEPROM #define HIGHEST_VALID_ADDRESS 0x7fff -// Type definition for a single address (nullable) -typedef struct { - bool isValid; - address_t value; -} Address; - // Type definition for address ranges (from-to) typedef struct { bool isValid; diff --git a/firmware/src/eeprom.c b/firmware/src/eeprom.c index abe6e6b..7b7e00d 100644 --- a/firmware/src/eeprom.c +++ b/firmware/src/eeprom.c @@ -115,16 +115,12 @@ void eepromWriteByte(address_t address, uint8_t data) { } // Read multiple bytes from EEPROM into a buffer -Address eepromReadBlock(AddressRange addressRange, DataBuffer* buffer) { +address_t eepromReadBlock(AddressRange addressRange, DataBuffer* buffer) { // Set read mode eepromSetReadMode(); buffer->bytes = 0; - if (!addressRange.isValid) { - return (Address) {false, 0}; - } - address_t currentAddress = addressRange.from; address_t highestAddress = addressRange.to; @@ -134,41 +130,20 @@ Address eepromReadBlock(AddressRange addressRange, DataBuffer* buffer) { while (currentAddress <= highestAddress && buffer->bytes < buffer->maxSize) { buffer->data[buffer->bytes++] = eepromReadByte(currentAddress++); - - // Handle integer overflow - if (currentAddress == 0) { - return (Address) {false, 0}; - } } - return (Address) {true, currentAddress}; + return currentAddress; } -// Write multiple bytes from a buffer to EEPROM -Address eepromWriteBlock(Address startAddress, DataBuffer buffer) { - // Set write mode - eepromSetWriteMode(); +// // Write multiple bytes from a buffer to EEPROM +// address_t eepromWriteBlock(address_t currentAddress, DataBuffer buffer) { +// // Set write mode +// eepromSetWriteMode(); - if (!startAddress.isValid) { - return (Address) {false, 0}; - } +// for (uint8_t i = 0; currentAddress <= HIGHEST_VALID_ADDRESS && i < buffer.bytes; i++) { +// eepromWriteByte(currentAddress++, buffer.data[i]); +// // TODO address overflow +// } - address_t currentAddress = startAddress.value; - uint8_t i; - - for (i = 0; i < buffer.bytes && currentAddress <= HIGHEST_VALID_ADDRESS; i++) { - eepromWriteByte(currentAddress++, buffer.data[i]); - - // Handle integer overflow - if (currentAddress == 0) { - break; - } - } - - if (i < buffer.bytes) { - // There are unwritten bytes left -> must be an address overflow - return (Address) {false, 0}; - } - - return (Address) {true, currentAddress}; -} +// return currentAddress; +// } diff --git a/firmware/src/eeprom.h b/firmware/src/eeprom.h index 0dfdffd..c12bbd2 100644 --- a/firmware/src/eeprom.h +++ b/firmware/src/eeprom.h @@ -41,9 +41,9 @@ uint8_t eepromReadByte(address_t address); void eepromWriteByte(address_t address, uint8_t data); // Read multiple bytes from EEPROM into a buffer -Address eepromReadBlock(AddressRange addressRange, DataBuffer* buffer); +address_t eepromReadBlock(AddressRange addressRange, DataBuffer* buffer); -// Write multiple bytes from a buffer to EEPROM -Address eepromWriteBlock(Address startAddress, DataBuffer buffer); +// // Write multiple bytes from a buffer to EEPROM +// address_t eepromWriteBlock(address_t addressRange, DataBuffer buffer); #endif /* EEPROM_H_ */ diff --git a/firmware/src/parsing.c b/firmware/src/parsing.c index 8316251..7df21e7 100644 --- a/firmware/src/parsing.c +++ b/firmware/src/parsing.c @@ -8,9 +8,6 @@ #include #include -// Command parsing -// --------------- - // Read and parse command line and dispatch command void parseNextCommand() { const int bufferLength = 80; @@ -31,7 +28,7 @@ CommandLine readNextCommand(char* buffer, uint8_t bufferLength) { if (readChars >= bufferLength - 1) { // Reading was aborted after bufferLength-1 characters to prevent buffer overflow. - uartPutLine("ERROR buffer overflow, discarding line"); + uartPutLine("ERR buffer overflow, discarding line"); // Discard everything until we read an actual end of line for (unsigned char c = 0; c != '\n' && c != '\r'; c = uartGetChar()); @@ -69,11 +66,8 @@ CommandLine tokenizeCommand(char* cmd) { } // Address parsing -// --------------- - -// Validates a single 2-byte hexadecimal address string "XXXX". -bool validateAddressString(char* addressStr) { - if (addressStr == NULL || strlen(addressStr) != 4) { +bool parseSingleAddressTo(char* addressStr, address_t* address) { + if (addressStr == NULL || strlen(addressStr) != 4 || address == NULL) { return false; } @@ -83,19 +77,18 @@ bool validateAddressString(char* addressStr) { } } + *address = strtol(addressStr, NULL, 16); return true; } -// Parses a single 2-byte hexadecimal address string "XXXX" to an actual address. -Address parseSingleAddress(char* addressStr) { - Address address = {false, 0}; - - if (validateAddressString(addressStr)) { - address.isValid = true; - address.value = strtol(addressStr, NULL, 16); +// Parses a single 2-byte hexadecimal address string "XXXX:YYYY" to an actual address. +AddressRange parseSingleAddress(char* addressStr) { + AddressRange range = {true, 0, 0}; + if (!parseSingleAddressTo(addressStr, &range.from)) { + return (AddressRange) {false, 0, 0}; } - - return address; + range.to = range.from; + return range; } // Parses a hexadecimal address range string "XXXX:YYYY" to actual addresses. @@ -105,29 +98,25 @@ AddressRange parseAddressRange(char* addressStr) { return (AddressRange) {false, 0, 0}; } - int length = strlen(addressStr); - - if (length == 4) { - Address address = parseSingleAddress(addressStr); - - return (AddressRange) { - .isValid = address.isValid, - .from = address.value, - .to = address.value - }; - } - else if (length == 9 && addressStr[4] == ':') { - addressStr[4] = '\0'; - Address fromAddress = parseSingleAddress(addressStr); - Address toAddress = parseSingleAddress(addressStr + 5); - - return (AddressRange) { - .isValid = fromAddress.isValid && toAddress.isValid, - .from = fromAddress.value, - .to = toAddress.value - }; - } - else { + int len = strlen(addressStr); + if (len != 4 && len != 9) { return (AddressRange) {false, 0, 0}; } + + if (len == 9) { + if (addressStr[4] != ':') { + return (AddressRange) {false, 0, 0}; + } + addressStr[4] = '\0'; + } + + AddressRange range = parseSingleAddress(addressStr); + + if (range.isValid && len == 9) { + if (!parseSingleAddressTo(addressStr + 5, &range.to)) { + return (AddressRange) {false, 0, 0}; + } + } + + return range; } diff --git a/firmware/src/parsing.h b/firmware/src/parsing.h index 13cbe6d..fe15c27 100644 --- a/firmware/src/parsing.h +++ b/firmware/src/parsing.h @@ -14,8 +14,8 @@ void parseNextCommand(); CommandLine readNextCommand(char* buffer, uint8_t bufferLength); CommandLine tokenizeCommand(char* cmd); -bool validateAddressString(char* addressStr); -Address parseSingleAddress(char* addressStr); +bool parseSingleAddressTo(char* addressStr, address_t* address); +AddressRange parseSingleAddress(char* addressStr); AddressRange parseAddressRange(char* addressStr); #endif /* PARSING_H_ */ diff --git a/firmware/src/uart.c b/firmware/src/uart.c index e2dc588..1d6fcba 100644 --- a/firmware/src/uart.c +++ b/firmware/src/uart.c @@ -56,18 +56,17 @@ 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); -} +// Transmit a sprintf formatted string (maximum buffer: 256 bytes!) +void uartPrintf(const char* format, ...) { + char outBuffer[256]; -// Convert a byte to hexadecimal ASCII and transmit -void uartPutHexByte(uint8_t byte) { - char outBuffer[8]; - snprintf(outBuffer, 8, "%02hhX", byte); + va_list args; + va_start(args, format); + + vsprintf(outBuffer, format, args); uartPutString(outBuffer); + + va_end(args); } // Receive a single character (blocking) diff --git a/firmware/src/uart.h b/firmware/src/uart.h index 9065993..7421af4 100644 --- a/firmware/src/uart.h +++ b/firmware/src/uart.h @@ -16,11 +16,8 @@ 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); +// Transmit a sprintf formatted string (maximum buffer: 256 bytes!) +void uartPrintf(const char* format, ...); // Read a single character (blocking) unsigned char uartGetChar();