-
Notifications
You must be signed in to change notification settings - Fork 24
/
I2CSlave.c
62 lines (56 loc) · 1.44 KB
/
I2CSlave.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <util/twi.h>
#include <avr/interrupt.h>
#include "I2CSlave.h"
static void (*I2C_recv)(uint8_t);
static void (*I2C_req)();
void I2C_setCallbacks(void (*recv)(uint8_t), void (*req)())
{
I2C_recv = recv;
I2C_req = req;
}
void I2C_init(uint8_t address)
{
cli();
// 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);
sei();
}
void I2C_stop(void)
{
// clear acknowledge and enable bits
cli();
TWCR = 0;
TWAR = 0;
sei();
}
ISR(TWI_vect)
{
switch(TW_STATUS)
{
case TW_SR_DATA_ACK:
// received data from master, call the receive callback
I2C_recv(TWDR);
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_ST_SLA_ACK:
// master is requesting data, call the request callback
I2C_req();
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_ST_DATA_ACK:
// master is requesting data, call the request callback
I2C_req();
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
case TW_BUS_ERROR:
// some sort of erroneous state, prepare TWI to be readdressed
TWCR = 0;
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
default:
TWCR = (1<<TWIE) | (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
break;
}
}