diff options
Diffstat (limited to 'examples/baremetal/cy7c68013a/nes-gamepads')
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 |