]> git.donarmstrong.com Git - qmk_firmware.git/blob - drivers/avr/i2c_slave.c
DC01 keyboard addition (#3428)
[qmk_firmware.git] / drivers / avr / i2c_slave.c
1 /* Library made by: g4lvanix
2  * Github repository: https://github.com/g4lvanix/I2C-slave-lib
3  */
4
5 #include <avr/io.h>
6 #include <util/twi.h>
7 #include <avr/interrupt.h>
8 #include <stdbool.h>
9
10 #include "i2c_slave.h"
11
12 void i2c_init(uint8_t address){
13     // load address into TWI address register
14     TWAR = (address << 1);
15     // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
16     TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN);
17 }
18
19 void i2c_stop(void){
20     // clear acknowledge and enable bits
21     TWCR &= ~((1 << TWEA) | (1 << TWEN));
22 }
23
24 ISR(TWI_vect){
25     uint8_t ack = 1;
26     // temporary stores the received data
27     //uint8_t data;
28     
29     switch(TW_STATUS){
30         case TW_SR_SLA_ACK:
31             // The device is now a slave receiver
32             slave_has_register_set = false;
33             break;
34
35         case TW_SR_DATA_ACK:
36             // This device is a slave receiver and has received data
37             // First byte is the location then the bytes will be writen in buffer with auto-incriment
38             if(!slave_has_register_set){
39                 buffer_address = TWDR;
40
41                 if (buffer_address >= RX_BUFFER_SIZE){ // address out of bounds dont ack
42                     ack = 0;
43                     buffer_address = 0;
44                 }
45                 slave_has_register_set = true; // address has been receaved now fill in buffer
46             } else {
47                 rxbuffer[buffer_address] = TWDR;
48                 buffer_address++;
49             }
50             break;
51
52         case TW_ST_SLA_ACK:
53         case TW_ST_DATA_ACK:
54             // This device is a slave transmitter and master has requested data
55             TWDR = txbuffer[buffer_address];
56             buffer_address++;
57             break;
58
59         case TW_BUS_ERROR:
60             // We got an error, reset i2c
61             TWCR = 0;
62         default:
63             break;
64     }
65
66     // Reset i2c state mahcine to be ready for next interrupt
67     TWCR |= (1 << TWIE) | (1 << TWINT) | (ack << TWEA) | (1 << TWEN);
68 }