contrib/firmware: add new adapter ANGIE's firmware/bitstream code 01/7701/25
authorAhmed BOUDJELIDA <aboudjelida@nanoxplore.com>
Fri, 16 Jun 2023 21:19:05 +0000 (23:19 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 12 Aug 2023 16:42:19 +0000 (16:42 +0000)
This is ANGIE's firmware and bitstream code.
The 'Embeded C' code is based on the openULINK project.
The hdl bitstream source code is for the spartan-6 FPGA included in
ANGIE.

Since ANGIE has a different microcontroller (EZ-USB FX2) than openULINK
(EZ-USB AN2131), the registers file (reg_ezusb.h) has been changed
completely, so are the descriptors, interruptions and the endpoints
configuration.

Change-Id: I70590c7c58bac6f1939c5ffba57e87d86850664d
Signed-off-by: Ahmed BOUDJELIDA <aboudjelida@nanoxplore.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/7701
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
25 files changed:
contrib/firmware/angie/c/Makefile [new file with mode: 0644]
contrib/firmware/angie/c/README [new file with mode: 0644]
contrib/firmware/angie/c/include/delay.h [new file with mode: 0644]
contrib/firmware/angie/c/include/fx2macros.h [new file with mode: 0644]
contrib/firmware/angie/c/include/io.h [new file with mode: 0644]
contrib/firmware/angie/c/include/jtag.h [new file with mode: 0644]
contrib/firmware/angie/c/include/msgtypes.h [new file with mode: 0644]
contrib/firmware/angie/c/include/protocol.h [new file with mode: 0644]
contrib/firmware/angie/c/include/reg_ezusb.h [new file with mode: 0644]
contrib/firmware/angie/c/include/serial.h [new file with mode: 0644]
contrib/firmware/angie/c/include/usb.h [new file with mode: 0644]
contrib/firmware/angie/c/src/USBJmpTb.a51 [new file with mode: 0644]
contrib/firmware/angie/c/src/delay.c [new file with mode: 0644]
contrib/firmware/angie/c/src/gpif.c [new file with mode: 0644]
contrib/firmware/angie/c/src/jtag.c [new file with mode: 0644]
contrib/firmware/angie/c/src/main.c [new file with mode: 0644]
contrib/firmware/angie/c/src/protocol.c [new file with mode: 0644]
contrib/firmware/angie/c/src/serial.c [new file with mode: 0644]
contrib/firmware/angie/c/src/usb.c [new file with mode: 0644]
contrib/firmware/angie/hdl/Makefile [new file with mode: 0644]
contrib/firmware/angie/hdl/README [new file with mode: 0644]
contrib/firmware/angie/hdl/set_env.sh [new file with mode: 0644]
contrib/firmware/angie/hdl/src/angie_openocd.ucf [new file with mode: 0644]
contrib/firmware/angie/hdl/src/angie_openocd.vhd [new file with mode: 0644]
doc/usb_adapters/angie/584e_424e_angie.txt [new file with mode: 0644]

diff --git a/contrib/firmware/angie/c/Makefile b/contrib/firmware/angie/c/Makefile
new file mode 100644 (file)
index 0000000..80e8cbe
--- /dev/null
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#****************************************************************************
+#   File : Makefile                                                         *
+#   Contents : Code for NanoXplore USB-JTAG ANGIE adapter hardware.         *
+#   Based on openULINK project by: Martin Schmoelzer.                       *
+#   Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.              *
+#   <aboudjelida@nanoxplore.com>                                            *
+#      <ahmederrachedbjld@gmail.com>                                                                                   *
+# ***************************************************************************/
+
+# Define the name of tools.
+PREFIX =
+
+# Small Device C Compiler: http://sdcc.sourceforge.net/
+CC = $(PREFIX)sdcc
+
+# 8051 assembler, part of the SDCC software package.
+AS = $(PREFIX)sdas8051
+
+# SDCC produces quite messy Intel HEX files. This tool is be used to re-format
+# those files. It is not required for the firmware download functionality in
+# the OpenOCD driver, but the resulting file is smaller.
+PACKIHX = $(PREFIX)packihx
+
+# GNU binutils size. Used to print the size of the IHX file generated by SDCC.
+SIZE = size
+
+# Source and header directories.
+SRC_DIR     = src
+INCLUDE_DIR = include
+
+CODE_SIZE = 0x3C00
+XRAM_LOC  = 0x3C00
+XRAM_SIZE = 0x0400
+
+CFLAGS  = --std-sdcc99 --opt-code-size --model-small
+LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \
+          --xram-size $(XRAM_SIZE) --iram-size 256 --model-small
+
+# list of base object files
+OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel serial.rel gpif.rel
+HEADERS = $(INCLUDE_DIR)/usb.h          \
+          $(INCLUDE_DIR)/protocol.h     \
+          $(INCLUDE_DIR)/jtag.h         \
+          $(INCLUDE_DIR)/delay.h        \
+          $(INCLUDE_DIR)/reg_ezusb.h    \
+          $(INCLUDE_DIR)/io.h           \
+          $(INCLUDE_DIR)/serial.h       \
+          $(INCLUDE_DIR)/fx2macros.h    \
+          $(INCLUDE_DIR)/msgtypes.h
+
+# Disable all built-in rules.
+.SUFFIXES:
+
+# Targets which are executed even when identically named file is present.
+.PHONY: all, clean
+
+all: angie_firmware.ihx
+       $(SIZE) angie_firmware.ihx
+
+angie_firmware.ihx: $(OBJECTS)
+       $(CC) -mmcs51 $(LDFLAGS) -o $@ $^
+
+# Rebuild every C module (there are only 5 of them) if any header changes.
+%.rel: $(SRC_DIR)/%.c $(HEADERS)
+       $(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $<
+
+%.rel: $(SRC_DIR)/%.a51
+       $(AS) -lsgo $@ $<
+
+clean:
+       rm -f *.asm *.lst *.rel *.rst *.sym *.ihx *.lk *.map *.mem
+
+bin: angie_firmware.ihx
+       makebin -p angie_firmware.ihx angie_firmware.bin
diff --git a/contrib/firmware/angie/c/README b/contrib/firmware/angie/c/README
new file mode 100644 (file)
index 0000000..04ed0be
--- /dev/null
@@ -0,0 +1,37 @@
+#SPDX-License-Identifier: GPL-2.0-or-later
+
+This is the ANGIE firmware for ANGIE USB-JTAG adapter.
+
+The main components of ANGIE adapter are:
+- Cypress EZ-USB FX2 microcontroller
+- Spartan-6 FPGA
+- SRAM memory chip
+- Pin headers for various JTAG pin assignments
+
+To compile the firmware, the SDCC compiler package is required. Most Linux
+distributions include SDCC in their official package repositories. The SDCC
+source code can be found at http://sdcc.sourceforge.net/
+
+Simply type "make hex" in the ANGIE directory to compile the firmware.
+"make clean" will remove all generated files except the Intel HEX file
+required for downloading the firmware to ANGIE.
+
+Note that the EZ-USB FX2 microcontroller does not have on-chip flash,
+ANGIE include on-board EEPROM memory to store the firmware program of
+the FX2, but we are not going to use this method.
+
+Instead, upon initial connection of the ANGIE adapter to the host PC
+via USB, the EZ-USB FX2 core has enough intelligence to act as a
+stand-alone USB device, responding to USB control requests and allowing
+firmware download via a special VENDOR-type control request. Then, the
+EZ-USB microcontroller simulates a disconnect and re-connect to the USB bus.
+It may take up to two seconds for the host to recognize the newly connected
+device before OpenOCD can proceed to execute JTAG commands. This delay is
+only visible when OpenOCD first uses a blank (unconfigured) ANGIE device.
+
+Once the firmware downloaded, the FX2 microcontroller activate its GPIF mode,
+download the Spartan-6 FPGA's bitstream, program the FPGA rapidly, and switch
+back to default io mode.
+
+Once the user disconnects the ANGIE adapter, all its memory contents are lost
+and the firmware & bitstream download process has to be executed again.
diff --git a/contrib/firmware/angie/c/include/delay.h b/contrib/firmware/angie/c/include/delay.h
new file mode 100644 (file)
index 0000000..0397941
--- /dev/null
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/****************************************************************
+    File : delay.h                                              *
+    Contents : Delays handling header file for NanoXplore       *
+    USB-JTAG ANGIE adapter hardware.                            *
+    Based on openULINK project code by: Martin Schmoelzer.      *
+    Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.  *
+    <aboudjelida@nanoxplore.com>                                *
+    <ahmederrachedbjld@gmail.com>                               *
+*****************************************************************/
+
+#ifndef __DELAY_H
+#define __DELAY_H
+
+#include <stdint.h>
+
+void syncdelay(uint8_t count);
+void delay_5us(void);
+void delay_1ms(void);
+void delay_us(uint16_t delay);
+void delay_ms(uint16_t delay);
+
+#ifndef _IFREQ
+#define _IFREQ 48000   /* IFCLK frequency in kHz */
+#endif
+
+/* CFREQ can be any one of: 48000, 24000, or 12000 */
+#ifndef _CFREQ
+#define _CFREQ 48000   /* CLKOUT frequency in kHz */
+#endif
+
+#if (_IFREQ < 5000)
+#error "_IFREQ too small!  Valid Range: 5000 to 48000..."
+#endif
+
+#if (_IFREQ > 48000)
+#error "_IFREQ too large!  Valid Range: 5000 to 48000..."
+#endif
+
+#if (_CFREQ != 48000)
+#if (_CFREQ != 24000)
+#if (_CFREQ != 12000)
+#error "_CFREQ invalid!  Valid values: 48000, 24000, 12000..."
+#endif
+#endif
+#endif
+
+/* Synchronization Delay formula: see TRM section 15-14 */
+#define _SCYCL (3 * (_CFREQ) + 5 * (_IFREQ) - 1) / (2 * (_IFREQ))
+#endif
diff --git a/contrib/firmware/angie/c/include/fx2macros.h b/contrib/firmware/angie/c/include/fx2macros.h
new file mode 100644 (file)
index 0000000..9067b56
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/*
+ * This code was taken from the fx2lib project from this link:
+ * https://github.com/djmuhlestein/fx2lib
+ *
+ * Copyright (C) 2009 Ubixum, Inc.
+*/
+
+/*! \file
+ *  Macros for simple common tasks in fx2 firmware.
+ * */
+
+#ifndef FX2MACROS_H
+#define FX2MACROS_H
+
+#include "reg_ezusb.h"
+
+typedef enum {FALSE = 0, TRUE} BOOL_VALS;
+
+/**
+ * \brief Used for getting and setting the CPU clock speed.
+ **/
+typedef enum {CLK_12M = 0, CLK_24M, CLK_48M} CLK_SPD;
+
+/**
+ * \brief Evaluates to a CLK_SPD enum.
+ **/
+#define CPUFREQ (CLK_SPD)((CPUCS & bmclkspd) >> 3)
+
+#endif
diff --git a/contrib/firmware/angie/c/include/io.h b/contrib/firmware/angie/c/include/io.h
new file mode 100644 (file)
index 0000000..35afa62
--- /dev/null
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/****************************************************************************
+    File : io.h                                                             *
+    Contents : input/output declaration header file for NanoXplore          *
+    USB-JTAG ANGIE adapter hardware.                                        *
+    Based on openULINK project code by: Martin Schmoelzer.                  *
+    Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.              *
+    <aboudjelida@nanoxplore.com>                                            *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#ifndef __IO_H
+#define __IO_H
+
+#include "reg_ezusb.h"
+
+/***************************************************************************
+ *  JTAG Signals:                                                          *
+ ***************************************************************************
+ * TMS ....... Test Mode Select                                            *
+ * TCK ....... Test Clock                                                  *
+ * TDI ....... Test Data Input  (from device point of view, not JTAG       *
+ *             adapter point of view!)                                     *
+ * TDO ....... Test Data Output (from device point of view, not JTAG       *
+ *             adapter point of view!)                                     *
+ * TRST ...... Test Reset: Used to reset the TAP Finite State Machine      *
+ *             into the Test Logic Reset state                             *
+ * SRST .....  Chip Reset                                                  *
+ ***************************************************************************/
+
+/* PORT A */
+/* PA0 Not Connected */
+/* PA1 Not Connected */
+#define PIN_RDWR_B        IOA2
+#define PIN_CSI_B         IOA3
+#define PIN_INIT_B        IOA4
+#define PIN_PROGRAM_B     IOA5
+/* PA6 Not Connected */
+/* PA7 Not Connected */
+
+/* PORT B */
+#define PIN_TRST      IOB0
+#define PIN_TMS       IOB1
+#define PIN_TCK       IOB2
+#define PIN_TDI       IOB3
+#define PIN_TDO       IOB4
+#define PIN_SRST      IOB5
+/* PA6 Not Connected */
+/* PA7 Not Connected */
+
+/* JTAG Signals with direction 'OUT' on port B */
+/* PIN_TDI - PIN_TCK - PIN_TMS - PIN_TRST - PIN_SRST */
+#define MASK_PORTB_DIRECTION_OUT (bmbit0 | bmbit1 | bmbit2 | bmbit3 | bmbit5)
+
+/* PORT C */ // Debug:
+#define PIN_T0      IOC0
+#define PIN_T1      IOC1
+#define PIN_T2      IOC2
+#define PIN_T3      IOC3
+#define PIN_T4      IOC4
+/* PC5 Not Connected */
+/* PC6 Not Connected */
+/* PC7 Not Connected */
+
+#endif
diff --git a/contrib/firmware/angie/c/include/jtag.h b/contrib/firmware/angie/c/include/jtag.h
new file mode 100644 (file)
index 0000000..6d5df64
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/****************************************************************************
+       File : jtag.h                                                                                                                   *
+       Contents : Jtag handling functions header file for NanoXplore                   *
+       USB-JTAG ANGIE adapter hardware.                                                                                *
+       Based on openULINK project code by: Martin Schmoelzer.                                  *
+       Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.                              *
+       <aboudjelida@nanoxplore.com>                                                                                    *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#ifndef __JTAG_H
+#define __JTAG_H
+
+#include <stdint.h>
+
+uint16_t jtag_get_signals(void);
+void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
+       uint8_t scan_io, uint8_t tck, uint8_t tms);
+void jtag_clock_tms(uint8_t count, uint8_t sequence);
+void jtag_slow_clock_tms(uint8_t count, uint8_t sequence);
+void jtag_set_signals(uint8_t low, uint8_t high);
+void jtag_clock_tck(uint16_t count);
+void jtag_slow_clock_tck(uint16_t count);
+void jtag_scan_in(uint8_t out_offset, uint8_t in_offset);
+void jtag_scan_out(uint8_t out_offset);
+void jtag_scan_io(uint8_t out_offset, uint8_t in_offset);
+void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset);
+void jtag_slow_scan_out(uint8_t out_offset);
+void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset);
+#endif
diff --git a/contrib/firmware/angie/c/include/msgtypes.h b/contrib/firmware/angie/c/include/msgtypes.h
new file mode 100644 (file)
index 0000000..9111690
--- /dev/null
@@ -0,0 +1,171 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/****************************************************************************
+    File : msgtypes.h                                                       *
+    Contents : Definition of the commands supported by NanoXplore           *
+    USB-JTAG ANGIE adapter hardware.                                        *
+    Based on openULINK project code by: Martin Schmoelzer.                  *
+    Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.              *
+    <aboudjelida@nanoxplore.com>                                            *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+/**
+ * @file
+ * Definition of the commands supported by the ANGIE firmware.
+ *
+ * Basically, two types of commands can be distinguished:
+ *  - Commands with fixed payload size
+ *  - Commands with variable payload size
+ *
+ * SCAN commands (in all variations) carry payloads of variable size, all
+ * other commands carry payloads of fixed size.
+ *
+ * In the case of SCAN commands, the payload size (n) is calculated by
+ * dividing the scan_size_bits variable by 8, rounding up the result.
+ *
+ * Offset zero always contains the command ID.
+ *
+ ****************************************************************************
+ * CMD_SCAN_IN, CMD_SLOW_SCAN_IN:                                           *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0..n: TDO data                                                    *
+ ****************************************************************************
+ * CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT:                                         *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ * offset 6..x: TDI data                                                    *
+ ****************************************************************************
+ * CMD_SCAN_IO, CMD_SLOW_SCAN_IO:                                           *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ * offset 6..x: TDI data                                                    *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0..n: TDO data                                                    *
+ ****************************************************************************
+ * CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS:                                       *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: tms_count                                                      *
+ * offset 2: tms_sequence                                                   *
+ ****************************************************************************
+ * CMD_CLOCK_TCK, CMD_SLOW_CLOCK_TCK:                                       *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of tck_count                                          *
+ * offset 2: high byte of tck_count                                         *
+ ****************************************************************************
+ * CMD_CLOCK_SLEEP_US:                                                      *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of sleep_us                                           *
+ * offset 2: high byte of sleep_us                                          *
+ ****************************************************************************
+ * CMD_CLOCK_SLEEP_MS:                                                      *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of sleep_ms                                           *
+ * offset 2: high byte of sleep_ms                                          *
+ ****************************************************************************
+ * CMD_GET_SIGNALS:                                                         *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0: current state of input signals                                 *
+ * offset 1: current state of output signals                                *
+ ****************************************************************************
+ * CMD_SET_SIGNALS:                                                         *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: signals that should be de-asserted                             *
+ * offset 2: signals that should be asserted                                *
+ ****************************************************************************
+ * CMD_CONFIGURE_TCK_FREQ:                                                  *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: delay value for scan_in function                               *
+ * offset 2: delay value for scan_out function                              *
+ * offset 3: delay value for scan_io function                               *
+ * offset 4: delay value for clock_tck function                             *
+ * offset 5: delay value for clock_tms function                             *
+ ****************************************************************************
+ * CMD_SET_LEDS:                                                            *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: LED states:                                                    *
+ *           Bit 0: turn COM LED on                                         *
+ *           Bit 1: turn RUN LED on                                         *
+ *           Bit 2: turn COM LED off                                        *
+ *           Bit 3: turn RUN LED off                                        *
+ *           Bits 7..4: Reserved                                            *
+ ****************************************************************************
+ * CMD_TEST:                                                                *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: unused dummy value                                             *
+ ****************************************************************************
+ */
+
+#ifndef __MSGTYPES_H
+#define __MSGTYPES_H
+
+/*
+ * Command IDs:
+ *
+ * Bits 7..6: Reserved, should always be zero
+ * Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs,
+ *            the IDs 0x00..0x1F are commands with variable payload size,
+ *            the IDs 0x20..0x3F are commands with fixed payload size.
+ */
+
+#define CMD_ID_MASK             0x3F
+
+/* Commands with variable payload size */
+#define CMD_SCAN_IN             0x00
+#define CMD_SLOW_SCAN_IN        0x01
+#define CMD_SCAN_OUT            0x02
+#define CMD_SLOW_SCAN_OUT       0x03
+#define CMD_SCAN_IO             0x04
+#define CMD_SLOW_SCAN_IO        0x05
+
+/* Commands with fixed payload size */
+#define CMD_CLOCK_TMS           0x20
+#define CMD_SLOW_CLOCK_TMS      0x21
+#define CMD_CLOCK_TCK           0x22
+#define CMD_SLOW_CLOCK_TCK      0x23
+#define CMD_SLEEP_US            0x24
+#define CMD_SLEEP_MS            0x25
+#define CMD_GET_SIGNALS         0x26
+#define CMD_SET_SIGNALS         0x27
+#define CMD_CONFIGURE_TCK_FREQ  0x28
+#define CMD_SET_LEDS            0x29
+#define CMD_TEST                0x2A
+
+/* JTAG signal definition for jtag_get_signals() -- Input signals! */
+#define SIGNAL_TDO      1
+
+/* JTAG signal definition for jtag_get_signals() -- Output signals! */
+#define SIGNAL_TDI      8
+#define SIGNAL_TMS      2
+#define SIGNAL_TCK      4
+#define SIGNAL_TRST     1
+#define SIGNAL_SRST     32
+
+#endif
diff --git a/contrib/firmware/angie/c/include/protocol.h b/contrib/firmware/angie/c/include/protocol.h
new file mode 100644 (file)
index 0000000..a12644b
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/****************************************************************************
+    File : protocol.h                                                       *
+    Contents : Jtag commands handling protocol header file for NanoXplore   *
+    USB-JTAG ANGIE adapter hardware.                                        *
+    Based on openULINK project code by: Martin Schmoelzer.                  *
+    Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.              *
+    <aboudjelida@nanoxplore.com>                                            *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#ifndef __PROTOCOL_H
+#define __PROTOCOL_H
+
+#include <stdbool.h>
+
+bool execute_command(void);
+void command_loop(void);
+
+#endif
diff --git a/contrib/firmware/angie/c/include/reg_ezusb.h b/contrib/firmware/angie/c/include/reg_ezusb.h
new file mode 100644 (file)
index 0000000..c22476a
--- /dev/null
@@ -0,0 +1,656 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/****************************************************************************
+    File : reg_ezusb.h                                                      *
+    Contents : FX2 microcontroller registers file for NanoXplore            *
+    USB-JTAG ANGIE adapter hardware.                                        *
+    Based on openULINK project code by: Martin Schmoelzer.                  *
+    Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.              *
+    <aboudjelida@nanoxplore.com>                                            *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#ifndef REG_EZUSB_H
+#define REG_EZUSB_H
+
+/**
+ * @file
+ * All information in this file was taken from the EZ-USB FX2 Technical
+ * Reference Manual, Cypress Semiconductor, 3901 North First Street
+ * San Jose, CA 95134 (www.cypress.com).
+ *
+ * The EZ-USB Technical Reference Manual is called "EZ-USB FX2 TRM" hereafter.
+ */
+
+/* Compiler-specific definitions of SBIT, SFR, SFRX, ... macros */
+#include <mcs51/compiler.h>
+
+/* Bit vectors */
+#define bmbit0      0x01
+#define bmbit1      0x02
+#define bmbit2      0x04
+#define bmbit3      0x08
+#define bmbit4      0x10
+#define bmbit5      0x20
+#define bmbit6      0x40
+#define bmbit7      0x80
+
+/**************************************************************************
+ ************************ Special Function Registers **********************
+ ***************************************************************************/
+SFR(IOA,            0x80);
+SBIT(IOA0,          0x80, 0);
+SBIT(IOA1,          0x80, 1);
+SBIT(IOA2,          0x80, 2);
+SBIT(IOA3,          0x80, 3);
+SBIT(IOA4,          0x80, 4);
+SBIT(IOA5,          0x80, 5);
+SBIT(IOA6,          0x80, 6);
+SBIT(IOA7,          0x80, 7);
+
+SFR(SP,             0x81);
+SFR(DPL0,           0x82);
+SFR(DPH0,           0x83);
+SFR(DPL1,           0x84);
+SFR(DPL2,           0x85);
+
+SFR(DPS,            0x86);
+#define SEL         bmbit0
+/* Bit 1 read-only, always reads '0' */
+/* Bit 2 read-only, always reads '0' */
+/* Bit 3 read-only, always reads '0' */
+/* Bit 4 read-only, always reads '0' */
+/* Bit 5 read-only, always reads '0' */
+/* Bit 6 read-only, always reads '0' */
+/* Bit 7 read-only, always reads '0' */
+
+SFR(PCON,           0x87);
+#define IDLE        bmbit0
+#define STOP        bmbit1
+#define GF0         bmbit2
+#define GF1         bmbit3
+/* Bit 4 read-only, always reads '1' */
+/* Bit 5 read-only, always reads '1' */
+/* Bit 6 unused */
+#define SMOD0     bmbit7
+
+SFR(TCON,           0x88);
+SBIT(IT0,           0x88, 0);
+SBIT(IE0,           0x88, 1);
+SBIT(IT1,           0x88, 2);
+SBIT(IE1,           0x88, 3);
+SBIT(TR0,           0x88, 4);
+SBIT(TF0,           0x88, 5);
+SBIT(TR1,           0x88, 6);
+SBIT(TF1,           0x88, 7);
+
+SFR(TMOD,           0x89);
+SFR(TL0,            0x8A);
+SFR(TL1,            0x8B);
+SFR(TH0,            0x8C);
+SFR(TH1,            0x8D);
+
+SFR(CKCON,          0x8E);
+#define MD0         bmbit0
+#define MD1         bmbit1
+#define MD2         bmbit2
+#define T0M         bmbit3
+#define T1M         bmbit4
+#define T2M         bmbit5
+/* Bit 6 unused */
+/* Bit 7 unused */
+
+SFR(SPC_FNC,        0x8F);
+#define BMWRS       bmbit0
+/* Bit 1 read-only, always reads '0' */
+/* Bit 2 read-only, always reads '0' */
+/* Bit 3 read-only, always reads '0' */
+/* Bit 4 read-only, always reads '0' */
+/* Bit 5 read-only, always reads '0' */
+/* Bit 6 read-only, always reads '0' */
+/* Bit 7 read-only, always reads '0' */
+
+SFR(IOB,            0x90);
+SBIT(IOB0,          0x90, 0);
+SBIT(IOB1,          0x90, 1);
+SBIT(IOB2,          0x90, 2);
+SBIT(IOB3,          0x90, 3);
+SBIT(IOB4,          0x90, 4);
+SBIT(IOB5,          0x90, 5);
+SBIT(IOB6,          0x90, 6);
+SBIT(IOB7,          0x90, 7);
+
+SFR(EXIF,           0x91);
+SBIT(USBINT,        0x91, 4);
+SBIT(I2CINT,        0x91, 5);
+SBIT(IE4,           0x91, 6);
+SBIT(IE5,           0x91, 7);
+
+SFR(MPAGE,          0x92);
+SFR(SCON0,          0x98);
+SBIT(RI,            0x98, 0);
+SBIT(TI,            0x98, 1);
+SBIT(RB8,           0x98, 2);
+SBIT(TB8,           0x98, 3);
+SBIT(REN,           0x98, 4);
+SBIT(SM2,           0x98, 5);
+SBIT(SM1,           0x98, 6);
+SBIT(SM0,           0x98, 7);
+
+SFR(SBUF0,          0x99);
+SFR(AUTOPTRH1,      0x9A);
+SFR(AUTOPTRL1,      0x9B);
+SFR(AUTOPTRH2,      0x9D);
+SFR(AUTOPTRL2,      0x9E);
+
+#define AUTOPTR1H AUTOPTRH1 /* for backwards compatibility with examples */
+#define AUTOPTR1L AUTOPTRL1 /* for backwards compatibility with examples */
+#define APTR1H AUTOPTRH1 /* for backwards compatibility with examples */
+#define APTR1L AUTOPTRL1 /* for backwards compatibility with examples */
+
+SFR(IOC,            0xA0);
+SBIT(IOC0,          0xA0, 0);
+SBIT(IOC1,          0xA0, 1);
+SBIT(IOC2,          0xA0, 2);
+SBIT(IOC3,          0xA0, 3);
+SBIT(IOC4,          0xA0, 4);
+SBIT(IOC5,          0xA0, 5);
+SBIT(IOC6,          0xA0, 6);
+SBIT(IOC7,          0xA0, 7);
+
+SFR(INT2CLR,        0xA1);
+SFR(INT4CLR,        0xA2);
+SFR(IE,             0xA8);
+SBIT(EX0,           0xA8, 0);
+SBIT(ET0,           0xA8, 1);
+SBIT(EX1,           0xA8, 2);
+SBIT(ET1,           0xA8, 3);
+SBIT(ES0,           0xA8, 4);
+SBIT(ET2,           0xA8, 5);
+SBIT(ES1,           0xA8, 6);
+SBIT(EA,            0xA8, 7);
+
+SFR(EP2468STAT,     0xAA);
+#define EP8F        bmbit7
+#define EP8E        bmbit6
+#define EP6F        bmbit5
+#define EP6E        bmbit4
+#define EP4F        bmbit3
+#define EP4E        bmbit2
+#define EP2F        bmbit1
+#define EP2E        bmbit0
+
+SFR(EP24FIFOFLGS,   0xAB);
+SFR(EP68FIFOFLGS,   0xAC);
+SFR(AUTOPTRSETUP,   0xAF);
+SFR(IOD,            0xB0);
+SBIT(IOD0,          0xB0, 0);
+SBIT(IOD1,          0xB0, 1);
+SBIT(IOD2,          0xB0, 2);
+SBIT(IOD3,          0xB0, 3);
+SBIT(IOD4,          0xB0, 4);
+SBIT(IOD5,          0xB0, 5);
+SBIT(IOD6,          0xB0, 6);
+SBIT(IOD7,          0xB0, 7);
+
+SFR(IOE,            0xB1);
+SFR(OEA,            0xB2);
+SFR(OEB,            0xB3);
+SFR(OEC,            0xB4);
+SFR(OED,            0xB5);
+SFR(OEE,            0xB6);
+
+SFR(IP,             0xB8);
+SBIT(PX0,           0xB8, 0);
+SBIT(PT0,           0xB8, 1);
+SBIT(PX1,           0xB8, 2);
+SBIT(PT1,           0xB8, 3);
+SBIT(PS0,           0xB8, 4);
+SBIT(PT2,           0xB8, 5);
+SBIT(PS1,           0xB8, 6);
+/* Bit 7 read-only, always reads '1' */
+
+SFR(EP01STAT,       0xBA);
+SFR(GPIFTRIG,       0xBB);
+#define BMGPIFDONE  bmbit7
+#define BMGPIFREAD  bmbit2
+#define GPIF_EP2    0
+#define GPIF_EP4    1
+#define GPIF_EP6    2
+#define GPIF_EP8    3
+
+SFR(GPIFSGLDATH,    0xBD);
+SFR(GPIFSGLDATLX,   0xBE);
+SFR(GPIFSGLDATLNOX, 0xBF);
+
+SFR(SCON1,          0xC0);
+SBIT(RI_1,          0xC0, 0);
+SBIT(TI_1,          0xC0, 1);
+SBIT(RB8_1,         0xC0, 2);
+SBIT(TB8_1,         0xC0, 3);
+SBIT(REN_1,         0xC0, 4);
+SBIT(SM2_1,         0xC0, 5);
+SBIT(SM1_1,         0xC0, 6);
+SBIT(SM0_1,         0xC0, 7);
+
+SFR(SBUF1,          0xC1);
+SFR(T2CON,          0xC8);
+SBIT(CPRL2,         0xC8, 0);
+SBIT(C_T2,          0xC8, 1);
+SBIT(TR2,           0xC8, 2);
+SBIT(EXEN2,         0xC8, 3);
+SBIT(TCLK,          0xC8, 4);
+SBIT(RCLK,          0xC8, 5);
+SBIT(EXF2,          0xC8, 6);
+SBIT(TF2,           0xC8, 7);
+
+SFR(RCAP2L,         0xCA);
+SFR(RCAP2H,         0xCB);
+SFR(TL2,            0xCC);
+SFR(TH2,            0xCD);
+SFR(PSW,            0xD0);
+SBIT(P,             0xD0, 0);
+SBIT(F1,            0xD0, 1);
+SBIT(OV,            0xD0, 2);
+SBIT(RS0,           0xD0, 3);
+SBIT(RS1,           0xD0, 4);
+SBIT(F0,            0xD0, 5);
+SBIT(AC,            0xD0, 6);
+SBIT(CY,            0xD0, 7);
+
+SFR(EICON,          0xD8);
+/* Bit 0 read-only, always reads '0' */
+/* Bit 1 read-only, always reads '0' */
+/* Bit 2 read-only, always reads '0' */
+SBIT(INT6,          0xD8, 3);
+SBIT(RESI,          0xD8, 4);
+SBIT(ERESI,         0xD8, 5);
+/* Bit 6 read-only, always reads '1' */
+SBIT(SMOD1,         0xD8, 7);
+
+SFR(ACC,            0xE0);
+SFR(EIE,            0xE8);
+SBIT(EUSB,          0xE8, 0);
+SBIT(EI2C,          0xE8, 1);
+SBIT(EX4,           0xE8, 2);
+SBIT(EX5,           0xE8, 3);
+SBIT(EWDI,          0xE8, 4);
+/* Bit 5 read-only, always reads '1' */
+/* Bit 6 read-only, always reads '1' */
+/* Bit 7 read-only, always reads '1' */
+
+SFR(B,              0xF0);
+SFR(EIP,            0xF8);
+SBIT(PUSB,          0xF8, 0);
+SBIT(PI2C,          0xF8, 1);
+SBIT(PX4,           0xF8, 2);
+SBIT(PX5,           0xF8, 3);
+SBIT(PX6,           0xF8, 4);
+/* Bit 5 read-only, always reads '1' */
+/* Bit 6 read-only, always reads '1' */
+/* Bit 7 read-only, always reads '1' */
+
+/**************************************************************************
+ ***************************** XDATA Registers ****************************
+ ***************************************************************************/
+
+SFRX(GPIF_WAVE_DATA,         0xE400);
+SFRX(RES_WAVEDATA_END,       0xE480);
+
+/* General Configuration */
+SFRX(CPUCS,         0xE600);
+#define RES8051     bmbit0
+#define CLKOE       bmbit1
+#define BMCLKINV    bmbit2
+#define bmclkspd0   bmbit3
+#define bmclkspd1   bmbit4
+#define bmclkspd   (bmbit4 | bmbit3)
+#define BMPRTCSTB   bmbit5
+
+/* PCON register */
+#define BMSMOD0     bmbit7
+
+SFRX(IFCONFIG,        0xE601);
+#define BMIFCLKSRC    bmbit7
+#define BM3048MHZ     bmbit6
+#define BMIFCLKOE     bmbit5
+#define BMIFCLKPOL    bmbit4
+#define BMASYNC       bmbit3
+#define BMGSTATE      bmbit2
+#define BMIFCFG1      bmbit1
+#define BMIFCFG0      bmbit0
+#define BMIFCFGMASK   (BMIFCFG0 | BMIFCFG1)
+#define BMIFGPIF      BMIFCFG1
+
+SFRX(PINFLAGSAB,      0xE602);
+SFRX(PINFLAGSCD,      0xE603);
+SFRX(FIFORESET,       0xE604);
+#define BMNAKALL      bmbit7
+
+SFRX(BREAKPT,         0xE605);
+#define BMBREAK       bmbit3
+#define BMBPPULSE     bmbit2
+#define BMBPEN        bmbit1
+
+SFRX(BPADDRH,         0xE606);
+SFRX(BPADDRL,         0xE607);
+SFRX(UART230,         0xE608);
+SFRX(FIFOPINPOLAR,    0xE609);
+SFRX(REVID,           0xE60A);
+SFRX(REVCTL,          0xE60B);
+#define BMNOAUTOARM    bmbit1
+#define BMSKIPCOMMIT   bmbit0
+
+/* Endpoint Configuration */
+SFRX(EP1OUTCFG,       0xE610);
+SFRX(EP1INCFG,        0xE611);
+SFRX(EP2CFG,          0xE612);
+SFRX(EP4CFG,          0xE613);
+SFRX(EP6CFG,          0xE614);
+SFRX(EP8CFG,          0xE615);
+SFRX(EP2FIFOCFG,      0xE618);
+SFRX(EP4FIFOCFG,      0xE619);
+SFRX(EP6FIFOCFG,      0xE61A);
+SFRX(EP8FIFOCFG,      0xE61B);
+#define BMINFM        bmbit6
+#define BMOEP         bmbit5
+#define BMAUTOOUT     bmbit4
+#define BMAUTOIN      bmbit3
+#define BMZEROLENIN   bmbit2
+#define BMWORDWIDE    bmbit0
+
+SFRX(EP2AUTOINLENH,   0xE620);
+SFRX(EP2AUTOINLENL,   0xE621);
+SFRX(EP4AUTOINLENH,   0xE622);
+SFRX(EP4AUTOINLENL,   0xE623);
+SFRX(EP6AUTOINLENH,   0xE612);
+SFRX(EP6AUTOINLENL,   0xE613);
+SFRX(EP8AUTOINLENH,   0xE614);
+SFRX(EP8AUTOINLENL,   0xE615);
+SFRX(EP2FIFOPFH,      0xE630);
+SFRX(EP2FIFOPFL,      0xE631);
+SFRX(EP4FIFOPFH,      0xE632);
+SFRX(EP4FIFOPFL,      0xE633);
+SFRX(EP6FIFOPFH,      0xE634);
+SFRX(EP6FIFOPFL,      0xE635);
+SFRX(EP8FIFOPFH,      0xE636);
+SFRX(EP8FIFOPFL,      0xE637);
+SFRX(EP2ISOINPKTS,    0xE640);
+SFRX(EP4ISOINPKTS,    0xE641);
+SFRX(EP6ISOINPKTS,    0xE642);
+SFRX(EP8ISOINPKTS,    0xE643);
+SFRX(INPKTEND,        0xE648);
+SFRX(OUTPKTEND,       0xE649);
+
+/* Interrupts */
+SFRX(EP2FIFOIE,       0xE650);
+SFRX(EP2FIFOIRQ,      0xE651);
+SFRX(EP4FIFOIE,       0xE652);
+SFRX(EP4FIFOIRQ,      0xE653);
+SFRX(EP6FIFOIE,       0xE654);
+SFRX(EP6FIFOIRQ,      0xE655);
+SFRX(EP8FIFOIE,       0xE656);
+SFRX(EP8FIFOIRQ,      0xE657);
+SFRX(IBNIE,           0xE658);
+SFRX(IBNIRQ,          0xE659);
+#define EP0IBN        bmbit0
+#define EP1IBN        bmbit1
+#define EP2IBN        bmbit2
+#define EP4IBN        bmbit3
+#define EP6IBN        bmbit4
+#define EP8IBN        bmbit5
+
+SFRX(NAKIE,           0xE65A);
+SFRX(NAKIRQ,          0xE65B);
+#define EP8PING       bmbit7
+#define EP6PING       bmbit6
+#define EP4PING       bmbit5
+#define EP2PING       bmbit4
+#define EP1PING       bmbit3
+#define EP0PING       bmbit2
+#define IBN           bmbit0
+
+SFRX(USBIEN,          0xE65C);
+SFRX(USBIRQ,          0xE65D);
+#define SUDAVI        bmbit0
+#define SOFI          bmbit1
+#define SUTOKI        bmbit2
+#define SUSPI         bmbit3
+#define URESI         bmbit4
+#define HSGRANT       bmbit5
+#define EP0ACK        bmbit6
+
+SFRX(EPIE,            0xE65E);
+SFRX(EPIRQ,           0xE65F);
+SFRX(GPIFIE,          0xE660);
+SFRX(GPIFIRQ,         0xE661);
+SFRX(USBERRIE,        0xE662);
+SFRX(USBERRIRQ,       0xE663);
+SFRX(ERRCNTLIM,       0xE664);
+SFRX(CLRERRCNT,       0xE665);
+SFRX(INT2IVEC,        0xE666);
+#define I2V0          bmbit2
+#define I2V1          bmbit3
+#define I2V2          bmbit4
+#define I2V3          bmbit5
+#define I2V4          bmbit6
+
+SFRX(INT4IVEC,        0xE667);
+SFRX(INTSETUP,        0xE668);
+#define AV4EN         bmbit0
+#define INT4IN        bmbit1
+#define AV2EN         bmbit3
+
+/* Input/Output */
+SFRX(PORTACFG,        0xE670);
+#define BMINT0        bmbit0
+#define BMINT1        bmbit1
+#define BMFLAGD       bmbit7
+
+SFRX(PORTCCFG,        0xE671);
+#define BMGPIFA0      bmbit0
+#define BMGPIFA1      bmbit1
+#define BMGPIFA2      bmbit2
+#define BMGPIFA3      bmbit3
+#define BMGPIFA4      bmbit4
+#define BMGPIFA5      bmbit5
+#define BMGPIFA6      bmbit6
+#define BMGPIFA7      bmbit7
+
+SFRX(PORTECFG,        0xE672);
+#define BMT0OUT       bmbit0
+#define BMT1OUT       bmbit1
+#define BMT2OUT       bmbit2
+#define BMRXD0OUT     bmbit3
+#define BMRXD1OUT     bmbit4
+#define BMINT6        bmbit5
+#define BMT2EX        bmbit6
+#define BMGPIFA8      bmbit7
+
+SFRX(I2CS,            0xE678);
+#define BMDONE        bmbit0
+#define BMACK         bmbit1
+#define BMBERR        bmbit2
+#define BMID         (bmbit4 | bmbit3)
+#define BMLASTRD      bmbit5
+#define BMSTOP        bmbit6
+#define BMSTART       bmbit7
+
+SFRX(I2DAT,           0xE679);
+SFRX(I2CTL,           0xE67A);
+#define BMSTOPIE      bmbit1
+#define BM400KHZ      bmbit0
+
+SFRX(XAUTODAT1,       0xE67B);
+SFRX(XAUTODAT2,       0xE67C);
+#define EXTAUTODAT1   XAUTODAT1
+#define EXTAUTODAT2   XAUTODAT2
+
+/* USB Control */
+SFRX(USBCS,           0xE680);
+#define SIGRSUME      bmbit0
+#define RENUM         bmbit1
+#define NOSYNSOF      bmbit2
+#define DISCON        bmbit3
+#define HSM           bmbit7
+
+SFRX(SUSPEND,         0xE681);
+SFRX(WAKEUPCS,        0xE682);
+#define BMWU2         bmbit7
+#define BMWU          bmbit6
+#define BMWU2POL      bmbit5
+#define BMWUPOL       bmbit4
+#define BMDPEN        bmbit2
+#define BMWU2EN       bmbit1
+#define BMWUEN        bmbit0
+
+SFRX(TOGCTL,           0xE683);
+#define BMTOGCTLEPMASK bmbit3 | bmbit2 | bmbit1 | bmbit0
+#define BMRESETTOGGLE  bmbit5
+#define BMSETTOGGLE    bmbit6
+#define BMQUERYTOGGLE  bmbit7
+
+SFRX(USBFRAMEH,        0xE684);
+SFRX(USBFRAMEL,        0xE685);
+SFRX(MICROFRAME,       0xE686);
+SFRX(FNADDR,           0xE687);
+
+/* Endpoints */
+SFRX(EP0BCH,           0xE68A);
+SFRX(EP0BCL,           0xE68B);
+SFRX(EP1OUTBC,         0xE68D);
+SFRX(EP1INBC,          0xE68F);
+SFRX(EP2BCH,           0xE690);
+SFRX(EP2BCL,           0xE691);
+SFRX(EP4BCH,           0xE694);
+SFRX(EP4BCL,           0xE695);
+SFRX(EP6BCH,           0xE698);
+SFRX(EP6BCL,           0xE699);
+SFRX(EP8BCH,           0xE69C);
+SFRX(EP8BCL,           0xE69D);
+SFRX(EP0CS,            0xE6A0);
+#define HSNAK          bmbit7
+
+SFRX(EP1INCS,          0xE6A2);
+SFRX(EP1OUTCS,         0xE6A1);
+#define EPSTALL        bmbit0
+#define EPBSY          bmbit1
+
+SFRX(EP2CS,            0xE6A3);
+SFRX(EP4CS,            0xE6A4);
+SFRX(EP6CS,            0xE6A5);
+SFRX(EP8CS,            0xE6A6);
+#define BMEPEMPTY      bmbit2
+#define BMEPFULL       bmbit3
+#define BMNPAK        (bmbit6 | bmbit5 | bmbit4)
+
+SFRX(EP2FIFOFLGS,      0xE6A7);
+SFRX(EP4FIFOFLGS,      0xE6A8);
+SFRX(EP6FIFOFLGS,      0xE6A9);
+SFRX(EP8FIFOFLGS,      0xE6AA);
+SFRX(EP2FIFOBCH,       0xE6AB);
+SFRX(EP2FIFOBCL,       0xE6AC);
+SFRX(EP4FIFOBCH,       0xE6AD);
+SFRX(EP4FIFOBCL,       0xE6AE);
+SFRX(EP6FIFOBCH,       0xE6AF);
+SFRX(EP6FIFOBCL,       0xE6B0);
+SFRX(EP8FIFOBCH,       0xE6B1);
+SFRX(EP8FIFOBCL,       0xE6B2);
+SFRX(SUDPTRH,          0xE6B3);
+SFRX(SUDPTRL,          0xE6B4);
+
+SFRX(SUDPTRCTL,        0xE6B5);
+#define BMSDPAUTO      bmbit0
+
+SFRX(SETUPDAT[8],      0xE6B8);
+
+/* GPIF */
+SFRX(GPIFWFSELECT,     0xE6C0);
+SFRX(GPIFIDLECS,       0xE6C1);
+SFRX(GPIFIDLECTL,      0xE6C2);
+SFRX(GPIFCTLCFG,       0xE6C3);
+SFRX(GPIFADRH,         0xE6C4);
+SFRX(GPIFADRL,         0xE6C5);
+SFRX(GPIFTCB3,         0xE6CE);
+SFRX(GPIFTCB2,         0xE6CF);
+SFRX(GPIFTCB1,         0xE6D0);
+SFRX(GPIFTCB0,         0xE6D1);
+
+#define EP2GPIFTCH     GPIFTCB1   /* these are here for backwards compatibility */
+#define EP2GPIFTCL     GPIFTCB0
+#define EP4GPIFTCH     GPIFTCB1   /* these are here for backwards compatibility */
+#define EP4GPIFTCL     GPIFTCB0
+#define EP6GPIFTCH     GPIFTCB1   /* these are here for backwards compatibility */
+#define EP6GPIFTCL     GPIFTCB0
+#define EP8GPIFTCH     GPIFTCB1   /* these are here for backwards compatibility */
+#define EP8GPIFTCL     GPIFTCB0
+
+SFRX(EP2GPIFFLGSEL,    0xE6D2);
+SFRX(EP2GPIFPFSTOP,    0xE6D3);
+SFRX(EP2GPIFTRIG,      0xE6D4);
+SFRX(EP4GPIFFLGSEL,    0xE6DA);
+SFRX(EP4GPIFPFSTOP,    0xE6DB);
+SFRX(EP4GPIFTRIG,      0xE6DC);
+SFRX(EP6GPIFFLGSEL,    0xE6E2);
+SFRX(EP6GPIFPFSTOP,    0xE6E3);
+SFRX(EP6GPIFTRIG,      0xE6E4);
+SFRX(EP8GPIFFLGSEL,    0xE6EA);
+SFRX(EP8GPIFPFSTOP,    0xE6EB);
+SFRX(EP8GPIFTRIG,      0xE6EC);
+SFRX(XGPIFSGLDATH,     0xE6F0);
+SFRX(XGPIFSGLDATLX,    0xE6F1);
+SFRX(XGPIFSGLDATLNOX,  0xE6F2);
+SFRX(GPIFREADYCFG,     0xE6F3);
+SFRX(GPIFREADYSTAT,    0xE6F4);
+SFRX(GPIFABORT,        0xE6F5);
+
+// UDMA
+SFRX(FLOWSTATE,        0xE6C6);
+SFRX(FLOWLOGIC,        0xE6C7);
+SFRX(FLOWEQ0CTL,       0xE6C8);
+SFRX(FLOWEQ1CTL,       0xE6C9);
+SFRX(FLOWHOLDOFF,      0xE6CA);
+SFRX(FLOWSTB,          0xE6CB);
+SFRX(FLOWSTBEDGE,      0xE6CC);
+SFRX(FLOWSTBHPERIOD,   0xE6CD);
+SFRX(GPIFHOLDAMOUNT,   0xE60C);
+SFRX(UDMACRCH,         0xE67D);
+SFRX(UDMACRCL,         0xE67E);
+SFRX(UDMACRCQUAL,      0xE67F);
+
+/* Debug/Test
+ * The following registers are for Cypress's internal testing purposes only.
+ * These registers are not documented in the datasheet or the Technical Reference
+ * Manual as they were not designed for end user application usage
+ */
+SFRX(DBUG,             0xE6F8);
+SFRX(TESTCFG,          0xE6F9);
+SFRX(USBTEST,          0xE6FA);
+SFRX(CT1,              0xE6FB);
+SFRX(CT2,              0xE6FC);
+SFRX(CT3,              0xE6FD);
+SFRX(CT4,              0xE6FE);
+
+/* Endpoint Buffers */
+SFRX(EP0BUF[64],        0xE740);
+SFRX(EP1INBUF[64],      0xE7C0);
+SFRX(EP1OUTBUF[64],     0xE780);
+SFRX(EP2FIFOBUF[512],   0xF000);
+SFRX(EP4FIFOBUF[512],   0xF400);
+SFRX(EP6FIFOBUF[512],   0xF800);
+SFRX(EP8FIFOBUF[512],   0xFC00);
+
+/* Error Correction Code (ECC) Registers (FX2LP/FX1 only) */
+SFRX(ECCCFG,            0xE628);
+SFRX(ECCRESET,          0xE629);
+SFRX(ECC1B0,            0xE62A);
+SFRX(ECC1B1,            0xE62B);
+SFRX(ECC1B2,            0xE62C);
+SFRX(ECC2B0,            0xE62D);
+SFRX(ECC2B1,            0xE62E);
+SFRX(ECC2B2,            0xE62F);
+
+/* Feature Registers  (FX2LP/FX1 only) */
+SFRX(GPCR2,         0xE50D);
+#define BMFULLSPEEDONLY    bmbit4
+
+#endif
diff --git a/contrib/firmware/angie/c/include/serial.h b/contrib/firmware/angie/c/include/serial.h
new file mode 100644 (file)
index 0000000..548c005
--- /dev/null
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/**
+ * This code was taken from the fx2lib project from this link:
+ * https://github.com/djmuhlestein/fx2lib
+ *
+ * Copyright (C) 2009 Ubixum, Inc.
+ **/
+
+/** \file serial.h
+ * defines functions to print to a serial console with SIO0
+ **/
+
+#include "fx2macros.h"
+#include <stdint.h>
+/**
+ * This function inits sio0 to use T2CON (timer 2)
+ * See TRM 14.3.4.1 (Table 14-16)
+ * Certain baud rates have too high an error rate to work.  All baud rates are .16%
+ * except:
+ *
+ *          12MHZ      24MHZ
+ *   \li 57600  -6.99%
+ *   \li 38400  -2.34%     -2.34%
+ *   \li 19200  -2.34%
+ *
+ *   Possible Baud rates:
+ *    \li 2400
+ *    \li 4800
+ *    \li 9600
+ *    \li 19200
+ *    \li 28800
+ *    \li 38400
+ *    \li 57600
+ *
+ *    Any of these rates should work except 57600 at 12mhz.  -2.34% is pushing
+ *    most hardware specs for working.  All rates at 48mhz work at .16%
+ **/
+
+void sio0_init(uint32_t baud_rate) __critical; /* baud_rate max should be 57600 since int=2 bytes */
+
+/**
+ * putchar('\\n') or putchar('\\r') both transmit \\r\\n
+ * Just use one or the other. (This makes terminal echo easy)
+ **/
+int putchar(char c);
+int getchar(void);
diff --git a/contrib/firmware/angie/c/include/usb.h b/contrib/firmware/angie/c/include/usb.h
new file mode 100644 (file)
index 0000000..0450d1d
--- /dev/null
@@ -0,0 +1,273 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/****************************************************************************
+       File : usb.h                                                                                                                    *
+       Contents : usb communication handling header file for NanoXplore                *
+       USB-JTAG ANGIE adapter hardware.                                                                                *
+       Based on openULINK project code by: Martin Schmoelzer.                                  *
+       Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.                              *
+       <aboudjelida@nanoxplore.com>                                                                                    *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#ifndef __USB_H
+#define __USB_H
+
+#include "reg_ezusb.h"
+#include <stdint.h>
+#include <stdbool.h>
+
+/* High and Low byte of a word (uint16_t) */
+#define HI8(word)   (uint8_t)(((uint16_t)(word) >> 8) & 0xff)
+#define LO8(word)   (uint8_t)((uint16_t)(word) & 0xff)
+
+/* Convenience functions */
+#define STALL_EP0()   (EP0CS |= EPSTALL)
+#define CLEAR_IRQ()   (USBINT = 0)
+
+/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/
+
+/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */
+#define DESCRIPTOR_TYPE_DEVICE         0x01
+#define DESCRIPTOR_TYPE_CONFIGURATION  0x02
+#define DESCRIPTOR_TYPE_STRING         0x03
+#define DESCRIPTOR_TYPE_INTERFACE      0x04
+#define DESCRIPTOR_TYPE_ENDPOINT       0x05
+
+#define STR_DESCR(len, ...) { (len) * 2 + 2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } }
+
+/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */
+struct usb_device_descriptor {
+       uint8_t blength;                /**< Size of this descriptor in bytes. */
+       uint8_t bdescriptortype;        /**< DEVICE Descriptor Type. */
+       uint16_t bcdusb;                /**< USB specification release number (BCD). */
+       uint8_t bdeviceclass;           /**< Class code. */
+       uint8_t bdevicesubclass;        /**< Subclass code. */
+       uint8_t bdeviceprotocol;        /**< Protocol code. */
+       uint8_t bmaxpacketsize0;        /**< Maximum packet size for EP0 (8, 16, 32, 64). */
+       uint16_t idvendor;              /**< USB Vendor ID. */
+       uint16_t idproduct;             /**< USB Product ID. */
+       uint16_t bcddevice;             /**< Device Release Number (BCD). */
+       uint8_t imanufacturer;          /**< Index of manufacturer string descriptor. */
+       uint8_t iproduct;               /**< Index of product string descriptor. */
+       uint8_t iserialnumber;          /**< Index of string descriptor containing serial #. */
+       uint8_t bnumconfigurations;     /**< Number of possible configurations. */
+};
+
+/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */
+struct usb_config_descriptor {
+       uint8_t blength;                /**< Size of this descriptor in bytes. */
+       uint8_t bdescriptortype;        /**< CONFIGURATION descriptor type. */
+       uint16_t wtotallength;          /**< Combined total length of all descriptors. */
+       uint8_t bnuminterfaces;         /**< Number of interfaces in this configuration. */
+       uint8_t bconfigurationvalue;    /**< Value used to select this configuration. */
+       uint8_t iconfiguration;         /**< Index of configuration string descriptor. */
+       uint8_t bmattributes;           /**< Configuration characteristics. */
+       uint8_t maxpower;               /**< Maximum power consumption in 2 mA units. */
+};
+
+/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */
+struct usb_interface_descriptor {
+       uint8_t blength;                /**< Size of this descriptor in bytes. */
+       uint8_t bdescriptortype;        /**< INTERFACE descriptor type. */
+       uint8_t binterfacenumber;       /**< Interface number. */
+       uint8_t balternatesetting;      /**< Value used to select alternate setting. */
+       uint8_t bnumendpoints;          /**< Number of endpoints used by this interface. */
+       uint8_t binterfaceclass;        /**< Class code. */
+       uint8_t binterfacesubclass;     /**< Subclass code. */
+       uint8_t binterfaceprotocol;     /**< Protocol code. */
+       uint8_t iinterface;             /**< Index of interface string descriptor. */
+};
+
+/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */
+struct usb_endpoint_descriptor {
+       uint8_t blength;                /**< Size of this descriptor in bytes. */
+       uint8_t bdescriptortype;        /**< ENDPOINT descriptor type. */
+       uint8_t bendpointaddress;       /**< Endpoint Address: IN/OUT + EP number. */
+       uint8_t bmattributes;           /**< Endpoint Attributes: BULK/INTR/ISO/CTRL. */
+       uint16_t wmaxpacketsize;        /**< Maximum packet size for this endpoint. */
+       uint8_t binterval;              /**< Polling interval (in ms) for this endpoint. */
+};
+
+/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */
+struct usb_language_descriptor {
+       uint8_t blength;                /**< Size of this descriptor in bytes. */
+       uint8_t bdescriptortype;        /**< STRING descriptor type. */
+       uint16_t wlangid[];             /**< LANGID codes. */
+};
+
+/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */
+struct usb_string_descriptor {
+       uint8_t blength;                /**< Size of this descriptor in bytes. */
+       uint8_t bdescriptortype;        /**< STRING descriptor type. */
+       uint16_t bstring[];             /**< UNICODE encoded string. */
+};
+
+/********************** USB Control Endpoint 0 related *********************/
+
+/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */
+struct setup_data {
+       uint8_t bmrequesttype;          /**< Characteristics of a request. */
+       uint8_t brequest;               /**< Specific request. */
+       uint16_t wvalue;                /**< Field that varies according to request. */
+       uint16_t windex;                /**< Field that varies according to request. */
+       uint16_t wlength;               /**< Number of bytes to transfer in data stage. */
+};
+
+/* External declarations for variables that need to be accessed outside of
+ * the USB module */
+extern volatile bool ep1_out;
+extern volatile bool ep1_in;
+
+extern volatile __xdata __at 0xE6B8 struct setup_data setup_data;
+
+/*
+ * USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2
+ *
+ * Bit 7: Data transfer direction
+ *    0 = Host-to-device
+ *    1 = Device-to-host
+ * Bit 6...5: Type
+ *    0 = Standard
+ *    1 = Class
+ *    2 = Vendor
+ *    3 = Reserved
+ * Bit 4...0: Recipient
+ *    0 = Device
+ *    1 = Interface
+ *    2 = Endpoint
+ *    3 = Other
+ *    4...31 = Reserved
+ */
+
+#define USB_DIR_OUT             0x00
+#define USB_DIR_IN              0x80
+
+#define USB_REQ_TYPE_STANDARD   (0x00 << 5)
+#define USB_REQ_TYPE_CLASS      (0x01 << 5)
+#define USB_REQ_TYPE_VENDOR     (0x02 << 5)
+#define USB_REQ_TYPE_RESERVED   (0x03 << 5)
+
+#define USB_RECIP_DEVICE        0x00
+#define USB_RECIP_INTERFACE     0x01
+#define USB_RECIP_ENDPOINT      0x02
+#define USB_RECIP_OTHER         0x03
+
+/* Clear Interface Request */
+#define CF_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define CF_ENDPOINT  (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Get Configuration Request */
+#define GC_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Get Descriptor Request */
+#define GD_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Get Interface Request */
+#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+
+/* Get Status Request: See USB 1.1 spec, page 190 */
+#define GS_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define GS_ENDPOINT  (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Set Address Request is handled by EZ-USB core */
+
+/* Set Configuration Request */
+#define SC_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Set Descriptor Request */
+#define SD_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Set Feature Request */
+#define SF_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define SF_ENDPOINT  (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Set Interface Request */
+#define SI_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+
+/* Synch Frame Request */
+#define SY_ENDPOINT  (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */
+#define GET_STATUS               0
+#define CLEAR_FEATURE            1
+/* Value '2' is reserved for future use */
+#define SET_FEATURE              3
+/* Value '4' is reserved for future use */
+#define SET_ADDRESS              5
+#define GET_DESCRIPTOR           6
+#define SET_DESCRIPTOR           7
+#define GET_CONFIGURATION        8
+#define SET_CONFIGURATION        9
+#define GET_INTERFACE           10
+#define SET_INTERFACE           11
+#define SYNCH_FRAME             12
+
+/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */
+#define DEVICE_REMOTE_WAKEUP     1
+#define ENDPOINT_HALT            0
+
+/************************** EZ-USB specific stuff **************************/
+/** USB Interrupts. See AN2131-TRM, page 9-4 for details */
+enum usb_isr {
+       SUDAV_ISR = 13,
+       SOF_ISR,
+       SUTOK_ISR,
+       SUSPEND_ISR,
+       USBRESET_ISR,
+       HIGHSPEED_ISR,
+       EP0ACK_ISR,
+       STUB_ISR,
+       EP0IN_ISR,
+       EP0OUT_ISR,
+       EP1IN_ISR,
+       EP1OUT_ISR,
+       EP2_ISR,
+       EP4_ISR,
+       EP6_ISR,
+       EP8_ISR,
+       IBN_ISR,
+       EP0PINGNAK_ISR,
+       EP1PINGNAK_ISR,
+       EP2PINGNAK_ISR,
+       EP4PINGNAK_ISR,
+       EP6PINGNAK_ISR,
+       EP8PINGNAK_ISR,
+       ERRORLIMIT_ISR,
+       EP2PIDERROR_ISR,
+       EP4PIDERROR_ISR,
+       EP6PIDERROR_ISR,
+       EP8PIDERROR_ISR,
+       EP2PFLAG_ISR,
+       EP4PFLAG_ISR,
+       EP6PFLAG_ISR,
+       EP8PFLAG_ISR,
+       EP2EFLAG_ISR,
+       EP4EFLAG_ISR,
+       EP6EFLAG_ISR,
+       EP8EFLAG_ISR,
+       EP2FFLAG_ISR,
+       EP4FFLAG_ISR,
+       EP6FFLAG_ISR,
+       EP8FFLAG_ISR,
+       GPIFCOMPLETE_ISR,
+       GPIFWAVEFORM_ISR
+};
+
+/*************************** Function Prototypes ***************************/
+__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep);
+void usb_reset_data_toggle(uint8_t ep);
+bool usb_handle_get_status(void);
+bool usb_handle_clear_feature(void);
+bool usb_handle_set_feature(void);
+bool usb_handle_get_descriptor(void);
+void usb_handle_set_interface(void);
+void usb_handle_setup_data(void);
+
+void ep_init(void);
+void interrupt_init(void);
+void io_init(void);
+
+#endif
diff --git a/contrib/firmware/angie/c/src/USBJmpTb.a51 b/contrib/firmware/angie/c/src/USBJmpTb.a51
new file mode 100644 (file)
index 0000000..13b5f72
--- /dev/null
@@ -0,0 +1,125 @@
+; SPDX-License-Identifier: GPL-2.0-or-later
+;****************************************************************************
+;      File : USBJmpTb.a51                                                                                                             *
+;      Contents : Interruptions vector configuration.                                  *
+;      Based on openULINK project code by: Martin Schmoelzer.                                  *
+;      Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.                              *
+;      <aboudjelida@nanoxplore.com>                                                                                    *
+;      <ahmederrachedbjld@gmail.com>                                                                                   *
+;****************************************************************************
+.module JUMPTABLE
+
+.globl USB_AutoVector
+.globl USB_Jump_Table
+
+.globl _sudav_isr, _sof_isr, _sutok_isr, _suspend_isr, _usbreset_isr, _highspeed_isr, _ep0ack_isr, _stub_isr, _ep0in_isr, _ep0out_isr, _ep1in_isr, _ep1out_isr, _ep2_isr, _ep4_isr, _ep6_isr, _ep8_isr, _ibn_isr
+.globl _ep0pingnak_isr, _ep1pingnak_isr, _ep2pingnak_isr, _ep4pingnak_isr, _ep6pingnak_isr, _ep8pingnak_isr, _errorlimit_isr, _stub_isr, _stub_isr, _stub_isr, _ep2piderror_isr, _ep4piderror_isr, _ep6piderror_isr, _ep8piderror_isr
+.globl _ep2pflag_isr, _ep4pflag_isr, _ep6pflag_isr, _ep8pflag_isr, _ep2eflag_isr, _ep4eflag_isr, _ep6eflag_isr, _ep8eflag_isr, _ep2fflag_isr, _ep4fflag_isr, _ep6fflag_isr, _ep8fflag_isr, _gpifcomplete_isr, _gpifwaveform_isr
+
+;--------------------------------------------------------------------------;
+; Interrupt Vectors                                                        ;
+;--------------------------------------------------------------------------;
+.area   USB_JV (ABS,OVR)   ; Absolute, Overlay
+.org    0x43               ; USB interrupt (INT2) jumps here
+USB_AutoVector = #. + 2
+    ljmp  USB_Jump_Table    ; Autovector will replace byte 45
+
+;--------------------------------------------------------------------------;
+; USB Jump Table                                                           ;
+;--------------------------------------------------------------------------;
+.area  USB_JT (ABS)        ; Absolute placement
+.org   0x0200              ; Place jump table at 0x0200
+
+USB_Jump_Table:            ; autovector jump table
+    ljmp  _sudav_isr       ; (00) Setup Data Available
+    .db 0
+    ljmp  _sof_isr         ; (04) Start of Frame
+    .db 0
+    ljmp  _sutok_isr       ; (08) Setup Data Loading
+    .db 0
+    ljmp  _suspend_isr     ; (0C) Global Suspend
+    .db 0
+    ljmp  _usbreset_isr    ; (10) USB Reset
+    .db 0
+    ljmp  _highspeed_isr   ; (14) Entered High Speed
+    .db 0
+    ljmp  _ep0ack_isr      ; (18) EP0ACK
+    .db 0
+    ljmp  _stub_isr        ; (1C) Reserved
+    .db 0
+    ljmp  _ep0in_isr       ; (20) EP0 In
+    .db 0
+    ljmp  _ep0out_isr      ; (24) EP0 Out
+    .db 0
+    ljmp  _ep1in_isr       ; (28) EP1 In
+    .db 0
+    ljmp  _ep1out_isr      ; (2C) EP1 Out
+    .db 0
+    ljmp  _ep2_isr         ; (30) EP2 In/Out
+    .db 0
+    ljmp  _ep4_isr         ; (34) EP4 In/Out
+    .db 0
+    ljmp  _ep6_isr         ; (38) EP6 In/Out
+    .db 0
+    ljmp  _ep8_isr         ; (3C) EP8 In/Out
+    .db 0
+    ljmp  _ibn_isr         ; (40) IBN
+    .db 0
+    ljmp  _stub_isr        ; (44) Reserved
+    .db 0
+    ljmp  _ep0pingnak_isr  ; (48) EP0 PING NAK
+    .db 0
+    ljmp  _ep1pingnak_isr  ; (4C) EP1 PING NAK
+    .db 0
+    ljmp  _ep2pingnak_isr  ; (50) EP2 PING NAK
+    .db 0
+    ljmp  _ep4pingnak_isr  ; (54) EP4 PING NAK
+    .db 0
+    ljmp  _ep6pingnak_isr  ; (58) EP6 PING NAK
+    .db 0
+    ljmp  _ep8pingnak_isr  ; (5C) EP8 PING NAK
+    .db 0
+    ljmp  _errorlimit_isr  ; (60) Error Limit
+    .db 0
+    ljmp  _stub_isr        ; (64) Reserved
+    .db 0
+    ljmp  _stub_isr        ; (68) Reserved
+    .db 0
+    ljmp  _stub_isr        ; (6C) Reserved
+    .db 0
+    ljmp  _ep2piderror_isr ; (70) EP2 ISO Pid Sequence Error
+    .db 0
+    ljmp  _ep4piderror_isr ; (74) EP4 ISO Pid Sequence Error
+    .db 0
+    ljmp  _ep6piderror_isr ; (78) EP6 ISO Pid Sequence Error
+    .db 0
+    ljmp  _ep8piderror_isr ; (7C) EP8 ISO Pid Sequence Error
+    .db 0
+    ljmp  _ep2pflag_isr    ; (80) EP2 Programmable Flag
+    .db 0
+    ljmp  _ep4pflag_isr    ; (84) EP4 Programmable Flag
+    .db 0
+    ljmp  _ep6pflag_isr    ; (88) EP6 Programmable Flag
+    .db 0
+    ljmp  _ep8pflag_isr    ; (8C) EP8 Programmable Flag
+    .db 0
+    ljmp  _ep2eflag_isr    ; (90) EP2 Empty Flag
+    .db 0
+    ljmp  _ep4eflag_isr    ; (94) EP4 Empty Flag
+    .db 0
+    ljmp  _ep6eflag_isr    ; (98) EP6 Empty Flag
+    .db 0
+    ljmp  _ep8eflag_isr    ; (9C) EP8 Empty Flag
+    .db 0
+    ljmp  _ep2fflag_isr    ; (A0) EP2 Full Flag
+    .db 0
+    ljmp  _ep4fflag_isr    ; (A4) EP4 Full Flag
+    .db 0
+    ljmp  _ep6fflag_isr    ; (A8) EP6 Full Flag
+    .db 0
+    ljmp  _ep8fflag_isr    ; (AC) EP8 Full Flag
+    .db 0
+    ljmp  _gpifcomplete_isr    ; (B0) GPIF Operation Complete
+    .db 0
+    ljmp  _gpifwaveform_isr    ; (B4) GPIF Waveform
+    .db 0
diff --git a/contrib/firmware/angie/c/src/delay.c b/contrib/firmware/angie/c/src/delay.c
new file mode 100644 (file)
index 0000000..471e160
--- /dev/null
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/****************************************************************************
+       File : delay.c                                                                                                                  *
+       Contents : Delays handling fucntions code for NanoXplore                                *
+       USB-JTAG ANGIE adapter hardware.                                                                                *
+       Based on openULINK project code by: Martin Schmoelzer.                                  *
+       Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.                              *
+       <aboudjelida@nanoxplore.com>                                                                                    *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#include "delay.h"
+#include <mcs51/compiler.h>
+
+void syncdelay(uint8_t count)
+{
+       for (uint8_t i = 0; i < count; i++)
+               NOP();
+}
+
+void delay_5us(void)
+{
+       NOP();
+}
+
+void delay_1ms(void)
+{
+       uint16_t i;
+
+       for (i = 0; i < 598; i++)
+               ;
+}
+
+void delay_us(uint16_t delay)
+{
+       uint16_t i;
+       uint16_t maxcount = (delay / 5);
+
+       for (i = 0; i < maxcount; i++)
+               delay_5us();
+}
+
+void delay_ms(uint16_t delay)
+{
+       uint16_t i;
+
+       for (i = 0; i < delay; i++)
+               delay_1ms();
+}
diff --git a/contrib/firmware/angie/c/src/gpif.c b/contrib/firmware/angie/c/src/gpif.c
new file mode 100644 (file)
index 0000000..80a9571
--- /dev/null
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/*
+  This program configures the General Programmable Interface (GPIF) for FX2.
+  Please do not modify sections of text which are marked as "DO NOT EDIT ...".
+*/
+
+/* GPIF Program Code */
+
+#include "reg_ezusb.h"
+#include "delay.h"
+
+/****************************** GPIF PROGRAM CODE ********************************/
+/* DO NOT EDIT ... */
+const char wavedata[128] = {
+/* Wave 0 */
+/* LenBr */ 0x01,     0x3F,     0x01,     0x01,     0x01,     0x01,     0x01,     0x07,
+/* Opcode*/ 0x02,     0x07,     0x02,     0x02,     0x02,     0x02,     0x02,     0x00,
+/* Output*/ 0x04,     0x07,     0x07,     0x07,     0x07,     0x07,     0x07,     0x07,
+/* LFun  */ 0x00,     0x09,     0x00,     0x00,     0x00,     0x00,     0x00,     0x3F,
+/* Wave 1 */
+/* LenBr */ 0x88,     0x01,     0x3F,     0x01,     0x01,     0x01,     0x01,     0x07,
+/* Opcode*/ 0x01,     0x02,     0x05,     0x00,     0x00,     0x00,     0x00,     0x00,
+/* Output*/ 0x07,     0x05,     0x07,     0x07,     0x07,     0x07,     0x07,     0x07,
+/* LFun  */ 0x09,     0x00,     0x09,     0x00,     0x00,     0x00,     0x00,     0x3F,
+/* Wave 2 */
+/* LenBr */ 0x01,     0x01,     0x01,     0x01,     0x01,     0x01,     0x01,     0x07,
+/* Opcode*/ 0x00,     0x00,     0x00,     0x00,     0x00,     0x00,     0x00,     0x00,
+/* Output*/ 0x07,     0x07,     0x07,     0x07,     0x07,     0x07,     0x07,     0x07,
+/* LFun  */ 0x00,     0x00,     0x00,     0x00,     0x00,     0x00,     0x00,     0x3F,
+/* Wave 3 */
+/* LenBr */ 0x01,     0x01,     0x01,     0x01,     0x01,     0x01,     0x01,     0x07,
+/* Opcode*/ 0x00,     0x00,     0x00,     0x00,     0x00,     0x00,     0x00,     0x00,
+/* Output*/ 0x07,     0x07,     0x07,     0x07,     0x07,     0x07,     0x07,     0x07,
+/* LFun  */ 0x00,     0x00,     0x00,     0x00,     0x00,     0x00,     0x00,     0x3F,
+};
+/* END DO NOT EDIT */
+
+/* DO NOT EDIT ... */
+const char flowstates[36] = {
+/* Wave 0 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Wave 1 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Wave 2 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Wave 3 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+/* END DO NOT EDIT */
+
+/* DO NOT EDIT ... */
+const char initdata[7] = {
+/* Regs  */ 0xE0, 0x00, 0x00, 0x07, 0xEE, 0xF2, 0x00
+};
+/* END DO NOT EDIT */
+
+void gpif_init(void)
+{
+       uint8_t i;
+
+       IFCONFIG = 0xEE;
+
+       GPIFABORT = 0xFF;       /* abort any waveforms pending */
+       GPIFREADYCFG = initdata[0];
+       GPIFCTLCFG = initdata[1];
+       GPIFIDLECS = initdata[2];
+       GPIFIDLECTL = initdata[3];
+       GPIFWFSELECT = initdata[5];
+       GPIFREADYSTAT = initdata[6];
+
+       /* use dual autopointer feature... */
+       AUTOPTRSETUP = 0x07;
+
+       /* source */
+       AUTOPTRH1 = (uint8_t)(((uint16_t)(&wavedata) >> 8) & 0xff);
+       AUTOPTRL1 = (uint8_t)((uint16_t)(&wavedata) & 0xff);
+
+       /* destination */
+       AUTOPTRH2 = 0xE4;
+       AUTOPTRL2 = 0x00;
+
+       /* transfer */
+       for (i = 0x00; i < 128; i++)
+               EXTAUTODAT2 = EXTAUTODAT1;
+
+       /* GPIF address pins update when GPIFADRH/L written */
+       syncdelay(3);
+       GPIFADRH = 0x00;    /* bits[7:1] always 0 */
+       syncdelay(3);
+       GPIFADRL = 0x00;    /* point to PERIPHERAL address 0x0000 */
+
+       /* Configure GPIF flowstates registers for Wave 0 of wavedata */
+       FLOWSTATE = flowstates[0];
+       FLOWLOGIC = flowstates[1];
+       FLOWEQ0CTL = flowstates[2];
+       FLOWEQ1CTL = flowstates[3];
+       FLOWHOLDOFF = flowstates[4];
+       FLOWSTB = flowstates[5];
+       FLOWSTBEDGE = flowstates[6];
+       FLOWSTBHPERIOD = flowstates[7];
+}
diff --git a/contrib/firmware/angie/c/src/jtag.c b/contrib/firmware/angie/c/src/jtag.c
new file mode 100644 (file)
index 0000000..9a44cd0
--- /dev/null
@@ -0,0 +1,674 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/****************************************************************************
+       File : jtag.c                                                                                                                   *
+       Contents : Jtag handling functions code for NanoXplore                                  *
+       USB-JTAG ANGIE adapter hardware.                                                                                *
+       Based on openULINK project code by: Martin Schmoelzer.                                  *
+       Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.                              *
+       <aboudjelida@nanoxplore.com>                                                                                    *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#include "jtag.h"
+#include "io.h"
+#include "msgtypes.h"
+#include "reg_ezusb.h"
+#include <stdbool.h>
+#include <serial.h>
+#include <stdio.h>
+
+/** Delay value for SCAN_IN operations with less than maximum TCK frequency */
+uint8_t delay_scan_in;
+
+/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
+uint8_t delay_scan_out;
+
+/** Delay value for SCAN_IO operations with less than maximum TCK frequency */
+uint8_t delay_scan_io;
+
+/** Delay value for CLOCK_TCK operations with less than maximum frequency */
+uint8_t delay_tck;
+
+/** Delay value for CLOCK_TMS operations with less than maximum frequency */
+uint8_t delay_tms;
+
+/**
+ * Perform JTAG SCAN-IN operation at maximum TCK frequency.
+ *
+ * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
+ * stored in the EP2 IN buffer.
+ *
+ * Maximum achievable TCK frequency is 182 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param out_offset offset in EP1OUTBUF where payload data starts
+ * @param in_offset
+ */
+void jtag_scan_in(uint8_t out_offset, uint8_t in_offset)
+{
+       uint8_t scan_size_bytes, bits_last_byte;
+       uint8_t tms_count_start, tms_count_end;
+       uint8_t tms_sequence_start, tms_sequence_end;
+       uint8_t tdo_data, i, j;
+
+       uint8_t outb_buffer;
+
+       /* Get parameters from EP1OUTBUF */
+       scan_size_bytes = EP1OUTBUF[out_offset];
+       bits_last_byte = EP1OUTBUF[out_offset + 1];
+       tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
+       tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
+       tms_sequence_start = EP1OUTBUF[out_offset + 3];
+       tms_sequence_end = EP1OUTBUF[out_offset + 4];
+
+       if (tms_count_start > 0)
+               jtag_clock_tms(tms_count_start, tms_sequence_start);
+
+       outb_buffer = IOB & ~(bmbit1 | bmbit2 | bmbit3);
+
+       /* Shift all bytes except the last byte */
+       for (i = 0; i < scan_size_bytes - 1; i++) {
+               tdo_data = 0;
+
+               for (j = 0; j < 8; j++) {
+                       IOB = outb_buffer;      /* TCK changes here */
+                       tdo_data = tdo_data >> 1;
+                       IOB = (outb_buffer | bmbit2);
+
+                       if (PIN_TDO)
+                               tdo_data |= 0x80;
+               }
+
+               /* Copy TDO data to EP1INBUF */
+               EP1INBUF[i + in_offset] = tdo_data;
+       }
+       tdo_data = 0;
+
+       /* Shift the last byte */
+       for (j = 0; j < bits_last_byte; j++) {
+               /* Assert TMS signal if requested and this is the last bit */
+               if (j == (bits_last_byte - 1) && tms_count_end > 0) {
+                       outb_buffer |= bmbit1;
+                       tms_count_end--;
+                       tms_sequence_end = tms_sequence_end >> 1;
+               }
+
+               IOB = outb_buffer;      /* TCK changes here */
+               tdo_data = tdo_data >> 1;
+               IOB = (outb_buffer | bmbit2);
+
+               if (PIN_TDO)
+                       tdo_data |= 0x80;
+       }
+       tdo_data = tdo_data >> (8 - bits_last_byte);
+
+       /* Copy TDO data to EP1INBUF */
+       EP1INBUF[i + in_offset] = tdo_data;
+
+       /* Move to correct end state */
+       if (tms_count_end > 0)
+               jtag_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+
+/**
+ * Perform JTAG SCAN-IN operation at variable TCK frequency.
+ *
+ * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
+ * stored in the EP2 IN buffer.
+ *
+ * Maximum achievable TCK frequency is 113 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param out_offset offset in EP1OUTBUF where payload data starts
+ * @param in_offset
+ */
+void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset)
+{
+       uint8_t scan_size_bytes, bits_last_byte;
+       uint8_t tms_count_start, tms_count_end;
+       uint8_t tms_sequence_start, tms_sequence_end;
+       uint8_t tdo_data, i, j, k;
+       uint8_t outb_buffer;
+
+       /* Get parameters from EP1OUTBUF */
+       scan_size_bytes = EP1OUTBUF[out_offset];
+       bits_last_byte = EP1OUTBUF[out_offset + 1];
+       tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
+       tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
+       tms_sequence_start = EP1OUTBUF[out_offset + 3];
+       tms_sequence_end = EP1OUTBUF[out_offset + 4];
+
+       if (tms_count_start > 0)
+               jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+
+       outb_buffer = IOB & ~(bmbit3 | bmbit2 | bmbit1);
+
+       /* Shift all bytes except the last byte */
+       for (i = 0; i < scan_size_bytes - 1; i++) {
+               tdo_data = 0;
+
+               for (j = 0; j < 8; j++) {
+                       IOB = outb_buffer;      /* TCK changes here */
+                       for (k = 0; k < delay_scan_in; k++)
+                               ;
+                       tdo_data = tdo_data >> 1;
+
+                       IOB = (outb_buffer | bmbit2);
+                       for (k = 0; k < delay_scan_in; k++)
+                               ;
+
+                       if (PIN_TDO)
+                               tdo_data |= 0x80;
+               }
+
+               /* Copy TDO data to EP1INBUF */
+               EP1INBUF[i + in_offset] = tdo_data;
+       }
+
+       tdo_data = 0;
+
+       /* Shift the last byte */
+       for (j = 0; j < bits_last_byte; j++) {
+               /* Assert TMS signal if requested and this is the last bit */
+               if (j == (bits_last_byte - 1) && tms_count_end > 0) {
+                       outb_buffer |= bmbit1;
+                       tms_count_end--;
+                       tms_sequence_end = tms_sequence_end >> 1;
+               }
+
+               IOB = outb_buffer;      /* TCK changes here */
+               for (k = 0; k < delay_scan_in; k++)
+                       ;
+               tdo_data = tdo_data >> 1;
+
+               IOB = (outb_buffer | bmbit2);
+               for (k = 0; k < delay_scan_in; k++)
+                       ;
+
+               if (PIN_TDO)
+                       tdo_data |= 0x80;
+       }
+       tdo_data = tdo_data >> (8 - bits_last_byte);
+
+       /* Copy TDO data to EP1INBUF */
+       EP1INBUF[i + in_offset] = tdo_data;
+
+       /* Move to correct end state */
+       if (tms_count_end > 0)
+               jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+
+/**
+ * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is not sampled.
+ * The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 142 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param out_offset offset in EP1OUTBUF where payload data starts
+ */
+void jtag_scan_out(uint8_t out_offset)
+{
+       uint8_t scan_size_bytes, bits_last_byte;
+       uint8_t tms_count_start, tms_count_end;
+       uint8_t tms_sequence_start, tms_sequence_end;
+       uint8_t tdi_data, i, j;
+       uint8_t outb_buffer;
+
+       /* Get parameters from EP1OUTBUF */
+       scan_size_bytes = EP1OUTBUF[out_offset];
+       bits_last_byte = EP1OUTBUF[out_offset + 1];
+       tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
+       tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
+       tms_sequence_start = EP1OUTBUF[out_offset + 3];
+       tms_sequence_end = EP1OUTBUF[out_offset + 4];
+
+       if (tms_count_start > 0)
+               jtag_clock_tms(tms_count_start, tms_sequence_start);
+       outb_buffer = IOB & ~(bmbit2 | bmbit1);
+
+       /* Shift all bytes except the last byte */
+       for (i = 0; i < scan_size_bytes - 1; i++) {
+               tdi_data = EP1OUTBUF[i + out_offset + 5];
+
+               for (j = 0; j < 8; j++) {
+                       if (tdi_data & 0x01)
+                               outb_buffer |= bmbit3;
+                       else
+                               outb_buffer &= ~bmbit3;
+
+                       IOB = outb_buffer;      /* TDI and TCK change here */
+                       tdi_data = tdi_data >> 1;
+                       IOB = (outb_buffer | bmbit2);
+               }
+       }
+       tdi_data = EP1OUTBUF[i + out_offset + 5];
+
+       /* Shift the last byte */
+       for (j = 0; j < bits_last_byte; j++) {
+               if (tdi_data & 0x01)
+                       outb_buffer |= bmbit3;
+               else
+                       outb_buffer &= ~bmbit3;
+
+               /* Assert TMS signal if requested and this is the last bit */
+               if (j == (bits_last_byte - 1) && tms_count_end > 0) {
+                       outb_buffer |= bmbit1;
+                       tms_count_end--;
+                       tms_sequence_end = tms_sequence_end >> 1;
+               }
+               IOB = outb_buffer;      /* TDI and TCK change here */
+               tdi_data = tdi_data >> 1;
+               IOB = (outb_buffer | bmbit2);
+       }
+
+       /* Move to correct end state */
+       if (tms_count_end > 0)
+               jtag_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is not sampled.
+ * The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 97 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param out_offset offset in EP1OUTBUF where payload data starts
+ */
+void jtag_slow_scan_out(uint8_t out_offset)
+{
+       uint8_t scan_size_bytes, bits_last_byte;
+       uint8_t tms_count_start, tms_count_end;
+       uint8_t tms_sequence_start, tms_sequence_end;
+       uint8_t tdi_data, i, j, k;
+       uint8_t outb_buffer;
+
+       /* Get parameters from EP1OUTBUF */
+       scan_size_bytes = EP1OUTBUF[out_offset];
+       bits_last_byte = EP1OUTBUF[out_offset + 1];
+       tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
+       tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
+       tms_sequence_start = EP1OUTBUF[out_offset + 3];
+       tms_sequence_end = EP1OUTBUF[out_offset + 4];
+
+       if (tms_count_start > 0)
+               jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+       outb_buffer = IOB & ~(bmbit2 | bmbit1);
+
+       /* Shift all bytes except the last byte */
+       for (i = 0; i < scan_size_bytes - 1; i++) {
+               tdi_data = EP1OUTBUF[i + out_offset + 5];
+
+               for (j = 0; j < 8; j++) {
+                       if (tdi_data & 0x01)
+                               outb_buffer |= bmbit3;
+                       else
+                               outb_buffer &= ~bmbit3;
+                       IOB = outb_buffer;      /* TDI and TCK change here */
+                       for (k = 0; k < delay_scan_out; k++)
+                               ;
+                       tdi_data = tdi_data >> 1;
+                       IOB = (outb_buffer | bmbit2);
+                       for (k = 0; k < delay_scan_out; k++)
+                               ;
+               }
+       }
+       tdi_data = EP1OUTBUF[i + out_offset + 5];
+
+       /* Shift the last byte */
+       for (j = 0; j < bits_last_byte; j++) {
+               if (tdi_data & 0x01)
+                       outb_buffer |= bmbit3;
+               else
+                       outb_buffer &= ~bmbit3;
+
+               /* Assert TMS signal if requested and this is the last bit */
+               if (j == (bits_last_byte - 1) && tms_count_end > 0) {
+                       outb_buffer |= bmbit1;
+                       tms_count_end--;
+                       tms_sequence_end = tms_sequence_end >> 1;
+               }
+               IOB = outb_buffer;      /* TDI and TCK change here */
+               for (k = 0; k < delay_scan_out; k++)
+                       ;
+               tdi_data = tdi_data >> 1;
+               IOB = (outb_buffer | bmbit2);
+               for (k = 0; k < delay_scan_out; k++)
+                       ;
+       }
+
+       /* Move to correct end state */
+       if (tms_count_end > 0)
+               jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+
+/**
+ * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is sampled and stored in the EP2 IN buffer.
+ * The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 100 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param out_offset offset in EP1OUTBUF where payload data starts
+ * @param in_offset
+ */
+int it;
+void jtag_scan_io(uint8_t out_offset, uint8_t in_offset)
+{
+       uint8_t scan_size_bytes, bits_last_byte;
+       uint8_t tms_count_start, tms_count_end;
+       uint8_t tms_sequence_start, tms_sequence_end;
+       uint8_t tdi_data, tdo_data, i, j;
+       uint8_t outb_buffer;
+
+       it++;
+       /* Get parameters from EP1OUTBUF */
+       scan_size_bytes = EP1OUTBUF[out_offset];
+       bits_last_byte = EP1OUTBUF[out_offset + 1];
+       tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
+       tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
+       tms_sequence_start = EP1OUTBUF[out_offset + 3];
+       tms_sequence_end = EP1OUTBUF[out_offset + 4];
+
+       if (tms_count_start > 0)
+               jtag_clock_tms(tms_count_start, tms_sequence_start);
+       outb_buffer = IOB & ~(bmbit2 | bmbit1);
+
+       /* Shift all bytes except the last byte */
+       for (i = 0; i < scan_size_bytes - 1; i++) {
+               tdi_data = EP1OUTBUF[i + out_offset + 5];
+               tdo_data = 0;
+               for (j = 0; j < 8; j++) {
+                       if (tdi_data & 0x01)
+                               outb_buffer |= bmbit3;
+                       else
+                               outb_buffer &= ~bmbit3;
+                       IOB = outb_buffer;      /* TDI and TCK change here */
+                       tdi_data = tdi_data >> 1;
+                       IOB = (outb_buffer | bmbit2);
+                       tdo_data = tdo_data >> 1;
+                       if (PIN_TDO)
+                               tdo_data |= 0x80;
+               }
+
+               /* Copy TDO data to EP1INBUF */
+               EP1INBUF[i + in_offset] = tdo_data;
+       }
+       tdi_data = EP1OUTBUF[i + out_offset + 5];
+       tdo_data = 0;
+
+       /* Shift the last byte */
+       for (j = 0; j < bits_last_byte; j++) {
+               if (tdi_data & 0x01)
+                       outb_buffer |= bmbit3;
+               else
+                       outb_buffer &= ~bmbit3;
+
+               /* Assert TMS signal if requested and this is the last bit */
+               if (j == (bits_last_byte - 1) && tms_count_end > 0) {
+                       outb_buffer |= bmbit1;
+                       tms_count_end--;
+                       tms_sequence_end = tms_sequence_end >> 1;
+               }
+               IOB = outb_buffer;      /* TDI and TCK change here */
+               tdi_data = tdi_data >> 1;
+               IOB = (outb_buffer | bmbit2);
+               tdo_data = tdo_data >> 1;
+               if (PIN_TDO)
+                       tdo_data |= 0x80;
+       }
+       tdo_data = tdo_data >> (8 - bits_last_byte);
+
+       /* Copy TDO data to EP1INBUF */
+       EP1INBUF[i + in_offset] = tdo_data;
+
+       /* Move to correct end state */
+       if (tms_count_end > 0)
+               jtag_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is sampled and stored in the EP2 IN buffer.
+ * The TAP-FSM state is always left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * Maximum achievable TCK frequency is 78 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param out_offset offset in EP1OUTBUF where payload data starts
+ * @param in_offset
+ */
+void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset)
+{
+       uint8_t scan_size_bytes, bits_last_byte;
+       uint8_t tms_count_start, tms_count_end;
+       uint8_t tms_sequence_start, tms_sequence_end;
+       uint8_t tdi_data, tdo_data, i, j, k;
+       uint8_t outb_buffer;
+
+       /* Get parameters from EP1OUTBUF */
+       scan_size_bytes = EP1OUTBUF[out_offset];
+       bits_last_byte = EP1OUTBUF[out_offset + 1];
+       tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
+       tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
+       tms_sequence_start = EP1OUTBUF[out_offset + 3];
+       tms_sequence_end = EP1OUTBUF[out_offset + 4];
+
+       if (tms_count_start > 0)
+               jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
+       outb_buffer = IOB & ~(bmbit2 | bmbit1);
+
+       /* Shift all bytes except the last byte */
+       for (i = 0; i < scan_size_bytes - 1; i++) {
+               tdi_data = EP1OUTBUF[i + out_offset + 5];
+               tdo_data = 0;
+               for (j = 0; j < 8; j++) {
+                       if (tdi_data & 0x01)
+                               outb_buffer |= bmbit3;
+                       else
+                               outb_buffer &= ~bmbit3;
+                       IOB = outb_buffer;      /* TDI and TCK change here */
+                       for (k = 0; k < delay_scan_io; k++)
+                               ;
+                       tdi_data = tdi_data >> 1;
+                       IOB = (outb_buffer | bmbit2);
+                       for (k = 0; k < delay_scan_io; k++)
+                               ;
+                       tdo_data = tdo_data >> 1;
+                       if (PIN_TDO)
+                               tdo_data |= 0x80;
+               }
+
+               /* Copy TDO data to EP1INBUF */
+               EP1INBUF[i + in_offset] = tdo_data;
+       }
+       tdi_data = EP1OUTBUF[i + out_offset + 5];
+       tdo_data = 0;
+
+       /* Shift the last byte */
+       for (j = 0; j < bits_last_byte; j++) {
+               if (tdi_data & 0x01)
+                       outb_buffer |= bmbit3;
+               else
+                       outb_buffer &= ~bmbit3;
+
+               /* Assert TMS signal if requested and this is the last bit */
+               if (j == (bits_last_byte - 1) && tms_count_end > 0) {
+                       outb_buffer |= bmbit1;
+                       tms_count_end--;
+                       tms_sequence_end = tms_sequence_end >> 1;
+               }
+               IOB = outb_buffer;      /* TDI and TCK change here */
+               for (k = 0; k < delay_scan_io; k++)
+                       ;
+               tdi_data = tdi_data >> 1;
+               IOB = (outb_buffer | bmbit2);
+               for (k = 0; k < delay_scan_io; k++)
+                       ;
+               tdo_data = tdo_data >> 1;
+               if (PIN_TDO)
+                       tdo_data |= 0x80;
+       }
+       tdo_data = tdo_data >> (8 - bits_last_byte);
+
+       /* Copy TDO data to EP1INBUF */
+       EP1INBUF[i + in_offset] = tdo_data;
+
+       /* Move to correct end state */
+       if (tms_count_end > 0)
+               jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
+}
+
+/**
+ * Generate TCK clock cycles.
+ *
+ * Maximum achievable TCK frequency is 375 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param count number of TCK clock cycles to generate.
+ */
+void jtag_clock_tck(uint16_t count)
+{
+       uint16_t i;
+       uint8_t outb_buffer = IOB & ~(bmbit2);
+
+       for (i = 0; i < count; i++) {
+               IOB = outb_buffer;
+               IOB = outb_buffer | bmbit2;
+       }
+}
+
+/**
+ * Generate TCK clock cycles at variable frequency.
+ *
+ * Maximum achievable TCK frequency is 166.6 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param count number of TCK clock cycles to generate.
+ */
+void jtag_slow_clock_tck(uint16_t count)
+{
+       uint16_t i;
+       uint8_t j;
+       uint8_t outb_buffer = IOB & ~(bmbit2);
+
+       for (i = 0; i < count; i++) {
+               IOB = outb_buffer;
+               for (j = 0; j < delay_tck; j++)
+                       ;
+               IOB = outb_buffer | bmbit2;
+               for (j = 0; j < delay_tck; j++)
+                       ;
+       }
+}
+
+/**
+ * Perform TAP FSM state transitions at maximum TCK frequency.
+ *
+ * Maximum achievable TCK frequency is 176 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param count the number of state transitions to perform.
+ * @param sequence the TMS pin levels for each state transition, starting with
+ *  the least-significant bit.
+ */
+void jtag_clock_tms(uint8_t count, uint8_t sequence)
+{
+       uint8_t outb_buffer = IOB & ~(bmbit2);
+       uint8_t i;
+
+       for (i = 0; i < count; i++) {
+               /* Set TMS pin according to sequence parameter */
+               if (sequence & 0x1)
+                       outb_buffer |= bmbit1;
+               else
+                       outb_buffer &= ~bmbit1;
+               IOB = outb_buffer;
+               sequence = sequence >> 1;
+               IOB = outb_buffer | bmbit2;
+       }
+}
+
+/**
+ * Perform TAP-FSM state transitions at less than maximum TCK frequency.
+ *
+ * Maximum achievable TCK frequency is 117 kHz for ANGIE clocked at 24 MHz.
+ *
+ * @param count the number of state transitions to perform.
+ * @param sequence the TMS pin levels for each state transition, starting with
+ *  the least-significant bit.
+ */
+void jtag_slow_clock_tms(uint8_t count, uint8_t sequence)
+{
+       uint8_t outb_buffer = IOB & ~(bmbit2);
+       uint8_t i, j;
+
+       for (i = 0; i < count; i++) {
+               /* Set TMS pin according to sequence parameter */
+               if (sequence & 0x1)
+                       outb_buffer |= bmbit1;
+               else
+                       outb_buffer &= ~bmbit1;
+               IOB = outb_buffer;
+               for (j = 0; j < delay_tms; j++)
+                       ;
+               sequence = sequence >> 1;
+               IOB = outb_buffer | bmbit2;
+               for (j = 0; j < delay_tms; j++)
+                       ;
+       }
+}
+
+uint16_t jtag_get_signals(void)
+{
+       uint8_t input_signal_state, output_signal_state;
+       input_signal_state = 0;
+       output_signal_state = 0;
+
+       /* Get states of input pins */
+       if (PIN_TDO)
+               input_signal_state |= SIGNAL_TDO;
+
+       /* Get states of output pins */
+       output_signal_state = IOB & MASK_PORTB_DIRECTION_OUT;
+
+       return ((uint16_t)input_signal_state << 8) | ((uint16_t)output_signal_state);
+}
+
+/**
+ * Set state of JTAG output signals.
+ *
+ * @param low signals which should be de-asserted.
+ * @param high signals which should be asserted.
+ */
+void jtag_set_signals(uint8_t low, uint8_t high)
+{
+       IOB &= ~(low & MASK_PORTB_DIRECTION_OUT);
+       IOB |= (high & MASK_PORTB_DIRECTION_OUT);
+}
+
+/**
+ * Configure TCK delay parameters.
+ *
+ * @param scan_in number of delay cycles in scan_in operations.
+ * @param scan_out number of delay cycles in scan_out operations.
+ * @param scan_io number of delay cycles in scan_io operations.
+ * @param tck number of delay cycles in clock_tck operations.
+ * @param tms number of delay cycles in clock_tms operations.
+ */
+void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
+       uint8_t scan_io, uint8_t tck, uint8_t tms)
+{
+       delay_scan_in = scan_in;
+       delay_scan_out = scan_out;
+       delay_scan_io = scan_io;
+       delay_tck = tck;
+       delay_tms = tms;
+}
diff --git a/contrib/firmware/angie/c/src/main.c b/contrib/firmware/angie/c/src/main.c
new file mode 100644 (file)
index 0000000..9290af2
--- /dev/null
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/****************************************************************************
+       File : main.c                                                                                                                   *
+       Contents : main code for NanoXplore USB-JTAG ANGIE adapter                              *
+       hardware.                                                                                                                               *
+       Based on openULINK project code by: Martin Schmoelzer.                                  *
+       Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.                              *
+       <aboudjelida@nanoxplore.com>                                                                                    *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#include "usb.h"
+#include "delay.h"
+#include "protocol.h"
+#include "reg_ezusb.h"
+#include <serial.h>
+#include <stdio.h>
+
+extern void sudav_isr(void)__interrupt SUDAV_ISR;
+extern void sof_isr(void)__interrupt;
+extern void sutok_isr(void)__interrupt;
+extern void suspend_isr(void)__interrupt;
+extern void usbreset_isr(void)__interrupt;
+extern void highspeed_isr(void)__interrupt;
+extern void ep0ack_isr(void)__interrupt;
+extern void stub_isr(void)__interrupt;
+extern void ep0in_isr(void)__interrupt;
+extern void ep0out_isr(void)__interrupt;
+extern void ep1in_isr(void)__interrupt;
+extern void ep1out_isr(void)__interrupt;
+extern void ep2_isr(void)__interrupt;
+extern void ep4_isr(void)__interrupt;
+extern void ep6_isr(void)__interrupt;
+extern void ep8_isr(void)__interrupt;
+extern void ibn_isr(void)__interrupt;
+extern void ep0pingnak_isr(void)__interrupt;
+extern void ep1pingnak_isr(void)__interrupt;
+extern void ep2pingnak_isr(void)__interrupt;
+extern void ep4pingnak_isr(void)__interrupt;
+extern void ep6pingnak_isr(void)__interrupt;
+extern void ep8pingnak_isr(void)__interrupt;
+extern void errorlimit_isr(void)__interrupt;
+extern void ep2piderror_isr(void)__interrupt;
+extern void ep4piderror_isr(void)__interrupt;
+extern void ep6piderror_isr(void)__interrupt;
+extern void ep8piderror_isr(void)__interrupt;
+extern void ep2pflag_isr(void)__interrupt;
+extern void ep4pflag_isr(void)__interrupt;
+extern void ep6pflag_isr(void)__interrupt;
+extern void ep8pflag_isr(void)__interrupt;
+extern void ep2eflag_isr(void)__interrupt;
+extern void ep4eflag_isr(void)__interrupt;
+extern void ep6eflag_isr(void)__interrupt;
+extern void ep8eflag_isr(void)__interrupt;
+extern void ep2fflag_isr(void)__interrupt;
+extern void ep4fflag_isr(void)__interrupt;
+extern void ep6fflag_isr(void)__interrupt;
+extern void ep8fflag_isr(void)__interrupt;
+extern void gpifcomplete_isr(void)__interrupt;
+extern void gpifwaveform_isr(void)__interrupt;
+
+void gpif_init(void);
+
+int main(void)
+{
+       CPUCS = ((CPUCS & ~bmclkspd) | (CLK_48M << 3) | CLKOE); /* required for sio0_init */
+       sio0_init(57600);       /* needed for printf */
+
+       ep_init();
+       gpif_init();
+       interrupt_init();
+       io_init();
+
+       /* Perform ReNumeration */
+       USBCS |= (DISCON | RENUM);
+       delay_ms(250);
+       USBCS &= ~DISCON;
+
+       /* Begin executing command(s). This function never returns. */
+       command_loop();
+
+       /* Never reached, but SDCC complains about missing return statement */
+       return 0;
+}
diff --git a/contrib/firmware/angie/c/src/protocol.c b/contrib/firmware/angie/c/src/protocol.c
new file mode 100644 (file)
index 0000000..3f3aaaf
--- /dev/null
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/****************************************************************************
+       File : protocol.c                                                                                                               *
+       Contents : Jtag commands handling protocol code for NanoXplore                  *
+       USB-JTAG ANGIE adapter hardware.                                                                                *
+       Based on openULINK project code by: Martin Schmoelzer.                                  *
+       Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.                              *
+       <aboudjelida@nanoxplore.com>                                                                                    *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#include "usb.h"
+#include "protocol.h"
+#include "jtag.h"
+#include "delay.h"
+#include "io.h"
+#include "msgtypes.h"
+#include "reg_ezusb.h"
+#include <serial.h>
+#include <stdio.h>
+
+/** Index in EP1 Bulk-OUT data buffer that contains the current command ID */
+volatile uint8_t cmd_id_index;
+
+/** Number of data bytes already in EP1 Bulk-IN buffer */
+volatile uint8_t payload_index_in;
+
+/**
+ * Executes one command and updates global command indexes.
+ *
+ * @return true if this command was the last command.
+ * @return false if there are more commands within the current contents of the
+ * Bulk EP1-OUT data buffer.
+ */
+bool execute_command(void)
+{
+       uint8_t usb_out_bytecount, usb_in_bytecount;
+       uint16_t signal_state = 0;
+       uint16_t count;
+
+       /* Most commands do not transfer IN data. To save code space, we write 0 to
+        * usb_in_bytecount here, then modify it in the switch statement below where
+        * necessary */
+       usb_in_bytecount = 0;
+
+       switch (EP1OUTBUF[cmd_id_index] /* Command ID */) {
+       case CMD_SCAN_IN:
+               usb_out_bytecount = 5;
+               usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
+               jtag_scan_in((cmd_id_index + 1), payload_index_in);
+               break;
+       case CMD_SCAN_OUT:
+               usb_out_bytecount = EP1OUTBUF[cmd_id_index + 1] + 5;
+               jtag_scan_out(cmd_id_index + 1);
+               break;
+       case CMD_SCAN_IO:
+               usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
+               usb_out_bytecount = usb_in_bytecount + 5;
+               jtag_scan_io((cmd_id_index + 1), payload_index_in);
+               break;
+       case CMD_CLOCK_TMS:
+               usb_out_bytecount = 2;
+               jtag_clock_tms(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
+               break;
+       case CMD_CLOCK_TCK:
+               usb_out_bytecount = 2;
+               count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
+               count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
+               jtag_clock_tck(count);
+               break;
+       case CMD_SLOW_SCAN_IN:
+               usb_out_bytecount = 5;
+               usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
+               jtag_slow_scan_in(cmd_id_index + 1, payload_index_in);
+               break;
+       case CMD_SLOW_SCAN_OUT:
+               usb_out_bytecount = EP1OUTBUF[cmd_id_index + 1] + 5;
+               jtag_slow_scan_out(cmd_id_index + 1);
+               break;
+       case CMD_SLOW_SCAN_IO:
+               usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
+               usb_out_bytecount = usb_in_bytecount + 5;
+               jtag_slow_scan_io(cmd_id_index + 1, payload_index_in);
+               break;
+       case CMD_SLOW_CLOCK_TMS:
+               usb_out_bytecount = 2;
+               jtag_slow_clock_tms(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
+               break;
+       case CMD_SLOW_CLOCK_TCK:
+               usb_out_bytecount = 2;
+               count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
+               count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
+               jtag_slow_clock_tck(count);
+               break;
+       case CMD_SLEEP_US:
+               usb_out_bytecount = 2;
+               count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
+               count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
+               delay_us(count);
+               break;
+       case CMD_SLEEP_MS:
+               usb_out_bytecount = 2;
+               count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
+               count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
+               delay_ms(count);
+               break;
+       case CMD_GET_SIGNALS:
+               usb_out_bytecount = 0;
+               usb_in_bytecount = 2;
+               signal_state = jtag_get_signals();
+               EP1INBUF[payload_index_in] = (signal_state >> 8);
+               EP1INBUF[payload_index_in + 1] = (signal_state & 0xFF);
+               break;
+       case CMD_SET_SIGNALS:
+               usb_out_bytecount = 2;
+               jtag_set_signals(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
+               break;
+       case CMD_CONFIGURE_TCK_FREQ:
+               usb_out_bytecount = 5;
+               jtag_configure_tck_delay(EP1OUTBUF[cmd_id_index + 1],   /* scan_in */
+               EP1OUTBUF[cmd_id_index + 2],    /* scan_out */
+               EP1OUTBUF[cmd_id_index + 3],    /* scan_io */
+               EP1OUTBUF[cmd_id_index + 4],    /* clock_tck */
+               EP1OUTBUF[cmd_id_index + 5]);   /* clock_tms */
+               break;
+       case CMD_TEST:
+               usb_out_bytecount = 1;
+               /* Do nothing... This command is only used to test if the device is ready
+                * to accept new commands */
+               break;
+       default:
+               /* Should never be reached */
+               usb_out_bytecount = 0;
+               break;
+       }
+
+       /* Update EP1 Bulk-IN data byte count */
+       payload_index_in += usb_in_bytecount;
+
+       /* Determine if this was the last command */
+       if ((cmd_id_index + usb_out_bytecount + 1) >= EP1OUTBC) {
+               return true;
+               /* Line between return and else required by checkpatch: */
+               uint8_t a = 0;
+       } else {
+               /* Not the last command, update cmd_id_index */
+               cmd_id_index += (usb_out_bytecount + 1);
+               return false;
+       }
+}
+
+/**
+ * Forever wait for commands and execute them as they arrive.
+ */
+void command_loop(void)
+{
+       bool last_command;
+       while (1) {
+               cmd_id_index = 0;
+               payload_index_in = 0;
+
+               /* Wait until host sends EP1 Bulk-OUT packet */
+               while (!ep1_out)
+                       ;
+               ep1_out = false;
+
+               /* Execute the commands */
+               last_command = false;
+               while (!last_command)
+                       last_command = execute_command();
+
+               /* Send back EP6 Bulk-IN packet if required */
+               if (payload_index_in > 0) {
+                       EP1INBC = payload_index_in;
+                       syncdelay(3);
+
+                       while (!ep1_in)
+                               ;
+                       ep1_in = false;
+               }
+
+               /* Re-arm EP1-OUT after command execution */
+               EP1OUTBC = 0;
+               syncdelay(3);
+               EP1OUTBC = 0;
+               syncdelay(3);
+       }
+}
diff --git a/contrib/firmware/angie/c/src/serial.c b/contrib/firmware/angie/c/src/serial.c
new file mode 100644 (file)
index 0000000..0398cb2
--- /dev/null
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+/*
+ * This code was taken from the fx2lib project from this link:
+ * https://github.com/djmuhlestein/fx2lib
+ *
+ * Copyright (C) 2009 Ubixum, Inc.
+*/
+
+#include <reg_ezusb.h>
+#include <fx2macros.h>
+#include <serial.h>
+#include <stdint.h>
+/**
+ * using the comp port implies that timer 2 will be used as
+ * a baud rate generator.  (Don't use timer 2)
+ **/
+void sio0_init(uint32_t baud_rate) __critical
+{
+       uint16_t hl;     /* hl value for reload */
+       uint8_t mult;   /* multiplier for clock speed */
+       uint32_t tmp;   /* scratch for mult/divide */
+
+       mult = (CPUFREQ == CLK_12M) ? 1 : ((CPUFREQ == CLK_24M) ? 2 : 4);
+
+       /* set the clock rate */
+       /* use clock 2 */
+       RCLK = 1; TCLK = 1;
+       tmp = mult * 375000L * 2;
+       tmp /= baud_rate;
+       tmp += 1;
+       tmp /= 2;
+       hl = 0xFFFF - (uint16_t)tmp;
+       RCAP2H = (uint8_t)(((uint16_t)(hl) >> 8) & 0xff);
+
+       /* seems that the 24/48mhz calculations are always one less than suggested values */
+  /* trm table 14-16 */
+       RCAP2L = ((uint8_t)((uint16_t)(hl) & 0xff)) + (mult > 0 ? 1 : 0);
+
+  /* start the timer */
+       TR2 = 1;
+
+       /* set up the serial port       */
+       SM0 = 0; SM1 = 1; /* serial mode 1 (asyncronous)        */
+       SM2 = 0 ;       /* has to do with receiving */
+       REN = 1 ;       /* to enable receiving */
+       PCON |= 0x80;    /* SET SMOD0, baud rate doubler */
+       TI = 1;         /* we send initial byte */
+}
+
+int getchar(void)
+{
+       char c;
+       while (!RI)
+               ;
+       c = SBUF0;
+       RI = 0;
+       return c;
+}
+
+void _transchar(char c)
+{
+       while (!TI)
+               ; /* wait for TI=1 */
+       TI = 0;
+       SBUF0 = c;
+}
+
+int putchar (char c)
+{
+       if (c == '\n')
+               _transchar('\r'); /* transmit \r\n */
+       _transchar(c);
+       if (c == '\r')
+               _transchar('\n'); /* transmit \r\n */
+       return c;
+}
diff --git a/contrib/firmware/angie/c/src/usb.c b/contrib/firmware/angie/c/src/usb.c
new file mode 100644 (file)
index 0000000..8fd4de6
--- /dev/null
@@ -0,0 +1,784 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/****************************************************************************
+       File : usb.c                                                                                                                    *
+       Contents : usb communication handling code for NanoXplore USB-JTAG              *
+       ANGIE adapter hardware.                                                                                                 *
+       Based on openULINK project code by: Martin Schmoelzer.                                  *
+       Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS.                              *
+       <aboudjelida@nanoxplore.com>                                                                                    *
+       <ahmederrachedbjld@gmail.com>                                                                                   *
+*****************************************************************************/
+
+#include "usb.h"
+#include "stdint.h"
+#include "delay.h"
+#include "io.h"
+#include "reg_ezusb.h"
+#include <fx2macros.h>
+#include <serial.h>
+#include <stdio.h>
+
+/* Also update external declarations in "include/usb.h" if making changes to
+ * these variables!
+ */
+volatile bool ep1_out;
+volatile bool ep1_in;
+
+volatile __xdata __at 0xE6B8 struct setup_data setup_data;
+
+/* Define number of endpoints (except Control Endpoint 0) in a central place.
+ * Be sure to include the necessary endpoint descriptors!
+ */
+#define NUM_ENDPOINTS 3
+
+__code struct usb_device_descriptor device_descriptor = {
+       .blength =              sizeof(struct usb_device_descriptor),
+       .bdescriptortype =      DESCRIPTOR_TYPE_DEVICE,
+       .bcdusb =                       0x0200,     /* BCD: 02.00 (Version 2.0 USB spec) */
+       .bdeviceclass =         0xFF,           /* 0xFF = vendor-specific */
+       .bdevicesubclass =      0xFF,
+       .bdeviceprotocol =      0xFF,
+       .bmaxpacketsize0 =      64,
+       .idvendor =                     0x584e,
+       .idproduct =            0x424e,
+       .bcddevice =            0x0000,
+       .imanufacturer =        1,
+       .iproduct =                     2,
+       .iserialnumber =        3,
+       .bnumconfigurations =   1
+};
+
+/* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
+
+__code struct usb_config_descriptor config_descriptor = {
+       .blength =              sizeof(struct usb_config_descriptor),
+       .bdescriptortype =      DESCRIPTOR_TYPE_CONFIGURATION,
+       .wtotallength =         sizeof(struct usb_config_descriptor) +
+               sizeof(struct usb_interface_descriptor) +
+               (NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)),
+       .bnuminterfaces =       1,
+       .bconfigurationvalue =  1,
+       .iconfiguration =       4,      /* String describing this configuration */
+       .bmattributes =         0x80,   /* Only MSB set according to USB spec */
+       .maxpower =             50      /* 100 mA */
+};
+
+__code struct usb_interface_descriptor interface_descriptor00 = {
+       .blength = sizeof(struct usb_interface_descriptor),
+       .bdescriptortype =      DESCRIPTOR_TYPE_INTERFACE,
+       .binterfacenumber =     0,
+       .balternatesetting =    0,
+       .bnumendpoints =        NUM_ENDPOINTS,
+       .binterfaceclass =      0xFF,
+       .binterfacesubclass =   0xFF,
+       .binterfaceprotocol =   0xFF,
+       .iinterface =           0
+};
+
+__code struct usb_endpoint_descriptor bulk_ep1_out_endpoint_descriptor = {
+       .blength =              sizeof(struct usb_endpoint_descriptor),
+       .bdescriptortype =      0x05,
+       .bendpointaddress =     (1 | USB_DIR_OUT),
+       .bmattributes =         0x02,
+       .wmaxpacketsize =       64,
+       .binterval =            0
+};
+
+__code struct usb_endpoint_descriptor bulk_ep1_in_endpoint_descriptor = {
+       .blength =              sizeof(struct usb_endpoint_descriptor),
+       .bdescriptortype =      0x05,
+       .bendpointaddress =     (1 | USB_DIR_IN),
+       .bmattributes =         0x02,
+       .wmaxpacketsize =       64,
+       .binterval =            0
+};
+
+__code struct usb_endpoint_descriptor bulk_ep2_endpoint_descriptor = {
+       .blength =              sizeof(struct usb_endpoint_descriptor),
+       .bdescriptortype =      0x05,
+       .bendpointaddress =     (2 | USB_DIR_OUT),
+       .bmattributes =         0x02,
+       .wmaxpacketsize =       512,
+       .binterval =            0
+};
+
+__code struct usb_endpoint_descriptor bulk_ep4_endpoint_descriptor = {
+       .blength =              sizeof(struct usb_endpoint_descriptor),
+       .bdescriptortype =      0x05,
+       .bendpointaddress =     (4 | USB_DIR_IN),
+       .bmattributes =         0x02,
+       .wmaxpacketsize =       512,
+       .binterval =            0
+};
+
+__code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = {
+       .blength =              sizeof(struct usb_endpoint_descriptor),
+       .bdescriptortype =      0x05,
+       .bendpointaddress =     (6 | USB_DIR_OUT),
+       .bmattributes =         0x02,
+       .wmaxpacketsize =       512,
+       .binterval =            0
+};
+
+__code struct usb_endpoint_descriptor bulk_ep8_endpoint_descriptor = {
+       .blength =              sizeof(struct usb_endpoint_descriptor),
+       .bdescriptortype =      0x05,
+       .bendpointaddress =     (8 | USB_DIR_OUT),
+       .bmattributes =         0x02,
+       .wmaxpacketsize =       512,
+       .binterval =            0
+};
+
+__code struct usb_language_descriptor language_descriptor = {
+       .blength =              4,
+       .bdescriptortype =      DESCRIPTOR_TYPE_STRING,
+       .wlangid =              {0x0409 /* US English */}
+};
+
+__code struct usb_string_descriptor strmanufacturer =
+       STR_DESCR(16, 'N', 'a', 'n', 'o', 'X', 'p', 'l', 'o', 'r', 'e', ',', ' ', 'S', 'A', 'S', '.');
+
+__code struct usb_string_descriptor strproduct =
+       STR_DESCR(13, 'A', 'N', 'G', 'I', 'E', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
+
+__code struct usb_string_descriptor strserialnumber =
+       STR_DESCR(6, '0', '0', '0', '0', '0', '1');
+
+__code struct usb_string_descriptor strconfigdescr  =
+       STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
+
+/* Table containing pointers to string descriptors */
+__code struct usb_string_descriptor *__code en_string_descriptors[4] = {
+       &strmanufacturer,
+       &strproduct,
+       &strserialnumber,
+       &strconfigdescr
+};
+void sudav_isr(void)__interrupt SUDAV_ISR
+{
+       EXIF &= ~0x10;  /* Clear USBINT: Main global interrupt */
+       USBIRQ = SUDAVI;
+       EP0CS |= HSNAK;
+       usb_handle_setup_data();
+}
+void sof_isr(void)__interrupt  SOF_ISR
+{
+}
+void sutok_isr(void)__interrupt        SUTOK_ISR
+{
+}
+void suspend_isr(void)__interrupt      SUSPEND_ISR
+{
+}
+void usbreset_isr(void)__interrupt     USBRESET_ISR
+{
+}
+void highspeed_isr(void)__interrupt    HIGHSPEED_ISR
+{
+}
+void ep0ack_isr(void)__interrupt       EP0ACK_ISR
+{
+}
+void stub_isr(void)__interrupt STUB_ISR
+{
+}
+void ep0in_isr(void)__interrupt        EP0IN_ISR
+{
+}
+void ep0out_isr(void)__interrupt       EP0OUT_ISR
+{
+}
+void ep1in_isr(void)__interrupt        EP1IN_ISR
+{
+       ep1_in = true;
+
+       EXIF &= ~0x10;  /* Clear USBINT: Main global interrupt */
+       EPIRQ = 0x04;   /* Clear individual EP1IN IRQ */
+}
+void ep1out_isr(void)__interrupt       EP1OUT_ISR
+{
+       ep1_out = true;
+
+       EXIF &= ~0x10;  /* Clear USBINT: Main global interrupt */
+       EPIRQ = 0x08;   /* Clear individual EP1OUT IRQ */
+}
+void ep2_isr(void)__interrupt  EP2_ISR
+{
+       ep1_out = false; /* Does nothing but required by the compiler */
+}
+void ep4_isr(void)__interrupt  EP4_ISR
+{
+}
+void ep6_isr(void)__interrupt  EP6_ISR
+{
+}
+void ep8_isr(void)__interrupt  EP8_ISR
+{
+}
+void ibn_isr(void)__interrupt  IBN_ISR
+{
+}
+void ep0pingnak_isr(void)__interrupt   EP0PINGNAK_ISR
+{
+}
+void ep1pingnak_isr(void)__interrupt   EP1PINGNAK_ISR
+{
+}
+void ep2pingnak_isr(void)__interrupt   EP2PINGNAK_ISR
+{
+}
+void ep4pingnak_isr(void)__interrupt   EP4PINGNAK_ISR
+{
+}
+void ep6pingnak_isr(void)__interrupt   EP6PINGNAK_ISR
+{
+}
+void ep8pingnak_isr(void)__interrupt   EP8PINGNAK_ISR
+{
+}
+void errorlimit_isr(void)__interrupt   ERRORLIMIT_ISR
+{
+}
+void ep2piderror_isr(void)__interrupt  EP2PIDERROR_ISR
+{
+}
+void ep4piderror_isr(void)__interrupt  EP4PIDERROR_ISR
+{
+}
+void ep6piderror_isr(void)__interrupt  EP6PIDERROR_ISR
+{
+}
+void ep8piderror_isr(void)__interrupt  EP8PIDERROR_ISR
+{
+}
+void ep2pflag_isr(void)__interrupt     EP2PFLAG_ISR
+{
+}
+void ep4pflag_isr(void)__interrupt     EP4PFLAG_ISR
+{
+}
+void ep6pflag_isr(void)__interrupt     EP6PFLAG_ISR
+{
+}
+void ep8pflag_isr(void)__interrupt     EP8PFLAG_ISR
+{
+}
+void ep2eflag_isr(void)__interrupt     EP2EFLAG_ISR
+{
+}
+void ep4eflag_isr(void)__interrupt     EP4EFLAG_ISR
+{
+}
+void ep6eflag_isr(void)__interrupt     EP6EFLAG_ISR
+{
+}
+void ep8eflag_isr(void)__interrupt     EP8EFLAG_ISR
+{
+}
+void ep2fflag_isr(void)__interrupt     EP2FFLAG_ISR
+{
+}
+void ep4fflag_isr(void)__interrupt     EP4FFLAG_ISR
+{
+}
+void ep6fflag_isr(void)__interrupt     EP6FFLAG_ISR
+{
+}
+void ep8fflag_isr(void)__interrupt     EP8FFLAG_ISR
+{
+}
+void gpifcomplete_isr(void)__interrupt GPIFCOMPLETE_ISR
+{
+}
+void gpifwaveform_isr(void)__interrupt GPIFWAVEFORM_ISR
+{
+}
+
+/**
+ * Return the control/status register for an endpoint
+ *
+ * @param ep endpoint address
+ * @return on success: pointer to Control & Status register for endpoint
+ *  specified in \a ep
+ * @return on failure: NULL
+ */
+__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep)
+{
+       /* Mask direction bit */
+       uint8_t ep_num = ep & ~0x80;
+
+       switch (ep_num) {
+       case 0:
+               return  &EP0CS;
+       case 1:
+               return  ep & 0x80 ? &EP1INCS : &EP1OUTCS;
+       case 2:
+               return  &EP2CS;
+       case 4:
+               return  &EP4CS;
+       case 6:
+               return  &EP6CS;
+       case 8:
+               return  &EP8CS;
+       default:
+               return  NULL;
+       }
+}
+
+void usb_reset_data_toggle(uint8_t ep)
+{
+       /* TOGCTL register:
+               +----+-----+-----+------+-----+-------+-------+-------+
+               | Q  |  S  |  R  |  IO  |  EP3  |  EP2  |  EP1  |  EP0  |
+               +----+-----+-----+------+-----+-------+-------+-------+
+
+               To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
+               to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
+               separate write cycle, the R bit needs to be set.
+       */
+       TOGCTL = (((ep & 0x80) >> 3) + (ep & 0x0F));
+       TOGCTL |= BMRESETTOGGLE;
+}
+
+/**
+ * Handle GET_STATUS request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_get_status(void)
+{
+       uint8_t *ep_cs;
+       switch (setup_data.bmrequesttype) {
+       case GS_DEVICE:
+               /* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
+                *                    Byte 1: reserved, reset to zero */
+               EP0BUF[0] = 0;
+               EP0BUF[1] = 0;
+
+               /* Send response */
+               EP0BCH = 0;
+               syncdelay(3);
+               EP0BCL = 2;
+               syncdelay(3);
+               break;
+       case GS_INTERFACE:
+               /* Always return two zero bytes according to USB 1.1 spec, p. 191 */
+               EP0BUF[0] = 0;
+               EP0BUF[1] = 0;
+
+               /* Send response */
+               EP0BCH = 0;
+               syncdelay(3);
+               EP0BCL = 2;
+               syncdelay(3);
+               break;
+       case GS_ENDPOINT:
+               /* Get stall bit for endpoint specified in low byte of wIndex */
+               ep_cs = usb_get_endpoint_cs_reg(setup_data.windex & 0xff);
+
+               if (*ep_cs & EPSTALL)
+                       EP0BUF[0] = 0x01;
+               else
+                       EP0BUF[0] = 0x00;
+
+               /* Second byte sent has to be always zero */
+               EP0BUF[1] = 0;
+
+               /* Send response */
+               EP0BCH = 0;
+               syncdelay(3);
+               EP0BCL = 2;
+               syncdelay(3);
+               break;
+       default:
+               return false;
+       }
+       return true;
+}
+
+/**
+ * Handle CLEAR_FEATURE request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_clear_feature(void)
+{
+       __xdata uint8_t *ep_cs;
+
+       switch (setup_data.bmrequesttype) {
+       case CF_DEVICE:
+               /* Clear remote wakeup not supported: stall EP0 */
+           STALL_EP0();
+           break;
+       case CF_ENDPOINT:
+           if (setup_data.wvalue == 0) {
+                       /* Unstall the endpoint specified in wIndex */
+                   ep_cs = usb_get_endpoint_cs_reg(setup_data.windex);
+                   if (!ep_cs)
+                           return false;
+                   *ep_cs &= ~EPSTALL;
+               } else {
+                       /* Unsupported feature, stall EP0 */
+                   STALL_EP0();
+           }
+           break;
+    default:
+               /* Vendor commands... */
+               break;
+       }
+       return true;
+}
+
+/**
+ * Handle SET_FEATURE request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_set_feature(void)
+{
+       __xdata uint8_t *ep_cs;
+
+       switch (setup_data.bmrequesttype) {
+       case SF_DEVICE:
+               if (setup_data.wvalue == 2)
+                       return true;
+               break;
+       case SF_ENDPOINT:
+               if (setup_data.wvalue == 0) {
+                       /* Stall the endpoint specified in wIndex */
+                       ep_cs = usb_get_endpoint_cs_reg(setup_data.windex);
+                       if (!ep_cs)
+                               return false;
+                       *ep_cs |= EPSTALL;
+               } else {
+                       /* Unsupported endpoint feature */
+                       return false;
+               }
+               break;
+       default:
+               /* Vendor commands... */
+               break;
+       }
+
+       return true;
+}
+
+/**
+ * Handle GET_DESCRIPTOR request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_get_descriptor(void)
+{
+       __xdata uint8_t descriptor_type;
+       __xdata uint8_t descriptor_index;
+
+       descriptor_type = (setup_data.wvalue & 0xff00) >> 8;
+       descriptor_index = setup_data.wvalue & 0x00ff;
+
+       switch (descriptor_type) {
+       case DESCRIPTOR_TYPE_DEVICE:
+               SUDPTRH = HI8(&device_descriptor);
+               SUDPTRL = LO8(&device_descriptor);
+               break;
+       case DESCRIPTOR_TYPE_CONFIGURATION:
+               SUDPTRH = HI8(&config_descriptor);
+               SUDPTRL = LO8(&config_descriptor);
+               break;
+       case DESCRIPTOR_TYPE_STRING:
+               if (setup_data.windex == 0) {
+                       /* Supply language descriptor */
+                       SUDPTRH = HI8(&language_descriptor);
+                       SUDPTRL = LO8(&language_descriptor);
+               } else if (setup_data.windex == 0x0409 /* US English */) {
+                       /* Supply string descriptor */
+                       SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]);
+                       SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]);
+               } else {
+                       return false;
+               }
+               break;
+       default:
+               /* Unsupported descriptor type */
+               return false;
+       }
+       return true;
+}
+
+/**
+ * Handle SET_INTERFACE request.
+ */
+void usb_handle_set_interface(void)
+{
+       /* Reset Data Toggle */
+       usb_reset_data_toggle(USB_DIR_IN  | 4);
+       usb_reset_data_toggle(USB_DIR_OUT | 2);
+
+       /* Unstall & clear busy flag of all valid IN endpoints */
+       EP1INCS = 0 | EPBSY;
+
+       /* Unstall all valid OUT endpoints, reset bytecounts */
+       EP1OUTCS = 0;
+       EP1OUTBC = 0;
+       syncdelay(3);
+}
+
+/* Initialize GPIF interface transfer count */
+void set_gpif_cnt(uint32_t count)
+{
+       GPIFTCB3 = (uint8_t)(((uint32_t)(count) >> 24) & 0x000000ff);
+       syncdelay(3);
+       GPIFTCB2 = (uint8_t)(((uint32_t)(count) >> 16) & 0x000000ff);
+       syncdelay(3);
+       GPIFTCB1 = (uint8_t)(((uint32_t)(count) >> 8) & 0x000000ff);
+       syncdelay(3);
+       GPIFTCB0 = (uint8_t)((uint32_t)(count) & 0x000000ff);
+}
+
+/*
+ * Vendor commands handling:
+*/
+#define VR_CFGOPEN             0xB0
+#define VR_CFGCLOSE            0xB1
+
+uint8_t        ix;
+uint8_t bcnt;
+uint8_t __xdata *eptr;
+uint16_t wcnt;
+uint32_t __xdata gcnt;
+bool usb_handle_send_bitstream(void)
+{
+       eptr = EP0BUF;                                          /* points to EP0BUF 64-byte register */
+       wcnt = setup_data.wlength;                      /* total transfer count */
+
+       /* Clear EP0BUF for OUT requests */
+       if (setup_data.bmrequesttype & 0x80) {
+               bcnt = ((wcnt > 64) ? 64 : wcnt);
+               for (ix = 0; ix < bcnt; ix++)
+                       eptr[ix] = 0;
+       }
+
+       switch (setup_data.brequest) {
+       case VR_CFGOPEN:
+               /* Clear bytecount / to allow new data in / to stops NAKing */
+               EP0BCH = 0;
+               EP0BCL = 0;
+               while (EP0CS & EPBSY)
+                       ; /* wait to finish transferring in EP0BUF, until not busy */
+               gcnt  = ((uint32_t)(eptr[0]) << 24) | ((uint32_t)(eptr[1]) << 16)
+               | ((uint32_t)(eptr[2]) << 8) | (uint32_t)(eptr[3]);
+               /* Angie board FPGA bitstream download */
+               switch ((setup_data.wvalue) & 0x00C0) {
+               case 0x00:
+                       PIN_PROGRAM_B = 0;              /* Apply RPGM- pulse */
+                       GPIFWFSELECT = 0xF2;    /* Restore Config mode waveforms select */
+                       syncdelay(3);
+                       EP2FIFOCFG = BMAUTOOUT; /* and Automatic 8-bit GPIF OUT mode */
+                       syncdelay(3);
+                       PIN_PROGRAM_B = 1;              /* Negate RPGM- pulse */
+                       delay_ms(10);                   /* FPGA init time < 10mS */
+                       set_gpif_cnt(gcnt);             /* Initialize GPIF interface transfer count */
+                       PIN_RDWR_B = 0;
+                       PIN_CSI_B = 0;
+                       GPIFTRIG = GPIF_EP2;    /* Trigger GPIF OUT transfer on EP2 */
+                       syncdelay(3);
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case VR_CFGCLOSE:
+               ix = 10;
+               /* wait until GPIF transaction has been completed */
+               while ((GPIFTRIG & BMGPIFDONE) == 0) {
+                       if (ix-- == 0) {
+                               printf("GPIF done time out\n");
+                               break;
+                       }
+                       delay_ms(1);
+               }
+               switch ((setup_data.wvalue) & 0x00C0) {
+                       case 0x00:
+                               PIN_CSI_B = 1;
+                               PIN_RDWR_B = 1;
+                               IFCONFIG &= 0xFC; /* Exit gpif mode */
+                               break;
+                       default:
+                               break;
+               }
+               EP0BCH = 0;
+               EP0BCL = (uint8_t)(setup_data.wlength); /* Signal buffer is filled */
+               break;
+       default:
+               return true;    /* Error: unknown VR command */
+       }
+       return false;           /* no error; command handled OK */
+}
+
+/**
+ * Handle the arrival of a USB Control Setup Packet.
+ */
+void usb_handle_setup_data(void)
+{
+       switch (setup_data.brequest) {
+       case GET_STATUS:
+               if (!usb_handle_get_status())
+                       STALL_EP0();
+               break;
+       case CLEAR_FEATURE:
+               if (!usb_handle_clear_feature())
+                       STALL_EP0();
+               break;
+       case 2: case 4:
+               /* Reserved values */
+               STALL_EP0();
+               break;
+       case SET_FEATURE:
+               if (!usb_handle_set_feature())
+                       STALL_EP0();
+               break;
+       case SET_ADDRESS:
+               /* Handled by USB core */
+               break;
+       case SET_DESCRIPTOR:
+               /* Set Descriptor not supported. */
+               STALL_EP0();
+               break;
+       case GET_DESCRIPTOR:
+               if (!usb_handle_get_descriptor())
+                       STALL_EP0();
+               break;
+       case GET_CONFIGURATION:
+               /* ANGIE has only one configuration, return its index */
+               EP0BUF[0] = config_descriptor.bconfigurationvalue;
+               EP0BCH = 0;
+               EP0BCL = 1;
+               syncdelay(3);
+               break;
+       case SET_CONFIGURATION:
+               /* ANGIE has only one configuration -> nothing to do */
+               break;
+       case GET_INTERFACE:
+               /* ANGIE only has one interface, return its number */
+               EP0BUF[0] = interface_descriptor00.binterfacenumber;
+               EP0BCH = 0;
+               EP0BCL = 1;
+               syncdelay(3);
+               break;
+       case SET_INTERFACE:
+               usb_handle_set_interface();
+               break;
+       case SYNCH_FRAME:
+               /* Isochronous endpoints not used -> nothing to do */
+               break;
+       default:
+               /* if not Vendor command, Stall EndPoint 0 */
+               if (usb_handle_send_bitstream())
+                       STALL_EP0();
+               break;
+       }
+}
+
+/**
+ * Handle the initialization of endpoints.
+ */
+void ep_init(void)
+{
+       EP1INCFG = 0xA0;
+       syncdelay(3);
+       EP1OUTCFG = 0xA0;
+       syncdelay(3);
+       EP2CFG = 0xA0;
+       syncdelay(3);
+       EP4CFG = 0x00;
+       syncdelay(3);
+       EP6CFG = 0x00;
+       syncdelay(3);
+       EP8CFG = 0x00;
+       syncdelay(3);
+
+       /* arm EP1-OUT */
+       EP1OUTBC = 0;
+       syncdelay(3);
+       EP1OUTBC = 0;
+       syncdelay(3);
+
+       /* arm EP1-IN */
+       EP1INBC = 0;
+       syncdelay(3);
+       EP1INBC = 0;
+       syncdelay(3);
+
+       /* Standard procedure to reset FIFOs */
+       FIFORESET = BMNAKALL;   /* NAK all transfers during the reset */
+       syncdelay(3);
+       FIFORESET = 0x02;               /* reset EP2 FIFO */
+       syncdelay(3);
+       FIFORESET = 0x00;               /* deactivate the NAK all */
+       syncdelay(3);
+       EP2FIFOCFG = 0x00;
+       syncdelay(3);
+       EP2FIFOCFG = BMAUTOOUT; /* Automatic 8-bit GPIF OUT mode */
+       syncdelay(3);
+}
+
+/**
+ * Interrupt initialization. Configures USB interrupts.
+ */
+void interrupt_init(void)
+{
+       /* Enable Interrupts */
+       EA = 1;
+
+       /* Enable USB interrupt (EIE register) */
+       EUSB = 1;
+       EICON |= 0x20;
+
+       /* Enable INT 2 & 4 Autovectoring */
+       INTSETUP |= (AV2EN | AV4EN);
+
+       /* Enable individual EP1OUT&IN interrupts */
+       EPIE |= 0x0C;
+
+       /* Clear individual USB interrupt IRQ */
+       EPIRQ = 0x0C;
+
+       /* Enable SUDAV interrupt */
+       USBIEN |= SUDAVI;
+
+       /* Clear SUDAV interrupt */
+       USBIRQ = SUDAVI;
+}
+
+/**
+ * Handle the initialization of io ports.
+ */
+void io_init(void)
+{
+       /* PORT A */
+       PORTACFG = 0x01;        /* 0: normal ou 1: alternate function (each bit) */
+       OEA = 0xEF;     /* all OUT exept INIT_B IN */
+       IOA = 0xFF;
+       PIN_RDWR_B = 1;
+       PIN_CSI_B = 1;
+       PIN_PROGRAM_B = 1;
+
+       /* PORT B */
+       OEB = 0xEF;     /* all OUT exept TDO */
+       IOB = 0xFF;
+       PIN_TRST = 1;
+       PIN_TMS = 0;
+       PIN_TCK = 0;
+       PIN_TDI = 0;
+       PIN_SRST = 1;
+
+       /* PORT C */
+       PORTCCFG = 0x00;        /* 0: normal ou 1: alternate function (each bit) */
+       OEC = 0xEF;
+       IOC = 0xFF;
+}
diff --git a/contrib/firmware/angie/hdl/Makefile b/contrib/firmware/angie/hdl/Makefile
new file mode 100644 (file)
index 0000000..c2c74a0
--- /dev/null
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (C) 2023 by NanoXplore, France - all rights reserved
+
+# Needed by timing test
+export PROJECT := angie_openocd
+TARGET_PART := xc6slx9-2tqg144
+export TOPLEVEL := S609
+
+# Detects the ROOT dir from the .git marker
+sp :=
+sp +=
+_walk = $(if $1,$(wildcard /$(subst $(sp),/,$1)/$2) $(call _walk,$(wordlist 2,$(words $1),x $1),$2))
+_find = $(firstword $(call _walk,$(strip $(subst /, ,$1)),$2))
+_ROOT := $(patsubst %/.git,%,$(call _find,$(CURDIR),.git))
+
+SHELL := /bin/bash
+TOP_DIR := $(realpath $(_ROOT))
+HDL_DIR := $(CURDIR)
+SRC_DIR := $(HDL_DIR)/src
+TOOLS_DIR := $(TOP_DIR)/tools/build
+COMMON_DIR := $(TOP_DIR)/common/hdl
+COMMON_HDL_DIR := $(COMMON_DIR)/src
+COMMON_LIBS := $(COMMON_DIR)/libs
+HDL_BUILD_DIR := $(HDL_DIR)/build
+OUTPUT_DIR ?= $(HDL_BUILD_DIR)/output
+FINAL_OUTPUT_DIR := $(OUTPUT_DIR)/$(PROJECT)
+
+# Tools
+MKDIR := mkdir -p
+CP := cp -f
+
+HDL_SRC_PATH := $(addprefix $(COMMON_DIR)/ips/, $(HDL_IPS)) $(HDL_DIR)
+VHDSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.vhd))
+VSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.v))
+VSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.vh))
+
+CONSTRAINTS ?= $(SRC_DIR)/$(PROJECT).ucf
+
+COMMON_OPTS := -intstyle xflow
+XST_OPTS :=
+NGDBUILD_OPTS :=
+MAP_OPTS := -mt 2
+PAR_OPTS := -mt 4
+BITGEN_OPTS := -g Binary:Yes
+
+XILINX_PLATFORM := lin64
+PATH := $(PATH):$(XILINX_HOME)/bin/$(XILINX_PLATFORM)
+
+RUN = @echo -ne "\n\n\e[1;33m======== $(1) ========\e[m\n\n"; \
+       cd $(HDL_BUILD_DIR) && $(XILINX_HOME)/bin/$(XILINX_PLATFORM)/$(1)
+
+compile: $(HDL_BUILD_DIR)/$(PROJECT).bin
+
+install: $(HDL_BUILD_DIR)/$(PROJECT).bin
+       $(MKDIR) $(FINAL_OUTPUT_DIR)
+       $(CP) $(HDL_BUILD_DIR)/$(PROJECT).bin $(FINAL_OUTPUT_DIR)
+
+clean:
+       rm -rf $(HDL_BUILD_DIR)
+
+$(HDL_BUILD_DIR)/$(PROJECT).bin: $(HDL_BUILD_DIR)/$(PROJECT).ncd
+       $(call RUN,bitgen) $(COMMON_OPTS) $(BITGEN_OPTS) \
+       -w $(PROJECT).ncd $(PROJECT).bit
+
+$(HDL_BUILD_DIR)/$(PROJECT).ncd: $(HDL_BUILD_DIR)/$(PROJECT).map.ncd
+       $(call RUN,par) $(COMMON_OPTS) $(PAR_OPTS) \
+               -w $(PROJECT).map.ncd $(PROJECT).ncd $(PROJECT).pcf
+
+$(HDL_BUILD_DIR)/$(PROJECT).map.ncd: $(HDL_BUILD_DIR)/$(PROJECT).ngd
+       $(call RUN,map) $(COMMON_OPTS) $(MAP_OPTS) \
+               -p $(TARGET_PART) \
+               -w $(PROJECT).ngd -o $(PROJECT).map.ncd $(PROJECT).pcf
+
+$(HDL_BUILD_DIR)/$(PROJECT).ngd: $(HDL_BUILD_DIR)/$(PROJECT).ngc
+       $(call RUN,ngdbuild) $(COMMON_OPTS) $(NGDBUILD_OPTS) \
+               -p $(TARGET_PART) -uc $(CONSTRAINTS) \
+               $(PROJECT).ngc $(PROJECT).ngd
+
+$(HDL_BUILD_DIR)/$(PROJECT).ngc: $(HDL_BUILD_DIR)/$(PROJECT).prj $(HDL_BUILD_DIR)/$(PROJECT).scr
+       $(call RUN,xst) $(COMMON_OPTS) -ifn $(PROJECT).scr
+
+$(HDL_BUILD_DIR)/$(PROJECT).scr: | $(HDL_BUILD_DIR)
+       @echo "Updating $@"
+       @mkdir -p $(HDL_BUILD_DIR)
+       @rm -f $@
+       @echo "run" \
+           "-ifn $(PROJECT).prj" \
+           "-ofn $(PROJECT).ngc" \
+           "-ifmt mixed" \
+           "$(XST_OPTS)" \
+           "-top $(TOPLEVEL)" \
+           "-ofmt NGC" \
+           "-p $(TARGET_PART)" \
+       > $(HDL_BUILD_DIR)/$(PROJECT).scr
+
+$(HDL_BUILD_DIR)/$(PROJECT).prj: | $(HDL_BUILD_DIR)
+       @echo "Updating $@"
+       @rm -f $@
+       @$(foreach file,$(VSOURCE),echo "verilog work \"$(file)\"" >> $@;)
+       @$(foreach file,$(VHDSOURCE),echo "vhdl work \"$(file)\"" >> $@;)
+       @$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.vhd),echo "vhdl $(lib) \"$(file)\"" >> $@;))
+       @$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.v),echo "verilog $(lib) \"$(file)\"" >> $@;))
+       @$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.vh),echo "verilog $(lib) \"$(file)\"" >> $@;))
+
+$(HDL_BUILD_DIR):
+       $(MKDIR) $(HDL_BUILD_DIR)
+
+.PHONY: clean compile install
+
diff --git a/contrib/firmware/angie/hdl/README b/contrib/firmware/angie/hdl/README
new file mode 100644 (file)
index 0000000..00578ff
--- /dev/null
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (C) 2023 by NanoXplore, France - all rights reserved
+
+This is the source code of Nanoxplore USB-JTAG Adapter Angie's bitstream.
+This bitstream is for the "xc6slx9-2tqg144" Spartan-6 Xilinx FPGA.
+
+To generate this bitstream, you need to install Xilinx ISE Webpack 14.7
+You will need to give the ISE software path : export XILINX_HOME=path/to/ise/sw
+Please set the enviromnent first by executing the ". ./set_env.sh"
+
+All you have to do now is to write your vhd and constrains codes.
+
+One all is setup, you can use the make commands:
+    make compile : to compile your (.vhd & .ucf) files in the "src" directory
+    A directory named "build" will be created, which contains all the generated
+    files including the bitstream file.
+
+    make clean : to delete the build directory.
diff --git a/contrib/firmware/angie/hdl/set_env.sh b/contrib/firmware/angie/hdl/set_env.sh
new file mode 100644 (file)
index 0000000..60e9737
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright (C) 2023 by NanoXplore, France - all rights reserved
+
+[ -z "${XILINX_HOME}" ] && export XILINX_HOME=/home/software/Xilinx/ISE/14.7/ISE_DS/ISE
+export PATH="$XILINX_HOME:$PATH"
+echo "SET XILINX_HOME to ${XILINX_HOME}"
+# This is needed for isim
+XILINX_HOME_BASE=${XILINX_HOME}/..
+for part in common EDK PlanAhead ISE
+do
+       el=${XILINX_HOME_BASE}/${part}
+       .  ${el}/.settings64.sh ${el}
+done
diff --git a/contrib/firmware/angie/hdl/src/angie_openocd.ucf b/contrib/firmware/angie/hdl/src/angie_openocd.ucf
new file mode 100644 (file)
index 0000000..fda3cda
--- /dev/null
@@ -0,0 +1,35 @@
+## SPDX-License-Identifier: BSD-3-Clause
+##--------------------------------------------------------------------------
+## Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
+## Design Name:     NJTAG USB-JTAG Adapter FPGA source code
+## Module Name:     _angie_openocd.ucf
+## Target Device:   XC6SLX9-2 TQ144
+## Tool versions:   ISE Webpack 13.2 -> 14.2
+## Author:          Ahmed BOUDJELIDA    nanoXplore SAS
+##--------------------------------------------------------------------------
+# WARNING: PullUps on JTAG inputs should be enabled after configuration
+# (bitgen option) since the pins are not connected.
+
+net TRST       LOC = 'P48' ;
+net TMS                LOC = 'P43' ;
+net TCK                LOC = 'P44' ;
+net TDI                LOC = 'P45' ;
+net TDO                LOC = 'P46' ;
+net SRST    LOC = 'P61' ;
+net SI_TDO     LOC = 'P16' ;
+net SO_TRST    LOC = 'P32' ;
+net SO_TMS     LOC = 'P27' ;
+net SO_TCK     LOC = 'P30' ;
+net SO_TDI     LOC = 'P26' ;
+net SO_SRST    LOC = 'P12' ;
+net ST_0       LOC = 'P29' ;
+net ST_1       LOC = 'P21' ;
+net ST_2       LOC = 'P11' ;
+net FTP<0>     LOC = 'P121' ;
+net FTP<1>     LOC = 'P120' ;
+net FTP<2>     LOC = 'P119' ;
+net FTP<3>     LOC = 'P116' ;
+net FTP<4>     LOC = 'P111' ;
+net FTP<5>     LOC = 'P112' ;
+net FTP<6>     LOC = 'P115' ;
+net FTP<7>     LOC = 'P114' ;
diff --git a/contrib/firmware/angie/hdl/src/angie_openocd.vhd b/contrib/firmware/angie/hdl/src/angie_openocd.vhd
new file mode 100644 (file)
index 0000000..d79c0fe
--- /dev/null
@@ -0,0 +1,66 @@
+-- SPDX-License-Identifier: BSD-3-Clause
+----------------------------------------------------------------------------
+-- Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
+-- Design Name:     NJTAG USB-JTAG Adapter FPGA source code
+-- Module Name:     _angie_openocd.vhd
+-- Target Device:   XC6SLX9-2 TQ144
+-- Tool versions:   ISE Webpack 13.2 -> 14.2
+-- Author:          Ahmed BOUDJELIDA    nanoXplore SAS
+----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+library UNISIM;
+use UNISIM.VComponents.all;
+
+entity S609 is port(
+  TRST   : in std_logic;
+  TMS    : in std_logic;
+  TCK    : in std_logic;
+  TDI    : in std_logic;
+  TDO    : out std_logic;
+  SRST   : in std_logic;
+  FTP    : out std_logic_vector(7 downto 0); -- Test points
+  SI_TDO : in  std_logic;
+  ST_0   : out std_logic;
+  ST_1   : out std_logic;
+  ST_2   : out std_logic;
+  SO_TRST : out std_logic;
+  SO_TMS  : out std_logic;
+  SO_TCK  : out std_logic;
+  SO_TDI : out std_logic;
+  SO_SRST :out std_logic
+);
+end S609;
+
+architecture A_S609 of S609 is
+begin
+
+--Directions:
+ST_0 <= '0';
+ST_1 <= '1';
+
+--TDO:
+TDO <= not SI_TDO;
+
+--TRST - TCK - TMS - TDI:
+SO_TRST <= TRST;
+SO_TMS <= TMS;
+SO_TCK <= TCK;
+SO_TDI <= TDI;
+ST_2 <= SRST;
+SO_SRST <= '0';
+
+--Points de test:
+FTP(0) <= TRST;
+FTP(1) <= TMS;
+FTP(2) <= TCK;
+FTP(3) <= TDI;
+FTP(5) <= SRST;
+FTP(4) <= SI_TDO;
+FTP(6) <= '1';
+FTP(7) <= '1';
+
+end A_S609;
diff --git a/doc/usb_adapters/angie/584e_424e_angie.txt b/doc/usb_adapters/angie/584e_424e_angie.txt
new file mode 100644 (file)
index 0000000..8162cba
--- /dev/null
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
+
+Bus 001 Device 056: ID 584e:424e NanoXplore, SAS. ANGIE Adapter
+Device Descriptor:
+  bLength                18
+  bDescriptorType         1
+  bcdUSB               2.00
+  bDeviceClass          255 Vendor Specific Class
+  bDeviceSubClass       255 Vendor Specific Subclass
+  bDeviceProtocol       255 Vendor Specific Protocol
+  bMaxPacketSize0        64
+  idVendor           0x584e
+  idProduct          0x424e
+  bcdDevice            0.00
+  iManufacturer           1 NanoXplore, SAS.
+  iProduct                2 ANGIE Adapter
+  iSerial                 3 000001
+  bNumConfigurations      1
+  Configuration Descriptor:
+    bLength                 9
+    bDescriptorType         2
+    wTotalLength       0x0027
+    bNumInterfaces          1
+    bConfigurationValue     1
+    iConfiguration          4 (error)
+    bmAttributes         0x80
+      (Bus Powered)
+    MaxPower              100mA
+    Interface Descriptor:
+      bLength                 9
+      bDescriptorType         4
+      bInterfaceNumber        0
+      bAlternateSetting       0
+      bNumEndpoints           3
+      bInterfaceClass       255 Vendor Specific Class
+      bInterfaceSubClass    255 Vendor Specific Subclass
+      bInterfaceProtocol    255 Vendor Specific Protocol
+      iInterface              0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x01  EP 1 OUT
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0040  1x 64 bytes
+        bInterval               0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x81  EP 1 IN
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0040  1x 64 bytes
+        bInterval               0
+      Endpoint Descriptor:
+        bLength                 7
+        bDescriptorType         5
+        bEndpointAddress     0x02  EP 2 OUT
+        bmAttributes            2
+          Transfer Type            Bulk
+          Synch Type               None
+          Usage Type               Data
+        wMaxPacketSize     0x0200  1x 512 bytes
+        bInterval               0

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)