User | Revision | Line number | New contents of line |
humlet |
0:13c962fecb13
|
1
|
#include "I2CDriver.h"
|
humlet |
9:65aae53a34de
|
2
|
#include "i2cRtos_api.h"
|
humlet |
0:13c962fecb13
|
3
|
#include "error.h"
|
humlet |
0:13c962fecb13
|
4
|
|
humlet |
1:90455d5bdd8c
|
5
|
using namespace mbed;
|
humlet |
1:90455d5bdd8c
|
6
|
using namespace rtos;
|
humlet |
0:13c962fecb13
|
7
|
|
humlet |
1:90455d5bdd8c
|
8
|
#define DRV_USR_SIG (1<<6)
|
humlet |
1:90455d5bdd8c
|
9
|
|
humlet |
1:90455d5bdd8c
|
10
|
const PinName I2CDriver::c_sdas[] = {p9,p28};
|
humlet |
1:90455d5bdd8c
|
11
|
const PinName I2CDriver::c_scls[] = {p10,p27};
|
humlet |
1:90455d5bdd8c
|
12
|
|
humlet |
1:90455d5bdd8c
|
13
|
I2CDriver::Channel* I2CDriver::s_channels[2] = {0,0};
|
humlet |
0:13c962fecb13
|
14
|
|
humlet |
3:967dde37e712
|
15
|
I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr)
|
humlet |
3:967dde37e712
|
16
|
{
|
humlet |
3:967dde37e712
|
17
|
// check pins and determine i2c channel
|
humlet |
3:967dde37e712
|
18
|
int channel=0;
|
humlet |
3:967dde37e712
|
19
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
3:967dde37e712
|
20
|
if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1
|
humlet |
3:967dde37e712
|
21
|
else
|
humlet |
3:967dde37e712
|
22
|
#endif
|
humlet |
3:967dde37e712
|
23
|
if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
|
humlet |
9:65aae53a34de
|
24
|
else error("I2CDriver: Invalid I2C pins selected\n");
|
humlet |
3:967dde37e712
|
25
|
|
humlet |
9:65aae53a34de
|
26
|
if(s_channels[channel]==0) {
|
humlet |
11:8c1d44595620
|
27
|
new Thread(threadFun,(void *)channel,osPriorityRealtime,1024); // evillive
|
humlet |
8:5be85bd4c5ba
|
28
|
}
|
humlet |
3:967dde37e712
|
29
|
m_channel = s_channels[channel];
|
humlet |
3:967dde37e712
|
30
|
}
|
humlet |
3:967dde37e712
|
31
|
|
humlet |
3:967dde37e712
|
32
|
|
humlet |
1:90455d5bdd8c
|
33
|
void I2CDriver::threadFun(void const *args)
|
humlet |
0:13c962fecb13
|
34
|
{
|
humlet |
0:13c962fecb13
|
35
|
int channelIdx = (int)args;
|
humlet |
0:13c962fecb13
|
36
|
Channel channel;
|
humlet |
0:13c962fecb13
|
37
|
s_channels[channelIdx] = &channel;
|
humlet |
2:514105beb343
|
38
|
channel.driver = Thread::gettid();
|
humlet |
0:13c962fecb13
|
39
|
|
humlet |
3:967dde37e712
|
40
|
int freq = 0;
|
humlet |
3:967dde37e712
|
41
|
int adrSlave = 0;
|
humlet |
3:967dde37e712
|
42
|
int modeSlave = 0;
|
humlet |
3:967dde37e712
|
43
|
i2c_t i2c;
|
humlet |
9:65aae53a34de
|
44
|
i2cRtos_init(&i2c, c_sdas[channelIdx], c_scls[channelIdx]);
|
humlet |
2:514105beb343
|
45
|
|
humlet |
1:90455d5bdd8c
|
46
|
volatile Transfer& tr = channel.transfer;
|
humlet |
0:13c962fecb13
|
47
|
while(1) {
|
humlet |
1:90455d5bdd8c
|
48
|
// wait for requests
|
humlet |
1:90455d5bdd8c
|
49
|
osSignalWait(DRV_USR_SIG,osWaitForever);
|
humlet |
3:967dde37e712
|
50
|
|
humlet |
1:90455d5bdd8c
|
51
|
// check and adapt frequency
|
humlet |
3:967dde37e712
|
52
|
if(freq != tr.freq) {
|
humlet |
3:967dde37e712
|
53
|
freq = tr.freq;
|
humlet |
3:967dde37e712
|
54
|
i2c_frequency(&i2c, tr.freq);
|
humlet |
1:90455d5bdd8c
|
55
|
}
|
humlet |
3:967dde37e712
|
56
|
|
humlet |
3:967dde37e712
|
57
|
// check and adapt slave/master mode
|
humlet |
3:967dde37e712
|
58
|
if(modeSlave != tr.slv) {
|
humlet |
3:967dde37e712
|
59
|
modeSlave = tr.slv;
|
humlet |
3:967dde37e712
|
60
|
i2c_slave_mode(&i2c, tr.slv);
|
humlet |
3:967dde37e712
|
61
|
}
|
humlet |
3:967dde37e712
|
62
|
|
humlet |
3:967dde37e712
|
63
|
// check and adapt slave address
|
humlet |
3:967dde37e712
|
64
|
int adr = (tr.adr & 0xFF) | 1;
|
humlet |
3:967dde37e712
|
65
|
if(tr.slv && adrSlave != adr) {
|
humlet |
3:967dde37e712
|
66
|
adrSlave = adr;
|
humlet |
3:967dde37e712
|
67
|
i2c_slave_address(&i2c, 0, adr, 0);
|
humlet |
3:967dde37e712
|
68
|
}
|
humlet |
3:967dde37e712
|
69
|
|
humlet |
1:90455d5bdd8c
|
70
|
// just doit
|
humlet |
1:90455d5bdd8c
|
71
|
switch(tr.cmd) {
|
humlet |
0:13c962fecb13
|
72
|
case START:
|
humlet |
3:967dde37e712
|
73
|
i2c_start(&i2c);
|
humlet |
0:13c962fecb13
|
74
|
break;
|
humlet |
0:13c962fecb13
|
75
|
case STOP:
|
humlet |
3:967dde37e712
|
76
|
i2c_stop(&i2c);
|
humlet |
0:13c962fecb13
|
77
|
break;
|
humlet |
3:967dde37e712
|
78
|
case READ_MST:
|
humlet |
9:65aae53a34de
|
79
|
tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
|
humlet |
1:90455d5bdd8c
|
80
|
break;
|
humlet |
3:967dde37e712
|
81
|
case READ_MST_REG:
|
humlet |
9:65aae53a34de
|
82
|
tr.ret = i2cRtos_write(&i2c, tr.adr,(const char*)&(tr.reg), 1, 0);
|
humlet |
1:90455d5bdd8c
|
83
|
if(tr.ret)break; // error => bail out
|
humlet |
9:65aae53a34de
|
84
|
tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
|
humlet |
3:967dde37e712
|
85
|
break;
|
humlet |
3:967dde37e712
|
86
|
case READ_SLV:
|
humlet |
9:65aae53a34de
|
87
|
tr.ret = i2cRtos_slave_read(&i2c, tr.dta, tr.len);
|
humlet |
1:90455d5bdd8c
|
88
|
break;
|
humlet |
1:90455d5bdd8c
|
89
|
case READ_BYTE:
|
humlet |
9:65aae53a34de
|
90
|
tr.ret = i2cRtos_byte_read(&i2c, (tr.ack?0:1));
|
humlet |
1:90455d5bdd8c
|
91
|
break;
|
humlet |
3:967dde37e712
|
92
|
case WRITE_MST:
|
humlet |
9:65aae53a34de
|
93
|
tr.ret = i2cRtos_write(&i2c, tr.adr, tr.wdta, tr.len, (tr.rep?0:1));
|
humlet |
3:967dde37e712
|
94
|
break;
|
humlet |
3:967dde37e712
|
95
|
case WRITE_SLV:
|
humlet |
9:65aae53a34de
|
96
|
tr.ret = i2cRtos_slave_write(&i2c, tr.wdta, tr.len);
|
humlet |
1:90455d5bdd8c
|
97
|
break;
|
humlet |
1:90455d5bdd8c
|
98
|
case WRITE_BYTE:
|
humlet |
9:65aae53a34de
|
99
|
tr.ret = i2cRtos_byte_write(&i2c, tr.ack);
|
humlet |
1:90455d5bdd8c
|
100
|
break;
|
humlet |
3:967dde37e712
|
101
|
case RECEIVE:
|
humlet |
9:65aae53a34de
|
102
|
tr.ret = i2cRtos_slave_receive(&i2c, tr.tmout);
|
humlet |
4:eafa7efcd771
|
103
|
break;
|
humlet |
1:90455d5bdd8c
|
104
|
default:
|
humlet |
4:eafa7efcd771
|
105
|
error("call 911\n");
|
humlet |
0:13c962fecb13
|
106
|
}
|
humlet |
1:90455d5bdd8c
|
107
|
// inform the caller
|
humlet |
1:90455d5bdd8c
|
108
|
osSignalSet( channel.transfer.caller, DRV_USR_SIG);
|
humlet |
0:13c962fecb13
|
109
|
}
|
humlet |
0:13c962fecb13
|
110
|
}
|
humlet |
0:13c962fecb13
|
111
|
|
humlet |
6:5b98c902a659
|
112
|
void I2CDriver::lock()
|
humlet |
6:5b98c902a659
|
113
|
{
|
humlet |
6:5b98c902a659
|
114
|
// One and the same thread can lock twice, but then it needs also to unlock twice.
|
humlet |
6:5b98c902a659
|
115
|
// exactly what we need here
|
humlet |
6:5b98c902a659
|
116
|
m_callerID = osThreadGetId();
|
humlet |
6:5b98c902a659
|
117
|
m_callerPrio = osThreadGetPriority(m_callerID);
|
humlet |
6:5b98c902a659
|
118
|
m_channel->mutex.lock(osWaitForever);
|
humlet |
11:8c1d44595620
|
119
|
osThreadSetPriority(m_callerID, c_drvPrio); // evillive hopefully not interrupted since the lock
|
humlet |
6:5b98c902a659
|
120
|
}
|
humlet |
6:5b98c902a659
|
121
|
|
humlet |
6:5b98c902a659
|
122
|
void I2CDriver::unlock()
|
humlet |
6:5b98c902a659
|
123
|
{
|
humlet |
6:5b98c902a659
|
124
|
// free the mtex and restore original prio
|
humlet |
6:5b98c902a659
|
125
|
m_channel->mutex.unlock();
|
humlet |
6:5b98c902a659
|
126
|
osThreadSetPriority(m_callerID, m_callerPrio);
|
humlet |
6:5b98c902a659
|
127
|
}
|
humlet |
6:5b98c902a659
|
128
|
|
humlet |
3:967dde37e712
|
129
|
int I2CDriver::sendNwait()
|
humlet |
0:13c962fecb13
|
130
|
{
|
humlet |
3:967dde37e712
|
131
|
m_channel->transfer.freq = m_freq;
|
humlet |
1:90455d5bdd8c
|
132
|
m_channel->transfer.caller = Thread::gettid();
|
humlet |
1:90455d5bdd8c
|
133
|
osSignalSet( m_channel->driver, DRV_USR_SIG);
|
humlet |
0:13c962fecb13
|
134
|
osSignalWait(DRV_USR_SIG,osWaitForever);
|
humlet |
1:90455d5bdd8c
|
135
|
int ret = m_channel->transfer.ret;
|
humlet |
1:90455d5bdd8c
|
136
|
unlock();
|
humlet |
1:90455d5bdd8c
|
137
|
return ret;
|
humlet |
0:13c962fecb13
|
138
|
}
|
humlet |
0:13c962fecb13
|
139
|
|
humlet |
3:967dde37e712
|
140
|
int I2CDriver::readMaster(int address, char *data, int length, bool repeated)
|
humlet |
1:90455d5bdd8c
|
141
|
{
|
humlet |
1:90455d5bdd8c
|
142
|
lock();
|
humlet |
3:967dde37e712
|
143
|
m_channel->transfer.cmd = READ_MST;
|
humlet |
3:967dde37e712
|
144
|
m_channel->transfer.slv = false;
|
humlet |
1:90455d5bdd8c
|
145
|
m_channel->transfer.adr = address;
|
humlet |
1:90455d5bdd8c
|
146
|
m_channel->transfer.dta = data;
|
humlet |
1:90455d5bdd8c
|
147
|
m_channel->transfer.len = length;
|
humlet |
1:90455d5bdd8c
|
148
|
m_channel->transfer.rep = repeated;
|
humlet |
3:967dde37e712
|
149
|
return sendNwait();
|
humlet |
1:90455d5bdd8c
|
150
|
}
|
humlet |
1:90455d5bdd8c
|
151
|
|
humlet |
3:967dde37e712
|
152
|
int I2CDriver::readMaster(int address, uint8_t _register, char *data, int length, bool repeated)
|
humlet |
3:967dde37e712
|
153
|
{
|
humlet |
3:967dde37e712
|
154
|
lock();
|
humlet |
3:967dde37e712
|
155
|
m_channel->transfer.cmd = READ_MST_REG;
|
humlet |
3:967dde37e712
|
156
|
m_channel->transfer.slv = false;
|
humlet |
3:967dde37e712
|
157
|
m_channel->transfer.adr = address;
|
humlet |
3:967dde37e712
|
158
|
m_channel->transfer.reg = _register;
|
humlet |
3:967dde37e712
|
159
|
m_channel->transfer.dta = data;
|
humlet |
3:967dde37e712
|
160
|
m_channel->transfer.len = length;
|
humlet |
3:967dde37e712
|
161
|
m_channel->transfer.rep = repeated;
|
humlet |
3:967dde37e712
|
162
|
return sendNwait();
|
humlet |
3:967dde37e712
|
163
|
}
|
humlet |
3:967dde37e712
|
164
|
|
humlet |
3:967dde37e712
|
165
|
int I2CDriver::readMaster(int ack)
|
humlet |
1:90455d5bdd8c
|
166
|
{
|
humlet |
1:90455d5bdd8c
|
167
|
lock();
|
humlet |
1:90455d5bdd8c
|
168
|
m_channel->transfer.cmd = READ_BYTE;
|
humlet |
3:967dde37e712
|
169
|
m_channel->transfer.slv = false;
|
humlet |
1:90455d5bdd8c
|
170
|
m_channel->transfer.ack = ack;
|
humlet |
3:967dde37e712
|
171
|
return sendNwait();
|
humlet |
1:90455d5bdd8c
|
172
|
}
|
humlet |
1:90455d5bdd8c
|
173
|
|
humlet |
3:967dde37e712
|
174
|
int I2CDriver::writeMaster(int address, const char *data, int length, bool repeated)
|
humlet |
1:90455d5bdd8c
|
175
|
{
|
humlet |
0:13c962fecb13
|
176
|
lock();
|
humlet |
3:967dde37e712
|
177
|
m_channel->transfer.cmd = WRITE_MST;
|
humlet |
3:967dde37e712
|
178
|
m_channel->transfer.slv = false;
|
humlet |
1:90455d5bdd8c
|
179
|
m_channel->transfer.adr = address;
|
humlet |
1:90455d5bdd8c
|
180
|
m_channel->transfer.wdta = data;
|
humlet |
1:90455d5bdd8c
|
181
|
m_channel->transfer.len = length;
|
humlet |
1:90455d5bdd8c
|
182
|
m_channel->transfer.rep = repeated;
|
humlet |
3:967dde37e712
|
183
|
return sendNwait();
|
humlet |
1:90455d5bdd8c
|
184
|
}
|
humlet |
1:90455d5bdd8c
|
185
|
|
humlet |
3:967dde37e712
|
186
|
int I2CDriver::writeMaster(int data)
|
humlet |
1:90455d5bdd8c
|
187
|
{
|
humlet |
1:90455d5bdd8c
|
188
|
lock();
|
humlet |
1:90455d5bdd8c
|
189
|
m_channel->transfer.cmd = WRITE_BYTE;
|
humlet |
3:967dde37e712
|
190
|
m_channel->transfer.slv = false;
|
humlet |
1:90455d5bdd8c
|
191
|
m_channel->transfer.ack = data;
|
humlet |
3:967dde37e712
|
192
|
return sendNwait();
|
humlet |
0:13c962fecb13
|
193
|
}
|
humlet |
1:90455d5bdd8c
|
194
|
|
humlet |
3:967dde37e712
|
195
|
void I2CDriver::startMaster(void)
|
humlet |
1:90455d5bdd8c
|
196
|
{
|
humlet |
1:90455d5bdd8c
|
197
|
lock();
|
humlet |
1:90455d5bdd8c
|
198
|
m_channel->transfer.cmd = START;
|
humlet |
3:967dde37e712
|
199
|
m_channel->transfer.slv = false;
|
humlet |
1:90455d5bdd8c
|
200
|
sendNwait();
|
humlet |
3:967dde37e712
|
201
|
}
|
humlet |
3:967dde37e712
|
202
|
|
humlet |
3:967dde37e712
|
203
|
void I2CDriver::stopMaster(void)
|
humlet |
3:967dde37e712
|
204
|
{
|
humlet |
3:967dde37e712
|
205
|
lock();
|
humlet |
3:967dde37e712
|
206
|
m_channel->transfer.cmd = STOP;
|
humlet |
3:967dde37e712
|
207
|
m_channel->transfer.slv = false;
|
humlet |
3:967dde37e712
|
208
|
sendNwait();
|
humlet |
3:967dde37e712
|
209
|
}
|
humlet |
3:967dde37e712
|
210
|
|
humlet |
3:967dde37e712
|
211
|
void I2CDriver::stopSlave(void)
|
humlet |
3:967dde37e712
|
212
|
{
|
humlet |
3:967dde37e712
|
213
|
lock();
|
humlet |
3:967dde37e712
|
214
|
m_channel->transfer.cmd = STOP;
|
humlet |
3:967dde37e712
|
215
|
m_channel->transfer.slv = true;
|
humlet |
3:967dde37e712
|
216
|
m_channel->transfer.adr = m_slaveAdr;
|
humlet |
3:967dde37e712
|
217
|
sendNwait();
|
humlet |
3:967dde37e712
|
218
|
}
|
humlet |
3:967dde37e712
|
219
|
|
humlet |
3:967dde37e712
|
220
|
int I2CDriver::receiveSlave(uint32_t timeout_ms)
|
humlet |
3:967dde37e712
|
221
|
{
|
humlet |
3:967dde37e712
|
222
|
lock();
|
humlet |
3:967dde37e712
|
223
|
m_channel->transfer.cmd = RECEIVE;
|
humlet |
3:967dde37e712
|
224
|
m_channel->transfer.slv = true;
|
humlet |
3:967dde37e712
|
225
|
m_channel->transfer.adr = m_slaveAdr;
|
humlet |
3:967dde37e712
|
226
|
m_channel->transfer.tmout = timeout_ms;
|
humlet |
3:967dde37e712
|
227
|
return sendNwait();
|
humlet |
3:967dde37e712
|
228
|
}
|
humlet |
3:967dde37e712
|
229
|
|
humlet |
3:967dde37e712
|
230
|
int I2CDriver::readSlave(char* data, int length)
|
humlet |
3:967dde37e712
|
231
|
{
|
humlet |
3:967dde37e712
|
232
|
lock();
|
humlet |
3:967dde37e712
|
233
|
m_channel->transfer.cmd = READ_SLV;
|
humlet |
3:967dde37e712
|
234
|
m_channel->transfer.slv = true;
|
humlet |
3:967dde37e712
|
235
|
m_channel->transfer.adr = m_slaveAdr;
|
humlet |
3:967dde37e712
|
236
|
m_channel->transfer.dta = data;
|
humlet |
3:967dde37e712
|
237
|
m_channel->transfer.len = length;
|
humlet |
3:967dde37e712
|
238
|
return sendNwait();
|
humlet |
3:967dde37e712
|
239
|
}
|
humlet |
3:967dde37e712
|
240
|
|
humlet |
3:967dde37e712
|
241
|
int I2CDriver::readSlave(void)
|
humlet |
3:967dde37e712
|
242
|
{
|
humlet |
3:967dde37e712
|
243
|
lock();
|
humlet |
3:967dde37e712
|
244
|
m_channel->transfer.cmd = READ_BYTE;
|
humlet |
3:967dde37e712
|
245
|
m_channel->transfer.slv = true;
|
humlet |
3:967dde37e712
|
246
|
m_channel->transfer.adr = m_slaveAdr;
|
humlet |
3:967dde37e712
|
247
|
m_channel->transfer.ack = 1;
|
humlet |
3:967dde37e712
|
248
|
return sendNwait();
|
humlet |
3:967dde37e712
|
249
|
}
|
humlet |
3:967dde37e712
|
250
|
|
humlet |
3:967dde37e712
|
251
|
int I2CDriver::writeSlave(const char *data, int length)
|
humlet |
3:967dde37e712
|
252
|
{
|
humlet |
3:967dde37e712
|
253
|
lock();
|
humlet |
3:967dde37e712
|
254
|
m_channel->transfer.cmd = WRITE_SLV;
|
humlet |
3:967dde37e712
|
255
|
m_channel->transfer.slv = true;
|
humlet |
3:967dde37e712
|
256
|
m_channel->transfer.adr = m_slaveAdr;
|
humlet |
3:967dde37e712
|
257
|
m_channel->transfer.wdta = data;
|
humlet |
3:967dde37e712
|
258
|
m_channel->transfer.len = length;
|
humlet |
3:967dde37e712
|
259
|
return sendNwait();
|
humlet |
3:967dde37e712
|
260
|
}
|
humlet |
3:967dde37e712
|
261
|
|
humlet |
3:967dde37e712
|
262
|
int I2CDriver::writeSlave(int data)
|
humlet |
3:967dde37e712
|
263
|
{
|
humlet |
3:967dde37e712
|
264
|
lock();
|
humlet |
3:967dde37e712
|
265
|
m_channel->transfer.cmd = WRITE_BYTE;
|
humlet |
3:967dde37e712
|
266
|
m_channel->transfer.slv = true;
|
humlet |
3:967dde37e712
|
267
|
m_channel->transfer.adr = m_slaveAdr;
|
humlet |
3:967dde37e712
|
268
|
m_channel->transfer.ack = data;
|
humlet |
3:967dde37e712
|
269
|
return sendNwait();
|
humlet |
1:90455d5bdd8c
|
270
|
}
|
humlet |
1:90455d5bdd8c
|
271
|
|
humlet |
1:90455d5bdd8c
|
272
|
|
humlet |
3:967dde37e712
|
273
|
|
humlet |
3:967dde37e712
|
274
|
|