#include "../avr-i2c-slave/I2CSlave.h" #include #include #include #define I2C_ADDR 0x20 volatile uint8_t challenge = 0; // Use 0 as 'challenge not sent' condition uint8_t check_challenge(uint8_t arg) { return (arg >> 3) ^ (arg << 3); } void I2C_received(uint8_t received_data) { if (challenge != 0) { if (check_challenge(received_data) == check_challenge(challenge)) { // Check validity of response // Open lock PORTC |= 2 << 1; _delay_ms(5000); PORTC = 0; } } challenge = 0; } void I2C_requested() { challenge = (uint8_t)(TCNT1 & 0xff); // Use content of timer as pseudo-random number if (challenge == 0) // Prevent 'challenge' from being 0, which has a special meaning challenge = 1; I2C_transmitByte(challenge); } void setup() { // set received/requested callbacks I2C_setCallbacks(I2C_received, I2C_requested); // init I2C I2C_init(I2C_ADDR); // init output gpio DDRC = 0b00000100; // PC2 TCNT1 = 0; TCCR1B |= (1 << CS10) | (1 << CS11); // No prescaling } int main() { setup(); while (1); // All the work is done in the callbacks }