]> defiant.homedns.org Git - ros_wild_thumper.git/blobdiff - avr/nano/main.c
nano: provide wrf read only values
[ros_wild_thumper.git] / avr / nano / main.c
index 0cb0acfba471aaaf79d67feba98932da429af36c..51cd1450d68e1fab6cc981bb5cb8a9bcd8dbe790 100644 (file)
@@ -4,6 +4,7 @@
 #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
+ * 0x15 Distance forward MSB (read only)
+ * 0x16 Distance forward LSB (read only)
+ * 0x17 Distance backward MSB (read only)
+ * 0x18 Distance backward LSB (read only)
+ * 0x09 Voltage MSB
+ * 0x0A Voltage LSB
  *
  * 0xff Bootloader
  */
@@ -26,6 +37,11 @@ static volatile uint8_t ireg=0;
 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;
+static volatile uint16_t voltage=0;
 
 ISR(TWI_vect)
 {
@@ -41,6 +57,10 @@ 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;
@@ -72,6 +92,51 @@ ISR(TWI_vect)
                                        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;
+                               case 0x15: // Distance forward MSB
+                                       tmp16 = dist_forward;
+                                       TWDR = tmp16>>8;
+                                       TWI_ACK;
+                                       break;
+                               case 0x16: // Distance forward LSB
+                                       TWDR = tmp16;
+                                       TWI_ACK;
+                                       break;
+                               case 0x17: // Distance backward MSB
+                                       tmp16 = dist_backward;
+                                       TWDR = tmp16>>8;
+                                       TWI_ACK;
+                                       break;
+                               case 0x18: // Distance backward LSB
+                                       TWDR = tmp16;
+                                       TWI_ACK;
+                                       break;
+                               case 0x09: // Voltage MSB
+                                       tmp16 = voltage;
+                                       TWDR = tmp16>>8;
+                                       TWI_ACK;
+                                       break;
+                               case 0x0A: // Voltage LSB
+                                       TWDR = tmp16;
+                                       TWI_ACK;
+                                       break;
                                default:
                                        TWDR = 0;
                                        TWI_NAK;
@@ -92,7 +157,7 @@ uint16_t ReadChannel(uint8_t mux) {
        // setzen auf 8 (1) und ADC aktivieren (1)
 
        ADMUX = mux;                      // Kanal waehlen
-       ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen 
+       ADMUX |= (1<<REFS0);
 
        /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
           also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
@@ -128,6 +193,45 @@ static unsigned short get_distance(uint8_t i) {
 }
 
 
+static unsigned short get_voltage(void) {
+       return ReadChannel(2)*1.46;
+}
+
+
+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);
@@ -137,18 +241,28 @@ int main(void) {
        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 0x09: // voltage
+                               voltage = get_voltage();
+                               break;
                        case 0xff: // Magic reg that starts the bootloader
                                if (bootloader == 0xa5) {
                                        cli();
@@ -160,6 +274,31 @@ int main(void) {
                                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();
        }