#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
+#include <util/delay.h>
#include "uart.h"
/*
* 0x02 Distance left LSB
* 0x03 Distance right MSB
* 0x04 Distance right LSB
+ * 0x05 Distance forward MSB
+ * 0x06 Distance forward LSB
+ * 0x07 Distance backward MSB
+ * 0x08 Distance backward LSB
*
* 0xff Bootloader
*/
static volatile uint8_t bootloader=0;
static volatile uint16_t dist_left=0;
static volatile uint16_t dist_right=0;
+static volatile uint16_t dist_forward=0;
+static volatile uint16_t dist_backward=0;
+static volatile uint8_t start_dist_fwd=0;
+static volatile uint8_t start_dist_bwd=0;
ISR(TWI_vect)
{
switch(ireg) {
case 0x00: // register select
ireg = TWDR;
+
+ if (ireg == 0x05) start_dist_fwd=1;
+ if (ireg == 0x07) start_dist_bwd=1;
+
ireg--; // because we do ireg++ below
TWI_ACK;
break;
TWDR = tmp16;
TWI_ACK;
break;
+ case 0x05: // Distance forward MSB
+ tmp16 = dist_forward;
+ TWDR = tmp16>>8;
+ TWI_ACK;
+ break;
+ case 0x06: // Distance forward LSB
+ TWDR = tmp16;
+ TWI_ACK;
+ break;
+ case 0x07: // Distance backward MSB
+ tmp16 = dist_backward;
+ TWDR = tmp16>>8;
+ TWI_ACK;
+ break;
+ case 0x08: // Distance backward LSB
+ TWDR = tmp16;
+ TWI_ACK;
+ break;
default:
TWDR = 0;
TWI_NAK;
}
+ISR(INT0_vect) {
+ static uint16_t t_start=0;
+ uint16_t t_now = TCNT1;
+ uint16_t t_diff;
+
+ if (bit_is_set(PIND, 2)) { // high level
+ // start timer
+ t_start = t_now;
+ } else {
+ t_diff = t_now - t_start;
+ dist_forward = t_diff*2.7586 + 0.5; // t [µs] / 580 = mm
+ // disable this interrupt
+ EIMSK |= (1 << INT0);
+ }
+}
+
+
+ISR(INT1_vect) {
+ static uint16_t t_start=0;
+ uint16_t t_now = TCNT1;
+ uint16_t t_diff;
+
+ if (bit_is_set(PIND, 3)) { // high level
+ // start timer
+ t_start = t_now;
+ } else {
+ t_diff = t_now - t_start;
+ dist_backward = t_diff*2.7586 + 0.5; // t [µs] / 580 = mm
+ // disable this interrupt
+ EIMSK |= (1 << INT1);
+ }
+}
+
+
int main(void) {
bootloader = 0x00;
setup_uart(9600);
TWAR = 0x52;
TWI_RESET;
+ // Timer 1: Normal mode, Top: 0xffff, Prescaler: F_CPU/256=62500Hz
+ TCCR1A = 0x0;
+ TCCR1B = (1 << CS12);
+
+ // External Interrupts
+ EICRA = (1 << ISC10) | (1 << ISC00);
+
printf("\r\nStart\r\n");
set_sleep_mode(SLEEP_MODE_IDLE);
sei();
while(1) {
switch(ireg) {
- case 1: // ir left
+ case 0x01: // ir left
dist_left = get_distance(0);
break;
- case 3: // ir right
+ case 0x03: // ir right
dist_right = get_distance(1);
break;
case 0xff: // Magic reg that starts the bootloader
break;
}
+ if (start_dist_fwd) {
+ start_dist_fwd = 0;
+ dist_forward = 0;
+
+ DDRD |= (1 << 2);
+ PORTD |= (1 << 2);
+ _delay_us(10);
+ PORTD &= ~(1 << 2);
+ DDRD &= ~(1 << 2);
+ // wait for interrupt
+ EIMSK |= (1 << INT0);
+ }
+ if (start_dist_bwd) {
+ start_dist_bwd = 0;
+ dist_backward = 0;
+
+ DDRD |= (1 << 3);
+ PORTD |= (1 << 3);
+ _delay_us(10);
+ PORTD &= ~(1 << 3);
+ DDRD &= ~(1 << 3);
+ // wait for interrupt
+ EIMSK |= (1 << INT1);
+ }
+
sleep_mode();
}