Subversion Repositories group.electronics

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
138 pfowler 1
/*
2
 * i2cbb.c
3
 *
4
 *	Bit Banging I2C code for any Atmel device
5
 *		The I2CBB_DELAY delay (in header) may need to be tweaked
6
 *		for different clock speeds, 10 if a fast enough
7
 *		speed, 100 if your having problems and dont need
8
 *		the speed. 7 seems to work well with an Attiny85
9
 *		running the PLL 16.5Mhz clock.
10
 *
11
 *		Base code from Raul
12
 *		http://codinglab.blogspot.com.au/2008/10/i2c-on-avr-using-bit-banging.html
13
 */
14
 
15
#include <avr/io.h>
16
#include <util/delay.h>
17
 
18
 
19
#include "config.h"
20
#include "avrutil.h"
21
#include "i2cbb.h"
22
 
23
#define I2CBB_DATA_HI()\
24
I2CBB_DDR &= ~ (1 << I2CBB_DAT);\
25
I2CBB_PORT |= (1 << I2CBB_DAT);
26
#define I2CBB_DATA_LO()\
27
I2CBB_DDR |= (1 << I2CBB_DAT);\
28
I2CBB_PORT &= ~ (1 << I2CBB_DAT);
29
 
30
#define I2CBB_CLOCK_HI()\
31
I2CBB_DDR &= ~ (1 << I2CBB_CLK);\
32
I2CBB_PORT |= (1 << I2CBB_CLK);
33
#define I2CBB_CLOCK_LO()\
34
I2CBB_DDR |= (1 << I2CBB_CLK);\
35
I2CBB_PORT &= ~ (1 << I2CBB_CLK);
36
 
37
void i2cbb_WriteBit(unsigned char c) {
38
    if (c > 0) {
39
        I2CBB_DATA_HI();
40
    }
41
    else {
42
        I2CBB_DATA_LO();
43
    }
44
 
45
    I2CBB_CLOCK_HI();
46
    while ((I2CBB_PIN & (1 << I2CBB_CLK)) == 0);
47
    _delay_us(I2CBB_DELAY);
48
 
49
    I2CBB_CLOCK_LO();
50
    //_delay_us(I2CBB_DELAY);
51
 
52
    if (c > 0) {
53
    	_delay_us(I2CBB_DELAY); // Added
54
        I2CBB_DATA_LO();
55
    }
56
 
57
//    _delay_us(I2CBB_DELAY);
58
}
59
 
60
unsigned char i2cbb_ReadBit() {
61
    I2CBB_DATA_HI();
62
 
63
    I2CBB_CLOCK_HI();
64
    while ((I2CBB_PIN & (1 << I2CBB_CLK)) == 0);
65
    _delay_us(I2CBB_DELAY);
66
 
67
    unsigned char c = I2CBB_PIN;
68
 
69
    I2CBB_CLOCK_LO();
70
    //_delay_us(I2CBB_DELAY);
71
 
72
    return (c >> I2CBB_DAT) & 1;
73
}
74
 
75
// Inits bitbanging port, must be called before using the functions below
76
//
77
void i2cbb_Init() {
78
    I2CBB_PORT &= ~ ((1 << I2CBB_DAT) | (1 << I2CBB_CLK));
79
 
80
    I2CBB_CLOCK_HI();
81
    I2CBB_DATA_HI();
82
 
83
    _delay_us(I2CBB_DELAY);
84
}
85
 
86
// Send a START Condition
87
//
88
void i2cbb_Start() {
89
    // set both to high at the same time
90
    I2CBB_DDR &= ~ ((1 << I2CBB_DAT) | (1 << I2CBB_CLK));
91
    _delay_us(I2CBB_DELAY);
92
 
93
    I2CBB_DATA_LO();
94
    _delay_us(I2CBB_DELAY);
95
 
96
    I2CBB_CLOCK_LO();
97
    _delay_us(I2CBB_DELAY);
98
}
99
 
100
// Send a STOP Condition
101
//
102
void i2cbb_Stop() {
103
    I2CBB_DATA_LO();
104
    I2CBB_CLOCK_LO();
105
    _delay_us(I2CBB_DELAY);
106
    _delay_us(I2CBB_DELAY);
107
 
108
    I2CBB_CLOCK_HI();
109
    _delay_us(I2CBB_DELAY);
110
    _delay_us(I2CBB_DELAY);
111
 
112
    I2CBB_DATA_HI();
113
    //_delay_us(I2CBB_DELAY);
114
}
115
 
116
// write a byte to the I2C slave device
117
 
118
unsigned char i2cbb_Write(unsigned char c) {
119
	uint8_t i;
120
    for (i=0; i < 8; i++) {
121
    	i2cbb_WriteBit(c & 128);
122
        c <<= 1;
123
    }
124
    return i2cbb_ReadBit();
125
    //return 0;
126
}
127
 
128
 
129
// read a byte from the I2C slave device
130
//
131
unsigned char i2cbb_Read(unsigned char ack) {
132
    unsigned char res = 0;
133
    uint8_t i;
134
    for (i = 0; i < 8; i++) {
135
        res <<= 1;
136
        res |= i2cbb_ReadBit();
137
    }
138
 
139
    if (ack > 0) {
140
    	i2cbb_WriteBit(0);
141
    }
142
    else {
143
    	i2cbb_WriteBit(1);
144
    }
145
 
146
    //_delay_us(I2CBB_DELAY);
147
 
148
    return res;
149
}