-
Notifications
You must be signed in to change notification settings - Fork 3
/
linuxwattson.c
executable file
·187 lines (161 loc) · 5.18 KB
/
linuxwattson.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
/* openwattson - Linux specific library functions
* This file contains the common functions that are unique to
* Linux. The entire file is ignored in case of Windows
*
* Version 0.1
*
* Control Wattson power meter
*
* Copyright 2010, Kary Främling, Jan Nyman
* This program is published under the GNU General Public license
*/
#ifndef WIN32
#define DEBUG 0
#include <errno.h>
#include <sys/file.h>
#include "rwwattson.h"
/********************************************************************
* open_wattson, Linux version
*
* Input: devicename (/dev/tty0, /dev/tty1 etc)
*
* Returns: Handle to the Wattson (type WATTSON)
*
********************************************************************/
WATTSON open_wattson(char *device)
{
WATTSON wattson;
struct termios adtio;
int portstatus;
//Setup serial port
if ((wattson = open(device, O_RDWR | O_NOCTTY)) < 0)
{
printf("\nUnable to open serial device %s\n", device);
exit(EXIT_FAILURE);
}
if ( flock(wattson, LOCK_EX) < 0 ) {
perror("\nSerial device is locked by other program\n");
exit(EXIT_FAILURE);
}
//We want full control of what is set and simply reset the entire adtio struct
memset(&adtio, 0, sizeof(adtio));
// Serial control options
adtio.c_cflag &= ~PARENB; // No parity
adtio.c_cflag &= ~CSTOPB; // One stop bit
adtio.c_cflag &= ~CSIZE; // Character size mask
adtio.c_cflag |= CS8; // Character size 8 bits
adtio.c_cflag |= CREAD; // Enable Receiver
adtio.c_cflag &= ~HUPCL; // No "hangup"
adtio.c_cflag &= ~CRTSCTS; // No flowcontrol
adtio.c_cflag |= CLOCAL; // Ignore modem control lines
// Baudrate, for newer systems
cfsetispeed(&adtio, BAUDRATE);
cfsetospeed(&adtio, BAUDRATE);
// Serial local options: adtio.c_lflag
// Raw input = clear ICANON, ECHO, ECHOE, and ISIG
// Disable misc other local features = clear FLUSHO, NOFLSH, TOSTOP, PENDIN, and IEXTEN
// So we actually clear all flags in adtio.c_lflag
adtio.c_lflag = 0;
// Serial input options: adtio.c_iflag
// Disable parity check = clear INPCK, PARMRK, and ISTRIP
// Disable software flow control = clear IXON, IXOFF, and IXANY
// Disable any translation of CR and LF = clear INLCR, IGNCR, and ICRNL
// Ignore break condition on input = set IGNBRK
// Ignore parity errors just in case = set IGNPAR;
// So we can clear all flags except IGNBRK and IGNPAR
adtio.c_iflag = IGNBRK|IGNPAR;
// Serial output options
// Raw output should disable all other output options
adtio.c_oflag &= ~OPOST;
adtio.c_cc[VTIME] = 10; // timer 1s
adtio.c_cc[VMIN] = 0; // blocking read until 1 char
if (tcsetattr(wattson, TCSANOW, &adtio) < 0)
{
printf("Unable to initialize serial device");
exit(0);
}
tcflush(wattson, TCIOFLUSH);
// Set DTR low and RTS high and leave other ctrl lines untouched
ioctl(wattson, TIOCMGET, &portstatus); // get current port status
portstatus &= ~TIOCM_DTR;
portstatus |= TIOCM_RTS;
ioctl(wattson, TIOCMSET, &portstatus); // set current port status
return wattson;
}
/********************************************************************
* close_wattson, Linux version
*
* Input: Handle to the weatherstation (type WEATHERSTATION)
*
* Returns nothing
*
********************************************************************/
void close_wattson(WATTSON wattson)
{
close(wattson);
return;
}
int writeport(int fd, char *chars) {
int len = strlen(chars);
chars[len] = 0x0d; // stick a <CR> after the command
chars[len+1] = 0x00; // terminate the string properly
int n = write(fd, chars, strlen(chars));
if (n < 0) {
fputs("write failed!\n", stderr);
return -1;
}
return n;
}
int readport(int fd, char *result) {
int iIn = read(fd, result, 254);
result[iIn-1] = 0x00;
if (iIn < 0) {
if (errno == EAGAIN) {
printf("SERIAL EAGAIN ERROR\n");
return -1;
} else {
printf("SERIAL read error %d %s\n", errno, strerror(errno));
return -1;
}
}
return iIn;
}
int getbaud(int fd) {
struct termios termAttr;
int inputSpeed = -1;
speed_t baudRate;
tcgetattr(fd, &termAttr);
/* Get the input speed. */
baudRate = cfgetispeed(&termAttr);
switch (baudRate) {
case B0: inputSpeed = 0; break;
case B50: inputSpeed = 50; break;
case B110: inputSpeed = 110; break;
case B134: inputSpeed = 134; break;
case B150: inputSpeed = 150; break;
case B200: inputSpeed = 200; break;
case B300: inputSpeed = 300; break;
case B600: inputSpeed = 600; break;
case B1200: inputSpeed = 1200; break;
case B1800: inputSpeed = 1800; break;
case B2400: inputSpeed = 2400; break;
case B4800: inputSpeed = 4800; break;
case B9600: inputSpeed = 9600; break;
case B19200: inputSpeed = 19200; break;
case B38400: inputSpeed = 38400; break;
}
return inputSpeed;
}
/********************************************************************
* mySleep - Linux version
*
* Inputs: Time in microseconds (integer)
*
* Returns: nothing
*
********************************************************************/
void mySleep(int microseconds)
{
usleep(microseconds);
}
#endif