changeset 1:4c4f0373ef4c draft

Add I2C interface
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Mon, 19 Dec 2016 00:11:30 +0100
parents 1c66c9190b32
children eebf26b86400
files firmware/main.c firmware/servo.c firmware/servo.h
diffstat 3 files changed, 53 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/firmware/main.c	Sun Dec 18 23:51:12 2016 +0100
+++ b/firmware/main.c	Mon Dec 19 00:11:30 2016 +0100
@@ -1,8 +1,53 @@
 #include "servo.h"
+#include <avr/io.h>
+
+
+#define I2C_ADDRESS 0x10
+#define I2C_BUFFER_SIZE 32
 
 
 int main() {
-    servo_setup(20000);
+    unsigned char i2c_buffer[I2C_BUFFER_SIZE];
+    unsigned char i2c_cursor = 0;
+    unsigned char servo;
+    union {
+        unsigned char bytes[2];
+        unsigned int value;
+    } bytes2int;
+
+    PORTC |= 1<<PC4 | 1<<PC5; // enable pullups
+    TWAR = I2C_ADDRESS<<1;
+    servo_setup();
+
     while (1) {
+        TWCR = 1<<TWEN | 1<<TWINT | 1<<TWEA;
+        while (!(TWCR & (1<<TWINT))) {}
+        switch (TWSR & 0xF8) {
+            case 0x60: // received address for write and acked
+                i2c_cursor = 0;
+                break;
+            case 0x80: // received data and acked
+            case 0x88: // received data and nacked
+                if (i2c_cursor < I2C_BUFFER_SIZE) {
+                    i2c_buffer[i2c_cursor++] = TWDR;
+                }
+            case 0xa0: // stop or repeated start received
+                if (i2c_cursor > 0) {
+                    servo = i2c_buffer[0];
+                    if (servo < 20) {
+                        for (unsigned char i = 1; i < i2c_cursor - 1; i += 2) {
+                            bytes2int.bytes[0] = i2c_buffer[i];
+                            bytes2int.bytes[1] = i2c_buffer[i + 1];
+                            servo_pulse[servo] = bytes2int.value;
+                            ++servo;
+                            if (servo >= 20) {
+                                servo = 0;
+                            }
+                        }
+                        servo_update();
+                    }
+                }
+                break;
+        }
     }
 }
--- a/firmware/servo.c	Sun Dec 18 23:51:12 2016 +0100
+++ b/firmware/servo.c	Mon Dec 19 00:11:30 2016 +0100
@@ -32,11 +32,6 @@
 }
 
 
-uint16_t servo_ticks(uint16_t us) {
-    return (((F_CPU / 1000000L) * us) / prescaler) & 0xfff0;
-}
-
-
 void servo_update() {
     uint16_t last_pulse = 0;
     for (uint8_t event = 0; event < 8; ++event) {
@@ -47,7 +42,7 @@
                     smallest_pulse = servo_pulse[servo];
             }
         }
-        servo_delay[event] = servo_ticks(smallest_pulse);
+        servo_delay[event] = smallest_pulse;
         servo_mask_b[event] = 0xff;
         for (uint8_t servo = 0; servo < 6; ++servo) {
             if (servo_pulse[servo] <= smallest_pulse) {
@@ -71,31 +66,13 @@
 }
 
 
-void servo_setup(uint16_t period) {
-    uint8_t mask;
-    if (period < (1 * 65535L / (F_CPU / 1000000L))) {
-	prescaler = 1;
-	mask = 1<<CS10;
-    } else if (period < (8 * 65535L / (F_CPU / 1000000L))) {
-	prescaler = 8;
-	mask = 1<<CS11;
-    } else if (period < (64 * 65535L / (F_CPU / 1000000L))) {
-	prescaler = 64;
-	mask = 1<<CS11 | 1<<CS10;
-    } else if (period < (256 * 65535L / (F_CPU / 1000000L))) {
-	prescaler = 256;
-	mask = 1<<CS12;
-    } else if (period < (1024 * 65535L / (F_CPU / 1000000L))) {
-	prescaler = 1024;
-	mask = 1<<CS12 | 1<<CS10;
-    } else {
-	prescaler = 1024;
-	mask = 1<<CS12 | 1<<CS10;
-    }
+void servo_setup() {
+    // period 20000
+    // prescaler 8
     TCCR1A = 0x00;
     TCCR1B &= ~(_BV(CS12) | _BV(CS11) | _BV(CS10));
-    TCCR1B |= mask;
-    OCR1A = servo_ticks(period);
+    TCCR1B |= 0x02;
+    OCR1A = 20000;
     TIMSK1 = _BV(OCIE1A) | _BV(OCIE1B);
     DDRD = 0xff;
     for (int i = 0; i < 8; ++i) {
--- a/firmware/servo.h	Sun Dec 18 23:51:12 2016 +0100
+++ b/firmware/servo.h	Mon Dec 19 00:11:30 2016 +0100
@@ -5,4 +5,4 @@
 
 
 void servo_update();
-void servo_setup(uint16_t period);
+void servo_setup();