#include #include #include #include #include "oulib.h" /////// // GLOBAL STRUCTURES #define BUF_SIZE 30 volatile char buffer[BUF_SIZE]; volatile int front, nchars; /////// // Interrupt handler SIGNAL(SIG_UART_RECV) { char c; // Toggle port state to indicate when characters arrive PORTB ^= 1; // Get the character out of the buffer c = getchar(); // Insert the charcter into the buffer only if it is not full if(nchars < BUF_SIZE) { // Store the new character in the buffer buffer[(front+nchars)%BUF_SIZE] = c; // Increment charcter counter ++nchars; }; }; // Enable/disable the serial port interrupt. // This is accomplished by setting or clearing the // bit in UCSRB that corresponds to the serial port // receive completion interrupt. // // These functions are declared "inline": the compiler // in this case does not generate the assembly code to // perform a subroutine call. Instead, the contents of // the inline function are substituted directly into the // calling function. This may mean that there are multiple // copies of this code in the end, but it does mean that // it executes fast. // inline void serial_receive_enable(void) { UCSRB |= _BV(RXCIE); // Enable serial receive interrupt } inline void serial_receive_disable(void) { UCSRB &= ~_BV(RXCIE); // Disable serial receive interrupt } // int get_next_character(void) // // Return = next character in the buffer if there is one // = -1 otherwise // // Note: we disable the interrupt // int get_next_character(void) { int c; // Turn off interrupts serial_receive_disable(); if(nchars == 0) { // No characters in buffer: return error code // Enable interrupts serial_receive_enable(); return(-1); }else{ // There is at least one: return it c = buffer[front]; front = (front + 1)%BUF_SIZE; nchars--; // Enable interrupts serial_receive_enable(); return(c); }; }; // void flash_led(unsigned int i) // // Flash B0 for msec // void flash_led(unsigned int i) { PORTB |= 1; delay_ms(i); PORTB &= ~1; delay_ms(i); } int main (void) { int c; // Initialize global structures front = 0; nchars = 0; // Initialize I/O DDRB = 0xFF; PORTB = 0; // Wakeup procedure flash_led(250); flash_led(250); flash_led(250); // Initialize serial port serial0_init(9600); // Enable interrupts // Global interrupt enable sei(); // Serial port enable serial_receive_enable(); // Say hello... printf("hello world...\n\r"); // Loop forever for(;;) { // Eat all of the characters in the buffer do{ c = get_next_character(); if(c != -1) { // Echo the character putchar(c); } }while(c != -1); // Toggle LSB of PORTB on every cycle just to show that // we are still alive PORTB ^= 2; // "Something else": sleep for 5 sec delay_ms(5000); } };