Mercurial > d1-mini-20ch-servo
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) {
