Project

General

Profile

Statistics
| Branch: | Revision:

root / scout_avr / src / range.cpp @ 230b1b7f

History | View | Annotate | Download (1.55 KB)

1
#include "range.h"
2

    
3
extern "C"
4
{
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
}
8

    
9
/* Ultrasonic Sensor:
10
 * -if RX pin is left open, it will continuously take readings
11
 * -PW output is 147us/in.
12
 * -PW will be high for a maximum of 37.5ms if no target is detected
13
 * 
14
 * 37.5ms * 8 MHz / 8 prescaler = 37500 max wait
15
 */
16

    
17
// so that we can test on a 328
18
#if defined(__AVR_ATmega128RFA1__)
19
#  define read_INT0 (PIND & _BV(PD0))
20
#  define read_INT1 (PIND & _BV(PD1))
21
#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
22
#  define read_INT0 (PIND & _BV(PD2))
23
#  define read_INT1 (PIND & _BV(PD3))
24
#else
25
#  error "Please define read_INTx for this device"
26
#endif
27

    
28
struct range_t {
29
  unsigned int start; // timer value on rising edge
30
  unsigned int value; // last measured range
31
} range[2];
32

    
33
static void on_edge(int which)
34
{
35
  unsigned int time = TCNT1;
36
  if (read_INT0)
37
  {
38
    range[which].start = time;
39
  }
40
  else
41
  {
42
    // if timer overflowed since start, this arithmetic should still work out
43
    range[which].value = time - range[which].start;
44
  }
45
}
46

    
47
ISR(INT0_vect)
48
{
49
  on_edge(0);
50
}
51

    
52
ISR(INT1_vect)
53
{
54
  on_edge(1);
55
}
56

    
57
void range_init()
58
{
59
  // ISCx = 1, edge triggered
60
  EICRA |= _BV(ISC10) | _BV(ISC00);
61
  // enable INT0 and INT1
62
  EIMSK |= _BV(INT1) | _BV(INT0);
63
  
64
  // CS1 = 2, 1/8 prescaler
65
  TCCR1B = _BV(CS11);
66
  
67
  range[0].value = RANGE_ERR;
68
  range[1].value = RANGE_ERR;
69
}
70

    
71
unsigned int range_get(int which)
72
{
73
  unsigned int ret;
74
  if (0 <= which && which <= 1)
75
  {
76
    cli();
77
    ret = range[which].value;
78
    sei();
79
    return ret;
80
  }
81
  else return RANGE_ERR;
82
}