-
Notifications
You must be signed in to change notification settings - Fork 19
/
i2csw.c
152 lines (124 loc) · 3.84 KB
/
i2csw.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*! \file i2csw.c \brief Software I2C interface using port pins. */
#ifdef DO_NOT_INCLUDE
//*****************************************************************************
//
// File Name : 'i2csw.c'
// Title : Software I2C interface using port pins
// Author : Pascal Stang
// Created : 11/22/2000
// Revised : 5/2/2002
// Version : 1.1
// Target MCU : Atmel AVR series
// Editor Tabs : 4
//
// This code is distributed under the GNU Public License
// which can be found at http://www.gnu.org/licenses/gpl.txt
//
//*****************************************************************************
/*
#include <avr/io.h>
#include "i2csw.h"
// Standard I2C bit rates are:
// 100KHz for slow speed
// 400KHz for high speed
//#define QDEL delay(5) // i2c quarter-bit delay
//#define HDEL delay(10) // i2c half-bit delay
// i2c quarter-bit delay
#define QDEL asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
// i2c half-bit delay
#define HDEL asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop"); asm volatile("nop");
#define I2C_SDL_LO cbi( SDAPORT, SDA)
#define I2C_SDL_HI sbi( SDAPORT, SDA)
#define I2C_SCL_LO cbi( SCLPORT, SCL);
#define I2C_SCL_HI sbi( SCLPORT, SCL);
#define I2C_SCL_TOGGLE HDEL; I2C_SCL_HI; HDEL; I2C_SCL_LO;
#define I2C_START I2C_SDL_LO; QDEL; I2C_SCL_LO;
#define I2C_STOP HDEL; I2C_SCL_HI; QDEL; I2C_SDL_HI; HDEL;
UINT i2cPutbyte(u08 b)
{
int i;
for (i=7;i>=0;i--)
{
if ( b & (1<<i) )
I2C_SDL_HI;
else
I2C_SDL_LO; // address bit
I2C_SCL_TOGGLE; // clock HI, delay, then LO
}
I2C_SDL_HI; // leave SDL HI
// added
cbi(SDADDR, SDA); // change direction to input on SDA line (may not be needed)
HDEL;
I2C_SCL_HI; // clock back up
b = inb(SDAPIN) & (1<<SDA); // get the ACK bit
HDEL;
I2C_SCL_LO; // not really ??
sbi(SDADDR, SDA); // change direction back to output
HDEL;
return (b == 0); // return ACK value
}
u08 i2cGetbyte(UINT last)
{
int i;
u08 c,b = 0;
I2C_SDL_HI; // make sure pullups are ativated
cbi(SDADDR, SDA); // change direction to input on SDA line (may not be needed)
for(i=7;i>=0;i--)
{
HDEL;
I2C_SCL_HI; // clock HI
c = inb(SDAPIN) & (1<<SDA);
b <<= 1;
if(c) b |= 1;
HDEL;
I2C_SCL_LO; // clock LO
}
sbi(SDADDR, SDA); // change direction to output on SDA line
if (last)
I2C_SDL_HI; // set NAK
else
I2C_SDL_LO; // set ACK
I2C_SCL_TOGGLE; // clock pulse
I2C_SDL_HI; // leave with SDL HI
return b; // return received byte
}
//! Initialize I2C communication
void i2cInit(void)
{
sbi( SDADDR, SDA); // set SDA as output
sbi( SCLDDR, SCL); // set SCL as output
I2C_SDL_HI; // set I/O state and pull-ups
I2C_SCL_HI; // set I/O state and pull-ups
}
//! Send a byte sequence on the I2C bus
void i2cSend(u08 device, u08 subAddr, u08 length, u08 *data)
{
I2C_START; // do start transition
i2cPutbyte(device); // send DEVICE address
i2cPutbyte(subAddr); // and the subaddress
// send the data
while (length--)
i2cPutbyte(*data++);
I2C_SDL_LO; // clear data line and
I2C_STOP; // send STOP transition
}
//! Retrieve a byte sequence on the I2C bus
void i2cReceive(u08 device, u08 subAddr, u08 length, u08 *data)
{
int j = length;
u08 *p = data;
I2C_START; // do start transition
i2cPutbyte(device); // send DEVICE address
i2cPutbyte(subAddr); // and the subaddress
HDEL;
I2C_SCL_HI; // do a repeated START
I2C_START; // transition
i2cPutbyte(device | READ); // resend DEVICE, with READ bit set
// receive data bytes
while (j--)
*p++ = i2cGetbyte(j == 0);
I2C_SDL_LO; // clear data line and
I2C_STOP; // send STOP transition
}
*/
#endif