-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpe0fko_I2Copencollector.c
143 lines (129 loc) · 3.05 KB
/
pe0fko_I2Copencollector.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
//************************************************************************
//**
//** Project......: Firmware USB AVR Si570 controler.
//**
//** Platform.....: ATtiny45
//**
//** Licence......: This software is freely available for non-commercial
//** use - i.e. for research and experimentation only!
//** Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
//** Based on ObDev's AVR USB driver by Christian Starkjohann
//**
//** Programmer...: F.W. Krom, PE0FKO and
//** thanks to Tom Baier DG8SAQ for the initial program.
//**
//** Description..: I2C Protocol, trying to simulate a open Collector output.
//**
//** History......: V15.1 02/12/2008: First release of PE0FKO.
//** Check the main.c file
//**
//**************************************************************************
//#include "main.h"
#include "Mobo.h"
#define SDA (1<<BIT_SDA)
#define SCL (1<<BIT_SCL)
#define I2C_SDA_LO I2C_DDR |= SDA
#define I2C_SDA_HI I2C_DDR &= ~SDA
#define I2C_SCL_LO I2C_DDR |= SCL
#define I2C_SCL_HI I2C_DDR &= ~SCL
#define I2C_DELAY_uS (1000.0 / I2C_KBITRATE)
static void
I2CDelay(void)
{
_delay_us(I2C_DELAY_uS);
}
//PE0FKO: The original code has no stop condition (hang on SCL low)
//static
void
//I2CStretch() // Wait until clock hi
I2CStretch(void) // Wait until clock hi
{ // Terminate the loop @ max 2.1ms
uint16_t i = 50; // 2.1mS
do {
I2CDelay(); // Delay some time
if (i-- == 0)
{
I2CErrors = True; // Error timeout
break;
}
}
while(!(I2C_PIN & SCL)); // Clock line still low
}
/*
* Generates a start condition on the bus.
*
* SDA: ..\____..
* __
* SCL: .. \__..
*/
void
I2CSendStart(void)
{
I2CErrors = False; // reset error flag
I2C_SCL_HI;
I2C_SDA_LO; I2CDelay(); // Start SDA to low
I2C_SCL_LO; I2CDelay(); // and the clock low
}
/*
* Generates a stop condition on the bus.
* __
* SDA: ..___/ ..
* _____
* SCL: ../ ..
*/
void
I2CSendStop(void)
{
I2C_SDA_LO;
I2C_SCL_HI; I2CDelay();
I2C_SDA_HI; I2CDelay();
}
void
I2CSend0(void)
{
I2C_SDA_LO; // Data low = 0
I2C_SCL_HI; I2CStretch();
I2C_SCL_LO; I2CDelay();
}
void
I2CSend1(void)
{
I2C_SDA_HI; // Data high = 1
I2C_SCL_HI; I2CStretch();
I2C_SCL_LO; I2CDelay();
}
static uint8_t
I2CGetBit(void)
{
uint8_t b;
I2C_SDA_HI; // Data high = input (opencollector)
I2C_SCL_HI; I2CStretch(); // SDA Hi Z and wait
b = (I2C_PIN & SDA); // get bit
I2C_SCL_LO; // clock low
return b;
}
void
I2CSendByte(uint8_t b)
{
uint8_t i,p;
p = 0x80;
for (i=0; i<8; i++)
{
if ((p & b) == 0) I2CSend0(); else I2CSend1();
p = p >> 1;
};
I2CErrors |= I2CGetBit(); //Acknowledge
return;
}
uint8_t
I2CReceiveByte(void)
{
uint8_t i;
uint8_t b = 0;
for (i=0; i<8; i++)
{
b = b << 1;
if (I2CGetBit()) b |= 1;
};
return b;
}