-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtml_alt-i2c.c
198 lines (175 loc) · 5.66 KB
/
tml_alt-i2c.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
* Copyright (c), NXP Semiconductors Caen / France
*
* (C)NXP Semiconductors
* All rights are reserved. Reproduction in whole or in part is
* prohibited without the written consent of the copyright owner.
* NXP reserves the right to make changes without notice at any time.
* NXP makes no warranty, expressed, implied or statutory, including but
* not limited to any implied warranty of merchantability or fitness for any
*particular purpose, or that the use will not infringe any third party patent,
* copyright or trademark. NXP must not be liable for any loss or damage
* arising from its use.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <poll.h>
#include <tml.h>
#define I2C_BUS "/dev/i2c-1"
#define I2C_ADDRESS 0x28
#define PIN_INT 23
#define PIN_ENABLE 24
#define EDGE_NONE 0
#define EDGE_RISING 1
#define EDGE_FALLING 2
#define EDGE_BOTH 3
static int iEnableFd = 0;
static int iInterruptFd = 0;
static int verifyPin( int pin, int isoutput, int edge ) {
char buf[40];
int hasGpio = 0;
sprintf( buf, "/sys/class/gpio/gpio%d", pin );
int fd = open( buf, O_RDONLY );
if ( fd <= 0 ) {
// Pin not exported yet
if ( ( fd = open( "/sys/class/gpio/export", O_WRONLY ) ) > 0 ) {
sprintf(buf, "%d", pin);
if ( write( fd, buf, strlen(buf)) == strlen(buf)) {
hasGpio = 1;
}
close( fd );
}
} else {
hasGpio = 1;
close( fd );
}
usleep(100000);
if ( hasGpio ) {
// Make sure it is an output
sprintf( buf, "/sys/class/gpio/gpio%d/direction", pin );
fd = open( buf, O_WRONLY );
if ( fd > 0 ) {
if ( isoutput ) {
write(fd,"out",3);
close(fd);
// Open pin and make sure it is off
sprintf( buf, "/sys/class/gpio/gpio%d/value", pin );
fd = open( buf, O_RDWR );
if ( fd > 0 ) {
write( fd, "0", 1 );
return( fd ); // Success
}
} else {
write(fd,"in",2);
close(fd);
if(edge != EDGE_NONE) {
// Open pin edge control
sprintf( buf, "/sys/class/gpio/gpio%d/edge", pin );
fd = open( buf, O_RDWR );
if ( fd > 0 ) {
char * edge_str = "none";
switch ( edge ) {
case EDGE_RISING: edge_str = "rising"; break;
case EDGE_FALLING: edge_str = "falling"; break;
case EDGE_BOTH: edge_str = "both"; break;
default: break;
}
write( fd, edge_str, strlen(edge_str));
close(fd);
}
}
// Open pin
sprintf( buf, "/sys/class/gpio/gpio%d/value", pin );
fd = open( buf, O_RDONLY );
if ( fd > 0 ) {
return( fd ); // Success
}
}
}
}
return( 0 );
}
static int pnGetint( void ) {
char buf[2];
int len;
if (iInterruptFd <= 0) return -1;
lseek(iInterruptFd, SEEK_SET, 0);
len = read(iInterruptFd, buf, 2);
if (len != 2) return 0;
return (buf[0] != '0');
}
int tml_open(int * handle)
{
iInterruptFd = verifyPin(PIN_INT, 0, EDGE_RISING);
iEnableFd = verifyPin(PIN_ENABLE, 1, EDGE_NONE);
*handle = open(I2C_BUS, O_RDWR | O_NOCTTY);
if((*handle <= 0) || (iInterruptFd <= 0) || (iEnableFd <= 0)) goto error;
if(ioctl(*handle, I2C_SLAVE, I2C_ADDRESS) < 0) goto error;
return 0;
error:
if (iEnableFd) close(iEnableFd);
if (iInterruptFd) close(iInterruptFd);
if (*handle) close(*handle);
return -1;
}
void tml_close(int handle)
{
if(iEnableFd) close(iEnableFd);
if(iInterruptFd) close(iInterruptFd);
if(handle) close(handle);
}
void tml_reset(int handle)
{
if(iEnableFd) write(iEnableFd, "0", 1 );
usleep(10 * 1000);
if(iEnableFd) write(iEnableFd, "1", 1 );
usleep(10 * 1000);
}
int tml_send(int handle, char *pBuff, int buffLen)
{
int ret = write(handle, pBuff, buffLen);
if(ret <= 0) return 0;
PRINT_BUF(">> ", pBuff, ret);
return ret;
}
int tml_receive(int handle, char *pBuff, int buffLen)
{
int numRead = 0;
struct timeval tv;
fd_set rfds;
int ret;
if(pnGetint())
{
FD_ZERO(&rfds);
FD_SET(handle, &rfds);
tv.tv_sec = 2;
tv.tv_usec = 1;
ret = select(handle+1, &rfds, NULL, NULL, &tv);
if(ret <= 0) return 0;
ret = read(handle, pBuff, 3);
if (ret <= 0) return 0;
numRead = 3;
if(pBuff[2] + 3 > buffLen) return 0;
ret = read(handle, &pBuff[3], pBuff[2]);
if (ret <= 0) return 0;
numRead += ret;
PRINT_BUF("<< ", pBuff, numRead);
}
return numRead;
}
int tml_transceive(int handle, char *pTx, int TxLen, char *pRx, int RxLen)
{
int NbBytes = 0;
if(tml_send(handle, pTx, TxLen) == 0) {
usleep(10 * 1000);
if(tml_send(handle, pTx, TxLen) == 0) return 0;
}
while(NbBytes==0) NbBytes = tml_receive(handle, pRx, RxLen);
return NbBytes;
}