2017-04-15 18:00:15 +02:00
# include "keyboard.h"
# include <avr/io.h>
# include <avr/wdt.h>
# include <util/delay.h>
# include <avr/pgmspace.h>
# include <avr/interrupt.h>
# include <avr/eeprom.h>
# 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
2017-04-23 20:24:44 +02:00
# define CMD_GETLED 11
2017-04-23 20:12:21 +02:00
# define CMD_SETBRIGHTNESS 12
# define CMD_GETBRIGHTNESS 13
2017-04-15 18:00:15 +02:00
2017-04-23 18:22:27 +02:00
# define IEE_ADDR_DEFAULT_BRIGHTNESS 0
# define IEE_ADDR_DEFAULT_BLOCK 4
2017-04-23 20:12:21 +02:00
# define BLOCKCODE_RERENDER 254
# define BLOCKCODE_RELOAD 253
2017-04-15 18:00:15 +02:00
volatile int change_block = 255 ;
2017-04-23 20:12:21 +02:00
volatile uint8_t brightness = 1 ;
2017-04-15 18:00:15 +02:00
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 } ;
2017-04-23 19:12:44 +02:00
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 ,
2017-04-23 20:03:26 +02:00
290 , 400 , 500 } ;
2017-04-23 19:12:44 +02:00
2017-04-15 18:00:15 +02:00
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 ;
}
2017-04-23 20:12:21 +02:00
else if ( rq - > bRequest = = CMD_SETBRIGHTNESS ) {
brightness = rq - > wValue . bytes [ 0 ] ;
return 0 ;
}
else if ( rq - > bRequest = = CMD_GETBRIGHTNESS ) {
reportBuffer [ 0 ] = brightness ;
return 1 ;
}
2017-04-15 18:00:15 +02:00
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 ;
}
2017-04-23 20:24:44 +02:00
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 ;
}
2017-04-15 18:00:15 +02:00
return 0 ;
}
enum enum_state {
IDLE = 0 ,
LOAD ,
PREP_LOAD ,
RENDER ,
SLEEP ,
WAIT_NO_KEY
} ;
void keyboard ( void ) {
2017-04-23 18:22:27 +02:00
enum enum_state state = IDLE ;
2017-04-15 18:00:15 +02:00
enum enum_state next_state = IDLE ;
uint8_t i ;
2017-04-23 19:12:44 +02:00
uint16_t factor = 1 ;
2017-04-15 18:00:15 +02:00
uint8_t key = 0 ;
uint16_t loadAddress ;
uint16_t loadCount ;
uint8_t sleepcnt = 0 ;
uint16_t loadAddress_ld = 0 ;
2017-04-23 18:22:27 +02:00
int current_block = 0 ;
2017-04-15 18:00:15 +02:00
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 ) ;
2017-04-23 19:12:44 +02:00
brightness = eeprom_read_byte ( IEE_ADDR_DEFAULT_BRIGHTNESS ) ;
2017-04-23 18:22:27 +02:00
change_block = eeprom_read_byte ( IEE_ADDR_DEFAULT_BLOCK ) ;
2017-04-15 18:00:15 +02:00
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 ) {
2017-04-23 20:12:21 +02:00
if ( change_block = = BLOCKCODE_RERENDER ) {
2017-04-15 18:00:15 +02:00
state = RENDER ;
next_state = IDLE ;
} else {
2017-04-23 20:34:45 +02:00
if ( change_block = = BLOCKCODE_RELOAD )
2017-04-23 20:12:21 +02:00
change_block = current_block ;
2017-04-15 18:00:15 +02:00
loadAddress_ld = ( change_block ) * LEDS_PER_SLOT * 3 ;
state = PREP_LOAD ;
next_state = IDLE ;
2017-04-23 18:22:27 +02:00
current_block = change_block ;
2017-04-15 18:00:15 +02:00
}
change_block = 255 ;
} else if ( key ) {
if ( key > 12 ) { /* Special key */
switch ( key ) {
case KEY_BRIGHTNESS_UP :
2017-04-23 19:12:44 +02:00
brightness = ( brightness < = 0 ? 0 : brightness - 1 ) ;
2017-04-15 18:00:15 +02:00
break ;
case KEY_BRIGHTNESS_DOWN :
2017-04-23 20:03:26 +02:00
brightness = ( brightness > = sizeof ( gammaBright ) - 3 ? /* No idea why -3... */
sizeof ( gammaBright ) - 3 : brightness + 1 ) ;
2017-04-15 18:00:15 +02:00
break ;
case KEY_SF_1 :
break ;
2017-04-23 18:22:27 +02:00
case KEY_SF_2 : /* Save current as default */
2017-04-23 19:12:44 +02:00
eeprom_write_byte ( IEE_ADDR_DEFAULT_BRIGHTNESS , brightness ) ;
2017-04-23 18:22:27 +02:00
eeprom_write_byte ( IEE_ADDR_DEFAULT_BLOCK , current_block ) ;
2017-04-15 18:00:15 +02:00
break ;
default :
break ;
}
state = PREP_LOAD ;
loadCount = LEDS_PER_SLOT ;
} else { /* Program key */
loadAddress_ld = ( key - 1 ) * LEDS_PER_SLOT * 3 ;
state = PREP_LOAD ;
2017-04-23 18:22:27 +02:00
current_block = ( key - 1 ) ;
2017-04-15 18:00:15 +02:00
}
sleepcnt = 50 ;
next_state = SLEEP ;
}
break ;
case PREP_LOAD :
loadAddress = loadAddress_ld ;
loadCount = LEDS_PER_SLOT ;
state = LOAD ;
case LOAD :
2017-04-23 19:12:44 +02:00
factor = pgm_read_byte ( & gammaBright [ brightness ] ) ;
factor = 256 + factor * 25 ;
2017-04-15 18:00:15 +02:00
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]);
2017-04-23 19:12:44 +02:00
led [ LEDS_PER_SLOT - loadCount ] . r = ( uint8_t ) ( ( uint16_t ) ( ( uint16_t ) ( ( uint16_t ) ( led [ LEDS_PER_SLOT - loadCount ] . r ) < < 8 ) / factor ) ) ;
2017-04-15 18:00:15 +02:00
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]);
2017-04-23 19:12:44 +02:00
led [ LEDS_PER_SLOT - loadCount ] . g = ( uint8_t ) ( ( uint16_t ) ( ( uint16_t ) ( ( uint16_t ) ( led [ LEDS_PER_SLOT - loadCount ] . g ) < < 8 ) / factor ) ) ;
2017-04-15 18:00:15 +02:00
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]);
2017-04-23 19:12:44 +02:00
led [ LEDS_PER_SLOT - loadCount ] . b = ( uint8_t ) ( ( uint16_t ) ( ( uint16_t ) ( ( uint16_t ) ( led [ LEDS_PER_SLOT - loadCount ] . b ) < < 8 ) / factor ) ) ;
2017-04-15 18:00:15 +02:00
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 ;
}
}
}