aboutsummaryrefslogtreecommitdiff
path: root/drivers/avr/i2c_slave.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/avr/i2c_slave.c')
-rwxr-xr-xdrivers/avr/i2c_slave.c134
1 files changed, 51 insertions, 83 deletions
diff --git a/drivers/avr/i2c_slave.c b/drivers/avr/i2c_slave.c
index 3edf85b12..27696ca01 100755
--- a/drivers/avr/i2c_slave.c
+++ b/drivers/avr/i2c_slave.c
@@ -5,96 +5,64 @@
5#include <avr/io.h> 5#include <avr/io.h>
6#include <util/twi.h> 6#include <util/twi.h>
7#include <avr/interrupt.h> 7#include <avr/interrupt.h>
8#include <stdbool.h>
8 9
9#include "i2c_slave.h" 10#include "i2c_slave.h"
10 11
11void i2c_init(uint8_t address){ 12void i2c_init(uint8_t address){
12 // load address into TWI address register 13 // load address into TWI address register
13 TWAR = (address << 1); 14 TWAR = (address << 1);
14 // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt 15 // set the TWCR to enable address matching and enable TWI, clear TWINT, enable TWI interrupt
15 TWCR = (1<<TWIE) | (1<<TWEA) | (1<<TWINT) | (1<<TWEN); 16 TWCR = (1 << TWIE) | (1 << TWEA) | (1 << TWINT) | (1 << TWEN);
16} 17}
17 18
18void i2c_stop(void){ 19void i2c_stop(void){
19 // clear acknowledge and enable bits 20 // clear acknowledge and enable bits
20 TWCR &= ~( (1<<TWEA) | (1<<TWEN) ); 21 TWCR &= ~((1 << TWEA) | (1 << TWEN));
21} 22}
22 23
23ISR(TWI_vect){ 24ISR(TWI_vect){
24 25 uint8_t ack = 1;
25 // temporary stores the received data 26 // temporary stores the received data
26 uint8_t data; 27 //uint8_t data;
27 28
28 // own address has been acknowledged 29 switch(TW_STATUS){
29 if( (TWSR & 0xF8) == TW_SR_SLA_ACK ){ 30 case TW_SR_SLA_ACK:
30 buffer_address = 0xFF; 31 // The device is now a slave receiver
31 // clear TWI interrupt flag, prepare to receive next byte and acknowledge 32 slave_has_register_set = false;
32 TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); 33 break;
33 } 34
34 else if( (TWSR & 0xF8) == TW_SR_DATA_ACK ){ // data has been received in slave receiver mode 35 case TW_SR_DATA_ACK:
35 36 // This device is a slave receiver and has received data
36 // save the received byte inside data 37 // First byte is the location then the bytes will be writen in buffer with auto-incriment
37 data = TWDR; 38 if(!slave_has_register_set){
38 39 buffer_address = TWDR;
39 // check wether an address has already been transmitted or not 40
40 if(buffer_address == 0xFF){ 41 if (buffer_address >= RX_BUFFER_SIZE){ // address out of bounds dont ack
41 42 ack = 0;
42 buffer_address = data; 43 buffer_address = 0;
43 44 }
44 // clear TWI interrupt flag, prepare to receive next byte and acknowledge 45 slave_has_register_set = true; // address has been receaved now fill in buffer
45 TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); 46 } else {
46 } 47 rxbuffer[buffer_address] = TWDR;
47 else{ // if a databyte has already been received 48 buffer_address++;
48 49 }
49 // store the data at the current address 50 break;
50 rxbuffer[buffer_address] = data; 51
51 52 case TW_ST_SLA_ACK:
52 // increment the buffer address 53 case TW_ST_DATA_ACK:
53 buffer_address++; 54 // This device is a slave transmitter and master has requested data
54 55 TWDR = txbuffer[buffer_address];
55 // if there is still enough space inside the buffer 56 buffer_address++;
56 if(buffer_address < 0xFF){ 57 break;
57 // clear TWI interrupt flag, prepare to receive next byte and acknowledge 58
58 TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN); 59 case TW_BUS_ERROR:
59 } 60 // We got an error, reset i2c
60 else{ 61 TWCR = 0;
61 // Don't acknowledge 62 default:
62 TWCR &= ~(1<<TWEA); 63 break;
63 // clear TWI interrupt flag, prepare to receive last byte. 64 }
64 TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEN); 65
65 } 66 // Reset i2c state mahcine to be ready for next interrupt
66 } 67 TWCR |= (1 << TWIE) | (1 << TWINT) | (ack << TWEA) | (1 << TWEN);
67 } 68} \ No newline at end of file
68 else if( (TWSR & 0xF8) == TW_ST_DATA_ACK ){ // device has been addressed to be a transmitter
69
70 // copy data from TWDR to the temporary memory
71 data = TWDR;
72
73 // if no buffer read address has been sent yet
74 if( buffer_address == 0xFF ){
75 buffer_address = data;
76 }
77
78 // copy the specified buffer address into the TWDR register for transmission
79 TWDR = txbuffer[buffer_address];
80 // increment buffer read address
81 buffer_address++;
82
83 // if there is another buffer address that can be sent
84 if(buffer_address < 0xFF){
85 // clear TWI interrupt flag, prepare to send next byte and receive acknowledge
86 TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
87 }
88 else{
89 // Don't acknowledge
90 TWCR &= ~(1<<TWEA);
91 // clear TWI interrupt flag, prepare to receive last byte.
92 TWCR |= (1<<TWIE) | (1<<TWINT) | (1<<TWEN);
93 }
94
95 }
96 else{
97 // if none of the above apply prepare TWI to be addressed again
98 TWCR |= (1<<TWIE) | (1<<TWEA) | (1<<TWEN);
99 }
100}