z21emu - and atmega sources

master
Steffen Pohle 4 years ago
parent dc48847baf
commit a0b390886f

10
.gitignore vendored

@ -0,0 +1,10 @@
server/.depend
server/modelbahn-cgi
server/modelbahn-server
server/test-json
*~
*.oo
*.o
*.elf
*.bin

@ -0,0 +1,123 @@
# .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)

@ -0,0 +1,41 @@
# .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

@ -0,0 +1,26 @@
/*
* 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
}

@ -0,0 +1,18 @@
/*
* 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_ */

@ -0,0 +1,284 @@
/************************************************************
* 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;
};

@ -0,0 +1,47 @@
# .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

@ -0,0 +1,26 @@
/*
* 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
}

@ -0,0 +1,18 @@
/*
* 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_ */

@ -0,0 +1,247 @@
/************************************************************
* 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;
};

@ -0,0 +1,250 @@
/************************************************************
* 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;
};

@ -0,0 +1,153 @@
/************************************************************
* 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;
};

@ -0,0 +1,14 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define VERSION "0.1"
#define PREFIX "/usr/local"
#define RUNPID "/var/run/z21Emulation.pid"
#define DATAPREFIX "/var/lib"
#define ETCPREFIX "/etc"
#define DEFAULT_Z21PORT 21104
#endif

@ -0,0 +1,45 @@
/*
* 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");
};

@ -0,0 +1,16 @@
/*
* 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_ */

@ -0,0 +1,105 @@
/*
* 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;
};

@ -0,0 +1,31 @@
/*
* 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_ */

@ -0,0 +1,183 @@
/*
*
*/
#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;
}

@ -0,0 +1,55 @@
#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

@ -0,0 +1,286 @@
#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);
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], "-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))
rbus[index].status = 0xFF; // error
}
}
//
// 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) {
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 tmp;
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 (" -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);
}

@ -0,0 +1,22 @@
# 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

@ -0,0 +1,52 @@
/*
* 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];
void xlan_turnout (int addr, bool enable);
#endif /* Z21EMU_H_ */

@ -0,0 +1,36 @@
#! /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
:

@ -0,0 +1,268 @@
/*
* 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);
};

@ -0,0 +1,58 @@
/*
* 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