Project

General

Profile

Statistics
| Branch: | Revision:

root / scout_avr / bom / tiny-twi.c @ 6185434e

History | View | Annotate | Download (2.49 KB)

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
#include "tiny-twi.h"
5

    
6
#define SDA PB0
7
#define SCL PB2
8

    
9
#define RECV_BUF_SIZE 2
10

    
11
uint8_t address;
12

    
13
typedef enum {
14
  IDLE,
15
  ADDRESS,
16
  SEND_READ_ACK,
17
  SEND_WRITE_ACK,
18
  SEND_DATA,
19
  RECV_DATA,
20
  RECV_ACK
21
} state_t;
22

    
23
state_t state;
24
uint8_t recv_idx;
25
uint8_t recv_data[RECV_BUF_SIZE];
26
slave_rx_t onDataRecieved;
27

    
28
static void twi_set_ctr(char n) {
29
  USISR = n;
30
}
31

    
32
static void twi_ready() {
33
  USISR = _BV(USISIF) | _BV(USIOIF) | _BV(USIPF) | _BV(USIDC);
34
  DDRB |= _BV(SCL);  //SCL output
35
  DDRB &= ~_BV(SDA); //SDA input
36

    
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
  // enable counter overflow interrupt (fires after 8 bits)
48
  USICR |= _BV(USIOIE);
49

    
50
  USISR = _BV(USISIF);
51

    
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
  DDRB |= _BV(SDA);
67

    
68
  // set state
69
  state = is_read? SEND_READ_ACK : SEND_WRITE_ACK;
70
}
71

    
72
ISR(USI_START_vect) {
73
  twi_start();
74
}
75

    
76
ISR(USI_OVF_vect) {
77
  uint8_t input = USIDR; // TODO make sure this is correct
78
  switch (state) {
79

    
80
    case IDLE:
81
      // shouldn't reach here
82
      twi_ready();
83
      break;
84

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

    
95
    case SEND_WRITE_ACK:
96
      if (recv_idx == RECV_BUF_SIZE) {
97
        twi_ready();
98
        onDataRecieved(recv_data, RECV_BUF_SIZE);
99
      } else {
100
        DDRB &= ~_BV(SDA);
101
        state = RECV_DATA;
102
      }
103
      break;
104

    
105
    case RECV_DATA:
106
      twi_send_ack(0);
107
      recv_data[recv_idx] = input;
108
      recv_idx++;
109
      break;
110

    
111
    case SEND_READ_ACK:
112
      DDRB &= ~_BV(SDA);
113
      // 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
  USISR = _BV(USIOIF) | (USISR & 0xF);
124
}
125

    
126
void smb_init(slave_rx_t callback) {
127
  // TODO do we want USICS0 (3)?
128
  USICR = _BV(USIWM1) | _BV(USIWM0) | _BV(USICS1);
129
  PORTB |= _BV(SDA) | _BV(SCL);
130
  twi_ready();
131
  onDataRecieved = callback;
132
}
133

    
134
void smb_set_address(uint8_t addr) {
135
  address = addr;
136
}
137

    
138
void testCB(uint8_t* data, int length) {
139
}
140

    
141

    
142
int main() {
143
  sei();
144
  smb_set_address(5);
145
  DDRB |= _BV(DDB4);
146
  smb_init(testCB);
147
  while(1);
148
}