Statistics
| Branch: | Revision:

scoutos / scout_avr / src / range.cpp @ f1582e6c

History | View | Annotate | Download (1.95 KB)

1
extern "C"
2
{
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
}
7
#include "range.h"
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
 * 37.5ms * 16 MHz / 8 prescaler = problem
16
 * 37.5ms * 16 MHz / 64 prescaler = 9375 max wait
17
 */
18

    
19
struct range_t {
20
  unsigned int start; // timer value on rising edge
21
  unsigned int value; // last measured range
22
  char started;
23
  char done;
24
} volatile range[2];
25

    
26
static void on_edge(int which)
27
{
28
  unsigned char int_high;
29
  unsigned int time = TCNT5;
30
  
31
  if (which)
32
  {
33
    int_high = PIN_SONAR_PWM & _BV(P_SONAR_PWM1);
34
  }
35
  else
36
  {
37
    int_high = PIN_SONAR_PWM & _BV(P_SONAR_PWM0);
38
  }
39
  
40
  if (int_high)
41
  {
42
    range[which].start = time;
43
    range[which].started = 1;
44
  }
45
  else
46
  {
47
    // if timer overflowed since start, this arithmetic should still work out
48
    range[which].value = time - range[which].start;
49
    range[which].done = 1;
50
  }
51
}
52

    
53
ISR(INT3_vect)
54
{
55
  on_edge(0);
56
}
57

    
58
ISR(INT2_vect)
59
{
60
  on_edge(1);
61
}
62

    
63
void range_init()
64
{
65
  // ISCx = 1, edge triggered
66
  EICRA |= _BV(ISC20) | _BV(ISC30);
67
  // enable INT2 and INT3
68
  EIMSK |= _BV(INT2) | _BV(INT3);
69
  
70
  // CS1 = 3, 1/64 prescaler
71
  // if this is changed, remember to change recv_edge in bom.cpp!
72
  TCCR5B = _BV(CS50) | _BV(CS51);
73

    
74
  // set tx as output
75
  DDRG |= _BV(DDG1);
76
  PORT_SONAR_TX &= ~ _BV(P_SONAR_TX);
77
}
78

    
79
void range_measure(unsigned int *values)
80
{
81
  int i;
82

    
83
  for (i = 0; i < 2; i++)
84
  {
85
    range[i].value = RANGE_ERR;
86
    range[i].started = 0;
87
    range[i].done = 0;
88
  }
89

    
90
  // TODO ensure that one interrupt won't be delayed because of the other
91
  PORT_SONAR_TX |= _BV(P_SONAR_TX);
92
  _delay_ms(1);
93
  PORT_SONAR_TX &= ~ _BV(P_SONAR_TX);
94

    
95
  for (i = 0; i < 2; i++)
96
  {
97
    if (range[i].started) {
98
      while (!range[i].done) {}
99
      values[i] = range[i].value;
100
    }
101
  }
102
}