Project

General

Profile

Revision c4f160ba

IDc4f160bab94b3c0ac252b588a6f70c350302c038
Parent c7445989
Child 7327a8ed

Added by Thomas Mullins over 10 years ago

Adding partly finished attiny i2c code

View differences:

scout_avr/bom/tiny-twi.c
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

  
4
#define RECV_BUF_SIZE 2
5

  
6
uint8_t address;
7

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

  
18
uint8_t recv_idx;
19
uint8_t recv_data[RECV_BUF_SIZE];
20

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

  
26
static void twi_ready() {
27

  
28
  // enable start condition interrupt
29
  USICR |= _BV(USISIE);
30

  
31
  // disable counter overflow interrupt
32
  USICR &= ~_BV(USIOIE);
33

  
34
  // TODO somehow release SCL following the ovf interrupt
35

  
36
  state = IDLE;
37
}
38

  
39
static void twi_start() {
40

  
41
  // zero counter
42
  twi_set_ctr(0);
43

  
44
  // enable counter overflow interrupt (fires after 8 bits)
45
  USICR |= _BV(USIOIE);
46

  
47
  state = ADDRESS;
48
  recv_idx = 0;
49
}
50

  
51
static void twi_send_ack(char is_read) {
52

  
53
  // set counter to 14
54
  twi_set_ctr(14);
55

  
56
  // set SDA low
57
  USIDR = 0;
58

  
59
  // set state
60
  state = is_read? SEND_READ_ACK : SEND_WRITE_ACK;
61
}
62

  
63
ISR(USI_START_vect) {
64
  twi_start();
65
}
66

  
67
ISR(USI_OVF_vect) {
68
  uint8_t input = USIBR;
69
  switch (state) {
70

  
71
    case IDLE:
72
      // shouldn't reach here
73
      twi_ready();
74
      break;
75

  
76
    case ADDRESS:
77
      if (input >> 1 == address) {
78
        // send ack
79
        twi_send_ack(input & 1);
80
      } else {
81
        // go back to listening for start condition
82
        twi_ready();
83
      }
84
      break;
85

  
86
    case SEND_WRITE_ACK:
87
      state = RECV_DATA;
88
      break;
89

  
90
    case RECV_DATA:
91
      twi_send_ack(0);
92
      recv_data[recv_idx] = USIBR;
93
      recv_idx++;
94
      if (recv_idx == RECV_BUF_SIZE) {
95
        twi_ready();
96
        // TODO callback
97
      }
98
      break;
99

  
100
    case SEND_READ_ACK:
101
      // TODO write to USIDR
102
      state = SEND_DATA;
103
      break;
104

  
105
    case SEND_DATA:
106
      break;
107

  
108
    case RECV_ACK:
109
      break;
110
  }
111
}
112

  
113
void smb_init() {
114
  state = START;
115

  
116
  // TODO do we want USICS0 (3)?
117
  USICR = _BV(USIWM1) | _BV(USIWM0) | _BV(USICS1);
118
  twi_ready();
119
}
120

  
121
void smb_set_address(uint8_t addr) {
122
  address = addr;
123
}

Also available in: Unified diff