I want to implement the SMBUS protocol in my AVR device (ATMega1284P), which will have the role of slave. I need to support the PEC (Packet Error Code) feature, which means that the master device (which is not mine) will send a "checksum" byte after the last byte of its command, to which I need to respond with ACK or NACK depending on its validity.
I have some experience with I²C/SMBUS/TWI as I used it before, but it seems I can't solve this particular problem. Apparently, with AVR's TWI implementation I need to decide for ACK or NACK in the byte received prior to the PEC value; i.e., in response to a previous TWSR = 0x80 (data has been received). The problem is, I don't know in advance if the PEC I will be receiving next will be valid or not! Apparently setting or clearing the TWEA bit is only effective for the next byte to be received. Example:
1 - ME = Prepare for TWI slave operation; set address and ACK 2 - MASTER = Writes SLA+W (gets ACK from step #1) 3 - ME = INT with TWSR 0x60; Sets ACK/NACK for next byte (ACK) 4 - MASTER = Sends Byte (gets ACK/NACK from step #3) 5 - ME = INT with TWSR 0x80; Sets ACK/NACK for next byte (ACK) 6 - MASTER = Sends Byte (gets ACK/NACK from step #5) 7 - ME = INT with TWSR 0x80; Sets ACK/NACK for next byte (ACK) 8 - MASTER = Sends PEC Byte (gets ACK/NACK from step #7) 9 - ME = INT with TWSR 0x80 (PEC); too late to ACK/NACK PEC value!
As you can see, I should decide for ACK/NACK in step #9, but the master's already got an ACK set at step #7!
As much as I digged into the docs, I cannot find a way to respond with NACK "on the fly" because the ATMega sets the interrupt AFTER sending the ACK (or NACK). TWSR will be either 0x80 or 0x88, which means "byte received, ACK sent" and "byte received, NACK sent" respectively.
Aside from implementing a bit-banging SMBUS library, is there some way to solve this?