Cómo configurar NACK justo después del byte actual en TWI (ATMega8)

Tengo algo de experiencia con I²C (TWI) como lo usé antes, pero parece que no puedo resolver este problema en particular. Tengo la intención de comunicar dos CPU a través de I²C. Uno es siempre el amo y el otro es el esclavo. Estoy definiendo el protocolo de comunicación yo mismo, por lo que es algo flexible, pero tengo la intención de que sea lo más eficiente posible (es decir, cuantos menos bytes, mejor).

Quiero que el esclavo configure NACK para ciertos valores; por ejemplo:

MASTER = START + sends SLAVE ADDRESS
SLAVE = sets ACK
MASTER = sends any one "byte" command
SLAVE = sets ACK or NACK depending if "byte" was a valid command or not.

La última declaración es el problema, porque aparentemente yo, como esclavo, tengo que decidirme por ACK o NACK antes de recibir el comando de un "byte"; es decir, en respuesta a TWSR = 0x60 (SLA+W recibido). El problema es que no sé de antemano si el comando será válido o no. Aparentemente, establecer o borrar el bit TWEA solo es efectivo para recibir el siguiente byte.

Por mucho que investigué en los documentos, no puedo encontrar una manera de responder con NACK "sobre la marcha" porque ATMega establece la interrupción DESPUÉS de enviar el ACK (o NACK). TWSR será 0x80 o 0x88, lo que significa "byte recibido, ACK enviado" y "byte recibido, NACK enviado", respectivamente.

Además de agregar bytes de relleno o implementar una biblioteca I²C de bits, ¿hay alguna forma de resolver esto?

El controlador maestro es un NXP LPC2148, mientras que el controlador esclavo es un ATMega1284P.

Gracias.

Respuestas (1)

¡Por favor, no hagas eso! Eso no es para lo que están destinados los I²C ACK/NACK. Se entienden como elementos de protocolo, no como parte de los datos.

Por ejemplo, un NACK recibido al enviar la dirección del dispositivo hará que el controlador del host señale un "Error de direccionamiento", y un NACK recibido durante una transferencia de N bytes hará que el controlador del host señale un "Error de transmisión de datos" al controlador que llama. Es decir, la cantidad de bytes enviados fue incorrecta o la suma de verificación de SMBUS falló.

Durante las transmisiones de lectura, el NACK generalmente indica el final de los datos para recibir.

¿Es eso lo que quieres señalar? ¡Apuesto a que no!

EDITAR: Te doy un ejemplo. Eche un vistazo al puente maestro DS28E17 Onewire a I²C. Es un controlador de host I²C que reside en un bus de un solo cable. Hace toda la comunicación I²C de forma autónoma y no puedes ( no puedes ) recibir ACK/NACK individuales. Le aconsejas a ese chip que escriba una cantidad de bytes y lo hará felizmente. Pero no le dirá si el último bit fue ACK o NACK. Solo puede decirle si hubo un NACK inesperado. Entonces, su esclavo rompe el protocolo y no puede usarse detrás de un DS28E17.

Sin embargo, no parece ser el caso. Leí en el (*UM10204 I2C-bus especificación y manual de usuario) lo siguiente: "Hay cinco condiciones que conducen a la generación de un NACK: [...] 3. Durante la transferencia, el receptor recibe datos o comandos que no entiende. 4. Durante la transferencia, el receptor no puede recibir más bytes de datos. [...]". Tengo la intención de usarlo tanto para [3] como para [4].
El hecho de que haya dispositivos que no hagan eso (quizás el AVR incluido) no significa que no se pueda o no se deba hacer.
Es el uso práctico lo que cuenta. Eche un vistazo a las diversas peculiaridades que el kernel de Linux tiene que implementar para admitir la gran cantidad de adaptadores de host y dispositivos dañados. Todos están rotos porque sus diseñadores dijeron "la especificación lo permite" y luego, usan todo lo que la especificación permite al máximo. Así es como envías a tus usuarios directamente a la perdición. ¡Por favor, no hagas eso! Por favor, diseñe un dispositivo que sea más compatible con el pandemónium que ya está en libertad.
Este no es un caso de "las especificaciones no lo niegan, por lo que está permitido". Esto está explícito en la especificación como un uso previsto de la señal NACK. Su respuesta "Eso no es para lo que están destinados los I²C ACK/NACK" es su opinión personal (que es irrelevante para mi pregunta) o simplemente incorrecta.
@Guillermo Prandi: Continúe con su trabajo de desarrollo en paz y, por favor, niéguese a dejarme mirarlo más. Gracias.
Solo para reír, SC16IS741A (interfaz I²C a UART) de NXP hace exactamente lo que quiero hacer: establece NACK cuando su búfer está lleno. Solo quiero emular ese comportamiento de mi ATmega.