Compare commits

..

No commits in common. 'master' and 'origin' have entirely different histories.

24
.gitignore vendored

@ -1,24 +0,0 @@
.cproject
.project
.settings
gmon.out
*/.depend
server/gmon.out
server/modelbahn-cgi
server/modelbahn-server
server/test-json
z21emu/gmon.out
z21emu/config.h
z21emu/z21emu
*~
*.oo
*.o
*.elf
*.bin
track.json
track.json.backup.*
Modelbahn.anjuta
*.track.json
Backup/
.anjuta_sym_db.db
.anjuta/

@ -1,51 +1,3 @@
2024-01-04:
- fixed: AutoCheckWaySingleStep: stops preparing way at next block
2024-01-16:
- fixed: not all pthread_mutexes has been initialization.
2023-12-30:
- fixed: FindWay will check for loops between two blocks
2023-12-27:
- split blocks do work.
- fixed issues with the way finding routine
2023-05-01:
- another work on the split blocks. long trains wont go into split blocks. Some final
checks are still needed to implement.
2023-04-02:
- fixed: track infomation is fixed.
- removed unneded debug file
2023-03-13:
- prepared split and short tracks. - needs to be tested completly.
2022-04-17:
- added "-simulation" parmeter for debugging purpose.
needed to simulate turnout manipulation
- fixed: locomotive AUTO->MAN mode is working if searching for a new way.
2022-02-13:
- Interfaces are now virtual classes.
2021-12-19:
- adding sensor context menu for sensor simulation
2021-12-10:
- adding support for scheduling ways
- fixed: webinterface, update on loco will now change its detail display
2021-12-02:
- mark blocks as onlyCARGO or onlyPESSANGER, random-automode looks nice now.
- webinterface: debug messages will be print to the console.
- webinterface: contextmenu will be displayed inside the visible area
2021-11-06:
- fixed: compiling error on compare with pointer
2021-03-09:
- changed: passenger trains (no cargo flag set) will always stop at stations.
- added station flag to blocks
@ -60,7 +12,7 @@
2021-01-31:
- automtic mode is improving, manual setting of destination
automatic routing and moving the train to the destination.
autoatic routing and moving the train to the destination.
- locked turnouts can not anymore been set.
- assign loco and set destination is working now.

@ -1,9 +0,0 @@
TOPTARGETS := all clean
SUBDIRS := server
$(TOPTARGETS): $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $@ $(MAKECMDGOALS)
.PHONY: $(TOPTARGETS) $(SUBDIRS)

@ -1,34 +0,0 @@
# Modelbahn
## Requirements:
Webserver with CGI enabled
## Installation:
+ copy the webinterface files to your location of the webserver
+ compile the server
+ copy the modelbahn-cgi binary to the cgi folder of the webserver
+ run the modelbahn-server application.
![Screenshot](https://steffen.gulpe.de/progs/modelbahn.png)
## Z21EMU and ATmega Sensors
Per default all devices get the same I2C defive address. As soon as the device is connected you should set up a new address for them. The following commands will set the device [0x2f] to address 0x31 and save this setting in the EPROM.
i2cset -y 1 0x2f 0x22 0x31
i2cset -y 1 0x2f 0x21 0x02
The following registers are used:
0x00 .. 0x08 INPUT and OUTPUT registers dependung on device
0x20 VERSION of the device
0x21 Command Register
0 no command
1 EEPROM read
2 EEPORM write
0x22 I2C Address
0x23 Input Off Delay

@ -0,0 +1,11 @@
Requirements:
- Webserver with CGI enabled
Installation:
- copy the webinterface files to your location of the webserver
- compile the server
- copy the modelbahn-cgi binary to the cgi folder of the webserver
- run the modelbahn-server application.

Binary file not shown.

@ -9,16 +9,16 @@ ETCPREFIX=/etc
DISTNAME=modelbahn
CXX=g++
CXXFLAGS= -Wall -ggdb -fPIC -Wno-write-strings -g -ggdb -std=c++11 -pg
CXXFLAGS= -ggdb -fPIC -Wno-write-strings -g -ggdb -std=c++11 -pg
LDFLAGS= -lm -lc -lpthread -L/usr/local/lib -g -ggdb -pg
LDFLAGS_CGI= -lm -lc -lpthread -L/usr/local/lib -g -ggdb
LDFLAGS_CGI= -lm -lc -lpthread -L/usr/local/lib -g -ggdb -pg
DEPENDFILE=.depend
TARGET=modelbahn-server
SERVEROBJ=server.o network.o session.o server-loadsave.o debug.o \
json.o main.o sensor.o turnout.o railway.o interfaces.o locomotive.o \
block.o interface.o interface-z21.o
json.o main.o sensor.o turnout.o railway.o interface.o locomotive.o \
block.o interface-z21.o
CURDIR=`pwd`

@ -1,19 +1,12 @@
#include <string>
#include "modelbahn.h"
#include "block.h"
#include <list>
#include <string>
#include <string.h>
using namespace std;
Blocks::Blocks () {
pthread_mutex_init(&mtx, NULL);
changed = 0;
blocks = (Block*) malloc(sizeof(Block)*SENSORS_MAX);
memset (blocks, 0x0, sizeof(Block)*SENSORS_MAX);
max = BLOCKS_MAX;
last_blockidx = -1;
};
@ -42,24 +35,16 @@ int Blocks::UnLock() {
JSONParse Blocks::_GetJSON(Block *bl) {
JSONParse json;
JSONElement je;
string s = "";
json.Clear();
json.AddObject("name", bl->name);
s = bl->name; json.AddObject("name", s);
json.AddObject("flags", bl->flags);
json.AddObject("lockedby", bl->lockedby);
json.AddObject("sensor_enter_0", bl->s_enter[0]);
json.AddObject("sensor_slow_0", bl->s_slow[0]);
json.AddObject("sensor_stop_0", bl->s_stop[0]);
json.AddObject("sensor_shortstop_0", bl->s_shortstop[0]);
json.AddObject("sensor_enter_1", bl->s_enter[1]);
json.AddObject("sensor_slow_1", bl->s_slow[1]);
json.AddObject("sensor_stop_1", bl->s_stop[1]);
json.AddObject("sensor_shortstop_1", bl->s_shortstop[1]);
json.AddObject("secondblock", bl->secondblock);
json.AddObject("sensor_pos_1", bl->s_pos_1);
json.AddObject("sensor_center", bl->s_center);
json.AddObject("sensor_neg_1", bl->s_neg_1);
return json;
};
@ -112,50 +97,23 @@ Block Blocks::GetBlockFromJSON(JSONParse *j) {
string s;
bl.name[0] = 0;
bl.secondblock[0] = 0;
bl.flags = 0;
bl.lockedby[0] = 0;
j->GetValue("name", &s);
strncpy (bl.name, s.c_str(), REFERENCENAME_LEN);
j->GetValueInt("flags", &bl.flags);
// j->GetValue("lockedby", &s);
// strncpy (bl.lockedby, s.c_str(), REFERENCENAME_LEN);
//
// old version input data
//
s = "";
if (j->GetValue("sensor_pos_1", &s)) {
strncpy (bl.s_enter[0], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_stop[1], s.c_str(), REFERENCENAME_LEN);
}
s = "";
if (j->GetValue("sensor_center", &s)) {
strncpy (bl.s_shortstop[0], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_shortstop[1], s.c_str(), REFERENCENAME_LEN);
}
s = "";
if (j->GetValue("sensor_neg_1", &s)) {
strncpy (bl.s_enter[1], s.c_str(), REFERENCENAME_LEN);
strncpy (bl.s_stop[0], s.c_str(), REFERENCENAME_LEN);
}
//
// new version
//
s = ""; if (j->GetValue("sensor_enter_0", &s)) strncpy (bl.s_enter[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_enter_1", &s)) strncpy (bl.s_enter[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_slow_0", &s)) strncpy (bl.s_slow[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_slow_1", &s)) strncpy (bl.s_slow[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_stop_0", &s)) strncpy (bl.s_stop[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_stop_1", &s)) strncpy (bl.s_stop[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_shortstop_0", &s)) strncpy (bl.s_shortstop[0], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("sensor_shortstop_1", &s)) strncpy (bl.s_shortstop[1], s.c_str(), REFERENCENAME_LEN);
s = ""; if (j->GetValue("secondblock", &s)) strncpy (bl.secondblock, s.c_str(), REFERENCENAME_LEN);
s = ""; j->GetValue("sensor_pos_1", &s);
strncpy (bl.s_pos_1, s.c_str(), REFERENCENAME_LEN);
s = ""; j->GetValue("sensor_center", &s);
strncpy (bl.s_center, s.c_str(), REFERENCENAME_LEN);
s = ""; j->GetValue("sensor_neg_1", &s);
strncpy (bl.s_neg_1, s.c_str(), REFERENCENAME_LEN);
printf ("%s:%d block: %s flags: %d\n", __FILE__, __LINE__, bl.name, bl.flags);
return bl;
};
@ -253,7 +211,7 @@ int Blocks::SetLockedby (string blname, string lockedby, int lock_onoff) {
Block *bl = NULL;
JSONParse jp;
int res = -1;
int x, y, cnt;
int x, y;
debug (0, "Blocks::SetLockedby block:'%s' locked for '%s' locked:%d", blname.c_str(), lockedby.c_str(), lock_onoff);
@ -266,8 +224,7 @@ int Blocks::SetLockedby (string blname, string lockedby, int lock_onoff) {
if(network) network->ChangeListPushToAll(jp.ToString());
x = -1; y = -1;
cnt = 0;
while (server->railways.FindReference(&x, &y, blname, (cnt++))) {
while (server->railways.FindReference(&x, &y, blname)) {
server->railways.SetLockedby(x, y, lockedby, lock_onoff);
}
@ -303,22 +260,6 @@ string Blocks::GetLockedby (string blname) {
};
string Blocks::GetSecondBlock(string block) {
Block *bl = NULL;
string sb;
Lock();
if ((bl = FindBlock(block)) != NULL) {
sb = bl->secondblock;
UnLock();
return sb;
}
UnLock();
return "";
}
Block* Blocks::FindBlock(string name) {
Block *bl = NULL;
@ -383,125 +324,43 @@ int Blocks::GetFlags (string blname) {
};
/*
* return a pointer to the blockdata in case of split blocks also return the second block
*/
int Blocks::GetBlocksPtr (string blname, Block **b1, Block **b2) {
int i;
(*b1) = NULL;
(*b2) = NULL;
for (i = 0; i < max; i++) if (blname.compare(blocks[i].name) == 0) {
(*b1) = &blocks[i];
}
if ((*b1) == NULL) {
debug (0, "Blocks::%s Could not find block: %s", __FUNCTION__, blname.c_str());
return 0;
}
if ((*b1)->flags & BLOCK_F_SPLIT) {
for (i = 0; i < max; i++) if (strcmp ((*b1)->secondblock, blocks[i].name) == 0) {
(*b2) = &blocks[i];
}
if ((*b2) == NULL) {
debug (0, "Blocks::%s Could not find second block: %s", __FUNCTION__, (*b1)->secondblock);
return 0;
}
}
return 1;
}
string Blocks::GetSensorEnter (int direction, string blname, int locoflags) {
string Blocks::GetSensorMinus (string blname) {
string res = "";
int i;
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_enter[direction];
else res = b2->s_enter[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_enter[direction];
else res = b1->s_enter[direction];
}
}
if (res.length() == 0) {
res = b1->s_enter[direction];
for (i = 0; i < max; i++) if (blname.compare(blocks[i].name) == 0) {
res = blocks[i].s_neg_1;
}
UnLock();
return res;
};
string Blocks::GetSensorSlow (int direction, string blname, int locoflags) {
string Blocks::GetSensorCenter (string blname) {
string res = "";
int i;
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_slow[direction];
else res = b1->s_slow[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_slow[direction];
else res = b2->s_slow[direction];
}
}
if (res.length() == 0) {
res = b1->s_slow[direction];
}
if (res.length() == 0) {
res = b1->s_enter[direction];
for (i = 0; i < max; i++) if (blname.compare(blocks[i].name) == 0) {
res = blocks[i].s_center;
}
UnLock();
return res;
};
string Blocks::GetSensorStop (int direction, string blname, int locoflags) {
string Blocks::GetSensorPlus (string blname) {
string res = "";
int i;
JSONParse jp;
Block *b1 = NULL;
Block *b2 = NULL;
Lock();
if (!GetBlocksPtr(blname, &b1, &b2)) return res;
if ((locoflags & LOCO_F_SHORTTRAIN) && b1->s_shortstop[direction][0] != 0)
res = b1->s_shortstop[direction];
if (!(locoflags & LOCO_F_SHORTTRAIN) && (b1->flags & BLOCK_F_SPLIT)) {
if (direction == 0) {
if (b1->flags & BLOCK_F_SPLITPOS) res = b2->s_stop[direction];
else res = b1->s_stop[direction];
}
else {
if (b1->flags & BLOCK_F_SPLITPOS) res = b1->s_stop[direction];
else res = b2->s_stop[direction];
}
}
if (res.length() == 0) {
res = b1->s_stop[direction];
for (i = 0; i < max; i++) if (blname.compare(blocks[i].name) == 0) {
res = blocks[i].s_pos_1;
}
UnLock();
return res;
};

@ -2,55 +2,22 @@
#ifndef _BLOCK_H_
#define _BLOCK_H_
#include <list>
#include <string>
#include <string.h>
using namespace std;
#include "modelbahn.h"
#include "server.h"
#define BLOCK_F_OFF 0x0001
#define BLOCK_F_SPLIT 0x0002 // is this a split block? only works for short
#define BLOCK_F_SPLITPOS 0x0004 // is this a split block? only works for short
#define BLOCK_F_SHORT 0x0010
#define BLOCK_F_LONG 0x0020
#define BLOCK_F_ENDSTATION 0x0040
#define BLOCK_F_STATION 0x0080
#define BLOCK_F_SPEEDLIMIT 0x0100
#define BLOCK_F_ONLYCARGO 0x0200
#define BLOCK_F_ONLYPASSENGER 0x0400
/*
* FIXME: long trains on split blocks
* FIXME: sample how to set up positive entry side
*
* Dirction Pos: from Left to Right Neg: from Right to Left
* Dirction Pos: from Top to Bottom Neg: from Bottom to Top
*
* pos SPLIT BLOCK neg SPLIT BLOCK
* F_SPLIT | F_SPLITPOS F_SPLIT
* >----o-------------o------o-------------o---> entry direction
*
* ^ ^ ^
* | | |
* s_enter[0] s_shortstop[0] | positive_block
* s_stop[0] negative block
*/
struct s_Block {
char name[REFERENCENAME_LEN];
// default sensors [0].. positive side [1] negative side
char s_enter[2][REFERENCENAME_LEN];
char s_slow[2][REFERENCENAME_LEN];
char s_stop[2][REFERENCENAME_LEN];
char s_shortstop[2][REFERENCENAME_LEN];
char secondblock[REFERENCENAME_LEN]; // short two blocks segment.
char s_pos_1[REFERENCENAME_LEN]; //
char s_center[REFERENCENAME_LEN];
char s_neg_1[REFERENCENAME_LEN];
int flags;
char lockedby[REFERENCENAME_LEN]; // element locked by locreference (only set by server, not by JSON/Webinterface)
@ -72,7 +39,6 @@ class Blocks {
int last_blockidx; // to speed up things
Block* FindBlock(string name);
int GetBlocksPtr(string blname, Block **b1, Block **b2);
public:
Blocks();
~Blocks();
@ -90,11 +56,10 @@ class Blocks {
int SetOff(string blname);
int IsOff(string blname);
string GetSensorEnter (int direction, string blname, int locoflags);
string GetSensorSlow (int direction, string blname, int locoflags);
string GetSensorStop (int direction, string blname, int locoflags);
string GetSensorMinus (string blname);
string GetSensorCenter (string blname);
string GetSensorPlus (string blname);
int GetFlags (string blname);
string GetSecondBlock(string block);
int SetLockedby (string blname, string lockedby, int lock_onoff);
string GetLockedby (string blname);

@ -2,49 +2,32 @@
// #define _GNU_SOURCE /* See feature_test_macros(7) */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <execinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/time.h>
#include "modelbahn.h"
#define DEBUG_FILE "/tmp/modelbahn-server.log"
#define LEN_TEXT 256
int _debuglevel = 0xff;
pid_t gettid();
void debug (int type, char *fmt,...) {
va_list args;
char texttime[LEN_TEXT];
char text1[DEBUG_TEXT1LEN];
char text2[DEBUG_TEXT2LEN];
pid_t pid = gettid();
int tms;
struct timeval tv;
struct tm tmp;
struct tm *tmptr = NULL;
va_start (args, fmt);
vsnprintf (text1, (DEBUG_TEXT1LEN-1), fmt, args);
va_end (args);
texttime[0] = 0;
text1[DEBUG_TEXT1LEN-1] = 0;
text2[DEBUG_TEXT2LEN-1] = 0;
gettimeofday (&tv, NULL);
tmptr = localtime_r(&tv.tv_sec, &tmp);
if (tmptr != NULL)
strftime(texttime, LEN_TEXT, "%H:%M:%S", &tmp);
if (type > 0) snprintf (text2, DEBUG_TEXT2LEN-1, "(%d, %s.%03d) %d : %s", pid, texttime, tv.tv_usec/1000, type, text1);
else snprintf (text2, DEBUG_TEXT2LEN-1, "(%d, %s.%03d) : %s", pid, texttime, tv.tv_usec/1000, text1);
if (type > 0) snprintf (text2, DEBUG_TEXT2LEN-1, "(%d)%d: %s", pid, type, text1);
else snprintf (text2, DEBUG_TEXT2LEN-1, "(%d) %s", pid, text1);
if (type == 0 || (type & _debuglevel) != 0) {
FILE *f;

@ -33,14 +33,11 @@ static unsigned char RX_RMBUS_DATACHANGED[] { 0x0F, 0x00, 0x80, 0x00 };
#define Z21_IDX_SETTURNOUT_CHK 8
InterfaceZ21::InterfaceZ21 () {
debug (DEBUG_INFO | DEBUG_IFACE, "InterfaceZ21:%s", __FUNCTION__);
status_connected = false;
status_poweron = false;
status_programmingmode = false;
status_shortcircuit = false;
status_emergencystop = false;
timer_start(&turnouttimeout);
send_logon = false;
@ -48,6 +45,7 @@ InterfaceZ21::InterfaceZ21 () {
rmsensorinit = 0;
serial = "";
hostname = "";
timeout = time(NULL);
rmgetdatatimeout = time(NULL) - INTF_Z21_RMGETDATA_TIMEOUT;
};
@ -57,11 +55,11 @@ InterfaceZ21::~InterfaceZ21() {
};
void InterfaceZ21::Connect () {
debug (DEBUG_INFO | DEBUG_IFACE, "InterfaceZ21: Connect %s to: %s", name, host);
void InterfaceZ21::Connect (string destination) {
debug (DEBUG_INFO | DEBUG_IFACE, "%s:%d Connect to: %s", __FILE__, __LINE__, destination.c_str());
if (status_connected) Disconnect();
hostname = destination;
if (udp.Listen(0) == 0) {
debug (DEBUG_ERROR | DEBUG_IFACE, "%s:%d Error could not bind UDP socket (%s)",
@ -99,18 +97,12 @@ void InterfaceZ21::Disconnect() {
//
// check if we are connected and for timeouts.
// read and go through incoming data
int InterfaceZ21::Loop() {
int InterfaceZ21::Loop(string interfacename) {
time_t curtime = time(NULL);
string source;
int inlen;
int i;
// debug (DEBUG_INFO | DEBUG_IFACE, "* InterfaceZ21 (%s) Loop", name);
flags &= ~(INTF_F_CONNECTED | INTF_F_POWER | INTF_F_STOP | INTF_F_SHORT_CIRCUIT | INTF_F_PROGRAMMING);
if (needs_update) {
needs_update = 0;
}
int update = false;
if (status_connected) {
//
@ -118,14 +110,14 @@ int InterfaceZ21::Loop() {
if ((timeout + 2 * INTF_Z21_TIMEOUT) < curtime) {
debug (DEBUG_ERROR | DEBUG_IFACE, "%s:%d connection timed out (%d)", __FILE__, __LINE__, curtime-(timeout + 2 * INTF_Z21_TIMEOUT));
Disconnect();
needs_update = true;
update = true;
}
else if (send_logon == false && (timeout + INTF_Z21_TIMEOUT) < curtime) {
send_logon = true;
send_GET_SERIAL_NUMBER();
send_SET_BROADCASTFLAGS();
timeout = time(NULL);
needs_update = true;
update = true;
}
//
@ -144,7 +136,7 @@ int InterfaceZ21::Loop() {
if ((inlen = udp.ReadTimeout(&source, inbuffer, INTF_Z21_INBUFFER, 10)) > 0) {
//
// got some data
debug (DEBUG_INFO | DEBUG_IFACE, "%s:%d [%s] got some data.", __FILE__, __LINE__, name);
//
// check for LAN_SYSTEMSTATE_DATACHANGED
if (memcmp (inbuffer, RX_GET_SERIAL_NUMBER, sizeof(RX_GET_SERIAL_NUMBER)) == 0) {
@ -157,13 +149,13 @@ int InterfaceZ21::Loop() {
if (memcmp (inbuffer, RX_X_GET_TURNOUT_INFO, sizeof(RX_X_GET_TURNOUT_INFO)) == 0) {
// got turnout information
int addr = 0;
addr = ((unsigned char)inbuffer[Z21_IDX_SETTURNOUT_ADRH] << 8) + (unsigned char)inbuffer[Z21_IDX_SETTURNOUT_ADRL];
debug (0, "%s:%d Interface-Z21: TurnoutInformation Addr:%d", __FILE__, __LINE__, addr);
if (inbuffer[Z21_IDX_SETTURNOUT_MODE] == 2)
server->TurnoutAddrMode(name, addr, 1);
server->TurnoutAddrMode(interfacename, addr, 1);
else if (inbuffer[Z21_IDX_SETTURNOUT_MODE] == 1)
server->TurnoutAddrMode(name, addr, 0);
server->TurnoutAddrMode(interfacename, addr, 0);
}
@ -174,14 +166,20 @@ int InterfaceZ21::Loop() {
int cs = (unsigned char) inbuffer[16];
int csex = (unsigned char) inbuffer[17];
bool old_poweron = status_poweron;
bool old_shortcircuit = status_shortcircuit;
bool old_programmingmode = status_programmingmode;
bool old_connected = status_connected;
bool old_emergencystop = status_emergencystop;
status_emergencystop = (cs & INTF_Z21_CS_EmergencyStop);
status_poweron = (cs & INTF_Z21_CS_TrackVoltageOff);
status_shortcircuit = (cs & INTF_Z21_CS_ShortCircuit);
status_programmingmode = (cs & INTF_Z21_CS_ProgModeActive);
debug (0, "%s:%d Name:%s cs:%d csex:%d", __FILE__, __LINE__, name, cs, csex);
debug (0, "%s:%d cs:%d csex:%d", __FILE__, __LINE__, cs, csex);
needs_update = true;
update = true;
//if ( old_poweron != status_poweron ||
// old_shortcircuit != status_shortcircuit ||
// old_programmingmode != status_programmingmode ||
@ -218,7 +216,7 @@ int InterfaceZ21::Loop() {
debug (0, "%s:%d Loc:%d Speed:%d", __FILE__, __LINE__, loconet_map[inloc].addr, inspeed);
if (loconet_map[inloc].addr > 0) {
int speed = inspeed;
server->LocomotiveAddrSpeed(name, loconet_map[inloc].addr, speed);
server->LocomotiveAddrSpeed(interfacename, loconet_map[inloc].addr, speed);
}
}
loconet_last.addr = 0;
@ -237,7 +235,7 @@ int InterfaceZ21::Loop() {
debug (0, "%s:%d Loc:%d Function:%d", __FILE__, __LINE__, loconet_map[inloc].addr, infunc);
if (loconet_map[inloc].addr > 0) {
server->LocomotiveAddrFunction(name, loconet_map[inloc].addr, infunc);
server->LocomotiveAddrFunction(interfacename, loconet_map[inloc].addr, infunc);
}
loconet_last.addr = 0;
@ -248,9 +246,9 @@ int InterfaceZ21::Loop() {
// check for LAM_RMBUS_DATACHANGED
else if (memcmp (inbuffer, RX_RMBUS_DATACHANGED, sizeof(RX_RMBUS_DATACHANGED)) == 0) {
int group = (unsigned char)inbuffer[4];
int idx;
int idx, bit;
printf ("LAN_RMBUS_DATA_CHANGE[%s] ", name);
printf ("LAN_RMBUS_DATA_CHANGE[%s] ", interfacename.c_str());
for (idx = 0; idx < INTF_Z21_RMSENSOR_BYTES * INTF_Z21_RMSENSOR_GROUPS; idx++) {
printf ("%x ", (unsigned char) inbuffer[4+idx]);
}
@ -267,9 +265,9 @@ int InterfaceZ21::Loop() {
for (idx = 0; idx < INTF_Z21_RMSENSOR_GROUPS*INTF_Z21_RMSENSOR_BYTES; idx++) {
if (rmsold[idx]^rmsensors[idx]) {
for (i = 0; i < 8; i++) if (rmsensorinit || (rmsold[idx] & 1 << i) != (rmsensors[idx] & 1 << i)) {
debug (0, "Sendor Data Changed: %s[%d]", name, idx*8+i);
if (rmsensors[idx] & 1 << i) server->SensorAddrChange(name, idx*8+i, 1);
else server->SensorAddrChange(name, idx*8+i, 0);
debug (0, "Sendor Data Changed: %s[%d]", interfacename.c_str(), idx*8+i);
if (rmsensors[idx] & 1 << i) server->SensorAddrChange(interfacename, idx*8+i, 1);
else server->SensorAddrChange(interfacename, idx*8+i, 0);
}
}
}
@ -278,7 +276,7 @@ int InterfaceZ21::Loop() {
}
else {
printf ("InterfaceZ21(%s) Got some Data:", name);
printf ("InterfaceZ21(%s) Got some Data:", interfacename.c_str());
for (i = 0; i < inlen; i++) {
int z = (unsigned char) inbuffer[i];
printf ("%02x:", z);
@ -294,12 +292,7 @@ int InterfaceZ21::Loop() {
}
}
if (IsConnected()) flags |= INTF_F_CONNECTED;
if (IsPoweron()) flags |= INTF_F_POWER;
if (IsEmergencyStop()) flags |= INTF_F_STOP;
if (IsSortCircuit()) flags |= INTF_F_SHORT_CIRCUIT;
return needs_update;
return update;
};
@ -307,14 +300,14 @@ int InterfaceZ21::Loop() {
// send_SET_BROADCASTFLAGS();
void InterfaceZ21::send_SET_BROADCASTFLAGS() {
unsigned char buffer[] = { 0x08, 0x00, 0x50, 0x00, 0x0F, 0x01, 0x00, 0x03 };
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
}
//
// send_GET_SERIAL_NUMBER
void InterfaceZ21::send_GET_SERIAL_NUMBER() {
unsigned char buffer[] = { 0x04, 0x00, 0x10, 0x00 };
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
}
@ -324,7 +317,7 @@ void InterfaceZ21::send_RM_GETDATA(int group) {
unsigned char buffer[] = { 0x05, 0x00, 0x81, 0x00, 0x00 };
if (group < INTF_Z21_RMSENSOR_GROUPS) {
buffer[4] = (unsigned char)group;
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
}
}
@ -335,7 +328,7 @@ void InterfaceZ21::send_LOGOFF() {
if (status_connected == false) return;
unsigned char buffer[] = { 0x04, 0x00, 0x30, 0x00 };
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
}
@ -387,16 +380,16 @@ void InterfaceZ21::SetLocoSpeed(Locomotive *l, int step) {
//
// XOR Byte
for (int i = 4; i < (int) sizeof (buffer)-1; i++)
for (int i = 4; i < sizeof (buffer)-1; i++)
buffer[Z21_IDX_SETLOCO_DRIVE_CHK] = (unsigned char)buffer[Z21_IDX_SETLOCO_DRIVE_CHK] xor (unsigned char)buffer[i];
printf ("Send Data:");
for (int i = 0; i < (int)sizeof (buffer); i++) {
for (int i = 0; i < sizeof (buffer); i++) {
int z = (unsigned char) buffer[i];
printf ("%02x:", z);
}
printf ("\n");
udp.Write(host, (char*)buffer, sizeof (buffer));
udp.Write(hostname, (char*)buffer, sizeof (buffer));
loconet_last.addr = l->addr;
loconet_last.dir = l->flags & LOCO_F_REVERSE;
loconet_last.speed = l->speed;
@ -414,19 +407,9 @@ void InterfaceZ21::SetLocoFunction(Locomotive *l, int func, int value) {
//
// Set Turnout
void InterfaceZ21::SetTurnout(Turnout *t, int activate, int outputactive) {
void InterfaceZ21::SetTurnout(Turnout *t, int activate, int motoractive) {
unsigned char buffer[] = { 0x09, 0x00, 0x40, 0x00, 0x53, 0x00, 0x00, 0x00, 0x00 };
debug (DEBUG_INFO | DEBUG_IFACE, "InterfaceZ21 (%s) SetTurnout Addr:%d Acitve:%d Output:%d", name,
t->addr, activate, outputactive);
//
//
if (outputactive == 1 && timer_get(&turnouttimeout) < 100) {
debug (0, "%s:%d Interface need to wait between two turnout commands", __FILE__, __LINE__);
return;
}
timer_start(&turnouttimeout);
//
// setup turnout addr
buffer[Z21_IDX_SETTURNOUT_ADRL] = (unsigned char) (t->addr & 0xFF);
@ -436,21 +419,20 @@ void InterfaceZ21::SetTurnout(Turnout *t, int activate, int outputactive) {
// setup steps and selected step
buffer[Z21_IDX_SETTURNOUT_MODE] = 0x80;
if (activate) buffer[Z21_IDX_SETTURNOUT_MODE] |= 1;
if (outputactive) buffer[Z21_IDX_SETTURNOUT_MODE] |= 8;
if (motoractive) buffer[Z21_IDX_SETTURNOUT_MODE] |= 8;
//
// XOR Byte
for (int i = 4; i < (int) sizeof (buffer)-1; i++)
for (int i = 4; i < sizeof (buffer)-1; i++)
buffer[Z21_IDX_SETTURNOUT_CHK] = (unsigned char)buffer[Z21_IDX_SETTURNOUT_CHK] xor (unsigned char)buffer[i];
udp.Write(host, (char*)buffer, sizeof (buffer));
//
// set the output flag
if (outputactive) t->flags |= TURNOUT_F_ACTIVE;
else t->flags &= ~TURNOUT_F_ACTIVE;
gettimeofday (&t->activatetime, NULL);
printf ("Send Data:");
for (int i = 0; i < sizeof (buffer); i++) {
int z = (unsigned char) buffer[i];
printf ("%02x:", z);
}
printf ("\n");
udp.Write(hostname, (char*)buffer, sizeof (buffer));
};
@ -459,11 +441,11 @@ void InterfaceZ21::SetTurnout(Turnout *t, int activate, int outputactive) {
// send_X_SET_TRACK_POWER_ON(); send_X_SET_TRACK_POWER_ON();
void InterfaceZ21::PowerOnOff(int onoff) {
if (status_connected == false) return;
debug (DEBUG_INFO | DEBUG_IFACE, "InterfaceZ21::PowerOnOff onoff:%d", onoff);
if (onoff) {
udp.Write(host, (char*)TX_X_SET_TRACK_POWER_ON, sizeof (TX_X_SET_TRACK_POWER_ON));
udp.Write(hostname, (char*)TX_X_SET_TRACK_POWER_ON, sizeof (TX_X_SET_TRACK_POWER_ON));
}
else {
udp.Write(host, (char*)TX_X_SET_TRACK_POWER_OFF, sizeof (TX_X_SET_TRACK_POWER_OFF));
udp.Write(hostname, (char*)TX_X_SET_TRACK_POWER_OFF, sizeof (TX_X_SET_TRACK_POWER_OFF));
}
};

@ -28,8 +28,9 @@ struct s_loconet_map{
int maxspeed;
};
class InterfaceZ21: public Interface {
class InterfaceZ21 {
private:
string hostname;
string serial;
char inbuffer[INTF_Z21_INBUFFER];
struct s_loconet_map loconet_map[INTF_Z21_LOCONET_MAXADDR];
@ -38,7 +39,6 @@ class InterfaceZ21: public Interface {
UDP udp;
time_t timeout;
time_t rmgetdatatimeout;
struct timeval turnouttimeout;
bool send_logon;
bool status_poweron;
@ -61,7 +61,7 @@ class InterfaceZ21: public Interface {
InterfaceZ21();
~InterfaceZ21();
void Connect();
void Connect(string destination);
void Disconnect();
bool IsConnected() { return status_connected; };
@ -70,11 +70,11 @@ class InterfaceZ21: public Interface {
bool IsProgramminnMode() { return status_programmingmode; };
bool IsEmergencyStop() { return status_emergencystop; };
int Loop();
int Loop(string interfacename);
void PowerOnOff(int onoff);
void SetLocoSpeed(Locomotive *l, int step);
void SetLocoFunction(Locomotive *l, int func, int value);
void SetTurnout(Turnout *t, int activate, int outputactive);
void SetTurnout(Turnout *t, int activate, int motoractive);
};

@ -10,13 +10,12 @@
// **************************************************************************
Interface::Interface() {
debug (DEBUG_INFO | DEBUG_IFACE, "Interface:%s", __FUNCTION__);
name[0] = 0;
host[0] = 0;
flags = 0;
type = INTF_T_OFF_UNKNOWN;
needs_update = true;
timer_start(&turnouttimeout);
};
Interface::~Interface() {
@ -25,28 +24,56 @@ Interface::~Interface() {
void Interface::Connect () {
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) Connect to %s", name, host);
switch (type) {
case INTF_T_Z21: intz21.Connect(host); break;
default: break;
}
};
void Interface::Disconnect() {
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) Disconnect", name);
switch (type) {
case INTF_T_Z21: intz21.Disconnect(); break;
default: break;
}
};
void Interface::PowerOnOff(int onoff) {
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) PowerOnOff %d", name, onoff);
switch (type) {
case INTF_T_Z21: intz21.PowerOnOff(onoff); break;
default: break;
}
};
/*
* Turnout:
* this function will check if the interface has not set any output within the past 100ms. For this we
* will save the current time in the value turnouttime.
*/
void Interface::SetTurnout(Turnout *t, int active, int outputactive) {
JSONParse jp;
//
// Turnout
//
void Interface::SetTurnout(Turnout *t, int active, int motoractive) {
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) SetTurnout Addr:%d FinalAcitve:%d Motor:%d", name,
t->addr, active, motoractive);
if (motoractive == 1 && timer_get(&turnouttimeout) < 100) {
debug (0, "* Interface need to wait between two turnout commands");
return;
}
timer_start(&turnouttimeout);
switch (type) {
case INTF_T_Z21: intz21.SetTurnout(t, active, motoractive); break;
default: break;
}
debug (DEBUG_INFO | DEBUG_IFACE, "%s:%d Interface (%s) SetTurnout Addr:%d Acitve:%d Output:%d", __FILE__, __LINE__, name,
t->addr, active, outputactive);
//
// make sure we turn the motor later off
if (motoractive) t->flags |= TURNOUT_F_ACTIVE;
else t->flags &= ~TURNOUT_F_ACTIVE;
gettimeofday (&t->activatetime, NULL);
};
//
@ -54,62 +81,326 @@ void Interface::SetTurnout(Turnout *t, int active, int outputactive) {
//
void Interface::SetLocoSpeed(Locomotive *l, int step) {
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) SetLocoSpeed Addr:%d Speed:%d ", name, l->addr, step);
switch (type) {
case INTF_T_Z21: intz21.SetLocoSpeed(l, step); break;
default: break;
}
};
void Interface::SetLocoFunction(Locomotive *l, int func, int value) {
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) SetLocoFunction Addr:%d Func:%d:%d", name, l->addr, func, value);
switch (type) {
case INTF_T_Z21: intz21.SetLocoFunction(l, func, value); break;
default: break;
}
};
//
// if update is needed return 1
//
int Interface::Loop() {
int ret = 0;
// debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) Loop", name);
flags &= ~(INTF_F_CONNECTED | INTF_F_POWER | INTF_F_STOP | INTF_F_SHORT_CIRCUIT | INTF_F_PROGRAMMING);
if (needs_update) {
ret = 1;
needs_update = 0;
}
switch (type) {
case INTF_T_Z21:
ret = intz21.Loop(name);
if (intz21.IsConnected()) flags |= INTF_F_CONNECTED;
if (intz21.IsPoweron()) flags |= INTF_F_POWER;
if (intz21.IsEmergencyStop()) flags |= INTF_F_STOP;
if (intz21.IsSortCircuit()) flags |= INTF_F_SHORT_CIRCUIT;
break;
default: break;
}
// debug (DEBUG_INFO | DEBUG_IFACE, "%s:%d Interface: name:'%s' , Flags: %d", __FILE__, __LINE__, name, flags);
return ret;
};
bool Interface::IsConnected() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsConnected", name);
switch (type) {
case INTF_T_Z21: ret = intz21.IsConnected(); break;
default: break;
}
return ret;
}
bool Interface::IsPoweron() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsPoweron", name);
return ret;
}
switch (type) {
case 1: ret = intz21.IsPoweron(); break;
default: break;
}
bool Interface::IsSortCircuit() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsSortCircuit", name);
return ret;
}
bool Interface::IsProgramminnMode() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsProgramminnMode", name);
return ret;
// **************************************************************************
// *
// * I N T E R F A C E S (gateway to all devices)
// *
// **************************************************************************
Interfaces::Interfaces () {
max = INTERFACES_MAX;
changed = 0;
};
Interfaces::~Interfaces() {
max = 0;
};
int Interfaces::LockThread() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
else return 0;
}
bool Interface::IsEmergencyStop() {
bool ret = false;
debug (DEBUG_INFO | DEBUG_IFACE, "* Interface (%s) IsEmergencyStop", name);
return ret;
int Interfaces::UnLockThread() {
if (pthread_mutex_unlock(&mtx) == 0) return 1;
else return 0;
}
JSONParse Interfaces::_GetJSON(int idx) {
JSONParse json;
JSONElement je;
string s = "";
json.Clear();
s = interfaces[idx].name; json.AddObject("name", s);
s = interfaces[idx].host; json.AddObject("host", s);
json.AddObject("flags", interfaces[idx].flags);
json.AddObject("type", interfaces[idx].type);
return json;
};
JSONParse Interfaces::GetJSON(string name) {
int i;
JSONParse jp;
jp.Clear();
LockThread();
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
if (name.compare(interfaces[i].name) == 0) {
jp = _GetJSON(i);
}
}
UnLockThread();
return jp;
};
void Interfaces::GetJSONAll(JSONParse *json) {
int i, cnt;
JSONElement je;
LockThread();
//
// write all railway data
// create json object array manualy
je.type = JSON_T_ARRAY;
je.name = "interfaces";
for (cnt = 0, i = 0; i < max; i++)
if (interfaces[i].name[0] != 0) {
if (cnt != 0) je.value += ","; // not first element
je.value += _GetJSON(i).ToString();
cnt++;
}
json->AddObject(je);
UnLockThread();
};
Interface Interfaces::GetInterfaceFromJSON(JSONParse *j) {
Interface i;
string s;
i.name[0] = 0;
i.host[0] = 0;
j->GetValue("name", &s);
strncpy (i.name, s.c_str(), REFERENCENAME_LEN);
j->GetValue("host", &s);
strncpy (i.host, s.c_str(), REFERENCENAME_LEN);
j->GetValueInt("flags", &i.flags);
j->GetValueInt("type", &i.type);
return i;
};
int Interfaces::Change(Interface *iface) {
int i;
int ifree = -1;
LockThread();
for (i = 0; i < max; i++) {
if (interfaces[i].name[0] != 0) {
// found element
if (strncmp(interfaces[i].name, iface->name, REFERENCENAME_LEN) == 0) {
ifree = i;
break;
}
}
else if (ifree == -1) ifree = i;
}
// element not found add new element
if (ifree != -1 && ifree < max) {
strncpy (interfaces[ifree].name, iface->name, REFERENCENAME_LEN);
strncpy (interfaces[ifree].host, iface->host, REFERENCENAME_LEN);
interfaces[ifree].flags = iface->flags;
interfaces[ifree].type = iface->type;
interfaces[ifree].Connect();
}
changed = 1;
UnLockThread();
return 1;
};
int Interfaces::Delete(string name) {
int i;
LockThread();
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
if (name.compare(interfaces[i].name) == 0) {
interfaces[i].Disconnect();
interfaces[i].name[0] = 0;
interfaces[i].host[0] = 0;
interfaces[i].flags = 0;
interfaces[i].type = INTF_T_OFF_UNKNOWN;
changed = 1;
break;
}
}
UnLockThread();
return 1;
};
void Interfaces::PowerOnOff(int onoff) {
int i;
LockThread();
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
if (!interfaces[i].IsConnected()) interfaces[i].Connect();
interfaces[i].PowerOnOff(onoff);
}
UnLockThread();
};
//
// Turnouts
//
void Interfaces::SetTurnout(Turnout *t, int active, int motoractive) {
int i;
LockThread();
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
if (!interfaces[i].IsConnected()) interfaces[i].Connect();
if (strncmp(t->ifname, interfaces[i].name, REFERENCENAME_LEN) == 0)
interfaces[i].SetTurnout(t, active, motoractive);
}
UnLockThread();
};
//
// Locomotives
//
void Interfaces::SetLocoSpeed(Locomotive *l, int speed) {
int i;
int step = 0, maxstep = 0;
switch(l->stepcode) {
case LOCO_INT_DCC14: maxstep = 14; break;
case LOCO_INT_DCC28: maxstep = 28; break;
case LOCO_INT_DCC128: maxstep = 126; break;
default: maxstep = 0; break;
}
if (abs(speed) < l->vmin) step = 0;
if (abs(speed) >= l->vmin) step = (speed * (maxstep)) / l->vmax;
if (abs(speed) > l->vmax) step = maxstep;
l->speed = speed;
LockThread();
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
if (!interfaces[i].IsConnected()) interfaces[i].Connect();
if (strncmp(l->ifname, interfaces[i].name, REFERENCENAME_LEN) == 0)
interfaces[i].SetLocoSpeed(l, step);
}
UnLockThread();
};
void Interfaces::SetLocoFunction(Locomotive *l, int func, int value) {
int i;
LockThread();
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
if (!interfaces[i].IsConnected()) interfaces[i].Connect();
if (strncmp(l->ifname, interfaces[i].name, REFERENCENAME_LEN) == 0)
interfaces[i].SetLocoFunction(l, func, value);
}
UnLockThread();
};
void Interfaces::Loop() {
int i;
JSONParse jout;
for (i = 0; i < max; i++) if (interfaces[i].name[0] != 0) {
if (interfaces[i].Loop()) {
//
// now we need to send an update
jout.Clear();
jout.AddObject ("interface", _GetJSON(i));
if (network) network->ChangeListPushToAll(jout.ToString());
}
}
};

@ -6,6 +6,7 @@
#include "server.h"
#include "UDPTCPNetwork.h"
#include "json.h"
#include "interface-z21.h"
#define INTF_F_CONNECTED 0x0001
#define INTF_F_POWER 0x0002
@ -14,34 +15,73 @@
#define INTF_F_PROGRAMMING 0x0010
#define INTF_F_NEEDUPDATE 0x8000 // if something changes during the Loop
#define INTF_T_OFF_UNKNOWN 0
#define INTF_T_Z21 1
class Interface {
private:
public:
InterfaceZ21 intz21;
bool needs_update;
struct timeval turnouttimeout;
public:
char name[REFERENCENAME_LEN];
char host[NET_HOSTLEN];
int flags;
int type;
Interface();
virtual ~Interface();
~Interface();
void Connect();
void Disconnect();
void PowerOnOff(int onoff);
void SetLocoSpeed(Locomotive *l, int step);
void SetLocoFunction(Locomotive *l, int func, int value);
void SetTurnout(Turnout *t, int active, int motoractive);
bool IsConnected();
bool IsPoweron();
int Loop();
};
class Interfaces {
private:
Interface interfaces[INTERFACES_MAX];
int max;
int changed;
pthread_mutex_t mtx;
int LockThread();
int UnLockThread();
// not thread safe
JSONParse _GetJSON(int idx);
public:
Interfaces();
~Interfaces();
bool IsChanged() { return changed; }
void ClearChanged() { changed = 0; };
virtual void Connect();
virtual void Disconnect();
int Change(Interface *iface);
int Delete(string name);
virtual void PowerOnOff(int onoff);
virtual void SetLocoSpeed(Locomotive *l, int step);
virtual void SetLocoFunction(Locomotive *l, int func, int value);
virtual void SetTurnout(Turnout *t, int active, int motoractive);
JSONParse GetJSON(string name);
void GetJSONAll(JSONParse *json);
Interface GetInterfaceFromJSON(JSONParse *j);
virtual bool IsConnected();
virtual bool IsPoweron();
virtual bool IsSortCircuit();
virtual bool IsProgramminnMode();
virtual bool IsEmergencyStop();
//
//
void PowerOnOff(int onoff);
void SetLocoSpeed(Locomotive *l, int speed);
void SetLocoFunction(Locomotive *l, int func, int value);
void SetTurnout(Turnout *t, int active, int motoractive);
virtual int Loop();
void Loop();
};
#endif

@ -1,293 +0,0 @@
#include <string>
#include "modelbahn.h"
#include "interface.h"
#include "interface-z21.h"
#include "interfaces.h"
// **************************************************************************
// *
// * I N T E R F A C E S (gateway to all devices)
// *
// **************************************************************************
Interfaces::Interfaces () {
max = INTERFACES_MAX;
pthread_mutex_init(&mtx, NULL);
for (int i = 0; i < max; i++) interfaces[i] = NULL;
changed = 0;
};
Interfaces::~Interfaces() {
max = 0;
};
int Interfaces::LockThread() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
else return 0;
}
int Interfaces::UnLockThread() {
if (pthread_mutex_unlock(&mtx) == 0) return 1;
else return 0;
}
JSONParse Interfaces::_GetJSON(int idx) {
JSONParse json;
JSONElement je;
string s = "";
json.Clear();
if (interfaces[idx] != NULL) {
s = interfaces[idx]->name; json.AddObject("name", s);
s = interfaces[idx]->host; json.AddObject("host", s);
json.AddObject("flags", interfaces[idx]->flags);
json.AddObject("type", interfaces[idx]->type);
}
return json;
};
JSONParse Interfaces::GetJSON(string name) {
int i;
JSONParse jp;
jp.Clear();
LockThread();
for (i = 0; i < max; i++) if (interfaces[i] != NULL){
if (interfaces[i]->name[0] != 0) {
if (name.compare(interfaces[i]->name) == 0) {
jp = _GetJSON(i);
}
}
}
UnLockThread();
return jp;
};
void Interfaces::GetJSONAll(JSONParse *json) {
int i, cnt;
JSONElement je;
LockThread();
//
// write all railway data
// create json object array manualy
je.type = JSON_T_ARRAY;
je.name = "interfaces";
for (cnt = 0, i = 0; i < max; i++) if(interfaces[i] != NULL)
if (interfaces[i]->name[0] != 0) {
if (cnt != 0) je.value += ","; // not first element
je.value += _GetJSON(i).ToString();
cnt++;
}
json->AddObject(je);
UnLockThread();
};
Interface Interfaces::GetInterfaceFromJSON(JSONParse *j) {
Interface i;
string s;
i.name[0] = 0;
i.host[0] = 0;
j->GetValue("name", &s);
strncpy (i.name, s.c_str(), REFERENCENAME_LEN);
j->GetValue("host", &s);
strncpy (i.host, s.c_str(), REFERENCENAME_LEN);
j->GetValueInt("flags", &i.flags);
j->GetValueInt("type", &i.type);
return i;
};
int Interfaces::Change(Interface *iface) {
int i;
int ifree = -1;
printf ("Interface Type:%d\n", iface->type);
LockThread();
for (i = 0; i < max; i++) {
if (interfaces[i] != NULL) {
// found element
if (strncmp(interfaces[i]->name, iface->name, REFERENCENAME_LEN) == 0) {
delete interfaces[i];
interfaces[i] = NULL;
ifree = i;
break;
}
}
else if (ifree == -1) ifree = i;
}
// element found or we need to add the element.
if (ifree != -1 && ifree < max) {
if (iface->type == INTF_T_Z21) interfaces[ifree] = new InterfaceZ21();
else interfaces[ifree] = new Interface();
strncpy (interfaces[ifree]->name, iface->name, REFERENCENAME_LEN);
strncpy (interfaces[ifree]->host, iface->host, REFERENCENAME_LEN);
interfaces[ifree]->flags = iface->flags;
interfaces[ifree]->type = iface->type;
interfaces[ifree]->Connect();
}
changed = 1;
UnLockThread();
return 1;
};
int Interfaces::Delete(string name) {
int i;
LockThread();
for (i = 0; i < max; i++) if (interfaces[i] != NULL) {
if (name.compare(interfaces[i]->name) == 0) {
interfaces[i]->Disconnect();
interfaces[i]->name[0] = 0;
interfaces[i]->host[0] = 0;
interfaces[i]->flags = 0;
interfaces[i]->type = INTF_T_OFF_UNKNOWN;
delete interfaces[i];
interfaces[i] = NULL;
changed = 1;
break;
}
}
UnLockThread();
return 1;
};
void Interfaces::PowerOnOff(int onoff) {
int i;
LockThread();
for (i = 0; i < max; i++) if (interfaces[i] != NULL) {
if (!interfaces[i]->IsConnected()) interfaces[i]->Connect();
interfaces[i]->PowerOnOff(onoff);
}
UnLockThread();
};
//
// Turnouts
//
void Interfaces::SetTurnout(Turnout *t, int active, int motoractive) {
int i;
if (t == NULL) return;
LockThread();
debug (0, "%s:%d Interfaces::SetTurnout Name:%s active:%d Output%d", __FILE__, __LINE__, t->name, active, motoractive);
//
// if the interfacename is debug ... simulate a change in the turnout
//
if (strncmp(t->ifname, "DEBUG", REFERENCENAME_LEN) == 0) {
if (active) t->flags |= TURNOUT_F_ACTIVE;
else t->flags &= ~TURNOUT_F_ACTIVE;
server->TurnoutAddrMode(t->ifname, t->addr, active);
}
else {
for (i = 0; i < max; i++) if (interfaces[i] != NULL) {
if (!interfaces[i]->IsConnected()) interfaces[i]->Connect();
if (strncmp(t->ifname, interfaces[i]->name, REFERENCENAME_LEN) == 0)
interfaces[i]->SetTurnout(t, active, motoractive);
}
}
UnLockThread();
};
//
// Locomotives
//
void Interfaces::SetLocoSpeed(Locomotive *l, int speed) {
int i;
int step = 0, maxstep = 0;
debug (0, "Interfaces::SetLocoSpeed Loco:'%s' Speed:%d", l->name, speed);
switch(l->stepcode) {
case LOCO_INT_DCC14: maxstep = 14; break;
case LOCO_INT_DCC28: maxstep = 28; break;
case LOCO_INT_DCC128: maxstep = 126; break;
default: maxstep = 0; break;
}
if (abs(speed) < l->vmin) step = 0;
if (abs(speed) >= l->vmin) step = (speed * (maxstep)) / l->vmax;
if (abs(speed) > l->vmax) step = maxstep;
l->speed = speed;
LockThread();
for (i = 0; i < max; i++) if (interfaces[i] != NULL) {
if (!interfaces[i]->IsConnected()) interfaces[i]->Connect();
if (strncmp(l->ifname, interfaces[i]->name, REFERENCENAME_LEN) == 0)
interfaces[i]->SetLocoSpeed(l, step);
}
UnLockThread();
};
void Interfaces::SetLocoFunction(Locomotive *l, int func, int value) {
int i;
debug (0, "Interfaces::SetLocoFunction Loco:'%s' Function:%d Value:%d", l->name, func, value);
LockThread();
for (i = 0; i < max; i++) if (interfaces[i] != NULL) {
if (!interfaces[i]->IsConnected()) interfaces[i]->Connect();
if (strncmp(l->ifname, interfaces[i]->name, REFERENCENAME_LEN) == 0)
interfaces[i]->SetLocoFunction(l, func, value);
}
UnLockThread();
};
void Interfaces::Loop() {
int i;
JSONParse jout;
for (i = 0; i < max; i++) if (interfaces[i] != NULL) {
if (interfaces[i]->Loop()) {
//
// now we need to send an update
jout.Clear();
jout.AddObject ("interface", _GetJSON(i));
if (network) network->ChangeListPushToAll(jout.ToString());
}
}
};

@ -1,61 +0,0 @@
#ifndef _INTERFACES_H_
#define _INTERFACES_H_
#include "modelbahn.h"
#include "server.h"
#include "UDPTCPNetwork.h"
#include "json.h"
#include "interface.h"
#include "interfaces.h"
#define INTF_F_CONNECTED 0x0001
#define INTF_F_POWER 0x0002
#define INTF_F_STOP 0x0004
#define INTF_F_SHORT_CIRCUIT 0x0008
#define INTF_F_PROGRAMMING 0x0010
#define INTF_F_NEEDUPDATE 0x8000 // if something changes during the Loop
enum {
INTF_T_OFF_UNKNOWN = 0,
INTF_T_Z21,
INTF_T_MAX
};
class Interfaces {
private:
Interface *interfaces[INTERFACES_MAX];
int max;
int changed;
pthread_mutex_t mtx;
int LockThread();
int UnLockThread();
// not thread safe
JSONParse _GetJSON(int idx);
public:
Interfaces();
~Interfaces();
bool IsChanged() { return changed; }
void ClearChanged() { changed = 0; };
int Change(Interface *iface);
int Delete(string name);
JSONParse GetJSON(string name);
void GetJSONAll(JSONParse *json);
Interface GetInterfaceFromJSON(JSONParse *j);
//
//
void PowerOnOff(int onoff);
void SetLocoSpeed(Locomotive *l, int speed);
void SetLocoFunction(Locomotive *l, int func, int value);
void SetTurnout(Turnout *t, int active, int outputactive);
void Loop();
};
#endif

@ -3,9 +3,6 @@
#include <string>
#include <string.h>
using namespace std;
#include "debug.h"
#include "json.h"
@ -52,7 +49,7 @@ int JSONParse::Set(string json) {
Clear();
// find start and read until end
for (step = STEP_NONE, i = 0, ignorenext = false; i < (int) json.length(); i++) {
for (step = STEP_NONE, i = 0, ignorenext = false; i < json.length(); i++) {
// need to copy next character
// debug (0, "JSONParse: step:%d i:%d name:'%s' value:'%s'", step, i, jelement.name.c_str(), jelement.value.c_str());
if (ignorenext) {
@ -249,7 +246,7 @@ int JSONParse::GetIdx(string src, int idx, string *dest) {
// printf("\n***************************************idx:%d\n", idx);
for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0;
for (i = 0; i < (int) src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
for (i = 0; i < src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
// printf ("i:%d rcnt:%d['%c'] cnt:%d char:'%c' ous:'%s'\n",
// i, rcnt, recursive[rcnt], cnt, src[i], dest->c_str());
if (src[i] == '[') {

File diff suppressed because it is too large Load Diff

@ -10,9 +10,8 @@
#define LOCO_F_CANREVERSE 0x0020
#define LOCO_F_SHORTTRAIN 0x0040
#define LOCO_F_AUTO 0x0100
#define LOCO_F_AUTOSHED 0x0200
#define LOCO_F_AUTORANDOM 0x0400
#define LOCO_F_AUTOSTOP 0x0800
#define LOCO_F_RANDOM 0x0200
#define LOCO_F_AUTOSTOP 0x0400
#define LOCO_TO_TURNOUT (50+TURNOUT_DEFAULT_ACTIVETIMEOUT)
#define LOCO_TO_TRYAGAIN (1000)
@ -30,7 +29,7 @@ enum {
LOCO_OR_NOTHING = 0,
LOCO_OR_SEARCH, // search way (to next block and lock way)
LOCO_OR_PREPARE, // switch turnouts right way (one every 100ms)
// if no turnout has to been set, continue
// if no turnout has to be set, continue
LOCO_OR_ONTHEWAY, // locomotive is on the way // maybe prepare next block?
// ASSIGN -> PREV, NEXT -> ASSIGN, NEXT <- (empty)
// propabely searching next block (if DEST is set)?
@ -40,6 +39,11 @@ enum {
LOCO_OR_STOPWAIT // stopping
};
struct s_LocoAuto {
int onroute; // LOCO_OR_.....
struct timeval waituntil; // wait until this time for next action (tournout, waiting station...)
};
struct s_Locomotive {
char name[REFERENCENAME_LEN]; // name
char ifname[REFERENCENAME_LEN]; // ref. of interface
@ -51,7 +55,6 @@ struct s_Locomotive {
int vmid; // speed - for normal trains (max for cargo trains, on automode)
int vfast; // speed - for normal trains
int vmax; // speed - maximum speed
char schedway[WAYDATA_LEN]; // scheduled way W:15,B:+B17,W30,B:-B21
// dynamic data
int speed; // current speed
@ -61,7 +64,6 @@ struct s_Locomotive {
char blockprev[REFERENCENAME_LEN]; // prev block (mostly assigned block
char blockdest[REFERENCENAME_LEN]; // destination block
int sched_step; // on automode this is the scheduled way step
char auto_way[WAYDATA_LEN]; // route to way "b:+blockname,t:name:0,t:name:1,b:-blockname"
char auto_wayold[WAYDATA_LEN]; // route to way "b:+blockname,t:name:0,t:name:1,b:-blockname"
int auto_onroute; // LOCO_OR_....
@ -69,7 +71,6 @@ struct s_Locomotive {
struct timeval auto_timenext; // timeval of the next active step
} typedef Locomotive;
class Locomotives {
private:
Locomotive *locomotives;
@ -82,15 +83,7 @@ class Locomotives {
// not thread safe
JSONParse _GetJSON(int idx);
int SchedulerNextStep(Locomotive *loc); // automode, calculate next step
void SendUpdate(Locomotive *loc);
int Loco_SearchAndLock(Locomotive *loco);
int Loco_PrepareWay(Locomotive *loco);
int Loco_OnRoute(Locomotive *loco);
int Loco_BlockEnterStop(Locomotive *loco);
int Loco_BlockEnterNext(Locomotive *loco);
int Loco_BlockStopWait(Locomotive *loco);
public:
Locomotives();
~Locomotives();
@ -104,18 +97,17 @@ class Locomotives {
int SetReverse(string name, int reverse);
int SetFunction(string name, int func, int value);
int Reset(string name);
int SetModeMan(string name);
int SetModeAutoMan(string name);
int SetModeAuto(string name);
int SetModeAutoRand(string name);
int SetModeAutoShed(string name);
int SetMan(string name);
int SetAutoMan(string name);
int SetAuto(string name);
int SetAutoRand(string name);
int SetSpeedFromBus (string ifname, int addr, int speed);
int SetFunctionFromBus (string ifname, int addr, int func);
int SetDestination (string name, string block, int direction);
int SetAssign (string name, string block, int direction);
int GetFlags(string name);
int AutoCheckWaySingleStep(string way, Locomotive *loc, int *data);
int AutoCheckWaySingleStep(string way, string locname, int *data);
int Loop();
string GetName(int idx);
@ -123,6 +115,7 @@ class Locomotives {
JSONParse GetJSON(string name);
void GetJSONAll(JSONParse *json);
Locomotive GetLocomotiveFromJSON(JSONParse *j);
int Test(string loco);
};

@ -18,12 +18,9 @@ int running = 1;
Server *server = NULL;
Network *network = NULL;
int simulation = 0;
int main (int argc, char **argv) {
int i;
tzset(); // needed for localtime to work
int ret;
//
// setup signals
@ -52,14 +49,6 @@ int main (int argc, char **argv) {
debug (0, "* *");
debug (0, "***************************************************");
debug (0, "");
for (i = 1; i < argc; i++) {
if (strcmp (argv[i], "-simulation") == 0) {
simulation = 1;
debug (0, "WARINING SIMULATION MODE ACTIVE. ALL COMMANDS WILL BE SEND");
debug (0, "TO THE INTERFACES. TURNOUT AND SENSORDATA WILL BE FORCED.");
sleep (5);
}
}
//////////////////////////////////////////////////////////////////////
//

@ -35,14 +35,12 @@ int main (int argc, char **argv) {
//
// read data
memset (buffer, 0x0, BUFFERSIZE+1);
for (ptr = buffer, inlen = 0; inlen < BUFFERSIZE-1 && (fgets (ptr, BUFFERSIZE - inlen, stdin)) != NULL;) {
for (ptr = buffer, inlen = 0; inlen < BUFFERSIZE-1 && (fgets (ptr, BUFFERSIZE - inlen, stdin)) > 0;) {
inlen = strlen (buffer);
ptr = buffer+inlen;
}
if (inlen >= BUFFERSIZE-1) fprintf (logf, "read input puffer full.\n");
fprintf (logf, "read from stdin %lu bytes\n", strlen(buffer));
// fprintf (logf, "%s\n", buffer);
fprintf (logf, "*************************************\n");
fprintf (logf, "read from stdin %d bytes\n", strlen(buffer));
//
// send data to server
@ -56,7 +54,7 @@ int main (int argc, char **argv) {
i = u.ReadTimeout(buffer, BUFFERSIZE-1, 1000);
buffer[i] = 0;
fprintf (logf, "read from server %d bytes\n", i);
fprintf (logf, "%s\n", buffer);
// fprintf (logf, "%s\n", buffer);
printf ("%s", buffer);
} while (i == BUFFERSIZE-1);
u.Close();

@ -6,7 +6,7 @@
#define BUFFERSIZE 64000
#define MAXWAITTIME 500
#define UNIX_SOCKET_FILE "/tmp/modelbahn.socket"
#define DEFAULT_DATADIR "/home/steffen/Dokumente/Programmierung/Modelbahn/"
#define DEFAULT_DATADIR "/home/steffen/Dokumente/Programmierung/modelbahn/"
#define SESSIONS_MAX 8
#define REFERENCENAME_LEN 128
@ -27,7 +27,7 @@ extern int running;
extern Server *server;
extern Network *network;
extern int simulation;
//
// to measure the time in ms (used for debugging)

@ -29,8 +29,11 @@ Network::Network() {
thread = 0;
sessions.clear();
thread_running = 0;
pthread_mutex_init(&mtx, NULL);
pthread_mutex_init(&mtxsessions, NULL);
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
mtxsessions = { 0 };
mtxsessions = PTHREAD_MUTEX_INITIALIZER;
}
Network::~Network() {
@ -51,6 +54,7 @@ Network::~Network() {
void Network::ThreadProcess() {
list<UNIX*>::iterator iteru;
Session *s;
UNIX *u;
int i = 0;
@ -177,7 +181,9 @@ Session *Network::GetSession(int sid) {
int Network::ClientLoop(UNIX *client) {
char bufferin[BUFFERSIZE];
int len, rid, sid;
char bufferout[BUFFERSIZE];
int len, i, rid, sid;
int res;
list<Session*>::iterator siter;
Session *session = NULL;
string value;
@ -194,7 +200,6 @@ int Network::ClientLoop(UNIX *client) {
JSONParse json;
JSONParse jsonout;
JSONParse jelement;
long int l;
bufferin[len] = 0; // prevent reading behind the data
@ -227,6 +232,8 @@ int Network::ClientLoop(UNIX *client) {
}
if (sid <= 0) {
int x, y;
debug (0, "* sid not set, gettin new SID");
session = new Session(rid);
sid = session->GetSessionID();
@ -272,9 +279,8 @@ int Network::ClientLoop(UNIX *client) {
jsonout.AddObject(je);
}
s = jsonout.ToString();
// printf ("***************************** %s:%d ---> send:\n\n\n%s\n\n\n", __FILE__, __LINE__, s.c_str());
l = client->Write((char*)s.c_str(), strlen(s.c_str()));
// printf ("\n\n Network::ClientLoop %s:%d strlen:%ld result:%ld \n\n\n", __FILE__, __LINE__, strlen(s.c_str()), l);
// debug (0, "%s:%d ---> send:\n\n\n%s\n\n\n", __FILE__, __LINE__, s.c_str());
client->Write((char*)s.c_str(), strlen(s.c_str()));
result = 1;
}
else {

@ -55,7 +55,6 @@ private:
void AddJSONSensor(JSONParse *jp);
void DelJSONSensor(JSONParse *jp);
void SetJSONSensorActive(JSONParse *jp);
void AddJSONInterface(JSONParse *jp);
void DelJSONInterface(JSONParse *jp);
@ -66,11 +65,11 @@ private:
void SetJSONLocoDest(JSONParse *jp);
void SetJSONLocoAssign(JSONParse *jp);
void SetJSONLocoReset(JSONParse *jp);
void SetJSONLocoTest(JSONParse *jp);
void SetJSONLocoMan(JSONParse *jp);
void SetJSONLocoAutoMan(JSONParse *jp);
void SetJSONLocoAuto(JSONParse *jp);
void SetJSONLocoAutoRand(JSONParse *jp);
void SetJSONLocoAutoShed(JSONParse *jp);
void BlockJSONOff(JSONParse *jp);
void BlockJSONClear(JSONParse *jp);

File diff suppressed because it is too large Load Diff

@ -25,7 +25,6 @@ enum {
#define RAILWAYS_MAX_WIDTH 500
#define RAILWAYS_MAX_HEIGHT 500
#define RAILWAYS_LOCKF_KEEPSTART 0x0001 // keep start
// direktion
//
@ -75,7 +74,7 @@ struct s_findway_data {
int oldx;
int oldy;
int oldenterfrom;
int dist;
int parma;
string way;
};
@ -100,10 +99,7 @@ class Railways {
JSONParse _GetJSONRailway(int x, int y);
void _New (int w, int h);
void DebugPrintFindWay(struct s_findway_map *fw);
int _FindReference(int *x, int *y, string name, int cnt);
int _SplitBlockIsFreeAndAllowed(string loconame, int locoflags, string block);
int _NextPosIsValid(string loconame, int locoflags, struct s_findway_data *fwd);
string GetDestBlock(int locoflags, string blockend);
int _FindReference(int *x, int *y, string name);
public:
Railways();
@ -129,11 +125,12 @@ class Railways {
void GetJSONAll(JSONParse *json);
Railway GetRailwayFromJSON(JSONParse *j);
int FindReference(int *x, int *y, string name, int cnt);
int FindReference(int *x, int *y, string name);
int FindWay(string blockstart, string blockend, string lockedfor, string *next);
int FindWayCheckIfNoDoubleTurnouts (string *next);
int FindRandomWay(string blockstart, string lockedfor, string *next);
int LockWay (string way, string lockedby, int lockonoff, int flags);
int LockWay (string way, string lockedby, int lockonoff);
int LockWay (string way, string lockedby) { return LockWay(way, lockedby, 1); };
int UnLockWay (string way, string lockedby) { return LockWay(way, lockedby, 0); };
int SetLockedby (int x, int y, string name, int locked);
struct s_findway_data NextPos(struct s_findway_data pos, int dirtype);

@ -7,12 +7,9 @@
Sensors::Sensors () {
changed = 0;
sensors = (Sensor*) malloc(sizeof(Sensor)*SENSORS_MAX);
memset (sensors, 0x0, sizeof(Sensor)*SENSORS_MAX);
max = SENSORS_MAX;
pthread_mutex_init(&mtx, NULL);
};
Sensors::~Sensors() {
free (sensors);
sensors = NULL;
@ -38,29 +35,6 @@ int Sensors::GetActive(string name) {
};
int Sensors::SetActive(string name, int value) {
int i;
JSONParse jp;
Lock();
for (i = 0; i < max; i++) if (sensors[i].name[0] != 0) {
if (name.compare(sensors[i].name) == 0) {
if (value) sensors[i].flags |= SENSOR_F_ACTIVE;
else sensors[i].flags &= ~SENSOR_F_ACTIVE;
jp.Clear();
jp.AddObject("sensor", _GetJSON(i));
if(network) network->ChangeListPushToAll(jp.ToString());
break;
}
}
UnLock();
return 1;
};
int Sensors::Lock() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
else return 0;

@ -37,7 +37,6 @@ class Sensors {
int Change(Sensor *se);
int Get(int idx, Sensor *dest);
int GetActive(string name);
int SetActive(string name, int value);
int Get(string name, Sensor *dest);
int Delete(string name);

@ -73,7 +73,7 @@ int Server::Load(string fn) {
close (fd);
// everything read?
if (len < (size_t) sbuf.st_size) {
if (len < sbuf.st_size) {
free (buf);
debug (DEBUG_ERROR, "* Reading Track File Failed. (len < filesize)");
return 0;
@ -137,6 +137,7 @@ int Server::Load(string fn) {
turnouts.Change(&to);
}
//
// read blocks
Block bl;

@ -24,9 +24,10 @@
int Server::Start() {
int err;
thread_running = 1;
pthread_attr_t attr;
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
thread_running = 1;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
err = pthread_create (&thread, &attr, ThreadEntry, this);
@ -40,12 +41,9 @@ int Server::Start() {
Server::Server() {
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
thread = 0;
thread_running = 0;
railways.SetSize(64, 32);
railways.SetSize(200, 200);
status_text = "init server";
mode = SMODE_STARTUP;
data_reset.mr_idx = -1;
@ -64,30 +62,18 @@ Server::~Server() {
int Server::TurnoutSet(string name, int active) {
int x, y, locked = 0;
string lockedby;
int cnt = 0;
Railway r;
//
// check if locked
while (server->railways.FindReference(&x, &y, name, (cnt++))) {
while (server->railways.FindReference(&x, &y, name)) {
r = server->railways.Get(x, y);
debug (0, "%s:%d Reference %d,%d Name:%s Lockedby:%s", __FILE__, __LINE__, x, y, r.name, r.lockedby);
printf ("Reference %d,%d Name:%s Lockedby:%d\n", x, y, r.name, r.lockedby);
if (r.lockedby[0] != 0) {
locked = 1;
lockedby = r.lockedby;
}
}
if (simulation) {
int flags;
debug (0, "%s:%d WARNING SIMULATION MODE", __FILE__, __LINE__);
flags = turnouts.GetFlags(turnouts.GetIdx(name));
if (flags & TURNOUT_F_TURNOUT) flags &= ~TURNOUT_F_TURNOUT;
else flags |= TURNOUT_F_TURNOUT;
turnouts.SetFlags(turnouts.GetIdx(name), flags);
turnouts.Set(name, active);
}
if (locked == 0) return turnouts.Set(name, active);
else {
debug (0, "%s:%d SetJSONTurnout Element %s is locked by %s", __FILE__, __LINE__, name.c_str(), lockedby.c_str());
@ -265,7 +251,7 @@ void Server::CycleModeReset() {
else {
data_reset.mr_idx = -1;
data_reset.mr_step++;
data_reset.mr_lastelm = "";
data_reset.mr_lastelm;
}
}
}
@ -278,23 +264,19 @@ void Server::CycleModeReset() {
data_reset.mr_idx++;
data_reset.mr_lastelm = turnouts.GetName(data_reset.mr_idx);
if (data_reset.mr_lastelm.length() > 0) {
//
// reset output/turnout only if not a relais
flags = turnouts.GetFlags(data_reset.mr_idx);
if ((flags & TURNOUT_F_ISRELAIS) == 0) {
if (flags & TURNOUT_F_TURNOUT) active = 1;
else active = 0;
timer_start (&data_reset.mr_timestamp);
if (data_reset.mr_lastelm.length() > 0) {
debug (0, "* Reset Turnout %s", data_reset.mr_lastelm.c_str());
TurnoutSet(data_reset.mr_lastelm, active);
}
}
else {
data_reset.mr_idx = -1;
data_reset.mr_step++;
data_reset.mr_lastelm = "";
data_reset.mr_lastelm;
}
}
}

@ -27,7 +27,7 @@
#include "railway.h"
#include "locomotive.h"
#include "sensor.h"
#include "interfaces.h"
#include "interface.h"
#include "block.h"
enum SMODE {
@ -164,11 +164,11 @@ public:
int LocomotiveSetDest(string name, string block, int direction) { return locomotives.SetDestination(name, block, direction); };
int LocomotiveSetAssign(string name, string block, int direction) { return locomotives.SetAssign(name, block, direction); };
int LocomotiveReset(string name) { return locomotives.Reset(name); };
int LocomotiveSetMan(string name) { return locomotives.SetModeMan(name); };
int LocomotiveSetAuto(string name) { return locomotives.SetModeAuto(name); };
int LocomotiveSetAutoMan(string name) { return locomotives.SetModeAutoMan(name); };
int LocomotiveSetAutoRand(string name) { return locomotives.SetModeAutoRand(name); };
int LocomotiveSetAutoShed(string name) { return locomotives.SetModeAutoShed(name); };
int LocomotiveSetMan(string name) { return locomotives.SetMan(name); };
int LocomotiveSetAuto(string name) { return locomotives.SetAuto(name); };
int LocomotiveSetAutoMan(string name) { return locomotives.SetAutoMan(name); };
int LocomotiveSetAutoRand(string name) { return locomotives.SetAutoRand(name); };
int LocomotiveTest(string name) { return locomotives.Test(name); };
/////////////////////////////////////////
// Sensor
@ -176,7 +176,6 @@ public:
Sensor SensorFromJSON(JSONParse *j) { return sensors.GetSensorFromJSON(j); };
JSONParse SensorGetJSON(string name) { return sensors.GetJSON(name); };
int SensorDelete(string name) { return sensors.Delete(name); };
int SensorSetActive(string name, int value) { return sensors.SetActive(name, value); };
/////////////////////////////////////////
// Blocks

@ -64,10 +64,6 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
debug (0, "* Session Del Interface");
DelJSONInterface(jin);
}
//
// turnouts
//
else if (command.compare("addsensor") == 0) {
debug (0, "* Session Add Sensor");
AddJSONSensor(jin);
@ -76,11 +72,6 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
debug (0, "* Session del Sensor");
DelJSONSensor(jin);
}
else if (command.compare("sensorSetActive") == 0) {
debug (0, "* Session Sensor Set Active");
printf ("%s:%d jin:%s", __FILE__, __LINE__, jin->ToString().c_str());
SetJSONSensorActive(jin);
}
//
// turnouts
@ -148,12 +139,12 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
else if (command.compare("locomotivesetautorand") == 0) {
SetJSONLocoAutoRand(jin);
}
else if (command.compare("locomotivesetautoshed") == 0) {
SetJSONLocoAutoShed(jin);
}
else if (command.compare("locomotivereset") == 0) {
SetJSONLocoReset(jin);
}
else if (command.compare("locomotivetest") == 0) {
SetJSONLocoTest(jin);
}
//
// poweron / poweroff / save and resetdata
//
@ -187,11 +178,9 @@ int Session::ProcessData(JSONParse *jin, JSONParse *jout) {
// debuggin maybe we need to fix this somehow
elements = json.GetElements();
for (iter = elements.begin(); iter != elements.end(); iter++) {
// printf ("*********************** Session::ProcessData %s:%d\n\n***\n%s\n***\n", __FILE__, __LINE__, (*iter).GetString().c_str());
for (iter = elements.begin(); iter != elements.end(); iter++)
ChangeListPush("{"+(*iter).GetString()+"}");
}
}
else {
debug (DEBUG_ERROR | DEBUG_SESSION, "%s:%d Unknown command: '%s' JSON:%s",
__FILE__, __LINE__, command.c_str(), jin->ToString().c_str());
@ -532,85 +521,85 @@ void Session::SetJSONLocoAssign(JSONParse *jp) {
};
void Session::SetJSONLocoReset(JSONParse *jp) {
void Session::SetJSONLocoTest(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveReset(loco);
server->LocomotiveTest(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoMan(JSONParse *jp) {
void Session::SetJSONLocoReset(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetMan(loco);
server->LocomotiveReset(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAutoMan(JSONParse *jp) {
void Session::SetJSONLocoMan(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetAutoMan(loco);
server->LocomotiveSetMan(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAuto(JSONParse *jp) {
void Session::SetJSONLocoAutoMan(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetAuto(loco);
server->LocomotiveSetAutoMan(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAutoRand(JSONParse *jp) {
void Session::SetJSONLocoAuto(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetAutoRand(loco);
server->LocomotiveSetAuto(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
void Session::SetJSONLocoAutoShed(JSONParse *jp) {
void Session::SetJSONLocoAutoRand(JSONParse *jp) {
string loco;
JSONParse jout;
jp->GetValue("locomotive", &loco);
server->LockThread();
server->LocomotiveSetAutoShed(loco);
server->LocomotiveSetAutoRand(loco);
jout.Clear();
jout.AddObject("locomotive", server->LocomotiveGetJSON(loco));
if (network) network->ChangeListPushToAll(jout.ToString());
@ -677,6 +666,9 @@ void Session::SetJSONTurnout(JSONParse *jp) {
string name;
string lockedby;
int active;
int x, y;
int locked = 0;
Railway r;
server->LockThread();
@ -688,11 +680,15 @@ void Session::SetJSONTurnout(JSONParse *jp) {
// activate
debug (0, "%s:%d SetJSONTurnout Element %s active:%d", __FILE__, __LINE__, name.c_str(), active);
server->TurnoutSet(name, active);
jout.Clear();
jout.AddObject("turnout", server->TurnoutGetJSON(name));
if (network) network->ChangeListPushToAll(jout.ToString());
}
server->UnLockThread();
};
//
// add new block
//
@ -773,27 +769,6 @@ void Session::BlockJSONClear(JSONParse *jp) {
};
//
// add new block
//
void Session::SetJSONSensorActive(JSONParse *jp) {
string name;
int enabled;
JSONParse jtmp;
JSONParse jout;
server->LockThread();
jp->GetValue("sensor", &name);
jp->GetValueInt("enabled", &enabled);
server->SensorSetActive(name, enabled);
// jout.Clear();
// jout.AddObject("block", server->BlockGetJSON(bl.name));
// if (network) network->ChangeListPushToAll(jout.ToString());
server->UnLockThread();
};
/*
res = json.GetValue("command", &value);

@ -5,9 +5,7 @@
Turnouts::Turnouts() {
changed = 0;
turnouts = (Turnout*) malloc(sizeof(Turnout)*TURNOUTS_MAX);
memset (turnouts, 0x0, sizeof(Turnout)*TURNOUTS_MAX);
max = TURNOUTS_MAX;
pthread_mutex_init(&mtx, NULL);
};
Turnouts::~Turnouts() {
@ -166,33 +164,20 @@ int Turnouts::Delete(string name) {
int Turnouts::Set(string name, int value) {
int i;
JSONParse jp;
//
Lock();
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
if (name.compare(turnouts[i].name) == 0) {
debug (0, "%s:%d Turnout::Set: Name:%s Flags:%d[%c%c%c%c] Value:%d", __FILE__, __LINE__, name.c_str(), turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_ISRELAIS) ? 'R' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
debug (0, "Turnout::Set: Name:%s Flags:%d[%c%c%c] Value:%d", name.c_str(), turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-',
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
value);
if (turnouts[i].flags & TURNOUT_F_ISRELAIS) {
printf ("%s:%d is relais.... %d\n", __FILE__, __LINE__, value);
server->interfaces.SetTurnout(&turnouts[i], value, value);
}
else {
if (turnouts[i].flags & TURNOUT_F_INVERSE)
server->interfaces.SetTurnout(&turnouts[i], !value, 1); // motor on
else
server->interfaces.SetTurnout(&turnouts[i], value, 1); // motor on
}
jp.Clear();
jp.AddObject("turnout", _GetJSON(i));
if (network) network->ChangeListPushToAll(jp.ToString());
gettimeofday (&turnouts[i].activatetime, NULL);
changed = 1;
@ -230,15 +215,14 @@ void Turnouts::SetFromBus(string ifname, int addr, int value) {
int i;
JSONParse jp;
debug (0, "%s:%d Turnouts::SetFromBus Interface:%s, addr: %d, value:%d", __FILE__, __LINE__, ifname.c_str(), addr, value);
debug (0, "Turnouts::SetFromBus Interface:%s, addr: %d, value:%d", ifname.c_str(), addr, value);
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
if (ifname.compare(turnouts[i].ifname) == 0 && turnouts[i].addr == addr) {
debug (0, "%s:%d Turnout::SetFromBus Name:%s Flags:%d[%c%c%c%c]", __FILE__, __LINE__, turnouts[i].name, turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_ISRELAIS) ? 'R' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
debug (0, "Turnout::SetFromBus Name:%s Flags:%d[%c%c%c]", turnouts[i].name, turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-',
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-');
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-');
// if (value) turnouts[i].flags |= TURNOUT_F_ACTIVE;
// else turnouts[i].flags &= ~TURNOUT_F_ACTIVE;
@ -251,11 +235,10 @@ void Turnouts::SetFromBus(string ifname, int addr, int value) {
if (value) turnouts[i].flags |= TURNOUT_F_TURNOUT;
else turnouts[i].flags &= ~TURNOUT_F_TURNOUT;
}
debug (0, "%s:%d Turnout::SetFromBus Name:%s Flags:%d[%c%c%c%c]", __FILE__, __LINE__, turnouts[i].name, turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_ISRELAIS) ? 'R' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
debug (0, "Turnout::SetFromBus Name:%s Flags:%d[%c%c%c]", turnouts[i].name, turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-',
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-');
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-');
jp.AddObject("turnout", _GetJSON(i));
if(network) network->ChangeListPushToAll(jp.ToString());
@ -265,13 +248,11 @@ void Turnouts::SetFromBus(string ifname, int addr, int value) {
/*
* this loop is important: some outputs especially motors needs to be deactivated
* after a short period of time.
*/
//
// this loop is important: Turnout motors needs to be deactivated after a short time
//
void Turnouts::Loop() {
int i;
JSONParse jp;
struct timeval curtime;
gettimeofday(&curtime, NULL);
@ -279,9 +260,9 @@ void Turnouts::Loop() {
Lock();
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
if ((turnouts[i].flags & TURNOUT_F_ACTIVE) && ((turnouts[i].flags & TURNOUT_F_ISRELAIS) == 0)) {
if (turnouts[i].flags & TURNOUT_F_ACTIVE) {
//
// motor/output still active check timeout and deactivate
// motor still active check timeout and deactivate
int timediff = (1000 * (curtime.tv_sec - turnouts[i].activatetime.tv_sec)) +
((curtime.tv_usec - turnouts[i].activatetime.tv_usec) / 1000);
if (timediff < 0) gettimeofday (&turnouts[i].activatetime, NULL);
@ -289,25 +270,12 @@ void Turnouts::Loop() {
// debug (0, "%s:%d timediff: %d", __FILE__, __LINE__, timediff);
if (timediff > turnouts[i].activetimeout) {
int turnout = (turnouts[i].flags & TURNOUT_F_TURNOUT) != 0 ? 1 : 0;
debug (0, "%s:%d Turnout::Loop Name:%s Flags:%d[%c%c%c%c] Turnout:%d", __FILE__, __LINE__, turnouts[i].name, turnouts[i].flags,
(turnouts[i].flags & TURNOUT_F_ISRELAIS) ? 'R' : '-',
(turnouts[i].flags & TURNOUT_F_TURNOUT) ? 'T' : '-',
(turnouts[i].flags & TURNOUT_F_ACTIVE) ? 'A' : '-',
(turnouts[i].flags & TURNOUT_F_INVERSE) ? 'I' : '-',
turnout);
int active = turnouts[i].flags & TURNOUT_F_TURNOUT;
if (turnouts[i].flags & TURNOUT_F_INVERSE)
server->interfaces.SetTurnout(&turnouts[i], !turnout, 0); // motor on
server->interfaces.SetTurnout(&turnouts[i], !active, 0); // motor on
else
server->interfaces.SetTurnout(&turnouts[i], turnout, 0); // motor on
server->interfaces.SetTurnout(&turnouts[i], active, 0); // motor on
turnouts[i].flags &= ~TURNOUT_F_ACTIVE;
jp.Clear();
jp.AddObject("turnout", _GetJSON(i));
if (network) network->ChangeListPushToAll(jp.ToString());
}
}
}
@ -339,34 +307,3 @@ int Turnouts::GetFlags(int idx) {
};
void Turnouts::SetFlags(int idx, int flags) {
JSONParse jp;
Lock();
if (idx <= max && idx >= 0) {
turnouts[idx].flags = flags;
jp.Clear();
jp.AddObject("turnout", _GetJSON(idx));
if (network) network->ChangeListPushToAll(jp.ToString());
}
UnLock();
};
int Turnouts::GetIdx(string name) {
int i;
int res = -1;
//
Lock();
for (i = 0; i < max; i++) if (turnouts[i].name[0] != 0) {
if (name.compare(turnouts[i].name) == 0) {
res = i;
break;
}
}
UnLock();
return res;
}

@ -6,9 +6,8 @@
#include "server.h"
//
#define TURNOUT_F_INVERSE 0x0001 // inverse output
#define TURNOUT_F_ACTIVE 0x0002 // motor/output active
#define TURNOUT_F_ACTIVE 0x0002 // motor active
#define TURNOUT_F_TURNOUT 0x0004 // turnout active
#define TURNOUT_F_ISRELAIS 0x0008 // output is relais no auto off
#define TURNOUT_DEFAULT_ACTIVETIMEOUT 250 // active timeout default value
@ -55,9 +54,7 @@ class Turnouts {
Turnout GetTurnoutFromJSON(JSONParse *j);
string GetName(int idx);
int GetIdx(string name);
int GetFlags(int idx);
void SetFlags(int idx, int flags);
void SetFromBus(string name, int addr, int active);
};

@ -4,14 +4,13 @@
var blocks = [];
const BLOCK_F_OFF = 0x0001;
const BLOCK_F_SPLIT = 0x0002;
const BLOCK_F_SPLITPOS = 0x0004;
const BLOCK_F_SHORT = 0x0010;
const BLOCK_F_LONG = 0x0020;
const BLOCK_F_ENDSTATION = 0x0040;
const BLOCK_F_STATION = 0x0080;
const BLOCK_F_SPEEDLIMIT = 0x0100;
const BLOCK_F_ONLYCARGO = 0x0200;
const BLOCK_F_ONLYPASSENGER = 0x0400;
//
// update or add a new element
@ -22,35 +21,23 @@ function block_Update(blockdata) {
blocks[i].name = blockdata.name;
blocks[i].flags = blockdata.flags;
blocks[i].lockedby = blockdata.lockedby;
blocks[i].sensor_stop_0 = blockdata.sensor_stop_0;
blocks[i].sensor_shortstop_0 = blockdata.sensor_shortstop_0;
blocks[i].sensor_slow_0 = blockdata.sensor_slow_0;
blocks[i].sensor_enter_0 = blockdata.sensor_enter_0;
blocks[i].sensor_stop_1 = blockdata.sensor_stop_1;
blocks[i].sensor_shortstop_1 = blockdata.sensor_shortstop_1;
blocks[i].sensor_slow_1 = blockdata.sensor_slow_1;
blocks[i].sensor_enter_1 = blockdata.sensor_enter_1;
blocks[i].secondblock = blockdata.secondblock;
blocks[i].sensor_pos_1 = blockdata.sensor_pos_1,
blocks[i].sensor_center = blockdata.sensor_center,
blocks[i].sensor_neg_1 = blockdata.sensor_neg_1
blockdetail_setData(blocks[i]);
return;
}
}
// not found add element
//console.log ("Add Interface:" + intdata.name + "(" + intdata.host + ")");
//debug ("Add Interface:" + intdata.name + "(" + intdata.host + ")");
blocks.push ({
name: blockdata.name,
flags: blockdata.flags,
lockedby: blockdata.lockedby,
sensor_enter_0: blockdata.sensor_enter_0,
sensor_slow_0: blockdata.sensor_slow_0,
sensor_stop_0: blockdata.sensor_stop_0,
sensor_shortstop_0: blockdata.sensor_shortstop_0,
sensor_enter_1: blockdata.sensor_enter_1,
sensor_slow_1: blockdata.sensor_slow_1,
sensor_stop_1: blockdata.sensor_stop_1,
sensor_shortstop_1: blockdata.sensor_shortstop_1,
secondblock: blockdata.secondblock
sensor_pos_1: blockdata.sensor_pos_1,
sensor_center: blockdata.sensor_center,
sensor_neg_1: blockdata.sensor_neg_1
});
};
@ -191,23 +178,13 @@ function block_server_Clear(blockname) {
//
function block_server_Off(blockname) {
var request = { command: "blockoff", block: blockname };
console.log ("send BlockOff:" + blockname);
debug ("send BlockOff:" + blockname);
serverinout (request, serverinout_defaultCallback);
};
//
// if create is set the name should be filled in
function blockdetail_fillsensor() {
let r = "<option value=\"\"></option>";
for (var i = 0; i < sensors.length; i++) {
if (sensors[i].name)
r += "<option value=\""+sensors[i].name+"\">"+sensors[i].name+"</option>";
};
return r;
}
function blockdetail_show(name, create) {
var win = document.getElementById("blockdetail");
let innerHTML = " \
@ -221,44 +198,44 @@ function blockdetail_show(name, create) {
\
<table><tr><td>\
\
<table><tr> \
<td><label><input id=\"blockdet_flagoff\" type=\"checkbox\" value=\"\" disabled>Off Service</label></td> \
<td><label><input id=\"blockdet_flagonlycargo\" type=\"checkbox\" value=\"\">Only Cargo</label></td> \
<td><label><input id=\"blockdet_flagshort\" type=\"checkbox\" value=\"\">Short</label></td> \
</tr><tr> \
<td><label><input id=\"blockdet_flagend\" type=\"checkbox\" value=\"\">End</label></td> \
<td><label><input id=\"blockdet_flagonlypassenger\" type=\"checkbox\" value=\"\">Only Passenger</label></td> \
<td><label><input id=\"blockdet_flagsplit\" type=\"checkbox\" value=\"\">Split</label></td> \
</tr><tr> \
<td><label><input id=\"blockdet_flagspeedlimit\" type=\"checkbox\" value=\"\">Speed Limit</label></td> \
<td><label><input id=\"blockdet_flagstation\" type=\"checkbox\" value=\"\">Station</label></td> \
<td><label><input id=\"blockdet_flagsplitpos\" type=\"checkbox\" value=\"\">Splitpos</label></td> \
</tr><tr> \
<td></td><td>second block:</td><td>";
innerHTML += "<input id=\"blockdet_secondblock\" style=\"width: 100\">";
innerHTML += " \
</tr></table> \
<table><tr><td> \
<label><input id=\"blockdet_flagoff\" type=\"checkbox\" value=\"\" disabled>Off Service</label><br> \
<label><input id=\"blockdet_flagshort\" type=\"checkbox\" value=\"\">Short</label><br>\
<label><input id=\"blockdet_flaglong\" type=\"checkbox\" value=\"\">Long</label> \
</td><td> \
<label><input id=\"blockdet_flagend\" type=\"checkbox\" value=\"\">End</label><br> \
<label><input id=\"blockdet_flagstation\" type=\"checkbox\" value=\"\">Station</label><br> \
<label><input id=\"blockdet_flagspeedlimit\" type=\"checkbox\" value=\"\">Speed Limit</label><br> \
</td></tr></table> \
\
</td><td></td></tr></table> \
<fieldset><legend>Automatic Mode</legend><table> \
<tr><td>Lockedby:</td><td><input id=\"blockdet_lockedby\" style=\"width: 100\" disabled></td></tr>"
innerHTML += "<table><tr><td></td><td>enter</td><td>slow</td><td>shortstop</td><td>stop</td></tr>";
innerHTML += "<tr><td>Direction &rarr;&darr;:</td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_enter_0\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_slow_0\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_shortstop_0\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_stop_0\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "</tr>";
innerHTML += "<tr><td>Direction &larr;&uarr;:</td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_enter_1\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_slow_1\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_shortstop_1\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "<td align=center><label><select id=\"blockdet_sensor_stop_1\">" + blockdetail_fillsensor() + "</select></label></td>";
innerHTML += "</tr></table>";
innerHTML += "</td></tr></table></fileset>\
<tr><td>Lockedby:</td><td><input id=\"blockdet_lockedby\" style=\"width: 100\" disabled></td></tr>\
<tr><td>Sensor &larr;&uarr;:</td><td><label><select id=\"blockdet_sensorLU\">";
innerHTML += "<option value=\"\"></option>";
for (var i = 0; i < sensors.length; i++) {
if (sensors[i].name)
innerHTML += "<option value=\""+sensors[i].name+"\">"+sensors[i].name+"</option>";
}
innerHTML += "</select></label></td></tr>\
<tr><td>Sensor Center:</td><td><label><select id=\"blockdet_sensorC\">";
innerHTML += "<option value=\"\"></option>";
for (var i = 0; i < sensors.length; i++) {
if (sensors[i].name)
innerHTML += "<option value=\""+sensors[i].name+"\">"+sensors[i].name+"</option>";
}
innerHTML += "</select></label></td></tr>\
<tr><td>Sensor &rarr;&darr;:</td><td><label><select id=\"blockdet_sensorRD\">";
innerHTML += "<option value=\"\"></option>";
for (var i = 0; i < sensors.length; i++) {
if (sensors[i].name)
innerHTML += "<option value=\""+sensors[i].name+"\">"+sensors[i].name+"</option>";
}
innerHTML += "</select></label></td></tr>\
</table></fileset>\
</div> <hr>\
<div align=right> \
<button id=\"blockdet_SAVE\" type=\"button\">Save</button> \
@ -267,10 +244,10 @@ function blockdetail_show(name, create) {
</div> \
\
";
console.log ("blockdetail_show");
debug ("blockdetail_show");
if (!win) {
console.log ("blockdetail_show create window");
debug ("blockdetail_show create window");
win = gWindowCreate("blockdetail", "Block", 500, 400, innerHTML);
gAddEventListener("blockdet_CLOSE", 'click', blockdetail_cb_close);
@ -344,7 +321,7 @@ function blockdetail_cb_next () {
if (i == cursel) blockdetail_setData(blocks[i]);
}
// console.log ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
// debug ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
};
@ -367,7 +344,7 @@ function blockdetail_cb_prev () {
if (i == cursel) blockdetail_setData(blocks[i]);
}
// console.log ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
// debug ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
};
@ -378,44 +355,26 @@ function blockdetail_setData(elm) {
var name = document.getElementById("blockdet_name");
var flagoff = document.getElementById("blockdet_flagoff");
var flagshort = document.getElementById("blockdet_flagshort");
var flagsplit = document.getElementById("blockdet_flagsplit");
var flagsplitpos = document.getElementById("blockdet_flagsplitpos");
var flaglong = document.getElementById("blockdet_flaglong");
var flagend = document.getElementById("blockdet_flagend");
var flagonlycargo = document.getElementById("blockdet_flagonlycargo");
var flagonlypassenger = document.getElementById("blockdet_flagonlypassenger");
var flagstation = document.getElementById("blockdet_flagstation");
var flagspeedlimit = document.getElementById("blockdet_flagspeedlimit");
var sensor_enter_0 = document.getElementById("blockdet_sensor_enter_0");
var sensor_slow_0 = document.getElementById("blockdet_sensor_slow_0");
var sensor_stop_0 = document.getElementById("blockdet_sensor_stop_0");
var sensor_shortstop_0 = document.getElementById("blockdet_sensor_shortstop_0");
var sensor_enter_1 = document.getElementById("blockdet_sensor_enter_1");
var sensor_slow_1 = document.getElementById("blockdet_sensor_slow_1");
var sensor_stop_1 = document.getElementById("blockdet_sensor_stop_1");
var sensor_shortstop_1 = document.getElementById("blockdet_sensor_shortstop_1");
var sensorLU = document.getElementById("blockdet_sensorLU");
var sensorC = document.getElementById("blockdet_sensorC");
var sensorRD = document.getElementById("blockdet_sensorRD");
var lockedby = document.getElementById("blockdet_lockedby");
var secondblock = document.getElementById("blockdet_secondblock");
if (elm) {
if (name) name.value = elm.name;
if (flagoff) flagoff.checked = Number(elm.flags) & BLOCK_F_OFF;
if (flagshort) flagshort.checked = Number(elm.flags) & BLOCK_F_SHORT;
if (flagsplit) flagsplit.checked = Number(elm.flags) & BLOCK_F_SPLIT;
if (flagsplitpos) flagsplitpos.checked = Number(elm.flags) & BLOCK_F_SPLITPOS;
if (flaglong) flaglong.checked = Number(elm.flags) & BLOCK_F_LONG;
if (flagend) flagend.checked = Number(elm.flags) & BLOCK_F_ENDSTATION;
if (flagonlycargo) flagonlycargo.checked = Number(elm.flags) & BLOCK_F_ONLYCARGO;
if (flagonlypassenger) flagonlypassenger.checked = Number(elm.flags) & BLOCK_F_ONLYPASSENGER;
if (flagstation) flagstation.checked = Number(elm.flags) & BLOCK_F_STATION;
if (flagspeedlimit) flagspeedlimit.checked = Number(elm.flags) & BLOCK_F_SPEEDLIMIT;
if (sensor_enter_0) sensor_enter_0.value = elm.sensor_enter_0;
if (sensor_slow_0) sensor_slow_0.value = elm.sensor_slow_0;
if (sensor_stop_0) sensor_stop_0.value = elm.sensor_stop_0;
if (sensor_shortstop_0) sensor_shortstop_0.value = elm.sensor_shortstop_0;
if (sensor_enter_1) sensor_enter_1.value = elm.sensor_enter_1;
if (sensor_slow_1) sensor_slow_1.value = elm.sensor_slow_1;
if (sensor_stop_1) sensor_stop_1.value = elm.sensor_stop_1;
if (sensor_shortstop_1) sensor_shortstop_1.value = elm.sensor_shortstop_1;
if (secondblock) secondblock.value = elm.secondblock;
if (sensorLU) sensorLU.value = elm.sensor_pos_1;
if (sensorC) sensorC.value = elm.sensor_center;
if (sensorRD) sensorRD.value = elm.sensor_neg_1;
if (lockedby) lockedby.value = elm.lockedby;
}
};
@ -430,63 +389,30 @@ function blockdetail_getData() {
var name = document.getElementById("blockdet_name");
var flagoff = document.getElementById("blockdet_flagoff");
var flagshort = document.getElementById("blockdet_flagshort");
var flagsplit = document.getElementById("blockdet_flagsplit");
var flagsplitpos = document.getElementById("blockdet_flagsplitpos");
var flaglong = document.getElementById("blockdet_flaglong");
var flagend = document.getElementById("blockdet_flagend");
var flagonlycargo = document.getElementById("blockdet_flagonlycargo");
var flagonlypassenger = document.getElementById("blockdet_flagonlypassenger");
var flagstation = document.getElementById("blockdet_flagstation");
var flagspeedlimit = document.getElementById("blockdet_flagspeedlimit");
var sensor_enter_0 = document.getElementById("blockdet_sensor_enter_0");
var sensor_slow_0 = document.getElementById("blockdet_sensor_slow_0");
var sensor_stop_0 = document.getElementById("blockdet_sensor_stop_0");
var sensor_shortstop_0 = document.getElementById("blockdet_sensor_shortstop_0");
var sensor_enter_1 = document.getElementById("blockdet_sensor_enter_1");
var sensor_slow_1 = document.getElementById("blockdet_sensor_slow_1");
var sensor_stop_1 = document.getElementById("blockdet_sensor_stop_1");
var sensor_shortstop_1 = document.getElementById("blockdet_sensor_shortstop_1");
var secondblock = document.getElementById("blockdet_secondblock");
var sensorLU = document.getElementById("blockdet_sensorLU");
var sensorC = document.getElementById("blockdet_sensorC");
var sensorRD = document.getElementById("blockdet_sensorRD");
if (name) res.name = name.value;
if (flagoff.checked) res.flags |= BLOCK_F_OFF;
else res.flags &= ~BLOCK_F_OFF;
if (flagshort.checked) res.flags |= BLOCK_F_SHORT;
else res.flags &= ~BLOCK_F_SHORT;
if (flagsplit.checked) res.flags |= BLOCK_F_SPLIT;
else res.flags &= ~BLOCK_F_SPLIT;
if (flagsplitpos.checked) res.flags |= BLOCK_F_SPLITPOS;
else res.flags &= ~BLOCK_F_SPLITPOS;
if (flaglong.checked) res.flags |= BLOCK_F_LONG;
else res.flags &= ~BLOCK_F_LONG;
if (flagend.checked) res.flags |= BLOCK_F_ENDSTATION;
else res.flags &= ~BLOCK_F_ENDSTATION;
if (flagonlycargo.checked) res.flags |= BLOCK_F_ONLYCARGO;
else res.flags &= ~BLOCK_F_ONLYCARGO;
if (flagonlypassenger.checked) res.flags |= BLOCK_F_ONLYPASSENGER;
else res.flags &= ~BLOCK_F_ONLYPASSENGER;
if (flagstation.checked) res.flags |= BLOCK_F_STATION;
else res.flags &= ~BLOCK_F_STATION;
if (flagspeedlimit.checked) res.flags |= BLOCK_F_SPEEDLIMIT;
else res.flags &= ~BLOCK_F_SPEEDLIMIT;
if (sensor_enter_0) res.sensor_enter_0 = sensor_enter_0.value;
if (sensor_slow_0) res.sensor_slow_0 = sensor_slow_0.value;
if (sensor_stop_0) res.sensor_stop_0 = sensor_stop_0.value;
if (sensor_shortstop_0) res.sensor_shortstop_0 = sensor_shortstop_0.value;
if (sensor_enter_1) res.sensor_enter_1 = sensor_enter_1.value;
if (sensor_slow_1) res.sensor_slow_1 = sensor_slow_1.value;
if (sensor_stop_1) res.sensor_stop_1 = sensor_stop_1.value;
if (sensor_shortstop_1) res.sensor_shortstop_1 = sensor_shortstop_1.value;
if (secondblock) res.secondblock = secondblock.value;
if (sensorLU) res.sensor_pos_1 = sensorLU.value;
if (sensorC) res.sensor_center = sensorC.value;
if (sensorRD) res.sensor_neg_1 = sensorRD.value;
return res;
};

@ -91,7 +91,7 @@ button {
input {
border: 1px solid var(--input-fg-color);
border: 1px solid var(--input-bg-color);
background-color: var(--input-bg-color);
color: var(--input-fg-color);
font-family: "Lucida Console", Courier, monospace;

@ -6,7 +6,7 @@ var MousePosY = null;
//
// init all variables with the class givin
$(document).ready(function() {
// console.log ("init");
// debug ("init");
$(".GUIwindow").each( function (i) {
gWindowDragElement(this);
@ -65,7 +65,7 @@ function gContextmenuCreate(title, clientInnerHTML) {
parent.removeChild(cm);
}
console.log("create Contextmenu:" + title);
debug("create Contextmenu:" + title);
var head = document.createElement("div");
head.setAttribute("id", "ConextMenuHead");
@ -88,9 +88,6 @@ function gContextmenuCreate(title, clientInnerHTML) {
cm.style.top = getMouseY();
cm.style.left = getMouseX();
if (parseInt(cm.style.left) + 150 > window.innerWidth) cm.style.left = window.innerWidth - 150;
if (parseInt(cm.style.top) + 400 > window.innerHeight) cm.style.top = window.innerHeight - 400;
return cm;
};

@ -0,0 +1,9 @@
function debug (t) {
var pre = document.getElementById("debug");
var div = document.getElementById("debug_div");
if (pre) pre.innerHTML = pre.innerHTML + "<br>" + t;
if (div) div.scrollTop = div.scrollHeight;
};

@ -77,7 +77,7 @@ function gWindowDragElement(elmnt) {
function gWindowCreate(id, title, sizex, sizey, clientHTML) {
var win = document.getElementById(id);
if (!win) {
console.log("create Title:" + title);
debug("create Title:" + title);
var head = document.createElement("div");
head.setAttribute("id", id+"Head");
@ -98,7 +98,7 @@ function gWindowCreate(id, title, sizex, sizey, clientHTML) {
document.body.appendChild(win);
gWindowDragElement(win);
console.log ("move to 100px from top");
debug ("move to 100px from top");
win.style.top = "100px";
}
return win;
@ -108,7 +108,7 @@ function gWindowCreate(id, title, sizex, sizey, clientHTML) {
function gWindowCreateSize(id, title, sizex, sizey) {
var win = document.getElementById(id);
if (!win) {
console.log("create Title:" + title);
debug("create Title:" + title);
var head = document.createElement("div");
head.setAttribute("id", id+"Head");
@ -129,7 +129,7 @@ function gWindowCreateSize(id, title, sizex, sizey) {
win.appendChild (client);
document.body.appendChild(win);
gWindowDragElement(win);
console.log ("move to 100px from top");
debug ("move to 100px from top");
win.style.top = "100px";
}
return win;

@ -3,6 +3,7 @@
<head>
<title>Modelbahn</title>
<script src="jquery-3.1.0.min.js"></script>
<script src="gui/guidebug.js"></script>
<script src="gui/guiwindow.js"></script>
<script src="gui/gui.js"></script>
<script src="serverinout.js"></script>
@ -27,6 +28,7 @@
</button>
<div class="dropdown-content">
<a href="#" onclick="serverinout_Save(this);">Save</a>
<a href="#" onclick="debug_Enable(this);">Debug</a>
</div>
</div>
<div class="dropdown">
@ -84,8 +86,24 @@
<div class="page_main" id="page_main"></div>
<div class="page_bottom" id="debug_div">
<pre id="debug"></pre>
</div>
<script>
function debug_Enable() {
var x = document.getElementById("debug_div");
if (x.style.display === "none") {
$(':root').css('--bottom-height', '256px');
x.style.display = "block";
} else {
$(':root').css('--bottom-height', '0px');
x.style.display = "none";
}
}
$(document).ready(function() {
var client = document.getElementById("page_main");

@ -10,7 +10,7 @@ var interfaces = [];
function interface_Update(intdata) {
for (var i = 0; i < interfaces.length; i++) {
if (intdata.name == interfaces[i].name) {
console.log ("Update Interface:" + interfaces[i].name + "(" + interfaces[i].host + ") with Interface:" + intdata.name + "(" + intdata.host + ") Flags:" + intdata.flags);
//debug ("Update Interface:" + interfaces[i].name + "(" + interfaces[i].host + ") with Interface:" + intdata.name + "(" + intdata.host + ")");
if (!(intdata.flags & 0x0001)) sideBtnOnOffMode (3); // not connected
else if ((intdata.flags & 0x0010)) sideBtnOnOffMode (3); // programming mode
@ -28,7 +28,7 @@ function interface_Update(intdata) {
}
// not found add element
//console.log ("Add Interface:" + intdata.name + "(" + intdata.host + ")");
//debug ("Add Interface:" + intdata.name + "(" + intdata.host + ")");
interfaces.push ({
name: intdata.name,
host: intdata.host,
@ -80,10 +80,10 @@ function interface_server_Del(elm) {
function intdetail_show(intname) {
var win = document.getElementById("intdetail");
console.log ("intdetail_show");
debug ("intdetail_show");
if (!win) {
console.log ("intdetail_show create window");
debug ("intdetail_show create window");
win = gWindowCreate("intdetail", "Interface", 400, 300, " \
<div style=\"float: left\"> \
Interface Name: <input id=\"intdet_name\" style=\"width: 100\"> \
@ -181,7 +181,7 @@ function intdetail_cb_next () {
if (i == cursel) intdetail_setData(interfaces[i]);
}
// console.log ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
// debug ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
};
@ -204,7 +204,7 @@ function intdetail_cb_prev () {
if (i == cursel) intdetail_setData(interfaces[i]);
}
// console.log ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
// debug ("Cursel: " + cursel + " interfaces.lenght:" + interfaces.length);
};

@ -5,9 +5,9 @@ body {
}
:root {
--top-height: 35px;
--top-height: 34px;
--side-width: 37px;
--bottom-height: 0px;
--bottom-height: 2px;
--menu-bg-color: #333;
--menu-fg-color: linen;
@ -33,8 +33,6 @@ body {
--turnout-other: #666;
--sensor-active: #0F0;
--sensor-inactive: #666;
--button-active: #0F0;
--button-inactive: #666;
}
.page_side {

@ -7,9 +7,8 @@ const LOCO_F_CARGO = 0x0010;
const LOCO_F_CANREVERSE = 0x0020;
const LOCO_F_SHORTTRAIN = 0x0040;
const LOCO_F_AUTO = 0x0100;
const LOCO_F_AUTOSHED = 0x0200;
const LOCO_F_AUTORANDOM = 0x0400;
const LOCO_F_AUTOSTOP = 0x0800;
const LOCO_F_RANDOM = 0x0200;
const LOCO_F_AUTOSTOP = 0x0400;
var locomotives = [];
@ -20,9 +19,7 @@ var locomotives = [];
function locomotive_Update(data) {
for (var i = 0; i < locomotives.length; i++) {
if (data.name == locomotives[i].name) {
var loco_name = document.getElementById("locodet_name");
console.log ("Update Locomotive:" + locomotives[i].name + " with Locomotive:" + data.name);
debug ("Update Locomotive:" + locomotives[i].name + " with Locomotive:" + data.name);
locomotives[i].name = data.name;
locomotives[i].ifname = data.ifname;
locomotives[i].addr = data.addr;
@ -35,25 +32,18 @@ function locomotive_Update(data) {
locomotives[i].vmax = data.vmax;
locomotives[i].flags = data.flags;
if (data.blockassign) locomotives[i].blockassign = data.blockassign;
else locomotives[i].blockassign = "";
if (data.blockprev) locomotives[i].blockprev = data.blockprev;
else locomotives[i].blockprev = "";
if (data.blocknext) locomotives[i].blocknext = data.blocknext;
else locomotives[i].blocknext = "";
if (data.blockdest) locomotives[i].blockdest = data.blockdest;
else locomotives[i].blockdest = "";
if (data.schedway) locomotives[i].schedway = data.schedway;
else locomotives[i].schedway = "";
if (data.auto_way) locomotives[i].auto_way = data.auto_way;
if (loco_name == data.name) locodetail_setData(locomotives[i]);
locodetail_setData(locomotives[i]);
lococtrl_setData(data);
return;
}
}
// not found add element
console.log ("Add Locomotive:" + data.name);
debug ("Add Locomotive:" + data.name);
locomotives.push ({
name: data.name,
ifname: data.ifname,
@ -70,7 +60,6 @@ function locomotive_Update(data) {
blockdest: data.blockdest,
blocknext: data.blocknext,
blockprev: data.blockprev,
schedway: data.schedway,
auto_way: data.auto_way
});
@ -147,11 +136,11 @@ function locomotive_server_Set(elm) {
function locodetail_show(loconame) {
var win = document.getElementById("locodetail");
console.log ("locodetail_show");
debug ("locodetail_show");
if (!win) {
console.log ("loco_showdetail create window");
win = gWindowCreate("locodetail", "Locomotive", 450, 550,
debug ("loco_showdetail create window");
win = gWindowCreate("locodetail", "Locomotive", 450, 500,
"<div style=\"float: left\"> \
Name: <input id=\"locodet_name\" style=\"width: 100\"> \
</div> <div style=\"float: right\"> \
@ -163,18 +152,16 @@ function locodetail_show(loconame) {
Adress: <input id=\"locodet_addr\" style=\"width: 50\"> \
Flags: <input id=\"locodet_flags\" style=\"width: 50\"> \
</div> <hr>\
<div><table><tr><td> \
<div> <table><tr><td> \
<table><tr><td> \
<label><input id=\"locodet_auto\" type=\"checkbox\" value=\"\" disabled>Auto</label><br> \
<label><input id=\"locodet_autoshed\" type=\"checkbox\" value=\"\" disabled>Sheduler</label><br> \
<label><input id=\"locodet_autorandom\" type=\"checkbox\" value=\"\" disabled>Random</label><br> \
<label><input id=\"locodet_random\" type=\"checkbox\" value=\"\" disabled>Random</label><br> \
</td><td> \
<label><input id=\"locodet_cargo\" type=\"checkbox\" value=\"\">Cargo</label><br> \
<label><input id=\"locodet_short\" type=\"checkbox\" value=\"\">Short Train</label><br> \
<label><input id=\"locodet_canreverse\" type=\"checkbox\" value=\"\">Can Reverse</label><br> \
</td><td> \
<label><input id=\"locodet_cargo\" type=\"checkbox\" value=\"\">Cargo</label><br> \
</td></tr></table></div> \
</td></tr></table> \
\
<div> <table><tr><td> \
<fieldset><legend>Speed</legend> <table>\
<label><input id=\"locodet_reverse\" type=\"checkbox\" value=\"\">Reverse</label><br> \
<tr><td></td><td>Stop</td><td><button id=\"locodet_btnvstop\" type=\"button\" value=\"vstop\">X</button> </td></tr>\
@ -202,13 +189,7 @@ function locodetail_show(loconame) {
</table><button id=\"locodet_RESET\" type=\"button\">Reset</button> \
<button id=\"locodet_TEST\" type=\"button\">Test</button></fileset>\
\
</td></tr></table></div> \
\
<table><tr><td> \
Sched. Way: <input id=\"locodet_schedway\" style=\"width: 250\" placeholder=\"B:+:B13,W:30,B:-:B42,W:15\"> \
</td></tr></table> \
\
<hr>\
</td></tr></table></div> <hr>\
<div align=right> \
<button id=\"locodet_SAVE\" type=\"button\">Save</button> \
<button id=\"locodet_DELETE\" type=\"button\">Delete</button> \
@ -245,7 +226,7 @@ function locodetail_show(loconame) {
//
// load default values
var res = { name: "", ifname: "", addr: "", flags: 0, steps: "",
vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100", schedway: "" };
vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100" };
locodetail_setData(res);
if (loconame) {
@ -363,7 +344,7 @@ function locodetail_cb_btnmove () {
}
locomotive_server_Set ({name: loco_name.value, speed: speed});
console.log ("Locomotive: '" + loco_name.value +"' Speed: " + speed);
debug ("Locomotive: '" + loco_name.value +"' Speed: " + speed);
};
@ -417,7 +398,7 @@ function locodetail_cb_next () {
if (i == cursel) locodetail_setData(locomotives[i]);
}
console.log ("Cursel: " + cursel + " locomotives.lenght:" + locomotives.length);
debug ("Cursel: " + cursel + " locomotives.lenght:" + locomotives.length);
};
@ -440,7 +421,7 @@ function locodetail_cb_prev () {
if (i == cursel) locodetail_setData(locomotives[i]);
}
console.log ("Cursel: " + cursel + " locomotives.lenght:" + locomotives.length);
debug ("Cursel: " + cursel + " locomotives.lenght:" + locomotives.length);
};
@ -463,14 +444,12 @@ function locodetail_setData(elm) {
var loco_short = document.getElementById("locodet_short");
var loco_cargo = document.getElementById("locodet_cargo");
var loco_auto = document.getElementById("locodet_auto");
var loco_autorandom = document.getElementById("locodet_autorandom");
var loco_autoshed = document.getElementById("locodet_autoshed");
var loco_random = document.getElementById("locodet_random");
var loco_blockassign = document.getElementById("locodet_blockassign");
var loco_blockdest = document.getElementById("locodet_blockdest");
var loco_blocknext = document.getElementById("locodet_blocknext");
var loco_blockprev = document.getElementById("locodet_blockprev");
var loco_auto_way = document.getElementById("locodet_auto_way");
var loco_schedway = document.getElementById("locodet_schedway");
if (elm) {
if (loco_name) loco_name.value = elm.name;
@ -503,27 +482,21 @@ function locodetail_setData(elm) {
if (Number(elm.flags) & LOCO_F_AUTO) loco_auto.checked = true;
else loco_auto.checked = false;
}
if (loco_autorandom) {
if (Number(elm.flags) & LOCO_F_AUTORANDOM) loco_autorandom.checked = true;
else loco_autorandom.checked = false;
}
if (loco_autoshed) {
if (Number(elm.flags) & LOCO_F_AUTOSHED) loco_autoshed.checked = true;
else loco_autoshed.checked = false;
if (loco_random) {
if (Number(elm.flags) & LOCO_F_RANDOM) loco_random.checked = true;
else loco_random.checked = false;
}
if (loco_blockassign) loco_blockassign.value = elm.blockassign;
if (loco_blockdest) loco_blockdest.value = elm.blockdest;
if (loco_blocknext) loco_blocknext.value = elm.blocknext;
if (loco_blockprev) loco_blockprev.value = elm.blockprev;
if (loco_schedway && elm.schedway) loco_schedway.value = elm.schedway;
else if (loco_shedway) loco_schedway.value = "";
if (loco_auto_way) loco_auto_way.value = elm.auto_way;
}
var codes = document.getElementsByName('STEPCODE');
for(var i = 0; i < codes.length; i++) {
// console.log ("STEPCODE: elm.stepcode: " + elm.stepcode + " i:" + i + " codes[i].value: " + codes[i].value + " codes.id: " + codes[i].id);
// debug ("STEPCODE: elm.stepcode: " + elm.stepcode + " i:" + i + " codes[i].value: " + codes[i].value + " codes.id: " + codes[i].id);
if(elm.stepcode == codes[i].value) codes[i].checked = true;
else codes[i].checked = false;
}
@ -536,7 +509,7 @@ function locodetail_setData(elm) {
//
function locodetail_getData() {
var res = { name: "", ifname: "", addr: "", flags: 0, stepcode:"0",
vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100", schedway: "" };
vmin: "20", vslow: "40", vmid:"60", vfast:"80", vmax:"100" };
var codes = document.getElementsByName('STEPCODE');
for(var i = 0; i < codes.length; i++){
@ -555,7 +528,6 @@ function locodetail_getData() {
var loco_vfast = document.getElementById("locodet_vfast");
var loco_vmax = document.getElementById("locodet_vmax");
var loco_speed = document.getElementById("locodet_speed");
var loco_schedway = document.getElementById("locodet_schedway");
if (loco_name) res.name = loco_name.value;
if (loco_ifname) res.ifname = loco_ifname.value;
@ -567,7 +539,6 @@ function locodetail_getData() {
if (loco_vfast) res.vfast = loco_vfast.value;
if (loco_vmax) res.vmax = loco_vmax.value;
if (loco_speed) res.speed = loco_speed.speed;
if (loco_schedway) res.schedway = loco_schedway.value;
return res;
};
@ -582,10 +553,10 @@ function locodetail_getData() {
function locolist_show() {
var win = document.getElementById("locolist");
console.log ("locolist_show");
debug ("locolist_show");
if (!win) {
console.log ("locolist_show create window");
debug ("locolist_show create window");
win = gWindowCreate("locolist", "Locomotives", 400, 500, " \
<div id=\"locolist_listdiv\"> \
<ul id=\"locolist_elements\" style=\"list-style-type:none\"></ul> \
@ -624,7 +595,7 @@ function locolist_show() {
function locolist_clicked() {
var i;
console.log ("childnodes: " + this.childNodes[0].textContent);
debug ("childnodes: " + this.childNodes[0].textContent);
lococtrl_show(this.childNodes[0].textContent);
};
@ -649,10 +620,10 @@ function lococtrl_show(name) {
var win = document.getElementById("lococtrl_"+name);
var i;
console.log ("lococtrl_show:" + name);
debug ("lococtrl_show:" + name);
if (!win) {
console.log ("locolist_show create window");
debug ("locolist_show create window");
win = gWindowCreate("lococtrl_"+name, "Loco:"+name, 600, 600, " \
<table><tr><td> \
<fieldset><legend>Speed</legend><table><tr><td align=center>\
@ -677,16 +648,13 @@ function lococtrl_show(name) {
<td><button id=\"lococtrl_"+name+"_btnman\" type=\"button\" value=\"vstop\">MAN</button></td> \
</tr><tr> \
<td align=center><input id=\"lococtrl_"+name+"_cbstopman\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnstopman\" type=\"button\" value=\"vstop\">A&rArr;M</button></td> \
<td><button id=\"lococtrl_"+name+"_btnstopman\" type=\"button\" value=\"vstop\">A&lArr;M</button></td> \
</tr><tr> \
<td align=center><input id=\"lococtrl_"+name+"_cbauto\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnauto\" type=\"button\" value=\"vstop\">AUTO</button></td> \
</tr><tr> \
<td align=center><input id=\"lococtrl_"+name+"_cbautoshed\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnautoshed\" type=\"button\" value=\"vstop\">SHED</button></td> \
</tr><tr> \
<td align=center><input id=\"lococtrl_"+name+"_cbautorand\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnautorand\" type=\"button\" value=\"vstop\">RAND</button></td> \
<td align=center><input id=\"lococtrl_"+name+"_cbrand\" type=\"checkbox\" value=\"\" disabled></td>\
<td><button id=\"lococtrl_"+name+"_btnrand\" type=\"button\" value=\"vstop\">RAND</button></td> \
</tr> \
</table></fieldset> \
</td><tr></table>\
@ -707,8 +675,7 @@ function lococtrl_show(name) {
gAddEventListener("lococtrl_"+name+"_btnman", 'click', lococtrl_cb_btnman);
gAddEventListener("lococtrl_"+name+"_btnstopman", 'click', lococtrl_cb_btnstopman);
gAddEventListener("lococtrl_"+name+"_btnauto", 'click', lococtrl_cb_btnauto);
gAddEventListener("lococtrl_"+name+"_btnautorand", 'click', lococtrl_cb_btnautorand);
gAddEventListener("lococtrl_"+name+"_btnautoshed", 'click', lococtrl_cb_btnautoshed);
gAddEventListener("lococtrl_"+name+"_btnrand", 'click', lococtrl_cb_btnrand);
gAddEventListener("lococtrl_"+name+"_RANGE", 'click', lococtrl_speed);
gAddEventListener("lococtrl_"+name+"_REVBTN", 'click', lococtrl_reverse);
@ -721,13 +688,11 @@ function lococtrl_show(name) {
};
function lococtrl_cb_btnreset() {
var name = getTextBetween(this.id, "lococtrl_", "_btnreset");
var request = { command: "locomotivereset", locomotive: name };
serverinout (request, serverinout_defaultCallback);
request = { command: "locomotivesetman", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
@ -752,20 +717,13 @@ function lococtrl_cb_btnauto() {
};
function lococtrl_cb_btnautorand() {
var name = getTextBetween(this.id, "lococtrl_", "_btnautorand");
function lococtrl_cb_btnrand() {
var name = getTextBetween(this.id, "lococtrl_", "_btnauto");
var request = { command: "locomotivesetautorand", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
function lococtrl_cb_btnautoshed() {
var name = getTextBetween(this.id, "lococtrl_", "_btnautoshed");
var request = { command: "locomotivesetautoshed", locomotive: name };
serverinout (request, serverinout_defaultCallback);
};
function lococtrl_reverse() {
var name = getTextBetween(this.id, "lococtrl_", "_REVBTN");
var reverse;
@ -806,7 +764,7 @@ function lococtrl_cb_btnmove () {
if (reverse.innerHTML == "REV") speed = 0 - speed;
locomotive_server_Set ({name: name, speed: speed});
console.log ("Locomotive: '" + name +"' Speed: " + speed);
debug ("Locomotive: '" + name +"' Speed: " + speed);
};
@ -817,7 +775,7 @@ function lococtrl_speed() {
let speed = this.value;
if (reverse.innerHTML == "REV") speed = 0 - speed;
console.log ("Speed Loco:'"+name+"' Speed:'"+speed+"'");
debug ("Speed Loco:'"+name+"' Speed:'"+speed+"'");
for (var i = 0; i < locomotives.length; i++) {
if (name == locomotives[i].name) {
locomotive_server_Set ({name: name, speed: speed});
@ -830,48 +788,19 @@ function lococtrl_setData(data) {
var range = document.getElementById("lococtrl_"+data.name+"_RANGE");
var reverse = document.getElementById("lococtrl_"+data.name+"_REVBTN");
var cbauto = document.getElementById("lococtrl_"+data.name+"_cbauto");
var cbautorand = document.getElementById("lococtrl_"+data.name+"_cbautorand");
var cbautoshed = document.getElementById("lococtrl_"+data.name+"_cbautoshed");
var cbrand = document.getElementById("lococtrl_"+data.name+"_cbrand");
var cbmanstop = document.getElementById("lococtrl_"+data.name+"_cbstopman");
var btnman = document.getElementById("lococtrl_"+data.name+"_btnman");
var btnautostop = document.getElementById("lococtrl_"+data.name+"_btnstopman");
var btnauto = document.getElementById("lococtrl_"+data.name+"_btnauto");
var btnautorand = document.getElementById("lococtrl_"+data.name+"_btnautorand");
var btnautoshed = document.getElementById("lococtrl_"+data.name+"_btnautoshed");
if (range && reverse) {
console.log ("lococtrl: " + data.name + " speed:" + data.speed + " vmax:" +
debug ("lococtrl: " + data.name + " speed:" + data.speed + " vmax:" +
data.vmax + " flags:" + data.flags);
if (data.flags & LOCO_F_REVERSE) reverse.innerHTML = "REV";
else reverse.innerHTML = "FWD";
cbauto.checked = (data.flags & LOCO_F_AUTO);
cbautorand.checked = (data.flags & LOCO_F_AUTORANDOM);
cbautoshed.checked = (data.flags & LOCO_F_AUTOSHED);
cbrand.checked = (data.flags & LOCO_F_RANDOM);
cbmanstop.checked = (data.flags & LOCO_F_AUTOSTOP);
if (data.flags & LOCO_F_AUTOSTOP) {
btnman.disabled = false;
btnauto.disabled = true;
btnautorand.disabled = true;
btnautoshed.disabled = true;
btnautostop.disabled = true;
}
else if (data.flags & LOCO_F_AUTO) {
btnman.disabled = true;
btnautorand.disabled = false;
btnautoshed.disabled = false;
btnautostop.disabled = false;
}
else {
btnman.disabled = true;
btnautorand.disabled = true;
btnautostop.disabled = true;
btnautoshed.disabled = true;
btnauto.disabled = false;
}
range.min = 0;
if (data.vmax) range.max = data.vmax;
range.value = Math.abs(Number(data.speed));
@ -880,7 +809,7 @@ function lococtrl_setData(data) {
function lococtrl_close() {
console.log ("LocoCtrl_close:" + this.value);
debug ("LocoCtrl_close:" + this.value);
var win = document.getElementById("lococtrl_"+this.value);
if (win) document.body.removeChild(win);

@ -2,32 +2,20 @@
//
//
const RAILWAY_T_NOTHING = 0;
const RAILWAY_T_NORMAL = 1;
const RAILWAY_T_CROSSING = 2;
const RAILWAY_T_TURNOUT = 3;
const RAILWAY_T_SENSOR = 4;
const RAILWAY_T_CONNECTOR = 5;
const RAILWAY_T_BUTTON = 6;
const RAILWAY_T_TEXT = 7;
const RAILWAY_T_BLOCK = 8;
const TURNOUT_F_INVERSE = 1;
const TURNOUT_F_OUTPUTACTIVE = 2;
const TURNOUT_F_MOTORACTIVE = 2;
const TURNOUT_F_TURNOUT = 4;
const TURNOUT_F_ISRELAIS = 8;
function rwdetail_requestcallback(response) {
console.log ("rwdetail_requestcallback");
debug ("rwdetail_requestcallback");
};
function rwdetail_request(posx, posy) {
var request = {locoid: locoID, parameter1: -1, name:"Otto"};
console.log ("rwdetail_request");
debug ("rwdetail_request");
serverinout(request, rwdetail_requestcallback);
};
@ -35,10 +23,10 @@ function rwdetail_request(posx, posy) {
function rwdetail_show(posx, posy) {
var win = document.getElementById("rwdetail");
console.log ("rwdetail_show");
debug ("rwdetail_show");
if (!win) {
console.log ("rwdetail_show create window");
debug ("rwdetail_show create window");
win = gWindowCreate("rwdetail", "Railway", 400, 500, " \
<div style=\"float: left\"> \
Position: <input id=\"rwdet_X\" style=\"width: 50\" value=\"" + posx +"\"> , <input id=\"rwdet_Y\" style=\"width: 50\" value=\"" + posy +"\"> \
@ -101,15 +89,10 @@ function rwdetail_show(posx, posy) {
y.value = posy;
}
console.log ("rwdetail_show track dimensions: " + track.size.x + "," + track.size.y + " Position: " + posx + "," + posy + " idx:" + (posx + posy * track.size.x));
rwdetail_setData({type: 0, x: posx, y: posy, dir: 0, altdir: 0, name: ""});
if (track.elements[posx + posy * track.size.x]) {
console.log ("rwdetail_show element found.");
rwdetail_setData(track.elements[posx + posy * track.size.x]);
}
else console.log ("rwdetail_show element NOT found.");
};
@ -117,13 +100,13 @@ function rwdetail_cb_gotoref () {
var type = document.getElementById("rwdet_type");
var name = document.getElementById("rwdet_name");
console.log ("Name:" + name.value + " Type:" + type.value);
debug ("Name:" + name.value + " Type:" + type.value);
switch(Number(type.value)) {
case RAILWAY_T_BUTTON: turndetail_show(name.value, true); break; // button
case RAILWAY_T_TURNOUT: turndetail_show(name.value, true); break; // turnout
case RAILWAY_T_SENSOR: sensordetail_show(name.value, true); break; // sensor
case RAILWAY_T_BLOCK: blockdetail_show(name.value, true); break; // block
case 3: turndetail_show(name.value, true); break; // turnout
case 4: sensordetail_show(name.value, true); break; // sensor
case 5: break; // connector
case 8: blockdetail_show(name.value, true); break; // block
default: break;
}
};
@ -235,23 +218,10 @@ function rw_Click(x,y) {
var idx = x + y * track.size.x;
if (track.elements[idx]) {
//
// Turnout?
if (track.elements[idx].type == RAILWAY_TURNOUT) {
// Button or Turnout?
if (track.elements[idx].type == RAILWAY_TURNOUT || track.elements[idx].type == RAILWAY_BUTTON) {
if (track.elements[idx].name != "") {
if (turnout_IsTurnoutActive(track.elements[idx].name)) {
turnout_server_Activate(track.elements[idx].name, 0);
}
else {
turnout_server_Activate(track.elements[idx].name, 1);
}
}
}
//
// Button
else if (track.elements[idx].type == RAILWAY_T_BUTTON) {
if (track.elements[idx].name != "") {
if (turnout_IsOutputActive(track.elements[idx].name)) {
if (turnout_IsActive(track.elements[idx].name)) {
turnout_server_Activate(track.elements[idx].name, 0);
}
else {
@ -264,7 +234,6 @@ function rw_Click(x,y) {
// Sensor
else if (track.elements[idx].type == RAILWAY_SENSOR) {
if (track.elements[idx].name != "") {
sensor_contextmenu(track.elements[idx].name);
}
}
@ -314,7 +283,7 @@ var turnouts = [];
function turnout_Update(data) {
for (var i = 0; i < turnouts.length; i++) {
if (data.name == turnouts[i].name) {
console.log ("Update turnout:" + turnouts[i].name + " with turnout:" + data.name + " Flags:" + data.flags);
debug ("Update turnout:" + turnouts[i].name + " with turnout:" + data.name);
turnouts[i].name = data.name;
turnouts[i].ifname = data.ifname;
turnouts[i].addr = data.addr;
@ -324,7 +293,7 @@ function turnout_Update(data) {
}
// not found add element
console.log ("Add turnout:" + data.name + " Flags:" + data.flags);
debug ("Add turnout:" + data.name);
turnouts.push ({
name: data.name,
ifname: data.ifname,
@ -337,7 +306,7 @@ function turnout_Update(data) {
//
// return if the turnout is active or not
//
function turnout_IsTurnoutActive(name) {
function turnout_IsActive(name) {
for (var i = 0; i < turnouts.length; i++) {
if (name == turnouts[i].name) {
if (turnouts[i].flags & TURNOUT_F_TURNOUT) return 1
@ -348,17 +317,6 @@ function turnout_IsTurnoutActive(name) {
};
function turnout_IsOutputActive(name) {
for (var i = 0; i < turnouts.length; i++) {
if (name == turnouts[i].name) {
if (turnouts[i].flags & TURNOUT_F_OUTPUTACTIVE) return 1
else return 0;
}
}
return 0;
}
//
// delete element from the list
// in arrays we can not delete just an element, so we create a new one
@ -409,10 +367,10 @@ function turnout_server_Activate(name, onoff) {
function turndetail_show(turnname, create) {
var win = document.getElementById("turndetail");
console.log ("turndetail_show");
debug ("turndetail_show");
if (!win) {
console.log ("turndetail_show create window");
debug ("turndetail_show create window");
win = gWindowCreate("turndetail", "Turnout", 400, 500, " \
<div style=\"float: left\"> \
Name: <input id=\"turndet_name\" style=\"width: 100\"> \
@ -426,8 +384,6 @@ function turndetail_show(turnname, create) {
<tr><td>Flags:</td><td><input id=\"turndet_flags\" style=\"width: 50\"></td></tr> \
</table> </td><td> \
<label><input id=\"turndet_inverse\" type=\"checkbox\" value=\"\"> Inverse</label><br>\
<label><input id=\"turndet_output\" type=\"checkbox\" value=\"\"> Output Active</label><br>\
<label><input id=\"turndet_relais\" type=\"checkbox\" value=\"\"> Is Relais</label><br>\
<label><input id=\"turndet_active\" type=\"checkbox\" value=\"\"><dfn title=\"save first\"> Active</dfn></label>\
\
</td></tr></table></div> <hr>\
@ -441,8 +397,6 @@ function turndetail_show(turnname, create) {
gAddEventListener("turndet_inverse", 'click', turndetail_cb_inverse);
gAddEventListener("turndet_active", 'click', turndetail_cb_active);
gAddEventListener("turndet_output", 'click', turndetail_cb_output);
gAddEventListener("turndet_relais", 'click', turndetail_cb_relais);
gAddEventListener("turndet_CLOSE", 'click', turndetail_cb_close);
gAddEventListener("turndet_DELETE", 'click', turndetail_cb_delete);
@ -502,34 +456,6 @@ function turndetail_cb_active () {
};
//
// output
function turndetail_cb_output () {
var cb = document.getElementById("turndet_output");
var flags = document.getElementById("turndet_flags");
var name = document.getElementById("turndet_name");
if (cb.checked)
flags.value = Number(flags.value) | TURNOUT_F_OUTPUTACTIVE;
else
flags.value = Number(flags.value) & (0xFFFF-TURNOUT_F_OUTPUTACTIVE);
};
//
// isrelais
function turndetail_cb_relais () {
var cb = document.getElementById("turndet_relais");
var flags = document.getElementById("turndet_flags");
var name = document.getElementById("turndet_name");
if (cb.checked)
flags.value = Number(flags.value) | TURNOUT_F_ISRELAIS;
else
flags.value = Number(flags.value) & (0xFFFF-TURNOUT_F_ISRELAIS);
};
function turndetail_cb_close () {
var win = document.getElementById("turndetail");
@ -580,7 +506,7 @@ function turndetail_cb_next () {
if (i == cursel) turndetail_setData(turnouts[i]);
}
// console.log ("Cursel: " + cursel + " turnouts.lenght:" + turnouts.length);
// debug ("Cursel: " + cursel + " turnouts.lenght:" + turnouts.length);
};
@ -603,7 +529,7 @@ function turndetail_cb_prev () {
if (i == cursel) turndetail_setData(turnouts[i]);
}
// console.log ("Cursel: " + cursel + " turnouts.lenght:" + turnouts.length);
// debug ("Cursel: " + cursel + " turnouts.lenght:" + turnouts.length);
};
@ -617,8 +543,6 @@ function turndetail_setData(elm) {
var turnflags = document.getElementById("turndet_flags");
var cbinverse = document.getElementById("turndet_inverse");
var cbactive = document.getElementById("turndet_active");
var cbrelais = document.getElementById("turndet_relais");
var cboutput = document.getElementById("turndet_output");
if (elm) {
if (turnname) turnname.value = elm.name;
@ -626,21 +550,13 @@ function turndetail_setData(elm) {
if (turnaddr) turnaddr.value = elm.addr;
if (turnflags) turnflags.value = elm.flags;
if (cbinverse) {
if (Number(elm.flags) & TURNOUT_F_INVERSE) cbinverse.checked = true;
if (Number(elm.flags) & 1) cbinverse.checked = true;
else cbinverse.checked = false;
}
if (cbactive) {
if (Number(elm.flags) & TURNOUT_F_TURNOUT) cbactive.checked = true;
if (Number(elm.flags) & 2) cbactive.checked = true;
else cbactive.checked = false;
}
if (cboutput) {
if (Number(elm.flags) & TURNOUT_F_OUTPUTACTIVE) cboutput.checked = true;
else cboutput.checked = false;
}
if (cbrelais) {
if (Number(elm.flags) & TURNOUT_F_ISRELAIS) cbrelais.checked = true;
else cbrelais.checked = false;
}
}
};

@ -14,7 +14,7 @@ var sensors = [];
function sensor_Update(sdata) {
for (var i = 0; i < sensors.length; i++) {
if (sdata.name == sensors[i].name) {
console.log ("Update Sensor:" + sensors[i].name + " with Sensor:" + sdata.name);
debug ("Update Sensor:" + sensors[i].name + " with Sensor:" + sdata.name);
sensors[i].name = sdata.name;
sensors[i].ifname = sdata.ifname;
sensors[i].addr = sdata.addr;
@ -24,7 +24,7 @@ function sensor_Update(sdata) {
}
// not found add element
console.log ("Add Sensor:" + sdata.name);
debug ("Add Sensor:" + sdata.name);
sensors.push ({
name: sdata.name,
ifname: sdata.ifname,
@ -88,13 +88,14 @@ function sensor_IsActive(name) {
function sensordetail_show(name, create) {
var win = document.getElementById("sensordetail");
console.log ("sensordetail_show");
debug ("sensordetail_show");
if (!win) {
console.log ("sensordetail_show create window");
debug ("sensordetail_show create window");
win = gWindowCreate("sensordetail", "Sensor", 400, 300, " \
<div style=\"float: left\"> \
Sensor Name: <input id=\"sensor_name\" style=\"width: 100\"> \
@ -187,7 +188,7 @@ function sensordetail_cb_next () {
if (i == cursel) sensordetail_setData(sensors[i]);
}
console.log ("Cursel: " + cursel + " sensors.lenght:" + sensors.length);
debug ("Cursel: " + cursel + " sensors.lenght:" + sensors.length);
};
@ -210,7 +211,7 @@ function sensordetail_cb_prev () {
if (i == cursel) sensordetail_setData(sensors[i]);
}
console.log ("Cursel: " + cursel + " sensors.lenght:" + sensors.length);
debug ("Cursel: " + cursel + " sensors.lenght:" + sensors.length);
};
@ -261,10 +262,10 @@ function sensordetail_getData() {
function sensorlist_show() {
var win = document.getElementById("sensorlist");
console.log ("sensorlist_show");
debug ("sensorlist_show");
if (!win) {
console.log ("sensorlist_show create window");
debug ("sensorlist_show create window");
win = gWindowCreate("sensorlist", "Sensors", 400, 500, " \
<div id=\"sensorlist_listdiv\"> \
<ul id=\"sensorlist_elements\" style=\"list-style-type:none\"></ul> \
@ -305,7 +306,7 @@ function sensorlist_show() {
function sensorlist_clicked() {
var i;
console.log ("childnodes: " + this.childNodes[0].textContent);
debug ("childnodes: " + this.childNodes[0].textContent);
sensordetail_show(this.childNodes[0].textContent);
};
@ -319,54 +320,3 @@ function sensorlist_cb_close () {
// ***********************************************************************************************
// ***********************************************************************************************
// sensor contextmenu: show a context menu for the sensor
// this is only if the INTERFACE name is set tu DEBUG
// ***********************************************************************************************
// ***********************************************************************************************
function sensor_contextmenu(name) {
let innerhtml = "";
for (var i = 0; i < sensors.length; i++) {
if (name == sensors[i].name) {
if (sensors[i].ifname == "DEBUG") {
innerhtml = "<center>";
innerhtml += "<button id=\"contextbox_On\" type=\"button\">Set On</button><br>";
innerhtml += "<button id=\"contextbox_Off\" type=\"button\">Set Off</button><br>";
innerhtml += "<button id=\"contextbox_Close\" type=\"button\">Close</button></center>";
gContextmenuCreate(name, innerhtml);
gAddEventListener("contextbox_On", 'click', sensor_ctxmenu_On);
gAddEventListener("contextbox_Off", 'click', sensor_ctxmenu_Off);
gAddEventListener("contextbox_Close", 'click', gContextmenuClose);
}
}
}
};
function sensor_ctxmenu_On (element, value) {
let name = document.getElementById("ConextMenuHead").innerHTML;
sensor_server_setactive(name, "1");
gContextmenuClose();
}
function sensor_ctxmenu_Off (element, value) {
let name = document.getElementById("ConextMenuHead").innerHTML;
sensor_server_setactive(name, "0");
gContextmenuClose();
}
//
// send sensor activate and deactivate to server
//
function sensor_server_setactive(name, value) {
var request = { command: "sensorSetActive", sensor: name, enabled: value };
console.log ("send sensor active:" + name);
serverinout (request, serverinout_defaultCallback);
};

@ -24,14 +24,18 @@ function serverinout(request, callback) {
request.sid = sessionID;
request.rid = randomID;
// e.preventDefault();
senddata = JSON.stringify(request);
// debug('serverinout: send request:' + senddata);
$.ajax({
type: "POST",
// url: '/modelbahn/serverinout.php',
url: '/cgi-bin/modelbahn-cgi',
data: senddata,
success: function(response)
{
var jsonData = {};
// ENABLE LATER try {
jsonData = JSON.parse(response);
if (jsonData.success == "1")
{
@ -44,6 +48,10 @@ function serverinout(request, callback) {
var clientstatus = document.getElementById("infoclient");
clientstatus.innerHTML = "-trying-";
}
// ENABLE LATER } catch(err) {
// ENABLE LATER var serverstatus = document.getElementById("infoserver");
// ENABLE LATER serverstatus.innerHTML = "-error-";
// ENABLE LATER }
},
error: function(error) {
var status = document.getElementById("infoclient");
@ -84,6 +92,7 @@ function serverinout_Save(data) {
function serverinout_defaultCallback(data) {
// if (data.changes) if (data.changes.length > 0) debug ("From Server :" + JSON.stringify(data));
if (data.sid && data.rid) {
//
// valid data from server
@ -105,7 +114,7 @@ function serverinout_defaultCallback(data) {
//
// Infoline changes
if (data.changes[i].infoline) {
console.log ("Info:" + data.changes[i].infoline);
debug ("Info:" + data.changes[i].infoline);
}
//
@ -181,7 +190,7 @@ function serverinout_defaultCallback(data) {
}
}
if (data.changes[i].block) {
console.log ("update Block:"+ data.changes[i].block.name + " Flags:" + data.changes[i].block.flags);
debug ("update Block:"+ data.changes[i].block.name + " Flags:" + data.changes[i].block.flags);
block_Update(data.changes[i].block);
}
if (data.changes[i].blockdelete) {
@ -197,16 +206,17 @@ function serverinout_defaultCallback(data) {
else if (data.rid == randomID && data.sid > 0) {
// we got a new sessionID --> request track data
if (sessionID == 0) {
debug ("setup session ID");
sessionID = data.sid;
serverinout( {command: "getall" }, serverinout_defaultCallback);
}
}
else {
console.log ("ERROR: serverinout_defaultCallback");
debug ("ERROR: serverinout_defaultCallback");
}
}
else {
console.log ("ERROR: serverinout_defaultCallback no data.sid && data.rid");
debug ("ERROR: serverinout_defaultCallback no data.sid && data.rid");
}
};
@ -220,7 +230,7 @@ function serverinout_AutoUpdateCallback(data) {
function serverinout_AutoUpdate() {
// console.log ("serverinout_AutoUpdate");
// debug ("serverinout_AutoUpdate");
if (request_running == 0) {
request_running = 0;
serverinout({}, serverinout_defaultCallback);

@ -1,8 +1,4 @@
<?php
/*
* This code is not used anymore. PHP is just too slow. We went back to the cgi-bin interface
*/
session_start();

@ -11,7 +11,7 @@ function side_Display(type) {
var side_normal = document.getElementById("side_normalbuttons");
var btn = document.getElementById("cmd-none");
console.log ("side_display(" + type +")");
debug ("side_display(" + type +")");
if (type == SIDE_DISPLAY_EDITTRACK) {
side_normal.style.display = "none";

@ -3,7 +3,7 @@
//
function testwinbtnclick() {
console.log ("Test Button");
debug ("Test Button");
locodetail_show("");
}

@ -19,13 +19,9 @@ var track = {
elements: []
};
// trackMouse.step = 0 normal
// trackMouse.step = 1 destination
var trackMouse = {
pos: {x: -1, y: -1, subx: 0.5, suby: 0.5},
down: {x :-1 , y: -1, subx: 0.5, suby: 0.5},
rect: {x1: -1, x2: -1, y1: -1, y2: -1},
step: 0
down: {x :-1 , y: -1, subx: 0.5, suby: 0.5}
};
@ -123,8 +119,8 @@ function trackDrawElement(ctx, element, mode) {
var dir = element.dir;
var altdir = element.altdir;
if (element.name != "") if (turnout_IsTurnoutActive(element.name)) {
// console.log ("draw element:" + element.name + " isActive:" + turnout_IsActive(element.name));
if (element.name != "") if (turnout_IsActive(element.name)) {
// debug ("draw element:" + element.name + " isActive:" + turnout_IsActive(element.name));
altdir = element.dir;
dir = element.altdir;
}
@ -141,26 +137,6 @@ function trackDrawElement(ctx, element, mode) {
trackDrawTrack (ctx, {x: element.x, y: element.y}, altdir);
}
else if (element.type == RAILWAY_BUTTON) {
let bi;
ctx.beginPath();
ctx.lineWidth = 2;
ctx.setLineDash([0,0]);
ctx.strokeStyle = cssVar('--button-inactive');
for (bi = 0; bi < turnouts.length; bi++) {
if (turnouts[bi].name == element.name) {
if ((turnouts[bi].flags & TURNOUT_F_OUTPUTACTIVE) != 0)
ctx.strokeStyle = cssVar('--button-active');
}
}
ctx.moveTo((element.x+0.1) * track.scale, (element.y+0.1) * track.scale);
ctx.lineTo((element.x+0.9) * track.scale, (element.y+0.1) * track.scale);
ctx.lineTo((element.x+0.9) * track.scale, (element.y+0.9) * track.scale);
ctx.lineTo((element.x+0.1) * track.scale, (element.y+0.9) * track.scale);
ctx.lineTo((element.x+0.1) * track.scale, (element.y+0.1) * track.scale);
ctx.stroke();
}
else if (element.type == RAILWAY_NORMAL || element.type == RAILWAY_SENSOR || element.type == RAILWAY_BLOCK) {
//
// normal
@ -293,7 +269,7 @@ function trackDrawBlock(ctx, blockelm) {
y1 = y1 + (blockelm.y) * track.scale;
y2 = y2 + (blockelm.y) * track.scale;
// console.log ("Flags:" + Number(blockelm.flags) + " Res:" + (Number(blockelm.flags) & BLOCK_F_OFF));
// debug ("Flags:" + Number(blockelm.flags) + " Res:" + (Number(blockelm.flags) & BLOCK_F_OFF));
if (block && Number(block.flags) & BLOCK_F_OFF) ctx.fillStyle = cssVar('--block-bg-closed');
else if (blockelm.lockedby && blockelm.lockedby != "") ctx.fillStyle = cssVar('--block-bg-locked');
else ctx.fillStyle = cssVar('--block-bg');
@ -383,7 +359,7 @@ function trackDraw() {
var elm = {};
var tmpblocks = new Array();
// console.log ("trackDraw pos: " + trackMouse.pos.x + "," + trackMouse.pos.y +
// debug ("trackDraw pos: " + trackMouse.pos.x + "," + trackMouse.pos.y +
// " down: " + trackMouse.down.x + "," + trackMouse.down.y);
@ -408,6 +384,44 @@ function trackDraw() {
}
tmpblocks.length = 0;
//
// draw down position
if (trackMouse.down.x >= 0) {
var p1 = {};
var p2 = {};
if (trackMouse.pos.x < trackMouse.down.x) {
p1.x = trackMouse.pos.x;
p2.x = trackMouse.down.x;
}
else {
p1.x = trackMouse.down.x;
p2.x = trackMouse.pos.x;
}
if (trackMouse.pos.y < trackMouse.down.y) {
p1.y = trackMouse.pos.y;
p2.y = trackMouse.down.y;
}
else {
p1.y = trackMouse.down.y;
p2.y = trackMouse.pos.y;
}
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([2,2]);
ctx.strokeStyle = cssVar('--track-color-selectframe');
ctx.beginPath();
ctx.moveTo(0.5+(p1.x + 0) * track.scale, 0.5+(p1.y+0) * track.scale);
ctx.lineTo(0.5+(p2.x + 1) * track.scale, 0.5+(p1.y+0) * track.scale);
ctx.lineTo(0.5+(p2.x + 1) * track.scale, 0.5+(p2.y+1) * track.scale);
ctx.lineTo(0.5+(p1.x + 0) * track.scale, 0.5+(p2.y+1) * track.scale);
ctx.lineTo(0.5+(p1.x + 0) * track.scale, 0.5+(p1.y+0) * track.scale);
ctx.stroke();
}
//
// draw mouse cursor
ctx.lineWidth = 1;
@ -427,8 +441,8 @@ function trackDraw() {
// draw mouseselection
var mode = sideBtnCmdGet();
if (mode == "cmd-track-rail" || mode == "cmd-track-delete") {
if (trackMouse.down.x >= 0 && trackMouse.down.y >= 0) {
if ((mode == "cmd-track-rail" || mode == "cmd-track-delete") &&
trackMouse.down.x >= 0 && trackMouse.down.y >= 0) {
var selected = new Array();
selected.length = 0;
@ -440,83 +454,14 @@ function trackDraw() {
var infoline = document.getElementById("infoline");
if (infoline) infoline.innerHTML = trackMouse.direction;
}
}
else if (mode == "cmd-track-move") {
if (trackMouse.step == 0) {
// draw rectangle for selection
let x1, x2, y1, y2;
// sort position down < pos
if (trackMouse.pos.x > trackMouse.down.x) {
x1 = trackMouse.down.x;
x2 = trackMouse.pos.x;
}
else {
x2 = trackMouse.down.x;
x1 = trackMouse.pos.x;
}
if (trackMouse.pos.y > trackMouse.down.y) {
y1 = trackMouse.down.y;
y2 = trackMouse.pos.y;
}
else {
y2 = trackMouse.down.y;
y1 = trackMouse.pos.y;
}
if (trackMouse.down.x >= 0) {
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([2,2]);
ctx.strokeStyle = cssVar('--track-element-fgborder');
ctx.beginPath();
ctx.moveTo(0.5+(x1 + 0) * track.scale, 0.5+(y1+0) * track.scale);
ctx.lineTo(0.5+(x2 + 1) * track.scale, 0.5+(y1+0) * track.scale);
ctx.lineTo(0.5+(x2 + 1) * track.scale, 0.5+(y2+1) * track.scale);
ctx.lineTo(0.5+(x1 + 0) * track.scale, 0.5+(y2+1) * track.scale);
ctx.lineTo(0.5+(x1 + 0) * track.scale, 0.5+(y1+0) * track.scale);
ctx.stroke();
}
}
else if (trackMouse.step == 1) {
let dx = trackMouse.pos.x - trackMouse.down.x;
let dy = trackMouse.pos.y - trackMouse.down.y;
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([2,2]);
ctx.strokeStyle = cssVar('--track-element-selectframe');
ctx.beginPath();
ctx.moveTo(0.5+(trackMouse.rect.x1 + 0) * track.scale, 0.5+(trackMouse.rect.y1+0) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x2 + 1) * track.scale, 0.5+(trackMouse.rect.y1+0) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x2 + 1) * track.scale, 0.5+(trackMouse.rect.y2+1) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x1 + 0) * track.scale, 0.5+(trackMouse.rect.y2+1) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x1 + 0) * track.scale, 0.5+(trackMouse.rect.y1+0) * track.scale);
ctx.stroke();
ctx.lineWidth = 1;
ctx.lineJoin="round";
ctx.miterLimit = 1;
ctx.setLineDash([1,1]);
ctx.strokeStyle = cssVar('--track-element-selectframe');
ctx.beginPath();
ctx.moveTo(0.5+(trackMouse.rect.x1 + dx + 0) * track.scale, 0.5+(trackMouse.rect.y1 + dy + 0) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x2 + dx + 1) * track.scale, 0.5+(trackMouse.rect.y1 + dy + 0) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x2 + dx + 1) * track.scale, 0.5+(trackMouse.rect.y2 + dy + 1) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x1 + dx + 0) * track.scale, 0.5+(trackMouse.rect.y2 + dy + 1) * track.scale);
ctx.lineTo(0.5+(trackMouse.rect.x1 + dx + 0) * track.scale, 0.5+(trackMouse.rect.y1 + dy + 0) * track.scale);
ctx.stroke();
}
}
else if (mode == "cmd-track-rail" || mode == "cmd-track-detail" || mode == "cmd-track-none" || mode == "cmd-none") {
//
// draw possible turnout
else if (mode == "cmd-track-turn") {
var t = trackGetTurnout({x: trackMouse.pos.x, y: trackMouse.pos.y});
}
else alert("track.js: unknown mode:" + mode);
else if (!mode == "cmd-track-none") alert("track.js: unknown mode:" + mode);
//
// flip screen - double buffering
@ -559,7 +504,7 @@ function trackMousemove(event) {
var mode = sideBtnCmdGet();
trackMouse.pos = trackMouseGetPos(event);
// console.log ("trackMousemove pos: " + trackMouse.pos.x + "," + trackMouse.pos.y +
// debug ("trackMousemove pos: " + trackMouse.pos.x + "," + trackMouse.pos.y +
// " subx: " + trackMouse.pos.subx + " suby:" + trackMouse.pos.suby);
trackDraw();
@ -573,11 +518,8 @@ function trackMousedown(event) {
if (mode == "cmd-track-rail" || mode == "cmd-track-delete") {
trackMouse.down = trackMouseGetPos(event);
}
else if (mode == "cmd-track-move") {
if (trackMouse.step == 0) trackMouse.down = trackMouseGetPos(event);
}
// console.log ("trackMousedown pos: " + tmp.x + "," + tmp.y + " subx: " + tmp.subx + " suby:" + tmp.suby);
// debug ("trackMousedown pos: " + tmp.x + "," + tmp.y + " subx: " + tmp.subx + " suby:" + tmp.suby);
trackDraw();
};
@ -590,10 +532,9 @@ function trackMouseup(event) {
var mode = sideBtnCmdGet();
var tmp = trackMouseGetPos(event);
console.log ("trackMouseup tmp: " + tmp.x + "," + tmp.y + " mode:" + mode);
console.log ("trackMouseup down: " + trackMouse.down.x + "," + trackMouse.down.y);
console.log ("trackMouseup pos: " + trackMouse.pos.x + "," + trackMouse.pos.y);
console.log ("trackMouseup step: " + trackMouse.step);
debug ("trackMouseup tmp: " + tmp.x + "," + tmp.y + " mode:" + mode);
debug ("trackMouseup down: " + trackMouse.down.x + "," + trackMouse.down.y);
debug ("trackMouseup pos: " + trackMouse.pos.x + "," + trackMouse.pos.y);
gContextmenuClose();
@ -605,14 +546,10 @@ function trackMouseup(event) {
selected = trackGetElementList(trackMouse.down, trackMouse.pos, trackMouse.direction);
serverinout_addTrack(selected);
selected.length = 0;
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
else if (mode == "cmd-track-detail") {
rwdetail_show(trackMouse.pos.x, trackMouse.pos.y);
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
else if (mode == "cmd-track-delete") {
@ -642,62 +579,23 @@ function trackMouseup(event) {
ye = trackMouse.down.y;
}
debug ("delete: xs: " + xs + " , " + ys + " xe: " + xe + " , " + ye);
for (x = xs; x <= xe; x++) for (y = ys; y <= ye; y++) {
selected.push({x: x, y: y, dir: 1, type: 0});
}
serverinout_delTrack(selected);
selected.length = 0;
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
else if (mode == "cmd-track-move") {
if (trackMouse.step == 0) {
let x1, x2, y1, y2;
// sort position down < pos
if (trackMouse.pos.x > trackMouse.down.x) {
trackMouse.rect.x1 = trackMouse.down.x;
trackMouse.rect.x2 = trackMouse.pos.x;
}
else {
trackMouse.rect.x2 = trackMouse.down.x;
trackMouse.rect.x1 = trackMouse.pos.x;
}
if (trackMouse.pos.y > trackMouse.down.y) {
trackMouse.rect.y1 = trackMouse.down.y;
trackMouse.rect.y2 = trackMouse.pos.y;
}
else {
trackMouse.rect.y2 = trackMouse.down.y;
trackMouse.rect.y1 = trackMouse.pos.y;
}
trackMouse.step = 1;
trackMouse.down = trackMouse.pos;
debug ("rw_Click was das?");
rw_Click(trackMouse.pos.x, trackMouse.pos.y);
}
else if (trackMouse.step == 1) {
//
// move railways
let dx = trackMouse.pos.x - trackMouse.down.x;
let dy = trackMouse.pos.y - trackMouse.down.y;
trackMoveArea(trackMouse.rect, dx, dy);
trackMouse.step = 0;
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
else {
trackMouse.step = 0;
}
}
else {
console.log ("rw_Click was das?");
rw_Click(trackMouse.pos.x, trackMouse.pos.y);
trackMouse.down.x = -1;
trackMouse.down.y = -1;
}
trackDraw();
};
@ -707,10 +605,10 @@ function trackMouseup(event) {
// add/or delete element
// fill in element
function trackAddElement(elm) {
// console.log ("trackAddElement: pos:" + elm.x + "," + elm.y + " d: " + elm.dir + " name:" + elm.name + " type:" + elm.type);
// debug ("trackAddElement: pos:" + elm.x + "," + elm.y + " d: " + elm.dir + " name:" + elm.name + " type:" + elm.type);
if (track.size.x > 0 && track.size.y > 0) {
track.elements[elm.x + track.size.x * elm.y] = elm;
track.elements[elm.x + track.size.y * elm.y] = elm;
}
};
@ -720,7 +618,7 @@ function trackAddElement(elm) {
// init the track view screen
// bind callback functions
function trackCreate(sizex, sizey) {
console.log ("trackCreate " + sizex + " , " + sizey);
debug ("trackCreate " + sizex + " , " + sizey);
var canvas = document.createElement("canvas");
track.size.x = sizex;
@ -746,7 +644,7 @@ function trackCreate(sizex, sizey) {
//
// get the size fo track from server, setup all data
function trackSetup(tracksetup) {
console.log ("trackSetup");
debug ("trackSetup");
var client = document.getElementById("page_main");
var oldc = document.getElementById("TrackCanvas");
@ -838,7 +736,7 @@ function trackGetElementList(start, end) {
}
else {
// should not possible but somehow we ended up here
console.log ("trackGetElementList: ERROR elm 3 or 5 expected");
debug ("trackGetElementList: ERROR elm 3 or 5 expected");
break;
}
}
@ -861,7 +759,7 @@ function trackGetElementList(start, end) {
}
else {
// should not possible but somehow we ended up here
console.log ("trackGetElementList: ERROR elm 4 or 6 expected");
debug ("trackGetElementList: ERROR elm 4 or 6 expected");
break;
}
}
@ -897,7 +795,6 @@ function trackGetElementList(start, end) {
return list;
};
//
// returns the element at the givin point
function trackGetTurnout(mousepos) {
@ -913,40 +810,3 @@ function trackGetTurnout(mousepos) {
return elm;
};
//
// trackMoveArea: moves an area from one to another place, it will overwrite the objects on this place.
//
function trackMoveArea (rect, dx, dy) {
let elmMove = new Array();
let elmDel = new Array();
let elm;
let x, y, idx;
if (dx == 0 && dy == 0) return;
for (x = rect.x1; x <= rect.x2; x++) for (y = rect.y1; y <= rect.y2; y++) {
idx = x + y * track.size.x;
elm = track.elements[idx];
if (!elm) {
elm = { x: x + dx,
y: y + dy,
type: RAILWAY_T_NOTHING,
dir: 0,
altdir: 0,
name: "" };
}
else {
elm.x = elm.x + dx;
elm.y = elm.y + dy;
}
elmMove.push (track.elements[idx]);
elm = {x: x, y: y};
elmDel.push (elm);
}
serverinout_delTrack(elmDel);
serverinout_addTrack(elmMove);
};

@ -1,123 +0,0 @@
# .SILENT:
DEPENDFILE=.depend
VERSION=0.1
#
# default configuration
# after chaning run make config
# default ports: 21105, 21106 and 3472?
PREFIX=/usr/local
DATAPREFIX=/var/lib
RUNPID=/var/run/z21Emulation.pid
ETCPREFIX=/etc
# DEFAULT_Z21PORT=21105
DEFAULT_Z21PORT=21104
#
#
#
ifndef CXX
CXX=g++
endif
#CXX=/data/CreateImages/RaspberryPi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-g++
CXXFLAGS= -ggdb -fPIC -Wall -pg
LDFLAGS= -lm -lc -pg
#
#
#
all: dep z21emu
# install: $(OBJSLAVES) collect-master collectd
# cp -rf collectd $(PREFIX)/bin
# cp -rf collect-master $(PREFIX)/bin
# $(foreach i,$(OBJSLAVES), cp -rf $(i) $(PREFIX)/bin;)
#
# mkdir -p $(ETCPREFIX)/collect
# $(foreach i,$(shell ls *.conf.sample), cp -rvf $(i) $(ETCPREFIX)/collect/;)
# $(foreach i,$(shell ls *.map), cp -rvf $(i) $(ETCPREFIX)/collect/;)
# $(foreach i,$(shell ls *.conf), echo $(i);)
# mkdir -p $(DATAPREFIX)/collect
#
#
# installinitd: install
# cp -rf collectd.sh /etc/init.d
# ln -fs ../init.d/collectd.sh /etc/rc2.d/S20collectd.sh
# ln -fs ../init.d/collectd.sh /etc/rc0.d/K10collectd.sh
# ln -fs ../init.d/collectd.sh /etc/rc1.d/K10collectd.sh
# ln -fs ../init.d/collectd.sh /etc/rc6.d/K10collectd.sh
#
# uninstall:
# rm -rf $(PREFIX)/bin/collectd
# rm -rf $(PREFIX)/bin/collect-master
# rm -rf /etc/init.d/collectd.sh
# rm -rf /etc/rc2.d/S10collectd.sh
# rm -rf /etc/rc0.d/K10collectd.sh
# rm -rf /etc/rc1.d/K10collectd.sh
# rm -rf /etc/rc6.d/K10collectd.sh
#
# $(foreach i,$(OBJSLAVES), rm -rf $(PREFIX)/bin/$(i);)
# # rm -rf $(ETCPREFIX)/collect
#
z21emu: z21emu.o udp.o debug.o z21prot.o i2csensor.o
$(CXX) $^ -o $@ $(LDFLAGS)
config:
echo "#ifndef _CONFIG_H_" > config.h
echo "#define _CONFIG_H_" >> config.h
echo "" >> config.h
echo "#define VERSION \"$(VERSION)\"" >> config.h
echo "" >> config.h
echo "#define PREFIX \"$(PREFIX)\"" >> config.h
echo "#define RUNPID \"$(RUNPID)\"" >> config.h
echo "#define DATAPREFIX \"$(DATAPREFIX)\"" >> config.h
echo "#define ETCPREFIX \"$(ETCPREFIX)\"" >> config.h
echo "" >> config.h
echo "#define DEFAULT_Z21PORT $(DEFAULT_Z21PORT)" >> config.h
echo "" >> config.h
# ifeq ($(HAVE_SIMPLEHD),1)
# echo "#define HAVE_SIMPLEHD 1" >> config.h
# else
# echo "// #define HAVE_SIMPLEHD 1" >> config.h
# endif
echo "" >> config.h
echo "#endif" >> config.h
rebuild: clean all
dep:
$(CXX) -MM `ls *.cc` $(CXXFLAGS) > $(DEPENDFILE)
dist:
mkdir z21emu-$(VERSION)
cp -rf *.conf.sample z21emu-$(VERSION)/
cp -rf *.cc z21emu-$(VERSION)/
cp -rf *.h z21emu-$(VERSION)/
cp -rf *.sh z21emu-$(VERSION)/
cp -rf Makefile z21emu-$(VERSION)/
cp -rf INSTALL z21emu-$(VERSION)/
tar cvzf z21emu-$(VERSION).tgz z21emu-$(VERSION)
rm -rf z21emu-$(VERSION)
clean:
rm *.s -rf
rm *.o -rf
rm *.oo -rf
rm *~ -rf
rm -rf .depend
rm -rf *.so
rm -rf *.so.*
rm -rf z21emu
rm -rf gmon.out
rm -rf config.h
rm -rf Makefile.rules
cleanall: clean
source: cleanall
-include $(DEPENDFILE)

@ -1,41 +0,0 @@
# .SILENT:
# Atmega88
# CFLAGS= -Os -g -Wall -mmcu=atmega16 -DF_CPU=8000000UL
# LDFLAGS= -mmcu=atmega16
CPUTYPE1= atmega16
CPUTYPE2= m16
# Atmega32
CFLAGS= -Os -g -Wall -mmcu=$(CPUTYPE1) -DF_CPU=16000000UL
LDFLAGS= -mmcu=$(CPUTYPE1)
all: gleiserkennung-v3.bin
%.o: %.c
avr-gcc $(CFLAGS) -c -o $@ $^
rebuild: clean all
gleiserkennung-v3.elf: gleiserkennung-v3.o eprom.o
avr-gcc $^ -o $@ $(LDFLAGS)
%.bin: %.elf
avr-objcopy -j .text -j .data -O binary $^ $@
clean:
rm *.o -rf
rm *.bin -rf
rm *.elf -rf
rm *~ -rf
cleanall: clean
source: cleanall
upload-v3: gleiserkennung-v3.bin
avrdude -c avrispmkII -P usb -p $(CPUTYPE2) -v -V -U flash:w:gleiserkennung-v3.bin:r

@ -1,26 +0,0 @@
/*
* eprom.c
*
* Created on: 11.02.2018
* Author: steffen
*/
#include "eprom.h"
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address and data registers
EEDR = ucData;
EECR |= (1<<EEMWE); // Write logical one to EEMWE
EECR |= (1<<EEWE); // Start eeprom write by setting EEWE
}
unsigned char EEPROM_read(unsigned int uiAddress) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address register
EECR |= (1<<EERE); // Start eeprom read by writing EERE
return EEDR; // return eeprom data register
}

@ -1,18 +0,0 @@
/*
* eprom.h
*
* Created on: 11.02.2018
* Author: steffen
*/
#ifndef EPROM_H_
#define EPROM_H_
#include <avr/io.h>
#include <avr/interrupt.h>
void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
unsigned char EEPROM_read(unsigned int uiAddress);
#endif /* ATMEGA8_DETECT_EPROM_H_ */

@ -1,283 +0,0 @@
/************************************************************
* reads some dis and make them readable over i2c bus.
*
* Atmega 16
* +-------+
* S26 (XCK/T0) PB0 -|1 O 40|- PA0 (ADC0) S14
* S25 (T1) PB1 -|2 39|- PA1 (ADC1) S13
* S24 (INT2/AIN0) PB2 -|3 38|- PA2 (ADC2) S12
* S23 (OC0/AIN1) PB3 -|4 37|- PA3 (ADC3) S11
* S22 (SS) PB4 -|5 36|- PA4 (ADC4) S10
* (MOSI) PB5 -|6 35|- PA5 (ADC5) S9
* (MISO) PB6 -|7 34|- PA6 (ADC6) S8
* (SCK) PB7 -|8 33|- PA7 (ADC7)
* RESET -|9 32|- AREF
* VCC -|10 31|- GND
* GND -|11 30|- AVCC
* XTAL2 -|12 29|- PC7 (TOSC2) S7
* XTAL1 -|13 28|- PC6 (TOSC1) S6
* S21 (RXD) PD0 -|14 27|- PC5 (TDI) S5
* S20 (TXD) PD1 -|15 26|- PC4 (TDO) S4
* S19 (INT0) PD2 -|16 25|- PC3 (TMS) S3
* S18 (INT1) PD3 -|17 24|- PC2 (TCK) S2
* S17 (OC1B) PD4 -|18 23|- PC1 (DSA) I2C
* S16 (OC1A) PD5 -|19 22|- PC0 (SCL) I2C
* S15 (ICP1) PD6 -|20 21|- PD7 (OC2) S1
* +-------+ */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.h"
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
#define I2C_DEFAULT_ADDR 0x2F
#define VERSION 3
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
uint32_t cnt[32] = { 0 };
unsigned int i;
uint32_t inval = 0;
uint32_t temp = 0;
int offdelay;
//
// disable JTAG
MCUCSR |= (1<<JTD);
MCUCSR |= (1<<JTD);
// enable inputs
DDRA = 0;
PORTA = 0xFF;
DDRB = 0;
PORTB = 0xFF;
DDRC = 0;
PORTC = 0xFF;
DDRD = 0;
PORTD = 0xFF;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
for (i = 0; i < 32; i++) cnt[i] = 0;
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
// S1 - S14
i = 0; if (!(PIND & (1 << 7))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PINC & (1 << 7))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 0))) cnt[i] = offdelay;
// S15 - S26
i++; if (!(PIND & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 0))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 0))) cnt[i] = offdelay;
// all values
for (i = 0; i < 16; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
for (i = 0; i < 16; i++) {
if (cnt[16+i] == 0) temp &= ~(1 << (i));
else {
cnt[16+i]--;
temp |= (1 << (i));
}
}
i2c_regs[0] = (unsigned char) (inval & 0x000000FF);
i2c_regs[1] = (unsigned char) ((inval & 0x0000FF00) >> 8);
i2c_regs[2] = (unsigned char) (temp & 0x000000FF);
i2c_regs[3] = (unsigned char) ((temp & 0x0000FF00) >> 8);
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};

@ -1,41 +0,0 @@
# .SILENT:
# Atmega88
# CFLAGS= -Os -g -Wall -mmcu=atmega16 -DF_CPU=8000000UL
# LDFLAGS= -mmcu=atmega16
CPUTYPE1= atmega32
CPUTYPE2= m32
# Atmega32
CFLAGS= -Os -g -Wall -mmcu=$(CPUTYPE1) -DF_CPU=16000000UL
LDFLAGS= -mmcu=$(CPUTYPE1)
all: gleiserkennung-v4.bin
%.o: %.c
avr-gcc $(CFLAGS) -c -o $@ $^
rebuild: clean all
gleiserkennung-v4.elf: gleiserkennung-v4.o eprom.o
avr-gcc $^ -o $@ $(LDFLAGS)
%.bin: %.elf
avr-objcopy -j .text -j .data -O binary $^ $@
clean:
rm *.o -rf
rm *.bin -rf
rm *.elf -rf
rm *~ -rf
cleanall: clean
source: cleanall
upload-v4: gleiserkennung-v4.bin
avrdude -c avrispmkII -P usb -p $(CPUTYPE2) -v -V -U flash:w:gleiserkennung-v4.bin:r

@ -1,26 +0,0 @@
/*
* eprom.c
*
* Created on: 11.02.2018
* Author: steffen
*/
#include "eprom.h"
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address and data registers
EEDR = ucData;
EECR |= (1<<EEMWE); // Write logical one to EEMWE
EECR |= (1<<EEWE); // Start eeprom write by setting EEWE
}
unsigned char EEPROM_read(unsigned int uiAddress) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address register
EECR |= (1<<EERE); // Start eeprom read by writing EERE
return EEDR; // return eeprom data register
}

@ -1,18 +0,0 @@
/*
* eprom.h
*
* Created on: 11.02.2018
* Author: steffen
*/
#ifndef EPROM_H_
#define EPROM_H_
#include <avr/io.h>
#include <avr/interrupt.h>
void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
unsigned char EEPROM_read(unsigned int uiAddress);
#endif /* ATMEGA8_DETECT_EPROM_H_ */

@ -1,281 +0,0 @@
/******************************************************************
* reads some digital inputs and make them readable over i2c bus.
*
* Atmega 32
* +-------+
* S17 (XCK/T0) PB0 -|1 O 40|- PA0 (ADC0) S9
* S18 (T1) PB1 -|2 39|- PA1 (ADC1) S10
* S19 (INT2/AIN0) PB2 -|3 38|- PA2 (ADC2) S11
* S20 (OC0/AIN1) PB3 -|4 37|- PA3 (ADC3) S12
* S21 (SS) PB4 -|5 36|- PA4 (ADC4) S13
* S22 (MOSI) PB5 -|6 35|- PA5 (ADC5) S14
* S23 (MISO) PB6 -|7 34|- PA6 (ADC6) S15
* S24 (SCK) PB7 -|8 33|- PA7 (ADC7) S16
* RESET -|9 32|- AREF
* VCC -|10 31|- GND
* GND -|11 30|- AVCC
* XTAL2 -|12 29|- PC7 (TOSC2)
* XTAL1 -|13 28|- PC6 (TOSC1)
* S1 (RXD) PD0 -|14 27|- PC5 (TDI)
* S2 (TXD) PD1 -|15 26|- PC4 (TDO)
* S3 (INT0) PD2 -|16 25|- PC3 (TMS)
* S4 (INT1) PD3 -|17 24|- PC2 (TCK)
* S5 (OC1B) PD4 -|18 23|- PC1 (DSA) I2C
* S6 (OC1A) PD5 -|19 22|- PC0 (SCL) I2C
* S7 (ICP1) PD6 -|20 21|- PD7 (OC2) S8
* +-------+ */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.h"
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
#define I2C_DEFAULT_ADDR 0x2F
#define VERSION 4
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
uint32_t cnt[32] = { 0 };
unsigned int i;
uint32_t inval = 0;
uint32_t temp = 0;
int offdelay;
//
// disable JTAG
MCUCSR |= (1<<JTD);
MCUCSR |= (1<<JTD);
// enable inputs
DDRA = 0;
PORTA = 0xFF;
DDRB = 0;
PORTB = 0xFF;
DDRC = 0;
PORTC = 0xFF;
DDRD = 0;
PORTD = 0xFF;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
for (i = 0; i < 32; i++) cnt[i] = 0;
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
// S1 - S8
i = 0; if (!(PINB & (1 << 0))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PINB & (1 << 7))) cnt[i] = offdelay;
// S9 - S16
i++; if (!(PINA & (1 << 0))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PINA & (1 << 7))) cnt[i] = offdelay;
// S17 - S24
i++; if (!(PIND & (1 << 0))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 1))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 2))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 3))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 4))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 5))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 6))) cnt[i] = offdelay;
i++; if (!(PIND & (1 << 7))) cnt[i] = offdelay;
// all values
for (i = 0; i < 16; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
for (i = 0; i < 16; i++) {
if (cnt[16+i] == 0) temp &= ~(1 << (i));
else {
cnt[16+i]--;
temp |= (1 << (i));
}
}
i2c_regs[0] = (unsigned char) (inval & 0x000000FF);
i2c_regs[1] = (unsigned char) ((inval & 0x0000FF00) >> 8);
i2c_regs[2] = (unsigned char) (temp & 0x000000FF);
i2c_regs[3] = (unsigned char) ((temp & 0x0000FF00) >> 8);
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};

@ -1,47 +0,0 @@
# .SILENT:
# Atmega88
# CFLAGS= -Os -g -Wall -mmcu=atmega16 -DF_CPU=8000000UL
# LDFLAGS= -mmcu=atmega16
CPUTYPE1= atmega8
CPUTYPE2= m8
# Atmega32
CFLAGS= -Os -g -Wall -mmcu=$(CPUTYPE1) -DF_CPU=16000000UL
LDFLAGS= -mmcu=$(CPUTYPE1)
all: gleiserkennung-v1.bin gleiserkennung-v2.bin
%.o: %.c
avr-gcc $(CFLAGS) -c -o $@ $^
rebuild: clean all
gleiserkennung-v2.elf: gleiserkennung-v2.o eprom.o
avr-gcc $^ -o $@ $(LDFLAGS)
gleiserkennung-v1.elf: gleiserkennung-v1.o eprom.o
avr-gcc $^ -o $@ $(LDFLAGS)
%.bin: %.elf
avr-objcopy -j .text -j .data -O binary $^ $@
clean:
rm *.o -rf
rm *.bin -rf
rm *.elf -rf
rm *~ -rf
cleanall: clean
source: cleanall
upload-v1: gleiserkennung-v1.bin
avrdude -c avrispmkII -P usb -p $(CPUTYPE2) -v -V -U flash:w:gleiserkennung-v1.bin:r
upload-v2: gleiserkennung-v2.bin
avrdude -c avrispmkII -P usb -p $(CPUTYPE2) -v -V -U flash:w:gleiserkennung-v2.bin:r

@ -1,26 +0,0 @@
/*
* eprom.c
*
* Created on: 11.02.2018
* Author: steffen
*/
#include "eprom.h"
void EEPROM_write(unsigned int uiAddress, unsigned char ucData) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address and data registers
EEDR = ucData;
EECR |= (1<<EEMWE); // Write logical one to EEMWE
EECR |= (1<<EEWE); // Start eeprom write by setting EEWE
}
unsigned char EEPROM_read(unsigned int uiAddress) {
while(EECR & (1<<EEWE)); // Wait for completion of previous write
EEAR = uiAddress; // Set up address register
EECR |= (1<<EERE); // Start eeprom read by writing EERE
return EEDR; // return eeprom data register
}

@ -1,18 +0,0 @@
/*
* eprom.h
*
* Created on: 11.02.2018
* Author: steffen
*/
#ifndef EPROM_H_
#define EPROM_H_
#include <avr/io.h>
#include <avr/interrupt.h>
void EEPROM_write(unsigned int uiAddress, unsigned char ucData);
unsigned char EEPROM_read(unsigned int uiAddress);
#endif /* ATMEGA8_DETECT_EPROM_H_ */

@ -1,247 +0,0 @@
/************************************************************
* reads some digital in and make them readable over i2c bus.
* register 0 -
*
* +-------+
* (RESET) PC6 -|1 O 28|- PC5 (ADC5/SCL)
* S3 (RXD) PD0 -|2 27|- PC4 (ADC4/SDA)
* S2 (TXD) PD1 -|3 26|- PC3 (ADC3)
* S1 (INT0) PD2 -|4 25|- PC2 (ADC2) S12
* S10 (INT1) PD3 -|5 24|- PC1 (ADC1) S16
* S7 (XCK/T0)PD4 -|6 23|- PC0 (ADC0) S15
* VCC -|7 22|- GND
* GND -|8 21|- AREF
* S8 (XTAL2/TOSC2) PB6 -|9 20|- AVCC
* S9 (XTAL2/TOSC2) PB7 -|10 19|- PB5 (SCK)
* S4 (T1) PD5 -|11 18|- PB4 (MISO)
* S5 (AIN0) PD6 -|12 17|- PB3 (MOSI(OC2)
* S6 (AIN1) PD7 -|13 16|- PB2 (SS/OC1B) S14
* S11 (ICP1) PB0 -|14 15|- PB1 (OC1A) S13
* +-------+
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.h"
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
#define I2C_DEFAULT_ADDR 0x4F
#define VERSION 1
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_DOOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
long int cnt[16] = { 0 };
unsigned int i;
unsigned short int inval = 0;
unsigned short int temp = 0;
int offdelay;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_system[I2C_SREG_DOOFFDELAY] = EEPROM_read(I2C_SREG_DOOFFDELAY);
if (i2c_system[I2C_SREG_DOOFFDELAY] == 0) {
i2c_system[I2C_SREG_DOOFFDELAY] = 0xFF;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
i = 0;
if (PIND & (1 << 2)) cnt[0] = offdelay;
if (PIND & (1 << 1)) cnt[1] = offdelay;
if (PIND & (1 << 0)) cnt[2] = offdelay;
if (PIND & (1 << 5)) cnt[3] = offdelay;
if (PIND & (1 << 6)) cnt[4] = offdelay;
if (PIND & (1 << 7)) cnt[5] = offdelay;
if (PIND & (1 << 4)) cnt[6] = offdelay;
if (PINB & (1 << 6)) cnt[7] = offdelay;
if (PINB & (1 << 7)) cnt[8] = offdelay;
if (PIND & (1 << 3)) cnt[9] = offdelay;
if (PINB & (1 << 0)) cnt[10] = offdelay;
if (PINC & (1 << 2)) cnt[11] = offdelay;
if (PINB & (1 << 1)) cnt[12] = offdelay;
if (PINB & (1 << 2)) cnt[13] = offdelay;
if (PINC & (1 << 0)) cnt[14] = offdelay;
if (PINC & (1 << 1)) cnt[15] = offdelay;
// all values
for (i = 0; i < 16; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
i2c_regs[0] = (unsigned char) (inval & 0x00FF);
i2c_regs[1] = (unsigned char) ((inval & 0xFF00) >> 8);
temp++;
i2c_regs[2] = (unsigned char) (temp & 0x00FF);
i2c_regs[3] = (unsigned char) ((temp & 0xFF00) >> 8);
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};

@ -1,250 +0,0 @@
/************************************************************
* reads some dis and make them readable over i2c bus.
* out of 8 registers only the register 1 is needed
*
* +-------+
* (RESET) PC6 -|1 O 28|- PC5 (ADC5/SCL)
* Sensor 1 (RXD) PD0 -|2 27|- PC4 (ADC4/SDA)
* Sensor 2 (TXD) PD1 -|3 26|- PC3 (ADC3) Relais 1
* Sensor 3 (INT0) PD2 -|4 25|- PC2 (ADC2) Relais 2
* Sensor 4 (INT1) PD3 -|5 24|- PC1 (ADC1) Relais 3
* Sensor 5 (XCK/T0) PD4 -|6 23|- PC0 (ADC0) Relais 4
* VCC -|7 22|- GND
* GND -|8 21|- AREF
* Sen6(XTAL2/TOSC2) PB6 -|9 20|- AVCC
* Sen7(XTAL2/TOSC2) PB7 -|10 19|- PB5 (SCK)
* Sensor 8 (T1) PD5 -|11 18|- PB4 (MISO)
* (AIN0) PD6 -|12 17|- PB3 (MOSI(OC2)
* Relais 7 (AIN1) PD7 -|13 16|- PB2 (SS/OC1B) Relais 5
* Relais 8 (ICP1) PB0 -|14 15|- PB1 (OC1A) Relais 6
* +-------+
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#include "eprom.h"
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
#define VERSION 2
#define I2C_DEFAULT_ADDR 0x4F
#define I2C_SREGS_OFFSET 0x20
enum {
I2C_SREG_VERSION = 0,
I2C_SREG_CMD,
I2C_SREG_ADDR,
I2C_SREG_DIOFFDELAY,
I2C_SREG_DOOFFDELAY,
I2C_SREG_MAX
};
enum {
I2C_CMD_NONE = 0,
I2C_CMD_EEPROMREAD,
I2C_CMD_EEPROMWRITE
};
volatile uint8_t i2c_reg;
volatile uint8_t i2c_system[I2C_SREG_MAX];
volatile uint8_t i2c_regs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
int i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_regs[i] = 0;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS || (data >= I2C_SREGS_OFFSET && data < I2C_SREGS_OFFSET+I2C_SREG_MAX)) {
i2c_reg = data;
TWCR_ACK;
}
else
TWCR_NACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_regs[i2c_reg] = data;
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
i2c_system[i2c_reg-I2C_SREGS_OFFSET] = data;
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_regs[i2c_reg];
i2c_reg++;
TWCR_ACK;
}
else if (i2c_reg >= I2C_SREGS_OFFSET && i2c_reg < I2C_SREGS_OFFSET+I2C_SREG_MAX) {
TWDR = i2c_system[i2c_reg-I2C_SREGS_OFFSET];
i2c_reg++;
TWCR_ACK;
}
else TWCR_NACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
int main( void ) {
long int cnt[8] = { 0 };
unsigned int i;
char inval = 0;
int offdelay;
//
// read all variables from eeprom
i2c_system[I2C_SREG_VERSION] = VERSION;
i2c_system[I2C_SREG_CMD] = 0;
i2c_system[I2C_SREG_ADDR] = EEPROM_read(I2C_SREG_ADDR);
if (i2c_system[I2C_SREG_ADDR] > 0x4f || i2c_system[I2C_SREG_ADDR] < 0x20) {
i2c_system[I2C_SREG_ADDR] = I2C_DEFAULT_ADDR;
}
i2c_system[I2C_SREG_DIOFFDELAY] = EEPROM_read(I2C_SREG_DIOFFDELAY);
if (i2c_system[I2C_SREG_DIOFFDELAY] == 0 || i2c_system[I2C_SREG_DIOFFDELAY] == 0xFF) {
i2c_system[I2C_SREG_DIOFFDELAY] = 0x20;
}
i2c_system[I2C_SREG_DOOFFDELAY] = EEPROM_read(I2C_SREG_DOOFFDELAY);
if (i2c_system[I2C_SREG_DOOFFDELAY] == 0) {
i2c_system[I2C_SREG_DOOFFDELAY] = 0xFF;
}
i2c_slave_init (i2c_system[I2C_SREG_ADDR]);
DDRB |= 1 | (1<<1) | (1<<2);
DDRC |= 1 | (1<<1) | (1<<2) | (1<<3);
DDRD |= (1<<7);
//
// system loop
while( 1 ) {
//
// digital in registers..
offdelay = i2c_system[I2C_SREG_DIOFFDELAY] << 8;
if (PIND & 0x01) cnt[0] = offdelay;
if (PIND & 0x02) cnt[1] = offdelay;
if (PIND & 0x04) cnt[2] = offdelay;
if (PIND & 0x08) cnt[3] = offdelay;
if (PIND & 0x10) cnt[4] = offdelay;
if (PINB & 0x40) cnt[5] = offdelay;
if (PINB & 0x80) cnt[6] = offdelay;
if (PIND & 0x20) cnt[7] = offdelay;
for (i = 0; i < 8; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
i2c_regs[0] = inval;
//
// digital out registers..
if (i2c_regs[1] & 0x01) PORTC |= (1 << 3);
else PORTC &= ~(1 << 3);
if (i2c_regs[1] & 0x02) PORTC |= (1 << 2);
else PORTC &= ~(1 << 2);
if (i2c_regs[1] & 0x04) PORTC |= (1 << 1);
else PORTC &= ~(1 << 1);
if (i2c_regs[1] & 0x08) PORTC |= 1;
else PORTC &= ~1;
if (i2c_regs[1] & 0x10) PORTB |= (1 << 2);
else PORTB &= ~(1 << 2);
if (i2c_regs[1] & 0x20) PORTB |= (1 << 1);
else PORTB &= ~(1 << 1);
if (i2c_regs[1] & 0x40) PORTD |= (1 << 7);
else PORTD &= ~(1 << 7);
if (i2c_regs[1] & 0x80) PORTB |= 1;
else PORTB &= ~1;
//
// system registers
if (i2c_system[I2C_SREG_CMD] != 0) {
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMREAD) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
i2c_system[i] = EEPROM_read(i);
}
sei();
}
if (i2c_system[I2C_SREG_CMD] == I2C_CMD_EEPROMWRITE) {
cli();
i2c_system[I2C_SREG_CMD] = 0;
for (i = 0; i < I2C_SREG_MAX; i++) {
EEPROM_write(i, i2c_system[i]);
}
sei();
}
}
i2c_system[I2C_SREG_CMD] = 0;
}
return 0;
};

@ -1,153 +0,0 @@
/************************************************************
* reads some dis and make them readable over i2c bus.
* out of 8 registers only the register 1 is needed
*
* +-------+
* (RESET) PC6 -|1 O 28|- PC5 (ADC5/SCL)
* (RXD) PD0 -|2 27|- PC4 (ADC4/SDA)
* (TXD) PD1 -|3 26|- PC3 (ADC3)
* (INT0) PD2 -|4 25|- PC2 (ADC2)
* (INT1) PD3 -|5 24|- PC1 (ADC1) Sensor 4
* (XCK/T0) PD4 -|6 23|- PC0 (ADC0) Sensor 3
* VCC -|7 22|- GND
* GND -|8 21|- AREF
* (XTAL2/TOSC2) PB6 -|9 20|- AVCC
* (XTAL2/TOSC2) PB7 -|10 19|- PB5 (SCK)
* Sensor 8 (T1) PD5 -|11 18|- PB4 (MISO)
* Sensor 7 (AIN0) PD6 -|12 17|- PB3 (MOSI(OC2)
* Sensor 6 (AIN1) PD7 -|13 16|- PB2 (SS/OC1B) Sensor 2
* Sensor 5 (ICP1) PB0 -|14 15|- PB1 (OC1A) Sensor 1
* +-------+
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdarg.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/twi.h>
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA);
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO);
#define I2C_NUM_REGS 8
volatile int i2c_reg;
volatile uint8_t i2c_inregs[I2C_NUM_REGS];
volatile uint8_t i2c_outregs[I2C_NUM_REGS];
//
// i2c slave addresse festlegen und interrupts einschalten
void i2c_slave_init(uint8_t adr) {
char i;
for (i = 0; i < I2C_NUM_REGS; i++) {
i2c_inregs[i] = i;
i2c_outregs[i] = i | 0x80;
}
TWAR = adr << 1;
TWCR &= ~(1<<TWSTA) | (1<<TWSTO);
TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
i2c_reg = 0x0;
sei();
}
ISR (TWI_vect) {
char data=0;
switch (TW_STATUS) {
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
TWCR_ACK;
i2c_reg=0xFF;
break;
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
data=TWDR;
if (i2c_reg == 0xFF) {
if(data < I2C_NUM_REGS)
i2c_reg = data;
else
i2c_reg = 0; // FIXME: wrong address so start at register 0
TWCR_ACK;
}
else {
if(i2c_reg < I2C_NUM_REGS) {
i2c_inregs[i2c_reg] = data;
i2c_reg++;
}
TWCR_ACK;
}
break;
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
if (i2c_reg == 0xFF) {
i2c_reg = 0;
}
if (i2c_reg < I2C_NUM_REGS) {
TWDR = i2c_outregs[i2c_reg];
// TWDR = 0xF3;
i2c_reg++;
}
else {
TWDR = 0; //Kein Daten mehr im Buffer
}
TWCR_ACK;
break;
case TW_SR_STOP:
TWCR_ACK;
break;
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert
case TW_SR_DATA_NACK: // 0x88
case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
default:
TWCR_RESET;
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
#define OFFDELAY 0x2000;
int main( void ) {
long int cnt[8] = { 0 };
unsigned int i;
char inval = 0;
long int t;
// i2c benutzt PORTC bit5+C4
i2c_slave_init (0x30);
while( 1 ) {
if (PINB & 0x02) cnt[0] = OFFDELAY;
if (PINB & 0x04) cnt[1] = OFFDELAY;
if (PINC & 0x02) cnt[2] = OFFDELAY;
if (PINC & 0x01) cnt[3] = OFFDELAY;
if (PINB & 0x01) cnt[4] = OFFDELAY;
if (PIND & 0x80) cnt[5] = OFFDELAY;
if (PIND & 0x40) cnt[6] = OFFDELAY;
if (PIND & 0x20) cnt[7] = OFFDELAY;
for (i = 0; i < 8; i++) {
if (cnt[i] == 0) inval &= ~(1 << (i));
else {
cnt[i]--;
inval |= (1 << (i));
}
}
i2c_outregs[1] = inval;
}
return 0;
};

@ -1,45 +0,0 @@
/*
* debug.cc
*
* Created on: 15.12.2017
* Author: steffen
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
char *int2hex (int val, char *buf, int len) {
char tmp[] = "0123456789ABCDEF";
int i;
unsigned int v;
if (buf == NULL) return NULL;
memset (buf, '0', len-1);
buf[len-1] = 0;
for (v = val, i = 0; i < len-1; i++) {
buf[len-2-i] = tmp[v % 16];
v = v >> 4;
}
return buf;
}
void debug_mem (char *c, int len) {
int i;
int v;
char _hexpos[32];
char _hexval[32];
for (i = 0; i < len; i++) {
if (i > 0 && (i % 16) == 0) printf ("\n");
if ((i % 16) == 0)
printf (" 0x%s ", int2hex(i, _hexpos, 5));
if ((i % 8) == 0) printf (" ");
v = (unsigned char) c[i];
printf ("%s ", int2hex(v, _hexval, 3));
}
printf ("\n");
};

@ -1,16 +0,0 @@
/*
* debug.h
*
* Created on: 15.12.2017
* Author: steffen
*/
#ifndef DEBUG_H_
#define DEBUG_H_
void debug_mem (char *c, int len);
char *int2hex (int val, char *buf, int len);
#endif /* DEBUG_H_ */

@ -1,105 +0,0 @@
/*
* i2csensor.cc
*
* Created on: 18.12.2017
* Author: steffen
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include "i2csensor.h"
#define LEN_FILENAME 255
#define LEN_BUFFER 32
I2C::I2C () {
i2cdev = 1;
};
I2C::~I2C () {
};
bool I2C::ReadByte(int addr, int reg, uint8_t *readval) {
int file;
char filename[LEN_FILENAME];
unsigned char buffer[LEN_BUFFER];
if (readval == NULL) return false;
// i2c device
snprintf(filename, 255, "/dev/i2c-%d", i2cdev);
file = open(filename, O_RDWR);
if (file < 0) {
return false;
}
// setup slave addresse
if (ioctl(file, I2C_SLAVE, addr) < 0) {
close (file);
return false;
}
usleep (10000);
// write register
buffer[0] = reg;
if (write(file, buffer, 1) != 1) {
close (file);
return false;
}
// read value
if (read(file, buffer, 1) != 1) {
close (file);
return false;
}
*readval = buffer[0];
close (file);
return true;
};
bool I2C::SendByte(int addr, int reg, uint8_t data) {
int file;
char filename[LEN_FILENAME];
unsigned char buffer[LEN_BUFFER];
// i2c device
snprintf(filename, 255, "/dev/i2c-%d", i2cdev);
file = open(filename, O_RDWR);
if (file < 0) {
return false;
}
// setup slave addresse
if (ioctl(file, I2C_SLAVE, addr) < 0) {
close (file);
return false;
}
usleep (10000);
// write register and value
buffer[0] = reg;
buffer[1] = data;
if (write(file, buffer, 2) != 2) {
close (file);
return false;
}
close (file);
return true;
};

@ -1,31 +0,0 @@
/*
* i2csensor.h
*
* Created on: 18.12.2017
* Author: steffen
*/
#ifndef I2CSENSOR_H_
#define I2CSENSOR_H_
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string>
using namespace std;
class I2C {
private:
int i2cdev;
public:
I2C ();
~I2C ();
bool ReadByte(int addr, int reg, uint8_t *readval);
bool SendByte(int addr, int reg, uint8_t data);
};
#endif /* I2CSENSOR_H_ */

@ -1,183 +0,0 @@
/*
*
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h> /* close() */
#include <string.h> /* memset() */
#include "udp.h"
char dnsip[NET_HOSTLEN];
int dns_filladdr (string host, string port, int ai_family, struct sockaddr_in *sAddr) {
struct addrinfo hints, *res;
int err;
/* we have to complete the sAddr struct */
bzero (&hints, sizeof (struct addrinfo));
hints.ai_family = ai_family;
hints.ai_socktype = SOCK_DGRAM;
if ((err = getaddrinfo (host.c_str(), port.c_str(), &hints, &res)) < 0) {
fprintf (stdout, "dns_filladdr (getaddrinfo):%s\n", gai_strerror (err));
return -1;
}
memcpy (sAddr, res->ai_addr, res->ai_addrlen);
freeaddrinfo (res);
return 1;
};
UDPConnection::UDPConnection() {
sock = -1;
port = "";
writecnt = 0;
readcnt = 0;
};
UDPConnection::~UDPConnection() {
Close();
}
void UDPConnection::Close () {
if (sock > -1) close (sock);
sock = -1;
}
int UDPConnection::Listen(int port) {
struct sockaddr_in servAddr;
/* socket creation */
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("%s: socket error: %s \n",__FUNCTION__, strerror(errno));
return 0;
}
/* bind local server port */
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port);
if (bind (sock, (struct sockaddr *) &servAddr,sizeof(servAddr)) < 0) {
printf("%s: bind error: %s \n",__FUNCTION__, strerror(errno));
return 0;
}
return 1;
}
int UDPConnection::Listen(string port) {
return Listen (atoi(port.c_str()));
}
long int UDPConnection::ReadTimeout(string *source, char *buffer, long int len, int timeout) {
int i;
i = isData(timeout);
if (i > 0) {
return Read (source, buffer, len);
}
else
return i;
}
long int UDPConnection::Read(string *source, char *buffer, long int len) {
int n;
socklen_t addrlen;
sockaddr_in srcAddr;
if (!isListen()) return -1;
memset(buffer, 0x0, len);
addrlen = sizeof(srcAddr);
n = recvfrom(sock, buffer, len, 0, (sockaddr *) &srcAddr, &addrlen);
if(n<0) {
printf("%s: recvfrom error:%s\n",__FUNCTION__, strerror(errno));
return -1;
}
/* print received message */
char addr[NET_HOSTLEN];
snprintf (addr, NET_HOSTLEN, "%s:%d", inet_ntoa(srcAddr.sin_addr), ntohs(srcAddr.sin_port));
(*source) = (char*)addr;
return n;
}
long int UDPConnection::Send(string destaddr, char *buffer, long int len) {
int s;
int addrlen = sizeof (struct sockaddr_in);
sockaddr_in dstAddr;
string host;
string port;
if (!isListen()) {
/* socket creation */
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
printf("%s: socket error: %s \n",__FUNCTION__, strerror(errno));
return -1;
}
}
else s = sock;
int pos = destaddr.rfind(':', destaddr.length());
if (pos == -1) {
port = "NET_PORT";
host = destaddr;
}
else {
port = destaddr.substr (pos+1, destaddr.length() - pos);
host = destaddr.substr (0, pos);
}
dns_filladdr (host, port, PF_INET, &dstAddr);
if (sendto (s, buffer, len, 0, (sockaddr *) &dstAddr, addrlen) == -1) {
printf("%s: sendto error: %s \n",__FUNCTION__, strerror(errno));
return -1;
}
if (!isListen()) close (s);
return 1;
}
int UDPConnection::isListen() {
return (sock != -1);
}
int UDPConnection::isData(int timeout) {
fd_set sockset;
struct timeval tval;
if (sock <= 0) {
printf ("isData:socket error\n");
return -1;
}
FD_ZERO (&sockset);
FD_SET (sock, &sockset);
tval.tv_sec = timeout / 1000;
tval.tv_usec = (timeout % 1000);
if (select (sock + 1, &sockset, NULL, NULL, &tval) >= 0) {
if (FD_ISSET (sock, &sockset)) {
return 1;
}
}
return 0;
}

@ -1,55 +0,0 @@
#ifndef _SP_UDP_H_
#define _SP_UDP_H_
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#include "config.h"
using namespace std;
#define NET_HOSTLEN 128
#define NET_PORTLEN 6
#define NET_BUFFERSIZE 1024
class UDPConnection {
private:
string port;
int sock;
size_t readcnt;
size_t writecnt;
public:
UDPConnection();
~UDPConnection();
int Listen(int port);
int Listen(string port);
long int ReadTimeout(string *srcaddr, char *buffer, long int len, int timeout);
long int Read(string *srcaddr, char *buffer, long int len);
long int Send(string destaddr, char *buffer, long int len);
void Close();
int isListen();
int isData(int timeout); // timeout in ms;
int getSocket() { return sock; };
void setSocket(int s);
};
#endif

@ -1,296 +0,0 @@
#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", &reg);
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);
}

@ -1,22 +0,0 @@
# autoscan configuration
# sensor NUM addr ADDR reg REG
sbox 0 addr 30 reg 0
sbox 1 addr 31 reg 0
sbox 2 addr 31 reg 1
sbox 3 addr 0 reg 0
sbox 4 addr 0 reg 0
sbox 5 addr 0 reg 0
sbox 6 addr 0 reg 0
sbox 7 addr 0 reg 0
sbox 8 addr 0 reg 0
sbox 9 addr 0 reg 0
sbox 10 addr 0 reg 0
sbox 11 addr 0 reg 0
sbox 12 addr 0 reg 0
sbox 13 addr 0 reg 0
sbox 14 addr 0 reg 0
sbox 15 addr 0 reg 0
sbox 16 addr 0 reg 0
sbox 17 addr 0 reg 0
sbox 18 addr 0 reg 0
sbox 19 addr 0 reg 0

@ -1,52 +0,0 @@
/*
* z21emu.h
*
* Created on: 16.12.2017
* Author: steffen
*/
#ifndef Z21EMU_H_
#define Z21EMU_H_
#include "config.h"
#define DEFAULT_CONFIG ETCPREFIX"/z21emu.conf"
#define RBUS_BYTESPERGROUP 10
#define RBUS_GROUPS 2
#define RBUS_MAXSENSORBYTES (RBUS_GROUPS*RBUS_BYTESPERGROUP)
#define XLAN_TURNOUT_MAX 1024
#define XLAN_TURNOUTBYTES (XLAN_TURNOUT_MAX / 8)
enum {
I2CREGTYPE_UNDEF,
I2CREGTYPE_DI,
I2CREGTYPE_DO
};
struct s_rbussensor {
unsigned char status; // current value
unsigned char last; // last value
unsigned char i2c_addr; // i2c address
unsigned char i2c_reg; // i2c register
};
extern struct s_rbussensor rbus[RBUS_MAXSENSORBYTES];
struct s_xlanturnout {
unsigned char i2c_addr; // i2c address
unsigned char i2c_reg; // i2c register
unsigned char output; // current value
unsigned char last; // last value
};
extern struct s_xlanturnout xlturn[XLAN_TURNOUT_MAX];
extern int debug;
void xlan_turnout (int addr, bool enable);
#endif /* Z21EMU_H_ */

@ -1,36 +0,0 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: z21emu
# Required-Start:
# Required-Stop:
# Should-Start:
# Default-Start:
# Default-Stop:
# Short-Description: z21 wrapper to support i2c sensors
# Description: z21 is a control device for model trains. this software implements a wrapper onto the z21 protocoll so you can connect some i2c devices to the rocrail or any other model train controlling software supporting z21.
### END INIT INFO
PATH=/sbin:/bin:/usr/local/bin:/usr/bin:/usr/sbin
case "$1" in
start)
/usr/local/bin/z21emu >&2 > /dev/null &
;;
restart|reload|force-reload)
echo "not pupported yet" >&2
exit 3
;;
stop)
killall z21emu
;;
status)
ps xa -H | grep z21emu
exit $?
;;
*)
echo "Usage: z21emu.sh [start|stop|status]" >&2
exit 3
;;
esac
:

@ -1,268 +0,0 @@
/*
* z21prot.cc
*
* Created on: 15.12.2017
* Author: steffen
*/
#include "config.h"
#include "z21prot.h"
#include "z21emu.h"
#include "debug.h"
Z21Client::Z21Client() {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
};
Z21Client::~Z21Client() {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
};
bool Z21Client::LoopData (UDPConnection *udp, char *buffer, size_t len) {
short unsigned int pktlen = le16toh(bufgetint16(buffer, 0));
short int pktheader = le16toh(bufgetint16(buffer, 2));
int i, k;
// LAN_GET_SERIAL_NUMBER
if (pktlen == 4 && pktheader == 0x10) {
bufsetint16 (outbuf, 0, htole16(8));
bufsetint16 (outbuf, 2, htole16(0x10));
bufsetint32 (outbuf, 4, htole32(55555953));
udp->Send(source, outbuf, 8);
}
// LAN_LOGOFF
else if (pktlen == 4 && pktheader == 0x0030) {
return false;
}
// LAN_X_ Commandos
else if (pktheader == 0x0040) {
if (pktlen > len) {
printf ("ERROR: got broken udp paket? pktlen(%d) > len(%ld)\n", pktlen, len);
} else {
Z21_lan_x_data xdata;
int pos = 4;
int chksum;
char db;
while (pos < pktlen) {
xdata.xheader = buffer[pos++];
for (i = 0; i < Z21_X_LEN && (unsigned int) i+pos < len; i++)
xdata.db[i] = buffer[pos+i];
// LAN_X_GET_VERSION
if (xdata.xheader == 0x21 &&
xdata.db[0] == 0x21 && xdata.db[1] == 0x00) {
printf ("LAN_X_GET_VERSION\n");
pos += 2;
bufsetint16 (outbuf, 0, htole16(9));
bufsetint16 (outbuf, 2, htole16(0x40));
k = 4;
bufsetint8 (outbuf, k++, db=0x63); // XHeader
chksum = db;
bufsetint8 (outbuf, k++, db=0x21); // DB0
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, db=0x30); // DB1
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, db=0x12); // DB2
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, chksum); // XOR-Byte
// debug_mem(outbuf, k);
udp->Send(source, outbuf, k);
}
// LAN_X_GET_FIRMWARE_VERSION
else if (xdata.xheader == 0xF1 &&
xdata.db[0] == 0x0A && xdata.db[1] == 0xFB) {
printf ("LAN_X_GET_FIRMWARE_VERSION\n");
pos += 3;
bufsetint16 (outbuf, 0, htole16(9)); // LEN
bufsetint16 (outbuf, 2, htole16(0x40)); // X_CMD
k = 4;
bufsetint8 (outbuf, k++, db=0xF3); // XHeader
chksum = db;
bufsetint8 (outbuf, k++, db=0x0A); // DB0
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, db=0x01); // DB1
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, db=0x20); // DB2
chksum = chksum ^ db;
bufsetint8 (outbuf, k++, chksum); // XOR-Byte
// debug_mem(outbuf, k);
udp->Send(source, outbuf, k);
}
// LAN_X_SET_TURNOUT
else if (xdata.xheader == 0x53) {
int addr = (xdata.db[0] << 8) + xdata.db[1];
int cmd = xdata.db[2];
int cmd_q = cmd & 0x20;
int cmd_a = cmd & 0x08;
int cmd_p = cmd & 0x01;
pos += 4;
printf ("LAN_X_SETTURNOUT addr: %d cmd: %x (q:%d a:%d p:%d)\n", addr, cmd, cmd_q, cmd_a, cmd_p);
xlan_turnout (addr, (cmd_a != 0));
}
else {
printf ("LAN_X command not understood: %x\n", xdata.xheader);
}
}
}
}
// LAN_RMBUS_GETDATA --> send LAN_RMBUS_DATACHANGED
else if (pktheader == 0x0081 && pktlen == 5) {
unsigned char rmbus_grpidx = bufgetint8(buffer, 4);
printf ("LAN_RMBUS_GETDATA\n");
Send_LAN_RMBUS_DATACHANGED(udp, rmbus_grpidx);
}
else {
printf ("unknown command: ");
// debug_mem (buffer, len);
}
return true;
}
void Z21Client::Send_LAN_RMBUS_DATACHANGED (UDPConnection *udp, unsigned char grpidx) {
int k, i;
printf ("Send LAN_RMBUS_DATACHANGED\n");
if (grpidx >= RBUS_GROUPS) {
printf (" giving group (%d) is not supported.\n", grpidx);
return;
}
bufsetint16 (outbuf, 0, htole16(15)); // LEN
bufsetint16 (outbuf, 2, htole16(0x80)); // X_CMD
k = 4;
bufsetint8 (outbuf, k++, grpidx); // Gruppenindex
for (i = 0; i < RBUS_BYTESPERGROUP; i++)
bufsetint8 (outbuf, k++, rbus[grpidx*RBUS_BYTESPERGROUP + i].status);
udp->Send(source, outbuf, k);
}
/************************************************************************/
Z21Server::Z21Server () {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
};
Z21Server::~Z21Server () {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
};
void Z21Server::Start() {
// printf ("** %s:%d %s\n", __FILE__, __LINE__, __FUNCTION__);
udp.Listen(DEFAULT_Z21PORT);
};
int Z21Server::Loop() {
string source;
size_t len;
int newclient = 1;
list<Z21Client*>::iterator iter;
int i, grp;
if (udp.isListen()) {
//
// read new data from UDP
len = udp.ReadTimeout(&source, buffer, NET_BUFFERSIZE, 25); // timeout 25ms
if (len > 0) {
//
// check known connection
newclient = 1;
iter = clients.begin();
while (iter != clients.end()) {
if ((*iter)->isSource(source)) {
newclient = 0;
if (!((*iter)->LoopData(&udp, buffer, len))) {
printf ("remove client: '%s' count:%ld\n", source.c_str(), clients.size());
iter = clients.erase(iter);
}
break;
}
iter++;
}
//
// new connection
if (newclient && iter == clients.end()) {
Z21Client *client;
client = new Z21Client();
client->setSource(source);
if (client->LoopData(&udp, buffer, len)) {
clients.push_back(client);
printf ("add client: '%s' count:%ld\n", source.c_str(), clients.size());
}
}
}
//
// broadcast changed values
for (grp = 0; grp < RBUS_GROUPS; grp++) {
for (i = 0; i < RBUS_BYTESPERGROUP; i++)
if (rbus[grp*RBUS_BYTESPERGROUP+i].status != rbus[grp*RBUS_BYTESPERGROUP+i].last) break;
if (i != RBUS_BYTESPERGROUP) {
//
// send broadcast to all clients
for (iter = clients.begin(); iter != clients.end(); iter++)
(*iter)->Send_LAN_RMBUS_DATACHANGED(&udp, grp);
}
}
}
return clients.size();
};
/************************************************************************/
uint8_t bufgetint8 (char *buf, int pos) {
int8_t i;
memcpy (&i, buf+pos, 1);
return i;
};
uint16_t bufgetint16 (char *buf, int pos) {
int16_t i;
memcpy (&i, buf+pos, 2);
return i;
};
uint32_t bufgetint32 (char *buf, int pos) {
int32_t i;
memcpy (&i, buf+pos, 4);
return i;
};
void bufsetint8 (char *buf, int pos, uint8_t i) {
memcpy (buf+pos, &i, 1);
};
void bufsetint16 (char *buf, int pos, uint16_t i) {
memcpy (buf+pos, &i, 2);
};
void bufsetint32 (char *buf, int pos, uint32_t i) {
memcpy (buf+pos, &i, 4);
};

@ -1,58 +0,0 @@
/*
* z21prot.h
*
* Created on: 15.12.2017
* Author: steffen
*/
#ifndef Z21PROT_H_
#define Z21PROT_H_
#include <list>
#include "udp.h"
#define Z21_X_LEN 16
struct {
unsigned char xheader;
unsigned char db[Z21_X_LEN];
} typedef Z21_lan_x_data;
//
// work around for memory alignment on some CPUs/PocketPCs
uint8_t bufgetint8 (char *buf, int pos);
uint16_t bufgetint16 (char *buf, int pos);
uint32_t bufgetint32 (char *buf, int pos);
void bufsetint8 (char *buf, int pos, uint8_t i);
void bufsetint16 (char *buf, int pos, uint16_t i);
void bufsetint32 (char *buf, int pos, uint32_t i);
class Z21Client {
private:
char outbuf[NET_BUFFERSIZE];
string source;
public:
Z21Client();
~Z21Client();
void setSource(string newsrc) { source = newsrc; };
string getSource() { return source; };
bool isSource(string srcaddr) { return (source.compare(srcaddr) == 0); };
bool LoopData (UDPConnection *udp, char *buffer, size_t len);
void Send_LAN_RMBUS_DATACHANGED (UDPConnection *udp, unsigned char grpidx);
};
class Z21Server{
private:
list<Z21Client*> clients;
UDPConnection udp;
char buffer[NET_BUFFERSIZE];
public:
Z21Server ();
~Z21Server ();
int Loop(); // returns number of connections
void Start();
};
#endif /* Z21PROT_H_ */
Loading…
Cancel
Save