Initial commit

master
Jochen Friedrich 7 years ago
commit 65be3ae3fc

5
.gitignore vendored

@ -0,0 +1,5 @@
*.hex
*.lst
*.elf
*.o
*.map

@ -0,0 +1,48 @@
PROJ = avr-eb
CC = avr-gcc
OBJCOPY = avr-objcopy
CPU = atmega88
CFLAGS += -Os -g -mmcu=$(CPU) -Wall
CFLAGS += -Wa,-adhlns=$(<:%.c=%.lst)
CLDFLAGS += -mmcu=$(CPU) -Wl,-Map=$(@:%.elf=%.map)
TESTOBJS += testnode.o testhbw.o
RELAISOBJS += relaisnode.o relaishbw.o
IO6OBJS += io6node.o io6hbw.o
all: testnode.hex relaisnode.hex io6node.hex
testnode.o: testnode.c hbw.h hw.h testhw.h
$(CC) $(CFLAGS) -DTESTNODE -c $< -o $@
testhbw.o: hbw.c hbw.h hw.h testhw.h
$(CC) $(CFLAGS) -DTESTNODE -c $< -o $@
testnode.elf: $(TESTOBJS)
$(CC) $(CLDFLAGS) -o $@ $(TESTOBJS)
relaisnode.o: relaisnode.c hbw.h hw.h relaishw.h
$(CC) $(CFLAGS) -DRELAISNODE -c $< -o $@
relaishbw.o: hbw.c hbw.h hw.h relaishw.h
$(CC) $(CFLAGS) -DRELAISNODE -c $< -o $@
relaisnode.elf: $(RELAISOBJS)
$(CC) $(CLDFLAGS) -o $@ $(RELAISOBJS)
io6node.o: io6node.c hbw.h hw.h io6hw.h
$(CC) $(CFLAGS) -DIO6NODE -c $< -o $@
io6hbw.o: hbw.c hbw.h hw.h io6hw.h
$(CC) $(CFLAGS) -DIO6NODE -c $< -o $@
io6node.elf: $(IO6OBJS)
$(CC) $(CLDFLAGS) -o $@ $(IO6OBJS)
%hex:%elf
$(OBJCOPY) -j .text -j .data -O srec $< $@
clean:
rm -f *.hex *.elf *.o *.lst *.map

762
hbw.c

@ -0,0 +1,762 @@
#include "hw.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <stdlib.h>
#include <string.h>
#include "hbw.h"
uint32_t my_address;
uint8_t rind;
uint16_t rcrc;
uint32_t raddress;
uint32_t rdest;
uint8_t resc;
uint8_t rctl;
volatile uint8_t rready;
uint8_t rmessage[62];
uint8_t rlen;
uint8_t sind;
uint8_t sdisc;
uint8_t sctl;
uint16_t scrc;
uint8_t sesc;
uint32_t saddress;
uint8_t slen;
uint8_t smessage[62];
uint8_t slocked;
uint8_t sbusy;
volatile uint16_t sdelay;
uint8_t waitack;
uint32_t aaddress;
uint8_t actl;
uint8_t alen;
uint8_t alink;
uint8_t amessage[62];
uint8_t asent;
uint8_t dsent;
uint8_t gotack;
uint8_t configled;
uint8_t configbutton;
uint8_t configstate;
uint16_t configtimer;
static uint16_t crc16shift(uint16_t crc, uint8_t data)
{
int stat, i;
for (i=0; i<8; i++) {
stat = crc & 0x8000;
crc = crc << 1;
if (data & 0x80)
crc = crc | 1;
if (stat)
crc = crc ^ 0x1002;
data = data << 1;
}
return crc;
}
static void readaddr(void)
{
((uint8_t*)&my_address)[0]=eeprom_read_byte((const uint8_t *)EESIZE-4);
((uint8_t*)&my_address)[1]=eeprom_read_byte((const uint8_t *)EESIZE-3);
((uint8_t*)&my_address)[2]=eeprom_read_byte((const uint8_t *)EESIZE-2);
((uint8_t*)&my_address)[3]=eeprom_read_byte((const uint8_t *)EESIZE-1);
if (my_address == 0xFFFFFFFF)
((uint8_t*)&my_address)[0] = 0x42;
}
static void send(uint8_t i,uint8_t crc)
{
if (bit_is_set(UCSR0A, UDRE0)) {
if (sesc) {
UDR0 = i & 0x7F;
sind++;
sesc = 0;
return;
}
if (crc == 1) {
scrc = crc16shift(scrc, i);
}
if (crc == 2) {
scrc = crc16shift(scrc, 0);
scrc = crc16shift(scrc, 0);
i = (scrc >> 8) & 0xFF;
}
if ((i == 0xFD) || (i == 0xFC) || (i == 0xFE)) {
UDR0 = 0xFC;
sesc = 1;
return;
}
UDR0 = i;
sind++;
}
}
void rloop(void)
{
if (!sind)
return;
if (sdisc) {
if (sind == 1) {
send(0x04,1);
return;
}
if (sind == 2) {
send(0x01,1);
return;
}
if (sind == 3) {
send((scrc >> 8) & 0xFF,2);
return;
}
if (sind == 4) {
send(scrc & 0xFF,0);
return;
}
if (bit_is_set(UCSR0A, TXC0)) {
PORTD &= ~(1<<SenderEnable);
PORTD &= ~(1<<ReceiverDisable);
sind = 0;
sdisc = 0;
}
return;
}
if (sind < 5) {
send(((uint8_t*)&saddress)[sind-1],1);
return;
}
if (sind == 5) {
send(sctl,1);
return;
}
if (sind < 10) {
send(((uint8_t*)&my_address)[sind-6],1);
return;
}
if (sind == 10) {
send(slen+2,1);
return;
}
if (sind < slen+10) {
send(smessage[sind-11],1);
return;
}
if (sind == slen+10) {
send(smessage[sind-11],1);
return;
}
if (sind == slen+11) {
send((scrc >> 8) & 0xFF,2);
return;
}
if (sind == slen+12) {
send(scrc & 0xFF,0);
return;
}
if (bit_is_set(UCSR0A, TXC0)) {
PORTD &= ~(1<<SenderEnable);
PORTD &= ~(1<<ReceiverDisable);
sind = 0;
}
}
static uint8_t sendmsg(void)
{
if (sind)
return 0;
PORTD |= (1<<SenderEnable);
PORTD |= (1<<ReceiverDisable);
UCSR0A = (1<<TXC0);
scrc = crc16shift(0xFFFF, 0xFD);
UDR0 = 0xFD;
sind = 1;
sesc = 0;
sdisc = 0;
return ~0;
}
static uint8_t senddsc(void)
{
if (sind)
return 0;
PORTD |= (1<<SenderEnable);
PORTD |= (1<<ReceiverDisable);
UCSR0A = (1<<TXC0);
scrc = crc16shift(0xFFFF, 0xFE);
UDR0 = 0xFE;
sind = 1;
sesc = 0;
dsent = 1;
sdisc = 1;
sdelay = 1000 + (rand() & 0x1F);
return ~0;
}
static uint8_t is_bus_free(void)
{
if(sdelay || slocked || sind)
return 0;
return 1;
}
static void announce(void)
{
sctl = 0xF8;
saddress = 0xFFFFFFFF;
slen = 16;
smessage[0] = 0x41;
smessage[1] = 0;
smessage[2] = HBWTYPE;
smessage[3] = 0;
smessage[4] = HBWMAJOR;
smessage[5] = HBWMINOR;
smessage[6] = HBWSERIAL0;
smessage[7] = HBWSERIAL1;
smessage[8] = HBWSERIAL2;
smessage[9] = HBWSERIAL3;
smessage[10] = HBWSERIAL4;
smessage[11] = HBWSERIAL5;
smessage[12] = HBWSERIAL6;
smessage[13] = HBWSERIAL7;
smessage[14] = 0x30 + ((((uint8_t*)&my_address)[3] >> 4) & 0x0F);
smessage[15] = 0x30 + (((uint8_t*)&my_address)[3] & 0x0F);
if(smessage[14] > 0x39) smessage[14] += 7;
if(smessage[15] > 0x39) smessage[15] += 7;
if (sendmsg())
asent = 1;
}
void hbw_init(void)
{
DDRD |= (1<<SenderEnable);
DDRD |= (1<<ReceiverDisable);
PORTD &= ~(1<<SenderEnable);
PORTD &= ~(1<<ReceiverDisable);
#ifdef ConfigButton
DDRD &= ~(1<<ConfigButton);
PORTD |= (1<<ConfigButton);
#endif
#ifdef ConfigLED
DDRD |= (1<<ConfigLED);
PORTD &= ~(1<<ConfigLED);
#endif
UBRR0L = ((F_CPU/(BAUDRATE*16))-1) & 0xFF;
UBRR0H = 0;
UCSR0B = (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0);
UCSR0C = (1 << UPM01) | (1 << UCSZ01) | (1 << UCSZ00);
OCR2A = 249;
TIMSK2 |= (1 << OCIE2A);
TCCR2A |= (1 << WGM21);
TCCR2B = TCCR2B | (1 << CS22);
rind = 0;
sind = 0;
sdisc = 0;
rready = 0;
asent = 0;
dsent = 0;
hbw_timer = 0;
gotack = 0;
waitack = 0;
configled = 0;
configbutton = 0;
configstate = 0;
slocked = 0;
sbusy = 0;
alink = 0;
readaddr();
hbw_read_config();
srand(my_address);
sdelay = 1000 + (rand() & 0x1F);
sei();
}
void snext(void)
{
#ifdef HBW_MAXLINKS
uint8_t linkchannel;
if (amessage[0] != 'K') {
alink = 0;
return;
}
while (alink < HBW_MAXLINKS) {
linkchannel = eeprom_read_byte((const uint8_t *)(alink*6)+HBW_LINKOFFS);
if (amessage[1] == linkchannel) {
((uint8_t*)&aaddress)[0]=eeprom_read_byte((const uint8_t *)(alink*6)+HBW_LINKOFFS+1);
((uint8_t*)&aaddress)[1]=eeprom_read_byte((const uint8_t *)(alink*6)+HBW_LINKOFFS+2);
((uint8_t*)&aaddress)[2]=eeprom_read_byte((const uint8_t *)(alink*6)+HBW_LINKOFFS+3);
((uint8_t*)&aaddress)[3]=eeprom_read_byte((const uint8_t *)(alink*6)+HBW_LINKOFFS+4);
linkchannel=eeprom_read_byte((const uint8_t *)(alink*6)+HBW_LINKOFFS+5);
if(aaddress == my_address) {
hbw_receive_key(aaddress, amessage[1], linkchannel, amessage[3]);
} else {
amessage[2] = linkchannel;
sbusy = 1;
alink++;
return;
}
}
alink++;
}
#endif
alink = 0;
}
void sprocess(void)
{
if (gotack) {
gotack = 0;
waitack = 0;
sbusy= 0;
snext();
return;
}
if (!is_bus_free())
return;
if(waitack > 2) {
waitack = 0;
sbusy= 0;
snext();
return;
}
saddress = aaddress;
sctl = actl;
slen = alen;
memcpy(smessage,amessage,slen);
if (!sendmsg())
return;
if (aaddress == 0xFFFFFFFF) {
sbusy = 0;
snext();
return;
}
waitack++;
gotack = 0;
sdelay = 100 + (rand() & 0x1F);
}
void emessage(void)
{
uint8_t blocksize;
uint8_t blocknum;
uint8_t b,i;
blocksize = rmessage[3];
blocknum = rmessage[4];
slen = 4 + blocknum / 8;
if(blocknum % 8) slen++;
memset(smessage,0,slen);
smessage[0] = 'e';
smessage[1] = rmessage[1];;
smessage[2] = rmessage[2];;
smessage[3] = rmessage[3];;
for(b = 0; b <= blocknum; b++) {
for(i = 0; i < blocksize; i++) {
if(eeprom_read_byte((const uint8_t *)(b * blocksize + i)) != 0xFF) {
smessage[4 + b / 8] |= (1 << b % 8);
break;
}
}
}
}
static void rprocess(void)
{
uint8_t seq,i;
uint16_t addr;
if ((rdest == my_address) &&
(raddress == aaddress) &&
waitack) {
waitack = 0;
gotack = 1;
}
if ((rdest == my_address) &&
((rctl & 0x11) == 0x10)) {
saddress = raddress;
seq = (rctl >> 1) & 3;
if(!rlen)
return;
switch (rmessage[0]) {
case '@':
if (rlen != 6)
return;
if (rmessage[1] == 'a') {
eeprom_write_byte((uint8_t *)EESIZE-4, rmessage[2]);
eeprom_write_byte((uint8_t *)EESIZE-3, rmessage[3]);
eeprom_write_byte((uint8_t *)EESIZE-2, rmessage[4]);
eeprom_write_byte((uint8_t *)EESIZE-1, rmessage[5]);
readaddr();
}
slen = 0;
sctl = 0x19 | (seq << 5);
sendmsg();
break;
case 'h':
smessage[0] = HBWTYPE;
smessage[1] = 0;
slen = 2;
sctl = 0x18 | (seq << 5);
sendmsg();
break;
case 'n':
smessage[0] = HBWSERIAL0;
smessage[1] = HBWSERIAL1;
smessage[2] = HBWSERIAL2;
smessage[3] = HBWSERIAL3;
smessage[4] = HBWSERIAL4;
smessage[5] = HBWSERIAL5;
smessage[6] = HBWSERIAL6;
smessage[7] = HBWSERIAL7;
smessage[8] = 0x30 + ((((uint8_t*)&my_address)[3] >> 4) & 0x0F);
smessage[9] = 0x30 + (((uint8_t*)&my_address)[3] & 0x0F);
if(smessage[8] > 0x39) smessage[8] += 7;
if(smessage[9] > 0x39) smessage[9] += 7;
slen = 10;
seq = (rctl >> 1) & 3;
sctl = 0x18 | (seq << 5);
sendmsg();
break;
case 'v':
smessage[0] = HBWMAJOR;
smessage[1] = HBWMINOR;
slen = 2;
seq = (rctl >> 1) & 3;
sctl = 0x18 | (seq << 5);
sendmsg();
break;
case 'R':
if (rlen != 4)
return;
if (rmessage[3] > 62)
return;
addr = (rmessage[1] >> 8) | rmessage[2];
for (i = 0; i < rmessage[3]; i++)
smessage[i] = eeprom_read_byte((const uint8_t *)addr+i);
slen = rmessage[3];
seq = (rctl >> 1) & 3;
sctl = 0x18 | (seq << 5);
sendmsg();
break;
case 'W':
if (rlen <= 4)
return;
if (rlen != rmessage[3] + 4)
return;
addr = (rmessage[1] >> 8) | rmessage[2];
for (i = 0; i < rmessage[3]; i++)
eeprom_write_byte((uint8_t *)addr+i, rmessage[4+i]);
slen = 0;
sctl = 0x19 | (seq << 5);
sendmsg();
break;
case 'x':
case 's':
if (rlen <= 2)
return;
hbw_set_channel(rmessage[1], rlen - 2, &(rmessage[2]));
case 'S':
if (rlen < 2)
return;
smessage[0] = 'i';
smessage[1] = rmessage[1];
slen = hbw_get_channel(rmessage[1], &(smessage[2])) + 2;
seq = (rctl >> 1) & 3;
sctl = 0x18 | (seq << 5);
sendmsg();
break;
case 'C':
hbw_read_config();
slen = 0;
sctl = 0x19 | (seq << 5);
sendmsg();
break;
case 'K':
case 0xCB:
if (rlen != 4)
return;
hbw_receive_key(raddress, rmessage[1], rmessage[2], rmessage[3]);
slen = 0;
sctl = 0x19 | (seq << 5);
sendmsg();
break;
case 'E':
if (rlen != 4)
return;
emessage();
seq = (rctl >> 1) & 3;
sctl = 0x18 | (seq << 5);
sendmsg();
break;
}
}
if ((rdest == 0xFFFFFFFF) &&
((rctl & 0x11) == 0x10)) {
if(!rlen)
return;
switch (rmessage[0]) {
case 'z':
slocked = 1;
break;
case 'Z':
slocked = 0;
break;
}
}
}
static void eeprom_clear(void)
{
uint16_t i;
for (i=0; i < EESIZE-4; i++)
eeprom_write_byte((uint8_t *)i, 0xFF);
}
void hbw_loop(void)
{
rloop();
if (rready) {
rprocess();
rready = 0;
}
if (sbusy) {
sprocess();
} else {
if (!dsent) {
if (is_bus_free()) {
senddsc();
}
}
if (!asent) {
if (is_bus_free()) {
announce();
}
}
}
#ifdef ConfigButton
switch (configstate) {
case 0:
if (bit_is_clear(PIND, ConfigButton)) {
configtimer = hbw_timer;
configstate = 1;
configled = 1;
}
break;
case 1:
if (((hbw_timer - configtimer) > 20) &&
(bit_is_set(PIND, ConfigButton))) {
asent = 0;
configstate = 2;
configtimer = hbw_timer;
}
if ((hbw_timer - configtimer) > 8000) {
configstate = 3;
configtimer = hbw_timer;
}
break;
case 2:
if ((hbw_timer - configtimer) > 2000) {
configstate = 0;
configled = 0;
}
break;
case 3:
configled = (hbw_timer & 128)?0:1;
if (bit_is_set(PIND, ConfigButton)) {
configstate = 4;
configtimer = hbw_timer;
}
break;
case 4:
configled = (hbw_timer & 128)?0:1;
if (((hbw_timer - configtimer) > 2000) &&
(bit_is_set(PIND, ConfigButton))) {
configstate = 0;
configled = 0;
}
if (((hbw_timer - configtimer) > 20) &&
(bit_is_clear(PIND, ConfigButton))) {
configstate = 5;
configled = 0;
}
break;
case 5:
configled = (hbw_timer & 512)?0:1;
if (((hbw_timer - configtimer) > 20) &&
(bit_is_set(PIND, ConfigButton))) {
eeprom_clear();
configstate = 0;
configled = 0;
asent = 0;
}
}
#endif
#ifdef ConfigLED
if (configled)
PORTD |= (1<<ConfigLED);
else
PORTD &= ~(1<<ConfigLED);
#endif
}
uint8_t hbw_send_key(uint8_t channel, uint8_t count, uint8_t flag)
{
if (sbusy)
return 0;
if (alink)
return 0;
alen = 4;
actl = 0xF8;
amessage[0] = 'K';
amessage[1] = channel;
amessage[2] = 0;
amessage[3] = (flag & 3) | (count << 2);
aaddress = 0xFFFFFFFF;
sbusy = 1;
alink = 0;
return 1;
}
uint8_t hbw_send_channel(uint8_t channel, uint8_t length, uint8_t const * const data)
{
if (sbusy)
return 0;
if (alink)
return 0;
alen = length + 2;
actl = 0xF8;
((uint8_t*)&aaddress)[0]=eeprom_read_byte((const uint8_t *)2);
((uint8_t*)&aaddress)[1]=eeprom_read_byte((const uint8_t *)3);
((uint8_t*)&aaddress)[2]=eeprom_read_byte((const uint8_t *)4);
((uint8_t*)&aaddress)[3]=eeprom_read_byte((const uint8_t *)5);
amessage[0] = 'i';
amessage[1] = channel;
memcpy(&(amessage[2]), data, length);
sbusy = 1;
return 1;
}
ISR(USART_RX_vect)
{
uint8_t c;
sdelay = 100 + (rand() & 0x1F);
c = UDR0;
if (c == 0xFE) {
rind = 255;
resc = 0;
}
if (c == 0xFD) {
rind = 0;
resc = 0;
rready = 0;
rcrc =0xFFFF;
}
if (rind < 255) {
if (c == 0xFC) {
resc = 1;
return;
}
if (resc)
c = c | 0x80;
rcrc = crc16shift(rcrc, c);
resc = 0;
rind++;
}
if ((rind == 1) || (rind == 255))
return;
if (rind < 6) {
((uint8_t*)&rdest)[rind-2] = c;
return;
}
if (rind == 6) {
rctl = c;
return;
}
if (rind < 11) {
((uint8_t*)&raddress)[rind-7] = c;
return;
}
if (rind == 11) {
rlen = c;
return;
}
if ((rlen < 2) || (rlen > 64)) {
rind = 255;
return;
}
if ((rind < rlen + 10)) {
rmessage[rind-12] = c;
return;
}
if (rind == rlen + 10)
return;
if (rind == rlen + 11) {
rind = 255;
if (rcrc)
return;
rready = 1;
rlen = rlen - 2;
return;
}
}
ISR(TIMER2_COMPA_vect)
{
cli();
hbw_timer++;
if (sdelay)
sdelay--;
sei();
}

22
hbw.h

@ -0,0 +1,22 @@
#ifndef __HBW_H__
#define __HBW_H__
#define BAUDRATE 19200L
uint8_t hbw_rmessage[62];
uint8_t hbw_rlen;
uint8_t hbw_slen;
uint8_t hbw_smessage[62];
volatile uint16_t hbw_timer;
void hbw_init(void);
void hbw_loop(void);
uint8_t hbw_send_channel(uint8_t channel, uint8_t length, uint8_t const * const data);
uint8_t hbw_send_key(uint8_t channel, uint8_t count, uint8_t flag);
void hbw_receive_key(uint32_t saddress, uint8_t schannel, uint8_t channel, uint8_t countflag);
uint8_t hbw_get_channel(uint8_t channel, uint8_t data[]);
void hbw_set_channel(uint8_t channel, uint8_t len, uint8_t data[]);
void hbw_read_config(void);
#endif

@ -0,0 +1,152 @@
<?xml version="1.0"?>
<device eep_size="512" version="01">
<supported_types>
<type priority="2" id="HBW-EBIO6" name="Elektor EBus I/O6 Board">
<parameter const_value="0xE2" size="1" index="0"/>
<parameter const_value="0" size="1" index="1"/>
</type>
</supported_types>
<paramset id="HBW-EBIO6_dev_master" type="MASTER">
<parameter id="LOGGING_TIME">
<logical type="float" unit="s" default="5.0" max="25.5" min="0.1"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="0x0001"/>
</physical>
<conversion type="float_integer_scale" offset="0.0" factor="10"/>
</parameter>
<parameter id="CENTRAL_ADDRESS" hidden="true">
<logical type="integer"/>
<physical size="4" type="integer" interface="eeprom">
<address index="0x0002"/>
</physical>
</parameter>
<enforce id="CENTRAL_ADDRESS" value="1"/>
</paramset>
<frames>
<frame id="LEVEL_SET" type="#x" channel_field="10" direction="to_device">
<parameter size="1.0" index="11.0" type="integer" param="LEVEL"/>
</frame>
<frame id="LEVEL_GET" type="#S" channel_field="10" direction="to_device"/>
<frame id="INFO_LEVEL" type="#i" channel_field="10" direction="from_device" event="true">
<parameter size="1.0" index="11.0" type="integer" param="LEVEL"/>
</frame>
</frames>
<channels>
<channel index="0" type="MAINTENANCE" count="1" class="maintenance" ui_flags="internal">
</channel>
<channel index="1" type="SWITCH" count="4" physical_index_offset="-1">
<paramset id="hmw_switch_ch_master" type="MASTER" address_step="2" address_start="0x06">
<parameter id="LOGGING">
<logical type="option">
<option id="OFF"/>
<option id="ON" default="true"/>
</logical>
<physical size="0.1" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
</parameter>
</paramset>
<paramset id="hmw_switch_ch_link" type="LINK" count="16" address_start="0x1a" address_step="7" peer_param="SENSOR" channel_param="CHANNEL">
<parameter id="SENSOR" hidden="true" operations="none">
<logical type="address"/>
<physical type="array">
<physical size="4.0" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+4"/>
</physical>
</physical>
</parameter>
<parameter id="CHANNEL" hidden="true" operations="none">
<logical type="integer" min="0" max="255" default="255"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+5"/>
</physical>
</parameter>
<parameter id="SHORT_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE"/>
<option id="TOGGLE" default="true"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6"/>
</physical>
</parameter>
<parameter id="LONG_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE"/>
<option id="TOGGLE" default="true"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.2"/>
</physical>
</parameter>
<parameter id="LONGRELEASE_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE" default="true"/>
<option id="TOGGLE"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.4"/>
</physical>
</parameter>
<parameter id="DOUBLE_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE" default="true"/>
<option id="TOGGLE"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.6"/>
</physical>
</parameter>
</paramset>
<paramset id="hmw_switch_ch_values" type="VALUES">
<parameter id="STATE" operations="read,write,event" control="SWITCH.STATE">
<logical type="boolean" default="false"/>
<physical type="integer" interface="command" value_id="LEVEL">
<set request="LEVEL_SET"/>
<get request="LEVEL_GET" response="INFO_LEVEL"/>
<event frame="INFO_LEVEL"/>
</physical>
<conversion type="boolean_integer" true="200" false="0" threshold="1"/>
</parameter>
</paramset>
</channel>
<channel index="5" type="SENSOR" count="6" physical_index_offset="-1">
<paramset id="hmw_sensor_ch_master" type="MASTER" address_step="2" address_start="0x0e">
<parameter id="LOGGING">
<logical type="option">
<option id="OFF"/>
<option id="ON" default="true"/>
</logical>
<physical size="0.1" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
</parameter>
</paramset>
<paramset id="hmw_sensor_ch_values" type="VALUES">
<parameter id="STATE" operations="read,event" control="SWITCH.STATE">
<logical type="boolean" default="false"/>
<physical type="integer" interface="command" value_id="LEVEL">
<get request="LEVEL_GET" response="INFO_LEVEL"/>
<event frame="INFO_LEVEL"/>
</physical>
<conversion type="boolean_integer" true="200" false="0" threshold="1"/>
</parameter>
</paramset>
</channel>
</channels>
</device>

@ -0,0 +1,152 @@
<?xml version="1.0"?>
<device eep_size="512" version="01">
<supported_types>
<type priority="2" id="HBW-EBRELAIS" name="Elektor EBus Relais Board">
<parameter const_value="0xE1" size="1" index="0"/>
<parameter const_value="0" size="1" index="1"/>
</type>
</supported_types>
<paramset id="HBW-EBRELAIS_dev_master" type="MASTER">
<parameter id="LOGGING_TIME">
<logical type="float" unit="s" default="5.0" max="25.5" min="0.1"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="0x0001"/>
</physical>
<conversion type="float_integer_scale" offset="0.0" factor="10"/>
</parameter>
<parameter id="CENTRAL_ADDRESS" hidden="true">
<logical type="integer"/>
<physical size="4" type="integer" interface="eeprom">
<address index="0x0002"/>
</physical>
</parameter>
<enforce id="CENTRAL_ADDRESS" value="1"/>
</paramset>
<frames>
<frame id="LEVEL_SET" type="#x" channel_field="10" direction="to_device">
<parameter size="1.0" index="11.0" type="integer" param="LEVEL"/>
</frame>
<frame id="LEVEL_GET" type="#S" channel_field="10" direction="to_device"/>
<frame id="INFO_LEVEL" type="#i" channel_field="10" direction="from_device" event="true">
<parameter size="1.0" index="11.0" type="integer" param="LEVEL"/>
</frame>
</frames>
<channels>
<channel index="0" type="MAINTENANCE" count="1" class="maintenance" ui_flags="internal">
</channel>
<channel index="1" type="SWITCH" count="2" physical_index_offset="-1">
<paramset id="hmw_switch_ch_master" type="MASTER" address_step="2" address_start="0x06">
<parameter id="LOGGING">
<logical type="option">
<option id="OFF"/>
<option id="ON" default="true"/>
</logical>
<physical size="0.1" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
</parameter>
</paramset>
<paramset id="hmw_switch_ch_link" type="LINK" count="16" address_start="0x12" address_step="7" peer_param="SENSOR" channel_param="CHANNEL">
<parameter id="SENSOR" hidden="true" operations="none">
<logical type="address"/>
<physical type="array">
<physical size="4.0" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+4"/>
</physical>
</physical>
</parameter>
<parameter id="CHANNEL" hidden="true" operations="none">
<logical type="integer" min="0" max="255" default="255"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+5"/>
</physical>
</parameter>
<parameter id="SHORT_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE"/>
<option id="TOGGLE" default="true"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6"/>
</physical>
</parameter>
<parameter id="LONG_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE"/>
<option id="TOGGLE" default="true"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.2"/>
</physical>
</parameter>
<parameter id="LONGRELEASE_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE" default="true"/>
<option id="TOGGLE"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.4"/>
</physical>
</parameter>
<parameter id="DOUBLE_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE" default="true"/>
<option id="TOGGLE"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.6"/>
</physical>
</parameter>
</paramset>
<paramset id="hmw_switch_ch_values" type="VALUES">
<parameter id="STATE" operations="read,write,event" control="SWITCH.STATE">
<logical type="boolean" default="false"/>
<physical type="integer" interface="command" value_id="LEVEL">
<set request="LEVEL_SET"/>
<get request="LEVEL_GET" response="INFO_LEVEL"/>
<event frame="INFO_LEVEL"/>
</physical>
<conversion type="boolean_integer" true="200" false="0" threshold="1"/>
</parameter>
</paramset>
</channel>
<channel index="3" type="SENSOR" count="4" physical_index_offset="-1">
<paramset id="hmw_sensor_ch_master" type="MASTER" address_step="2" address_start="0x0a">
<parameter id="LOGGING">
<logical type="option">
<option id="OFF"/>
<option id="ON" default="true"/>
</logical>
<physical size="0.1" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
</parameter>
</paramset>
<paramset id="hmw_sensor_ch_values" type="VALUES">
<parameter id="STATE" operations="read,event" control="SWITCH.STATE">
<logical type="boolean" default="false"/>
<physical type="integer" interface="command" value_id="LEVEL">
<get request="LEVEL_GET" response="INFO_LEVEL"/>
<event frame="INFO_LEVEL"/>
</physical>
<conversion type="boolean_integer" true="200" false="0" threshold="1"/>
</parameter>
</paramset>
</channel>
</channels>
</device>

@ -0,0 +1,210 @@
<?xml version="1.0"?>
<device eep_size="512" version="01">
<supported_types>
<type priority="2" id="HBW-EBTEST" name="Elektor EBus Test Board">
<parameter const_value="0xE0" size="1" index="0"/>
<parameter const_value="0" size="1" index="1"/>
</type>
</supported_types>
<paramset id="HBW-EBTEST_dev_master" type="MASTER">
<parameter id="LOGGING_TIME">
<logical type="float" unit="s" default="5.0" max="25.5" min="0.1"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="0x0001"/>
</physical>
<conversion type="float_integer_scale" offset="0.0" factor="10"/>
</parameter>
<parameter id="CENTRAL_ADDRESS" hidden="true">
<logical type="integer"/>
<physical size="4" type="integer" interface="eeprom">
<address index="0x0002"/>
</physical>
</parameter>
<enforce id="CENTRAL_ADDRESS" value="1"/>
</paramset>
<frames>
<frame id="LEVEL_SET" type="#x" channel_field="10" direction="to_device">
<parameter size="1.0" index="11.0" type="integer" param="LEVEL"/>
</frame>
<frame id="LEVEL_GET" type="#S" channel_field="10" direction="to_device"/>
<frame id="INFO_LEVEL" type="#i" channel_field="10" direction="from_device" event="true">
<parameter size="1.0" index="11.0" type="integer" param="LEVEL"/>
</frame>
<frame id="KEY_EVENT_SHORT" type="#K" channel_field="10" direction="from_device" event="true">
<parameter const_value="2" size="0.2" index="12.0" type="integer"/>
<parameter size="0.6" index="12.2" type="integer" param="COUNTER"/>
</frame>
<frame id="KEY_EVENT_LONG" type="#K" channel_field="10" direction="from_device" event="true">
<parameter const_value="3" size="0.2" index="12.0" type="integer"/>
<parameter size="0.6" index="12.2" type="integer" param="COUNTER"/>
</frame>
<frame id="KEY_EVENT_LONGRELEASE" type="#K" channel_field="10" direction="from_device" event="true">
<parameter const_value="0" size="0.2" index="12.0" type="integer"/>
<parameter size="0.6" index="12.2" type="integer" param="COUNTER"/>
</frame>
<frame id="KEY_EVENT_DOUBLE" type="#K" channel_field="10" direction="from_device" event="true">
<parameter const_value="1" size="0.2" index="12.0" type="integer"/>
<parameter size="0.6" index="12.2" type="integer" param="COUNTER"/>
</frame>
</frames>
<channels>
<channel index="0" type="MAINTENANCE" count="1" class="maintenance" ui_flags="internal">
</channel>
<channel index="1" type="SWITCH" count="1" physical_index_offset="-1">
<paramset id="hmw_switch_ch_master" type="MASTER" address_step="1" address_start="0x06">
<parameter id="LOGGING">
<logical type="option">
<option id="OFF"/>
<option id="ON" default="true"/>
</logical>
<physical size="0.1" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
</parameter>
</paramset>
<paramset id="hmw_switch_ch_link" type="LINK" count="16" address_start="0x10" address_step="7" peer_param="SENSOR" channel_param="CHANNEL">
<parameter id="SENSOR" hidden="true" operations="none">
<logical type="address"/>
<physical type="array">
<physical size="4.0" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+4"/>
</physical>
</physical>
</parameter>
<parameter id="CHANNEL" hidden="true" operations="none">
<logical type="integer" min="0" max="255" default="255"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+5"/>
</physical>
</parameter>
<parameter id="SHORT_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE"/>
<option id="TOGGLE" default="true"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6"/>
</physical>
</parameter>
<parameter id="LONG_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE"/>
<option id="TOGGLE" default="true"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.2"/>
</physical>
</parameter>
<parameter id="LONGRELEASE_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE" default="true"/>
<option id="TOGGLE"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.4"/>
</physical>
</parameter>
<parameter id="DOUBLE_ACTION_TYPE">
<logical type="option">
<option id="ON"/>
<option id="OFF"/>
<option id="INACTIVE" default="true"/>
<option id="TOGGLE"/>
</logical>
<physical size="0.2" type="integer" interface="eeprom">
<address index="+6.6"/>
</physical>
</parameter>
</paramset>
<paramset id="hmw_switch_ch_values" type="VALUES">
<parameter id="STATE" operations="read,write,event" control="SWITCH.STATE">
<logical type="boolean" default="false"/>
<physical type="integer" interface="command" value_id="LEVEL">
<set request="LEVEL_SET"/>
<get request="LEVEL_GET" response="INFO_LEVEL"/>
<event frame="INFO_LEVEL"/>
</physical>
<conversion type="boolean_integer" true="200" false="0" threshold="1"/>
</parameter>
</paramset>
</channel>
<channel index="2" type="KEY" count="1" physical_index_offset="-1">
<link_roles>
<source name="SWITCH"/>
</link_roles>
<paramset id="hmw_input_ch_master" type="MASTER" address_step="1" address_start="0x07">
<parameter id="LONG_PRESS_TIME">
<logical type="float" unit="s" default="1.0" max="5.0" min="0.4"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+1"/>
</physical>
<conversion type="float_integer_scale" factor="10"/>
<conversion type="integer_integer_map">
<value_map to_device="false" from_device="true" parameter_value="10" device_value="0xff"/>
</conversion>
</parameter>
</paramset>
<paramset id="hmw_input_ch_link" type="LINK" count="16" address_step="6" address_start="0x80" channel_param="CHANNEL" peer_param="ACTUATOR">
<parameter hidden="true" id="CHANNEL" operations="none">
<logical type="integer" default="255" max="255" min="0"/>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+0"/>
</physical>
</parameter>
<parameter hidden="true" id="ACTUATOR" operations="none">
<logical type="address"/>
<physical type="array">
<physical size="4.0" type="integer" interface="eeprom">
<address index="+1"/>
</physical>
<physical size="1.0" type="integer" interface="eeprom">
<address index="+5"/>
</physical>
</physical>
</parameter>
</paramset>
<paramset id="hmw_input_ch_values" type="VALUES">
<parameter id="PRESS_SHORT" operations="event,write" loopback="true" control="BUTTON.SHORT">
<logical type="action"/>
<physical type="integer" interface="command" value_id="COUNTER">
<event frame="KEY_EVENT_SHORT"/>
</physical>
<conversion type="action_key_counter" counter_size="6" sim_counter="SIM_COUNTER"/>
</parameter>
<parameter id="PRESS_LONG" operations="event,write" loopback="true" control="BUTTON.LONG">
<logical type="action"/>
<physical type="integer" interface="command" value_id="COUNTER">
<event frame="KEY_EVENT_LONG"/>
</physical>
<conversion type="action_key_counter" counter_size="6" sim_counter="SIM_COUNTER"/>
</parameter>
<parameter id="RELEASE_LONG" operations="event" loopback="true" control="BUTTON.RELEASE">
<logical type="action"/>
<physical type="integer" interface="command" value_id="COUNTER">
<event frame="KEY_EVENT_LONGRELEASE"/>
</physical>
<conversion type="action_key_counter" counter_size="6" sim_counter="SIM_COUNTER"/>
</parameter>
<parameter id="DOUBLECLICK" operations="event" loopback="true" control="BUTTON.DOUBLE">
<logical type="action"/>
<physical type="integer" interface="command" value_id="COUNTER">
<event frame="KEY_EVENT_DOUBLE"/>
</physical>
<conversion type="action_key_counter" counter_size="6" sim_counter="SIM_COUNTER"/>
</parameter>
</paramset>
</channel>
</channels>
</device>

47
hw.h

@ -0,0 +1,47 @@
#ifndef __HW_H__
#define __HW_H__
#define SenderEnable PD2
#define ReceiverDisable PD3
#ifdef TESTNODE
#include "testhw.h"
#endif
#ifdef RELAISNODE
#include "relaishw.h"
#endif
#ifdef IO6NODE
#include "io6hw.h"
#endif
#ifndef F_CPU
#define F_CPU 16000000L
#endif
#ifndef HBWTYPE
#define HBWTYPE 0xAB
#endif
#ifndef HBWSERIAL0
#define HBWSERIAL0 'C'
#define HBWSERIAL1 'O'
#define HBWSERIAL2 'L'
#define HBWSERIAL3 'A'
#define HBWSERIAL4 'B'
#define HBWSERIAL5 'D'
#define HBWSERIAL6 'E'
#define HBWSERIAL7 'V'
#endif
#ifndef HBWMAJOR
#define HBWMAJOR 0
#endif
#ifndef HBWMINOR
#define HBWMINOR 0
#endif
#ifndef EESIZE
#define EESIZE 512
#endif
#endif

@ -0,0 +1,30 @@
#ifndef __IO6HW_H__
#define __IO6HW_H__
#define ConfigLED PD4
#define ConfigButton PD5
#define Out0 PD6
#define Out1 PD7
#define In0 PC0
#define In1 PC1
#define In2 PC2
#define In3 PC3
#define In4 PC4
#define In5 PC5
#define RedLED PB0
#define GreenLED PB1
#define HBWTYPE 0xE2
#define HBWMAJOR 1
#define HBWMINOR 2
#define HBWSERIAL0 'C'
#define HBWSERIAL1 'O'
#define HBWSERIAL2 'L'
#define HBWSERIAL3 'A'
#define HBWSERIAL4 'B'
#define HBWSERIAL5 'I'
#define HBWSERIAL6 'O'
#define HBWSERIAL7 '6'
#endif

@ -0,0 +1,389 @@
#include "hw.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include "hbw.h"
uint8_t in0state;
uint8_t in1state;
uint8_t in2state;
uint8_t in3state;
uint8_t in4state;
uint8_t in5state;
uint8_t scount;
uint16_t logtime;
uint8_t logging0;
uint8_t logging1;
uint8_t logging2;
uint8_t logging3;
uint16_t logtimer0;
uint16_t logtimer1;
uint16_t logtimer2;
uint16_t logtimer3;
uint8_t scount;
void hbw_read_config(void)
{
uint8_t ee;
ee = eeprom_read_byte((const uint8_t *)1);
logtime = 100L * ee;
ee = eeprom_read_byte((const uint8_t *)6);
logging0 = ee & 0x01;
ee = eeprom_read_byte((const uint8_t *)8);
logging1 = ee & 0x01;
ee = eeprom_read_byte((const uint8_t *)10);
logging2 = ee & 0x01;
ee = eeprom_read_byte((const uint8_t *)12);
logging3 = ee & 0x01;
}
uint8_t hbw_get_channel(uint8_t channel, uint8_t data[])
{
if (channel == 0) {
if (bit_is_clear(PINB, RedLED))
data[0] = 0;
else
data[0] = 200;
return 1;
}
if (channel == 1) {
if (bit_is_clear(PINB, GreenLED))
data[0] = 0;
else
data[0] = 200;
return 1;
}
if (channel == 2) {
if (bit_is_clear(PIND, Out0))
data[0] = 0;
else
data[0] = 200;
return 1;
}
if (channel == 3) {
if (bit_is_clear(PIND, Out1))
data[0] = 0;
else
data[0] = 200;
return 1;
}
if (channel == 4) {
if (bit_is_clear(PINC, In0))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 5) {
if (bit_is_clear(PINC, In1))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 6) {
if (bit_is_clear(PINC, In2))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 7) {
if (bit_is_clear(PINC, In3))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 8) {
if (bit_is_clear(PINC, In4))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 9) {
if (bit_is_clear(PINC, In5))
data[0] = 200;
else
data[0] = 0;
return 1;
}
return 0;
}
void hbw_set_channel(uint8_t channel, uint8_t len, uint8_t data[])
{
if (channel == 0) {
if (data[0])
PORTB |= (1<<RedLED);
else
PORTB &= ~(1<<RedLED);
}
if (channel == 1) {
if (data[0])
PORTB |= (1<<GreenLED);
else
PORTB &= ~(1<<GreenLED);
}
if (channel == 2) {
if (data[0])
PORTD |= (1<<Out0);
else
PORTD &= ~(1<<Out0);
}
if (channel == 3) {
if (data[0])
PORTD |= (1<<Out1);
else
PORTD &= ~(1<<Out1);
}
}
void hbw_receive_key(uint32_t saddress, uint8_t schannel, uint8_t channel, uint8_t countflag)
{
uint8_t i, type;
if (channel > 3)
return;
if (scount == countflag)
return;
for (i=0; i < 16; i++) {
if ((eeprom_read_byte((const uint8_t *)(i*7)+0x10) == ((uint8_t*)&saddress)[0]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x11) == ((uint8_t*)&saddress)[1]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x12) == ((uint8_t*)&saddress)[2]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x13) == ((uint8_t*)&saddress)[3]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x14) == schannel) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x15) == channel)) {
type = eeprom_read_byte((const uint8_t *)(i*7)+0x16);
switch (countflag & 3) {
case 1:
type = (type >> 6) & 0x3;
break;
case 0:
type = (type >> 4) & 0x3;
break;
case 3:
type = (type >> 2) & 0x3;
break;
case 2:
type = type & 0x3;
}
switch (type) {
case 0:
if(channel == 0)
PORTB |= (1<<RedLED);
else if(channel == 1)
PORTB |= (1<<GreenLED);
else if(channel == 2)
PORTD |= (1<<Out0);
else
PORTD |= (1<<Out1);
break;
case 1:
if(channel == 0)
PORTB &= ~(1<<RedLED);
else if(channel == 1)
PORTB &= ~(1<<GreenLED);
else if(channel == 2)
PORTD &= ~(1<<Out0);
else
PORTD &= ~(1<<Out1);
break;
case 3:
if(channel == 0)
PORTB ^= (1<<RedLED);
else if(channel == 1)
PORTB ^= (1<<GreenLED);
else if(channel == 2)
PORTD ^= (1<<Out0);
else
PORTD ^= (1<<Out1);
}
if ((channel == 0) && logging0) {
logtimer0 = hbw_timer + logtime;
if (!logtimer0) logtimer0 = 1;
}
if ((channel == 1) && logging1) {
logtimer1 = hbw_timer + logtime;
if (!logtimer1) logtimer1 = 1;
}
if ((channel == 2) && logging2) {
logtimer2 = hbw_timer + logtime;
if (!logtimer2) logtimer2 = 1;
}
if ((channel == 3) && logging3) {
logtimer3 = hbw_timer + logtime;
if (!logtimer3) logtimer3 = 1;
}
return;
}
}
}
int main(void)
{
uint8_t state;
DDRB |= (1<<RedLED);
DDRB |= (1<<GreenLED);
DDRD |= (1<<Out0);
DDRD |= (1<<Out1);
DDRC &= ~(1<<In0);
DDRC &= ~(1<<In1);
DDRC &= ~(1<<In2);
DDRC &= ~(1<<In3);
DDRC &= ~(1<<In4);
DDRC &= ~(1<<In5);
PORTB &= ~(1<<RedLED);
PORTB &= ~(1<<GreenLED);
PORTD &= ~(1<<Out0);
PORTD &= ~(1<<Out1);
PORTC |= (1<<In0);
PORTC |= (1<<In1);
PORTC |= (1<<In2);
PORTC |= (1<<In3);
PORTC |= (1<<In4);
PORTC |= (1<<In5);
hbw_init();
while(1) {
hbw_loop();
if (bit_is_clear(PINC, In0) && (!in0state)) {
state = 200;
if (hbw_send_channel(4, 1, &state))
in0state = ~0;
}
if (bit_is_set(PINC, In0) && in0state) {
state = 0;
if (hbw_send_channel(4, 1, &state))
in0state = 0;
}
if (bit_is_clear(PINC, In1) && (!in1state)) {
state = 200;
if (hbw_send_channel(5, 1, &state))
in1state = ~0;
}
if (bit_is_set(PINC, In1) && in1state) {
state = 0;
if (hbw_send_channel(5, 1, &state))
in1state = 0;
}
if (bit_is_clear(PINC, In2) && (!in2state)) {
state = 200;
if (hbw_send_channel(6, 1, &state))
in2state = ~0;
}
if (bit_is_set(PINC, In2) && in2state) {
state = 0;
if (hbw_send_channel(6, 1, &state))
in2state = 0;
}
if (bit_is_clear(PINC, In3) && (!in3state)) {
state = 200;
if (hbw_send_channel(7, 1, &state))
in3state = ~0;
}
if (bit_is_set(PINC, In3) && in3state) {
state = 0;
if (hbw_send_channel(7, 1, &state))
in3state = 0;
}
if (bit_is_clear(PINC, In4) && (!in4state)) {
state = 200;
if (hbw_send_channel(8, 1, &state))
in4state = ~0;
}
if (bit_is_set(PINC, In4) && in4state) {
state = 0;
if (hbw_send_channel(8, 1, &state))
in4state = 0;
}
if (bit_is_clear(PINC, In5) && (!in5state)) {
state = 200;
if (hbw_send_channel(9, 1, &state))
in5state = ~0;
}
if (bit_is_set(PINC, In5) && in5state) {
state = 0;
if (hbw_send_channel(9, 1, &state))
in5state = 0;
}
if (logtimer0 && (hbw_timer - logtimer0 < 100)) {
state = 0;
if (bit_is_set(PINB, RedLED))
state = 200;
if (!hbw_send_channel(0, 1, &state))
logtimer0 += 300;
else
logtimer0 = 0;
}
if (logtimer1 && (hbw_timer - logtimer1 < 100)) {
state = 0;
if (bit_is_set(PINB, GreenLED))
state = 200;
if (!hbw_send_channel(1, 1, &state))
logtimer1 += 300;
else
logtimer1 = 0;
}
if (logtimer2 && (hbw_timer - logtimer2 < 100)) {
state = 0;
if (bit_is_set(PIND, Out0))
state = 200;
if (!hbw_send_channel(2, 1, &state))
logtimer2 += 300;
else
logtimer2 = 0;
}
if (logtimer3 && (hbw_timer - logtimer3 < 100)) {
state = 0;
if (bit_is_set(PIND, Out1))
state = 200;
if (!hbw_send_channel(3, 1, &state))
logtimer3 += 300;
else
logtimer3 = 0;
}
}
}

@ -0,0 +1,27 @@
#ifndef __RELAISHW_H__
#define __RELAISHW_H__
#define ConfigLED PD4
#define ConfigButton PD5
#define Relais1 PB0
#define Relais2 PB1
#define In0 PC0
#define In1 PC1
#define In2 PC2
#define In3 PC3
#define HBWTYPE 0xE1
#define HBWMAJOR 1
#define HBWMINOR 2
#define HBWSERIAL0 'C'
#define HBWSERIAL1 'O'
#define HBWSERIAL2 'L'
#define HBWSERIAL3 'A'
#define HBWSERIAL4 'B'
#define HBWSERIAL5 'R'
#define HBWSERIAL6 'E'
#define HBWSERIAL7 'L'
#endif

@ -0,0 +1,261 @@
#include "hw.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include "hbw.h"
uint8_t in0state;
uint8_t in1state;
uint8_t in2state;
uint8_t in3state;
uint8_t scount;
uint16_t logtime;
uint8_t logging0;
uint8_t logging1;
uint16_t logtimer0;
uint16_t logtimer1;
uint8_t scount;
void hbw_read_config(void)
{
uint8_t ee;
ee = eeprom_read_byte((const uint8_t *)1);
logtime = 100L * ee;
ee = eeprom_read_byte((const uint8_t *)6);
logging0 = ee & 0x01;
ee = eeprom_read_byte((const uint8_t *)8);
logging1 = ee & 0x01;
}
uint8_t hbw_get_channel(uint8_t channel, uint8_t data[])
{
if (channel == 0) {
if (bit_is_clear(PINB, Relais1))
data[0] = 0;
else
data[0] = 200;
return 1;
}
if (channel == 1) {
if (bit_is_clear(PINB, Relais2))
data[0] = 0;
else
data[0] = 200;
return 1;
}
if (channel == 2) {
if (bit_is_clear(PINC, In0))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 3) {
if (bit_is_clear(PINC, In1))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 4) {
if (bit_is_clear(PINC, In2))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 5) {
if (bit_is_clear(PINC, In3))
data[0] = 200;
else
data[0] = 0;
return 1;
}
return 0;
}
void hbw_set_channel(uint8_t channel, uint8_t len, uint8_t data[])
{
if (channel == 0) {
if (data[0])
PORTB |= (1<<Relais1);
else
PORTB &= ~(1<<Relais1);
}
if (channel == 1) {
if (data[0])
PORTB |= (1<<Relais2);
else
PORTB &= ~(1<<Relais2);
}
}
void hbw_receive_key(uint32_t saddress, uint8_t schannel, uint8_t channel, uint8_t countflag)
{
uint8_t i, type;
if (channel > 1)
return;
if (scount == countflag)
return;
for (i=0; i < 16; i++) {
if ((eeprom_read_byte((const uint8_t *)(i*7)+0x10) == ((uint8_t*)&saddress)[0]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x11) == ((uint8_t*)&saddress)[1]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x12) == ((uint8_t*)&saddress)[2]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x13) == ((uint8_t*)&saddress)[3]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x14) == schannel) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x15) == channel)) {
type = eeprom_read_byte((const uint8_t *)(i*7)+0x16);
switch (countflag & 3) {
case 1:
type = (type >> 6) & 0x3;
break;
case 0:
type = (type >> 4) & 0x3;
break;
case 3:
type = (type >> 2) & 0x3;
break;
case 2:
type = type & 0x3;
}
switch (type) {
case 0:
if(channel == 0)
PORTB |= (1<<Relais1);
else
PORTB |= (1<<Relais2);
break;
case 1:
if(channel == 0)
PORTB &= ~(1<<Relais1);
else
PORTB &= ~(1<<Relais2);
break;
case 3:
if(channel == 0)
PORTB ^= (1<<Relais1);
else
PORTB ^= (1<<Relais2);
}
if ((channel == 0) && logging0) {
logtimer0 = hbw_timer + logtime;
if (!logtimer0) logtimer0 = 1;
}
if ((channel == 1) && logging1) {
logtimer1 = hbw_timer + logtime;
if (!logtimer1) logtimer1 = 1;
}
return;
}
}
}
int main(void)
{
uint8_t state;
DDRB |= (1<<Relais1);
DDRB |= (1<<Relais2);
DDRC &= ~(1<<In0);
DDRC &= ~(1<<In1);
DDRC &= ~(1<<In2);
DDRC &= ~(1<<In3);
PORTB &= ~(1<<Relais1);
PORTB &= ~(1<<Relais2);
PORTC |= (1<<In0);
PORTC |= (1<<In1);
PORTC |= (1<<In2);
PORTC |= (1<<In3);
hbw_init();
while(1) {
hbw_loop();
if (bit_is_clear(PINC, In0) && (!in0state)) {
state = 200;
if (hbw_send_channel(2, 1, &state))
in0state = ~0;
}
if (bit_is_set(PINC, In0) && in0state) {
state = 0;
if (hbw_send_channel(2, 1, &state))
in0state = 0;
}
if (bit_is_clear(PINC, In1) && (!in1state)) {
state = 200;
if (hbw_send_channel(3, 1, &state))
in1state = ~0;
}
if (bit_is_set(PINC, In1) && in1state) {
state = 0;
if (hbw_send_channel(3, 1, &state))
in1state = 0;
}
if (bit_is_clear(PINC, In2) && (!in2state)) {
state = 200;
if (hbw_send_channel(4, 1, &state))
in2state = ~0;
}
if (bit_is_set(PINC, In2) && in2state) {
state = 0;
if (hbw_send_channel(4, 1, &state))
in2state = 0;
}
if (bit_is_clear(PINC, In3) && (!in3state)) {
state = 200;
if (hbw_send_channel(5, 1, &state))
in3state = ~0;
}
if (bit_is_set(PINC, In3) && in3state) {
state = 0;
if (hbw_send_channel(5, 1, &state))
in3state = 0;
}
if (logtimer0 && (hbw_timer - logtimer0 < 100)) {
state = 0;
if (bit_is_set(PINB, Relais1))
state = 200;
if (!hbw_send_channel(0, 1, &state))
logtimer0 += 300;
else
logtimer0 = 0;
}
if (logtimer1 && (hbw_timer - logtimer1 < 100)) {
state = 0;
if (bit_is_set(PINB, Relais2))
state = 200;
if (!hbw_send_channel(1, 1, &state))
logtimer1 += 300;
else
logtimer1 = 0;
}
}
}

@ -0,0 +1,23 @@
#ifndef __TESTHW_H__
#define __TESTHW_H__
#define ConfigLED PD4
#define ConfigButton PD5
#define ExpLED PD6
#define ExpButton PD7
#define HBWTYPE 0xE0
#define HBWMAJOR 1
#define HBWMINOR 2
#define HBWSERIAL0 'C'
#define HBWSERIAL1 'O'
#define HBWSERIAL2 'L'
#define HBWSERIAL3 'A'
#define HBWSERIAL4 'B'
#define HBWSERIAL5 'T'
#define HBWSERIAL6 'S'
#define HBWSERIAL7 'T'
#define HBW_MAXLINKS 16
#define HBW_LINKOFFS 0x80
#endif

@ -0,0 +1,193 @@
#include "hw.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include "hbw.h"
uint8_t expled;
uint8_t expbutton;
uint8_t expdouble;
uint16_t exptime;
uint16_t explong;
uint16_t longtime;
uint16_t logtime;
uint16_t logtimer;
uint8_t logging;
uint8_t scount;
void hbw_read_config(void)
{
uint8_t ee;
ee = eeprom_read_byte((const uint8_t *)1);
logtime = 100L * ee;
ee = eeprom_read_byte((const uint8_t *)6);
logging = ee & 0x01;
ee = eeprom_read_byte((const uint8_t *)8);
if (ee == 0xFF)
longtime = 1000;
else
longtime = 100L * ee;
}
uint8_t hbw_get_channel(uint8_t channel, uint8_t data[])
{
if (channel == 1) {
if (bit_is_clear(PIND, ExpButton))
data[0] = 200;
else
data[0] = 0;
return 1;
}
if (channel == 0) {
if (bit_is_clear(PIND, ExpLED))
data[0] = 0;
else
data[0] = 200;
return 1;
}
return 0;
}
void hbw_set_channel(uint8_t channel, uint8_t len, uint8_t data[])
{
if (channel == 0) {
if (data[0])
PORTD |= (1<<ExpLED);
else
PORTD &= ~(1<<ExpLED);
}
}
void hbw_receive_key(uint32_t saddress, uint8_t schannel, uint8_t channel, uint8_t countflag)
{
uint8_t i, type;
if (channel != 0)
return;
if (scount == countflag)
return;
for (i=0; i < 16; i++) {
if ((eeprom_read_byte((const uint8_t *)(i*7)+0x10) == ((uint8_t*)&saddress)[0]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x11) == ((uint8_t*)&saddress)[1]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x12) == ((uint8_t*)&saddress)[2]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x13) == ((uint8_t*)&saddress)[3]) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x14) == schannel) &&
(eeprom_read_byte((const uint8_t *)(i*7)+0x15) == channel)) {
type = eeprom_read_byte((const uint8_t *)(i*7)+0x16);
switch (countflag & 3) {
case 1:
type = (type >> 6) & 0x3;
break;
case 0:
type = (type >> 4) & 0x3;
break;
case 3:
type = (type >> 2) & 0x3;
break;
case 2:
type = type & 0x3;
}
switch (type) {
case 0:
PORTD |= (1<<ExpLED);
break;
case 1:
PORTD &= ~(1<<ExpLED);
break;
case 3:
PORTD ^= (1<<ExpLED);
}
if (logging) {
logtimer = hbw_timer + logtime;
if (!logtimer) logtimer = 1;
}
return;
}
}
}
int main(void)
{
uint16_t now;
uint8_t state;
uint8_t led;
DDRD |= (1<<ExpLED);
DDRD &= ~(1<<ExpButton);
PORTD &= ~(1<<ExpLED);
PORTD |= (1<<ExpButton);
hbw_init();
state = 255;
while(1) {
hbw_loop();
now = hbw_timer?hbw_timer:1;
if (bit_is_clear(PIND, ExpButton)) {
if (exptime) {
if (explong) {
if (now - explong >= 300) {
explong = now;
state = 3;
}
} else {
if (now - exptime > longtime) {
explong = now;
expbutton++;
state = 3;
}
}
} else {
exptime = now;
explong = 0;
if (expdouble == 1)
expdouble = 2;
}
}
if (bit_is_set(PIND, ExpButton)) {
if (exptime) {
if (now - exptime > 50 && !explong && (expdouble == 2)) {
expbutton++;
state = 1;
expdouble = 0;
}
if (now - exptime > 300 && !explong && (expdouble == 1)) {
expbutton++;
state = 2;
expdouble = 0;
}
if (now - exptime > 50 && !explong && (expdouble == 0))
expdouble = 1;
if (now - exptime > 50 && explong) {
state = 0;
expdouble = 0;
}
exptime = 0;
}
}
if (state != 255)
if (hbw_send_key(1, expbutton, state))
state = 255;
if (logtimer && (hbw_timer - logtimer < 100)) {
led = 0;
if (bit_is_set(PIND, ExpLED))
led = 200;
if (!hbw_send_channel(0, 1, &led))
logtimer += 300;
else
logtimer = 0;
}
}
}
Loading…
Cancel
Save