diff --git a/lambda-test/Makefile b/lambda-test/Makefile index b6451a1..7e0e6c8 100644 --- a/lambda-test/Makefile +++ b/lambda-test/Makefile @@ -15,12 +15,13 @@ ## If you've split your program into multiple .c / .h files, ## include the additional source (in same directory) here LOCAL_SOURCE = avrjunit.c adc-test.c alert-test.c command-test.c \ -display-test.c integers-test.c interrupts-test.c sensors-test.c strings-test.c +display-test.c integers-test.c interrupts-test.c sensors-test.c strings-test.c \ +usart-test.c ## Here you can link to one more directory (and multiple .c files) EXTRA_SOURCE_DIR = ../lambda/ -EXTRA_SOURCE_FILES = USART.c interrupts.c adc.c sensors.c integers.c \ -lcdroutines.c display.c alert.c command.c strings.c +EXTRA_SOURCE_FILES = interrupts.c adc.c sensors.c integers.c \ +lcdroutines.c display.c alert.c command.c strings.c usart.c ##########------------------------------------------------------########## ########## Programmer Defaults ########## diff --git a/lambda-test/avrjunit.c b/lambda-test/avrjunit.c index ce17e83..6215c49 100644 --- a/lambda-test/avrjunit.c +++ b/lambda-test/avrjunit.c @@ -11,8 +11,8 @@ #include #include -#include "USART.h" #include "avrjunit.h" +#include "usart.h" void beginSuite(char* const suite) { printString("\n"); @@ -25,8 +25,8 @@ printString("\n"); // send EOT - printString("\n"); - transmitByte(4); + char eot[] = {0x04, '\0'}; + printString(eot); } void runClass(TestClass class) { @@ -34,7 +34,7 @@ char cbuf[24]; char nbuf[64]; char tcbuf[128]; - // TODO use strncat (macro?) + // TODO use strncat_P (macro?) strcpy_P(cbuf, (PGM_P)pgm_read_word(&(class.tests[i].class))); strcpy_P(nbuf, (PGM_P)pgm_read_word(&(class.tests[i].name))); snprintf(tcbuf, sizeof(tcbuf), diff --git a/lambda-test/lambda-test.c b/lambda-test/lambda-test.c index 18272d8..00e08cd 100644 --- a/lambda-test/lambda-test.c +++ b/lambda-test/lambda-test.c @@ -8,17 +8,17 @@ * * DISCLAIMER: I'm new to C. * - * ATTRIBUTION: This project includes the module USART and the Makefile from - * the code accompanying the book Make: AVR Programming by Elliot Williams, - * a great book and a pleasant read, that helped me tremendously to get - * started with AVR programming. + * ATTRIBUTION: This project includes the the Makefile from the code + * accompanying the book Make: AVR Programming by Elliot Williams, a great book + * and a pleasant read that helped me tremendously to get started with AVR + * programming. * ATTRIBUTION: This project includes the module lcdroutines from * http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung */ #include -#include "USART.h" #include "avrjunit.h" +#include "usart.h" int main(void) { initUSART(); @@ -31,6 +31,7 @@ extern TestClass interruptsClass; extern TestClass sensorsClass; extern TestClass stringsClass; + extern TestClass usartClass; beginSuite("lambda"); runClass(adcClass); @@ -41,6 +42,7 @@ runClass(interruptsClass); runClass(sensorsClass); runClass(stringsClass); + runClass(usartClass); endSuite(); return 0; diff --git a/lambda-test/sensors-test.c b/lambda-test/sensors-test.c index 5081acb..ac878df 100644 --- a/lambda-test/sensors-test.c +++ b/lambda-test/sensors-test.c @@ -15,7 +15,6 @@ #include "adc.h" #include "sensors.h" #include "pins.h" -#include "USART.h" static TableEntry const testTable[] = { {10, 10}, diff --git a/lambda-test/usart-test.c b/lambda-test/usart-test.c new file mode 100644 index 0000000..4e1324e --- /dev/null +++ b/lambda-test/usart-test.c @@ -0,0 +1,54 @@ +/* + * usart-test.c + * + * Unit tests for the lambda project. + * + * Created on: 15.05.2015 + * Author: dode@luniks.net + * + */ + +#include +#include "avrjunit.h" +#include "usart.h" + +/* Module usart */ + +bool testInitUSART(void) { + assertTrue(BAUD); + + initUSART(); + + assertTrue(UBRR0H == UBRRH_VALUE); + assertTrue(UBRR0L == UBRRL_VALUE); + +#if USE_2X + assertTrue(bit_is_set(UCSR0A, U2X0)); +#else + assertTrue(bit_is_clear(UCSR0A, U2X0)); +#endif + + // transmission enabled + assertTrue(bit_is_set(UCSR0B, TXEN0)); + // receive enabled + assertTrue(bit_is_set(UCSR0B, RXEN0)); + + // 8 data bits + assertTrue(bit_is_set(UCSR0C, UCSZ01)); + assertTrue(bit_is_set(UCSR0C, UCSZ00)); + + return true; +} + +/* Test "class" */ +static const char class[] PROGMEM = "usart"; + +/* Test names */ +static const char testInitUSART_P[] PROGMEM = "testInitUSART"; + +/* Tests */ +static TestCase const tests[] = { + {class, testInitUSART_P, testInitUSART} +}; + +TestClass usartClass = {tests, sizeof(tests) / sizeof(tests[0])}; diff --git a/lambda/Makefile b/lambda/Makefile index 7b8b09c..0394c6b 100644 --- a/lambda/Makefile +++ b/lambda/Makefile @@ -14,7 +14,7 @@ ## If you've split your program into multiple .c / .h files, ## include the additional source (in same directory) here -LOCAL_SOURCE = USART.c interrupts.c adc.c sensors.c integers.c lcdroutines.c \ +LOCAL_SOURCE = usart.c interrupts.c adc.c sensors.c integers.c lcdroutines.c \ display.c alert.c command.c strings.c ## Here you can link to one more directory (and multiple .c files) diff --git a/lambda/USART.c b/lambda/USART.c deleted file mode 100644 index 7e8139a..0000000 --- a/lambda/USART.c +++ /dev/null @@ -1,137 +0,0 @@ - -/* - Quick and dirty functions that make serial communications work. - - Note that receiveByte() blocks -- it sits and waits _forever_ for - a byte to come in. If you're doing anything that's more interesting, - you'll want to implement this with interrupts. - - initUSART requires BAUDRATE to be defined in order to calculate - the bit-rate multiplier. 9600 is a reasonable default. - - May not work with some of the older chips: - Tiny2313, Mega8, Mega16, Mega32 have different pin macros - If you're using these chips, see (e.g.) iom8.h for how it's done. - These old chips don't specify UDR0 vs UDR1. - Correspondingly, the macros will just be defined as UDR. -*/ - -#include -#include "USART.h" -#include - -void initUSART(void) { /* requires BAUD */ - UBRR0H = UBRRH_VALUE; /* defined in setbaud.h */ - UBRR0L = UBRRL_VALUE; -#if USE_2X - UCSR0A |= (1 << U2X0); -#else - UCSR0A &= ~(1 << U2X0); -#endif - /* Enable USART transmitter/receiver */ - UCSR0B = (1 << TXEN0) | (1 << RXEN0); - UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /* 8 data bits, 1 stop bit */ -} - - -void transmitByte(uint8_t data) { - /* Wait for empty transmit buffer */ - loop_until_bit_is_set(UCSR0A, UDRE0); - UDR0 = data; /* send data */ -} - -uint8_t receiveByte(void) { - loop_until_bit_is_set(UCSR0A, RXC0); /* Wait for incoming data */ - return UDR0; /* return register value */ -} - - - /* Here are a bunch of useful printing commands */ - -void printString(const char myString[]) { - uint8_t i = 0; - while (myString[i]) { - transmitByte(myString[i]); - i++; - } -} - -void readString(char myString[], uint8_t maxLength) { - char response; - uint8_t i; - i = 0; - while (i < (maxLength - 1)) { /* prevent over-runs */ - response = receiveByte(); - transmitByte(response); /* echo */ - if (response == '\r') { /* enter marks the end */ - break; - } - else { - myString[i] = response; /* add in a letter */ - i++; - } - } - myString[i] = 0; /* terminal NULL character */ -} - -void printByte(uint8_t byte) { - /* Converts a byte to a string of decimal text, sends it */ - transmitByte('0' + (byte / 100)); /* Hundreds */ - transmitByte('0' + ((byte / 10) % 10)); /* Tens */ - transmitByte('0' + (byte % 10)); /* Ones */ -} - -void printWord(uint16_t word) { - transmitByte('0' + (word / 10000)); /* Ten-thousands */ - transmitByte('0' + ((word / 1000) % 10)); /* Thousands */ - transmitByte('0' + ((word / 100) % 10)); /* Hundreds */ - transmitByte('0' + ((word / 10) % 10)); /* Tens */ - transmitByte('0' + (word % 10)); /* Ones */ -} - -void printBinaryByte(uint8_t byte) { - /* Prints out a byte as a series of 1's and 0's */ - uint8_t bit; - for (bit = 7; bit < 255; bit--) { - if (bit_is_set(byte, bit)) - transmitByte('1'); - else - transmitByte('0'); - } -} - -char nibbleToHexCharacter(uint8_t nibble) { - /* Converts 4 bits into hexadecimal */ - if (nibble < 10) { - return ('0' + nibble); - } - else { - return ('A' + nibble - 10); - } -} - -void printHexByte(uint8_t byte) { - /* Prints a byte as its hexadecimal equivalent */ - uint8_t nibble; - nibble = (byte & 0b11110000) >> 4; - transmitByte(nibbleToHexCharacter(nibble)); - nibble = byte & 0b00001111; - transmitByte(nibbleToHexCharacter(nibble)); -} - -uint8_t getNumber(void) { - // Gets a numerical 0-255 from the serial port. - // Converts from string to number. - char hundreds = '0'; - char tens = '0'; - char ones = '0'; - char thisChar = '0'; - do { /* shift over */ - hundreds = tens; - tens = ones; - ones = thisChar; - thisChar = receiveByte(); /* get a new character */ - transmitByte(thisChar); /* echo */ - } while (thisChar != '\r'); /* until type return */ - return (100 * (hundreds - '0') + 10 * (tens - '0') + ones - '0'); -} diff --git a/lambda/USART.h b/lambda/USART.h deleted file mode 100644 index c3f18eb..0000000 --- a/lambda/USART.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Functions to initialize, send, receive over USART - - initUSART requires BAUD to be defined in order to calculate - the bit-rate multiplier. - */ - -#ifndef BAUD /* if not defined in Makefile... */ -#define BAUD 9600 /* set a safe default baud rate */ -#endif - - /* These are defined for convenience */ -#define USART_HAS_DATA bit_is_set(UCSR0A, RXC0) -#define USART_READY bit_is_set(UCSR0A, UDRE0) - -/* Takes the defined BAUD and F_CPU, - calculates the bit-clock multiplier, - and configures the hardware USART */ -void initUSART(void); - -/* Blocking transmit and receive functions. - When you call receiveByte() your program will hang until - data comes through. We'll improve on this later. */ -void transmitByte(uint8_t data); -uint8_t receiveByte(void); - -void printString(const char myString[]); - /* Utility function to transmit an entire string from RAM */ -void readString(char myString[], uint8_t maxLength); -/* Define a string variable, pass it to this function - The string will contain whatever you typed over serial */ - -void printByte(uint8_t byte); - /* Prints a byte out as its 3-digit ascii equivalent */ -void printWord(uint16_t word); - /* Prints a word (16-bits) out as its 5-digit ascii equivalent */ - -void printBinaryByte(uint8_t byte); - /* Prints a byte out in 1s and 0s */ -char nibbleToHex(uint8_t nibble); -void printHexByte(uint8_t byte); - /* Prints a byte out in hexadecimal */ -uint8_t getNumber(void); -/* takes in up to three ascii digits, - converts them to a byte when press enter */ diff --git a/lambda/display.c b/lambda/display.c index 60a39f6..b371378 100644 --- a/lambda/display.c +++ b/lambda/display.c @@ -13,7 +13,7 @@ #include #include #include -#include "USART.h" +#include "usart.h" #include "lcdroutines.h" #include "integers.h" #include "display.h" diff --git a/lambda/interrupts.c b/lambda/interrupts.c index 3b2a509..91288d1 100644 --- a/lambda/interrupts.c +++ b/lambda/interrupts.c @@ -18,11 +18,8 @@ #include "alert.h" static volatile bool buttonPressed = false; -static volatile bool usartReceived = false; static volatile uint8_t intCount = 0; -static char usartData[64]; - /** * Called every 16 ms. */ @@ -37,35 +34,6 @@ } } -/** - * Called when data was received via USART. - */ -ISR(USART_RX_vect) { - if (bit_is_set(UCSR0A, RXC0) && ! usartReceived) { - char data = UDR0; - size_t length = strlen(usartData); - if (length < sizeof(usartData) - 1 && data != '\n' && data != '\r') { - usartData[length] = data; - } else { - usartData[length] = '\0'; - usartReceived = true; - } - } -} - -bool isUSARTReceived(void) { - return usartReceived; -} - -void getUSARTData(char* const data, size_t const size) { - if (size > 0) { - data[0] = '\0'; - strncat(data, usartData, size - 1); - } - memset(usartData, 0, sizeof(usartData)); - usartReceived = false; -} - bool hasIntCount(uint8_t const count, bool const reset) { if (intCount >= count) { if (reset) { diff --git a/lambda/interrupts.h b/lambda/interrupts.h index 8cf2f9e..5df2368 100644 --- a/lambda/interrupts.h +++ b/lambda/interrupts.h @@ -12,17 +12,6 @@ #define INTERRUPTS_H_ /** - * Returns true if a CR or LF terminated line of data was received via USART. - */ -bool isUSARTReceived(void); - -/** - * Appends the data received via USART to the given string with the given - * length. - */ -void getUSARTData(char* data, size_t length); - -/** * Returns true if the current timer interrupt count is equal or greater to * the given count and resets it if the given boolean is true. */ diff --git a/lambda/lambda.c b/lambda/lambda.c index b03a8d1..5cac9de 100644 --- a/lambda/lambda.c +++ b/lambda/lambda.c @@ -9,10 +9,10 @@ * * DISCLAIMER: I'm new to C. * - * ATTRIBUTION: This project includes the module USART and the Makefile from - * the code accompanying the book Make: AVR Programming by Elliot Williams, - * a great book and a pleasant read, that helped me tremendously to get - * started with AVR programming. + * ATTRIBUTION: This project includes the the Makefile from the code + * accompanying the book Make: AVR Programming by Elliot Williams, a great book + * and a pleasant read that helped me tremendously to get started with AVR + * programming. * ATTRIBUTION: This project includes the module lcdroutines from * http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung */ @@ -22,7 +22,7 @@ #include #include #include -#include "USART.h" +#include "usart.h" #include "lcdroutines.h" #include "adc.h" #include "interrupts.h" diff --git a/lambda/sensors.c b/lambda/sensors.c index f67f84f..5b8fadf 100644 --- a/lambda/sensors.c +++ b/lambda/sensors.c @@ -12,7 +12,6 @@ #include #include #include -#include "USART.h" #include "adc.h" #include "sensors.h" #include "integers.h" diff --git a/lambda/usart.c b/lambda/usart.c new file mode 100644 index 0000000..aaae4c5 --- /dev/null +++ b/lambda/usart.c @@ -0,0 +1,68 @@ +/* + * usart.c + * + * Created on: 19.05.2015 + * Author: dode@luniks.net + */ + +#include +#include +#include +#include +#include "usart.h" + +static volatile bool usartReceived = false; + +static char usartData[64]; + +/** + * Called when data was received via USART. + */ +ISR(USART_RX_vect) { + if (bit_is_set(UCSR0A, RXC0) && ! usartReceived) { + char data = UDR0; + size_t length = strlen(usartData); + if (length < sizeof(usartData) - 1 && data != '\n' && data != '\r') { + usartData[length] = data; + } else { + usartData[length] = '\0'; + usartReceived = true; + } + } +} + +void initUSART(void) { + UBRR0H = UBRRH_VALUE; + UBRR0L = UBRRL_VALUE; + +#if USE_2X + UCSR0A |= (1 << U2X0); +#else + UCSR0A &= ~(1 << U2X0); +#endif + + UCSR0B = (1 << TXEN0) | (1 << RXEN0); + UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); +} + +bool isUSARTReceived(void) { + return usartReceived; +} + +void getUSARTData(char* const data, size_t const size) { + if (size > 0) { + data[0] = '\0'; + strncat(data, usartData, size - 1); + } + memset(usartData, 0, sizeof(usartData)); + usartReceived = false; +} + +void printString(char* const data) { + uint8_t i = 0; + char c; + while ((c = data[i++]) != '\0') { + loop_until_bit_is_set(UCSR0A, UDRE0); + UDR0 = c; + } +} diff --git a/lambda/usart.h b/lambda/usart.h new file mode 100644 index 0000000..b9bb4a2 --- /dev/null +++ b/lambda/usart.h @@ -0,0 +1,39 @@ +/* + * usart.h + * + * Created on: 19.05.2015 + * Author: dode@luniks.net + */ + +#ifndef USART_H_ +#define USART_H_ + +#ifndef BAUD +#define BAUD 9600 +#endif + +#include +#include + +/** + * Sets the baudrate and enables the transmitter and receiver. + */ +void initUSART(void); + +/** + * Returns true if a CR or LF terminated line of data was received via USART. + */ +bool isUSARTReceived(void); + +/** + * Appends the data received via USART to the given string with the given + * length. + */ +void getUSARTData(char* data, size_t length); + +/** + * Prints the given string via USART. + */ +void printString(char* data); + +#endif /* USART_H_ */