#include "usbdrv.h"
#include "libs-device/osccal.h"
+#define REPEAT_COUNT 10
+
#define CMD_ALL_ON 0xfe
#define CMD_ALL_OFF 0xfc
#define CMD_ON 0xff
#define CMD_OFF 0xfd
#define CMD_SET_SERIAL 0xfa
-/* Energenie 24 bit address , last 4 all 0 for code */
-#define ENER_ADDR 0x123450
-
-uchar serno_read = 0;
-uchar serno[6];
+int serno_str[] = {
+ USB_STRING_DESCRIPTOR_HEADER(5),
+ '1', '2', '3', '4', '5',
+};
+uint32_t serno;
unsigned long cmd = 0;
-int repeat = 0;
+int repeat = 0, wait = 0;
+uint8_t state = 0;
PROGMEM const char usbHidReportDescriptor[22] = {
0x06, 0x00, 0xff, /* USAGE PAGE (Generic Desktop) */
0xc0 /* END_COLLECTION */
};
+inline char hexdigit(int i)
+{
+ return (i < 10) ? ('0' + i) : ('A' - 10 + i);
+}
+
+inline int digithex(char i)
+{
+ if (i >= '0' && i <= '9')
+ return i - '0';
+
+ if (i >= 'A' && i <= 'F')
+ return i - 'A' + 10;
+
+ if (i >= 'a' && i <= 'f')
+ return i - 'a' + 10;
+
+ return 0;
+}
+
void fetch_serno(void)
{
- if (!serno_read) {
- eeprom_read_block(serno, 0, 6);
- if (serno[0] == 0xff) {
- /* If the EEPROM is blank, return a default serial # */
- serno[0] = 'U';
- serno[1] = 'N';
- serno[2] = 'S';
- serno[3] = 'E';
- serno[4] = 'T';
- serno[5] = 0;
- }
- serno_read = 1;
+ eeprom_read_block(&serno, 0, 4);
+ if (serno == 0xffffffff) {
+ /* If the EEPROM is blank, return a default serial # */
+ serno_str[1] = '1';
+ serno_str[2] = '2';
+ serno_str[3] = '3';
+ serno_str[4] = '4';
+ serno_str[5] = '5';
+ } else {
+ serno_str[1] = hexdigit((serno >> 20) & 0xF);
+ serno_str[2] = hexdigit((serno >> 16) & 0xF);
+ serno_str[3] = hexdigit((serno >> 12) & 0xF);
+ serno_str[4] = hexdigit((serno >> 8) & 0xF);
+ serno_str[5] = hexdigit((serno >> 4) & 0xF);
}
}
{
uchar i;
+ serno = 0;
+ for (i = 0; i < 5; i++) {
+ serno |= digithex(buf[i]);
+ serno <<= 4;
+ }
+
/*
* I have no idea why this gets stored 3 times, but the original
* firmware does it.
*/
- eeprom_write_block(buf, (void *) 0x00, len);
- eeprom_write_block(buf, (void *) 0x40, len);
- eeprom_write_block(buf, (void *) 0x80, len);
+ eeprom_write_block(&serno, (void *) 0x00, 4);
+ eeprom_write_block(&serno, (void *) 0x40, 4);
+ eeprom_write_block(&serno, (void *) 0x80, 4);
- for (i = 0; i < 6; i++) {
- serno[i] = buf[i];
+ for (i = 0; i < 5; i++) {
+ serno_str[i + 1] = buf[i];
}
}
return 0;
}
+usbMsgLen_t usbFunctionDescriptor(usbRequest_t *rq)
+{
+ if (rq->wValue.bytes[1] == USBDESCR_STRING &&
+ rq->wValue.bytes[0] == 3) {
+ usbMsgPtr = (usbMsgPtr_t) serno_str;
+ return sizeof(serno_str);
+ }
+ return 0;
+}
+
uchar usbFunctionRead(uchar *data, uchar len)
{
uchar i;
if (len != 0) {
- fetch_serno();
- for (i = 0; i < 6; i++) {
- data[i] = serno[i];
- }
- data[6] = data[7] = 0;
- if (PORTB & (1 << PB0)) {
- data[7] = 1;
+ for (i = 0; i < 5; i++) {
+ data[i] = serno_str[i + 1];
}
+ data[5] = data[6] = 0;
+ data[7] = state;
return len;
}
uchar usbFunctionWrite(uchar *data, uchar len)
{
if (data[0] == CMD_ALL_ON) {
- cmd = ENER_ADDR | 0xd;
- repeat = 5;
+ cmd = serno | 0xd;
+ state = 0xf;
+ wait = 200;
+ repeat = REPEAT_COUNT;
} else if (data[0] == CMD_ALL_OFF) {
- cmd = ENER_ADDR | 0xc;
- repeat = 5;
+ cmd = serno | 0xc;
+ state = 0;
+ wait = 10;
+ repeat = REPEAT_COUNT;
} else if (data[0] == CMD_ON) {
+ wait = 200;
switch (data[1]) {
case 1:
- cmd = ENER_ADDR | 0xf;
- repeat = 5;
+ cmd = serno | 0xf;
break;
case 2:
- cmd = ENER_ADDR | 0x7;
- repeat = 5;
+ cmd = serno | 0x7;
break;
case 3:
- cmd = ENER_ADDR | 0xb;
- repeat = 5;
+ cmd = serno | 0xb;
break;
case 4:
- cmd = ENER_ADDR | 0x3;
- repeat = 5;
+ cmd = serno | 0x3;
break;
default:
- break;
+ return len;
}
+ repeat = REPEAT_COUNT;
+ state |= (1 << (data[1] - 1));
} else if (data[0] == CMD_OFF) {
+ wait = 200;
switch (data[1]) {
case 1:
- cmd = ENER_ADDR | 0xe;
- repeat = 5;
+ cmd = serno | 0xe;
break;
case 2:
- cmd = ENER_ADDR | 0x6;
- repeat = 5;
+ cmd = serno | 0x6;
break;
case 3:
- cmd = ENER_ADDR | 0xa;
- repeat = 5;
+ cmd = serno | 0xa;
break;
case 4:
- cmd = ENER_ADDR | 0x2;
- repeat = 5;
+ cmd = serno | 0x2;
break;
default:
- break;
+ return len;
}
+ repeat = REPEAT_COUNT;
+ state &= ~(1 << (data[1] - 1));
} else if (data[0] == CMD_SET_SERIAL) {
update_serno(&data[1], 6);
}
wdt_enable(WDTO_1S);
+ fetch_serno();
+
usbInit();
usbDeviceDisconnect();
wdt_reset();
usbPoll();
if (cmd) {
- t433_send(cmd, 24);
- if (--repeat == 0)
- cmd = 0;
+ if (wait) {
+ wait--;
+ } else {
+ t433_send(cmd, 24);
+ if (--repeat == 0)
+ cmd = 0;
+ }
}
}
}