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 |
13:530968937ccb
|
8
|
#define PREFIX i2c
|
humlet |
13:530968937ccb
|
9
|
#define PASTER(x,y) x ## _ ## y
|
humlet |
13:530968937ccb
|
10
|
#define EVALUATOR(x,y) PASTER(x,y)
|
humlet |
13:530968937ccb
|
11
|
#define FUNCTION(fun) EVALUATOR(PREFIX, fun)
|
humlet |
1:90455d5bdd8c
|
12
|
|
humlet |
1:90455d5bdd8c
|
13
|
const PinName I2CDriver::c_sdas[] = {p9,p28};
|
humlet |
1:90455d5bdd8c
|
14
|
const PinName I2CDriver::c_scls[] = {p10,p27};
|
humlet |
1:90455d5bdd8c
|
15
|
|
humlet |
1:90455d5bdd8c
|
16
|
I2CDriver::Channel* I2CDriver::s_channels[2] = {0,0};
|
humlet |
0:13c962fecb13
|
17
|
|
humlet |
3:967dde37e712
|
18
|
I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr)
|
humlet |
3:967dde37e712
|
19
|
{
|
humlet |
13:530968937ccb
|
20
|
static Mutex mutex;
|
humlet |
13:530968937ccb
|
21
|
mutex.lock();
|
humlet |
3:967dde37e712
|
22
|
// check pins and determine i2c channel
|
humlet |
3:967dde37e712
|
23
|
int channel=0;
|
humlet |
3:967dde37e712
|
24
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
3:967dde37e712
|
25
|
if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1
|
humlet |
3:967dde37e712
|
26
|
else
|
humlet |
3:967dde37e712
|
27
|
#endif
|
humlet |
3:967dde37e712
|
28
|
if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
|
humlet |
9:65aae53a34de
|
29
|
else error("I2CDriver: Invalid I2C pins selected\n");
|
humlet |
3:967dde37e712
|
30
|
|
humlet |
9:65aae53a34de
|
31
|
if(s_channels[channel]==0) {
|
humlet |
13:530968937ccb
|
32
|
s_channels[channel] = new I2CDriver::Channel;
|
humlet |
13:530968937ccb
|
33
|
m_channel = s_channels[channel];
|
humlet |
13:530968937ccb
|
34
|
m_channel->freq = 0;
|
humlet |
13:530968937ccb
|
35
|
m_channel->slaveAdr = 0;
|
humlet |
13:530968937ccb
|
36
|
m_channel->modeSlave = 0;
|
humlet |
13:530968937ccb
|
37
|
FUNCTION(init)(&m_channel->i2c, c_sdas[channel], c_scls[channel]);
|
humlet |
8:5be85bd4c5ba
|
38
|
}
|
humlet |
3:967dde37e712
|
39
|
m_channel = s_channels[channel];
|
humlet |
13:530968937ccb
|
40
|
mutex.unlock();
|
humlet |
0:13c962fecb13
|
41
|
}
|
humlet |
0:13c962fecb13
|
42
|
|
humlet |
6:5b98c902a659
|
43
|
void I2CDriver::lock()
|
humlet |
6:5b98c902a659
|
44
|
{
|
humlet |
6:5b98c902a659
|
45
|
// One and the same thread can lock twice, but then it needs also to unlock twice.
|
humlet |
6:5b98c902a659
|
46
|
// exactly what we need here
|
humlet |
6:5b98c902a659
|
47
|
m_callerID = osThreadGetId();
|
humlet |
6:5b98c902a659
|
48
|
m_callerPrio = osThreadGetPriority(m_callerID);
|
humlet |
6:5b98c902a659
|
49
|
m_channel->mutex.lock(osWaitForever);
|
humlet |
13:530968937ccb
|
50
|
// maximize thread prio
|
humlet |
13:530968937ccb
|
51
|
osThreadSetPriority(m_callerID, c_drvPrio); // hopefully not interrupted since the lock in the line above
|
humlet |
13:530968937ccb
|
52
|
// mutex code looks like that waiting threads are priority ordered
|
humlet |
13:530968937ccb
|
53
|
// also priority inheritance seems to be provided
|
humlet |
6:5b98c902a659
|
54
|
}
|
humlet |
6:5b98c902a659
|
55
|
|
humlet |
6:5b98c902a659
|
56
|
void I2CDriver::unlock()
|
humlet |
6:5b98c902a659
|
57
|
{
|
humlet |
13:530968937ccb
|
58
|
// free the mutex and restore original prio
|
humlet |
6:5b98c902a659
|
59
|
m_channel->mutex.unlock();
|
humlet |
6:5b98c902a659
|
60
|
osThreadSetPriority(m_callerID, m_callerPrio);
|
humlet |
6:5b98c902a659
|
61
|
}
|
humlet |
6:5b98c902a659
|
62
|
|
humlet |
13:530968937ccb
|
63
|
void I2CDriver::config()
|
humlet |
0:13c962fecb13
|
64
|
{
|
humlet |
13:530968937ccb
|
65
|
// check and update frequency
|
humlet |
13:530968937ccb
|
66
|
if(m_freq != m_channel->freq) {
|
humlet |
13:530968937ccb
|
67
|
m_channel->freq = m_freq;
|
humlet |
13:530968937ccb
|
68
|
i2c_frequency(&m_channel->i2c, m_freq);
|
humlet |
13:530968937ccb
|
69
|
}
|
humlet |
13:530968937ccb
|
70
|
// check and update slave/master mode
|
humlet |
13:530968937ccb
|
71
|
if(m_modeSlave != m_channel->modeSlave) {
|
humlet |
13:530968937ccb
|
72
|
m_channel->modeSlave = m_modeSlave;
|
humlet |
13:530968937ccb
|
73
|
i2c_slave_mode(&m_channel->i2c, m_modeSlave);
|
humlet |
13:530968937ccb
|
74
|
}
|
humlet |
13:530968937ccb
|
75
|
// check and update slave address
|
humlet |
13:530968937ccb
|
76
|
if(m_modeSlave && m_slaveAdr != m_channel->slaveAdr) {
|
humlet |
13:530968937ccb
|
77
|
m_channel->slaveAdr = m_slaveAdr;
|
humlet |
13:530968937ccb
|
78
|
i2c_slave_address(&m_channel->i2c, 0, m_slaveAdr, 0);
|
humlet |
13:530968937ccb
|
79
|
}
|
humlet |
0:13c962fecb13
|
80
|
}
|
humlet |
0:13c962fecb13
|
81
|
|
humlet |
3:967dde37e712
|
82
|
int I2CDriver::readMaster(int address, char *data, int length, bool repeated)
|
humlet |
1:90455d5bdd8c
|
83
|
{
|
humlet |
13:530968937ccb
|
84
|
m_modeSlave = false;
|
humlet |
13:530968937ccb
|
85
|
lockNconfig();
|
humlet |
13:530968937ccb
|
86
|
int ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1));
|
humlet |
13:530968937ccb
|
87
|
unlock();
|
humlet |
13:530968937ccb
|
88
|
return ret;
|
humlet |
1:90455d5bdd8c
|
89
|
}
|
humlet |
3:967dde37e712
|
90
|
int I2CDriver::readMaster(int address, uint8_t _register, char *data, int length, bool repeated)
|
humlet |
3:967dde37e712
|
91
|
{
|
humlet |
13:530968937ccb
|
92
|
m_modeSlave = false;
|
humlet |
13:530968937ccb
|
93
|
lockNconfig();
|
humlet |
13:530968937ccb
|
94
|
int ret = FUNCTION(write)(&m_channel->i2c, address,(const char*)&_register, 1, 0);
|
humlet |
13:530968937ccb
|
95
|
if(!ret) ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1));
|
humlet |
13:530968937ccb
|
96
|
unlock();
|
humlet |
13:530968937ccb
|
97
|
return ret;
|
humlet |
3:967dde37e712
|
98
|
}
|
humlet |
3:967dde37e712
|
99
|
int I2CDriver::readMaster(int ack)
|
humlet |
1:90455d5bdd8c
|
100
|
{
|
humlet |
13:530968937ccb
|
101
|
m_modeSlave = false;
|
humlet |
13:530968937ccb
|
102
|
lockNconfig();
|
humlet |
13:530968937ccb
|
103
|
int ret = i2cRtos_byte_read(&m_channel->i2c, (ack?0:1));
|
humlet |
13:530968937ccb
|
104
|
unlock();
|
humlet |
13:530968937ccb
|
105
|
return ret;
|
humlet |
1:90455d5bdd8c
|
106
|
}
|
humlet |
3:967dde37e712
|
107
|
int I2CDriver::writeMaster(int address, const char *data, int length, bool repeated)
|
humlet |
1:90455d5bdd8c
|
108
|
{
|
humlet |
13:530968937ccb
|
109
|
m_modeSlave = false;
|
humlet |
13:530968937ccb
|
110
|
lockNconfig();
|
humlet |
13:530968937ccb
|
111
|
int ret = FUNCTION(write)(&m_channel->i2c, address, data, length, (repeated?0:1));
|
humlet |
13:530968937ccb
|
112
|
unlock();
|
humlet |
13:530968937ccb
|
113
|
return ret;
|
humlet |
1:90455d5bdd8c
|
114
|
}
|
humlet |
3:967dde37e712
|
115
|
int I2CDriver::writeMaster(int data)
|
humlet |
1:90455d5bdd8c
|
116
|
{
|
humlet |
13:530968937ccb
|
117
|
m_modeSlave = false;
|
humlet |
13:530968937ccb
|
118
|
lockNconfig();
|
humlet |
13:530968937ccb
|
119
|
int ret = i2cRtos_byte_write(&m_channel->i2c, data);
|
humlet |
13:530968937ccb
|
120
|
unlock();
|
humlet |
13:530968937ccb
|
121
|
return ret;
|
humlet |
0:13c962fecb13
|
122
|
}
|
humlet |
3:967dde37e712
|
123
|
void I2CDriver::startMaster(void)
|
humlet |
1:90455d5bdd8c
|
124
|
{
|
humlet |
13:530968937ccb
|
125
|
m_modeSlave = false;
|
humlet |
13:530968937ccb
|
126
|
lockNconfig();
|
humlet |
13:530968937ccb
|
127
|
i2c_start(&m_channel->i2c);
|
humlet |
13:530968937ccb
|
128
|
unlock();
|
humlet |
3:967dde37e712
|
129
|
}
|
humlet |
13:530968937ccb
|
130
|
bool I2CDriver::stopMaster(void)
|
humlet |
3:967dde37e712
|
131
|
{
|
humlet |
13:530968937ccb
|
132
|
m_modeSlave = false;
|
humlet |
13:530968937ccb
|
133
|
lockNconfig();
|
humlet |
13:530968937ccb
|
134
|
bool ret=i2cRtos_stop(&m_channel->i2c);
|
humlet |
13:530968937ccb
|
135
|
unlock();
|
humlet |
13:530968937ccb
|
136
|
return ret;
|
humlet |
3:967dde37e712
|
137
|
}
|
humlet |
3:967dde37e712
|
138
|
void I2CDriver::stopSlave(void)
|
humlet |
3:967dde37e712
|
139
|
{
|
humlet |
13:530968937ccb
|
140
|
m_modeSlave = true;
|
humlet |
13:530968937ccb
|
141
|
lockNconfig();
|
humlet |
13:530968937ccb
|
142
|
i2c_stop(&m_channel->i2c);
|
humlet |
13:530968937ccb
|
143
|
unlock();
|
humlet |
3:967dde37e712
|
144
|
}
|
humlet |
3:967dde37e712
|
145
|
int I2CDriver::receiveSlave(uint32_t timeout_ms)
|
humlet |
3:967dde37e712
|
146
|
{
|
humlet |
13:530968937ccb
|
147
|
m_modeSlave = true;
|
humlet |
13:530968937ccb
|
148
|
lockNconfig();
|
humlet |
13:530968937ccb
|
149
|
int ret = i2cRtos_slave_receive(&m_channel->i2c, timeout_ms);
|
humlet |
13:530968937ccb
|
150
|
unlock();
|
humlet |
13:530968937ccb
|
151
|
return ret;
|
humlet |
3:967dde37e712
|
152
|
}
|
humlet |
3:967dde37e712
|
153
|
int I2CDriver::readSlave(char* data, int length)
|
humlet |
3:967dde37e712
|
154
|
{
|
humlet |
13:530968937ccb
|
155
|
m_modeSlave = true;
|
humlet |
13:530968937ccb
|
156
|
lockNconfig();
|
humlet |
13:530968937ccb
|
157
|
int ret = i2cRtos_slave_read(&m_channel->i2c, data, length);
|
humlet |
13:530968937ccb
|
158
|
unlock();
|
humlet |
13:530968937ccb
|
159
|
return ret;
|
humlet |
3:967dde37e712
|
160
|
}
|
humlet |
3:967dde37e712
|
161
|
int I2CDriver::readSlave(void)
|
humlet |
3:967dde37e712
|
162
|
{
|
humlet |
13:530968937ccb
|
163
|
m_modeSlave = true;
|
humlet |
13:530968937ccb
|
164
|
lockNconfig();
|
humlet |
13:530968937ccb
|
165
|
int ret = i2cRtos_byte_read(&m_channel->i2c, 0);
|
humlet |
13:530968937ccb
|
166
|
unlock();
|
humlet |
13:530968937ccb
|
167
|
return ret;
|
humlet |
3:967dde37e712
|
168
|
}
|
humlet |
3:967dde37e712
|
169
|
int I2CDriver::writeSlave(const char *data, int length)
|
humlet |
3:967dde37e712
|
170
|
{
|
humlet |
13:530968937ccb
|
171
|
m_modeSlave = true;
|
humlet |
13:530968937ccb
|
172
|
lockNconfig();
|
humlet |
13:530968937ccb
|
173
|
int ret = i2cRtos_slave_write(&m_channel->i2c, data, length);
|
humlet |
13:530968937ccb
|
174
|
unlock();
|
humlet |
13:530968937ccb
|
175
|
return ret;
|
humlet |
3:967dde37e712
|
176
|
}
|
humlet |
3:967dde37e712
|
177
|
int I2CDriver::writeSlave(int data)
|
humlet |
3:967dde37e712
|
178
|
{
|
humlet |
13:530968937ccb
|
179
|
m_modeSlave = true;
|
humlet |
13:530968937ccb
|
180
|
lockNconfig();
|
humlet |
13:530968937ccb
|
181
|
int ret = i2cRtos_byte_write(&m_channel->i2c, data);
|
humlet |
13:530968937ccb
|
182
|
unlock();
|
humlet |
13:530968937ccb
|
183
|
return ret;
|
humlet |
1:90455d5bdd8c
|
184
|
}
|
humlet |
1:90455d5bdd8c
|
185
|
|
humlet |
1:90455d5bdd8c
|
186
|
|
humlet |
3:967dde37e712
|
187
|
|
humlet |
3:967dde37e712
|
188
|
|