#include "keyboard.h" #include #include #include #include #include #include #include "usbdrv.h" #include "lib/prgKeyboard.h" #include "lib/ws2812.h" // COMMANDS: #define CMD_PING 0 #define CMD_SWVERSION 1 #define CMD_EEWRITE 2 #define CMD_EEREAD 3 #define CMD_EEOPEN 4 // Can be used if errors occour while writing to the device. #define CMD_RESET 5 // WDT RESET #define CMD_SERIAL 6 // DEV-Serial #define CMD_IEEWRITE 7 //internal eeprom #define CMD_IEEREAD 8 // int. eep. #define CMD_SETBLOCK 9 #define CMD_SETLED 10 #define CMD_GETLED 11 #define CMD_SETBRIGHTNESS 12 #define CMD_GETBRIGHTNESS 13 #define IEE_ADDR_DEFAULT_BRIGHTNESS 0 #define IEE_ADDR_DEFAULT_BLOCK 4 #define BLOCKCODE_RERENDER 254 #define BLOCKCODE_RELOAD 253 volatile int change_block = 255; volatile uint8_t brightness = 1; const uint8_t PROGMEM gamma8[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114, 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142, 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175, 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213, 215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 }; const uint8_t PROGMEM gammaBright[] = { 0, 1, 2, 3, 6, 10, 14, 18, 26, 31, 38, 46, 54, 66, 76, 89, 104, 128, 150, 180, 240, 290, 400, 500}; struct cRGB led[LEDS_PER_SLOT]; USB_PUBLIC uchar usbFunctionSetup(uchar data[8]) { usbRequest_t *rq = (void *)data; static uchar reportBuffer[2]; usbMsgPtr = reportBuffer; if(rq->bRequest == CMD_PING) { reportBuffer[0] = rq->wValue.bytes[0]; return 1; } else if(rq->bRequest == CMD_SWVERSION) { reportBuffer[0] = '0'; reportBuffer[1] = '1'; reportBuffer[2] = 'B'; return 3; } else if(rq->bRequest == CMD_EEWRITE) { EEWriteByte(rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8), rq->wIndex.bytes[0]); //reportBuffer[0] = EEReadByte(rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8)); // WE MIGHT HAVE 2 REMOVE THIS BECAUSE OF PERFORMANCE ISSUES -- Reading back too quickly causes an error (-1) reportBuffer[0] = rq->wIndex.bytes[0]; return 1; } else if(rq->bRequest == CMD_EEREAD) { reportBuffer[0] = EEReadByte(rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8)); reportBuffer[1] = EEReadByte(rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8)); // We read twice to ensure the right value was loaded and transmitted. return 2; } else if(rq->bRequest == CMD_EEOPEN) { EEOpen(); reportBuffer[0] = 1; return 1; } else if(rq->bRequest == CMD_RESET) { wdt_enable(WDTO_15MS); // faster reboot while (1); // Wait 'til the watchdog resets our system } else if(rq->bRequest == CMD_IEEWRITE) { eeprom_write_byte(rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8), rq->wIndex.bytes[0]); reportBuffer[0] = eeprom_read_byte(rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8)); // (WE MIGHT HAVE 2 REMOVE THIS BECAUSE OF PERFORMANCE ISSUES) return 1; } else if(rq->bRequest == CMD_IEEREAD) { reportBuffer[0] = eeprom_read_byte(rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8)); reportBuffer[1] = eeprom_read_byte(rq->wValue.bytes[0] + (rq->wValue.bytes[1] << 8)); // Check return 2; } else if (rq->bRequest == CMD_SETBLOCK) { change_block = rq->wValue.bytes[0]; return 0; } else if (rq->bRequest == CMD_SETBRIGHTNESS) { brightness = rq->wValue.bytes[0]; return 0; } else if(rq->bRequest == CMD_GETBRIGHTNESS) { reportBuffer[0] = brightness; return 1; } else if (rq->bRequest == CMD_SETLED) { led[rq->wValue.bytes[0]].r = rq->wValue.bytes[1]; led[rq->wValue.bytes[0]].g = rq->wIndex.bytes[0]; led[rq->wValue.bytes[0]].b = rq->wIndex.bytes[1]; return 0; } else if (rq->bRequest == CMD_GETLED) { reportBuffer[0] = led[rq->wValue.bytes[0]].r; reportBuffer[1] = led[rq->wValue.bytes[0]].g; reportBuffer[2] = led[rq->wValue.bytes[0]].b; return 3; } return 0; } enum enum_state { IDLE = 0, LOAD, PREP_LOAD, RENDER, SLEEP, WAIT_NO_KEY }; void keyboard(void) { enum enum_state state = IDLE; enum enum_state next_state = IDLE; uint8_t i; uint16_t factor = 1; uint8_t key = 0; uint16_t loadAddress; uint16_t loadCount; uint8_t sleepcnt = 0; uint16_t loadAddress_ld = 0; int current_block = 0; LED_PORT |= (1 << LED_RED); LED_PORT |= (1 << LED_GREEN); _delay_ms(500); while (getKey()); wdt_enable(WDTO_2S); EEOpen(); cli(); usbInit(); usbDeviceDisconnect(); i = 0; while(--i){ wdt_reset(); _delay_ms(2); } usbDeviceConnect(); sei(); LED_PORT &= ~(1 << LED_RED); LED_PORT |= (1 << LED_GREEN); brightness = eeprom_read_byte(IEE_ADDR_DEFAULT_BRIGHTNESS); change_block = eeprom_read_byte(IEE_ADDR_DEFAULT_BLOCK); for (;;) { /* main event loop */ wdt_reset(); usbPoll(); key = getKey(); if (key == KEY_MODE) { /* Exit to bootloader */ LED_PORT |= (1 << LED_RED); LED_PORT |= (1 << LED_GREEN); //_delay_ms(100); LED_PORT &= ~(1 << LED_RED); LED_PORT &= ~(1 << LED_GREEN); wdt_enable(WDTO_15MS); while(1); } switch (state) { case IDLE: if (change_block != 255) { if (change_block == BLOCKCODE_RERENDER) { state = RENDER; next_state = IDLE; } else { if (change_block == BLOCKCODE_RELOAD) change_block = current_block; loadAddress_ld = (change_block) * LEDS_PER_SLOT * 3; state = PREP_LOAD; next_state = IDLE; current_block = change_block; } change_block = 255; } else if (key) { if (key > 12) { /* Special key */ switch (key) { case KEY_BRIGHTNESS_UP: brightness = (brightness <= 0 ? 0 : brightness - 1); break; case KEY_BRIGHTNESS_DOWN: brightness = (brightness >= sizeof(gammaBright) - 3 ? /* No idea why -3... */ sizeof(gammaBright) - 3 : brightness + 1); break; case KEY_SF_1: break; case KEY_SF_2: /* Save current as default */ eeprom_write_byte(IEE_ADDR_DEFAULT_BRIGHTNESS, brightness); eeprom_write_byte(IEE_ADDR_DEFAULT_BLOCK, current_block); break; default: break; } state = PREP_LOAD; loadCount = LEDS_PER_SLOT; } else { /* Program key */ loadAddress_ld = (key - 1) * LEDS_PER_SLOT * 3; state = PREP_LOAD; current_block = (key - 1); } sleepcnt = 50; next_state = SLEEP; } break; case PREP_LOAD: loadAddress = loadAddress_ld; loadCount = LEDS_PER_SLOT; state = LOAD; case LOAD: factor = pgm_read_byte(&gammaBright[brightness]); factor = 256 + factor * 25; led[LEDS_PER_SLOT - loadCount].r = EEReadByte(loadAddress++); //led[LEDS_PER_SLOT - loadCount].r = (int)pgm_read_byte(&gamma8[led[LEDS_PER_SLOT - loadCount].r]); led[LEDS_PER_SLOT - loadCount].r = (uint8_t) ((uint16_t) ((uint16_t) ((uint16_t) (led[LEDS_PER_SLOT - loadCount].r) << 8) / factor)); led[LEDS_PER_SLOT - loadCount].g = EEReadByte(loadAddress++); ////led[LEDS_PER_SLOT - loadCount].g = (int)pgm_read_byte(&gamma8[led[LEDS_PER_SLOT - loadCount].g]); led[LEDS_PER_SLOT - loadCount].g = (uint8_t) ((uint16_t) ((uint16_t) ((uint16_t) (led[LEDS_PER_SLOT - loadCount].g) << 8) / factor)); led[LEDS_PER_SLOT - loadCount].b = EEReadByte(loadAddress++); //led[LEDS_PER_SLOT - loadCount].b = (int)pgm_read_byte(&gamma8[led[LEDS_PER_SLOT - loadCount].b]); led[LEDS_PER_SLOT - loadCount].b = (uint8_t) ((uint16_t) ((uint16_t) ((uint16_t) (led[LEDS_PER_SLOT - loadCount].b) << 8) / factor)); if (!--loadCount) { state = RENDER; loadCount = LEDS_PER_SLOT; } break; case RENDER: ws2812_setleds(led, LEDS_PER_SLOT); state = next_state; break; case WAIT_NO_KEY: if (!key) state = IDLE; next_state = IDLE; break; case SLEEP: _delay_ms(2); if (!--sleepcnt) state = IDLE; break; default: break; } } }