Project

General

Profile

Statistics
| Branch: | Revision:

root / scout_avr / src / Atmega128rfa1.cpp @ daf6a575

History | View | Annotate | Download (2.25 KB)

1
#include "Atmega128rfa1.h"
2
#include "bom.h"
3

    
4
extern "C"
5
{
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
  void __cxa_pure_virtual(void) {}
9
}
10

    
11
#define T0_KHZ 76
12
#define T0_OCR (F_CPU / 1000 / T0_KHZ) // 210 ticks
13
#define T0_ERROR (F_CPU / 1000 - T0_OCR*T0_KHZ) // 40 ticks/ms
14

    
15
unsigned char t0_count, t0_error;
16
unsigned long millis;
17

    
18
int rx_start, rx_end;
19
char rx_buffer[RX_BUFFER_SIZE];
20

    
21
Atmega128rfa1::Atmega128rfa1()
22
{
23
}
24

    
25
ISR(TIMER0_COMPA_vect)
26
{
27
  bom_isr();
28

    
29
  // F_CPU = T0_OCR * T0_KHZ + T0_ERROR
30
  // every millisecond, accumulate T0_ERROR, and when it reaches T0_OCR skip
31
  // one iteration
32
  t0_count++;
33
  if (t0_count >= T0_KHZ) {
34
    t0_error += T0_ERROR;
35
    if (t0_error < T0_OCR) {
36
      t0_count = 0;
37
    } else {
38
      t0_count = -1;
39
      t0_error -= T0_OCR;
40
    }
41
    millis++;
42
  }
43
}
44

    
45
ISR(USART0_RX_vect)
46
{
47
  char data = UDR0;
48
  int new_end = rx_end+1;
49
  if (new_end == RX_BUFFER_SIZE) {
50
    new_end = 0;
51
  }
52
  if (new_end == rx_start)
53
  {
54
    // TODO warn of buffer overflow?
55
  }
56
  else
57
  {
58
    rx_buffer[rx_end] = data;
59
    rx_end = new_end;
60
  }
61
}
62

    
63
void Atmega128rfa1::init()
64
{
65
  // === init serial ===
66
  // baud = F_CPU / (16 (UBRR + 1))
67
  uint16_t ubrr = F_CPU / 16 / BAUD_RATE - 1;
68
  UBRR0H = ubrr >> 8;
69
  UBRR0L = ubrr;
70
  // UMSEL0 = 0, asynchronous usart
71
  // UPM0 = 0, parity check disabled
72
  // USBS0 = 0, 1 stop bit
73
  // UCSZ0 = 3, 8-bit
74
  UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
75
  UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
76

    
77
  // === init time ===
78
  // COM0x = 0, pin OC0x not used
79
  // WGM0 = 2, clear timer on compare match, TOP = OCRA
80
  // CS0 = 1, no prescaler
81
  TCCR0A = _BV(WGM01);
82
  TCCR0B = _BV(CS00);
83
  // enable interrupt on compare match A
84
  TIMSK0 = _BV(OCIE0A);
85
  OCR0A = T0_OCR;
86
  millis = 0;
87

    
88
  sei();
89
}
90

    
91
int Atmega128rfa1::read()
92
{
93
  int ret;
94
  cli();
95
  if (rx_start == rx_end)
96
    ret = -1;
97
  else
98
  {
99
    ret = rx_buffer[rx_start];
100
    rx_start++;
101
    if (rx_start == RX_BUFFER_SIZE)
102
      rx_start = 0;
103
  }
104
  sei();
105
  return ret;
106
}
107

    
108
void Atmega128rfa1::write(uint8_t* data, int length)
109
{
110
  // TODO make this non-blocking with a tx buffer
111
  int i;
112
  for (i = 0; i < length; i++)
113
  {
114
    while (!(UCSR0A & _BV(UDRE0)));
115
    UDR0 = data[i];
116
  }
117
}
118

    
119
unsigned long Atmega128rfa1::time()
120
{
121
  unsigned long ret;
122
  cli();
123
  ret = millis;
124
  sei();
125
  return ret;
126
}