root / scout_avr / src / range.cpp @ 86b48573
History | View | Annotate | Download (1.92 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 |
* 147us/in * 16 MHz / 64 prescaler = 1.44685039 ticks / mm
|
| 18 |
*/
|
| 19 |
|
| 20 |
struct range_t {
|
| 21 |
unsigned int start; // timer value on rising edge |
| 22 |
unsigned int value; // last measured range |
| 23 |
char busy;
|
| 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].busy = 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].busy = 0;
|
| 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].busy = 0;
|
| 87 |
} |
| 88 |
|
| 89 |
// TODO ensure that one interrupt won't be delayed because of the other
|
| 90 |
PORT_SONAR_TX |= _BV(P_SONAR_TX); |
| 91 |
_delay_ms(40);
|
| 92 |
PORT_SONAR_TX &= ~ _BV(P_SONAR_TX); |
| 93 |
|
| 94 |
for (i = 0; i < 2; i++) |
| 95 |
{
|
| 96 |
while (range[i].busy) {}
|
| 97 |
values[i] = range[i].value; |
| 98 |
} |
| 99 |
} |