]> defiant.homedns.org Git - ros_wild_thumper.git/blobdiff - avr/nano/main.c
avr nano: Fix adc sample rate
[ros_wild_thumper.git] / avr / nano / main.c
index 5ba30821e26227f6e936fede523b2d80b3dd4964..935ce4994d4ae418a1333a13aa44045210e1518b 100644 (file)
@@ -5,6 +5,10 @@
 #include <avr/interrupt.h>
 #include <avr/sleep.h>
 #include <util/delay.h>
+#include <util/twi.h>
+#include <avr/eeprom.h>
+#include <avr/wdt.h>
+#include <avr/pgmspace.h>
 #include "uart.h"
 
 /*
@@ -22,6 +26,8 @@
  * 0x0A Voltage LSB
  * 0x0B Distance forward2 MSB
  * 0x0C Distance forward2 LSB
+ * 0x0D Current MSB
+ * 0x0E Current LSB
  *
  * 0x15 Distance forward1 MSB (read only)
  * 0x16 Distance forward1 LSB (read only)
  */
 
 
-#define TWI_ACK                TWCR = (1<<TWEA) | (1<<TWINT) | (1<<TWEN) | (1<<TWIE)
-#define TWI_RESET      TWCR &= ~((1 << TWSTO) | (1 << TWEN)); TWI_ACK
-#define TWI_NAK                TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE)
+/**
+ * Nano Pinout
+ * A0 PC0/ADC0
+ * A1 PC1/ADC1
+ * A2 PC2/ADC2
+ * A3 PC3/ADC3
+ * A4 PC4/ADC4
+ * A5 PC5/ADC5
+ * A6 ADC6
+ * A7 ADC7
+ * D0 PD0/RX
+ * D1 PD1/TX
+ * D2 PD2/IND0
+ * D3 PD3/IND1
+ * D4 PD4/T0
+ * D5 PD5/T1
+ * D6 PD6/AIN0
+ * D7 PD7/AIN1
+ * D8 PB0/ICP
+ * D9 PB1/OC1
+ * D10 PB2/SS
+ * D11 PB3/MOSI
+ * D12 PB4/MISO
+ * D13 PB5/SCK
+ */
+
+
+#define TWI_ACK   TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN) | (1<<TWIE)
+#define TWI_NAK   TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWIE)
+#define TWI_RESET TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWSTO) | (1<<TWEN) | (1<<TWIE);
 
 static volatile uint8_t ireg=0;
 static volatile uint8_t bootloader=0;
@@ -49,26 +82,27 @@ static volatile uint8_t start_dist_fwd1=0;
 static volatile uint8_t start_dist_fwd2=0;
 static volatile uint8_t start_dist_bwd=0;
 static volatile uint16_t voltage=0;
+static volatile uint16_t current=0;
 static volatile uint8_t pind_pre=0;
 
 ISR(TWI_vect)
 {
        static int16_t tmp16=0;
 
-       switch (TWSR & 0xF8)
+       switch(TW_STATUS)
        {  
-               case 0x60: // start write
+               case TW_SR_SLA_ACK: // start write
                        TWI_ACK;
                        ireg = 0;
                        break;
-               case 0x80: // write
+               case TW_SR_DATA_ACK: // write
                        switch(ireg) {
                                case 0x00: // register select
                                        ireg = TWDR;
 
                                        if (ireg == 0x05) start_dist_fwd1=1;
                                        if (ireg == 0x07) start_dist_bwd=1;
-                                       if (ireg == 0x09) start_dist_fwd2=1;
+                                       if (ireg == 0x0b) start_dist_fwd2=1;
 
                                        ireg--; // because we do ireg++ below
                                        TWI_ACK;
@@ -78,10 +112,10 @@ ISR(TWI_vect)
                                default:
                                        TWI_NAK;
                        }
-                       ireg++;
+                       if (ireg < 0xff) ireg++;
                        break;
-               case 0xA8: // start read
-               case 0xB8: // read
+               case TW_ST_SLA_ACK: // start read
+               case TW_ST_DATA_ACK: // read
                        switch(ireg) {
                                case 0x01: // Distance left MSB
                                        tmp16 = dist_left;
@@ -137,6 +171,15 @@ ISR(TWI_vect)
                                        TWDR = tmp16;
                                        TWI_ACK;
                                        break;
+                               case 0x0D: // Current MSB
+                                       tmp16 = current;
+                                       TWDR = tmp16>>8;
+                                       TWI_ACK;
+                                       break;
+                               case 0x0E: // Current LSB
+                                       TWDR = tmp16;
+                                       TWI_ACK;
+                                       break;
                                case 0x15: // Distance forward1 MSB
                                        tmp16 = dist_forward1;
                                        TWDR = tmp16>>8;
@@ -170,6 +213,11 @@ ISR(TWI_vect)
                        }
                        ireg++;
                        break;
+               case TW_SR_STOP:
+                       TWI_ACK;
+                       break;
+               case TW_NO_INFO:
+                       break;
                default:
                        TWI_RESET;
        }
@@ -180,8 +228,9 @@ uint16_t ReadChannel(uint8_t mux) {
        uint8_t i;
        uint16_t result;
 
-       ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
-       // setzen auf 8 (1) und ADC aktivieren (1)
+       ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler
+       // setzen auf 128 (1) und ADC aktivieren (1)
+       // 16MHz/128=125kHz
 
        ADMUX = mux;                      // Kanal waehlen
        ADMUX |= (1<<REFS0);
@@ -225,6 +274,16 @@ static unsigned short get_voltage(void) {
 }
 
 
+/*
+ * zero offset: 0.5V
+ * sensitivity: 133mV/A
+ */
+static unsigned short get_current(void) {
+       double volt = ReadChannel(3)*5.0171; // mV
+       return (volt-517.78)/0.12656; // mA
+}
+
+
 ISR(INT0_vect) {
        static uint16_t t_start=0;
        uint16_t t_now = TCNT1;
@@ -289,7 +348,7 @@ int main(void) {
 
        // I2C
        TWAR = 0x52;
-       TWI_RESET;
+       TWI_ACK;
 
        // Timer 1: Normal mode, Top: 0xffff, Prescaler: F_CPU/256=62500Hz
        TCCR1A = 0x0;
@@ -299,7 +358,7 @@ int main(void) {
        EICRA = (1 << ISC10) | (1 << ISC00);
        PCICR = (1 << PCIE2);
 
-       printf("\r\nStart\r\n");
+       printf_P(PSTR("\r\nStart\r\n"));
 
        set_sleep_mode(SLEEP_MODE_IDLE);
        sei();
@@ -314,13 +373,17 @@ int main(void) {
                        case 0x09: // voltage
                                voltage = get_voltage();
                                break;
+                       case 0x0d: // current
+                               current = get_current();
+                               break;
                        case 0xff: // Magic reg that starts the bootloader
                                if (bootloader == 0xa5) {
                                        cli();
-                                       {
-                                               void (*start)(void) = (void*)0x1800;
-                                               start();
-                                       }
+                                       // write mark to first area in eeprom
+                                       eeprom_write_byte((uint8_t*)0, 123);
+                                       eeprom_busy_wait();
+                                       // Use watchdog to restart
+                                       wdt_enable(WDTO_15MS);
                                }
                                break;
                }