Project

General

Profile

Statistics
| Branch: | Revision:

scoutos / scout_avr / bom / tiny-twi.c @ 16da2c8f

History | View | Annotate | Download (2.52 KB)

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4

    
5
#define RECV_BUF_SIZE 2
6

    
7
uint8_t address;
8

    
9
enum {
10
  IDLE,
11
  ADDRESS,
12
  SEND_READ_ACK,
13
  SEND_WRITE_ACK,
14
  SEND_DATA,
15
  RECV_DATA,
16
  RECV_ACK
17
} state;
18

    
19
uint8_t recv_idx;
20
uint8_t recv_data[RECV_BUF_SIZE];
21
slave_rx_t onDataRecieved;
22

    
23
static void twi_set_ctr(char n) {
24
  USISR &= ~0x0F;
25
  USISR |= n;
26
}
27

    
28
static void twi_release_scl() {
29
  DDRB &= ~_BV(DDB2);
30
}
31

    
32
static void twi_sink_sda() {
33
  DDRB |= _BV(DDB0);
34
}
35

    
36
static void twi_release_sda() {
37
  DDRB &= ~_BV(DDB0);
38
}
39

    
40
static void twi_ready() {
41

    
42
  // enable start condition interrupt
43
  USICR |= _BV(USISIE);
44

    
45
  // disable counter overflow interrupt
46
  USICR &= ~_BV(USIOIE);
47

    
48
  state = IDLE;
49
}
50

    
51
static void twi_start() {
52

    
53
  // zero counter
54
  twi_set_ctr(0);
55

    
56
  // enable counter overflow interrupt (fires after 8 bits)
57
  USICR |= _BV(USIOIE);
58

    
59
  state = ADDRESS;
60
  recv_idx = 0;
61
}
62

    
63
static void twi_send_ack(char is_read) {
64

    
65
  // set counter to 14
66
  twi_set_ctr(14);
67

    
68
  // set SDA low
69
  USIDR = 0;
70
  twi_sink_sda();
71

    
72
  // set state
73
  state = is_read? SEND_READ_ACK : SEND_WRITE_ACK;
74
}
75

    
76
ISR(USI_START_vect) {
77
  twi_start();
78
}
79

    
80
ISR(USI_OVF_vect) {
81
  uint8_t input = USIBR;
82
  switch (state) {
83

    
84
    case IDLE:
85
      // shouldn't reach here
86
      twi_ready();
87
      break;
88

    
89
    case ADDRESS:
90
      if (input >> 1 == address) {
91
        // send ack
92
        twi_send_ack(input & 1);
93
      } else {
94
        // go back to listening for start condition
95
        twi_ready();
96
      }
97
      break;
98

    
99
    case SEND_WRITE_ACK:
100
      twi_release_sda();
101
      state = RECV_DATA;
102
      break;
103

    
104
    case RECV_DATA:
105
      twi_send_ack(0);
106
      recv_data[recv_idx] = USIBR;
107
      recv_idx++;
108
      if (recv_idx == RECV_BUF_SIZE) {
109
        twi_ready();
110
        onDataRecieved(recv_data, RECV_BUF_SIZE);
111
      }
112
      break;
113

    
114
    case SEND_READ_ACK:
115
      twi_release_sda();
116
      // TODO write to USIDR
117
      state = SEND_DATA;
118
      break;
119

    
120
    case SEND_DATA:
121
      break;
122

    
123
    case RECV_ACK:
124
      break;
125
  }
126
  twi_release_scl();
127
}
128

    
129
<<<<<<< HEAD
130
void smb_init(slave_rx_t callback) {
131
  state = START;
132

    
133
=======
134
void smb_init() {
135
>>>>>>> Added sink/release sda/scl
136
  // TODO do we want USICS0 (3)?
137
  USICR = _BV(USIWM1) | _BV(USIWM0) | _BV(USICS1);
138
  twi_ready();
139
  onDataRecieved = callback;
140
}
141

    
142
void smb_set_address(uint8_t addr) {
143
  address = addr;
144
}
145

    
146
void testCB(uint8_t* data, int length) {
147
  PORTB |= _BV(PB4);
148
  if (data[0])
149
    _delay_ms(1000);
150
  else
151
    _delay_ms(500);
152
  PORTB &= ~_BV(PB4);
153
}
154

    
155

    
156
int main() {
157
  smb_set_address(5);
158
  DDRB |= _BV(DDB4);
159
  smb_init(testCB);
160
}