]>
Commit | Line | Data |
---|---|---|
99e4226b MG |
1 | #include <util/twi.h> |
2 | #include <avr/interrupt.h> | |
3 | #include <stdio.h> | |
4 | #include "i2c.h" | |
da7751cb | 5 | #include "bmc.h" |
d5193055 | 6 | #include "ipmb.h" |
99e4226b MG |
7 | |
8 | #define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC); | |
9 | #define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC); | |
10 | #define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWWC); | |
11 | ||
45320371 | 12 | volatile unsigned char i2c_databuf[24]; |
da7751cb MG |
13 | volatile uint8_t i2c_len = 0x00; |
14 | static volatile uint8_t i2c_pos = 0x00; | |
15 | volatile uint8_t i2c_done = 0x00; | |
77ad1a84 | 16 | |
99e4226b MG |
17 | void i2c_init() |
18 | { | |
da7751cb | 19 | TWBR = 0xff; |
7f52e040 MG |
20 | TWAR = BMC_ADDR & 0xfe; |
21 | TWDR = 0x00; | |
22 | TWCR &= ~((1<<TWSTA) | (1<<TWSTO)); | |
23 | TWCR |= ((1<<TWEA) | (1<<TWEN) | (1<<TWIE)); | |
e641fce6 | 24 | #ifdef __AVR_ATmega16__ |
7f52e040 | 25 | PORTC = 0x03; |
e641fce6 MG |
26 | #else |
27 | #error "Don't know how to set pullups for this chip, please add support" | |
28 | #endif | |
99e4226b MG |
29 | } |
30 | ||
d5193055 MG |
31 | void i2c_send(unsigned char *buf, int len) |
32 | { | |
33 | uint8_t old_TWCR = TWCR; | |
34 | uint8_t old_SREG = SREG; | |
35 | int i; | |
36 | ||
37 | cli(); | |
38 | ||
39 | TWCR = ((1<<TWINT) | (1<<TWSTA) | (1<<TWEN)); /* Send start */ | |
40 | ||
41 | while(!(TWCR & (1<<TWINT))) {} | |
42 | if ((TW_STATUS & 0xf8) != TW_START) | |
43 | goto out; | |
44 | ||
45 | TWDR = buf[0]; /* SLA_W */ | |
46 | TWCR = ((1<<TWINT) | (1<<TWEN)); | |
47 | ||
48 | while(!(TWCR & (1<<TWINT))) {} | |
49 | if ((TW_STATUS & 0xf8) != TW_MT_SLA_ACK) | |
50 | goto out; | |
51 | ||
52 | for(i = 1; i < len; i++) { | |
53 | TWDR = buf[i]; /* Send Data */ | |
54 | TWCR = ((1<<TWINT) | (1<<TWEN)); | |
55 | ||
56 | while(!(TWCR & (1<<TWINT))) {} | |
57 | if ((TW_STATUS & 0xf8) != TW_MT_DATA_ACK) | |
58 | goto out; | |
59 | } | |
60 | ||
61 | TWCR = ((1<<TWINT) | (1<<TWEN) | (1<<TWSTO)); | |
27f7ea19 | 62 | while(TWCR & (1<<TWSTO)) {} |
d5193055 | 63 | |
27f7ea19 | 64 | #ifdef DEBUG |
da7751cb MG |
65 | printf("I2C Data sent\n"); |
66 | #endif | |
d5193055 MG |
67 | |
68 | out: | |
69 | TWDR = 0x00; | |
70 | TWCR = old_TWCR; | |
71 | SREG = old_SREG; | |
72 | } | |
73 | ||
7f52e040 | 74 | ISR (TWI_vect, ISR_BLOCK) |
99e4226b | 75 | { |
da7751cb MG |
76 | if (i2c_done) |
77 | TWCR_RESET; | |
78 | ||
75a01977 | 79 | switch (TW_STATUS & 0xf8) { |
77ad1a84 MG |
80 | case TW_SR_SLA_ACK: |
81 | #ifdef DEBUG | |
82 | printf("I2C: Slave 0x%02x adressed\n", TWDR); | |
83 | #endif | |
da7751cb MG |
84 | i2c_pos = 0x00; |
85 | i2c_databuf[i2c_pos] = TWDR; | |
86 | i2c_pos++; | |
77ad1a84 MG |
87 | TWCR_ACK; |
88 | break; | |
89 | ||
90 | case TW_SR_DATA_ACK: | |
91 | #ifdef DEBUG | |
92 | printf("I2C: Data received: 0x%02x\n", TWDR); | |
93 | #endif | |
a44532dc MG |
94 | if (i2c_pos >= sizeof(i2c_databuf)) { |
95 | TWCR_RESET; | |
96 | i2c_pos = 0x00; | |
97 | break; | |
98 | } | |
da7751cb MG |
99 | i2c_databuf[i2c_pos] = TWDR; |
100 | i2c_pos++; | |
77ad1a84 MG |
101 | TWCR_ACK; |
102 | break; | |
103 | ||
104 | case TW_SR_STOP: | |
105 | #ifdef DEBUG | |
106 | printf("I2C: STOP received\n"); | |
107 | #endif | |
da7751cb MG |
108 | i2c_len = i2c_pos; |
109 | i2c_pos = 0x00; | |
110 | i2c_done = 0x01; | |
77ad1a84 MG |
111 | TWCR_RESET; |
112 | break; | |
113 | ||
77ad1a84 | 114 | default: |
f9d5c6e0 | 115 | #ifdef DEBUG |
75a01977 | 116 | printf("I2C: Unimplemented status 0x%02x\n", (TW_STATUS & 0xf8)); |
f9d5c6e0 | 117 | #endif |
77ad1a84 MG |
118 | TWCR_RESET; |
119 | break; | |
99e4226b MG |
120 | } |
121 | } |