]> git.donarmstrong.com Git - qmk_firmware.git/commitdiff
Add I2C slave library
authoryiancar <yiangosyiangou@cytanet.com.cy>
Thu, 12 Jul 2018 08:50:55 +0000 (11:50 +0300)
committerJack Humbert <jack.humb@gmail.com>
Sun, 15 Jul 2018 17:00:50 +0000 (13:00 -0400)
- Add I2C slave library for general use.

drivers/avr/i2c_slave.c [new file with mode: 0755]
drivers/avr/i2c_slave.h [new file with mode: 0755]

diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c
new file mode 100755 (executable)
index 0000000..3edf85b
--- /dev/null
@@ -0,0 +1,100 @@
+/* Library made by: g4lvanix
+ * Github repository: https://github.com/g4lvanix/I2C-slave-lib
+ */
+
+#include <avr/io.h>
+#include <util/twi.h>
+#include <avr/interrupt.h>
+
+#include "i2c_slave.h"
+
+void i2c_init(uint8_t address){
+       // load address into TWI address register
+       TWAR = (address << 1);
+       // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
+       TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN);
+}
+
+void i2c_stop(void){
+       // clear acknowledge and enable bits
+       TWCR &= ~( (1<<TWEA) | (1<<TWEN) );
+}
+
+ISR(TWI_vect){
+       
+       // temporary stores the received data
+       uint8_t data;
+       
+       // own address has been acknowledged
+       if( (TWSR & 0xF8) == TW_SR_SLA_ACK ){  
+               buffer_address = 0xFF;
+               // clear TWI interrupt flag, prepare to receive next byte and acknowledge
+               TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); 
+       }
+       else if( (TWSR & 0xF8) == TW_SR_DATA_ACK ){ // data has been received in slave receiver mode
+               
+               // save the received byte inside data 
+               data = TWDR;
+               
+               // check wether an address has already been transmitted or not
+               if(buffer_address == 0xFF){
+                       
+                       buffer_address = data; 
+                       
+                       // clear TWI interrupt flag, prepare to receive next byte and acknowledge
+                       TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); 
+               }
+               else{ // if a databyte has already been received
+                       
+                       // store the data at the current address
+                       rxbuffer[buffer_address] = data;
+                       
+                       // increment the buffer address
+                       buffer_address++;
+                       
+                       // if there is still enough space inside the buffer
+                       if(buffer_address < 0xFF){
+                               // clear TWI interrupt flag, prepare to receive next byte and acknowledge
+                               TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); 
+                       }
+                       else{
+                               // Don't acknowledge
+                               TWCR &= ~(1<<TWEA); 
+                               // clear TWI interrupt flag, prepare to receive last byte.
+                               TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEN); 
+                       }
+               }
+       }
+       else if( (TWSR & 0xF8) == TW_ST_DATA_ACK ){ // device has been addressed to be a transmitter
+               
+               // copy data from TWDR to the temporary memory
+               data = TWDR;
+               
+               // if no buffer read address has been sent yet
+               if( buffer_address == 0xFF ){
+                       buffer_address = data;
+               }
+               
+               // copy the specified buffer address into the TWDR register for transmission
+               TWDR = txbuffer[buffer_address];
+               // increment buffer read address
+               buffer_address++;
+               
+               // if there is another buffer address that can be sent
+               if(buffer_address < 0xFF){
+                       // clear TWI interrupt flag, prepare to send next byte and receive acknowledge
+                       TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); 
+               }
+               else{
+                       // Don't acknowledge
+                       TWCR &= ~(1<<TWEA); 
+                       // clear TWI interrupt flag, prepare to receive last byte.
+                       TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEN); 
+               }
+               
+       }
+       else{
+               // if none of the above apply prepare TWI to be addressed again
+               TWCR |= (1<<TWIE) | (1<<TWEA) | (1<<TWEN);
+       } 
+}
diff --git a/drivers/avr/i2c_slave.h b/drivers/avr/i2c_slave.h
new file mode 100755 (executable)
index 0000000..3fda7f8
--- /dev/null
@@ -0,0 +1,19 @@
+/* Library made by: g4lvanix
+ * Github repository: https://github.com/g4lvanix/I2C-slave-lib
+
+ Info: Inititate the library by giving the required address.
+       Read or write to the necessary buffer according to the opperation.
+ */
+
+#ifndef I2C_SLAVE_H
+#define I2C_SLAVE_H
+
+volatile uint8_t buffer_address;
+volatile uint8_t txbuffer[0xFF];
+volatile uint8_t rxbuffer[0xFF];
+
+void i2c_init(uint8_t address);
+void i2c_stop(void);
+ISR(TWI_vect);
+
+#endif // I2C_SLAVE_H