libpropeller
Making PropellerGCC Easier
Main Page
Related Pages
Classes
Files
File List
File Members
All
Classes
Files
Functions
Variables
Enumerations
Enumerator
Macros
Pages
libpropeller
libpropeller
i2c
i2c_base.h
Go to the documentation of this file.
1
#ifndef LIBPROPELLER_I2C_BASE_H_
2
#define LIBPROPELLER_I2C_BASE_H_
3
4
#include <propeller.h>
5
6
#define I2C_FLOAT_SCL_HIGH (DIRA &= ~scl_mask_)
7
#define I2C_SET_SCL_LOW (DIRA |= scl_mask_)
8
#define I2C_FLOAT_SDA_HIGH (DIRA &= ~sda_mask_)
9
#define I2C_SET_SDA_LOW (DIRA |= sda_mask_)
10
11
//Note: refactoring this into it's own class took all of 8 bytes extra :^)
12
19
class
I2CBase
{
20
public
:
21
30
void
Init
(
const
int
scl = 28,
const
int
sda = 29,
const
int
frequency = 400000) {
31
scl_mask_ = 1 << scl;
32
sda_mask_ = 1 << sda;
33
34
SetFrequency
(frequency);
35
36
//Set pins to input
37
I2C_FLOAT_SCL_HIGH
;
38
I2C_FLOAT_SDA_HIGH
;
39
40
41
//Set outputs low
42
OUTA
&= ~scl_mask_;
43
OUTA
&= ~sda_mask_;
44
45
46
}
47
51
void
SetFrequency
(
const
int
frequency){
52
53
54
//Clock delay values (@80MHz system clock):
55
// 1600 == 25kHz
56
// 400 == 100kHz
57
// 100 == 400kHz
58
// 90 == 444kHz
59
// 32 == 1.25MHz
60
61
62
63
//clock_delay_ = 100; //90;
64
65
clock_delay_ = CLKFREQ/(2*frequency);
66
67
}
68
71
void
Start
(
void
) {
72
I2C_FLOAT_SDA_HIGH
;
73
I2C_FLOAT_SCL_HIGH
;
74
I2C_SET_SDA_LOW
;
75
I2C_SET_SCL_LOW
;
76
}
77
80
void
Stop
(
void
) {
81
I2C_FLOAT_SCL_HIGH
;
82
I2C_FLOAT_SDA_HIGH
;
83
}
84
90
bool
SendByte
(
const
unsigned
char
byte) {
91
int
result;
92
93
int
datamask, nextCNT, temp;
94
95
__asm__
volatile
(
96
" fcache #(PutByteEnd - PutByteStart)\n\t"
97
" .compress off \n\t"
98
/* Setup for transmit loop */
99
"PutByteStart: "
100
" mov %[datamask], #256 \n\t"
/* 0x100 */
101
" mov %[result], #0 \n\t"
102
" mov %[nextCNT], cnt \n\t"
103
" add %[nextCNT], %[clockDelay] \n\t"
104
105
/* Transmit Loop (8x) */
106
//Output bit of byte
107
"PutByteLoop: "
108
" shr %[datamask], #1 \n\t"
// Set up mask
109
" and %[datamask], %[databyte] wz,nr \n\t"
// Move the bit into Z flag
110
" muxz dira, %[SDAMask] \n\t"
111
112
//Pulse clock
113
" waitcnt %[nextCNT], %[clockDelay] \n\t"
114
" andn dira, %[SCLMask] \n\t"
// Set SCL high
115
" waitcnt %[nextCNT], %[clockDelay] \n\t"
116
" or dira, %[SCLMask] \n\t"
// Set SCL low
117
118
//Return for more bits
119
" djnz %[datamask], #__LMM_FCACHE_START+(PutByteLoop-PutByteStart) nr \n\t"
120
121
// Get ACK
122
" andn dira, %[SDAMask] \n\t"
// Float SDA high (release SDA)
123
" waitcnt %[nextCNT], %[clockDelay] \n\t"
124
" andn dira, %[SCLMask] \n\t"
// SCL high (by float)
125
" waitcnt %[nextCNT], %[clockDelay] \n\t"
126
" mov %[temp], ina \n\t"
//Sample input
127
" and %[SDAMask], %[temp] wz,nr \n\t"
// If != 0, ack'd, else nack
128
" muxz %[result], #1 \n\t"
// Set result to equal to Z flag (aka, 1 if ack'd)
129
" or dira, %[SCLMask] \n\t"
// Set scl low
130
" or dira, %[SDAMask] \n\t"
// Set sda low
131
" jmp __LMM_RET \n\t"
132
"PutByteEnd: "
133
" .compress default \n\t"
134
:
// Outputs
135
[datamask]
"=&r"
(datamask),
136
[result]
"=&r"
(result),
137
[nextCNT]
"=&r"
(nextCNT),
138
[temp]
"=&r"
(temp)
139
:
// Inputs
140
[SDAMask]
"r"
(sda_mask_),
141
[SCLMask]
"r"
(scl_mask_),
142
[databyte]
"r"
(byte),
143
[clockDelay]
"r"
(clock_delay_)
144
);
145
146
return
result;
147
}
148
154
unsigned
char
ReadByte
(
const
bool
acknowledge) {
155
156
int
result = 0;
157
int
datamask, nextCNT, temp;
158
159
__asm__
volatile
(
160
" fcache #(GetByteEnd - GetByteStart)\n\t"
161
" .compress off \n\t"
162
// Setup for receive loop
163
"GetByteStart: "
164
" andn dira, %[SDAMask] \n\t"
165
" mov %[datamask], #256 \n\t"
/* 0x100 */
166
" mov %[result], #0 \n\t"
167
" mov %[nextCNT], cnt \n\t"
168
" add %[nextCNT], %[clockDelay] \n\t"
169
170
// Recieve Loop (8x)
171
//Get bit of byte
172
"GetByteLoop: "
173
174
" waitcnt %[nextCNT], %[clockDelay] \n\t"
175
" shr %[datamask], #1 \n\t"
// Set up mask
176
177
//Pulse clock
178
" andn dira, %[SCLMask] \n\t"
// Set SCL high
179
" waitcnt %[nextCNT], %[clockDelay] \n\t"
180
" mov %[temp], ina \n\t"
//Sample the input
181
" and %[temp], %[SDAMask] nr,wz \n\t"
182
" muxnz %[result], %[datamask] \n\t"
183
" or dira, %[SCLMask] \n\t"
// Set SCL low
184
185
//Return for more bits
186
" djnz %[datamask], #__LMM_FCACHE_START+(GetByteLoop-GetByteStart) nr \n\t"
187
188
// Put ACK
189
190
" and %[acknowledge], #1 nr,wz \n\t"
//Output ACK
191
192
" muxnz dira, %[SDAMask] \n\t"
193
" waitcnt %[nextCNT], %[clockDelay] \n\t"
194
" andn dira, %[SCLMask] \n\t"
// SCL high (by float)
195
" waitcnt %[nextCNT], %[clockDelay] \n\t"
196
197
" or dira, %[SCLMask] \n\t"
// Set scl low
198
" or dira, %[SDAMask] \n\t"
// Set sda low
199
" jmp __LMM_RET \n\t"
200
"GetByteEnd: "
201
" .compress default \n\t"
202
203
:
// Outputs
204
[datamask]
"=&r"
(datamask),
205
[result]
"=&r"
(result),
206
[temp]
"=&r"
(temp),
207
[nextCNT]
"=&r"
(nextCNT)
208
209
:
// Inputs
210
[SDAMask]
"r"
(sda_mask_),
211
[SCLMask]
"r"
(scl_mask_),
212
[acknowledge]
"r"
(acknowledge),
213
[clockDelay]
"r"
(clock_delay_)
214
);
215
216
return
result;
217
218
}
219
220
private
:
221
unsigned
int
scl_mask_;
222
unsigned
int
sda_mask_;
223
224
int
clock_delay_;
225
226
};
227
228
229
230
#endif // LIBPROPELLER_I2C_BASE_H_
Generated on Fri Oct 25 2013 23:41:46 for libpropeller by
1.8.4