#include "hw.h" #include #include #include #include #include #include "hbw.h" uint8_t my_address[4]; uint8_t rind; uint16_t rcrc; uint8_t raddress[4]; uint8_t rdest[4]; 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; uint8_t saddress[4]; uint8_t slen; uint8_t smessage[62]; uint16_t sdelay; uint8_t asent; uint8_t waitack; uint8_t gotack; 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) { my_address[0]=eeprom_read_byte((const uint8_t *)EESIZE-4); my_address[1]=eeprom_read_byte((const uint8_t *)EESIZE-3); my_address[2]=eeprom_read_byte((const uint8_t *)EESIZE-2); my_address[3]=eeprom_read_byte((const uint8_t *)EESIZE-1); if ((my_address[0] == 0xFF) && (my_address[1] == 0xFF) && (my_address[2] == 0xFF) && (my_address[3] == 0xFF)) 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< 0x7FFF) return 1; return 0; } static void announce(void) { sctl = 0xF8; saddress[0] = 0xFF; saddress[1] = 0xFF; saddress[2] = 0xFF; saddress[3] = 0xFF; 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] = HBWSERIAL8; smessage[15] = HBWSERIAL9; sendmsg(); asent = 1; } void hbw_init(void) { DDRD |= (1<> 1) & 3; switch (rmessage[0]) { case '@': 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] = HBWSERIAL8; smessage[9] = HBWSERIAL9; 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': 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': 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': hbw_set_channel(rmessage[1], rlen - 2, &(rmessage[2])); case 'S': 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': slen = 0; sctl = 0x19 | (seq << 5); sendmsg(); break; } } } void hbw_loop(void) { rloop(); if (rready) { process(); rready = 0; } if (!asent) { if (is_bus_free()) { announce(); } } } uint8_t hbw_send_channel(uint8_t channel, uint8_t length, uint8_t const * const data, uint32_t target_address) { if (gotack) { gotack = 0; return 1; } if (!is_bus_free()) return 0; if (waitack) return 0; slen = length + 2; sctl = 0xF8; saddress[0] = eeprom_read_byte((const uint8_t *)2); saddress[1] = eeprom_read_byte((const uint8_t *)3); saddress[2] = eeprom_read_byte((const uint8_t *)4); saddress[3] = eeprom_read_byte((const uint8_t *)5); smessage[0] = 'i'; smessage[1] = channel; memcpy(&(smessage[2]), data, length); sendmsg(); waitack = 1; gotack = 0; return 0; } ISR(USART_RX_vect) { uint8_t c; sdelay = hbw_timer + 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) { rdest[rind-2] = c; return; } if (rind == 6) { rctl = c; return; } if (rind < 11) { 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; return; } } ISR(TIMER2_COMPA_vect) { cli(); hbw_timer++; sei(); }