Index: kbd/pcw2hid/code/Descriptors.c
===================================================================
--- kbd/pcw2hid/code/Descriptors.c	(revision a6ad6e8eb20b68578c16ed8d6a7098470d4d86ea)
+++ kbd/pcw2hid/code/Descriptors.c	(revision 110c6922461234282a264edb8a3c8349f2c610d7)
@@ -111,205 +111,4 @@
 				HID_RI_END_COLLECTION(0),
 
-			HID_RI_END_COLLECTION(0),
-
-			HID_RI_USAGE_PAGE(8, 0x01),
-			HID_RI_USAGE(8, 0x04),
-			HID_RI_COLLECTION(8, 0x01),
-
-				0x85, 0x02, // Report ID 2
-
-				// 15 constant bytes
-				HID_RI_REPORT_SIZE(8, 15),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE_PAGE(8, 0x09),
-				HID_RI_LOGICAL_MINIMUM(8, 0x00),
-				HID_RI_LOGICAL_MAXIMUM(8, 0x01),
-
-				HID_RI_USAGE_MINIMUM(8, 7),
-				HID_RI_USAGE_MAXIMUM(8, 9),
-				HID_RI_USAGE(8, 4),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 4),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_REPORT_SIZE(8, 1),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE(8, 10),
-				HID_RI_USAGE_MINIMUM(8, 1),
-				HID_RI_USAGE_MAXIMUM(8, 3),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 4),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_REPORT_SIZE(8, 1),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE_MINIMUM(8, 5),
-				HID_RI_USAGE_MAXIMUM(8, 6),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 2),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_USAGE_PAGE(8, 0x01),
-				HID_RI_USAGE(8, 0x01),
-				HID_RI_COLLECTION(8, 0x00),
-					HID_RI_USAGE(8, 0x31),
-					HID_RI_LOGICAL_MINIMUM(8, -2),
-					HID_RI_LOGICAL_MAXIMUM(8, 1),
-					HID_RI_REPORT_COUNT(8, 1),
-					HID_RI_REPORT_SIZE(8, 2),
-					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-					HID_RI_REPORT_SIZE(8, 1),
-					HID_RI_REPORT_COUNT(8, 0x01),
-					HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-					HID_RI_USAGE(8, 0x30),
-					HID_RI_LOGICAL_MINIMUM(8, -2),
-					HID_RI_LOGICAL_MAXIMUM(8, 1),
-					HID_RI_REPORT_COUNT(8, 1),
-					HID_RI_REPORT_SIZE(8, 2),
-					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-				HID_RI_END_COLLECTION(0),
-
-			HID_RI_END_COLLECTION(0),
-
-			HID_RI_USAGE_PAGE(8, 0x01),
-			HID_RI_USAGE(8, 0x04),
-			HID_RI_COLLECTION(8, 0x01),
-
-				0x85, 0x03, // Report ID 3
-
-				// 15 constant bytes
-				HID_RI_REPORT_SIZE(8, 15),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE_PAGE(8, 0x09),
-				HID_RI_LOGICAL_MINIMUM(8, 0x00),
-				HID_RI_LOGICAL_MAXIMUM(8, 0x01),
-
-				HID_RI_USAGE_MINIMUM(8, 7),
-				HID_RI_USAGE_MAXIMUM(8, 9),
-				HID_RI_USAGE(8, 4),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 4),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_REPORT_SIZE(8, 1),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE(8, 10),
-				HID_RI_USAGE_MINIMUM(8, 1),
-				HID_RI_USAGE_MAXIMUM(8, 3),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 4),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_REPORT_SIZE(8, 1),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE_MINIMUM(8, 5),
-				HID_RI_USAGE_MAXIMUM(8, 6),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 2),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_USAGE_PAGE(8, 0x01),
-				HID_RI_USAGE(8, 0x01),
-				HID_RI_COLLECTION(8, 0x00),
-					HID_RI_USAGE(8, 0x31),
-					HID_RI_LOGICAL_MINIMUM(8, -2),
-					HID_RI_LOGICAL_MAXIMUM(8, 1),
-					HID_RI_REPORT_COUNT(8, 1),
-					HID_RI_REPORT_SIZE(8, 2),
-					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-					HID_RI_REPORT_SIZE(8, 1),
-					HID_RI_REPORT_COUNT(8, 0x01),
-					HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-					HID_RI_USAGE(8, 0x30),
-					HID_RI_LOGICAL_MINIMUM(8, -2),
-					HID_RI_LOGICAL_MAXIMUM(8, 1),
-					HID_RI_REPORT_COUNT(8, 1),
-					HID_RI_REPORT_SIZE(8, 2),
-					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-				HID_RI_END_COLLECTION(0),
-
-			HID_RI_END_COLLECTION(0),
-
-			HID_RI_USAGE_PAGE(8, 0x01),
-			HID_RI_USAGE(8, 0x04),
-			HID_RI_COLLECTION(8, 0x01),
-
-				0x85, 0x04, // Report ID 4
-
-				// 15 constant bytes
-				HID_RI_REPORT_SIZE(8, 15),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE_PAGE(8, 0x09),
-				HID_RI_LOGICAL_MINIMUM(8, 0x00),
-				HID_RI_LOGICAL_MAXIMUM(8, 0x01),
-
-				HID_RI_USAGE_MINIMUM(8, 7),
-				HID_RI_USAGE_MAXIMUM(8, 9),
-				HID_RI_USAGE(8, 4),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 4),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_REPORT_SIZE(8, 1),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE(8, 10),
-				HID_RI_USAGE_MINIMUM(8, 1),
-				HID_RI_USAGE_MAXIMUM(8, 3),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 4),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_REPORT_SIZE(8, 1),
-				HID_RI_REPORT_COUNT(8, 0x01),
-				HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-				HID_RI_USAGE_MINIMUM(8, 5),
-				HID_RI_USAGE_MAXIMUM(8, 6),
-				HID_RI_REPORT_SIZE(8, 0x01),
-				HID_RI_REPORT_COUNT(8, 2),
-				HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-				HID_RI_USAGE_PAGE(8, 0x01),
-				HID_RI_USAGE(8, 0x01),
-				HID_RI_COLLECTION(8, 0x00),
-					HID_RI_USAGE(8, 0x31),
-					HID_RI_LOGICAL_MINIMUM(8, -2),
-					HID_RI_LOGICAL_MAXIMUM(8, 1),
-					HID_RI_REPORT_COUNT(8, 1),
-					HID_RI_REPORT_SIZE(8, 2),
-					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-
-					HID_RI_REPORT_SIZE(8, 1),
-					HID_RI_REPORT_COUNT(8, 0x01),
-					HID_RI_INPUT(8, HID_IOF_CONSTANT),
-
-					HID_RI_USAGE(8, 0x30),
-					HID_RI_LOGICAL_MINIMUM(8, -2),
-					HID_RI_LOGICAL_MAXIMUM(8, 1),
-					HID_RI_REPORT_COUNT(8, 1),
-					HID_RI_REPORT_SIZE(8, 2),
-					HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
-				HID_RI_END_COLLECTION(0),
-
 			HID_RI_END_COLLECTION(0)
 };
@@ -418,5 +217,5 @@
  *  Descriptor.
  */
-const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"Gravis GrIP gamepads");
+const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"Amstrad PCW Keyboard");
 
 /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
Index: kbd/pcw2hid/code/Descriptors.h
===================================================================
--- kbd/pcw2hid/code/Descriptors.h	(revision a6ad6e8eb20b68578c16ed8d6a7098470d4d86ea)
+++ kbd/pcw2hid/code/Descriptors.h	(revision 110c6922461234282a264edb8a3c8349f2c610d7)
@@ -82,5 +82,5 @@
 
 		/** Size in bytes of the Joystick HID reporting IN endpoint. */
-		#define JOYSTICK_EPSIZE              8
+		#define JOYSTICK_EPSIZE              16
 
 	/* Function Prototypes: */
Index: d/pcw2hid/code/Joystick.c
===================================================================
--- kbd/pcw2hid/code/Joystick.c	(revision a6ad6e8eb20b68578c16ed8d6a7098470d4d86ea)
+++ 	(revision )
@@ -1,193 +1,0 @@
-/*
-             LUFA Library
-     Copyright (C) Dean Camera, 2021.
-
-  dean [at] fourwalledcubicle [dot] com
-           www.lufa-lib.org
-*/
-
-/*
-  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
-  Permission to use, copy, modify, distribute, and sell this
-  software and its documentation for any purpose is hereby granted
-  without fee, provided that the above copyright notice appear in
-  all copies and that both that the copyright notice and this
-  permission notice and warranty disclaimer appear in supporting
-  documentation, and that the name of the author not be used in
-  advertising or publicity pertaining to distribution of the
-  software without specific, written prior permission.
-
-  The author disclaims all warranties with regard to this
-  software, including all implied warranties of merchantability
-  and fitness.  In no event shall the author be liable for any
-  special, indirect or consequential damages or any damages
-  whatsoever resulting from loss of use, data or profits, whether
-  in an action of contract, negligence or other tortious action,
-  arising out of or in connection with the use or performance of
-  this software.
-*/
-
-/** \file
- *
- *  Main source file for the Joystick demo. This file contains the main tasks of
- *  the demo and is responsible for the initial application hardware configuration.
- */
-
-#include "Joystick.h"
-
-extern void GrIP_Init();
-extern uint8_t GrIP_Read(uint32_t*, uint8_t);
-
-/** Buffer to hold the previously generated HID report, for comparison purposes inside the HID class driver. */
-static uint8_t PrevJoystickHIDReportBuffer[4];
-
-/** LUFA HID Class driver interface configuration and state information. This structure is
- *  passed to all HID Class driver functions, so that multiple instances of the same class
- *  within a device can be differentiated from one another.
- */
-USB_ClassInfo_HID_Device_t Joystick_HID_Interface =
-	{
-		.Config =
-			{
-				.InterfaceNumber              = INTERFACE_ID_Joystick,
-				.ReportINEndpoint             =
-					{
-						.Address              = JOYSTICK_EPADDR,
-						.Size                 = JOYSTICK_EPSIZE,
-						.Banks                = 1,
-					},
-				.PrevReportINBuffer           = PrevJoystickHIDReportBuffer,
-				.PrevReportINBufferSize       = sizeof(PrevJoystickHIDReportBuffer),
-			},
-	};
-
-
-/** Main program entry point. This routine contains the overall program flow, including initial
- *  setup of all components and the main program loop.
- */
-int main(void)
-{
-	SetupHardware();
-
-	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
-	GlobalInterruptEnable();
-
-	for (;;)
-	{
-		HID_Device_USBTask(&Joystick_HID_Interface);
-		USB_USBTask();
-	}
-}
-
-/** Configures the board hardware and chip peripherals for the demo's functionality. */
-void SetupHardware(void)
-{
-#if (ARCH == ARCH_AVR8)
-	/* Disable watchdog if enabled by bootloader/fuses */
-	MCUSR &= ~(1 << WDRF);
-	wdt_disable();
-
-	/* Disable clock division */
-	clock_prescale_set(clock_div_1);
-#elif (ARCH == ARCH_XMEGA)
-	/* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
-	XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
-	XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
-
-	/* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
-	XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
-	XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
-
-	PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
-#endif
-
-	/* Hardware Initialization */
-	GrIP_Init();
-	LEDs_Init();
-	Buttons_Init();
-	USB_Init();
-}
-
-/** Event handler for the library USB Connection event. */
-void EVENT_USB_Device_Connect(void)
-{
-	LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
-}
-
-/** Event handler for the library USB Disconnection event. */
-void EVENT_USB_Device_Disconnect(void)
-{
-	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
-}
-
-/** Event handler for the library USB Configuration Changed event. */
-void EVENT_USB_Device_ConfigurationChanged(void)
-{
-	bool ConfigSuccess = true;
-
-	ConfigSuccess &= HID_Device_ConfigureEndpoints(&Joystick_HID_Interface);
-
-	USB_Device_EnableSOFEvents();
-
-	LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
-}
-
-/** Event handler for the library USB Control Request reception event. */
-void EVENT_USB_Device_ControlRequest(void)
-{
-	HID_Device_ProcessControlRequest(&Joystick_HID_Interface);
-}
-
-/** Event handler for the USB device Start Of Frame event. */
-void EVENT_USB_Device_StartOfFrame(void)
-{
-	HID_Device_MillisecondElapsed(&Joystick_HID_Interface);
-}
-
-/** HID class driver callback function for the creation of HID reports to the host.
- *
- *  \param[in]     HIDInterfaceInfo  Pointer to the HID class interface configuration structure being referenced
- *  \param[in,out] ReportID    Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID
- *  \param[in]     ReportType  Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature
- *  \param[out]    ReportData  Pointer to a buffer where the created report should be stored
- *  \param[out]    ReportSize  Number of bytes written in the report (or zero if no report is to be sent)
- *
- *  \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent
- */
-bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
-                                         uint8_t* const ReportID,
-                                         const uint8_t ReportType,
-                                         void* ReportData,
-                                         uint16_t* const ReportSize)
-{
-	*ReportID = GrIP_Read(ReportData, *ReportID) + 1;
-
-	// Flip the up/down axis in the right direction for USB reports
-	uint8_t* data = (uint8_t*)ReportData;
-	uint8_t up = data[3] & 0x08;
-	uint8_t down = data[3] & 0x10;
-	data[3] ^= up | down;
-	data[3] ^= (up << 1) | (down >> 1);
-
-	*ReportSize = 4;
-	return true;
-}
-
-/** HID class driver callback function for the processing of HID reports from the host.
- *
- *  \param[in] HIDInterfaceInfo  Pointer to the HID class interface configuration structure being referenced
- *  \param[in] ReportID    Report ID of the received report from the host
- *  \param[in] ReportType  The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature
- *  \param[in] ReportData  Pointer to a buffer where the received report has been stored
- *  \param[in] ReportSize  Size in bytes of the received HID report
- */
-void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
-                                          const uint8_t ReportID,
-                                          const uint8_t ReportType,
-                                          const void* ReportData,
-                                          const uint16_t ReportSize)
-{
-	// Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports
-}
-
Index: d/pcw2hid/code/Joystick.h
===================================================================
--- kbd/pcw2hid/code/Joystick.h	(revision a6ad6e8eb20b68578c16ed8d6a7098470d4d86ea)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
-             LUFA Library
-     Copyright (C) Dean Camera, 2021.
-
-  dean [at] fourwalledcubicle [dot] com
-           www.lufa-lib.org
-*/
-
-/*
-  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [dot] com)
-
-  Permission to use, copy, modify, distribute, and sell this
-  software and its documentation for any purpose is hereby granted
-  without fee, provided that the above copyright notice appear in
-  all copies and that both that the copyright notice and this
-  permission notice and warranty disclaimer appear in supporting
-  documentation, and that the name of the author not be used in
-  advertising or publicity pertaining to distribution of the
-  software without specific, written prior permission.
-
-  The author disclaims all warranties with regard to this
-  software, including all implied warranties of merchantability
-  and fitness.  In no event shall the author be liable for any
-  special, indirect or consequential damages or any damages
-  whatsoever resulting from loss of use, data or profits, whether
-  in an action of contract, negligence or other tortious action,
-  arising out of or in connection with the use or performance of
-  this software.
-*/
-
-/** \file
- *
- *  Header file for Joystick.c.
- */
-
-#ifndef _JOYSTICK_H_
-#define _JOYSTICK_H_
-
-	/* Includes: */
-		#include <avr/io.h>
-		#include <avr/wdt.h>
-		#include <avr/power.h>
-		#include <avr/interrupt.h>
-		#include <string.h>
-
-		#include "Descriptors.h"
-
-		#include <LUFA/Drivers/Board/Joystick.h>
-		#include <LUFA/Drivers/Board/LEDs.h>
-		#include <LUFA/Drivers/Board/Buttons.h>
-		#include <LUFA/Drivers/USB/USB.h>
-		#include <LUFA/Platform/Platform.h>
-
-	/* Type Defines: */
-	/* Macros: */
-		/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
-		#define LEDMASK_USB_NOTREADY      LEDS_LED1
-
-		/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
-		#define LEDMASK_USB_ENUMERATING  (LEDS_LED2 | LEDS_LED3)
-
-		/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
-		#define LEDMASK_USB_READY        (LEDS_LED2 | LEDS_LED4)
-
-		/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
-		#define LEDMASK_USB_ERROR        (LEDS_LED1 | LEDS_LED3)
-
-	/* Function Prototypes: */
-		void SetupHardware(void);
-
-		void EVENT_USB_Device_Connect(void);
-		void EVENT_USB_Device_Disconnect(void);
-		void EVENT_USB_Device_ConfigurationChanged(void);
-		void EVENT_USB_Device_ControlRequest(void);
-		void EVENT_USB_Device_StartOfFrame(void);
-
-		bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
-		                                         uint8_t* const ReportID,
-		                                         const uint8_t ReportType,
-		                                         void* ReportData,
-		                                         uint16_t* const ReportSize);
-		void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
-		                                          const uint8_t ReportID,
-		                                          const uint8_t ReportType,
-		                                          const void* ReportData,
-		                                          const uint16_t ReportSize);
-
-#endif
-
Index: kbd/pcw2hid/code/Keyboard.c
===================================================================
--- kbd/pcw2hid/code/Keyboard.c	(revision 110c6922461234282a264edb8a3c8349f2c610d7)
+++ kbd/pcw2hid/code/Keyboard.c	(revision 110c6922461234282a264edb8a3c8349f2c610d7)
@@ -0,0 +1,190 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2021.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+  Permission to use, copy, modify, distribute, and sell this
+  software and its documentation for any purpose is hereby granted
+  without fee, provided that the above copyright notice appear in
+  all copies and that both that the copyright notice and this
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
+  software without specific, written prior permission.
+
+  The author disclaims all warranties with regard to this
+  software, including all implied warranties of merchantability
+  and fitness.  In no event shall the author be liable for any
+  special, indirect or consequential damages or any damages
+  whatsoever resulting from loss of use, data or profits, whether
+  in an action of contract, negligence or other tortious action,
+  arising out of or in connection with the use or performance of
+  this software.
+*/
+
+/** \file
+ *
+ *  Main source file for the Joystick demo. This file contains the main tasks of
+ *  the demo and is responsible for the initial application hardware configuration.
+ */
+
+#include "Keyboard.h"
+
+extern void PCW_Init();
+extern void scanall();
+
+/** Buffer to hold the previously generated HID report, for comparison purposes inside the HID class driver. */
+static uint8_t PrevJoystickHIDReportBuffer[4];
+
+/** LUFA HID Class driver interface configuration and state information. This structure is
+ *  passed to all HID Class driver functions, so that multiple instances of the same class
+ *  within a device can be differentiated from one another.
+ */
+USB_ClassInfo_HID_Device_t Joystick_HID_Interface =
+	{
+		.Config =
+			{
+				.InterfaceNumber              = INTERFACE_ID_Joystick,
+				.ReportINEndpoint             =
+					{
+						.Address              = JOYSTICK_EPADDR,
+						.Size                 = JOYSTICK_EPSIZE,
+						.Banks                = 1,
+					},
+				.PrevReportINBuffer           = PrevJoystickHIDReportBuffer,
+				.PrevReportINBufferSize       = sizeof(PrevJoystickHIDReportBuffer),
+			},
+	};
+
+
+/** Main program entry point. This routine contains the overall program flow, including initial
+ *  setup of all components and the main program loop.
+ */
+int main(void)
+{
+	SetupHardware();
+
+	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+	GlobalInterruptEnable();
+
+	for (;;)
+	{
+		HID_Device_USBTask(&Joystick_HID_Interface);
+		USB_USBTask();
+	}
+}
+
+/** Configures the board hardware and chip peripherals for the demo's functionality. */
+void SetupHardware(void)
+{
+#if (ARCH == ARCH_AVR8)
+	/* Disable watchdog if enabled by bootloader/fuses */
+	MCUSR &= ~(1 << WDRF);
+	wdt_disable();
+
+	/* Disable clock division */
+	clock_prescale_set(clock_div_1);
+#elif (ARCH == ARCH_XMEGA)
+	/* Start the PLL to multiply the 2MHz RC oscillator to 32MHz and switch the CPU core to run from it */
+	XMEGACLK_StartPLL(CLOCK_SRC_INT_RC2MHZ, 2000000, F_CPU);
+	XMEGACLK_SetCPUClockSource(CLOCK_SRC_PLL);
+
+	/* Start the 32MHz internal RC oscillator and start the DFLL to increase it to 48MHz using the USB SOF as a reference */
+	XMEGACLK_StartInternalOscillator(CLOCK_SRC_INT_RC32MHZ);
+	XMEGACLK_StartDFLL(CLOCK_SRC_INT_RC32MHZ, DFLL_REF_INT_USBSOF, F_USB);
+
+	PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
+#endif
+
+	/* Hardware Initialization */
+	PCW_Init();
+	LEDs_Init();
+	Buttons_Init();
+	USB_Init();
+}
+
+/** Event handler for the library USB Connection event. */
+void EVENT_USB_Device_Connect(void)
+{
+	LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);
+}
+
+/** Event handler for the library USB Disconnection event. */
+void EVENT_USB_Device_Disconnect(void)
+{
+	LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
+}
+
+/** Event handler for the library USB Configuration Changed event. */
+void EVENT_USB_Device_ConfigurationChanged(void)
+{
+	bool ConfigSuccess = true;
+
+	ConfigSuccess &= HID_Device_ConfigureEndpoints(&Joystick_HID_Interface);
+
+	USB_Device_EnableSOFEvents();
+
+	LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
+}
+
+/** Event handler for the library USB Control Request reception event. */
+void EVENT_USB_Device_ControlRequest(void)
+{
+	HID_Device_ProcessControlRequest(&Joystick_HID_Interface);
+}
+
+/** Event handler for the USB device Start Of Frame event. */
+void EVENT_USB_Device_StartOfFrame(void)
+{
+	HID_Device_MillisecondElapsed(&Joystick_HID_Interface);
+}
+
+/** HID class driver callback function for the creation of HID reports to the host.
+ *
+ *  \param[in]     HIDInterfaceInfo  Pointer to the HID class interface configuration structure being referenced
+ *  \param[in,out] ReportID    Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID
+ *  \param[in]     ReportType  Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature
+ *  \param[out]    ReportData  Pointer to a buffer where the created report should be stored
+ *  \param[out]    ReportSize  Number of bytes written in the report (or zero if no report is to be sent)
+ *
+ *  \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent
+ */
+bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+                                         uint8_t* const ReportID,
+                                         const uint8_t ReportType,
+                                         void* ReportData,
+                                         uint16_t* const ReportSize)
+{
+	uint8_t* matrix = scanall();
+	*ReportID = 1;
+
+	*ReportSize = 16;
+	for (int i = 0; i < 16; i++) {
+		ReportData[i] = matrix[i];
+	}
+	return true;
+}
+
+/** HID class driver callback function for the processing of HID reports from the host.
+ *
+ *  \param[in] HIDInterfaceInfo  Pointer to the HID class interface configuration structure being referenced
+ *  \param[in] ReportID    Report ID of the received report from the host
+ *  \param[in] ReportType  The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature
+ *  \param[in] ReportData  Pointer to a buffer where the received report has been stored
+ *  \param[in] ReportSize  Size in bytes of the received HID report
+ */
+void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+                                          const uint8_t ReportID,
+                                          const uint8_t ReportType,
+                                          const void* ReportData,
+                                          const uint16_t ReportSize)
+{
+	// Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports
+}
+
Index: kbd/pcw2hid/code/Keyboard.h
===================================================================
--- kbd/pcw2hid/code/Keyboard.h	(revision 110c6922461234282a264edb8a3c8349f2c610d7)
+++ kbd/pcw2hid/code/Keyboard.h	(revision 110c6922461234282a264edb8a3c8349f2c610d7)
@@ -0,0 +1,89 @@
+/*
+             LUFA Library
+     Copyright (C) Dean Camera, 2021.
+
+  dean [at] fourwalledcubicle [dot] com
+           www.lufa-lib.org
+*/
+
+/*
+  Copyright 2021  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+
+  Permission to use, copy, modify, distribute, and sell this
+  software and its documentation for any purpose is hereby granted
+  without fee, provided that the above copyright notice appear in
+  all copies and that both that the copyright notice and this
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
+  software without specific, written prior permission.
+
+  The author disclaims all warranties with regard to this
+  software, including all implied warranties of merchantability
+  and fitness.  In no event shall the author be liable for any
+  special, indirect or consequential damages or any damages
+  whatsoever resulting from loss of use, data or profits, whether
+  in an action of contract, negligence or other tortious action,
+  arising out of or in connection with the use or performance of
+  this software.
+*/
+
+/** \file
+ *
+ *  Header file for Joystick.c.
+ */
+
+#ifndef _JOYSTICK_H_
+#define _JOYSTICK_H_
+
+	/* Includes: */
+		#include <avr/io.h>
+		#include <avr/wdt.h>
+		#include <avr/power.h>
+		#include <avr/interrupt.h>
+		#include <string.h>
+
+		#include "Descriptors.h"
+
+		#include <LUFA/Drivers/Board/Joystick.h>
+		#include <LUFA/Drivers/Board/LEDs.h>
+		#include <LUFA/Drivers/Board/Buttons.h>
+		#include <LUFA/Drivers/USB/USB.h>
+		#include <LUFA/Platform/Platform.h>
+
+	/* Type Defines: */
+	/* Macros: */
+		/** LED mask for the library LED driver, to indicate that the USB interface is not ready. */
+		#define LEDMASK_USB_NOTREADY      LEDS_LED1
+
+		/** LED mask for the library LED driver, to indicate that the USB interface is enumerating. */
+		#define LEDMASK_USB_ENUMERATING  (LEDS_LED2 | LEDS_LED3)
+
+		/** LED mask for the library LED driver, to indicate that the USB interface is ready. */
+		#define LEDMASK_USB_READY        (LEDS_LED2 | LEDS_LED4)
+
+		/** LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */
+		#define LEDMASK_USB_ERROR        (LEDS_LED1 | LEDS_LED3)
+
+	/* Function Prototypes: */
+		void SetupHardware(void);
+
+		void EVENT_USB_Device_Connect(void);
+		void EVENT_USB_Device_Disconnect(void);
+		void EVENT_USB_Device_ConfigurationChanged(void);
+		void EVENT_USB_Device_ControlRequest(void);
+		void EVENT_USB_Device_StartOfFrame(void);
+
+		bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+		                                         uint8_t* const ReportID,
+		                                         const uint8_t ReportType,
+		                                         void* ReportData,
+		                                         uint16_t* const ReportSize);
+		void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
+		                                          const uint8_t ReportID,
+		                                          const uint8_t ReportType,
+		                                          const void* ReportData,
+		                                          const uint16_t ReportSize);
+
+#endif
+
Index: d/pcw2hid/code/grip.cpp
===================================================================
--- kbd/pcw2hid/code/grip.cpp	(revision a6ad6e8eb20b68578c16ed8d6a7098470d4d86ea)
+++ 	(revision )
@@ -1,169 +1,0 @@
-#include <avr/io.h>
-
-#include <stdbool.h>
-
-// The UART is on PD2 (Rx) and PD3 (Tx)
-// The gamepads are all connected on port B
-#define GRIP_PORT PORTD
-#define GRIP_DDR  DDRD
-#define GRIP_PIN  PIND
-#define GRIP_CLK_A  (1 << 0)
-#define GRIP_DAT_A  (1 << 1)
-#define GRIP_CLK_B  (1 << 2)
-#define GRIP_DAT_B  (1 << 3)
-#define GRIP_CLK_C  (1 << 4)
-#define GRIP_DAT_C  (1 << 5)
-#define GRIP_CLK_D  (1 << 6)
-#define GRIP_DAT_D  (1 << 7)
-
-class GrIP
-{
-public:
-	GrIP()
-	{
-		word = 0;
-		count = 0;
-		state = 0;
-	}
-
-	// Push the next bit and returns true if it completes a word.
-	// The whole 24 bit word is stored in "word" and consists of:
-	// - One 7-bit sync pattern: always 0111111
-	// - Three 6-bit blocks starting with a 0 followed by 5 button bits
-	bool PushBit(uint32_t bit)
-	{
-		word = (word >> 1) | ((bit & 1) << 31);
-		count++;
-
-		switch (state) {
-			case 0:
-				if ((word & 0xFE000000) != 0x7C000000) return false;
-				count = 7;
-				state = 1;
-				break;
-			case 1:
-				if (count == 24) {
-					state = 0;
-					count = 0;
-					return true;
-				}
-				break;
-		}
-
-		return false;
-	}
-
-public:
-	uint32_t word;
-private:
-	uint8_t count;
-	uint8_t state; // 0 = looking for sync, 1 = synchronized (we received 0111111)
-};
-
-
-extern "C" void GrIP_Init() {
-	// GrIP input
-	GRIP_PORT = 0xFF; // Enable pull-ups
-	GRIP_DDR = 0;  // Port as input
-}
-
-extern "C" uint8_t GrIP_Read(uint32_t* v, uint8_t k2) {
-	// Initial value of oldv for edge detection
-	uint8_t oldv = GRIP_PIN;
-	static uint8_t k = 0;
-	if (k2 != 0)
-		k = k2 - 1;
-	else {
-		k++; if (k > 3) k = 0;
-	}
-
-		// Because the CPU is too slow, if we try to scan all pads at once we
-		// don't manage to decode them (missed transitions). So we scan them
-		// one at a time.
-		// To scan all 4 gamepads this will take about 4 milliseconds, which
-		// is not the best we could do, but is okay. When we have the real
-		// hardware (with the CPU running at full 16MHz speed instead of crappy
-		// 1MHz here), we can try to interleave them again (one just has to put
-		// them all into a single for loop instead of separate loops for each).
-		// Then we get to 1ms to scan all 4 pads in parallel, cool! And it
-		// also fixes the problem mentionned below that when less pads are
-		// connected, it will not slowdown waiting for one of them to timeout.
-		//
-		// When a gamepad is plugged, the loop seems to complete in around 1000 iterations.
-		// When no gamepad is plugged, that's a timeout.
-
-		// Process pad1
-		GrIP pad;
-		uint16_t i;
-
-		if (k == 0)
-		for (i = 0; i < 2048; i++) {
-			uint8_t newv = GRIP_PIN;
-			if (!(newv & GRIP_CLK_A)) { // clock is down
-				if (oldv & GRIP_CLK_A) { // and it was up at previous read
-					// Read bit
-					uint32_t bit = (newv & GRIP_DAT_A) != 0;
-					if (pad.PushBit(bit)) {
-						*v = pad.word;
-						break;
-					}
-				}
-			}
-			oldv = newv;
-		}
-
-		// Process pad 2
-		if (k == 1)
-		for (i = 0; i < 2048; i++) {
-			uint8_t newv = GRIP_PIN;
-			if (!(newv & GRIP_CLK_B)) { // clock is down
-				if (oldv & GRIP_CLK_B) { // and it was up at previous read
-					// Read bit
-					uint32_t bit = (newv & GRIP_DAT_B) != 0;
-					if (pad.PushBit(bit)) {
-						*v = pad.word;
-						break;
-					}
-				}
-			}
-			oldv = newv;
-		}
-
-		// Process pad 3
-		if (k == 2)
-		for (i = 0; i < 2048; i++) {
-			uint8_t newv = GRIP_PIN;
-			if (!(newv & GRIP_CLK_C)) { // clock is down
-				if (oldv & GRIP_CLK_C) { // and it was up at previous read
-					// Read bit
-					uint32_t bit = (newv & GRIP_DAT_C) != 0;
-					if (pad.PushBit(bit)) {
-						*v = pad.word;
-						break;
-					}
-				}
-			}
-			oldv = newv;
-		}
-
-		// Process pad 4
-		if (k == 3)
-		for (i = 0; i < 2048; i++) {
-			uint8_t newv = GRIP_PIN;
-			if (!(newv & GRIP_CLK_D)) { // clock is down
-				if (oldv & GRIP_CLK_D) { // and it was up at previous read
-					// Read bit
-					uint32_t bit = (newv & GRIP_DAT_D) != 0;
-					if (pad.PushBit(bit)) {
-						*v = pad.word;
-						break;
-					}
-				}
-			}
-			oldv = newv;
-		}
-
-		return k;
-}
-
-
Index: kbd/pcw2hid/code/protocol.cpp
===================================================================
--- kbd/pcw2hid/code/protocol.cpp	(revision 110c6922461234282a264edb8a3c8349f2c610d7)
+++ kbd/pcw2hid/code/protocol.cpp	(revision 110c6922461234282a264edb8a3c8349f2c610d7)
@@ -0,0 +1,87 @@
+#include <avr/io.h>
+
+#include <stdbool.h>
+
+// The UART is on PD2 (Rx) and PD3 (Tx)
+// The gamepads are all connected on port B
+#define PCW_PORT PORTD
+#define PCW_DDR  DDRD
+#define PCW_PIN  PIND
+#define PCW_CLK_A  (1 << 0)
+#define PCW_DAT_A  (1 << 1)
+
+static uint8_t data;
+static uint8_t address;
+
+static uint8_t oldv;
+static uint8_t newv;
+
+static uint8_t pulses;
+
+static uint8_t kmatrix[16];
+
+uint8_t scanbyte()
+{
+	pulses = 0;
+	address = 0;
+
+	oldv = PCW_PIN;
+
+	for (int i = 0; i < 2048; i++) {
+		newv = PCW_PIN;
+
+		if (pulses < 2) {
+			// Initial sync phase: 2 pulses on data without changes of clock
+			if (((newv & PCW_CLK_A) == 0) && ((oldv & PCW_CLK_A) != 0)) {
+				// Clock moved while we were waiting for the initial data pulses
+				// We are not in sync, start over
+				pulses = 0;
+				address = 0;
+			}
+			if (((newv & PCW_DAT_A) == 0) && ((oldv & PCW_DAT_A) != 0)) {
+				pulses++;
+			}
+		} else if (pulses < 6) {
+			// Receiving address (4 bits)
+			if (((newv & PCW_CLK_A) == 0) && ((oldv & PCW_CLK_A) != 0)) {
+				address = (address << 1) | ((newv & PCW_DAT_A) ? 1 : 0);
+				pulses++;
+			}
+		} else {
+			// Receiving data (8 bits)
+			if (((newv & PCW_CLK_A) == 0) && ((oldv & PCW_CLK_A) != 0)) {
+				data = (data << 1) | ((newv & PCW_DAT_A) ? 1 : 0);
+				pulses++;
+			}
+
+			// If we reached the last bit, we can stop
+			if (pulses >= 10) {
+				kmatrix[address] = data;
+				return address;
+			}
+		}
+
+		oldv = newv;
+	}
+
+	// TODO set up some error LED or something?
+	return 255;
+}
+
+extern "C" uint8_t* scanall()
+{
+	uint8_t address;
+
+	do {
+		address = scanbyte();
+	} while ((address < 15) && (kmatrix[15] & 0x80 != 0));
+
+	return kmatrix;
+}
+
+extern "C" void PCW_Init() {
+	// GrIP input
+	PCW_PORT = 0xFF; // Enable pull-ups
+	PCW_DDR = 0;  // Port as input
+}
+
