summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2019-10-22 15:44:50 +0300
committerDenis Shienkov <denis.shienkov@gmail.com>2019-10-29 08:35:54 +0000
commit4ce68dd8dd4a012545a5d7f19039840e416ddfc3 (patch)
treeb192aeb06e2e773f6c4e92e44cc6ec1b8dbb5790
parent8c8fb4b0638f0cb41c8d546f78c5f3702edeb3a5 (diff)
baremetal: Add USB HID gamepads example for CY7C68013A chip
This example demonstrates how to create the USB HID device on CY7C68013A chip (based on 8051 architecture) using the different toolchains (SDCC, IAR EW, KEIL). Change-Id: I2678c680245c1b969466b2e91fe04850635cc09b Reviewed-by: Richard Weickelt <richard@weickelt.de> Reviewed-by: Ivan Komissarov <ABBAPOH@gmail.com> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--examples/baremetal/baremetal.qbs1
-rw-r--r--examples/baremetal/cy7c68013a/cy7c68013a.qbs58
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/README.md42
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/core.c86
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/core.h298
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/defs.h173
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/gpio.c161
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/gpio.h65
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/hid.c85
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/hid.h92
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/hiddesc.c345
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/hidep0.c377
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/hidep1.c89
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/irqs.h77
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/main.c85
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/nes-gamepads.qbs138
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/regs.h779
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/usb.c118
-rw-r--r--examples/baremetal/cy7c68013a/nes-gamepads/usb.h217
19 files changed, 3286 insertions, 0 deletions
diff --git a/examples/baremetal/baremetal.qbs b/examples/baremetal/baremetal.qbs
index 37a46bbf5..eba504512 100644
--- a/examples/baremetal/baremetal.qbs
+++ b/examples/baremetal/baremetal.qbs
@@ -58,5 +58,6 @@ Project {
"cc2540usbdongle/cc2540usbdongle.qbs",
"stm8s103f3/stm8s103f3.qbs",
"msp430f5529/msp430f5529.qbs",
+ "cy7c68013a/cy7c68013a.qbs"
]
}
diff --git a/examples/baremetal/cy7c68013a/cy7c68013a.qbs b/examples/baremetal/cy7c68013a/cy7c68013a.qbs
new file mode 100644
index 000000000..370844725
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/cy7c68013a.qbs
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import qbs
+
+Project {
+ name: "Examples for cy7c68013a board"
+ references: [
+ "nes-gamepads/nes-gamepads.qbs"
+ ]
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/README.md b/examples/baremetal/cy7c68013a/nes-gamepads/README.md
new file mode 100644
index 000000000..06d1fc77c
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/README.md
@@ -0,0 +1,42 @@
+This example demonstrates how to build a bare-metal application using
+different 8051 toolchains. It is designed for the target board
+based on Cypress FX2 cy7c68013a chip.
+
+It is possible to use the official development kit from the Cypress:
+
+* https://www.cypress.com/documentation/development-kitsboards/cy3684-ez-usb-fx2lp-development-kit
+
+but, a better solution is to buy the China's analogs or replacements,
+e.g. on Aliexpress.
+
+It implements a USB HID device that connects two 8-buttons NES
+(Dendy) gamepads to a PC. The gamepads are connected to the
+cy7c68013a chip as follows:
+
+1. CLK - it is an output clock signal which generates by chip from
+ the port A, pin 0 (PA0). This pin should be connected to the CLK
+ inputs for both gamepads.
+
+2. DATA1 - it is an input data signal which comes to chip on the
+ the port A, pin 2 (PA2). This pin should be connected to the DATA
+ output from the gamepad #1.
+
+3. DATA2 - it is an input data signal which comes to chip on the
+ the port A, pin 4 (PA4). This pin should be connected to the DATA
+ output from the gamepad #2.
+
+4. LATCH - it is an output clock signal which generates by chip from
+ the port A, pin 6 (PA6). This pin should be connected to the LATCH
+ inputs for both gamepads.
+
+Actual schematic and pinouts depends on an used gamepads (with 7, 9
+or other pins connectors) and a development boards.
+
+Also, do not forget to connect the +3.3V and GND wires to the gamepads.
+Then it is possible to play 8-bit NES games using various PC simulators.
+
+The following toolchains are supported:
+
+ * IAR Embedded Workbench
+ * SDCC
+ * KEIL C51
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/core.c b/examples/baremetal/cy7c68013a/nes-gamepads/core.c
new file mode 100644
index 000000000..17a9661eb
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/core.c
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "core.h"
+#include "regs.h"
+
+enum cpu_freq_clk {
+ CPU_CLK_12M = 0,
+ CPU_CLK_24M,
+ CPU_CLK_48M
+};
+
+#define cpu_freq_clk_get() \
+ ((CPUCS & bmCLKSPD) >> 3)
+
+#define cpu_freq_clk_set(freq_clk) \
+ CPUCS = (CPUCS & ~bmCLKSPD) | (freq_clk << 3)
+
+void core_init(void)
+{
+ // Set CPU clock to 48MHz.
+ cpu_freq_clk_set(CPU_CLK_48M);
+ sync_delay();
+ // Set stretch to 0.
+ CKCON = ((CKCON & (~bmSTRETCH)) | bmFW_STRETCH1);
+ sync_delay();
+ // Clear breakpoint register.
+ BREAKPT = 0;
+ sync_delay();
+ // Set all 8051 interrupts to low priority
+ IP = 0;
+ sync_delay();
+ // Clear interrupt enable bits.
+ EIE = 0;
+ sync_delay();
+ // Clear all external interrupt flags.
+ EXIF = 0;
+ sync_delay();
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/core.h b/examples/baremetal/cy7c68013a/nes-gamepads/core.h
new file mode 100644
index 000000000..a53ad2a48
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/core.h
@@ -0,0 +1,298 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FX2_HW_H
+#define FX2_HW_H
+
+#include "defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Allowed range: 5000 - 48000.
+#ifndef CORE_IFREQ
+# define CORE_IFREQ 48000 // IFCLK frequency in kHz.
+#endif
+
+// Allowed values: 48000, 24000, or 12000.
+#ifndef CORE_CFREQ
+# define CORE_CFREQ 48000 // CLKOUT frequency in kHz.
+#endif
+
+#if (CORE_IFREQ < 5000)
+# error "CORE_IFREQ too small! Valid range: 5000 - 48000."
+#endif
+
+#if (CORE_IFREQ > 48000)
+# error "CORE_IFREQ too large! Valid range: 5000 - 48000."
+#endif
+
+#if (CORE_CFREQ != 48000)
+# if (CORE_CFREQ != 24000)
+# if (CORE_CFREQ != 12000)
+# error "CORE_CFREQ invalid! Valid values: 48000, 24000, 12000."
+# endif
+# endif
+#endif
+
+// Calculate synchronization delay.
+#define CORE_SCYCL (3 * (CORE_CFREQ) + 5 * (CORE_IFREQ) - 1) / (2 * (CORE_IFREQ))
+
+#if (CORE_SCYCL == 1)
+# define sync_delay() {\
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 2)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 3)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 4)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 5)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 6)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 7)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 8)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 9)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 10)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 11)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 12)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 13)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 14)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 15)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#if (CORE_SCYCL == 16)
+# define sync_delay() {\
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); \
+ NOP(); }
+#endif
+
+#define code_all_irq_disable() (IE = 0)
+#define code_all_irq_enable() (IE = 1)
+
+void core_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FX2_HW_H
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/defs.h b/examples/baremetal/cy7c68013a/nes-gamepads/defs.h
new file mode 100644
index 000000000..7fb36fee8
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/defs.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FX2_DEFS_H
+#define FX2_DEFS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum bit_mask {
+ bmBIT0 = 0x01,
+ bmBIT1 = 0x02,
+ bmBIT2 = 0x04,
+ bmBIT3 = 0x08,
+ bmBIT4 = 0x10,
+ bmBIT5 = 0x20,
+ bmBIT6 = 0x40,
+ bmBIT7 = 0x80
+};
+
+enum boolean {
+ FALSE = 0,
+ TRUE
+};
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef unsigned char BOOL;
+
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+#if defined(__ICC8051__)
+
+#include <intrinsics.h>
+
+# define NOP() __no_operation()
+
+# define XDATA __xdata
+# define CODE __code
+# define AT __at
+
+# define SFR __sfr
+# define SBIT __bit
+
+# define XDATA_REG(reg_name, reg_addr) \
+ XDATA __no_init volatile BYTE reg_name @ reg_addr;
+
+# define SPEC_FUN_REG(reg_name, reg_addr) \
+ SFR __no_init volatile BYTE reg_name @ reg_addr;
+
+# define SPEC_FUN_REG_BIT(bit_name, reg_addr, bit_num) \
+ SBIT __no_init volatile _Bool bit_name @ (reg_addr+bit_num);
+
+# define _PPTOSTR_(x) #x
+# define _PPARAM_(address) _PPTOSTR_(vector=address * 8 + 3)
+# define INTERRUPT(isr_name, vector) \
+ _Pragma(_PPARAM_(vector)) __interrupt void isr_name(void)
+
+#elif defined (__C51__)
+
+# include <intrins.h>
+
+# define NOP() _nop_()
+
+# define XDATA xdata
+# define CODE code
+# define AT _at_
+
+# define SFR sfr
+# define SBIT sbit
+
+# if defined(DEFINE_REGS)
+# define XDATA_REG(reg_name, reg_addr) \
+ XDATA volatile BYTE reg_name AT reg_addr;
+# else
+# define XDATA_REG(reg_name, reg_addr) \
+ extern XDATA volatile BYTE reg_name;
+# endif
+
+# define SPEC_FUN_REG(reg_name, reg_addr) \
+ SFR reg_name = reg_addr;
+
+# define SPEC_FUN_REG_BIT(bit_name, reg_addr, bit_num) \
+ sbit bit_name = reg_addr + bit_num;
+
+# define INTERRUPT(isr_name, num) \
+ void isr_name (void) interrupt num
+
+#elif defined (__SDCC_mcs51)
+
+# define NOP() __asm nop __endasm
+
+# define XDATA __xdata
+# define CODE __code
+# define AT __at
+
+# define SFR __sfr
+# define SBIT __sbit
+
+# define XDATA_REG(reg_name, reg_addr) \
+ XDATA AT reg_addr volatile BYTE reg_name;
+
+# define SPEC_FUN_REG(reg_name, reg_addr) \
+ SFR AT reg_addr reg_name;
+
+# define SPEC_FUN_REG_BIT(bit_name, reg_addr, bit_num) \
+ SBIT AT reg_addr + bit_num bit_name;
+
+# define INTERRUPT(isr_name, num) \
+ void isr_name (void) __interrupt num
+
+#else
+
+#error "Unsupported toolchain"
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FX2_DEFS_H
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/gpio.c b/examples/baremetal/cy7c68013a/nes-gamepads/gpio.c
new file mode 100644
index 000000000..d7a74b3e0
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/gpio.c
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "core.h"
+#include "gpio.h"
+#include "hid.h"
+#include "regs.h"
+
+static WORD g_counter = 0;
+
+// We use this empirical value to make a GPIO polling
+// every ~10 msec (rough). It is a simplest way, because
+// instead we need to use a timers with interrupts callbacks.
+enum { POLLING_COUNTER = 580 };
+
+// Pins on the port A.
+enum gpio_pins {
+ GPIO_CLK_PIN = bmBIT0,
+ GPIO_DATA1_PIN = bmBIT2,
+ GPIO_DATA2_PIN = bmBIT4,
+ GPIO_LATCH_PIN = bmBIT6,
+};
+
+static struct {
+ const BYTE pin;
+ BYTE buttons;
+} g_reports[HID_REPORTS_COUNT] = {
+ {GPIO_DATA1_PIN, 0},
+ {GPIO_DATA2_PIN, 0}
+};
+
+// Pulse width around ~1 usec.
+static void gpio_latch_pulse(void)
+{
+ IOA |= GPIO_LATCH_PIN;
+ sync_delay();
+ sync_delay();
+ sync_delay();
+ IOA &= ~GPIO_LATCH_PIN;
+ sync_delay();
+}
+
+// Pulse width around ~1 usec.
+static void gpio_clk_pulse(void)
+{
+ IOA |= GPIO_CLK_PIN;
+ sync_delay();
+ sync_delay();
+ sync_delay();
+ IOA &= ~GPIO_CLK_PIN;
+ sync_delay();
+}
+
+static void gpio_reports_clean(void)
+{
+ BYTE index = 0;
+ for (index = 0; index < HID_REPORTS_COUNT; ++index)
+ g_reports[index].buttons = 0;
+}
+
+static void gpio_reports_send(void)
+{
+ BYTE index = 0;
+ for (index = 0; index < HID_REPORTS_COUNT; ++index)
+ hid_ep1_report_update(index, g_reports[index].buttons);
+}
+
+static void gpio_poll(void)
+{
+ BYTE pos = 0;
+
+ // Cleanup reports.
+ gpio_reports_clean();
+
+ // Send latch pulse.
+ gpio_latch_pulse();
+
+ for (pos = 0; pos < HID_REPORT_BITS_COUNT; ++pos) {
+ // TODO: Add some nops here?
+
+ BYTE index = 0;
+ for (index = 0; index < HID_REPORTS_COUNT; ++index) {
+ // Low state means that a button is pressed.
+ const BOOL v = (IOA & g_reports[index].pin) ? 0 : 1;
+ g_reports[index].buttons |= (v << pos);
+ }
+
+ // Send clock pulse.
+ gpio_clk_pulse();
+ }
+
+ gpio_reports_send();
+}
+
+void gpio_init(void)
+{
+ // Set interface to ports.
+ IFCONFIG = (IFCONFIG & (~bmIFCFG)) | bmIFPORTS;
+ sync_delay();
+
+ // Initialize the CLK and LATCH pins as output.
+ OEA = GPIO_CLK_PIN | GPIO_LATCH_PIN;
+ sync_delay();
+}
+
+void gpio_task(void)
+{
+ if (g_counter < POLLING_COUNTER) {
+ ++g_counter;
+ } else {
+ g_counter = 0;
+ gpio_poll();
+ }
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/gpio.h b/examples/baremetal/cy7c68013a/nes-gamepads/gpio.h
new file mode 100644
index 000000000..d2568fd76
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/gpio.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FX2_GPIO_H
+#define FX2_GPIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void gpio_init(void);
+void gpio_task(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FX2_GPIO_H
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/hid.c b/examples/baremetal/cy7c68013a/nes-gamepads/hid.c
new file mode 100644
index 000000000..cca4edab8
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/hid.c
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "hid.h"
+#include "core.h"
+#include "usb.h"
+
+void hid_init(void)
+{
+ // Disable end point 1 output.
+ EP1OUTCFG = bmEP_DISABLE;
+ sync_delay();
+ // Enable end point 1 input in interrupt mode.
+ EP1INCFG = bmEP_ENABLE | bmEP_INT;
+ sync_delay();
+ // Disable end point 2.
+ EP2CFG = bmEP_DISABLE;
+ sync_delay();
+ // Disable end point 4.
+ EP4CFG = bmEP_DISABLE;
+ sync_delay();
+ // Disable end point 6.
+ EP6CFG = bmEP_DISABLE;
+ sync_delay();
+ // Disable end point 8.
+ EP8CFG = bmEP_DISABLE;
+ sync_delay();
+
+ // Reset all FIFOs.
+ FIFORESET = bmNAKALL; // NAK all host transfers.
+ sync_delay();
+ FIFORESET = 0x00;
+ sync_delay();
+
+ // Enable dual autopointer(s).
+ AUTOPTRSETUP |= bmAPTREN;
+ sync_delay();
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/hid.h b/examples/baremetal/cy7c68013a/nes-gamepads/hid.h
new file mode 100644
index 000000000..c51b87370
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/hid.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FX2_HID_H
+#define FX2_HID_H
+
+#include "usb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum hid_constants {
+ HID_CONFIG_NUMBER = 1, // Number of valid configuration.
+ HID_IFACE_NUMBER = 0, // Number of valid interface.
+ HID_ALT_IFACE_NUMBER = 0, // Number of valid alternate interface.
+ HID_EP_IN = 0x81 // Active end point address.
+};
+
+enum hid_gamepad_id {
+ HID_REPORT_ID_GAMEPAD1 = 1,
+ HID_REPORT_ID_GAMEPAD2 = 2
+};
+
+enum {
+ HID_REPORTS_COUNT = 2,
+ HID_REPORT_BITS_COUNT = 8
+};
+
+void hid_init(void);
+
+void hid_ep0_init(void);
+void hid_ep0_setup_task(void);
+
+const BYTE CODE *hid_ep0_std_desc_get(void);
+const BYTE CODE *hid_ep0_report_desc_get(WORD *length);
+
+void hid_ep1_task(void);
+void hid_ep1_report_update(BYTE index, BYTE buttons);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FX2_HID_H
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/hiddesc.c b/examples/baremetal/cy7c68013a/nes-gamepads/hiddesc.c
new file mode 100644
index 000000000..74601f249
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/hiddesc.c
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "hid.h"
+
+enum usb_bcd_version {
+ USB_SPEC_BCD_VERSION = 0x0200,
+ USB_DEVICE_BCD_VERSION = 0x1234,
+ USB_HID_BCD_VERSION = 0x0111
+};
+
+enum usb_ids {
+ USB_DEVICE_VID = 0xFFFF,
+ USB_DEVICE_PID = 0xFFFF
+};
+
+enum usb_lang_id {
+ USB_LANG_ID = 0x0409
+};
+
+enum usb_descriptor_string_index {
+ USB_DESC_LANGID_STRING_INDEX = 0,
+ USB_DESC_MFG_STRING_INDEX,
+ USB_DESC_PRODUCT_STRING_INDEX,
+ USB_DESC_SERIAL_STRING_INDEX
+};
+
+enum usb_descr_length {
+ // Standard length.
+ USB_DESC_DEVICE_LEN = 18,
+ USB_DESC_DEVICE_QUAL_LEN = 10,
+ USB_DESC_CONF_LEN = 9,
+ USB_DESC_OTHER_SPEED_CONF_LEN = 9,
+ USB_DESC_INTERFACE_LEN = 9,
+ USB_DESC_HID_LEN = 9,
+ USB_DESCR_HID_REP_LEN = 56,
+ USB_DESC_ENDPOINT_LEN = 7,
+
+ // Total length.
+ USB_DESC_DEVICE_TOTAL_LEN = USB_DESC_DEVICE_LEN,
+ USB_DESC_DEVICE_QUAL_TOTAL_LEN = USB_DESC_DEVICE_QUAL_LEN,
+
+ USB_DESC_CONF_TOTAL_LEN = USB_DESC_CONF_LEN
+ + USB_DESC_INTERFACE_LEN
+ + USB_DESC_HID_LEN + USB_DESC_ENDPOINT_LEN,
+
+ USB_DESC_OTHER_SPEED_CONF_TOTAL_LEN = USB_DESC_OTHER_SPEED_CONF_LEN
+ + USB_DESC_INTERFACE_LEN,
+};
+
+enum usb_descr_attributes {
+ // Attributes (b7 - buspwr, b6 - selfpwr, b5 - rwu).
+ USB_DESC_ATTRIBUTES = 0xA0,
+ // 100 mA (div 2).
+ USB_DESC_POWER_CONSUMPTION = 50
+};
+
+enum usb_descr_numbers {
+ USB_DESC_CONFIG_COUNT = 1
+};
+
+static const BYTE CODE
+g_hid_report_desc[USB_DESCR_HID_REP_LEN] = {
+ // Pad #1 configuration.
+ 0x05, 0x01, // Usage page (Generic Desktop).
+ 0x09, 0x05, // Usage (Game Pad).
+ 0xa1, 0x01, // Collection (Application).
+ 0xa1, 0x00, // Collection (Physical).
+ 0x85, HID_REPORT_ID_GAMEPAD1, // Report id (1).
+ 0x05, 0x09, // Usage page (Button).
+ 0x19, 0x01, // Usage minimum (Button 1).
+ 0x29, 0x08, // Usage maximum (Button 8).
+ 0x15, 0x00, // Logical minimum (0).
+ 0x25, 0x01, // Logical maximum (1).
+ 0x95, HID_REPORT_BITS_COUNT, // Report count (8).
+ 0x75, 0x01, // Report size (1).
+ 0x81, 0x02, // Input (Data,Var,Abs).
+ 0xc0, // End collection.
+ 0xc0, // End collection.
+ // Pad #2 configuration.
+ 0x05, 0x01, // Usage page (Generic Desktop).
+ 0x09, 0x05, // Usage (Game Pad).
+ 0xa1, 0x01, // Collection (Application).
+ 0xa1, 0x00, // Collection (Physical).
+ 0x85, HID_REPORT_ID_GAMEPAD2, // Report id (2).
+ 0x05, 0x09, // Usage page (Button).
+ 0x19, 0x01, // Usage minimum (Button 1).
+ 0x29, 0x08, // Usage maximum (Button 8).
+ 0x15, 0x00, // Logical minimum (0).
+ 0x25, 0x01, // Logical maximum (1).
+ 0x95, HID_REPORT_BITS_COUNT, // Report count (8).
+ 0x75, 0x01, // Report size (1).
+ 0x81, 0x02, // Input (Data,Var,Abs).
+ 0xc0, // End collection
+ 0xc0 // End collection.
+};
+
+static const BYTE CODE
+g_device_desc[USB_DESC_DEVICE_TOTAL_LEN] = {
+ USB_DESC_DEVICE_LEN, // Descriptor length.
+ USB_DESC_DEVICE, // Descriptor type.
+ usb_word_lsb_get(USB_SPEC_BCD_VERSION), // USB BCD version, lo.
+ usb_word_msb_get(USB_SPEC_BCD_VERSION), // USB BCD version, hi.
+ 0x00, // Device class.
+ 0x00, // Device sub-class.
+ 0x00, // Device protocol.
+ MAX_EP0_SIZE, // Maximum packet size (ep0 size).
+ usb_word_lsb_get(USB_DEVICE_VID), // Vendor ID, lo.
+ usb_word_msb_get(USB_DEVICE_VID), // Vendor ID, hi.
+ usb_word_lsb_get(USB_DEVICE_PID), // Product ID, lo.
+ usb_word_msb_get(USB_DEVICE_PID), // Product ID, hi.
+ usb_word_lsb_get(USB_DEVICE_BCD_VERSION), // Device BCD version, lo.
+ usb_word_msb_get(USB_DEVICE_BCD_VERSION), // Device BCD version, hi.
+ USB_DESC_MFG_STRING_INDEX,
+ USB_DESC_PRODUCT_STRING_INDEX,
+ USB_DESC_SERIAL_STRING_INDEX,
+ USB_DESC_CONFIG_COUNT // Configurations count.
+};
+
+static const BYTE CODE
+g_device_qual_desc[USB_DESC_DEVICE_QUAL_TOTAL_LEN] = {
+ USB_DESC_DEVICE_QUAL_LEN, // Descriptor length.
+ USB_DESC_DEVICE_QUAL, // Descriptor type.
+ usb_word_lsb_get(USB_SPEC_BCD_VERSION), // USB BCD version, lo.
+ usb_word_msb_get(USB_SPEC_BCD_VERSION), // USB BCD version, hi.
+ 0x00, // Device class.
+ 0x00, // Device sub-class.
+ 0x00, // Device protocol.
+ MAX_EP0_SIZE, // Maximum packet size (ep0 size).
+ USB_DESC_CONFIG_COUNT, // Configurations count.
+ 0x00 // Reserved.
+};
+
+static const BYTE CODE
+g_config_desc[USB_DESC_CONF_TOTAL_LEN] = {
+ USB_DESC_CONF_LEN, // Descriptor length.
+ USB_DESC_CONF, // Descriptor type.
+ usb_word_lsb_get(USB_DESC_CONF_TOTAL_LEN), // Total length, lo.
+ usb_word_msb_get(USB_DESC_CONF_TOTAL_LEN), // Total length, hi.
+ 0x01, // Interfaces count.
+ HID_CONFIG_NUMBER, // Configuration number.
+ 0x00, // Configuration string index.
+ USB_DESC_ATTRIBUTES, // Attributes.
+ USB_DESC_POWER_CONSUMPTION, // Power consumption.
+
+ // Interface descriptor.
+ USB_DESC_INTERFACE_LEN, // Descriptor length.
+ USB_DESC_INTERFACE, // Descriptor type.
+ HID_IFACE_NUMBER, // Zero-based index of this interfacce.
+ HID_ALT_IFACE_NUMBER, // Alternate setting.
+ 0x01, // End points count (ep1 in).
+ 0x03, // Class code (HID).
+ 0x00, // Subclass code (boot).
+ 0x00, // Protocol code (none).
+ 0x00, // Interface string descriptor index.
+
+ // HID descriptor.
+ USB_DESC_HID_LEN, // Descriptor length.
+ USB_DESC_HID, // Descriptor type.
+ usb_word_lsb_get(USB_HID_BCD_VERSION), // HID class BCD version, lo.
+ usb_word_msb_get(USB_HID_BCD_VERSION), // HID class BCD version, hi.
+ 0x00, // Country code (HW country code).
+ 0x01, // Number of HID class descriptors to follow.
+ USB_DESC_REPORT, // Repord descriptor type (HID).
+ usb_word_lsb_get(USB_DESCR_HID_REP_LEN), // Report descriptor total length, lo.
+ usb_word_msb_get(USB_DESCR_HID_REP_LEN), // Report descriptor total length, hi.
+
+ // End point descriptor.
+ USB_DESC_ENDPOINT_LEN, // Descriptor length.
+ USB_DESC_ENDPOINT, // Descriptor type.
+ HID_EP_IN, // End point address (ep1 in).
+ 0x03, // End point type (interrupt).
+ usb_word_lsb_get(MAX_EP1_SIZE), // Maximum packet size, lo (ep1 size).
+ usb_word_msb_get(MAX_EP1_SIZE), // Maximum packet size, hi (ep1 size).
+ 0x01 // Polling interval (1 ms).
+};
+
+static const BYTE CODE
+g_other_config_desc[USB_DESC_OTHER_SPEED_CONF_TOTAL_LEN] = {
+ USB_DESC_OTHER_SPEED_CONF_LEN, // Descriptor length.
+ USB_DESC_OTHER_SPEED_CONF, // Descriptor type.
+ usb_word_lsb_get(USB_DESC_OTHER_SPEED_CONF_TOTAL_LEN), // Total length, lo.
+ usb_word_msb_get(USB_DESC_OTHER_SPEED_CONF_TOTAL_LEN), // Total length, hi.
+ 0x01, // Interfaces number.
+ 0x01, // Configuration number.
+ 0x00, // Configuration string index.
+ USB_DESC_ATTRIBUTES, // Attributes.
+ USB_DESC_POWER_CONSUMPTION, // Power consumption.
+
+ // Interface descriptor.
+ USB_DESC_INTERFACE_LEN, // Descriptor length.
+ USB_DESC_INTERFACE, // Descriptor type.
+ 0x00, // Zero-based index of this interfacce.
+ 0x00, // Alternate setting.
+ 0x00, // End points number (only ep0).
+ 0x00, // Class code.
+ 0x00, // Subclass code.USB_DESC_OTHER_SPEED_CONFIGURATION
+ 0x00, // Protocol code.
+ 0x00 // Interface string descriptor index.
+};
+
+static const BYTE CODE
+g_lang_id_desc[] = {
+ 0x04, // Descriptor length.
+ USB_DESC_STRING, // Descriptor type.
+ usb_word_lsb_get(USB_LANG_ID), // Language id, lo.
+ usb_word_msb_get(USB_LANG_ID) // Language id, hi.
+};
+
+static const BYTE CODE
+g_manuf_str_desc[] = {
+ 0x18, // Descriptor length.
+ USB_DESC_STRING, // Descriptor type.
+ // Unicode string:
+ 'Q', 0, 'B', 0, 'S', 0, ' ', 0,
+ 'e', 0, 'x', 0, 'a', 0, 'm', 0, 'p', 0, 'l', 0, 'e', 0
+};
+
+static const BYTE CODE
+g_product_str_desc[] = {
+ 0x1A, // Descriptor length.
+ USB_DESC_STRING, // Descriptor type.
+ // Unicode string:
+ 'N', 0, 'E', 0, 'S', 0, ' ', 0,
+ 'G', 0, 'a', 0, 'm', 0, 'e', 0,
+ 'P', 0, 'a', 0, 'd', 0, 's', 0
+};
+
+static const BYTE CODE
+g_serialno_str_desc[] = {
+ 0x1A, // Descriptor length.
+ USB_DESC_STRING, // Descriptor type.
+ // Unicode string:
+ '0', 0 ,'1', 0, '0', 0, '2', 0, '0', 0, '3', 0,
+ '0', 0, '4', 0, '0', 0, '5', 0, '0', 0, '6', 0
+};
+
+static const BYTE CODE *ep0_string_desc_get(void)
+{
+ switch (SETUPDAT[2]) {
+ case USB_DESC_LANGID_STRING_INDEX:
+ return g_lang_id_desc;
+ case USB_DESC_MFG_STRING_INDEX:
+ return g_manuf_str_desc;
+ case USB_DESC_PRODUCT_STRING_INDEX:
+ return g_product_str_desc;
+ case USB_DESC_SERIAL_STRING_INDEX:
+ return g_serialno_str_desc;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static const BYTE CODE *ep0_config_desc_get(BOOL other)
+{
+ if (!other) {
+ if (SETUPDAT[2] == 0) {
+ return usb_is_high_speed() ? g_config_desc
+ : g_other_config_desc;
+ }
+ } else {
+ return usb_is_high_speed() ? g_other_config_desc
+ : g_config_desc;
+ }
+
+ return NULL;
+}
+
+const BYTE CODE *hid_ep0_std_desc_get(void)
+{
+ switch (SETUPDAT[3]) {
+ case USB_DESC_DEVICE:
+ return g_device_desc;
+ case USB_DESC_CONF:
+ return ep0_config_desc_get(FALSE);
+ case USB_DESC_STRING:
+ return ep0_string_desc_get();
+ case USB_DESC_DEVICE_QUAL:
+ return g_device_qual_desc;
+ case USB_DESC_OTHER_SPEED_CONF:
+ return ep0_config_desc_get(TRUE);
+ case USB_DESC_HID:
+ return &g_config_desc[USB_DESC_CONF_LEN
+ + USB_DESC_INTERFACE_LEN];
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+const BYTE CODE *hid_ep0_report_desc_get(WORD *length)
+{
+ *length = sizeof(g_hid_report_desc);
+ return g_hid_report_desc;
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/hidep0.c b/examples/baremetal/cy7c68013a/nes-gamepads/hidep0.c
new file mode 100644
index 000000000..8648f6257
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/hidep0.c
@@ -0,0 +1,377 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "hid.h"
+#include "core.h"
+#include "usb.h"
+
+static BOOL g_rwuen = FALSE;
+static BOOL g_selfpwr = FALSE;
+
+static void ep0_ep1in_reset(void)
+{
+ EP1INCS &= ~bmEPBUSY;
+ sync_delay();
+ usp_ep_reset_toggle(HID_EP_IN);
+ sync_delay();
+}
+
+// Get status handle.
+
+static BYTE *ep_address_get(BYTE ep)
+{
+ const BYTE ep_num = ep & ~bmSETUP_DIR;
+ switch (ep_num) {
+ case 0:
+ return (BYTE *)&EP0CS;
+ case 1:
+ return (ep & bmSETUP_DIR)
+ ? (BYTE *)&EP1INCS
+ : (BYTE *)&EP1OUTCS;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static BOOL ep0_dev_status_get(void)
+{
+ BYTE status = 0;
+ if (g_selfpwr)
+ status |= USB_STATUS_SELF_POWERED;
+ if (g_rwuen)
+ status |= USB_STATUS_REMOTE_WAKEUP;
+ EP0BUF[0] = status;
+ EP0BUF[1] = 0;
+ EP0BCH = 0;
+ EP0BCL = 2;
+ return TRUE;
+}
+
+static BOOL ep0_iface_status_get(void)
+{
+ EP0BUF[0] = 0;
+ EP0BUF[1] = 0;
+ EP0BCH = 0;
+ EP0BCL = 2;
+ return TRUE;
+}
+
+static BOOL ep0_ep_status_get(void)
+{
+ const volatile BYTE XDATA *pep =
+ (BYTE XDATA *)ep_address_get(SETUPDAT[4]);
+ if (pep) {
+ EP0BUF[0] = *pep & bmEPSTALL ? 1 : 0;
+ EP0BUF[1] = 0;
+ EP0BCH = 0;
+ EP0BCL = 2;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL ep0_get_status_proc(void)
+{
+ if ((SETUPDAT[0] & bmSETUP_TO_HOST) == 0)
+ return FALSE;
+
+ switch (SETUPDAT[0] & bmSETUP_RECIPIENT) {
+ case bmSETUP_DEVICE:
+ return ep0_dev_status_get();
+ case bmSETUP_IFACE:
+ return ep0_iface_status_get();
+ case bmSETUP_EP:
+ return ep0_ep_status_get();
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+// Clear feature handle.
+
+static BOOL ep0_dev_feature_clear(void)
+{
+ if (SETUPDAT[2] == USB_FEATURE_REMOTE_WAKEUP) {
+ g_rwuen = FALSE;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL ep0_ep_feature_clear(void)
+{
+ if (SETUPDAT[2] == USB_FEATURE_STALL) {
+ volatile BYTE XDATA *pep =
+ (BYTE XDATA *)ep_address_get(SETUPDAT[4]);
+ if (!pep)
+ return FALSE;
+ *pep &= ~bmEPSTALL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL ep0_clear_feature_proc(void)
+{
+ switch (SETUPDAT[0] & bmSETUP_RECIPIENT) {
+ case bmSETUP_DEVICE:
+ return ep0_dev_feature_clear();
+ case bmSETUP_EP:
+ return ep0_ep_feature_clear();
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+// Set feature handle.
+
+static BOOL ep0_dev_feature_set(void)
+{
+ switch (SETUPDAT[2]) {
+ case USB_FEATURE_REMOTE_WAKEUP:
+ g_rwuen = TRUE;
+ return TRUE;
+ case USB_FEATRUE_TEST_MODE:
+ // This is "test mode", just return the handshake.
+ return TRUE;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static BOOL ep0_ep_feature_set(void)
+{
+ if (SETUPDAT[2] == USB_FEATURE_STALL) {
+ volatile BYTE XDATA *pep =
+ (BYTE XDATA *)ep_address_get(SETUPDAT[4]);
+ if (!pep)
+ return FALSE;
+ *pep |= bmEPSTALL;
+ usp_ep_reset_toggle(SETUPDAT[4]);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL ep0_set_feature_proc(void)
+{
+ switch (SETUPDAT[0] & bmSETUP_RECIPIENT) {
+ case bmSETUP_DEVICE:
+ return ep0_dev_feature_set();
+ case bmSETUP_EP:
+ return ep0_ep_feature_set();
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+// Get descriptor handle.
+
+static BOOL ep0_std_descriptor_proc(void)
+{
+ const BYTE XDATA *pdesc =
+ (BYTE XDATA *)hid_ep0_std_desc_get();
+ if (pdesc) {
+ SUDPTRH = usb_word_msb_get(pdesc);
+ SUDPTRL = usb_word_lsb_get(pdesc);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL ep0_report_descriptor_proc(void)
+{
+ WORD i = 0;
+ WORD length = 0;
+ const BYTE XDATA *pdesc =
+ (BYTE XDATA *)hid_ep0_report_desc_get(&length);
+ if (pdesc) {
+ AUTOPTRH1 = usb_word_msb_get(pdesc);
+ AUTOPTRL1 = usb_word_lsb_get(pdesc);
+
+ for (i = 0; i < length; ++i)
+ EP0BUF[i] = XAUTODAT1;
+
+ EP0BCH = usb_word_msb_get(length);
+ EP0BCL = usb_word_lsb_get(length);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL ep0_get_descriptor_proc(void)
+{
+ switch (SETUPDAT[3]) {
+ case USB_DESC_DEVICE:
+ case USB_DESC_CONF:
+ case USB_DESC_STRING:
+ case USB_DESC_DEVICE_QUAL:
+ case USB_DESC_OTHER_SPEED_CONF:
+ case USB_DESC_HID:
+ return ep0_std_descriptor_proc();
+ case USB_DESC_REPORT:
+ return ep0_report_descriptor_proc();
+ }
+
+ return FALSE;
+}
+
+// Get configuration handle.
+
+static BOOL ep0_get_config_proc(void)
+{
+ // We only support configuration 1.
+ EP0BUF[0] = HID_CONFIG_NUMBER;
+ EP0BCH = 0;
+ EP0BCL = 1;
+ return TRUE;
+}
+
+// Set configuration handle.
+
+static BOOL ep0_set_config_proc(void)
+{
+ // We only support configuration 1.
+ if (SETUPDAT[2] != HID_CONFIG_NUMBER)
+ return FALSE;
+
+ return TRUE;
+}
+
+// Get interface handle.
+
+static BOOL ep0_get_iface_proc(void)
+{
+ if (SETUPDAT[4] != HID_IFACE_NUMBER)
+ return FALSE;
+
+ EP0BUF[0] = HID_ALT_IFACE_NUMBER;
+ EP0BCH = 0;
+ EP0BCL = 1;
+ return TRUE;
+}
+
+// Set interface handle.
+
+static BOOL ep0_set_iface_proc(void)
+{
+ if (SETUPDAT[4] != HID_IFACE_NUMBER)
+ return FALSE;
+
+ if (SETUPDAT[2] != HID_ALT_IFACE_NUMBER)
+ return FALSE;
+
+ ep0_ep1in_reset();
+ return TRUE;
+}
+
+static BOOL ep0_std_proc(void)
+{
+ switch (SETUPDAT[1]) {
+ case USB_SETUP_GET_STATUS:
+ return ep0_get_status_proc();
+ case USB_SETUP_CLEAR_FEATURE:
+ return ep0_clear_feature_proc();
+ case USB_SETUP_SET_FEATURE:
+ return ep0_set_feature_proc();
+ case USB_SETUP_SET_ADDRESS:
+ // Handles automatically by FX2.
+ return TRUE;
+ case USB_SETUP_GET_DESCRIPTOR:
+ return ep0_get_descriptor_proc();
+ case USB_SETUP_GET_CONFIGURATION:
+ return ep0_get_config_proc();
+ case USB_SETUP_SET_CONFIGURATION:
+ return ep0_set_config_proc();
+ case USB_SETUP_GET_INTERFACE:
+ return ep0_get_iface_proc();
+ case USB_SETUP_SET_INTERFACE:
+ return ep0_set_iface_proc();
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static BOOL ep0_setup(void)
+{
+ switch (SETUPDAT[0] & bmSETUP_TYPE) {
+ case bmSETUP_STANDARD:
+ return ep0_std_proc();
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+void hid_ep0_setup_task(void)
+{
+ if (!ep0_setup())
+ usb_ep0_stall();
+
+ usb_ep0_hsnack();
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/hidep1.c b/examples/baremetal/cy7c68013a/nes-gamepads/hidep1.c
new file mode 100644
index 000000000..790311144
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/hidep1.c
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "hid.h"
+
+struct hid_report {
+ const BYTE id;
+ BYTE buttons;
+ BYTE ready;
+};
+
+static struct hid_report g_reports[HID_REPORTS_COUNT] = {
+ {HID_REPORT_ID_GAMEPAD1, 0, FALSE},
+ {HID_REPORT_ID_GAMEPAD2, 0, FALSE}
+};
+
+static void ep1_report_send(BYTE index)
+{
+ if (!g_reports[index].ready)
+ return;
+
+ if (EP1INCS & bmEPBUSY)
+ return;
+
+ EP1INBUF[0] = g_reports[index].id;
+ EP1INBUF[1] = g_reports[index].buttons;
+ EP1INBC = 2;
+ g_reports[index].ready = FALSE;
+}
+
+void hid_ep1_task(void)
+{
+ BYTE index = 0;
+ for (index = 0; index < HID_REPORTS_COUNT; ++index)
+ ep1_report_send(index);
+}
+
+void hid_ep1_report_update(BYTE index, BYTE buttons)
+{
+ g_reports[index].buttons = buttons;
+ g_reports[index].ready = TRUE;
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/irqs.h b/examples/baremetal/cy7c68013a/nes-gamepads/irqs.h
new file mode 100644
index 000000000..4b5f96837
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/irqs.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FX2_IRQS_H
+#define FX2_IRQS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Standard interrupt numbers.
+#define INT0_IRQ 0 // External interrupt 0.
+#define TMR0_IRQ 1 // Timer 0 interrupt.
+#define INT1_IRQ 2 // External interrupt 1.
+#define TMR1_IRQ 3 // Timer 1 interrupt.
+#define COM0_IRQ 4 // Serial port 0 transmit or receive interrupt.
+#define TMR2_IRQ 5 // Timer 2 interrupt.
+#define WKUP_IRQ 6 // Resume interrupt.
+#define COM1_IRQ 7 // Serial port 1 transmit or receive interrupt.
+#define USB_IRQ 8 // USB interrupt.
+#define I2C_IRQ 9 // I2C bus interrupt.
+#define INT4_IRQ 10 // External interrupt 4.
+#define INT5_IRQ 11 // External interrupt 5.
+#define INT6_IRQ 12 // External interrupt 6.
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FX2_IRQS_H
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/main.c b/examples/baremetal/cy7c68013a/nes-gamepads/main.c
new file mode 100644
index 000000000..71d5b924d
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/main.c
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Allocate all registers once here (only for C51 compiler).
+#define DEFINE_REGS
+#include "regs.h"
+
+#include "core.h"
+#include "gpio.h"
+#include "usb.h"
+
+static void hw_init(void)
+{
+ usb_disconnect();
+ code_all_irq_disable();
+
+ core_init();
+ gpio_init();
+ usb_init();
+
+ usb_connect();
+ code_all_irq_enable();
+}
+
+static void hw_loop_exec(void)
+{
+ while (TRUE) {
+ gpio_task();
+ usb_task();
+ }
+}
+
+int main(void)
+{
+ hw_init();
+ hw_loop_exec();
+ return 0;
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/nes-gamepads.qbs b/examples/baremetal/cy7c68013a/nes-gamepads/nes-gamepads.qbs
new file mode 100644
index 000000000..0d7994033
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/nes-gamepads.qbs
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import qbs
+
+CppApplication {
+ condition: {
+ if (!qbs.architecture.contains("mcs51"))
+ return false;
+ return qbs.toolchain.contains("iar")
+ || qbs.toolchain.contains("keil")
+ || qbs.toolchain.contains("sdcc")
+ }
+ name: "cy7c68013a-nes-gamepads"
+ cpp.positionIndependentCode: false
+
+ //
+ // IAR-specific properties and sources.
+ //
+
+ Properties {
+ condition: qbs.toolchain.contains("iar")
+ cpp.commonCompilerFlags: ["-e"]
+ cpp.staticLibraries: [
+ cpp.toolchainInstallPath + "/../lib/clib/cl-pli-nsid-1e16x01"
+ ]
+ cpp.driverLinkerFlags: [
+ "-D_IDATA_STACK_SIZE=0x40",
+ "-D_PDATA_STACK_SIZE=0x80",
+ "-D_XDATA_STACK_SIZE=0xEFF",
+ "-D_XDATA_HEAP_SIZE=0xFF",
+ "-D_EXTENDED_STACK_SIZE=0",
+ "-D_EXTENDED_STACK_START=0"
+ ]
+ }
+
+ Group {
+ name: "IAR Linker Script"
+ condition: qbs.toolchain.contains("iar")
+ prefix: cpp.toolchainInstallPath + "/../config/devices/cypress/"
+ fileTags: ["linkerscript"]
+ files: ["lnk51ew_CY7C68013A.xcl"]
+ }
+
+ //
+ // KEIL-specific properties and sources.
+ //
+
+ Properties {
+ condition: qbs.toolchain.contains("keil")
+ cpp.driverLinkerFlags: [
+ "RAMSIZE(256)",
+ "CODE(0x80)",
+ "XDATA(0x1000)"
+ ]
+ }
+
+ //
+ // SDCC-specific properties and sources.
+ //
+
+ Properties {
+ condition: qbs.toolchain.contains("sdcc")
+ cpp.driverLinkerFlags: [
+ "--code-loc", "0x80",
+ "--xram-loc", "0x1000"
+ ]
+ }
+
+ //
+ // Common code.
+ //
+
+ files: [
+ "core.c",
+ "core.h",
+ "defs.h",
+ "gpio.c",
+ "gpio.h",
+ "hid.c",
+ "hid.h",
+ "hiddesc.c",
+ "hidep0.c",
+ "hidep1.c",
+ "irqs.h",
+ "main.c",
+ "regs.h",
+ "usb.c",
+ "usb.h",
+ ]
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/regs.h b/examples/baremetal/cy7c68013a/nes-gamepads/regs.h
new file mode 100644
index 000000000..98e40f0ae
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/regs.h
@@ -0,0 +1,779 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FX2_REGS_H
+#define FX2_REGS_H
+
+#include "defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// XDATA registers.
+//
+
+XDATA_REG(GPIF_WAVE_DATA, 0xE400) // GPIF waveform descriptor.
+XDATA_REG(RES_WAVEDATA_END, 0xE480) // Reserved.
+
+// General configuration.
+
+XDATA_REG(CPUCS, 0xE600) // Control & status.
+XDATA_REG(IFCONFIG, 0xE601) // Interface configuration.
+XDATA_REG(PINFLAGSAB, 0xE602) // FIFO FLAGA and FLAGB assignments.
+XDATA_REG(PINFLAGSCD, 0xE603) // FIFO FLAGC and FLAGD assignments.
+XDATA_REG(FIFORESET, 0xE604) // Restore FIFOS to default state.
+XDATA_REG(BREAKPT, 0xE605) // Breakpoint.
+XDATA_REG(BPADDRH, 0xE606) // Breakpoint address H.
+XDATA_REG(BPADDRL, 0xE607) // Breakpoint address L.
+XDATA_REG(UART230, 0xE608) // 230 Kbaud clock for T0,T1,T2.
+XDATA_REG(FIFOPINPOLAR, 0xE609) // FIFO polarities.
+XDATA_REG(REVID, 0xE60A) // Chip revision.
+XDATA_REG(REVCTL, 0xE60B) // Chip revision control.
+
+// Endpoint configuration.
+
+XDATA_REG(EP1OUTCFG, 0xE610) // Endpoint 1-out configuration.
+XDATA_REG(EP1INCFG, 0xE611) // Endpoint 1-in configuration.
+XDATA_REG(EP2CFG, 0xE612) // Endpoint 2 configuration.
+XDATA_REG(EP4CFG, 0xE613) // Endpoint 4 configuration.
+XDATA_REG(EP6CFG, 0xE614) // Endpoint 6 configuration.
+XDATA_REG(EP8CFG, 0xE615) // Endpoint 8 configuration.
+XDATA_REG(EP2FIFOCFG, 0xE618) // Endpoint 2 FIFO configuration.
+XDATA_REG(EP4FIFOCFG, 0xE619) // Endpoint 4 FIFO configuration.
+XDATA_REG(EP6FIFOCFG, 0xE61A) // Endpoint 6 FIFO configuration.
+XDATA_REG(EP8FIFOCFG, 0xE61B) // Endpoint 8 FIFO configuration.
+XDATA_REG(EP2AUTOINLENH, 0xE620) // Endpoint 2 packet length H (in only).
+XDATA_REG(EP2AUTOINLENL, 0xE621) // Endpoint 2 packet length L (in only).
+XDATA_REG(EP4AUTOINLENH, 0xE622) // Endpoint 4 packet length H (in only).
+XDATA_REG(EP4AUTOINLENL, 0xE623) // Endpoint 4 packet length L (in only).
+XDATA_REG(EP6AUTOINLENH, 0xE624) // Endpoint 6 packet length H (in only).
+XDATA_REG(EP6AUTOINLENL, 0xE625) // Endpoint 6 packet length L (in only).
+XDATA_REG(EP8AUTOINLENH, 0xE626) // Endpoint 8 packet length H (in only).
+XDATA_REG(EP8AUTOINLENL, 0xE627) // Endpoint 8 packet length L (in only).
+XDATA_REG(EP2FIFOPFH, 0xE630) // EP2 programmable flag trigger H.
+XDATA_REG(EP2FIFOPFL, 0xE631) // EP2 programmable flag trigger L.
+XDATA_REG(EP4FIFOPFH, 0xE632) // EP4 programmable flag trigger H.
+XDATA_REG(EP4FIFOPFL, 0xE633) // EP4 programmable flag trigger L.
+XDATA_REG(EP6FIFOPFH, 0xE634) // EP6 programmable flag trigger H.
+XDATA_REG(EP6FIFOPFL, 0xE635) // EP6 programmable flag trigger L.
+XDATA_REG(EP8FIFOPFH, 0xE636) // EP8 programmable flag trigger H.
+XDATA_REG(EP8FIFOPFL, 0xE637) // EP8 programmable flag trigger L.
+XDATA_REG(EP2ISOINPKTS, 0xE640) // EP2 (if ISO) in packets per frame (1-3).
+XDATA_REG(EP4ISOINPKTS, 0xE641) // EP4 (if ISO) in packets per frame (1-3).
+XDATA_REG(EP6ISOINPKTS, 0xE642) // EP6 (if ISO) in packets per frame (1-3).
+XDATA_REG(EP8ISOINPKTS, 0xE643) // EP8 (if ISO) in packets per frame (1-3).
+XDATA_REG(INPKTEND, 0xE648) // Force in packet end.
+XDATA_REG(OUTPKTEND, 0xE649) // Force out packet end.
+
+// Interrupts.
+
+XDATA_REG(EP2FIFOIE, 0xE650) // Endpoint 2 flag interrupt enable.
+XDATA_REG(EP2FIFOIRQ, 0xE651) // Endpoint 2 flag interrupt request.
+XDATA_REG(EP4FIFOIE, 0xE652) // Endpoint 4 flag interrupt enable.
+XDATA_REG(EP4FIFOIRQ, 0xE653) // Endpoint 4 flag interrupt request.
+XDATA_REG(EP6FIFOIE, 0xE654) // Endpoint 6 flag interrupt enable.
+XDATA_REG(EP6FIFOIRQ, 0xE655) // Endpoint 6 flag interrupt request.
+XDATA_REG(EP8FIFOIE, 0xE656) // Endpoint 8 flag interrupt enable.
+XDATA_REG(EP8FIFOIRQ, 0xE657) // Endpoint 8 flag interrupt request.
+XDATA_REG(IBNIE, 0xE658) // IN-BULK-NAK interrupt enable.
+XDATA_REG(IBNIRQ, 0xE659) // IN-BULK-NAK interrupt request.
+XDATA_REG(NAKIE, 0xE65A) // Endpoint ping NAK interrupt enable.
+XDATA_REG(NAKIRQ, 0xE65B) // Endpoint ping NAK interrupt request.
+XDATA_REG(USBIE, 0xE65C) // USB Int enables.
+XDATA_REG(USBIRQ, 0xE65D) // USB interrupt requests.
+XDATA_REG(EPIE, 0xE65E) // Endpoint interrupt enables.
+XDATA_REG(EPIRQ, 0xE65F) // Endpoint interrupt requests.
+XDATA_REG(GPIFIE, 0xE660) // GPIF interrupt enable.
+XDATA_REG(GPIFIRQ, 0xE661) // GPIF interrupt request.
+XDATA_REG(USBERRIE, 0xE662) // USB error interrupt enables.
+XDATA_REG(USBERRIRQ, 0xE663) // USB error interrupt requests.
+XDATA_REG(ERRCNTLIM, 0xE664) // USB error counter and limit.
+XDATA_REG(CLRERRCNT, 0xE665) // Clear error counter EC[3..0].
+XDATA_REG(INT2IVEC, 0xE666) // Interrupt 2 (USB) autovector.
+XDATA_REG(INT4IVEC, 0xE667) // Interrupt 4 (FIFOS & GPIF) autovector.
+XDATA_REG(INTSETUP, 0xE668) // interrupt 2 & 4 setup.
+
+// Input/Output.
+
+XDATA_REG(PORTACFG, 0xE670) // I/O PORTA alternate configuration.
+XDATA_REG(PORTCCFG, 0xE671) // I/O PORTC alternate configuration.
+XDATA_REG(PORTECFG, 0xE672) // I/O PORTE alternate configuration.
+XDATA_REG(I2CS, 0xE678) // Bus control & status.
+XDATA_REG(I2DAT, 0xE679) // Bus data.
+XDATA_REG(I2CTL, 0xE67A) // Bus control.
+XDATA_REG(XAUTODAT1, 0xE67B) // Autoptr1 movx access.
+XDATA_REG(XAUTODAT2, 0xE67C) // Autoptr2 movx access.
+
+// USB Control.
+
+XDATA_REG(USBCS, 0xE680) // USB control & status.
+XDATA_REG(SUSPEND, 0xE681) // Put chip into suspend.
+XDATA_REG(WAKEUPCS, 0xE682) // Wakeup source and polarity.
+XDATA_REG(TOGCTL, 0xE683) // Toggle control.
+XDATA_REG(USBFRAMEH, 0xE684) // USB frame count H.
+XDATA_REG(USBFRAMEL, 0xE685) // USB frame count L.
+XDATA_REG(MICROFRAME, 0xE686) // Microframe count, 0-7.
+XDATA_REG(FNADDR, 0xE687) // USB function address.
+
+// Endpoints.
+
+XDATA_REG(EP0BCH, 0xE68A) // Endpoint 0 byte count H.
+XDATA_REG(EP0BCL, 0xE68B) // Endpoint 0 byte count L.
+XDATA_REG(EP1OUTBC, 0xE68D) // Endpoint 1 out byte count.
+XDATA_REG(EP1INBC, 0xE68F) // Endpoint 1 in byte count.
+XDATA_REG(EP2BCH, 0xE690) // Endpoint 2 byte count H.
+XDATA_REG(EP2BCL, 0xE691) // Endpoint 2 byte count L.
+XDATA_REG(EP4BCH, 0xE694) // Endpoint 4 byte count H.
+XDATA_REG(EP4BCL, 0xE695) // Endpoint 4 byte count L.
+XDATA_REG(EP6BCH, 0xE698) // Endpoint 6 byte count H.
+XDATA_REG(EP6BCL, 0xE699) // Endpoint 6 byte count L.
+XDATA_REG(EP8BCH, 0xE69C) // Endpoint 8 byte count H.
+XDATA_REG(EP8BCL, 0xE69D) // Endpoint 8 byte count L.
+XDATA_REG(EP0CS, 0xE6A0) // Endpoint control and status.
+XDATA_REG(EP1OUTCS, 0xE6A1) // Endpoint 1 out control and status.
+XDATA_REG(EP1INCS, 0xE6A2) // Endpoint 1 in control and status.
+XDATA_REG(EP2CS, 0xE6A3) // Endpoint 2 control and status.
+XDATA_REG(EP4CS, 0xE6A4) // Endpoint 4 control and status.
+XDATA_REG(EP6CS, 0xE6A5) // Endpoint 6 control and status.
+XDATA_REG(EP8CS, 0xE6A6) // Endpoint 8 control and status.
+XDATA_REG(EP2FIFOFLGS, 0xE6A7) // Endpoint 2 flags.
+XDATA_REG(EP4FIFOFLGS, 0xE6A8) // Endpoint 4 flags.
+XDATA_REG(EP6FIFOFLGS, 0xE6A9) // Endpoint 6 flags.
+XDATA_REG(EP8FIFOFLGS, 0xE6AA) // Endpoint 8 flags.
+XDATA_REG(EP2FIFOBCH, 0xE6AB) // EP2 FIFO total byte count H.
+XDATA_REG(EP2FIFOBCL, 0xE6AC) // EP2 FIFO total byte count L.
+XDATA_REG(EP4FIFOBCH, 0xE6AD) // EP4 FIFO total byte count H.
+XDATA_REG(EP4FIFOBCL, 0xE6AE) // EP4 FIFO total byte count L.
+XDATA_REG(EP6FIFOBCH, 0xE6AF) // EP6 FIFO total byte count H.
+XDATA_REG(EP6FIFOBCL, 0xE6B0) // EP6 FIFO total byte count L.
+XDATA_REG(EP8FIFOBCH, 0xE6B1) // EP8 FIFO total byte count H.
+XDATA_REG(EP8FIFOBCL, 0xE6B2) // EP8 FIFO total byte count L.
+XDATA_REG(SUDPTRH, 0xE6B3) // Setup data pointer high address byte.
+XDATA_REG(SUDPTRL, 0xE6B4) // Setup data pointer low address byte.
+XDATA_REG(SUDPTRCTL, 0xE6B5) // Setup data pointer auto mode.
+XDATA_REG(SETUPDAT[8], 0xE6B8) // 8 bytes of setup data.
+
+// GPIF.
+
+XDATA_REG(GPIFWFSELECT, 0xE6C0) // Waveform selector.
+XDATA_REG(GPIFIDLECS, 0xE6C1) // GPIF done, GPIF idle drive mode.
+XDATA_REG(GPIFIDLECTL, 0xE6C2) // Inactive bus, ctl states.
+XDATA_REG(GPIFCTLCFG, 0xE6C3) // CTL out pin drive.
+XDATA_REG(GPIFADRH, 0xE6C4) // GPIF address H.
+XDATA_REG(GPIFADRL, 0xE6C5) // GPIF address L.
+
+XDATA_REG(GPIFTCB3, 0xE6CE) // GPIF transaction count byte 3.
+XDATA_REG(GPIFTCB2, 0xE6CF) // GPIF transaction count byte 2.
+XDATA_REG(GPIFTCB1, 0xE6D0) // GPIF transaction count byte 1.
+XDATA_REG(GPIFTCB0, 0xE6D1) // GPIF transaction count byte 0.
+
+XDATA_REG(EP2GPIFFLGSEL, 0xE6D2) // EP2 GPIF flag select.
+XDATA_REG(EP2GPIFPFSTOP, 0xE6D3) // Stop GPIF EP2 transaction on prog flag.
+XDATA_REG(EP2GPIFTRIG, 0xE6D4) // EP2 FIFO trigger.
+XDATA_REG(EP4GPIFFLGSEL, 0xE6DA) // EP4 GPIF flag select.
+XDATA_REG(EP4GPIFPFSTOP, 0xE6DB) // Stop GPIF EP4 transaction on prog flag.
+XDATA_REG(EP4GPIFTRIG, 0xE6DC) // EP4 FIFO trigger.
+XDATA_REG(EP6GPIFFLGSEL, 0xE6E2) // EP6 GPIF Flag select.
+XDATA_REG(EP6GPIFPFSTOP, 0xE6E3) // Stop GPIF EP6 transaction on prog flag.
+XDATA_REG(EP6GPIFTRIG, 0xE6E4) // EP6 FIFO trigger.
+XDATA_REG(EP8GPIFFLGSEL, 0xE6EA) // EP8 GPIF flag select.
+XDATA_REG(EP8GPIFPFSTOP, 0xE6EB) // Stop GPIF EP8 transaction on prog flag.
+XDATA_REG(EP8GPIFTRIG, 0xE6EC) // EP8 FIFO trigger.
+XDATA_REG(XGPIFSGLDATH, 0xE6F0) // GPIF data H (16-bit mode only).
+XDATA_REG(XGPIFSGLDATLX, 0xE6F1) // Read/write GPIF data L & trigger transac.
+XDATA_REG(XGPIFSGLDATLNOX, 0xE6F2) // Read GPIF data L, no transac trigger.
+XDATA_REG(GPIFREADYCFG, 0xE6F3) // Internal RDY,Sync/Async, RDY5CFG.
+XDATA_REG(GPIFREADYSTAT, 0xE6F4) // RDY pin states.
+XDATA_REG(GPIFABORT, 0xE6F5) // Abort GPIF cycles.
+
+// UDMA.
+
+XDATA_REG(FLOWSTATE, 0xE6C6) // Defines GPIF flow state.
+XDATA_REG(FLOWLOGIC, 0xE6C7) // Defines flow/hold decision criteria.
+XDATA_REG(FLOWEQ0CTL, 0xE6C8) // CTL states during active flow state.
+XDATA_REG(FLOWEQ1CTL, 0xE6C9) // CTL states during hold flow state.
+XDATA_REG(FLOWHOLDOFF, 0xE6CA) // Holdoff configuration.
+XDATA_REG(FLOWSTB, 0xE6CB) // CTL/RDY signal to use as master data strobe.
+XDATA_REG(FLOWSTBEDGE, 0xE6CC) // Defines active master strobe edge.
+XDATA_REG(FLOWSTBHPERIOD, 0xE6CD) // Half period of output master strobe.
+XDATA_REG(GPIFHOLDAMOUNT, 0xE60C) // Data delay shift.
+XDATA_REG(UDMACRCH, 0xE67D) // CRC upper byte.
+XDATA_REG(UDMACRCL, 0xE67E) // CRC lower byte.
+XDATA_REG(UDMACRCQUAL, 0xE67F) // UDMA in only, host terminated use only.
+
+// Endpoint buffers.
+#define MAX_EP0_SIZE 64
+#define MAX_EP1_SIZE 64
+#define MAX_EP2468_SIZE 1024
+
+XDATA_REG(EP0BUF[MAX_EP0_SIZE], 0xE740) // EP0 buffer (in or out).
+XDATA_REG(EP1OUTBUF[MAX_EP1_SIZE], 0xE780) // EP1 buffer (out only).
+XDATA_REG(EP1INBUF[MAX_EP1_SIZE], 0xE7C0) // EP1 buffer (in only).
+XDATA_REG(EP2FIFOBUF[MAX_EP2468_SIZE], 0xF000) // 512/1024-byte EP2 buffer (in or out).
+XDATA_REG(EP4FIFOBUF[MAX_EP2468_SIZE], 0xF400) // 512 byte EP4 buffer (in or out).
+XDATA_REG(EP6FIFOBUF[MAX_EP2468_SIZE], 0xF800) // 512/1024-byte EP6 buffer (in or out).
+XDATA_REG(EP8FIFOBUF[MAX_EP2468_SIZE], 0xFC00) // 512 byte EP8 buffer (in or out).
+
+// Error correction code (ECC) registers (FX2LP/FX1 only).
+
+XDATA_REG(ECCCFG, 0xE628) // ECC configuration.
+XDATA_REG(ECCRESET, 0xE629) // ECC reset.
+XDATA_REG(ECC1B0, 0xE62A) // ECC1 byte 0.
+XDATA_REG(ECC1B1, 0xE62B) // ECC1 byte 1.
+XDATA_REG(ECC1B2, 0xE62C) // ECC1 byte 2.
+XDATA_REG(ECC2B0, 0xE62D) // ECC2 byte 0.
+XDATA_REG(ECC2B1, 0xE62E) // ECC2 byte 1.
+XDATA_REG(ECC2B2, 0xE62F) // ECC2 byte 2.
+
+// Feature registers(FX2LP/FX1 only).
+
+XDATA_REG(GPCR2, 0xE50D) // Chip features.
+
+//
+// SFR registers.
+//
+
+SPEC_FUN_REG(IOA, 0x80) // Port A.
+SPEC_FUN_REG_BIT(PA0, 0x80, 0)
+SPEC_FUN_REG_BIT(PA1, 0x80, 1)
+SPEC_FUN_REG_BIT(PA2, 0x80, 2)
+SPEC_FUN_REG_BIT(PA3, 0x80, 3)
+SPEC_FUN_REG_BIT(PA4, 0x80, 4)
+SPEC_FUN_REG_BIT(PA5, 0x80, 5)
+SPEC_FUN_REG_BIT(PA6, 0x80, 6)
+SPEC_FUN_REG_BIT(PA7, 0x80, 7)
+
+SPEC_FUN_REG(SP, 0x81) // Stack pointer.
+SPEC_FUN_REG(DPL, 0x82) // Data pointer 0 L.
+SPEC_FUN_REG(DPH, 0x83) // Data pointer 0 H.
+SPEC_FUN_REG(DPL1, 0x84) // Data pointer 1 L.
+SPEC_FUN_REG(DPH1, 0x85) // Data pointer 1 L.
+SPEC_FUN_REG(DPS, 0x86) // Data pointer 0/1 select.
+SPEC_FUN_REG(PCON, 0x87) // Power control.
+
+SPEC_FUN_REG(TCON, 0x88) // Timer/counter control.
+SPEC_FUN_REG_BIT(IT0, 0x88, 0)
+SPEC_FUN_REG_BIT(IE0, 0x88, 1)
+SPEC_FUN_REG_BIT(IT1, 0x88, 2)
+SPEC_FUN_REG_BIT(IE1, 0x88, 3)
+SPEC_FUN_REG_BIT(TR0, 0x88, 4)
+SPEC_FUN_REG_BIT(TF0, 0x88, 5)
+SPEC_FUN_REG_BIT(TR1, 0x88, 6)
+SPEC_FUN_REG_BIT(TF1, 0x88, 7)
+
+SPEC_FUN_REG(TMOD, 0x89) // Timer/counter mode control.
+SPEC_FUN_REG(TL0, 0x8A) // Timer 0 reload L.
+SPEC_FUN_REG(TL1, 0x8B) // Timer 1 reload L.
+SPEC_FUN_REG(TH0, 0x8C) // Timer 0 reload H.
+SPEC_FUN_REG(TH1, 0x8D) // Timer 1 reload H.
+SPEC_FUN_REG(CKCON, 0x8E) // Clock control.
+
+SPEC_FUN_REG(IOB, 0x90) // Port B.
+SPEC_FUN_REG_BIT(PB0, 0x90, 0)
+SPEC_FUN_REG_BIT(PB1, 0x90, 1)
+SPEC_FUN_REG_BIT(PB2, 0x90, 2)
+SPEC_FUN_REG_BIT(PB3, 0x90, 3)
+SPEC_FUN_REG_BIT(PB4, 0x90, 4)
+SPEC_FUN_REG_BIT(PB5, 0x90, 5)
+SPEC_FUN_REG_BIT(PB6, 0x90, 6)
+SPEC_FUN_REG_BIT(PB7, 0x90, 7)
+
+SPEC_FUN_REG(EXIF, 0x91) // External interrupt flag.
+SPEC_FUN_REG(MPAGE, 0x92) // Upper address page of movx.
+
+SPEC_FUN_REG(SCON0, 0x98) // Serial port 0 control.
+SPEC_FUN_REG_BIT(RI, 0x98, 0)
+SPEC_FUN_REG_BIT(TI, 0x98, 1)
+SPEC_FUN_REG_BIT(RB8, 0x98, 2)
+SPEC_FUN_REG_BIT(TB8, 0x98, 3)
+SPEC_FUN_REG_BIT(REN, 0x98, 4)
+SPEC_FUN_REG_BIT(SM2, 0x98, 5)
+SPEC_FUN_REG_BIT(SM1, 0x98, 6)
+SPEC_FUN_REG_BIT(SM0, 0x98, 7)
+
+SPEC_FUN_REG(SBUF0, 0x99) // Serial port 0 data buffer.
+
+SPEC_FUN_REG(AUTOPTRH1, 0x9A) // Auto-pointer 1 address H.
+SPEC_FUN_REG(AUTOPTRL1, 0x9B) // Auto-pointer 1 address L.
+SPEC_FUN_REG(AUTOPTRH2, 0x9D) // Auto-pointer 2 address H.
+SPEC_FUN_REG(AUTOPTRL2, 0x9E) // Auto-pointer 2 address L.
+
+SPEC_FUN_REG(IOC, 0xA0) // Port C.
+SPEC_FUN_REG_BIT(PC0, 0xA0, 0)
+SPEC_FUN_REG_BIT(PC1, 0xA0, 1)
+SPEC_FUN_REG_BIT(PC2, 0xA0, 2)
+SPEC_FUN_REG_BIT(PC3, 0xA0, 3)
+SPEC_FUN_REG_BIT(PC4, 0xA0, 4)
+SPEC_FUN_REG_BIT(PC5, 0xA0, 5)
+SPEC_FUN_REG_BIT(PC6, 0xA0, 6)
+SPEC_FUN_REG_BIT(PC7, 0xA0, 7)
+
+SPEC_FUN_REG(INT2CLR, 0xA1) // Interrupt 2 clear.
+SPEC_FUN_REG(INT4CLR, 0xA2) // Interrupt 4 clear.
+
+SPEC_FUN_REG(IE, 0xA8) // Interrupt enable.
+SPEC_FUN_REG_BIT(EX0, 0xA8, 0)
+SPEC_FUN_REG_BIT(ET0, 0xA8, 1)
+SPEC_FUN_REG_BIT(EX1, 0xA8, 2)
+SPEC_FUN_REG_BIT(ET1, 0xA8, 3)
+SPEC_FUN_REG_BIT(ES0, 0xA8, 4)
+SPEC_FUN_REG_BIT(ET2, 0xA8, 5)
+SPEC_FUN_REG_BIT(ES1, 0xA8, 6)
+SPEC_FUN_REG_BIT(EA, 0xA8, 7)
+
+SPEC_FUN_REG(EP2468STAT, 0xAA) // Endpoint 2,4,6,8 status flags.
+SPEC_FUN_REG(EP24FIFOFLGS, 0xAB) // Endpoint 2,4 slave FIFO status flags.
+SPEC_FUN_REG(EP68FIFOFLGS, 0xAC) // Endpoint 6,8 slave FIFO status flags.
+SPEC_FUN_REG(AUTOPTRSETUP, 0xAF) // Auto-pointer 1,2 setup.
+
+SPEC_FUN_REG(IOD, 0xB0) // Port D.
+SPEC_FUN_REG_BIT(PD0, 0xB0, 0)
+SPEC_FUN_REG_BIT(PD1, 0xB0, 1)
+SPEC_FUN_REG_BIT(PD2, 0xB0, 2)
+SPEC_FUN_REG_BIT(PD3, 0xB0, 3)
+SPEC_FUN_REG_BIT(PD4, 0xB0, 4)
+SPEC_FUN_REG_BIT(PD5, 0xB0, 5)
+SPEC_FUN_REG_BIT(PD6, 0xB0, 6)
+SPEC_FUN_REG_BIT(PD7, 0xB0, 7)
+
+SPEC_FUN_REG(IOE, 0xB1) // Port E.
+
+SPEC_FUN_REG(OEA, 0xB2) // Port A out enable.
+SPEC_FUN_REG(OEB, 0xB3) // Port B out enable.
+SPEC_FUN_REG(OEC, 0xB4) // Port C out enable.
+SPEC_FUN_REG(OED, 0xB5) // Port D out enable.
+SPEC_FUN_REG(OEE, 0xB6) // Port E out enable.
+
+SPEC_FUN_REG(IP, 0xB8) // Interrupt prority.
+SPEC_FUN_REG_BIT(PX0, 0xB8, 0)
+SPEC_FUN_REG_BIT(PT0, 0xB8, 1)
+SPEC_FUN_REG_BIT(PX1, 0xB8, 2)
+SPEC_FUN_REG_BIT(PT1, 0xB8, 3)
+SPEC_FUN_REG_BIT(PS0, 0xB8, 4)
+SPEC_FUN_REG_BIT(PT2, 0xB8, 5)
+SPEC_FUN_REG_BIT(PS1, 0xB8, 6)
+
+SPEC_FUN_REG(EP01STAT, 0xBA) // Endpoint 0,1 status.
+SPEC_FUN_REG(GPIFTRIG, 0xBB) // Endpoint 2,4,6,8 GPIF slave FIFO trigger.
+
+SPEC_FUN_REG(GPIFSGLDATH, 0xBD) // GPIF data H.
+SPEC_FUN_REG(GPIFSGLDATLX, 0xBE) // GPIF data L with trigger.
+SPEC_FUN_REG(GPIFSGLDATLNOX, 0xBF) // GPIF data L without trigger.
+
+SPEC_FUN_REG(SCON1, 0xC0) // Serial port 1 control.
+SPEC_FUN_REG_BIT(RI1, 0xC0, 0)
+SPEC_FUN_REG_BIT(TI1, 0xC0, 1)
+SPEC_FUN_REG_BIT(RB81, 0xC0, 2)
+SPEC_FUN_REG_BIT(TB81, 0xC0, 3)
+SPEC_FUN_REG_BIT(REN1, 0xC0, 4)
+SPEC_FUN_REG_BIT(SM21, 0xC0, 5)
+SPEC_FUN_REG_BIT(SM11, 0xC0, 6)
+SPEC_FUN_REG_BIT(SM01, 0xC0, 7)
+
+SPEC_FUN_REG(SBUF1, 0xC1) // Serial port 1 data buffer.
+
+SPEC_FUN_REG(T2CON, 0xC8) // Timer/counter 2 control.
+SPEC_FUN_REG_BIT(CP_RL2, 0xC8, 0)
+SPEC_FUN_REG_BIT(C_T2, 0xC8, 1)
+SPEC_FUN_REG_BIT(TR2, 0xC8, 2)
+SPEC_FUN_REG_BIT(EXEN2, 0xC8, 3)
+SPEC_FUN_REG_BIT(TCLK, 0xC8, 4)
+SPEC_FUN_REG_BIT(RCLK, 0xC8, 5)
+SPEC_FUN_REG_BIT(EXF2, 0xC8, 6)
+SPEC_FUN_REG_BIT(TF2, 0xC8, 7)
+
+SPEC_FUN_REG(RCAP2L, 0xCA) // Capture for timer 2 auto-reload up-counter L.
+SPEC_FUN_REG(RCAP2H, 0xCB) // Capture for timer 2 auto-reload up-counter H.
+SPEC_FUN_REG(TL2, 0xCC) // Timer 2 reload L.
+SPEC_FUN_REG(TH2, 0xCD) // Timer 2 reload H.
+
+SPEC_FUN_REG(PSW, 0xD0) // Program status word.
+SPEC_FUN_REG_BIT(P, 0xD0, 0)
+SPEC_FUN_REG_BIT(FL, 0xD0, 1)
+SPEC_FUN_REG_BIT(OV, 0xD0, 2)
+SPEC_FUN_REG_BIT(RS0, 0xD0, 3)
+SPEC_FUN_REG_BIT(RS1, 0xD0, 4)
+SPEC_FUN_REG_BIT(F0, 0xD0, 5)
+SPEC_FUN_REG_BIT(AC, 0xD0, 6)
+SPEC_FUN_REG_BIT(CY, 0xD0, 7)
+
+SPEC_FUN_REG(EICON, 0xD8) // External interrupt control.
+SPEC_FUN_REG_BIT(INT6, 0xD8, 3)
+SPEC_FUN_REG_BIT(RESI, 0xD8, 4)
+SPEC_FUN_REG_BIT(ERESI, 0xD8, 5)
+SPEC_FUN_REG_BIT(SMOD1, 0xD8, 7)
+
+SPEC_FUN_REG(ACC, 0xE0) // Accumulator.
+
+SPEC_FUN_REG(EIE, 0xE8) // External interrupt enable.
+SPEC_FUN_REG_BIT(EUSB, 0xE8, 0)
+SPEC_FUN_REG_BIT(EI2C, 0xE8, 1)
+SPEC_FUN_REG_BIT(EIEX4, 0xE8, 2)
+SPEC_FUN_REG_BIT(EIEX5, 0xE8, 3)
+SPEC_FUN_REG_BIT(EIEX6, 0xE8, 4)
+
+SPEC_FUN_REG(B, 0xF0) // B
+
+SPEC_FUN_REG(EIP, 0xF8) // External interrupt priority control.
+SPEC_FUN_REG_BIT(PUSB, 0xF8, 0)
+SPEC_FUN_REG_BIT(PI2C, 0xF8, 1)
+SPEC_FUN_REG_BIT(EIPX4, 0xF8, 2)
+SPEC_FUN_REG_BIT(EIPX5, 0xF8, 3)
+SPEC_FUN_REG_BIT(EIPX6, 0xF8, 4)
+
+//
+// Register bit masks.
+//
+
+// CPU control & status register (CPUCS).
+enum cpucs_bits {
+ bmPRTCSTB = bmBIT5,
+ bmCLKSPD = bmBIT4 | bmBIT3,
+ bmCLKSPD1 = bmBIT4,
+ bmCLKSPD0 = bmBIT3,
+ bmCLKINV = bmBIT2,
+ bmCLKOE = bmBIT1,
+ bm8051RES = bmBIT0
+};
+
+// Port A (PORTACFG).
+enum portacfg_bits {
+ bmFLAGD = bmBIT7,
+ bmINT1 = bmBIT1,
+ bmINT0 = bmBIT0
+};
+
+// Port C (PORTCCFG).
+enum portccfg_bits {
+ bmGPIFA7 = bmBIT7,
+ bmGPIFA6 = bmBIT6,
+ bmGPIFA5 = bmBIT5,
+ bmGPIFA4 = bmBIT4,
+ bmGPIFA3 = bmBIT3,
+ bmGPIFA2 = bmBIT2,
+ bmGPIFA1 = bmBIT1,
+ bmGPIFA0 = bmBIT0
+};
+
+// Port E (PORTECFG).
+enum portecfg_bits {
+ bmGPIFA8 = bmBIT7,
+ bmT2EX = bmBIT6,
+ bmINT6 = bmBIT5,
+ bmRXD1OUT = bmBIT4,
+ bmRXD0OUT = bmBIT3,
+ bmT2OUT = bmBIT2,
+ bmT1OUT = bmBIT1,
+ bmT0OUT = bmBIT0
+};
+
+// I2C control & status register (I2CS).
+enum i2cs_bits {
+ bmSTART = bmBIT7,
+ bmSTOP = bmBIT6,
+ bmLASTRD = bmBIT5,
+ bmID = bmBIT4 | bmBIT3,
+ bmBERR = bmBIT2,
+ bmACK = bmBIT1,
+ bmDONE = bmBIT0
+};
+
+// I2C control register (I2CTL).
+enum i2ctl_bits {
+ bmSTOPIE = bmBIT1,
+ bm400KHZ = bmBIT0
+};
+
+// Interrupt 2 (USB) autovector register (INT2IVEC).
+enum int2ivec_bits {
+ bmIV4 = bmBIT6,
+ bmIV3 = bmBIT5,
+ bmIV2 = bmBIT4,
+ bmIV1 = bmBIT3,
+ bmIV0 = bmBIT2
+};
+
+// USB interrupt request & enable registers (USBIE/USBIRQ).
+enum usbieirq_bits {
+ bmEP0ACK = bmBIT6,
+ bmHSGRANT = bmBIT5,
+ bmURES = bmBIT4,
+ bmSUSP = bmBIT3,
+ bmSUTOK = bmBIT2,
+ bmSOF = bmBIT1,
+ bmSUDAV = bmBIT0
+};
+
+// End point interrupt request & enable registers (EPIE/EPIRQ).
+enum epieirq_bits {
+ bmEP8 = bmBIT7,
+ bmEP6 = bmBIT6,
+ bmEP4 = bmBIT5,
+ bmEP2 = bmBIT4,
+ bmEP1OUT = bmBIT3,
+ bmEP1IN = bmBIT2,
+ bmEP0OUT = bmBIT1,
+ bmEP0IN = bmBIT0
+};
+
+// Breakpoint register (BREAKPT).
+enum breakpt_bits {
+ bmBREAK = bmBIT3,
+ bmBPPULSE = bmBIT2,
+ bmBPEN = bmBIT1
+};
+
+// Interrupt 2 & 4 setup (INTSETUP).
+enum intsetup_bits {
+ bmAV2EN = bmBIT3,
+ bmINT4SRC = bmBIT1,
+ bmAV4EN = bmBIT0
+};
+
+// USB control & status register (USBCS).
+enum usbcs_bits {
+ bmHSM = bmBIT7,
+ bmDISCON = bmBIT3,
+ bmNOSYNSOF = bmBIT2,
+ bmRENUM = bmBIT1,
+ bmSIGRESUME = bmBIT0
+};
+
+// Wakeup control and status register (WAKEUPCS).
+enum wakeupcs_bits {
+ bmWU2 = bmBIT7,
+ bmWU = bmBIT6,
+ bmWU2POL = bmBIT5,
+ bmWUPOL = bmBIT4,
+ bmDPEN = bmBIT2,
+ bmWU2EN = bmBIT1,
+ bmWUEN = bmBIT0
+};
+
+// End point 0 control & status register (EP0CS).
+enum ep0cs_bits {
+ bmHSNAK = bmBIT7
+};
+
+// End point 0-1 control & status registers
+// (EP0CS/EP1OUTCS/EP1INCS).
+enum ep01cs_bits {
+ bmEPBUSY = bmBIT1,
+ bmEPSTALL = bmBIT0
+};
+
+// End point 2-8 Control & status registers
+// (EP2CS/EP4CS/EP6CS/EP8CS).
+enum ep2468cs_bits {
+ MSK_EP2468CS_NPAK = bmBIT6 | bmBIT5 | bmBIT4,
+ MSK_EP2468CS_EPFULL = bmBIT3,
+ MSK_EP2468CS_EPEMPTY = bmBIT2
+};
+
+// End point status SFR bits (EP2468STAT).
+enum ep2468stat_bits {
+ bmEP8FULL = bmBIT7,
+ bmEP8EMPTY = bmBIT6,
+ bmEP6FULL = bmBIT5,
+ bmEP6EMPTY = bmBIT4,
+ bmEP4FULL = bmBIT3,
+ bmEP4EMPTY = bmBIT2,
+ bmEP2FULL = bmBIT1,
+ bmEP2EMPTY = bmBIT0
+};
+
+// End point 0,1 status bits (EP01STAT).
+enum ep01stat_bits {
+ bmEP1INBSY = bmBIT2,
+ bmEP1OUTBSY = bmBIT1,
+ bmEP0BSY = bmBIT0
+};
+
+// Setup data pointer auto mode (SUDPTRCTL).
+enum sudptrctl_bits {
+ bmSDPAUTO = bmBIT0
+};
+
+// End point data toggle control (TOGCTL).
+enum togctl_bits {
+ bmQUERYTOGGLE = bmBIT7,
+ bmSETTOGGLE = bmBIT6,
+ bmRESETTOGGLE = bmBIT5,
+ bmTOGCTLEPMASK = bmBIT3 | bmBIT2 | bmBIT1 | bmBIT0
+};
+
+// In bulk NAK enable and request bits (IBNIE/IBNIRQ).
+enum ibnieirq_bits {
+ bmEP8IBN = bmBIT5,
+ bmEP6IBN = bmBIT4,
+ bmEP4IBN = bmBIT3,
+ bmEP2IBN = bmBIT2,
+ bmEP1IBN = bmBIT1,
+ bmEP0IBN = bmBIT0
+};
+
+// Ping NAK enable and request bits (NAKIE/NAKIRQ).
+enum nakieirq_bits {
+ bmEP8PING = bmBIT7,
+ bmEP6PING = bmBIT6,
+ bmEP4PING = bmBIT5,
+ bmEP2PING = bmBIT4,
+ bmEP1PING = bmBIT3,
+ bmEP0PING = bmBIT2,
+ bmIBN = bmBIT0
+};
+
+// Interface configuration bits (IFCONFIG).
+enum ifconfig_bits {
+ bmIFCLKSRC = bmBIT7,
+ bm3048MHZ = bmBIT6,
+ bmIFCLKOE = bmBIT5,
+ bmIFCLKPOL = bmBIT4,
+ bmASYNC = bmBIT3,
+ bmGSTATE = bmBIT2,
+ bmIFCFG = bmBIT0 | bmBIT1
+};
+
+// IFCFG field of IFCONFIG register.
+enum ifcfg_bits {
+ bmIFPORTS = 0,
+ bmIFRESERVED = bmBIT0,
+ bmIFGPIF = bmBIT1,
+ bmIFSLAVEFIFO = bmBIT0 | bmBIT1
+};
+
+// End point 2,4,6,8 FIFO configuration bits
+// (EP2FIFOCFG,EP4FIFOCFG,EP6FIFOCFG,EP8FIFOCFG).
+enum ep2468fifocfg_bits {
+ bmINFM = bmBIT6,
+ bmOEP = bmBIT5,
+ bmAUTOOUT = bmBIT4,
+ bmAUTOIN = bmBIT3,
+ bmZEROLENIN = bmBIT2,
+ bmWORDWIDE = bmBIT0
+};
+
+// Chip revision control bits (REVCTL).
+enum revctl_bits {
+ bmNOAUTOARM = bmBIT1,
+ bmSKIPCOMMIT = bmBIT0
+};
+
+// Fifo reset bits (FIFORESET).
+enum fiforeset_bits {
+ bmNAKALL = bmBIT7,
+ bmFREP3 = bmBIT3,
+ bmFREP2 = bmBIT2,
+ bmFREP1 = bmBIT1,
+ bmFREP0 = bmBIT0
+};
+
+// Chip feature register (GPCR2).
+enum gpcr2_bits {
+ bmFULLSPEEDONLY = bmBIT4
+};
+
+// Clock control register (CKCON).
+// Note: a RevE errata states that stretch must=0
+// to set OUTxBC.
+enum ckcon_bits {
+ bmT2M = bmBIT5,
+ bmT1M = bmBIT4,
+ bmT0M = bmBIT3,
+ bmSTRETCH = bmBIT0 | bmBIT1 | bmBIT2
+};
+
+enum data_mem_stretch {
+ bmFW_STRETCH1 = 0, // Movx: 2 cycles, R/W strobe: 2 cycles...
+ bmFW_STRETCH2 = 1, // Movx: 3 cycles, R/W strobe: 4 cycles...
+ bmFW_STRETCH3 = 2, // Movx: 4 cycles, R/W strobe: 8 cycles...
+ bmFW_STRETCH4 = 3, // Movx: 5 cycles, R/W strobe: 12 cycles...
+ bmFW_STRETCH5 = 4, // Movx: 6 cycles, R/W strobe: 16 cycles...
+ bmFW_STRETCH6 = 5, // Movx: 7 cycles, R/W strobe: 20 cycles...
+ bmFW_STRETCH7 = 6, // Movx: 8 cycles, R/W strobe: 24 cycles...
+ bmFW_STRETCH8 = 7 // Movx: 9 cycles, R/W strobe: 28 cycles...
+};
+
+// External interrupt flags (EXIF).
+enum exif_bits {
+ bmIE5 = bmBIT7,
+ bmIE4 = bmBIT6,
+ bmI2CINT = bmBIT5,
+ bmUSBNT = bmBIT4
+};
+
+// External interrupt control (EICON).
+enum eicon_bits {
+ bmSMOD1 = bmBIT7,
+ bmERESI = bmBIT5,
+ bmRESI = bmBIT4,
+ //bmINT6 = bmBIT3
+};
+
+// Power control (PCON).
+enum pcon_bits {
+ bmSMOD0 = bmBIT7,
+ bmIDLE = bmBIT0
+};
+
+// Autopointer 1 & 2 setup (AUTOPTRSETUP).
+enum autoptrsetup_bits {
+ bmAPTR2INC = bmBIT2,
+ bmAPTR1INC = bmBIT1,
+ bmAPTREN = bmBIT0
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FX2_REGS_H
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/usb.c b/examples/baremetal/cy7c68013a/nes-gamepads/usb.c
new file mode 100644
index 000000000..59a008dee
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/usb.c
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "core.h"
+#include "hid.h"
+#include "usb.h"
+
+void usb_init(void)
+{
+ // Disable all USB interrupts.
+ USBIE = 0;
+ sync_delay();
+ // Disable all end point interrupts.
+ EPIE = 0;
+ sync_delay();
+ // Disable all end point ping-nak interrupts.
+ NAKIE = 0;
+ sync_delay();
+ // Disable all USB error interrupts.
+ USBERRIE = 0;
+ sync_delay();
+ // Disable USB && GPIF autovectoring.
+ INTSETUP = 0;
+ sync_delay();
+ // Clear USB interrupt requests.
+ USBIRQ = bmSUDAV | bmSOF | bmSUTOK | bmSUSP
+ | bmURES | bmHSGRANT | bmEP0ACK;
+ sync_delay();
+ // Clear end point interrupt requests.
+ EPIRQ = bmEP0IN | bmEP0OUT | bmEP1IN | bmEP1OUT
+ | bmEP2 | bmEP4 | bmEP6 | bmEP8;
+ sync_delay();
+ // Set USB interrupt to high priority.
+ PUSB = 1;
+ sync_delay();
+ // Enable USB interrupts.
+ EUSB = 1;
+ sync_delay();
+ // As we use SOFs to detect disconnect we have
+ // to disable SOF synthesizing.
+ USBCS |= bmNOSYNSOF;
+ sync_delay();
+
+ hid_init();
+
+ // Disable FX2-internal enumeration support.
+ USBCS |= bmRENUM;
+ sync_delay();
+}
+
+void usb_task(void)
+{
+ if (USBIRQ & bmSUDAV) {
+ USBIRQ = bmSUDAV;
+ hid_ep0_setup_task();
+ }
+
+ if (USBIRQ & bmEP0ACK) {
+ USBIRQ = bmEP0ACK;
+ }
+
+ if (USBIRQ & bmURES) {
+ USBIRQ = bmURES;
+ }
+
+ if (USBIRQ & bmSUSP) {
+ USBIRQ = bmSUSP;
+ }
+
+ hid_ep1_task();
+}
diff --git a/examples/baremetal/cy7c68013a/nes-gamepads/usb.h b/examples/baremetal/cy7c68013a/nes-gamepads/usb.h
new file mode 100644
index 000000000..67877a4b6
--- /dev/null
+++ b/examples/baremetal/cy7c68013a/nes-gamepads/usb.h
@@ -0,0 +1,217 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of Qbs.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef FX2_USB_H
+#define FX2_USB_H
+
+#include "regs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum usb_setup_bmreq_bits {
+ bmSETUP_DIR = bmBIT7,
+ bmSETUP_TYPE = bmBIT5 | bmBIT6,
+ bmSETUP_RECIPIENT = bmBIT0 | bmBIT1 | bmBIT2 | bmBIT3 | bmBIT4
+};
+
+// Setup request direction.
+enum usb_setup_req_direction_bits {
+ bmSETUP_TO_DEVICE = 0, // From host to sevice direction.
+ bmSETUP_TO_HOST = bmBIT7 // From device to host direction.
+};
+
+// Setup request type.
+enum usb_setup_req_type_bits {
+ bmSETUP_STANDARD = 0, // Standard request.
+ bmSETUP_CLASS = bmBIT5, // Class request.
+ bmSETUP_VENDOR = bmBIT6, // Vendor request.
+};
+
+// Setup request recipient.
+enum usb_setup_req_recipient_bits {
+ bmSETUP_DEVICE = 0, // Device recipient.
+ bmSETUP_IFACE = bmBIT0, // Interface recipient.
+ bmSETUP_EP = bmBIT1, // End point recipient.
+ bmSETUP_OTHER = bmBIT0 | bmBIT1 // Other recipient.
+};
+
+// Setup request code.
+enum usb_setup_req_code {
+ USB_SETUP_GET_STATUS = 0x00, // Get status code.
+ USB_SETUP_CLEAR_FEATURE = 0x01, // Clear feature code.
+ USB_SETUP_RESERVED1 = 0x02, // Reserved code.
+ USB_SETUP_SET_FEATURE = 0x03, // Set feature code.
+ USB_SETUP_RESERVED2 = 0x04, // Reserved code.
+ USB_SETUP_SET_ADDRESS = 0x05, // Set address code.
+ USB_SETUP_GET_DESCRIPTOR = 0x06, // Get descriptor code.
+ USB_SETUP_SET_DESCRIPTOR = 0x07, // Set descriptor code.
+ USB_SETUP_GET_CONFIGURATION = 0x08, // Get configuration code.
+ USB_SETUP_SET_CONFIGURATION = 0x09, // Set configuration code.
+ USB_SETUP_GET_INTERFACE = 0x0A, // Get interface code.
+ USB_SETUP_SET_INTERFACE = 0x0B, // Set interface code.
+ USB_SETUP_SYNC_FRAME = 0x0C, // Sync frame code.
+ USB_SETUP_ANCHOR_LOAD = 0xA0 // Anchor load code.
+};
+
+// Standard status responses.
+enum usb_setup_status_code {
+ USB_STATUS_SELF_POWERED = 0x01,
+ USB_STATUS_REMOTE_WAKEUP = 0x02
+};
+
+// Standard feature selectors.
+enum usb_setup_feature_selector {
+ USB_FEATURE_STALL = 0x00,
+ USB_FEATURE_REMOTE_WAKEUP = 0x01,
+ USB_FEATRUE_TEST_MODE = 0x02
+};
+
+// Get descriptor codes.
+enum usb_setup_get_descriptor_code {
+ USB_DESC_DEVICE = 0x01, // Device descriptor.
+ USB_DESC_CONF = 0x02, // Configuration descriptor.
+ USB_DESC_STRING = 0x03, // String descriptor.
+ USB_DESC_INTERFACE = 0x04, // Interface descriptor.
+ USB_DESC_ENDPOINT = 0x05, // End point descriptor.
+ USB_DESC_DEVICE_QUAL = 0x06, // Device qualifier descriptor.
+ USB_DESC_OTHER_SPEED_CONF = 0x07, // Other configuration descriptor.
+ USB_DESC_INTERFACE_POWER = 0x08, // Interface power descriptor.
+ USB_DESC_OTG = 0x09, // OTG descriptor.
+ USB_DESC_DEBUG = 0x0A, // Debug descriptor.
+ USB_DESC_INTERFACE_ASSOC = 0x0B, // Interface association descriptor.
+ USB_DESC_HID = 0x21, // Get HID descriptor.
+ USB_DESC_REPORT = 0x22 // Get report descriptor.
+};
+
+// End point configuration (EP1INCFG/EP1OUTCFG/EP2/EP4/EP6/EP8).
+enum epcfg_bits {
+ bmEP_VALID = bmBIT7,
+ bmEP_DIR = bmBIT6, // Only for EP2-EP8!
+ bmEP_TYPE = bmBIT5 | bmBIT4,
+ bmEP_SIZE = bmBIT3, // Only for EP2-EP8!
+ bmEP_BUF = bmBIT1 | bmBIT0 // Only for EP2-EP8!
+};
+
+enum ep_valid_bits {
+ bmEP_DISABLE = 0,
+ bmEP_ENABLE = bmBIT7
+};
+
+// Only for EP2-EP8!
+enum ep_direction {
+ bmEP_OUT = 0,
+ bmEP_IN = bmBIT6
+};
+
+enum ep_type {
+ bmEP_ISO = bmBIT4, // Only for EP2-EP8!
+ bmEP_BULK = bmBIT5, // Default value.
+ bmEP_INT = bmBIT4 | bmBIT5
+};
+
+// Only for EP2-EP8!
+enum ep_size {
+ EP_512 = 0,
+ EP_1024 = bmBIT3 // Except EP4/EP8.
+};
+
+// Only for EP2-EP8!
+enum ep_buf {
+ EP_QUAD = 0,
+ EP_DOUBLE = bmBIT1, // Default value.
+ EP_TRIPLE = bmBIT0 | bmBIT1
+};
+
+struct ep0_buf {
+ BYTE *dat;
+ WORD len;
+};
+
+#define usb_disconnect() (USBCS |= bmDISCON)
+#define usb_connect() (USBCS &= ~bmDISCON)
+
+#define usb_is_high_speed() \
+ (USBCS & bmHSM)
+
+#define usp_ep_reset_toggle(ep) \
+ TOGCTL = (((ep & 0x80) >> 3) + (ep & 0x0F)); \
+ TOGCTL |= bmRESETTOGGLE
+
+#define usb_ep0_stall() \
+ EP0CS |= bmEPSTALL
+
+#define usb_ep0_hsnack() \
+ EP0CS |= bmHSNAK
+
+#define usb_word_msb_get(word) \
+ (BYTE)(((WORD)(word) >> 8) & 0xFF)
+#define usb_word_lsb_get(word) \
+ (BYTE)((WORD)(word) & 0xFF)
+
+#define usb_word_swap(x) \
+ ((((WORD)((x) & 0x00FF)) << 8) | \
+ (((WORD)((x) & 0xFF00)) >> 8))
+
+#define usb_dword_swap(x) \
+ ((((DWORD)((x) & 0x000000FFul)) << 24) | \
+ (((DWORD)((x) & 0x0000FF00ul)) << 8) | \
+ (((DWORD)((x) & 0x00FF0000ul)) >> 8) | \
+ (((DWORD)((x) & 0xFF000000ul)) >> 24))
+
+void usb_init(void);
+void usb_task(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FX2_USB_H