root / scout_avr / bom / tiny-twi.c @ 797244ed
History | View | Annotate | Download (2.58 KB)
1 | c4f160ba | Tom Mullins | #include <avr/io.h> |
---|---|---|---|
2 | #include <avr/interrupt.h> |
||
3 | 0167b233 | Aaron Perley | #include <util/delay.h> |
4 | 08af0896 | Tom Mullins | #include "tiny-twi.h" |
5 | c4f160ba | Tom Mullins | |
6 | 797244ed | Aaron Perley | #define SDA PB0
|
7 | #define SCL PB2
|
||
8 | |||
9 | c4f160ba | Tom Mullins | #define RECV_BUF_SIZE 2 |
10 | |||
11 | uint8_t address; |
||
12 | |||
13 | 08af0896 | Tom Mullins | typedef enum { |
14 | c4f160ba | Tom Mullins | IDLE, |
15 | ADDRESS, |
||
16 | SEND_READ_ACK, |
||
17 | SEND_WRITE_ACK, |
||
18 | SEND_DATA, |
||
19 | RECV_DATA, |
||
20 | RECV_ACK |
||
21 | 08af0896 | Tom Mullins | } state_t; |
22 | c4f160ba | Tom Mullins | |
23 | 08af0896 | Tom Mullins | state_t state; |
24 | c4f160ba | Tom Mullins | uint8_t recv_idx; |
25 | uint8_t recv_data[RECV_BUF_SIZE]; |
||
26 | 0167b233 | Aaron Perley | slave_rx_t onDataRecieved; |
27 | c4f160ba | Tom Mullins | |
28 | static void twi_set_ctr(char n) { |
||
29 | 797244ed | Aaron Perley | USISR = n; |
30 | 16da2c8f | Tom Mullins | } |
31 | |||
32 | c4f160ba | Tom Mullins | static void twi_ready() { |
33 | 797244ed | Aaron Perley | USISR = _BV(USISIF) | _BV(USIOIF) | _BV(USIPF) | _BV(USIDC); |
34 | DDRB |= _BV(SCL); //SCL output
|
||
35 | DDRB &= ~_BV(SDA); //SDA input
|
||
36 | c4f160ba | Tom Mullins | |
37 | // enable start condition interrupt
|
||
38 | USICR |= _BV(USISIE); |
||
39 | |||
40 | // disable counter overflow interrupt
|
||
41 | USICR &= ~_BV(USIOIE); |
||
42 | |||
43 | state = IDLE; |
||
44 | } |
||
45 | |||
46 | static void twi_start() { |
||
47 | 797244ed | Aaron Perley | // enable counter overflow interrupt (fires after 8 bits)
|
48 | USICR |= _BV(USIOIE); |
||
49 | |||
50 | USISR = _BV(USISIF); |
||
51 | c4f160ba | Tom Mullins | |
52 | // zero counter
|
||
53 | twi_set_ctr(0);
|
||
54 | |||
55 | state = ADDRESS; |
||
56 | recv_idx = 0;
|
||
57 | } |
||
58 | |||
59 | static void twi_send_ack(char is_read) { |
||
60 | |||
61 | // set counter to 14
|
||
62 | twi_set_ctr(14);
|
||
63 | |||
64 | // set SDA low
|
||
65 | USIDR = 0;
|
||
66 | 797244ed | Aaron Perley | DDRB |= _BV(SDA); |
67 | c4f160ba | Tom Mullins | |
68 | // set state
|
||
69 | state = is_read? SEND_READ_ACK : SEND_WRITE_ACK; |
||
70 | } |
||
71 | |||
72 | ISR(USI_START_vect) { |
||
73 | 797244ed | Aaron Perley | PORTB |= _BV(PB4); // DEBUG: LED ON
|
74 | c4f160ba | Tom Mullins | twi_start(); |
75 | } |
||
76 | |||
77 | ISR(USI_OVF_vect) { |
||
78 | uint8_t input = USIBR; |
||
79 | switch (state) {
|
||
80 | |||
81 | case IDLE:
|
||
82 | // shouldn't reach here
|
||
83 | twi_ready(); |
||
84 | break;
|
||
85 | |||
86 | case ADDRESS:
|
||
87 | if (input >> 1 == address) { |
||
88 | // send ack
|
||
89 | twi_send_ack(input & 1);
|
||
90 | } else {
|
||
91 | // go back to listening for start condition
|
||
92 | twi_ready(); |
||
93 | } |
||
94 | break;
|
||
95 | |||
96 | case SEND_WRITE_ACK:
|
||
97 | 797244ed | Aaron Perley | DDRB &= ~_BV(SDA); |
98 | c4f160ba | Tom Mullins | state = RECV_DATA; |
99 | break;
|
||
100 | |||
101 | case RECV_DATA:
|
||
102 | twi_send_ack(0);
|
||
103 | recv_data[recv_idx] = USIBR; |
||
104 | recv_idx++; |
||
105 | if (recv_idx == RECV_BUF_SIZE) {
|
||
106 | twi_ready(); |
||
107 | 0167b233 | Aaron Perley | onDataRecieved(recv_data, RECV_BUF_SIZE); |
108 | c4f160ba | Tom Mullins | } |
109 | break;
|
||
110 | |||
111 | case SEND_READ_ACK:
|
||
112 | 797244ed | Aaron Perley | DDRB &= ~_BV(SDA); |
113 | c4f160ba | Tom Mullins | // TODO write to USIDR
|
114 | state = SEND_DATA; |
||
115 | break;
|
||
116 | |||
117 | case SEND_DATA:
|
||
118 | break;
|
||
119 | |||
120 | case RECV_ACK:
|
||
121 | break;
|
||
122 | } |
||
123 | 797244ed | Aaron Perley | USISR = _BV(USIOIF) | (USISR & 0xF);
|
124 | c4f160ba | Tom Mullins | } |
125 | |||
126 | 0167b233 | Aaron Perley | void smb_init(slave_rx_t callback) {
|
127 | c4f160ba | Tom Mullins | // TODO do we want USICS0 (3)?
|
128 | USICR = _BV(USIWM1) | _BV(USIWM0) | _BV(USICS1); |
||
129 | 797244ed | Aaron Perley | PORTB |= _BV(SDA) | _BV(SCL); |
130 | c4f160ba | Tom Mullins | twi_ready(); |
131 | 0167b233 | Aaron Perley | onDataRecieved = callback; |
132 | c4f160ba | Tom Mullins | } |
133 | |||
134 | void smb_set_address(uint8_t addr) {
|
||
135 | address = addr; |
||
136 | } |
||
137 | 0167b233 | Aaron Perley | |
138 | void testCB(uint8_t* data, int length) { |
||
139 | PORTB |= _BV(PB4); |
||
140 | if (data[0]) |
||
141 | _delay_ms(1000);
|
||
142 | else
|
||
143 | _delay_ms(500);
|
||
144 | PORTB &= ~_BV(PB4); |
||
145 | } |
||
146 | |||
147 | |||
148 | int main() {
|
||
149 | 797244ed | Aaron Perley | sei(); |
150 | 0167b233 | Aaron Perley | smb_set_address(5);
|
151 | DDRB |= _BV(DDB4); |
||
152 | smb_init(testCB); |
||
153 | 797244ed | Aaron Perley | while(1); |
154 | } |