Project

General

Profile

Statistics
| Branch: | Revision:

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
}