Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
19 jimmy 1
/**
2
 * @file    uart.c
3
 *          Routines for interrupt based USART communication on the ATmega8.
4
 * @author  Jimmy Myhrman
5
 * @date    2005-08-20
6
 */
7
 
8
/* -----------------------------------------------------------------------------
9
 * Includes
10
 * ---------------------------------------------------------------------------*/
11
#include "uart.h"
12
 
13
/* -----------------------------------------------------------------------------
14
 * Defines
15
 * ---------------------------------------------------------------------------*/
16
#define TX_BUFSIZE  256         /* must be power of 2 */
17
#define RX_BUFSIZE  2           /* must be power of 2 */
18
 
19
#define TX_MASK     (TX_BUFSIZE-1)
20
#define RX_MASK     (RX_BUFSIZE-1)
21
 
22
#define RX_BUFLEN   (rx_tail - rx_head)
23
#define TX_BUFLEN   (tx_tail - tx_head)
24
 
25
/* -----------------------------------------------------------------------------
26
 * Variables
27
 * ---------------------------------------------------------------------------*/
28
volatile unsigned char tx_buf[TX_BUFSIZE];
29
volatile unsigned char rx_buf[RX_BUFSIZE];
30
 
31
volatile uint8_t tx_head;
32
volatile uint8_t tx_tail;
33
 
34
volatile uint8_t rx_head;
35
volatile uint8_t rx_tail;
36
 
37
/* -----------------------------------------------------------------------------
38
 * Functions
39
 * ---------------------------------------------------------------------------*/
40
 
41
void uartInit(unsigned char baudrate) {
42
    UBRRH = (unsigned char) (baudrate>>8);
43
    UBRRL = (unsigned char) baudrate;
44
    /* 8 Databits, receive and transmit enabled, receive complete interrupt enabled */
45
    UCSRB = (1<<RXCIE)|(1<<TXEN)|(1<<RXEN);
46
}
47
 
48
int uartPutChar(char c) {
49
    // Fills the transmit buffer, if it is full wait
50
    //TODO: if interrupts are currently disabled (which is the case when this
51
    //function is called from within an interrupt routine), skip the while-loop
52
    //below. otherwise, use it
53
    //while ((TX_BUFSIZE - TX_BUFLEN) <= 2) {
54
        //if uartPutchar is called while global ints are disabled, we are
55
        //stuck here!
56
    //}
57
    if ((TX_BUFSIZE - TX_BUFLEN) <= 2) {
58
        return(1);
59
    }
60
    // Add data to the transmit buffer, move the tail and enable TXCIE
61
    // while tx_tail will count from 0 to 255... AND'ing it with 31 will
62
    //continually wrap the index 0 to 31
63
    tx_buf[tx_tail & TX_MASK] = c;
64
    tx_tail++;
65
    // enable data register empty interrupt
66
    UCSRB |= (1<<UDRIE);
67
    return(0);
68
}
69
 
70
 
71
int uartGetChar (void) {
72
    unsigned char c;
73
    // this will sit here and wait for SIG_UART0_RECV to get a character and
74
    //place it into rx0_buff
75
    while (RX_BUFLEN == 0) {
76
    }
77
    // rx_head will count from 0 to 255... AND'ing it with 31 will continually
78
    //wrap the index 0 to 31
79
    c = rx_buf[rx_head & RX_MASK];
80
    rx_head++;
81
    return(c);
82
}
83
 
84
 
85
// USART receive complete interrupt
86
SIGNAL(SIG_UART_RECV) {
87
    char c;
88
    // Get the received character
89
    c = UDR;
90
    // Echo the character back
91
    uartPutChar(c);
92
    // place the received character into the receive buffer and move the tail
93
    // rx_tail will count from 0 to 255... AND'ing it with 31 will continually
94
    //wrap the index 0 to 31
95
    rx_buf[rx_tail & RX_MASK] = c;
96
    rx_tail++;
97
}
98
 
99
 
100
// USART0 data register empty interrupt... another char can be transmitted if (tx0_head != tx0_tail)
101
SIGNAL(SIG_UART_DATA) {
102
    // tx_head will count from 0 to 255... AND'ing it with 31 will continually
103
    //wrap the index 0 to 31
104
    if (tx_head != tx_tail) {
105
        UDR = tx_buf[tx_head & TX_MASK];
106
        tx_head++;
107
    }
108
    else {
109
        // "~" is a one's compliment so UCSR0B = (UCSR0B AND 11011111) which disables udr empty interrupt
110
        UCSRB &= ~(1<<UDRIE);
111
    }
112
}
113
 
114
 
115
//string must be null-terminated
116
void uartPutString(char* str) {
117
    while (*str != 0) {
118
        uartPutChar(*str);
119
        str++;
120
    }
121
}
122
 
123
 
124
void uartPutUInt8(uint8_t number, uint8_t base) {
125
    uint8_t a;
126
    if ((a = number/base) != 0) {
127
        uartPutUInt8(a, base);
128
    }
129
    uartPutChar("0123456789ABCDEF"[(uint8_t)(number%base)]);
130
}
131
 
132
 
133
void uartPutUInt16(uint16_t number, uint8_t base) {
134
    uint16_t a;
135
    if ((a = number/base) != 0) {
136
        uartPutUInt16(a, base);
137
    }
138
    uartPutChar("0123456789ABCDEF"[(uint8_t)(number%base)]);
139
}
140
 
141
 
142
void uartNewLine(void) {
143
    uartPutString("\n\r");
144
}