Index: aktoserial/code/Makefile
===================================================================
--- aktoserial/code/Makefile	(revision c6e02cf092f860e6c0be10875587235403a35335)
+++ aktoserial/code/Makefile	(revision 08d538895e83f8b0fafc4ad3e3d6cba6fd80341d)
@@ -1,14 +1,22 @@
+#Set vars
+COMPILE = avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=16000000 
+
+#Rules
 keyboard.hex: keyboard.bin
 	avr-objcopy -j .text -j .data -O ihex keyboard.bin keyboard.hex
 
-keyboard.bin: keyboard.o usart.o main.o
-	avr-gcc keyboard.o usart.o main.o -o keyboard.bin -mmcu=atmega8 -Os
+keyboard.bin: keyboard.o main.o usbdrv/usbdrv.o usbdrv/usbdrvasm.o
+	$(COMPILE) keyboard.o main.o usbdrv/usbdrvasm.o usbdrv/usbdrv.o -o keyboard.bin
 
-main.o: main.c ../../libs/usart/usart.h ../../libs/amiga_keyboard/amiga_keyboard.h
-	avr-gcc -c main.c -mmcu=atmega8 -Os -o main.o -mmcu=atmega8 -Os -I../../libs/
-
-usart.o: ../../libs/usart/usart.c ../../libs/usart/usart.h
-	avr-gcc -c ../../libs/usart/usart.c -o usart.o -mmcu=atmega8 -Os
+main.o: main.c ../../libs/amiga_keyboard/amiga_keyboard.h
+	$(COMPILE) -c main.c -mmcu=atmega8 -Os -o main.o -mmcu=atmega8 -Os -I../../libs/ -I.
 
 keyboard.o: ../../libs/amiga_keyboard/amiga_keyboard.c ../../libs/amiga_keyboard/amiga_keyboard.h ../../libs/amiga_keyboard/keymap.h
-	avr-gcc -c ../../libs/amiga_keyboard/amiga_keyboard.c -mmcu=atmega8 -Os -o keyboard.o
+	$(COMPILE) -c ../../libs/amiga_keyboard/amiga_keyboard.c -mmcu=atmega8 -Os -o keyboard.o
+
+#Generic rules
+.S.o:
+	$(COMPILE) -x assembler-with-cpp -c $< -o $@
+
+.c.o:
+	$(COMPILE) -std=c99 -c $< -o $@
Index: aktoserial/code/keyboard.hex
===================================================================
--- aktoserial/code/keyboard.hex	(revision c6e02cf092f860e6c0be10875587235403a35335)
+++ aktoserial/code/keyboard.hex	(revision 08d538895e83f8b0fafc4ad3e3d6cba6fd80341d)
@@ -1,5 +1,5 @@
-:1000000052C061C06AC05FC05EC05DC05CC05BC002
-:100010005AC059C058C057C056C055C054C053C02C
-:1000200052C051C050C06031323334353637383960
+:10000000EFC071C212C107C106C105C104C103C15D
+:1000100002C101C100C1FFC0FEC0FDC0FCC0FBC0E9
+:10002000FAC0F9C0F8C06031323334353637383968
 :10003000302D3D5C3F3071776572747975696F70F2
 :100040005B5D3F3132336173646667686A6B6C3B3A
@@ -9,28 +9,152 @@
 :100080003F3F3F3F3F4853534358414141413F3F2A
 :100090003F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F70
-:1000A0003F3F3F3F3F3F11241FBECFE5D4E0DEBFBF
-:1000B000CDBF10E0A0E6B0E001C01D92A536B107AB
-:1000C000E1F7A3D0B3C09CCF8C9A949884E591E0DB
-:1000D0000197F1F7949A8C9808951F920F920FB69A
-:1000E0000F9211242F933F938F939F9382B390E4A9
-:1000F000892782BB83992CC080916100882339F4C1
-:1001000081E0809361001092630010926200309150
-:100110006300383090F484990DC02091620080E82B
-:1001200090E0032E02C0959587950A94E2F7282B5C
-:10013000209362003F5F30936300809163008830BA
-:1001400038F0109261001092630081E080936400A7
-:100150009F918F913F912F910F900FBE0F901F9005
-:100160001895E82FF0E0EA5DFF4F949180916000D0
-:10017000882311F4892F0895892F80520895809142
-:1001800064008823E1F380B380EA8A95F1F79CDF6D
-:1001900010926400809162000895109261001092A4
-:1001A0006200109263008B98839A85B7886085BF40
-:1001B00085B78B7F85BF8BB780688BBF789484DFD2
-:1001C000089589B990BD86E880BD88E18AB908950F
-:1001D0005D9BFECF8CB908955F9BFECF8CB10895D7
-:1001E000982F92959F709A3010F4905D01C0995CA1
-:1001F0005D9BFECF9CB98F708A3010F4805D01C08A
-:10020000895C5D9BFECF8CB908958E9A83E390E064
-:10021000D8DFC3DF82E5DCDFB2DF982F96958795C4
-:1002200088278795892BDCDF80E2F5CFF894FFCF14
+:1000A0003F3F3F3F3F3F351E1F202122232425266F
+:1000B000272D2E310062141A0815171C180C121364
+:1000C000302F00595A5B041607090A0B0D0E0F3327
+:1000D0003432005C5D5E641D1B0619051110363755
+:1000E0003800635F60612C4C2B5828292A000000DF
+:1000F000560052514F503A3B3C3D3E3F40414243F7
+:10010000838254555775000039000000000000003C
+:1001100000000000000000000000000000000000DF
+:10012000000000000000022000010400088005011A
+:100130000906A101050719E029E715002501750148
+:1001400095088102950175088103950575010508DB
+:10015000190129059102950175039103950675080A
+:10016000150025650507190029658100C0040309EC
+:10017000042403700075006C006B006F006D00615B
+:10018000006E00640079002E006100740068002E8B
+:100190000063007800160341006D0069006B006584
+:1001A0000079003200750073006200120110010036
+:1001B000000008424231E10001010200010902226F
+:1001C000000101008032090400000103010100095F
+:1001D0002101010001223F000705810308000A00F8
+:1001E00011241FBECFE5D4E0DEBFCDBF10E0A0E6F6
+:1001F000B0E0ECEDF9E002C005900D92A436B10735
+:10020000D9F710E0A4E6B0E001C01D92AB3AB10707
+:10021000E1F70FD1E1C3F4CE8C9A949884E591E094
+:100220000197F1F7949A8C9808951F920F920FB648
+:100230000F9211242F933F938F939F9382B390E457
+:10024000892782BB83992CC080917100882339F45F
+:1002500081E08093710010927300109272003091CF
+:100260007300383090F484990DC02091720080E8BA
+:1002700090E0032E02C0959587950A94E2F7282B0B
+:10028000209372003F5F3093730080917300883039
+:1002900038F0109271001092730081E08093740026
+:1002A0009F918F913F912F910F900FBE0F901F90B4
+:1002B0001895E82FF0E0EA5DFF4F9491809170006F
+:1002C000882311F4892F0895892F80520895839BE4
+:1002D000FECF80EA8A95F1F79FDF1092740080913B
+:1002E00072000895809174008823E1F3F0DF08958F
+:1002F0001092710010927200109273008B98839A82
+:1003000085B7886085BF85B78B7F85BF8BB78068D1
+:100310008BBF789481DF0895FC0187E690E090938D
+:10032000900080938F0080818076803271F581818A
+:10033000813011F488E00895893049F486819781ED
+:10034000019719F581E0809364008FEF0895823062
+:1003500019F486E690E013C08A3029F483818093F3
+:10036000660080E00895833031F48381882369F446
+:100370001092600008958B3041F480E690E09093F5
+:10038000900080938F0081E0089580E00895FC0143
+:1003900080916400882329F0613019F48081809372
+:1003A00065001092640081E00895DF93CF93CDB78C
+:1003B000DEB728970FB6F894DEBF0FBECDBF982FDB
+:1003C0008091800084FFFCCFFE01319688E0DF0140
+:1003D0001D928A95E9F799836B83CF0168E0D9D2A2
+:1003E00028960FB6F894DEBF0FBECDBFCF91DF9138
+:1003F000089598E0E7E6F0E0DF011D929A95E9F7AD
+:10040000282F30E0F901EA55FF4F9491805688304B
+:1004100010F020E004C02A533F4FF90124919923A2
+:1004200011F09093690080916700282B209367005A
+:100430000895DF92EF92FF920F931F938FE028E1D0
+:1004400030E00FB6F894A89521BD0FBE81BD85E0C0
+:1004500083BF8E9A69D14CDF789410E080E4D82E67
+:10046000EE24E39401C0102FA8956BD1F090740096
+:100470008091740081112BDF08B600FE0AC0E8BE2F
+:1004800000916600002329F0153030F0012F05504F
+:1004900001C0012FFF2039F38091800084FFE3CF5A
+:1004A0008CE1A7DF87E690E068E073D282B38D2508
+:1004B00082BBD9CFA82FB92F80E090E041E050EA6D
+:1004C000609530E009C02D9182279795879510F0AF
+:1004D00084279527305EC8F36F5FA8F30895EADF9D
+:1004E0008D939D930895CF93CFB7CF93DF93C3950B
+:1004F000859BE9F7859B0BC0859B09C0859B07C041
+:10050000859B05C0859B03C0859B01C08BC06F93F5
+:10051000C0918E00DD27CB56DF4F2F9365E5859B7D
+:1005200003C02F916F91E6CF0F931F934F9320E05D
+:1005300040E15F9300B3047205FB27F93F9350E05D
+:100540003BE039C0147240642F77012F5F5F1EC0FB
+:10055000406810B314722F7752501FC0406400B32C
+:100560002F770472D1F15F5F00C023C0406210B3E7
+:100570002F77147291F15F5F00C025C004721027BD
+:10058000515012F45D5F0000115027952C3F10B3BD
+:10059000C8F614720127015027952C3FC8F6422750
+:1005A000499300B3047210274F73115027952C3FC5
+:1005B000A8F64695469510B3147279F001270150BC
+:1005C00027952C3F98F66B5A60F3315000B3B0F684
+:1005D00000C010E41ABF002719C03B503195C31B5F
+:1005E000D04010E41ABF0881033C09F10B34F9F044
+:1005F00020918C001981110F1213EDCF4A81441FF5
+:10060000093651F10D3211F0013E29F700939300A4
+:100610003F915F914F911F910F912F916F91CAB7A9
+:10062000C6FD65CFDF91CF91CFBFCF9118952091B7
+:100630009300222369F310919100112391F5343036
+:1006400092F13093910020938D0010918E003BE049
+:10065000311B30938E0027C00091910001300CF5C2
+:100660000AE54F7049F43091610034FD1DC00093DC
+:100670006100C5E7D0E01CC03091800034FD14C09B
+:1006800000938000C1E8D0E013C0052710E000C04F
+:10069000000002BB1AC0052710E0221F1DC010E099
+:1006A00021C04AE502C032ED432FC4E1D0E032E080
+:1006B00011B31462959A02B311BB54E220E865E3CA
+:1006C00020FF052702BB279517951C3FF0F666957E
+:1006D000B8F7B1F720FF052702BB279517951C3FF8
+:1006E000D0F62795179517FF052700001C3F02BB82
+:1006F000B0F629913A9519F70B7D10919200110FE0
+:10070000C651D04002BB11F010938C0010E41ABF08
+:10071000006211B31B7D402F4B7D54E05A95F1F7D9
+:1007200002BB11BB42BB74CF85B7836085BF8BB75B
+:1007300080648BBF8BE4809381008AE58093800086
+:1007400008951F93CF93DF9360919100635067FDED
+:10075000C4C080918E00CCE0D0E0C81BD109CB563C
+:10076000DF4F80918D008D3209F0A4C0683009F010
+:10077000B2C083EC809375008AE58093610010928B
+:100780006F008881807641F0CE010E948C01282F75
+:100790008F3F09F47EC084C09A8110927E008981C7
+:1007A000882321F410927F0022E06CC0853019F478
+:1007B0009093920066C0863009F04FC08B818130E3
+:1007C00041F48BEA91E09093900080938F0022E1B6
+:1007D00040C0823041F48DEB91E090939000809383
+:1007E0008F0022E236C08330F9F48A81882341F4F5
+:1007F0008DE691E09093900080938F0024E029C0D3
+:10080000813041F481E791E09093900080938F00D4
+:1008100024E21FC08230E1F485E991E090939000DA
+:1008200080938F0026E115C0813241F48FEC91E076
+:100830009093900080938F0029E00BC0823241F4A6
+:100840008EE291E09093900080938F002FE301C09F
+:1008500020E080E480936F0023C0883021F421E001
+:1008600084E990E011C0893019F49093940009C094
+:100870008A3011F421E006C08B3019F48BE48093A8
+:10088000810020E08EE790E09093900080938F00AD
+:1008900007C0888187FD2E8180E880936F0006C0A5
+:1008A0008F81882319F48E81821708F0822F80931C
+:1008B000620011C080916F0087FF0DC0CE010E94C1
+:1008C000C7018F3F21F48EE18093610004C088232B
+:1008D00011F010926200109291008091610084FFEB
+:1008E0004AC0809162008F3F09F445C0182F8930BB
+:1008F00008F018E0811B809362008091750098E8F1
+:10090000892780937500112341F120918F00309148
+:10091000900080916F0086FF0DC0A6E7B0E080E0F8
+:1009200090E0F901E80FF91FE491ED930196181793
+:10093000C1F708C0912FD901E6E7F0E08D918193CE
+:100940009150E1F71150812F90E01F5F0196820FC7
+:10095000931F9093900080938F0086E790E0612F23
+:100960000E946F02612F6C5F6C3019F08FEF8093E3
+:1009700062006093610094E180B3847231F491501D
+:10098000D9F71092920010928C00DF91CF911F91B5
+:1009900008951F93DC01162F8091800084FF07C00B
+:1009A0008091810098E889278093810003C08AE5BF
+:1009B00080938000912FE2E8F0E08D918193915037
+:1009C0001916DCF382E890E0612F0E946F021C5F31
+:0C09D000109380001F910895F894FFCF51
+:0409DC00015AFF00BD
 :00000001FF
Index: aktoserial/code/keycodes.h
===================================================================
--- aktoserial/code/keycodes.h	(revision 08d538895e83f8b0fafc4ad3e3d6cba6fd80341d)
+++ aktoserial/code/keycodes.h	(revision 08d538895e83f8b0fafc4ad3e3d6cba6fd80341d)
@@ -0,0 +1,141 @@
+/**
+ * \file firmware/keycodes.h
+ * \brief This file contains modifier- and keycode definitions according to the
+ * USB-specifications for human interface devices.
+ *
+ * See usb.org's HID-usage-tables document, chapter 10 Keyboard/Keypad Page for
+ * more codes: http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
+ * \author Ronald Schaten <ronald@schatenseite.de>
+ * \version $Id: keycodes.h,v 1.1 2008-07-09 20:47:12 rschaten Exp $
+ *
+ * License: GNU GPL v2 (see License.txt)
+ */
+
+#ifndef __keycodes_h_included__
+#define __keycodes_h_included__
+
+/// Codes for modifier-keys.
+enum modifiers {
+    MOD_NONE          = 0,
+    MOD_CONTROL_LEFT  = (1 << 0),
+    MOD_SHIFT_LEFT    = (1 << 1),
+    MOD_ALT_LEFT      = (1 << 2),
+    MOD_GUI_LEFT      = (1 << 3),
+    MOD_CONTROL_RIGHT = (1 << 4),
+    MOD_SHIFT_RIGHT   = (1 << 5),
+    MOD_ALT_RIGHT     = (1 << 6),
+    MOD_GUI_RIGHT     = (1 << 7),
+};
+
+/// Codes for non-modifier-keys.
+enum keycodes {
+    KEY_Reserved = 0,     // unused
+    KEY_ErrorRollOver,
+    KEY_POSTFail,
+    KEY_ErrorUndefined,
+    KEY_A,                // 0x04
+    KEY_B,
+    KEY_C,
+    KEY_D,
+    KEY_E,
+    KEY_F,
+    KEY_G,
+    KEY_H,
+    KEY_I,
+    KEY_J,
+    KEY_K,
+    KEY_L,
+    KEY_M,                // 0x10
+    KEY_N,
+    KEY_O,
+    KEY_P,
+    KEY_Q,
+    KEY_R,
+    KEY_S,
+    KEY_T,
+    KEY_U,
+    KEY_V,
+    KEY_W,
+    KEY_X,
+    KEY_Y,
+    KEY_Z,
+    KEY_1,                //       1 and !
+    KEY_2,                //       2 and @
+    KEY_3,                // 0x20  3 and #
+    KEY_4,                //       4 and $
+    KEY_5,                //       5 and %
+    KEY_6,                //       6 and ^
+    KEY_7,                //       7 and &
+    KEY_8,                //       8 and *
+    KEY_9,                //       9 and (
+    KEY_0,                // 0x27  0 and )
+    KEY_Return,           // 0x28  enter
+    KEY_ESCAPE,           // 0x29
+    KEY_DELETE,           // 0x2A  backspace
+    KEY_Tab,              // 0x2B
+    KEY_Spacebar,         // 0x2C
+    KEY_minus,            // 0x2D  - and _
+    KEY_equals,           // 0x2E  = and +
+    KEY_lbracket,         // 0x2F  [ and {
+    KEY_rbracket,         // 0x30  ] and }
+    KEY_backslash,        // 0x31  \ and |
+    KEY_hash,             // 0x32  non-US # and ~
+    KEY_semicolon,        // 0x33  ; and :
+    KEY_apostroph,        // 0x34  ' and "
+    KEY_grave,            // 0x35  grave accent and tilde
+    KEY_comma,            // 0x36  , and <
+    KEY_dot,              // 0x37  . and >
+    KEY_slash,            // 0x38  / and ?
+    KEY_capslock,         // 0x39
+    KEY_F1,
+    KEY_F2,
+    KEY_F3,
+    KEY_F4,
+    KEY_F5,
+    KEY_F6,
+    KEY_F7,               // 0x40
+    KEY_F8,
+    KEY_F9,
+    KEY_F10,
+    KEY_F11,
+    KEY_F12,
+    KEY_PrintScreen,
+    KEY_ScrollLock,
+    KEY_Pause,            //       Break
+    KEY_Insert,
+    KEY_Home,
+    KEY_PageUp,
+    KEY_DeleteForward,
+    KEY_End,
+    KEY_PageDown,
+    KEY_RightArrow,
+    KEY_LeftArrow,        // 0x50
+    KEY_DownArrow,
+    KEY_UpArrow,
+    KEY_NumLock,          //       Clear
+    KEY_KPslash,
+    KEY_KPasterisk,
+    KEY_KPminus,
+    KEY_KPplus,
+    KEY_KPenter,
+    KEY_KP1,              //       End
+    KEY_KP2,              //       Down Arrow
+    KEY_KP3,              //       Page Down
+    KEY_KP4,              //       Left Arrow
+    KEY_KP5,
+    KEY_KP6,              //       Right Arrow
+    KEY_KP7,              //       Home
+    KEY_KP8,              // 0x60  Up Arrow
+    KEY_KP9,              //       Page Up
+    KEY_KP0,              //       Insert
+    KEY_KPcomma,          //       Delete
+    KEY_Euro,             //       non-US \ and |
+    KEY_Application,
+
+	KEY_Help = 0x75,
+	KEY_KPLParen = 0x182,
+   KEY_KPRParen = 0x183,	
+};
+
+#endif /* __keycodes_h_included__ */
+
Index: aktoserial/code/main.c
===================================================================
--- aktoserial/code/main.c	(revision c6e02cf092f860e6c0be10875587235403a35335)
+++ aktoserial/code/main.c	(revision 08d538895e83f8b0fafc4ad3e3d6cba6fd80341d)
@@ -1,29 +1,234 @@
-#define F_CPU 16000000UL
-
 #include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/pgmspace.h>
+#include <util/delay.h>
+
+#include <string.h>
 
 #include "amiga_keyboard/amiga_keyboard.h"
-#include "usart/usart.h"
+#include "usbdrv/usbdrv.h"
+#include "keycodes.h"
+
+const uint8_t PROGMEM keymatrix[128] = {
+// 0         1                 2            3            4          5          6           7            8            9              A             B             C             D             E              F
+KEY_grave,   KEY_1,            KEY_2,       KEY_3,       KEY_4,     KEY_5,     KEY_6,      KEY_7,       KEY_8,       KEY_9,         KEY_0,        KEY_minus,    KEY_equals,   KEY_backslash, KEY_Reserved,  KEY_KP0,      //0
+KEY_Q,       KEY_W,            KEY_E,       KEY_R,       KEY_T,     KEY_Y,     KEY_U,      KEY_I,       KEY_O,       KEY_P,         KEY_rbracket, KEY_lbracket, KEY_Reserved, KEY_KP1,       KEY_KP2,       KEY_KP3,      //1
+KEY_A,       KEY_S,            KEY_D,       KEY_F,       KEY_G,     KEY_H,     KEY_J,      KEY_K,       KEY_L,       KEY_semicolon, KEY_apostroph,KEY_hash,     KEY_Reserved, KEY_KP4,       KEY_KP5,       KEY_KP6,      //2
+KEY_Euro,    KEY_Z,            KEY_X,       KEY_C,       KEY_V,     KEY_B,     KEY_N,      KEY_M,       KEY_comma,   KEY_dot,       KEY_slash,    KEY_Reserved, KEY_KPcomma,  KEY_KP7,       KEY_KP8,       KEY_KP9,      //3
+KEY_Spacebar,KEY_DeleteForward,KEY_Tab,     KEY_KPenter, KEY_Return,KEY_ESCAPE,KEY_DELETE, KEY_Reserved,KEY_Reserved,KEY_Reserved,  KEY_KPminus,  KEY_Reserved, KEY_UpArrow,  KEY_DownArrow, KEY_RightArrow,KEY_LeftArrow,//4
+KEY_F1,      KEY_F2,           KEY_F3,      KEY_F4,      KEY_F5,    KEY_F6,    KEY_F7,     KEY_F8,      KEY_F9,      KEY_F10,       KEY_KPRParen, KEY_KPLParen, KEY_KPslash,  KEY_KPasterisk,KEY_KPplus,    KEY_Help,     //5
+KEY_Reserved,KEY_Reserved,     KEY_capslock,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,  KEY_Reserved,  KEY_Reserved, //6
+KEY_Reserved,KEY_Reserved,     KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,KEY_Reserved,  KEY_Reserved,  KEY_Reserved, //7
+};
+
+/**
+ * The modmatrix-array contains positions of the modifier-keys in the matrix.
+ * It is built in the same way as the keymatrix-array.
+ * \sa keymatrix
+ */
+const uint8_t PROGMEM modmatrix[8] = { // contains positions of modifiers in the matrix
+  // 0             1               2                 3         4         5         6                  7
+MOD_SHIFT_LEFT,MOD_SHIFT_RIGHT,MOD_NONE,MOD_CONTROL_LEFT,MOD_ALT_LEFT,MOD_NONE, MOD_GUI_LEFT, MOD_GUI_RIGHT,
+};
+
+static uint8_t idleRate;
+static uint8_t reportBuffer[8]; 
+
+void fillReportBuffer(uint8_t key_code) {
+	uint8_t key, modifier;
+	uint8_t reportIndex = 2; // reportBuffer[0] contains modifiers
+	memset(reportBuffer, 0, sizeof(reportBuffer)); // clear report buffer
+	key = pgm_read_byte(&keymatrix[key_code]);
+	if (key_code >= 0x60 && key_code < 0x68)
+		modifier = pgm_read_byte(&modmatrix[key_code - 0x60]);
+	else
+		modifier = MOD_NONE;
+	if (key != KEY_Reserved) {
+		reportBuffer[reportIndex] = key; // set next available entry
+		reportIndex++;
+	}
+	reportBuffer[0] |= modifier;
+}
+
+
+void usbSendReport(uint8_t mode, uint8_t key) {
+    // buffer for HID reports. we use a private one, so nobody gets disturbed
+    uint8_t repBuffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+    repBuffer[0] = mode;
+    repBuffer[2] = key;
+    while (!usbInterruptIsReady()); // wait
+    usbSetInterrupt(repBuffer, sizeof(repBuffer)); // send
+}
+
 
 int main() {
-  //debug LED - output
-  DDRD |= (1<<PD6);
-
-  USARTInit(51);
-  ak_init_keyboard(); 
-
-  uint8_t key_code = 0;
-
-  // Ready!
-  USARTWriteChar('R');
-
-  while(1) {
-	key_code = ak_read_scancode();
-    //USARTWriteChar(ak_scancode_to_ascii(key_code));
-	USARTWriteHex((key_code >> 1) |(key_code << 7));
-	USARTWriteChar(' ');
-  }
-  
-  return 0;
-}
-
+	uint8_t idleCounter = 0;
+    uint8_t updateNeeded = 0;
+
+	wdt_enable(WDTO_2S);
+    // configure timer 0 for a rate of 12M/(1024 * 256) = 45.78Hz (~22ms)
+    TCCR0 = 5;          // timer 0 prescaler: 1024
+
+	//debug LED - output
+	DDRD |= (1<<PD6);
+
+	// Keyboard
+	uint8_t key_code = 0;
+
+	// USB
+	usbInit();
+	ak_init_keyboard(); 
+	sei();
+
+	while(1) {
+		wdt_reset();
+		usbPoll();
+
+		updateNeeded = char_waiting;
+
+		if (char_waiting) {
+			key_code = ak_read_scancode();
+		}
+
+		// check timer if we need periodic reports
+		if (TIFR & (1 << TOV0)) {
+			TIFR = (1 << TOV0); // reset flag
+			if (idleRate != 0) { // do we need periodic reports?
+				if(idleCounter > 4){ // yes, but not yet
+					idleCounter -= 5; // 22ms in units of 4ms
+				} else { // yes, it is time now
+					updateNeeded = 1;
+					idleCounter = idleRate;
+				}
+			}
+
+		}
+		// if an update is needed, send the report
+		if (updateNeeded && usbInterruptIsReady()) {
+			updateNeeded = 0;
+			//fillReportBuffer(key_code);
+			fillReportBuffer(KEY_Y);
+			usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
+			PORTD ^= (1<<PD6);
+		}
+	}
+
+	return 0;
+}
+
+static uint8_t protocolVer = 1;
+uint8_t expectReport = 0;
+
+#define LED_NUM     0x01  ///< num LED on a boot-protocol keyboard
+#define LED_CAPS    0x02  ///< caps LED on a boot-protocol keyboard
+#define LED_SCROLL  0x04  ///< scroll LED on a boot-protocol keyboard
+#define LED_COMPOSE 0x08  ///< compose LED on a boot-protocol keyboard
+#define LED_KANA    0x10  ///< kana LED on a boot-protocol keyboard
+uint8_t LEDstate = 0;     ///< current state of the LEDs
+
+
+char PROGMEM usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
+	0x05, 0x01,   // USAGE_PAGE (Generic Desktop)
+	0x09, 0x06,   // USAGE (Keyboard)
+	0xa1, 0x01,   // COLLECTION (Application)
+	0x05, 0x07,   //   USAGE_PAGE (Keyboard)
+	0x19, 0xe0,   //   USAGE_MINIMUM (Keyboard LeftControl)
+	0x29, 0xe7,   //   USAGE_MAXIMUM (Keyboard Right GUI)
+	0x15, 0x00,   //   LOGICAL_MINIMUM (0)
+	0x25, 0x01,   //   LOGICAL_MAXIMUM (1)
+	0x75, 0x01,   //   REPORT_SIZE (1)
+	0x95, 0x08,   //   REPORT_COUNT (8)
+	0x81, 0x02,   //   INPUT (Data,Var,Abs)
+	0x95, 0x01,   //   REPORT_COUNT (1)
+	0x75, 0x08,   //   REPORT_SIZE (8)
+	0x81, 0x03,   //   INPUT (Cnst,Var,Abs)
+	0x95, 0x05,   //   REPORT_COUNT (5)
+	0x75, 0x01,   //   REPORT_SIZE (1)
+	0x05, 0x08,   //   USAGE_PAGE (LEDs)
+	0x19, 0x01,   //   USAGE_MINIMUM (Num Lock)
+	0x29, 0x05,   //   USAGE_MAXIMUM (Kana)
+	0x91, 0x02,   //   OUTPUT (Data,Var,Abs)
+	0x95, 0x01,   //   REPORT_COUNT (1)
+	0x75, 0x03,   //   REPORT_SIZE (3)
+	0x91, 0x03,   //   OUTPUT (Cnst,Var,Abs)
+	0x95, 0x06,   //   REPORT_COUNT (6)
+	0x75, 0x08,   //   REPORT_SIZE (8)
+	0x15, 0x00,   //   LOGICAL_MINIMUM (0)
+	0x25, 0x65,   //   LOGICAL_MAXIMUM (101)
+	0x05, 0x07,   //   USAGE_PAGE (Keyboard)
+	0x19, 0x00,   //   USAGE_MINIMUM (Reserved (no event indicated))
+	0x29, 0x65,   //   USAGE_MAXIMUM (Keyboard Application)
+	0x81, 0x00,   //   INPUT (Data,Ary,Abs)
+	0xc0          // END_COLLECTION
+};
+
+
+
+
+uint8_t usbFunctionSetup(uint8_t data[8]) {
+    usbRequest_t *rq = (void *)data;
+    usbMsgPtr = reportBuffer;
+    if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
+        // class request type
+        if (rq->bRequest == USBRQ_HID_GET_REPORT) {
+            // wValue: ReportType (highbyte), ReportID (lowbyte)
+            // we only have one report type, so don't look at wValue
+            return sizeof(reportBuffer);
+        } else if (rq->bRequest == USBRQ_HID_SET_REPORT) {
+            if (rq->wLength.word == 1) {
+                // We expect one byte reports
+                expectReport = 1;
+                return 0xff; // Call usbFunctionWrite with data
+            }
+        } else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
+            usbMsgPtr = &idleRate;
+            return 1;
+        } else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
+            idleRate = rq->wValue.bytes[1];
+        } else if (rq->bRequest == USBRQ_HID_GET_PROTOCOL) {
+            if (rq->wValue.bytes[1] < 1) {
+                protocolVer = rq->wValue.bytes[1];
+            }
+        } else if(rq->bRequest == USBRQ_HID_SET_PROTOCOL) {
+            usbMsgPtr = &protocolVer;
+            return 1;
+        }
+    } else {
+        // no vendor specific requests implemented
+    }
+    return 0;
+}
+
+/**
+ * The write function is called when LEDs should be set. Normally, we get only
+ * one byte that contains info about the LED states.
+ * \param data pointer to received data
+ * \param len number ob bytes received
+ * \return 0x01
+ */
+uint8_t usbFunctionWrite(uchar *data, uchar len) {
+    if (expectReport && (len == 1)) {
+        LEDstate = data[0]; // Get the state of all 5 LEDs
+		/* TODO
+        if (LEDstate & LED_NUM) { // light up caps lock
+            PORTLEDS &= ~(1 << LEDNUM);
+        } else {
+            PORTLEDS |= (1 << LEDNUM);
+        }
+        if (LEDstate & LED_CAPS) { // light up caps lock
+            PORTLEDS &= ~(1 << LEDCAPS);
+        } else {
+            PORTLEDS |= (1 << LEDCAPS);
+        }
+        if (LEDstate & LED_SCROLL) { // light up caps lock
+            PORTLEDS &= ~(1 << LEDSCROLL);
+        } else {
+            PORTLEDS |= (1 << LEDSCROLL);
+        }
+		*/
+    }
+    expectReport = 0;
+    return 0x01;
+}
+
