You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
297 lines
7.0 KiB
297 lines
7.0 KiB
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
|
|
#include "config.h"
|
|
#include "udp.h"
|
|
#include "debug.h"
|
|
#include "z21prot.h"
|
|
#include "z21emu.h"
|
|
#include "i2csensor.h"
|
|
|
|
using namespace std;
|
|
|
|
struct s_rbussensor rbus[RBUS_MAXSENSORBYTES] = { 0 };
|
|
struct s_xlanturnout xlturn[XLAN_TURNOUT_MAX] = { 0 };
|
|
|
|
void i2cloop(I2C *i2c);
|
|
void i2cscan(I2C *i2c);
|
|
void i2ccfgprint();
|
|
int i2ccfgload(const char *fname);
|
|
int debug = 0;
|
|
void help();
|
|
|
|
|
|
int main (int argc, char **argv) {
|
|
// time_t t1, t2;
|
|
string cfgfile = DEFAULT_CONFIG;
|
|
Z21Server z21server;
|
|
I2C i2c;
|
|
int i;
|
|
int numofclients = 0;
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
if (strcmp (argv[i], "-help") == 0) {
|
|
help();
|
|
exit (0);
|
|
}
|
|
|
|
if (strcmp (argv[i], "-scan") == 0) {
|
|
i2cscan(&i2c);
|
|
i2ccfgprint();
|
|
exit (0);
|
|
}
|
|
|
|
if (strcmp (argv[i], "-debug") == 0) {
|
|
debug = 1;
|
|
}
|
|
|
|
if (strcmp (argv[i], "-config") == 0) {
|
|
i++;
|
|
cfgfile = argv[i];
|
|
printf ("using configfile: %s\n", cfgfile.c_str());
|
|
}
|
|
}
|
|
|
|
|
|
if (i2ccfgload(cfgfile.c_str()) == 0) {
|
|
i2cscan(&i2c);
|
|
}
|
|
|
|
z21server.Start();
|
|
|
|
while ( 1 ) {
|
|
//
|
|
// for detection of changed values
|
|
for (i = 0; i < RBUS_MAXSENSORBYTES; i++)
|
|
rbus[i].last = rbus[i].status;
|
|
|
|
/* t2 = time (NULL);
|
|
if (t2-t1 > 1) {
|
|
rbus_status[2]++;
|
|
rbus_status[15]--;
|
|
t1 = t2;
|
|
}
|
|
*/
|
|
if (numofclients > 0) i2cloop (&i2c);
|
|
|
|
numofclients = z21server.Loop();
|
|
usleep(25000);
|
|
};
|
|
|
|
return 0;
|
|
};
|
|
|
|
|
|
void i2cloop (I2C *i2c) {
|
|
int index; // sensorbox number --> sbox + 0x30 = i2c address
|
|
|
|
//
|
|
// digital in
|
|
for (index = 0; index < RBUS_MAXSENSORBYTES; index++) {
|
|
if (rbus[index].i2c_addr != 0) {
|
|
if (!i2c->ReadByte(rbus[index].i2c_addr, rbus[index].i2c_reg, &rbus[index].status)) {
|
|
if (debug) printf ("i2cloop: Read ADDR:%02x REG:%02x Value:%2x Error\n", rbus[index].i2c_addr, rbus[index].i2c_reg, rbus[index].status);
|
|
rbus[index].status = 0xFF; // error
|
|
}
|
|
else if (debug) {
|
|
printf ("i2cloop: Read ADDR:%02x REG:%02x Value:%2x\n", rbus[index].i2c_addr, rbus[index].i2c_reg, rbus[index].status);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// digital out
|
|
for (index = 0; index < XLAN_TURNOUTBYTES; index++) {
|
|
if (xlturn[index].last != xlturn[index].output) {
|
|
// ignore if addr is not set
|
|
if (xlturn[index].i2c_addr == 0) xlturn[index].last = xlturn[index].output;
|
|
|
|
// send data
|
|
else if (i2c->SendByte(xlturn[index].i2c_addr, xlturn[index].i2c_reg, xlturn[index].output)) {
|
|
xlturn[index].last = xlturn[index].output;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// scan all i2c devices read version and create configuration
|
|
void i2cscan(I2C *i2c) {
|
|
int dicnt;
|
|
int docnt;
|
|
int addr;
|
|
unsigned char ver;
|
|
|
|
for (dicnt = 0, docnt = 0, addr = 0x20; addr < 0x7f; addr++) {
|
|
|
|
if (i2c->ReadByte(addr, 0x20, &ver)) {
|
|
if (ver == 1) {
|
|
if (dicnt < RBUS_MAXSENSORBYTES) {
|
|
rbus[dicnt].i2c_addr = addr;
|
|
rbus[dicnt].i2c_reg = 0x0;
|
|
dicnt++;
|
|
}
|
|
if (dicnt < RBUS_MAXSENSORBYTES) {
|
|
rbus[dicnt].i2c_addr = addr;
|
|
rbus[dicnt].i2c_reg = 0x1;
|
|
dicnt++;
|
|
}
|
|
}
|
|
else if (ver == 2) {
|
|
if (dicnt < RBUS_MAXSENSORBYTES) {
|
|
rbus[dicnt].i2c_addr = addr;
|
|
rbus[dicnt].i2c_reg = 0x0;
|
|
dicnt++;
|
|
}
|
|
if (docnt < RBUS_MAXSENSORBYTES) {
|
|
xlturn[docnt].i2c_addr = addr;
|
|
xlturn[docnt].i2c_reg = 0x1;
|
|
docnt++;
|
|
}
|
|
}
|
|
else if (ver == 3 || ver == 4) {
|
|
if (dicnt < RBUS_MAXSENSORBYTES) {
|
|
rbus[dicnt].i2c_addr = addr;
|
|
rbus[dicnt].i2c_reg = 0x0;
|
|
dicnt++;
|
|
}
|
|
if (dicnt < RBUS_MAXSENSORBYTES) {
|
|
rbus[dicnt].i2c_addr = addr;
|
|
rbus[dicnt].i2c_reg = 0x1;
|
|
dicnt++;
|
|
}
|
|
if (dicnt < RBUS_MAXSENSORBYTES) {
|
|
rbus[dicnt].i2c_addr = addr;
|
|
rbus[dicnt].i2c_reg = 0x2;
|
|
dicnt++;
|
|
}
|
|
if (dicnt < RBUS_MAXSENSORBYTES) {
|
|
rbus[dicnt].i2c_addr = addr;
|
|
rbus[dicnt].i2c_reg = 0x3;
|
|
dicnt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
void i2ccfgprint() {
|
|
int i;
|
|
printf ("# autoscan configuration\n");
|
|
printf ("#\n");
|
|
printf ("# digital input configuration\n");
|
|
printf ("#\n");
|
|
printf ("# di NUM addr ADDR reg REG\n");
|
|
|
|
for (i = 0; i < RBUS_MAXSENSORBYTES; i++) if (rbus[i].i2c_addr != 0)
|
|
printf ("di %d addr %x reg %x\n", i, rbus[i].i2c_addr, rbus[i].i2c_reg);
|
|
|
|
printf ("#\n");
|
|
printf ("# digital output configuration\n");
|
|
printf ("#\n");
|
|
printf ("# do NUM addr ADDR reg REG\n");
|
|
|
|
for (i = 0; i < XLAN_TURNOUTBYTES; i++) if (xlturn[i].i2c_addr != 0)
|
|
printf ("do %d addr %x reg %x\n", i, xlturn[i].i2c_addr, xlturn[i].i2c_reg);
|
|
};
|
|
|
|
|
|
#define STR_TOK_NOSPACE(_pnt_) while (_pnt_[0] != 0 && (_pnt_[0] == ' ' || _pnt_[0] == '\t')) _pnt_++
|
|
#define STR_TOK_NEXT(_pnt_) while (_pnt_[0] != 0 && _pnt_[0] != ' ' && _pnt_[0] != '\t') _pnt_++
|
|
int i2ccfgload(const char *fname) {
|
|
FILE *f;
|
|
char buf[1024];
|
|
char *pos;
|
|
int index = -1;
|
|
int type;
|
|
int addr;
|
|
int reg;
|
|
|
|
printf ("loading file: %s\n", fname);
|
|
f = fopen (fname, (char*)"r");
|
|
if (f == NULL) {
|
|
printf ("error:%s\n", strerror(errno));
|
|
return 0;
|
|
}
|
|
|
|
while (fgets (buf, sizeof (buf), f) != NULL) {
|
|
pos = buf;
|
|
if (pos[0] == '#') continue;
|
|
type = I2CREGTYPE_UNDEF;
|
|
addr = 0;
|
|
reg = 0;
|
|
index = -1;
|
|
|
|
while (pos != NULL && pos[0] != 0) {
|
|
STR_TOK_NOSPACE(pos);
|
|
if (strncmp ("di", pos, strlen ("di")) == 0) {
|
|
STR_TOK_NEXT(pos);
|
|
sscanf (pos, "%d", &index);
|
|
type = I2CREGTYPE_DI;
|
|
printf (" di %d", index);
|
|
}
|
|
if (strncmp ("do", pos, strlen ("do")) == 0) {
|
|
STR_TOK_NEXT(pos);
|
|
sscanf (pos, "%d", &index);
|
|
type = I2CREGTYPE_DO;
|
|
printf (" do %d", index);
|
|
}
|
|
if (strncmp ("addr", pos, strlen ("addr")) == 0) {
|
|
STR_TOK_NEXT(pos);
|
|
sscanf (pos, "%x", &addr);
|
|
printf (" addr %x", addr);
|
|
}
|
|
if (strncmp ("reg", pos, strlen ("reg")) == 0) {
|
|
STR_TOK_NEXT(pos);
|
|
sscanf (pos, "%x", ®);
|
|
printf (" reg %x", reg);
|
|
}
|
|
else STR_TOK_NEXT(pos);
|
|
}
|
|
|
|
if (type == I2CREGTYPE_DI && index >= 0 && index < RBUS_MAXSENSORBYTES) {
|
|
rbus[index].i2c_addr = addr;
|
|
rbus[index].i2c_reg = reg;
|
|
printf ("--> DI (%d) OK\n", index);
|
|
}
|
|
else if (type == I2CREGTYPE_DO && index >= 0 && index < XLAN_TURNOUTBYTES) {
|
|
xlturn[index].i2c_addr = addr;
|
|
xlturn[index].i2c_reg = reg;
|
|
printf ("--> DO (%d) OK\n", index);
|
|
}
|
|
else {
|
|
printf (" error\n");
|
|
}
|
|
}
|
|
fclose (f);
|
|
return 0;
|
|
};
|
|
#undef STR_TOK_NEXT
|
|
|
|
|
|
void help () {
|
|
printf ("z21emu:\n");
|
|
printf ("=======\n");
|
|
printf ("\n");
|
|
printf ("parameters: without any parameters the config will be read from file.\n");
|
|
printf (" if no file is found, autoscan is used first.\n");
|
|
printf (" -scan scanning i2c bus and print out a sample device config\n");
|
|
printf (" -debug enabling debugging\n");
|
|
printf (" -config FILE finename used for configuration (default %s/\n", DEFAULT_CONFIG);
|
|
printf ("\n");
|
|
}
|
|
|
|
void xlan_turnout (int addr, bool enable) {
|
|
int addrbyte = (addr-1)/8;
|
|
int bit = (addr-1)%8;
|
|
|
|
if (addr == 0) return;
|
|
if (addrbyte < 0 || addrbyte >= XLAN_TURNOUTBYTES) return;
|
|
if (enable) xlturn[addrbyte].output |= (1 << bit);
|
|
else xlturn[addrbyte].output &= ~(1 << bit);
|
|
}
|
|
|
|
|