aboutsummaryrefslogtreecommitdiffstats
path: root/examples/baremetal/cy7c68013a/nes-gamepads
diff options
context:
space:
mode:
Diffstat (limited to 'examples/baremetal/cy7c68013a/nes-gamepads')
-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
17 files changed, 3227 insertions, 0 deletions
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