changeset 14:326ed6d18e6b draft default tip

Fix address jumpers, add dead band, keep low when duty 0
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Fri, 20 Jan 2017 20:55:28 +0100
parents 846c874c742c
children
files firmware/Makefile firmware/main.c
diffstat 2 files changed, 76 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/firmware/Makefile	Fri Jan 20 17:47:37 2017 +0100
+++ b/firmware/Makefile	Fri Jan 20 20:55:28 2017 +0100
@@ -4,7 +4,7 @@
 OBJECTS = main.o
 
 FUSES = -U lfuse:w:0xE2:m -U hfuse:w:0xDF:m
-AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) -B 100
+AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) # -B 100
 COMPILE = avr-gcc -std=gnu99 -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE)
 
 all:	main.hex
--- a/firmware/main.c	Fri Jan 20 17:47:37 2017 +0100
+++ b/firmware/main.c	Fri Jan 20 20:55:28 2017 +0100
@@ -16,13 +16,19 @@
 
 
 #define MAX_SERVO 20
+#define DEAD_BAND 9
+
+
+struct masks {
+    uint8_t mask_b;
+    uint8_t mask_c;
+    uint8_t mask_d;
+};
 
 static uint16_t servo_pulse[MAX_SERVO];
 
 volatile static uint16_t servo_delay[MAX_SERVO + 1];
-volatile static uint8_t servo_mask_b[MAX_SERVO];
-volatile static uint8_t servo_mask_c[MAX_SERVO];
-volatile static uint8_t servo_mask_d[MAX_SERVO];
+volatile static struct masks servo_masks[MAX_SERVO];
 volatile static uint8_t servo_enable_b;
 volatile static uint8_t servo_enable_c;
 volatile static uint8_t servo_enable_d;
@@ -37,28 +43,51 @@
 };
 
 ISR(TIMER1_COMPA_vect) {
+    OCR1B = servo_delay[0];
+    TCNT1 = 0;
     servo_event = 0;
-    PORTB = 0xff;
-    // leave out RESET, A, SCL, PC7
-    // pull up SDA and SCL
-    PORTC = 0xff & 0x3f;
-    PORTD = 0xff;
-    TCNT1 = 0;
-    OCR1B = servo_delay[0];
+    PORTB = servo_enable_b;
+    PORTC = servo_enable_c;
+    PORTD = servo_enable_d;
 }
 
 
 ISR(TIMER1_COMPB_vect) {
-    PORTB &= servo_mask_b[servo_event];
-    PORTC &= servo_mask_c[servo_event] | 0x30;
-    PORTD &= servo_mask_d[servo_event];
-    servo_event += 1;
-    OCR1B = servo_delay[servo_event];
+    struct masks masks = servo_masks[servo_event];
+    OCR1B = servo_delay[++servo_event];
+    PORTB &= masks.mask_b;
+    PORTC &= masks.mask_c;
+    PORTD &= masks.mask_d;
 }
 
 
 void servo_update() {
+    uint8_t mask;
     uint16_t last_pulse = 0;
+
+    mask = 0x00;
+    for (uint8_t servo = 0; servo < 8; ++servo) {
+        if (servo_pulse[servo]) {
+            mask |= 1 << servo;
+        }
+    }
+    servo_enable_b = mask;
+    mask = 0x00;
+    for (uint8_t servo = 0; servo < 4; ++servo) {
+        if (servo_pulse[8 + servo]) {
+            mask |= 1 << servo;
+        }
+    }
+    // leave out RESET (PC6) and PC7
+    // pull up SDA (PC4) and SCL (PC5)
+    servo_enable_c = mask & 0x0f | 0x30;
+    mask = 0x00;
+    for (uint8_t servo = 0; servo < 8; ++servo) {
+        if (servo_pulse[12 + servo]) {
+            mask |= 1 << servo;
+        }
+    }
+    servo_enable_d = mask;
     for (uint8_t event = 0; event < 8; ++event) {
         uint16_t smallest_pulse = 0xffff;
         for (uint8_t servo = 0; servo < MAX_SERVO; ++servo) {
@@ -68,34 +97,45 @@
             }
         }
         servo_delay[event] = smallest_pulse;
-        servo_mask_b[event] = 0xff;
+        if (smallest_pulse != 0xffff) {
+            smallest_pulse += DEAD_BAND;
+        }
+
+        mask = 0x00;
         for (uint8_t servo = 0; servo < 8; ++servo) {
             if (servo_pulse[servo] &&
                 servo_pulse[servo] <= smallest_pulse) {
-                servo_mask_b[event] &= ~(1 << servo);
+                mask |= 1 << servo;
             }
         }
-        servo_mask_c[event] = 0xff;
+        servo_masks[event].mask_b = ~mask;
+
+        mask = 0x00;
         for (uint8_t servo = 0; servo < 4; ++servo) {
             if (servo_pulse[8 + servo] &&
                 servo_pulse[8 + servo] <= smallest_pulse) {
-                servo_mask_c[event] &= ~(1 << servo);
+                mask |= 1 << servo;
             }
         }
-        servo_mask_d[event] = 0xff;
+        // leave out rst, sda, scl and pc7
+        servo_masks[event].mask_c = (~mask) | 0xf0;
+
+        mask = 0x00;
         for (uint8_t servo = 0; servo < 8; ++servo) {
             if (servo_pulse[12 + servo] &&
                 servo_pulse[12 + servo] <= smallest_pulse) {
-                servo_mask_d[event] &= ~(1 << servo);
+                mask |= 1 << servo;
             }
         }
+        servo_masks[event].mask_d = ~mask;
+
         last_pulse = smallest_pulse;
     }
 }
 
 
 uint16_t adc(uint8_t pin) {
-    ADMUX = 0<<ADLAR | 0<<REFS1 | 0<<REFS0 | 0x03 & pin;
+    ADMUX = 0<<ADLAR | 0<<REFS1 | 0<<REFS0 | 0x07 & pin;
     ADCSRA |= 1<<ADSC;
     while (ADCSRA & (1<<ADSC)) {
         // Pass.
@@ -106,18 +146,19 @@
 
 int main() {
     uint8_t i2c_address = I2C_ADDRESS;
+
     // Init ADC.
-//    ADCSRA = 1<<ADEN | 1<<ADPS2 | 1<<ADPS1 | 0<<ADPS0; // Pre-scaler 64.
-//    if (adc(6) > 511) {
-//        i2c_address += 1;
-//    }
-//    if (adc(7) > 511) {
-//        i2c_address += 2;
-//    }
-//    ADCSRA = 0<<ADEN;
+    ADCSRA = 1<<ADEN | 1<<ADPS2 | 1<<ADPS1 | 0<<ADPS0; // Pre-scaler 64.
+    if (adc(6) > 511) {
+        i2c_address += 1;
+    }
+    if (adc(7) > 511) {
+        i2c_address += 2;
+    }
+    ADCSRA = 0;
 
     // setup i2c slave
-    //PORTC |= 1<<PC4 | 1<<PC5; // enable pullups
+    PORTC |= 1<<PC4 | 1<<PC5; // enable pullups
     TWAR = i2c_address<<1;
 
     // setup servos
@@ -127,7 +168,7 @@
     OCR1A = 20000; // period
     TIMSK1 = 1<<OCIE1A | 1<<OCIE1B;
     DDRB = 0xff;
-    DDRC = 0x0f;
+    DDRC = 0x0f; // leave out RST, SDA, SCL and PC7
     DDRD = 0xff;
     for (uint8_t i = 0; i < MAX_SERVO; ++i) {
         servo_pulse[i] = 0;
@@ -175,6 +216,8 @@
                 }
                 dirty = 1;
                 break;
+            default: // unexpected status
+                TWCR = 1<<TWINT | 1<<TWSTO | 1<<TWEN;
         }
     }
 }