Replace tabs with spaces
This commit is contained in:
parent
fccd19dbf4
commit
28be3c4e8b
|
|
@ -1,8 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* BitIO.h
|
* BitIO.h
|
||||||
* @author Andi Dittrich <http://andidittrich.de>
|
* @author Andi Dittrich <http://andidittrich.de>
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
* @license MIT Style X11 License
|
* @license MIT Style X11 License
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -15,29 +15,29 @@
|
||||||
// set bit
|
// set bit
|
||||||
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) __attribute__((always_inline));
|
||||||
static inline void BIT_SET(volatile uint8_t *target, uint8_t bit){
|
static inline void BIT_SET(volatile uint8_t *target, uint8_t bit){
|
||||||
*target |= (1<<bit);
|
*target |= (1<<bit);
|
||||||
};
|
};
|
||||||
|
|
||||||
// set clear
|
// set clear
|
||||||
static inline void BIT_CLEAR(volatile uint8_t *target, uint8_t bit) __attribute__((always_inline));
|
static inline void BIT_CLEAR(volatile uint8_t *target, uint8_t bit) __attribute__((always_inline));
|
||||||
static inline void BIT_CLEAR(volatile uint8_t *target, uint8_t bit){
|
static inline void BIT_CLEAR(volatile uint8_t *target, uint8_t bit){
|
||||||
*target &= ~(1<<bit);
|
*target &= ~(1<<bit);
|
||||||
};
|
};
|
||||||
|
|
||||||
// bit toogle
|
// bit toogle
|
||||||
static inline void BIT_TOGGLE(volatile uint8_t *target, uint8_t bit) __attribute__((always_inline));
|
static inline void BIT_TOGGLE(volatile uint8_t *target, uint8_t bit) __attribute__((always_inline));
|
||||||
static inline void BIT_TOGGLE(volatile uint8_t *target, uint8_t bit){
|
static inline void BIT_TOGGLE(volatile uint8_t *target, uint8_t bit){
|
||||||
*target ^= (1<<bit);
|
*target ^= (1<<bit);
|
||||||
};
|
};
|
||||||
|
|
||||||
// set bit by boolean
|
// set bit by boolean
|
||||||
static inline void BIT_BOOL_SET(volatile uint8_t *target, uint8_t bit, bool enable) __attribute__((always_inline));
|
static inline void BIT_BOOL_SET(volatile uint8_t *target, uint8_t bit, bool enable) __attribute__((always_inline));
|
||||||
static inline void BIT_BOOL_SET(volatile uint8_t *target, uint8_t bit, bool enable){
|
static inline void BIT_BOOL_SET(volatile uint8_t *target, uint8_t bit, bool enable){
|
||||||
if (enable){
|
if (enable){
|
||||||
BIT_SET(target, bit);
|
BIT_SET(target, bit);
|
||||||
}else{
|
}else{
|
||||||
BIT_CLEAR(target, bit);
|
BIT_CLEAR(target, bit);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* BITIO_H_ */
|
#endif /* BITIO_H_ */
|
||||||
|
|
|
||||||
|
|
@ -7,110 +7,110 @@
|
||||||
|
|
||||||
// Initialize EEPROM
|
// Initialize EEPROM
|
||||||
void eepromInit() {
|
void eepromInit() {
|
||||||
// Set initial value for control port (all disabled -- INVERTED VALUES, ~CE, ~OE, ~WE)
|
// Set initial value for control port (all disabled -- INVERTED VALUES, ~CE, ~OE, ~WE)
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
||||||
|
|
||||||
// Set data direction register for control port
|
// Set data direction register for control port
|
||||||
EEP_CTRL_DDR |= (1 << EEP_CTRL_BIT_CE)
|
EEP_CTRL_DDR |= (1 << EEP_CTRL_BIT_CE)
|
||||||
| (1 << EEP_CTRL_BIT_OE)
|
| (1 << EEP_CTRL_BIT_OE)
|
||||||
| (1 << EEP_CTRL_BIT_WE);
|
| (1 << EEP_CTRL_BIT_WE);
|
||||||
|
|
||||||
// Set initial value for address (0x0000)
|
// Set initial value for address (0x0000)
|
||||||
EEP_ADDR_LOW_PORT = 0x00;
|
EEP_ADDR_LOW_PORT = 0x00;
|
||||||
EEP_ADDR_HIGH_PORT = 0x00;
|
EEP_ADDR_HIGH_PORT = 0x00;
|
||||||
|
|
||||||
// Set data direction register for address ports
|
// Set data direction register for address ports
|
||||||
EEP_ADDR_LOW_DDR = 0xFF;
|
EEP_ADDR_LOW_DDR = 0xFF;
|
||||||
EEP_ADDR_HIGH_DDR = 0xFF;
|
EEP_ADDR_HIGH_DDR = 0xFF;
|
||||||
|
|
||||||
// Set data direction register and initial value for IO port (initialize in reading mode)
|
// Set data direction register and initial value for IO port (initialize in reading mode)
|
||||||
EEP_DATA_PORT = 0x00;
|
EEP_DATA_PORT = 0x00;
|
||||||
EEP_DATA_DDR = 0x00;
|
EEP_DATA_DDR = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable read mode (set data direction registers and enable output)
|
// Enable read mode (set data direction registers and enable output)
|
||||||
void eepromSetReadMode() {
|
void eepromSetReadMode() {
|
||||||
// Reset control bits (shouldn't be necessary, but let's be safe)
|
// Reset control bits (shouldn't be necessary, but let's be safe)
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
||||||
|
|
||||||
// Set data pins as input, reset PORT to disable pullups
|
// Set data pins as input, reset PORT to disable pullups
|
||||||
EEP_DATA_PORT = 0x00;
|
EEP_DATA_PORT = 0x00;
|
||||||
EEP_DATA_DDR = 0x00;
|
EEP_DATA_DDR = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable write mode (set data direction registers)
|
// Enable write mode (set data direction registers)
|
||||||
void eepromSetWriteMode() {
|
void eepromSetWriteMode() {
|
||||||
// Reset control bits (shouldn't be necessary, but let's be safe)
|
// Reset control bits (shouldn't be necessary, but let's be safe)
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
||||||
|
|
||||||
// Set data pins as output, reset data port
|
// Set data pins as output, reset data port
|
||||||
EEP_DATA_PORT = 0x00;
|
EEP_DATA_PORT = 0x00;
|
||||||
EEP_DATA_DDR = 0xFF;
|
EEP_DATA_DDR = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set address
|
// Set address
|
||||||
static inline void eepromSetAddress(address_t address) {
|
static inline void eepromSetAddress(address_t address) {
|
||||||
// Set low and high address bytes
|
// Set low and high address bytes
|
||||||
// (We actually only have 15 bit, the 16th will just be ignored)
|
// (We actually only have 15 bit, the 16th will just be ignored)
|
||||||
EEP_ADDR_LOW_PORT = address & 0xFF;
|
EEP_ADDR_LOW_PORT = address & 0xFF;
|
||||||
EEP_ADDR_HIGH_PORT = address >> 8;
|
EEP_ADDR_HIGH_PORT = address >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read byte (assumes we're in read mode)
|
// Read byte (assumes we're in read mode)
|
||||||
uint8_t eepromReadByte(address_t address) {
|
uint8_t eepromReadByte(address_t address) {
|
||||||
// Assume we're in read mode
|
// Assume we're in read mode
|
||||||
|
|
||||||
// Set address
|
// Set address
|
||||||
eepromSetAddress(address);
|
eepromSetAddress(address);
|
||||||
|
|
||||||
// Latch address
|
// Latch address
|
||||||
BIT_CLEAR(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
BIT_CLEAR(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
||||||
BIT_CLEAR(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
BIT_CLEAR(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
||||||
|
|
||||||
// 1 tick = 62.5 ns, EEPROM access time is 150 ns.
|
// 1 tick = 62.5 ns, EEPROM access time is 150 ns.
|
||||||
// 2 NOPs seem to be sufficient, but let's be sure.
|
// 2 NOPs seem to be sufficient, but let's be sure.
|
||||||
_NOP();
|
_NOP();
|
||||||
_NOP();
|
_NOP();
|
||||||
_NOP();
|
_NOP();
|
||||||
|
|
||||||
// Get data
|
// Get data
|
||||||
uint8_t byte = EEP_DATA_PIN;
|
uint8_t byte = EEP_DATA_PIN;
|
||||||
|
|
||||||
// Reset ~OE, ~CE
|
// Reset ~OE, ~CE
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_OE);
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
||||||
|
|
||||||
// Read and return data byte
|
// Read and return data byte
|
||||||
return byte;
|
return byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write byte (assumes we're in write mode)
|
// Write byte (assumes we're in write mode)
|
||||||
void eepromWriteByte(address_t address, uint8_t data) {
|
void eepromWriteByte(address_t address, uint8_t data) {
|
||||||
// Assume we're in write mode
|
// Assume we're in write mode
|
||||||
|
|
||||||
// Set address
|
// Set address
|
||||||
eepromSetAddress(address);
|
eepromSetAddress(address);
|
||||||
|
|
||||||
// Falling edge: latch address
|
// Falling edge: latch address
|
||||||
BIT_CLEAR(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
BIT_CLEAR(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
||||||
BIT_CLEAR(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
BIT_CLEAR(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
||||||
|
|
||||||
// Set data byte
|
// Set data byte
|
||||||
EEP_DATA_PORT = data;
|
EEP_DATA_PORT = data;
|
||||||
|
|
||||||
// Data setup time (50ns)
|
// Data setup time (50ns)
|
||||||
_NOP();
|
_NOP();
|
||||||
|
|
||||||
// Rising edge: latch data, start write cycle
|
// Rising edge: latch data, start write cycle
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_WE);
|
||||||
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
BIT_SET(&EEP_CTRL_PORT, EEP_CTRL_BIT_CE);
|
||||||
|
|
||||||
// Write pulse width high (50ns)
|
// Write pulse width high (50ns)
|
||||||
_NOP();
|
_NOP();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,18 +6,18 @@
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
// Init components (UART, EEPROM, ...)
|
// Init components (UART, EEPROM, ...)
|
||||||
uartInit();
|
uartInit();
|
||||||
eepromInit();
|
eepromInit();
|
||||||
|
|
||||||
// Initial pause (EEPROM needs 5ms startup time)
|
// Initial pause (EEPROM needs 5ms startup time)
|
||||||
_delay_ms(100);
|
_delay_ms(100);
|
||||||
|
|
||||||
// Write initial message via UART
|
// Write initial message via UART
|
||||||
uartPutString("INFO -- EEPROM programmer by binaryDiv\r\n");
|
uartPutString("INFO -- EEPROM programmer by binaryDiv\r\n");
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
// Run main loop endlessly
|
// Run main loop endlessly
|
||||||
protocolMainLoop();
|
protocolMainLoop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,131 +11,131 @@
|
||||||
// Splits a command "CMD ARGS" to two strings "CMD" and "ARGS". Returns pointer
|
// Splits a command "CMD ARGS" to two strings "CMD" and "ARGS". Returns pointer
|
||||||
// to "ARGS" or NULL if no arguments were found. Changes the input string!
|
// to "ARGS" or NULL if no arguments were found. Changes the input string!
|
||||||
char* tokenizeCommand(char* cmd) {
|
char* tokenizeCommand(char* cmd) {
|
||||||
if (cmd == NULL) {
|
if (cmd == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for a space character
|
// Search for a space character
|
||||||
for (char* p = cmd; *p != '\0'; p++) {
|
for (char* p = cmd; *p != '\0'; p++) {
|
||||||
if (*p == ' ') {
|
if (*p == ' ') {
|
||||||
// Split strings by replacing the space by \0, then return pointer
|
// Split strings by replacing the space by \0, then return pointer
|
||||||
// to command arguments
|
// to command arguments
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No space character found: command has no arguments, return NULL
|
// No space character found: command has no arguments, return NULL
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reads, parses and executes next command
|
// Reads, parses and executes next command
|
||||||
void parseNextCommand() {
|
void parseNextCommand() {
|
||||||
const int bufferLength = 80;
|
const int bufferLength = 80;
|
||||||
char buffer[bufferLength];
|
char buffer[bufferLength];
|
||||||
|
|
||||||
// Read next command
|
// Read next command
|
||||||
int readChars = uartGetLine(buffer, bufferLength);
|
int readChars = uartGetLine(buffer, bufferLength);
|
||||||
|
|
||||||
// Check if line is non-empty and has been read completely
|
// Check if line is non-empty and has been read completely
|
||||||
if (readChars == 0) {
|
if (readChars == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (readChars >= bufferLength-1) {
|
else if (readChars >= bufferLength-1) {
|
||||||
// Reading was aborted after bufferLength-1 characters to prevent
|
// Reading was aborted after bufferLength-1 characters to prevent
|
||||||
// buffer overflow.
|
// buffer overflow.
|
||||||
// TODO Actually this isn't quite correct: if exactly bufferLen-1
|
// TODO Actually this isn't quite correct: if exactly bufferLen-1
|
||||||
// characters have been read including the \n, this could be
|
// characters have been read including the \n, this could be
|
||||||
// true as well... test this?
|
// true as well... test this?
|
||||||
uartPutString("ERROR buffer overflow while reading line\r\n");
|
uartPutString("ERROR buffer overflow while reading line\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tokenize command
|
// Tokenize command
|
||||||
char* cmd = buffer;
|
char* cmd = buffer;
|
||||||
char* args = tokenizeCommand(cmd);
|
char* args = tokenizeCommand(cmd);
|
||||||
|
|
||||||
// Parse command
|
// Parse command
|
||||||
if (strcmp(cmd, "HELLO") == 0) {
|
if (strcmp(cmd, "HELLO") == 0) {
|
||||||
// HELLO command: initializes connection
|
// HELLO command: initializes connection
|
||||||
uartPutString("OHAI\r\n");
|
uartPutString("OHAI\r\n");
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "READ") == 0) {
|
else if (strcmp(cmd, "READ") == 0) {
|
||||||
// READ command: takes a hex address or address range as argument,
|
// READ command: takes a hex address or address range as argument,
|
||||||
// reads data and returns them in hexadecimal ASCII format.
|
// reads data and returns them in hexadecimal ASCII format.
|
||||||
|
|
||||||
// Check if arguments exist
|
// Check if arguments exist
|
||||||
if (args == NULL) {
|
if (args == NULL) {
|
||||||
uartPutString("ERROR READ needs an address\r\n");
|
uartPutString("ERROR READ needs an address\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse address(es)
|
// Parse address(es)
|
||||||
// TODO
|
// TODO
|
||||||
uartPutString(args);
|
uartPutString(args);
|
||||||
|
|
||||||
// Read...
|
// Read...
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "TESTREAD") == 0) {
|
else if (strcmp(cmd, "TESTREAD") == 0) {
|
||||||
// TESTREAD command: for testing purposes, reads a few bytes and
|
// TESTREAD command: for testing purposes, reads a few bytes and
|
||||||
// returns them in a human readable format.
|
// returns them in a human readable format.
|
||||||
|
|
||||||
uint8_t byte;
|
uint8_t byte;
|
||||||
char outBuffer[20];
|
char outBuffer[20];
|
||||||
|
|
||||||
eepromSetReadMode();
|
eepromSetReadMode();
|
||||||
|
|
||||||
for (int i = 0x00; i < 0x20; i++) {
|
for (int i = 0x00; i < 0x20; i++) {
|
||||||
itoa(i, outBuffer, 16);
|
itoa(i, outBuffer, 16);
|
||||||
uartPutString("TESTREAD 0x");
|
uartPutString("TESTREAD 0x");
|
||||||
uartPutString(outBuffer);
|
uartPutString(outBuffer);
|
||||||
uartPutString(": ");
|
uartPutString(": ");
|
||||||
|
|
||||||
byte = eepromReadByte(i);
|
byte = eepromReadByte(i);
|
||||||
itoa(byte, outBuffer, 16);
|
itoa(byte, outBuffer, 16);
|
||||||
|
|
||||||
uartPutChar(byte);
|
uartPutChar(byte);
|
||||||
uartPutString(" (0x");
|
uartPutString(" (0x");
|
||||||
uartPutString(outBuffer);
|
uartPutString(outBuffer);
|
||||||
uartPutString(")\r\n");
|
uartPutString(")\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(cmd, "TESTWRITE") == 0) {
|
else if (strcmp(cmd, "TESTWRITE") == 0) {
|
||||||
// TESTWRITE command: for testing purposes, writes a few bytes
|
// TESTWRITE command: for testing purposes, writes a few bytes
|
||||||
|
|
||||||
char str[] = "Ohai world";
|
char str[] = "Ohai world";
|
||||||
address_t addr = 0x00;
|
address_t addr = 0x00;
|
||||||
|
|
||||||
char* writeStr = str;
|
char* writeStr = str;
|
||||||
if (args != NULL) {
|
if (args != NULL) {
|
||||||
writeStr = args;
|
writeStr = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
eepromSetWriteMode();
|
eepromSetWriteMode();
|
||||||
|
|
||||||
// write input line instead of static string
|
// write input line instead of static string
|
||||||
for (char* p = writeStr; *p != '\0'; p++) {
|
for (char* p = writeStr; *p != '\0'; p++) {
|
||||||
eepromWriteByte(addr, *p);
|
eepromWriteByte(addr, *p);
|
||||||
//_delay_ms(100);
|
//_delay_ms(100);
|
||||||
addr++;
|
addr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO necessary?
|
// TODO necessary?
|
||||||
_delay_ms(100);
|
_delay_ms(100);
|
||||||
|
|
||||||
uartPutString("TESTWRITE success\r\n");
|
uartPutString("TESTWRITE success\r\n");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// unknown command: return error message
|
// unknown command: return error message
|
||||||
uartPutString("ERROR invalid command\r\n");
|
uartPutString("ERROR invalid command\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runs main loop to parse commands
|
// Runs main loop to parse commands
|
||||||
void protocolMainLoop() {
|
void protocolMainLoop() {
|
||||||
while(1) {
|
while(1) {
|
||||||
// Parse next command
|
// Parse next command
|
||||||
parseNextCommand();
|
parseNextCommand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,88 +6,88 @@
|
||||||
|
|
||||||
// Initialize UART
|
// Initialize UART
|
||||||
void uartInit() {
|
void uartInit() {
|
||||||
// Set Baud register
|
// Set Baud register
|
||||||
UBRRH = UBRRH_VALUE;
|
UBRRH = UBRRH_VALUE;
|
||||||
UBRRL = UBRRL_VALUE;
|
UBRRL = UBRRL_VALUE;
|
||||||
|
|
||||||
// Reset status register
|
// Reset status register
|
||||||
UCSRA = 0x00;
|
UCSRA = 0x00;
|
||||||
|
|
||||||
#if USE_2X
|
#if USE_2X
|
||||||
// U2X mode necessary
|
// U2X mode necessary
|
||||||
UCSRA |= (1 << U2X);
|
UCSRA |= (1 << U2X);
|
||||||
#else
|
#else
|
||||||
// U2X mode not necessary
|
// U2X mode not necessary
|
||||||
UCSRA &= ~(1 << U2X);
|
UCSRA &= ~(1 << U2X);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable transmitter and receiver
|
// Enable transmitter and receiver
|
||||||
UCSRB |= (1 << TXEN) | (1 << RXEN);
|
UCSRB |= (1 << TXEN) | (1 << RXEN);
|
||||||
|
|
||||||
// Set frame format (8 bit)
|
// Set frame format (8 bit)
|
||||||
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
|
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit a single character
|
// Transmit a single character
|
||||||
void uartPutChar(unsigned char data) {
|
void uartPutChar(unsigned char data) {
|
||||||
// Block until controller is ready to send
|
// Block until controller is ready to send
|
||||||
while (!(UCSRA & (1 << UDRE))) {
|
while (!(UCSRA & (1 << UDRE))) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write character to UART data register
|
// Write character to UART data register
|
||||||
UDR = data;
|
UDR = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit a string
|
// Transmit a string
|
||||||
void uartPutString(char* data) {
|
void uartPutString(char* data) {
|
||||||
// Write characters until \0 is reached
|
// Write characters until \0 is reached
|
||||||
while (*data) {
|
while (*data) {
|
||||||
uartPutChar(*data++);
|
uartPutChar(*data++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive a single character (blocking)
|
// Receive a single character (blocking)
|
||||||
unsigned char uartGetChar() {
|
unsigned char uartGetChar() {
|
||||||
// Block until a character has been received
|
// Block until a character has been received
|
||||||
while (!(UCSRA & (1 << RXC))) {
|
while (!(UCSRA & (1 << RXC))) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get character and return
|
// Get character and return
|
||||||
return UDR;
|
return UDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive a string until \n (blocking)
|
// Receive a string until \n (blocking)
|
||||||
uint8_t uartGetLine(char* buffer, uint8_t maxLength) {
|
uint8_t uartGetLine(char* buffer, uint8_t maxLength) {
|
||||||
uint8_t readChars = 0;
|
uint8_t readChars = 0;
|
||||||
unsigned char nextChar;
|
unsigned char nextChar;
|
||||||
|
|
||||||
// Read a maximum of maxLength-1 characters (-1 because we need one char for '\0')
|
// Read a maximum of maxLength-1 characters (-1 because we need one char for '\0')
|
||||||
while (readChars < maxLength - 1) {
|
while (readChars < maxLength - 1) {
|
||||||
// Get next character
|
// Get next character
|
||||||
nextChar = uartGetChar();
|
nextChar = uartGetChar();
|
||||||
|
|
||||||
// Skip trailing \n and \r
|
// Skip trailing \n and \r
|
||||||
if (nextChar == '\n' || nextChar == '\r') {
|
if (nextChar == '\n' || nextChar == '\r') {
|
||||||
if (readChars == 0) {
|
if (readChars == 0) {
|
||||||
// Skip trailing \n and \r
|
// Skip trailing \n and \r
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// End line (do not append the \r or \n to the buffer)
|
// End line (do not append the \r or \n to the buffer)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write character to buffer
|
// Write character to buffer
|
||||||
*buffer++ = nextChar;
|
*buffer++ = nextChar;
|
||||||
|
|
||||||
// Increment counter
|
// Increment counter
|
||||||
readChars++;
|
readChars++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a terminating '\0' byte
|
// Write a terminating '\0' byte
|
||||||
*buffer++ = '\0';
|
*buffer++ = '\0';
|
||||||
|
|
||||||
// Return number of read bytes (excluding the \0)
|
// Return number of read bytes (excluding the \0)
|
||||||
return readChars;
|
return readChars;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue