Project

General

Profile

Statistics
| Branch: | Revision:

root / toolbox / serial.c @ 975af07c

History | View | Annotate | Download (1.45 KB)

1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include "serial.h"
5

    
6
static int rx_start = 0, rx_end = 0;
7
static uint8_t rx_buffer[RX_BUFFER_SIZE];
8

    
9
ISR(USART1_RX_vect) {
10
  uint8_t data = UDR1;
11
  int new_end = rx_end+1;
12
  if (new_end == RX_BUFFER_SIZE) {
13
    new_end = 0;
14
  }
15
  if (new_end == rx_start) {
16
    // TODO warn of buffer overflow?
17
  } else {
18
    rx_buffer[rx_end] = data;
19
    rx_end = new_end;
20
  }
21
}
22

    
23
void serial_init() {
24
  // baud = F_CPU / (div (UBRR + 1))
25
  // where div = 16 if U2X = 0, or 8 otherwise
26
  uint16_t ubrr = F_CPU / 8 / BAUD_RATE - 1;
27
  UBRR1H = ubrr >> 8;
28
  UBRR1L = ubrr;
29
  // UMSEL = 0, asynchronous usart
30
  // UPM = 0, parity check disabled
31
  // USBS = 0, 1 stop bit
32
  // UCSZ = 3, 8-bit
33
  // U2X = 1, use 8 prescale instead of 16 for a more accurate baud rate
34
  UCSR1A = _BV(U2X1);
35
  UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1);
36
  UCSR1C = _BV(UCSZ11) | _BV(UCSZ10);
37
}
38

    
39
int serial_read() {
40
  int ret;
41
  cli();
42
  if (rx_start == rx_end) {
43
    ret = -1;
44
  } else {
45
    ret = rx_buffer[rx_start];
46
    rx_start++;
47
    if (rx_start == RX_BUFFER_SIZE) {
48
      rx_start = 0;
49
    }
50
  }
51
  sei();
52
  return ret;
53
}
54

    
55
void serial_flush() {
56
  cli();
57
  rx_start = 0;
58
  rx_end = 0;
59
  sei();
60
}
61

    
62
uint8_t serial_read_blocking() {
63
  int c;
64
  do {
65
    c = serial_read();
66
  } while (c < 0);
67
  return c;
68
}
69

    
70
void serial_write(uint8_t* data, int length) {
71
  int i;
72
  for (i = 0; i < length; i++) {
73
    while (!(UCSR1A & _BV(UDRE1)));
74
    UDR1 = data[i];
75
  }
76
}