From b60a0fe735141a33a225330cd5685a48816f93f7 Mon Sep 17 00:00:00 2001 From: Olaf Rempel Date: Sun, 3 Nov 2019 18:21:12 +0100 Subject: [PATCH] Simplify ACK handling TWEA bit in TWCR register needs to be cleared to send NACK. Clear it when too many bytes were received, re-enable it after when going idle. Add missing state for prev. send NACK. Catch all invalid states and reset bus. TWINT bit needs to be set every time in ISR. --- README.md | 8 ++++---- main.c | 23 +++++++++++------------ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d391857..16a870a 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,10 @@ Currently the following AVR MCUs are supported: AVR MCU | Flash bytes used (.text + .data) | Bootloader region size --- | --- | --- -atmega8 | 868 (0x364) | 512 words -atmega88 | 920 (0x398) | 512 words -atmega168 | 972 (0x3CC) | 512 words -atmega328p | 972 (0x3CC) | 512 words +atmega8 | 872 (0x368) | 512 words +atmega88 | 918 (0x396) | 512 words +atmega168 | 970 (0x3CA) | 512 words +atmega328p | 970 (0x3CA) | 512 words (Compiled on Ubuntu 18.04 LTS (gcc 5.4.0 / avr-libc 2.0.0) with EEPROM and LED support) diff --git a/main.c b/main.c index 66a8f92..8ee42ed 100644 --- a/main.c +++ b/main.c @@ -358,6 +358,7 @@ static uint8_t TWI_data_read(uint8_t bcnt) ISR(TWI_vect) { static uint8_t bcnt; + uint8_t control = TWCR; switch (TWSR & 0xF8) { @@ -365,18 +366,13 @@ ISR(TWI_vect) case 0x60: bcnt = 0; LED_RT_ON(); - TWCR |= (1< receive data and ACK */ case 0x80: - if (TWI_data_write(bcnt++, TWDR)) + if (TWI_data_write(bcnt++, TWDR) == 0x00) { - TWCR |= (1< send data */ case 0xB8: TWDR = TWI_data_read(bcnt++); - TWCR |= (1< IDLE */ + case 0x88: /* STOP or repeated START -> IDLE */ case 0xA0: /* prev. SLA+R, data sent, NACK returned -> IDLE */ case 0xC0: LED_RT_OFF(); - TWCR |= (1< reset hardware */ - case 0xF8: - TWCR |= (1< reset hardware */ + default: + control |= (1<