You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
3.7 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>
#include <strings.h>
void send_ack(int addr) {
unsigned char buf[16];
buf[0] = 0xAA;
buf[1] = 2;
buf[2] = addr;
buf[3] = addr;
buf[4] = 1;
buf[5] = 1;
buf[6] = 0;
buf[7] = 0;
buf[8] = 0;
buf[9] = 0;
buf[10] = 0;
buf[11] = 0;
buf[12] = 0;
buf[13] = 0;
buf[14] = 0;
rs485_crc(buf);
rs485_send(buf);
}
void send_read_req(int addr, int channel) {
unsigned char buf[16];
buf[0] = 0xAA;
buf[1] = 0;
buf[2] = addr;
buf[3] = addr;
buf[4] = 1;
buf[5] = 1;
buf[6] = 0x40 + channel;
buf[7] = 0;
buf[8] = 0;
buf[9] = 0;
buf[10] = 0;
buf[11] = 0;
buf[12] = 0;
buf[13] = 0;
buf[14] = 0;
rs485_crc(buf);
rs485_send(buf);
}
void send_write_req(int addr, int channel, int data) {
unsigned char buf[16];
buf[0] = 0xAA;
buf[1] = 0;
buf[2] = addr;
buf[3] = addr;
buf[4] = 1;
buf[5] = 1;
buf[6] = 0x60 + channel + ((data & 0x300 ) >> 5);
buf[7] = data & 0xFF;
buf[8] = 0;
buf[9] = 0;
buf[10] = 0;
buf[11] = 0;
buf[12] = 0;
buf[13] = 0;
buf[14] = 0;
rs485_crc(buf);
rs485_send(buf);
}
void send_poll(void) {
unsigned char buf[16];
buf[0] = 0xAA;
buf[1] = 0;
buf[2] = 0;
buf[3] = 0;
buf[4] = 1;
buf[5] = 1;
buf[6] = 0;
buf[7] = 0;
buf[8] = 0;
buf[9] = 0;
buf[10] = 0;
buf[11] = 0;
buf[12] = 0;
buf[13] = 0;
buf[14] = 0;
rs485_crc(buf);
rs485_send(buf);
}
void mainloop(int fd) {
struct timeval timeout;
int rd;
fd_set rset;
fd_set wset;
fd_set eset;
int quit;
int alt;
int ret;
int req_dev;
int req_channel;
int req_data;
int req_write;
int ack_dev;
int dev_poll;
unsigned char rbuf[16];
alt = 0;
quit = 0;
req_dev = 0;
req_channel = 0;
ack_dev = 0;
dev_poll = 2;
while (!quit) {
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_ZERO(&eset);
FD_SET(fd, &rset);
FD_SET(0, &rset);
timeout.tv_sec = 0;
timeout.tv_usec = 40000;
rd = select(fd + 1, &rset, &wset, &eset, &timeout);
if (rd == 0) {
if (alt) {
send_poll();
alt = 0;
continue;
}
alt = 1;
if (ack_dev) {
send_ack(ack_dev);
ack_dev = 0;
continue;
}
if (req_dev) {
if (req_write)
send_write_req(req_dev, req_channel, req_data);
else
send_read_req(req_dev, req_channel);
req_dev = 0;
continue;
}
send_read_req(dev_poll, 0);
dev_poll++;
if (dev_poll > 126)
dev_poll = 2;
} else {
if (FD_ISSET(fd, &rset)) {
ret = rs485_recv_loop();
if (ret < 0)
exit(-1);
if (ret == 0)
continue;
rs485_recv(&rbuf);
if ((rbuf[1] == 1) && (rbuf[2] == 1))
ack_dev = rbuf[4];
if ((rbuf[2] == 1) && (rbuf[6] >= 0x40) && (rbuf[6] < 0x60)) {
printf ("R %d %d %d\n", rbuf[4], (rbuf[6] - 0x40) & 0x7, rbuf[7] + (((rbuf[6] - 0x40) & 0x18) << 5));
fflush(stdout);
}
continue;
}
if (FD_ISSET(0, &rset)) {
unsigned char a;
unsigned char ibuf[100];
int d, c, v;
unsigned char *p;
p = fgets(ibuf, 100, stdin);
if (p == NULL)
exit(-1);
sscanf(ibuf, "%c %d %d %d\n", &a, &d, &c, &v);
if (a == 'Q') {
quit = 1;
continue;
}
if (a == 'R') {
req_dev = d;
req_channel = c;
req_write = 0;
continue;
}
if (a == 'W') {
req_dev = d;
req_channel = c;
req_data = v;
req_write = 1;
continue;
}
}
}
}
}
int main(int argc, char **argv) {
char *dev = "/dev/ttyS2";
int c;
int fd;
while ((c = getopt(argc, argv, "d:")) != -1)
switch (c) {
case 'd':
dev = optarg;
break;
}
fd = rs485_open(dev);
if (fd < 0) {
printf("RS485 open failed\n");
return -1;
}
mainloop(fd);
rs485_close();
return 0;
}