User | Revision | Line number | New contents of line |
humlet |
0:13c962fecb13
|
1
|
#include "I2CDriver.h"
|
humlet |
0:13c962fecb13
|
2
|
#include "error.h"
|
humlet |
0:13c962fecb13
|
3
|
|
humlet |
1:90455d5bdd8c
|
4
|
using namespace mbed;
|
humlet |
1:90455d5bdd8c
|
5
|
using namespace rtos;
|
humlet |
0:13c962fecb13
|
6
|
|
humlet |
1:90455d5bdd8c
|
7
|
#define ISR2DRV_SIG (1<<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 |
0:13c962fecb13
|
15
|
|
humlet |
0:13c962fecb13
|
16
|
void I2CDriver::channel_0_ISR()
|
humlet |
0:13c962fecb13
|
17
|
{
|
humlet |
1:90455d5bdd8c
|
18
|
osSignalSet( s_channels[0]->driver, ISR2DRV_SIG);
|
humlet |
1:90455d5bdd8c
|
19
|
NVIC_DisableIRQ(I2C1_IRQn);
|
humlet |
0:13c962fecb13
|
20
|
}
|
humlet |
0:13c962fecb13
|
21
|
|
humlet |
0:13c962fecb13
|
22
|
|
humlet |
0:13c962fecb13
|
23
|
void I2CDriver::channel_1_ISR()
|
humlet |
0:13c962fecb13
|
24
|
{
|
humlet |
1:90455d5bdd8c
|
25
|
osSignalSet( s_channels[1]->driver, ISR2DRV_SIG);
|
humlet |
1:90455d5bdd8c
|
26
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
1:90455d5bdd8c
|
27
|
NVIC_DisableIRQ(I2C2_IRQn);
|
humlet |
1:90455d5bdd8c
|
28
|
#elif defined(TARGET_LPC11U24)
|
humlet |
1:90455d5bdd8c
|
29
|
NVIC_DisableIRQ(I2C_IRQn);
|
humlet |
1:90455d5bdd8c
|
30
|
#endif
|
humlet |
0:13c962fecb13
|
31
|
}
|
humlet |
0:13c962fecb13
|
32
|
|
humlet |
0:13c962fecb13
|
33
|
|
humlet |
1:90455d5bdd8c
|
34
|
void I2CDriver::threadFun(void const *args)
|
humlet |
0:13c962fecb13
|
35
|
{
|
humlet |
0:13c962fecb13
|
36
|
int channelIdx = (int)args;
|
humlet |
0:13c962fecb13
|
37
|
Channel channel;
|
humlet |
0:13c962fecb13
|
38
|
s_channels[channelIdx] = &channel;
|
humlet |
0:13c962fecb13
|
39
|
|
humlet |
0:13c962fecb13
|
40
|
channel.driver = Thread::gettid();
|
humlet |
1:90455d5bdd8c
|
41
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
0:13c962fecb13
|
42
|
if(channelIdx==0)NVIC_SetVector(I2C1_IRQn, (uint32_t)I2CDriver::channel_0_ISR);
|
humlet |
0:13c962fecb13
|
43
|
if(channelIdx==1)NVIC_SetVector(I2C2_IRQn, (uint32_t)I2CDriver::channel_1_ISR);
|
humlet |
1:90455d5bdd8c
|
44
|
#elif defined(TARGET_LPC11U24)
|
humlet |
1:90455d5bdd8c
|
45
|
NVIC_SetVector(I2C_IRQn, (uint32_t)I2CDriver::channel_1_ISR);
|
humlet |
1:90455d5bdd8c
|
46
|
#endif
|
humlet |
1:90455d5bdd8c
|
47
|
I2C i2c(c_sdas[channelIdx], c_scls[channelIdx]);
|
humlet |
1:90455d5bdd8c
|
48
|
volatile Transfer& tr = channel.transfer;
|
humlet |
0:13c962fecb13
|
49
|
while(1) {
|
humlet |
1:90455d5bdd8c
|
50
|
// wait for requests
|
humlet |
1:90455d5bdd8c
|
51
|
osSignalWait(DRV_USR_SIG,osWaitForever);
|
humlet |
1:90455d5bdd8c
|
52
|
// check and adapt frequency
|
humlet |
1:90455d5bdd8c
|
53
|
if(channel.freq != tr.freq) {
|
humlet |
1:90455d5bdd8c
|
54
|
channel.freq = tr.freq;
|
humlet |
1:90455d5bdd8c
|
55
|
i2c.frequency(tr.freq);
|
humlet |
1:90455d5bdd8c
|
56
|
}
|
humlet |
1:90455d5bdd8c
|
57
|
// just doit
|
humlet |
1:90455d5bdd8c
|
58
|
switch(tr.cmd) {
|
humlet |
0:13c962fecb13
|
59
|
case START:
|
humlet |
0:13c962fecb13
|
60
|
i2c.start();
|
humlet |
0:13c962fecb13
|
61
|
break;
|
humlet |
0:13c962fecb13
|
62
|
case STOP:
|
humlet |
0:13c962fecb13
|
63
|
i2c.stop();
|
humlet |
0:13c962fecb13
|
64
|
break;
|
humlet |
1:90455d5bdd8c
|
65
|
case READ:
|
humlet |
1:90455d5bdd8c
|
66
|
tr.ret = i2c.read(tr.adr, tr.dta, tr.len, tr.rep);
|
humlet |
1:90455d5bdd8c
|
67
|
break;
|
humlet |
1:90455d5bdd8c
|
68
|
case READ_FROM_REGISTER:
|
humlet |
1:90455d5bdd8c
|
69
|
tr.ret = i2c.write(tr.adr,(const char*)&(tr.reg), 1, true);
|
humlet |
1:90455d5bdd8c
|
70
|
if(tr.ret)break; // error => bail out
|
humlet |
1:90455d5bdd8c
|
71
|
tr.ret = i2c.read(tr.adr, tr.dta, tr.len, tr.rep);
|
humlet |
1:90455d5bdd8c
|
72
|
break;
|
humlet |
1:90455d5bdd8c
|
73
|
case READ_BYTE:
|
humlet |
1:90455d5bdd8c
|
74
|
tr.ret = i2c.read(tr.ack);
|
humlet |
1:90455d5bdd8c
|
75
|
break;
|
humlet |
1:90455d5bdd8c
|
76
|
case WRITE:
|
humlet |
1:90455d5bdd8c
|
77
|
tr.ret = i2c.write(tr.adr, tr.wdta, tr.len, tr.rep);
|
humlet |
1:90455d5bdd8c
|
78
|
break;
|
humlet |
1:90455d5bdd8c
|
79
|
case WRITE_BYTE:
|
humlet |
1:90455d5bdd8c
|
80
|
tr.ret = i2c.write(tr.ack);
|
humlet |
1:90455d5bdd8c
|
81
|
break;
|
humlet |
1:90455d5bdd8c
|
82
|
default:
|
humlet |
1:90455d5bdd8c
|
83
|
error("call 911");
|
humlet |
0:13c962fecb13
|
84
|
}
|
humlet |
1:90455d5bdd8c
|
85
|
// inform the caller
|
humlet |
1:90455d5bdd8c
|
86
|
osSignalSet( channel.transfer.caller, DRV_USR_SIG);
|
humlet |
0:13c962fecb13
|
87
|
}
|
humlet |
0:13c962fecb13
|
88
|
}
|
humlet |
0:13c962fecb13
|
89
|
|
humlet |
0:13c962fecb13
|
90
|
|
humlet |
1:90455d5bdd8c
|
91
|
I2CDriver::I2CDriver(PinName sda, PinName scl):I2C(sda,scl)
|
humlet |
0:13c962fecb13
|
92
|
{
|
humlet |
0:13c962fecb13
|
93
|
// check pins and determine i2c channel
|
humlet |
0:13c962fecb13
|
94
|
int channel=0;
|
humlet |
1:90455d5bdd8c
|
95
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
1:90455d5bdd8c
|
96
|
if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1
|
humlet |
1:90455d5bdd8c
|
97
|
else
|
humlet |
1:90455d5bdd8c
|
98
|
#endif
|
humlet |
1:90455d5bdd8c
|
99
|
if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
|
humlet |
1:90455d5bdd8c
|
100
|
else error("I2CDriver: Invalid I2C pinns selected");
|
humlet |
0:13c962fecb13
|
101
|
if(s_channels[channel]==0)
|
humlet |
0:13c962fecb13
|
102
|
new Thread(threadFun,(void *)channel,osPriorityRealtime);
|
humlet |
1:90455d5bdd8c
|
103
|
m_channel = s_channels[channel];
|
humlet |
0:13c962fecb13
|
104
|
}
|
humlet |
0:13c962fecb13
|
105
|
|
humlet |
1:90455d5bdd8c
|
106
|
|
humlet |
1:90455d5bdd8c
|
107
|
void I2CDriver::sendNwait()
|
humlet |
1:90455d5bdd8c
|
108
|
{
|
humlet |
1:90455d5bdd8c
|
109
|
m_channel->transfer.freq = _hz;
|
humlet |
1:90455d5bdd8c
|
110
|
m_channel->transfer.caller = Thread::gettid();
|
humlet |
1:90455d5bdd8c
|
111
|
osSignalSet( m_channel->driver, DRV_USR_SIG);
|
humlet |
0:13c962fecb13
|
112
|
osSignalWait(DRV_USR_SIG,osWaitForever);
|
humlet |
0:13c962fecb13
|
113
|
}
|
humlet |
0:13c962fecb13
|
114
|
|
humlet |
0:13c962fecb13
|
115
|
|
humlet |
1:90455d5bdd8c
|
116
|
int I2CDriver::read(int address, char *data, int length, bool repeated)
|
humlet |
1:90455d5bdd8c
|
117
|
{
|
humlet |
0:13c962fecb13
|
118
|
lock();
|
humlet |
1:90455d5bdd8c
|
119
|
m_channel->transfer.cmd = READ;
|
humlet |
1:90455d5bdd8c
|
120
|
m_channel->transfer.adr = address;
|
humlet |
1:90455d5bdd8c
|
121
|
m_channel->transfer.dta = data;
|
humlet |
1:90455d5bdd8c
|
122
|
m_channel->transfer.len = length;
|
humlet |
1:90455d5bdd8c
|
123
|
m_channel->transfer.rep = repeated;
|
humlet |
0:13c962fecb13
|
124
|
sendNwait();
|
humlet |
1:90455d5bdd8c
|
125
|
int ret = m_channel->transfer.ret;
|
humlet |
1:90455d5bdd8c
|
126
|
unlock();
|
humlet |
1:90455d5bdd8c
|
127
|
return ret;
|
humlet |
0:13c962fecb13
|
128
|
}
|
humlet |
0:13c962fecb13
|
129
|
|
humlet |
0:13c962fecb13
|
130
|
|
humlet |
1:90455d5bdd8c
|
131
|
int I2CDriver::read(int address, uint8_t regist, char *data, int length, bool repeated)
|
humlet |
1:90455d5bdd8c
|
132
|
{
|
humlet |
1:90455d5bdd8c
|
133
|
lock();
|
humlet |
1:90455d5bdd8c
|
134
|
m_channel->transfer.cmd = READ_FROM_REGISTER;
|
humlet |
1:90455d5bdd8c
|
135
|
m_channel->transfer.adr = address;
|
humlet |
1:90455d5bdd8c
|
136
|
m_channel->transfer.reg = regist;
|
humlet |
1:90455d5bdd8c
|
137
|
m_channel->transfer.dta = data;
|
humlet |
1:90455d5bdd8c
|
138
|
m_channel->transfer.len = length;
|
humlet |
1:90455d5bdd8c
|
139
|
m_channel->transfer.rep = repeated;
|
humlet |
1:90455d5bdd8c
|
140
|
sendNwait();
|
humlet |
1:90455d5bdd8c
|
141
|
int ret = m_channel->transfer.ret;
|
humlet |
1:90455d5bdd8c
|
142
|
unlock();
|
humlet |
1:90455d5bdd8c
|
143
|
return ret;
|
humlet |
1:90455d5bdd8c
|
144
|
}
|
humlet |
1:90455d5bdd8c
|
145
|
|
humlet |
1:90455d5bdd8c
|
146
|
int I2CDriver::read(int ack)
|
humlet |
1:90455d5bdd8c
|
147
|
{
|
humlet |
1:90455d5bdd8c
|
148
|
lock();
|
humlet |
1:90455d5bdd8c
|
149
|
m_channel->transfer.cmd = READ_BYTE;
|
humlet |
1:90455d5bdd8c
|
150
|
m_channel->transfer.ack = ack;
|
humlet |
1:90455d5bdd8c
|
151
|
sendNwait();
|
humlet |
1:90455d5bdd8c
|
152
|
int ret = m_channel->transfer.ret;
|
humlet |
1:90455d5bdd8c
|
153
|
unlock();
|
humlet |
1:90455d5bdd8c
|
154
|
return ret;
|
humlet |
1:90455d5bdd8c
|
155
|
}
|
humlet |
1:90455d5bdd8c
|
156
|
|
humlet |
1:90455d5bdd8c
|
157
|
int I2CDriver::write(int address, const char *data, int length, bool repeated)
|
humlet |
1:90455d5bdd8c
|
158
|
{
|
humlet |
0:13c962fecb13
|
159
|
lock();
|
humlet |
1:90455d5bdd8c
|
160
|
m_channel->transfer.cmd = WRITE;
|
humlet |
1:90455d5bdd8c
|
161
|
m_channel->transfer.adr = address;
|
humlet |
1:90455d5bdd8c
|
162
|
m_channel->transfer.wdta = data;
|
humlet |
1:90455d5bdd8c
|
163
|
m_channel->transfer.len = length;
|
humlet |
1:90455d5bdd8c
|
164
|
m_channel->transfer.rep = repeated;
|
humlet |
1:90455d5bdd8c
|
165
|
sendNwait();
|
humlet |
1:90455d5bdd8c
|
166
|
int ret = m_channel->transfer.ret;
|
humlet |
1:90455d5bdd8c
|
167
|
unlock();
|
humlet |
1:90455d5bdd8c
|
168
|
return ret;
|
humlet |
1:90455d5bdd8c
|
169
|
}
|
humlet |
1:90455d5bdd8c
|
170
|
|
humlet |
1:90455d5bdd8c
|
171
|
int I2CDriver::write(int data)
|
humlet |
1:90455d5bdd8c
|
172
|
{
|
humlet |
1:90455d5bdd8c
|
173
|
lock();
|
humlet |
1:90455d5bdd8c
|
174
|
m_channel->transfer.cmd = WRITE_BYTE;
|
humlet |
1:90455d5bdd8c
|
175
|
m_channel->transfer.ack = data;
|
humlet |
0:13c962fecb13
|
176
|
sendNwait();
|
humlet |
1:90455d5bdd8c
|
177
|
int ret = m_channel->transfer.ret;
|
humlet |
1:90455d5bdd8c
|
178
|
unlock();
|
humlet |
1:90455d5bdd8c
|
179
|
return ret;
|
humlet |
0:13c962fecb13
|
180
|
}
|
humlet |
1:90455d5bdd8c
|
181
|
|
humlet |
1:90455d5bdd8c
|
182
|
void I2CDriver::start(void)
|
humlet |
1:90455d5bdd8c
|
183
|
{
|
humlet |
1:90455d5bdd8c
|
184
|
lock();
|
humlet |
1:90455d5bdd8c
|
185
|
m_channel->transfer.cmd = START;
|
humlet |
1:90455d5bdd8c
|
186
|
sendNwait();
|
humlet |
1:90455d5bdd8c
|
187
|
unlock();
|
humlet |
1:90455d5bdd8c
|
188
|
}
|
humlet |
1:90455d5bdd8c
|
189
|
|
humlet |
1:90455d5bdd8c
|
190
|
|
humlet |
1:90455d5bdd8c
|
191
|
void I2CDriver::stop(void)
|
humlet |
1:90455d5bdd8c
|
192
|
{
|
humlet |
1:90455d5bdd8c
|
193
|
lock();
|
humlet |
1:90455d5bdd8c
|
194
|
m_channel->transfer.cmd = STOP;
|
humlet |
1:90455d5bdd8c
|
195
|
sendNwait();
|
humlet |
1:90455d5bdd8c
|
196
|
unlock();
|
humlet |
1:90455d5bdd8c
|
197
|
}
|