1 /* Copyright (C) 2019 Elia Ritterbusch
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 /* Library made by: g4lvanix
17 * Github repository: https://github.com/g4lvanix/I2C-slave-lib
22 #include <avr/interrupt.h>
25 #include "i2c_slave.h"
27 volatile uint8_t i2c_slave_reg[I2C_SLAVE_REG_COUNT];
29 static volatile uint8_t buffer_address;
30 static volatile bool slave_has_register_set = false;
32 void i2c_slave_init(uint8_t address){
33 // load address into TWI address register
35 // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
36 TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN);
39 void i2c_slave_stop(void){
40 // clear acknowledge and enable bits
41 TWCR &= ~((1 << TWEA) | (1 << TWEN));
49 // The device is now a slave receiver
50 slave_has_register_set = false;
54 // This device is a slave receiver and has received data
55 // First byte is the location then the bytes will be writen in buffer with auto-incriment
56 if(!slave_has_register_set){
57 buffer_address = TWDR;
59 if (buffer_address >= I2C_SLAVE_REG_COUNT) { // address out of bounds dont ack
63 slave_has_register_set = true; // address has been receaved now fill in buffer
65 i2c_slave_reg[buffer_address] = TWDR;
72 // This device is a slave transmitter and master has requested data
73 TWDR = i2c_slave_reg[buffer_address];
78 // We got an error, reset i2c
84 // Reset i2c state machine to be ready for next interrupt
85 TWCR |= (1 << TWIE) | (1 << TWINT) | (ack << TWEA) | (1 << TWEN);