Subversion Repositories group.electronics

Rev

Rev 139 | Details | Compare with Previous | 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();
139 pfowler 62
    _delay_us(I2CBB_DELAY);
138 pfowler 63
 
64
    I2CBB_CLOCK_HI();
139 pfowler 65
 
138 pfowler 66
    while ((I2CBB_PIN & (1 << I2CBB_CLK)) == 0);
67
    _delay_us(I2CBB_DELAY);
68
 
69
    unsigned char c = I2CBB_PIN;
70
 
71
    I2CBB_CLOCK_LO();
72
    //_delay_us(I2CBB_DELAY);
73
 
74
    return (c >> I2CBB_DAT) & 1;
75
}
76
 
77
// Inits bitbanging port, must be called before using the functions below
78
//
79
void i2cbb_Init() {
80
    I2CBB_PORT &= ~ ((1 << I2CBB_DAT) | (1 << I2CBB_CLK));
81
 
82
    I2CBB_CLOCK_HI();
83
    I2CBB_DATA_HI();
84
 
85
    _delay_us(I2CBB_DELAY);
86
}
87
 
88
// Send a START Condition
89
//
90
void i2cbb_Start() {
91
    // set both to high at the same time
92
    I2CBB_DDR &= ~ ((1 << I2CBB_DAT) | (1 << I2CBB_CLK));
93
    _delay_us(I2CBB_DELAY);
94
 
95
    I2CBB_DATA_LO();
96
    _delay_us(I2CBB_DELAY);
97
 
98
    I2CBB_CLOCK_LO();
99
    _delay_us(I2CBB_DELAY);
100
}
101
 
102
// Send a STOP Condition
103
//
104
void i2cbb_Stop() {
105
    I2CBB_DATA_LO();
106
    I2CBB_CLOCK_LO();
107
    _delay_us(I2CBB_DELAY);
108
    _delay_us(I2CBB_DELAY);
109
 
110
    I2CBB_CLOCK_HI();
111
    _delay_us(I2CBB_DELAY);
112
    _delay_us(I2CBB_DELAY);
113
 
114
    I2CBB_DATA_HI();
115
    //_delay_us(I2CBB_DELAY);
116
}
117
 
118
// write a byte to the I2C slave device
119
 
120
unsigned char i2cbb_Write(unsigned char c) {
121
	uint8_t i;
122
    for (i=0; i < 8; i++) {
123
    	i2cbb_WriteBit(c & 128);
124
        c <<= 1;
125
    }
126
    return i2cbb_ReadBit();
127
    //return 0;
128
}
129
 
130
 
131
// read a byte from the I2C slave device
132
//
133
unsigned char i2cbb_Read(unsigned char ack) {
134
    unsigned char res = 0;
135
    uint8_t i;
136
    for (i = 0; i < 8; i++) {
137
        res <<= 1;
138
        res |= i2cbb_ReadBit();
139
    }
140
 
141
    if (ack > 0) {
142
    	i2cbb_WriteBit(0);
143
    }
144
    else {
145
    	i2cbb_WriteBit(1);
146
    }
147
 
148
    //_delay_us(I2CBB_DELAY);
149
 
150
    return res;
151
}