#include "hw.h" #include #include #include #include #include #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<> 8) & 0xFF,2); return; } if (sind == slen+12) { send(scrc & 0xFF,0); return; } if (bit_is_set(UCSR0A, TXC0)) { PORTD &= ~(1<> 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< 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< 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(); }