From beaebd989cab968cab8c9af24f4d376e89ca71b5 Mon Sep 17 00:00:00 2001 From: MX682X <58419867+MX682X@users.noreply.github.com> Date: Wed, 14 Aug 2024 19:01:04 +0200 Subject: [PATCH] PICkit 5 support (#1863) --- src/CMakeLists.txt | 4 + src/Makefile.am | 4 + src/avrdude.conf.in | 41 +- src/doc/avrdude.texi | 23 + src/main.c | 3 + src/pgm_type.c | 2 + src/pickit5.c | 1410 ++++++++++++++++++++++++++++++++++++++ src/pickit5.h | 32 + src/pickit5_lut.h | 83 +++ src/pickit5_updi_lut.c | 1110 ++++++++++++++++++++++++++++++ src/usbdevs.h | 1 + tools/scripts_decoder.py | 675 ++++++++++++++++++ 12 files changed, 3386 insertions(+), 2 deletions(-) create mode 100644 src/pickit5.c create mode 100644 src/pickit5.h create mode 100644 src/pickit5_lut.h create mode 100644 src/pickit5_updi_lut.c create mode 100644 tools/scripts_decoder.py diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5c02978e4..f7b1700b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -229,6 +229,10 @@ set(SOURCES pgm_type.c pickit2.c pickit2.h + pickit5_updi_lut.c + pickit5_lut.h + pickit5.c + pickit5.h pindefs.c ppi.c ppi.h diff --git a/src/Makefile.am b/src/Makefile.am index 5b9957564..b075ea869 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -156,6 +156,10 @@ libavrdude_la_SOURCES = \ pgm_type.c \ pickit2.c \ pickit2.h \ + pickit5_updi_lut.c \ + pickit5_lut.h \ + pickit5.c \ + pickit5.h \ pindefs.c \ ppi.c \ ppi.h \ diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 9d64a83ab..1dc05cb0b 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -2948,9 +2948,8 @@ programmer # powerdebugger_tpi # pickit4 / pickit4_jtag #------------------------------------------------------------ -# Microchip PICkit 4. See +# Microchip PICkit 4. For details see # https://www.microchip.com/en-us/development-tool/pg164140 -# for details. # # The PICkit 4 supports the following programming modes # using different programmer names: @@ -3055,6 +3054,44 @@ programmer # pickit4_tpi usbpid = 0x2177, 0x2178, 0x2179; ; + +# Microchip PICkit 5. For details, see +# https://www.microchip.com/en-us/development-tool/PG164150 +# +# Currently -c pickit5 only supports UPDI programming +# +# PIN UPDI +# > 1 !RST(*) +# 2 VCC +# 3 GND +# 4 UPDI(*) +# 5 +# 6 +# 7 +# 8 +# +# (*): The PICkit5 can generate a High-Voltage (12V) Pulse on this pins +# to restore the UPDI Pin functionality, if it was changed through fuses. +# AVRDUDE automatically selects the correct pin, if the HV pulse is +# enabled through the '-x hvupdi' flag. + +#------------------------------------------------------------ +# pickit5 /pickit5_updi +#------------------------------------------------------------ + +programmer # pickit5_updi + id = "pickit5_updi"; + desc = "MPLAB(R) PICkit 5, PICkit 4 and SNAP (PIC mode)"; + type = "pickit5_updi"; + prog_modes = PM_UPDI; + extra_features = HAS_VTARG_READ; + connection_type = usb; + baudrate = 200000; # UPDI default clock + usbvid = 0x04d8; + usbpid = 0x9036, 0x9012, 0x9018; # PK5, PK4 (pic mode), snap (pic mode) + hvupdi_support = 0, 1, 2; +; + #------------------------------------------------------------ # snap /snap_jtag #------------------------------------------------------------ diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index eb97eda84..5e1bfd8c5 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -325,6 +325,7 @@ See below for some hints about FLIP version 1 protocol behaviour. The MPLAB(R) PICkit 4 and MPLAB(R) SNAP are supported in JTAG, TPI, ISP, PDI and UPDI mode. The Curiosity Nano board is supported in UPDI mode. It is dubbed ``PICkit on Board'', thus the name @code{pkobn_updi}. +The MPLAB(R) PICkit 5 is currently only supported in UPDI mode. SerialUPDI programmer implementation is based on Microchip's @emph{pymcuprog} (@url{https://github.com/microchip-pic-avr-tools/pymcuprog}) @@ -1305,6 +1306,27 @@ for switching to PIC mode. Show help menu and exit. @end table +@cindex Option @code{-x} PICkit 5 +@item PICkit 5 +@item PICkit 4 (PIC Mode) + +The PICkit 5 and PICkit 4 (PIC Mode) programmer can accept following extended parameters +@table @code +@item @samp{vtarg=VALUE} +Specify a voltage between 1.8 and 5.5@w{ }V that the programmer should supply +to the target. If there is already a valid voltage applied to the VTG Pin, +this setting will be ignored. When AVRDUDE detects an external voltage outside +of this range, it will terminate the operation. You can disable this by +setting the voltage to 0@w{ }V. +@item @samp{hvupdi} +High-voltage UPDI programming is used to enable a UPDI pin that has previously +been set to RESET or GPIO mode. Use @samp{-x hvupdi} to enable high-voltage UPDI +initialization for supported targets. Depending on the target, the HV pulse will +be applied either on the RST pin, or the UPDI pin. +@item @samp{help} +Show help menu and exit. +@end table + @cindex Option @code{-x} Xplained Mini @item Xplained Mini @@ -2220,6 +2242,7 @@ Valid programmers for part AVR32EA32 are: jtag2updi = JTAGv2 to UPDI bridge via UPDI jtag3updi = Atmel AVR JTAGICE3 via UPDI pickit4_updi = MPLAB(R) PICkit 4 via UPDI + pickit5_updi = MPLAB(R) PICkit 5, PICkit 4 and SNAP (PIC mode) via UPDI pkobn_updi = Curiosity nano (nEDBG) via UPDI powerdebugger_updi = Atmel PowerDebugger (ARM/AVR) via UPDI serialupdi = SerialUPDI via UPDI diff --git a/src/main.c b/src/main.c index 427788942..ce2be3b53 100644 --- a/src/main.c +++ b/src/main.c @@ -1545,6 +1545,9 @@ int main(int argc, char * argv []) else imsg_error(" - use -B to set lower the bit clock frequency, e.g. -B 125kHz\n"); + if (str_starts(pgm->type, "pickit5")) + imsg_error(" - reset the programmer by unplugging it"); + if (!ovsigck) { imsg_error(" - use -F to override this check\n"); exitrc = 1; diff --git a/src/pgm_type.c b/src/pgm_type.c index e439e8568..d80097ee1 100644 --- a/src/pgm_type.c +++ b/src/pgm_type.c @@ -46,6 +46,7 @@ #include "micronucleus.h" #include "par.h" #include "pickit2.h" +#include "pickit5.h" #include "ppi.h" #include "serbb.h" #include "serialupdi.h" @@ -99,6 +100,7 @@ const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call th {"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0" {"par", par_initpgm, par_desc}, // "PPI" {"pickit2", pickit2_initpgm, pickit2_desc}, // "pickit2" + {"pickit5_updi", pickit5_initpgm, pickit5_desc}, // "pickit5" {"serbb", serbb_initpgm, serbb_desc}, // "SERBB" {"serialupdi", serialupdi_initpgm, serialupdi_desc}, // "serialupdi" {"serprog", serprog_initpgm, serprog_desc}, // "serprog" diff --git a/src/pickit5.c b/src/pickit5.c new file mode 100644 index 000000000..13bdc66bb --- /dev/null +++ b/src/pickit5.c @@ -0,0 +1,1410 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2024 MX682X + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This code is not affiliated in any way with Microchip® + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "libavrdude.h" + +#include "pickit5.h" +#include "pickit5_lut.h" +#include "updi_constants.h" +#include "usbdevs.h" + +#if defined(HAVE_USB_H) +#include // Linux/Mac +#elif defined(HAVE_LUSB0_USB_H) +#include // Windows +#endif + +// A USB driver is needed to talk with MacOS USB; it's unclear where to find it +// so remove the support under MacOS for the time being + +#if defined(HAVE_USB_H) || defined(HAVE_LUSB0_USB_H) +#define USB_PK5_CMD_READ_EP 0x81 +#define USB_PK5_CMD_WRITE_EP 0x02 +#define USB_PK5_DATA_READ_EP 0x83 +#define USB_PK5_DATA_WRITE_EP 0x04 + +#define USB_PK5_MAX_XFER 512 + +#define CHECK_ERROR 0x01 +#define BIST_TEST 0x02 +#define BIST_RESULT 0x03 + +#define PGM_TYPE_PK5 0x00 // Default +#define PGM_TYPE_PK4 0x01 // PICkit4 +#define PGM_TYPE_SNAP 0x02 // SNAP + +#define PK_OP_NONE 0x00 // Init +#define PK_OP_FOUND 0x01 // PK is connected to USB +#define PK_OP_RESPONDS 0x02 // Responds to get_fw() requests +#define PK_OP_READY 0x03 // Voltage Set, Clock Set + +#define POWER_SOURCE_EXT 0x00 +#define POWER_SOURCE_INT 0x01 +#define POWER_SOURCE_NONE 0x02 + +// Private data for this programmer +struct pdata { + unsigned char pgm_type; // Used to skip unsupported functions + unsigned char pk_op_mode; // See PK_OP_ defines + unsigned char power_source; // 0: external / 1: from PICkit / 2: ignore check + unsigned char hvupdi_enabled; // 0: no HV / 1: HV generation enabled + double target_voltage; // Voltage to supply to target + + double measured_vcc; // This and below for print_params() + unsigned int measured_current; + unsigned int actual_updi_clk; + + unsigned char nvm_version; // Used to determine the offset for SIGROW/DevID + + unsigned char devID[4]; // Last byte has the Chip Revision of the target + unsigned char app_version[3]; // Buffer for display() sent by get_fw() + unsigned char fw_info[16]; // Buffer for display() sent by get_fw() + unsigned char sernum_string[20]; // Buffer for display() sent by get_fw() + char sib_string[32]; + unsigned char txBuf[512]; + unsigned char rxBuf[512]; + SCRIPT scripts; +}; + +#define my (*(struct pdata *)(pgm->cookie)) + + +static void pickit5_setup(PROGRAMMER *pgm); +static void pickit5_teardown(PROGRAMMER *pgm); +static int pickit5_parseextparms(const PROGRAMMER *pgm, const LISTID extparms); + +static int pickit5_open(PROGRAMMER *pgm, const char *port); +static void pickit5_close(PROGRAMMER *pgm); + +static void pickit5_disable(const PROGRAMMER *pgm); +static void pickit5_enable(PROGRAMMER *pgm, const AVRPART *p); +static void pickit5_display(const PROGRAMMER *pgm, const char *p); +static int pickit5_initialize(const PROGRAMMER *pgm, const AVRPART *p); + +static int pickit5_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res); +static int pickit5_program_enable(const PROGRAMMER *pgm, const AVRPART *p); +static int pickit5_program_disable(const PROGRAMMER *pgm, const AVRPART *p); +static int pickit5_chip_erase(const PROGRAMMER *pgm, const AVRPART *p); +static int pickit5_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned int page_size, unsigned int addr, unsigned int n_bytes); +static int pickit5_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned int page_size, unsigned int addr, unsigned int n_bytes); +static int pickit5_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned long addr, unsigned char value); +static int pickit5_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned long addr, unsigned char *value); +static int pickit5_read_dev_id(const PROGRAMMER *pgm, const AVRPART *p); +static int pickit5_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib); +static int pickit5_read_chip_rev(const PROGRAMMER *pgm, const AVRPART *p, unsigned char *chip_rev); +static int pickit5_read_array(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, int len, unsigned char *value); +static int pickit5_write_array(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, int len, unsigned char *value); + +// UPDI-specific functions +static int pickit5_updi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, unsigned char value); +static int pickit5_updi_read_byte(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, unsigned char *value); + +// Extra functions +static int pickit5_get_fw_info(const PROGRAMMER *pgm); +static int pickit5_set_vtarget(const PROGRAMMER *pgm, double v); +static int pickit5_get_vtarget(const PROGRAMMER *pgm, double *v); +static int pickit5_set_ptg_mode(const PROGRAMMER *pgm); +static int pickit5_set_sck_period(const PROGRAMMER *pgm, double sckperiod); +static int pickit5_write_cs_reg(const PROGRAMMER *pgm, unsigned int addr, unsigned char value); +static int pickit5_read_cs_reg(const PROGRAMMER *pgm, unsigned int addr, unsigned char *value); + +// Internal functions +inline static void pickit5_uint32_to_array(unsigned char *buf, uint32_t num); +inline static unsigned int pickit5_array_to_uint32(unsigned char *buf); +inline static void pickit5_create_payload_header(unsigned char *buf, unsigned int type, + unsigned int msg_len, unsigned int trans_len); +inline static void pickit5_create_script_header(unsigned char *buf, unsigned int arg_len, unsigned int script_len); +inline static int pickit5_check_ret_status(const PROGRAMMER *pgm); + +static int pickit5_get_status(const PROGRAMMER *pgm, unsigned char status); +static int pickit5_send_script(const PROGRAMMER *pgm, unsigned int script_type, + const unsigned char *script, unsigned int script_len, + const unsigned char *param, unsigned int param_len, unsigned int payload_len); +static int pickit5_send_script_done(const PROGRAMMER *pgm, char *func); +static int pickit5_read_response(const PROGRAMMER *pgm, char *fn_name); + +// Extra-USB related functions, because we need more then 2 endpoints +static int usbdev_data_recv(const union filedescriptor *fd, unsigned char *buf, size_t nbytes); +static int usbdev_data_send(const union filedescriptor *fd, const unsigned char *bp, size_t mlen); + +inline static void pickit5_uint32_to_array(unsigned char *buf, uint32_t num) { + *(buf++) = (uint8_t) num; + *(buf++) = (uint8_t) (num >> 8); + *(buf++) = (uint8_t) (num >> 16); + *(buf) = (uint8_t) (num >> 24); +} + +inline static unsigned int pickit5_array_to_uint32(unsigned char *buf) { + unsigned int retval = 0; + + retval |= *(buf++); + retval |= *(buf++) << 8; + retval |= *(buf++) << 16; + retval |= *(buf++) << 24; + return retval; +} + +inline static void pickit5_create_payload_header(unsigned char *buf, unsigned int type, + unsigned int msg_len, unsigned int trans_len) { + pickit5_uint32_to_array(&buf[0], type); + pickit5_uint32_to_array(&buf[4], 0); + pickit5_uint32_to_array(&buf[8], msg_len); + pickit5_uint32_to_array(&buf[12], trans_len); +} + +inline static void pickit5_create_script_header(unsigned char *buf, unsigned int arg_len, unsigned int script_len) { + pickit5_uint32_to_array(&buf[0], arg_len); + pickit5_uint32_to_array(&buf[4], script_len); +} + +static void pickit5_setup(PROGRAMMER *pgm) { + pgm->cookie = mmt_malloc(sizeof(struct pdata)); +} + +static void pickit5_teardown(PROGRAMMER *pgm) { + mmt_free(pgm->cookie); + pgm->cookie = NULL; +} + +static int pickit5_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) { + LNODEID ln; + const char *extended_param; + int rv = 0; + + for(ln = lfirst(extparms); ln; ln = lnext(ln)) { + extended_param = ldata(ln); + + if(str_starts(extended_param, "vtarg=")) { + double voltage = -1.0; + + if(sscanf(extended_param, "vtarg=%lf", &voltage) != 1) { + + pmsg_error("invalid voltage parameter %s\n", extended_param); + rv = -1; + continue; + } + if(voltage < 0.1 && voltage > -1.0) { + my.power_source = POWER_SOURCE_NONE; // Voltage check disabled + continue; + } else if(voltage < 1.8 || voltage > 5.5) { + pmsg_error("voltage %1.1lf V outside valid range [1.8 V, 5.5 V]\n", voltage); + rv = -1; + continue; + } else { + my.power_source = POWER_SOURCE_INT; // PK supplies power + my.target_voltage = voltage; + continue; + } + } + if(str_starts(extended_param, "hvupdi")) { + my.hvupdi_enabled = 1; + continue; + } + + if(str_eq(extended_param, "help")) { + msg_error("%s -c %s extended options:\n", progname, pgmid); + msg_error(" -x vtarg= Enable power output; must be in [1.8, 5.5] V\n"); + msg_error(" -x hvupdi Enable high-voltage UPDI initialization\n"); + msg_error(" -x help Show this help menu and exit\n"); + return LIBAVRDUDE_EXIT; + } + + pmsg_error("invalid extended parameter %s\n", extended_param); + rv = -1; + } + return rv; +} + +// Internal functions + +// Type can be CMD, UPLOAD or DOWNLOAD +#define SCR_CMD 0x0100 +#define SCR_UPLOAD 0x80000102 +#define SCR_DOWNLOAD 0x0C0000101 + +static int pickit5_send_script(const PROGRAMMER *pgm, unsigned int script_type, + const unsigned char *script, unsigned int script_len, + const unsigned char *param, unsigned int param_len, unsigned int payload_len) { + + if(script == NULL) + return -1; + + unsigned int header_len = 16 + 8; // Header info + script header + unsigned int preamble_len = header_len + param_len; + unsigned int message_len = preamble_len + script_len; + + if(message_len > 1023) // Required memory will exceed buffer size, abort + return -1; // 1 kB should be enough for everything + + unsigned char *buf = my.txBuf; + + pickit5_create_payload_header(&buf[0], script_type, message_len, payload_len); + pickit5_create_script_header(&buf[16], param_len, script_len); + + if(param != NULL) + memcpy(&buf[24], param, param_len); + + memcpy(&buf[preamble_len], script, script_len); + + return serial_send(&pgm->fd, buf, message_len); +} + +static int pickit5_read_response(const PROGRAMMER *pgm, char *fn_name) { + unsigned char *buf = my.rxBuf; + + if(serial_recv(&pgm->fd, buf, 512) < 0) { + pmsg_error("reading from PICkit failed"); + return -1; + } + unsigned int status = pickit5_array_to_uint32(&buf[0]); + + if(status != 0x0D) { + pmsg_error("unexpected response in function %s", fn_name); + return -1; + } + + return 0; +} + +static int pickit5_send_script_done(const PROGRAMMER *pgm, char *func) { + unsigned char script_done[16]; + unsigned int script_done_type = 0x0103; + + pickit5_create_payload_header(script_done, script_done_type, 16, 0); + if(serial_send(&pgm->fd, script_done, 16) >= 0) + return pickit5_read_response(pgm, func); + pmsg_error("failed sending script done message"); + return -1; +} + +static int pickit5_open(PROGRAMMER *pgm, const char *port) { + if(!pgm->cookie) // Sanity + return -1; + pmsg_debug("%s(\"%s\")\n", __func__, port); + union pinfo pinfo; + LNODEID usbpid; + int rv = -1; + +#if !defined(HAVE_LIBUSB) + pmsg_error("need to be compiled with USB or HIDAPI support\n"); + return -1; +#endif + + if(!str_starts(port, "usb")) { + pmsg_error("port names must start with usb\n"); + return -1; + } + unsigned int new_vid = 0, new_pid = 0; + char *vidp, *pidp; + + /* + * The syntax for usb devices is defined as: + * + * -P usb:vid:pid + * -P usb::pid + * -P usb:serialnumber + * -P usb + * + * First we check if we have two colons. + * Then check the filed between the two colons is empty + * Parse VID as hex number + * If it is empty, assume Microchip VID + * The PID is handled similary but can not be empty + * + * If there are fewer than two colons nothing is changed + */ + + vidp = strchr(port, ':'); + if(vidp != NULL) { + vidp += 1; + pidp = strchr(vidp, ':'); + if(pidp != NULL) { + if(vidp != pidp) { // User specified an VID + // First: Handle VID input + if(sscanf(vidp, "%x", &new_vid) != 1) { + pmsg_error("failed to parse -P VID input %s: unexpected format", vidp); + return -1; + } + } else { // VID space empty: default to Microchip + new_vid = USB_VENDOR_MICROCHIP; + } + + // Now handle PID input + if(sscanf(pidp + 1, "%x", &new_pid) != 1) { + pmsg_error("failed to parse -P PID input %s: unexpected format", pidp+1); + return -1; + } + + if((new_vid != 0) && (new_pid != 0)) { + pmsg_notice("overwriting VID:PID to %04x:%04x\n", new_vid, new_pid); + port = "usb"; // Overwrite the string to avoid confusing the libusb + } + } // pidp == NULL means vidp could point to serial number + } // vidp == NULL means just 'usb' + + // If the config entry did not specify a USB PID, insert the default one + if(lfirst(pgm->usbpid) == NULL) + ladd(pgm->usbpid, (void *) USB_DEVICE_PICKIT5); + + pinfo.usbinfo.vid = pgm->usbvid? pgm->usbvid: USB_VENDOR_MICROCHIP; + + // PICkit 5 does not have support for HID, so no need to support it + serdev = &usb_serdev; + if(new_pid != 0 && new_vid != 0) { // In case a specific VID/PID was specified + pinfo.usbinfo.vid = new_vid; + pinfo.usbinfo.pid = new_pid; + pinfo.usbinfo.flags = PINFO_FL_SILENT; + pgm->fd.usb.max_xfer = USB_PK5_MAX_XFER; + pgm->fd.usb.rep = USB_PK5_CMD_READ_EP; // Command read + pgm->fd.usb.wep = USB_PK5_CMD_WRITE_EP; // Command write + pgm->fd.usb.eep = 0x00; + pgm->port = port; + rv = serial_open(port, pinfo, &pgm->fd); + } else { // Otherwise walk the list of config file PIDs + for(usbpid = lfirst(pgm->usbpid); rv < 0 && usbpid != NULL; usbpid = lnext(usbpid)) { + pinfo.usbinfo.flags = PINFO_FL_SILENT; + pinfo.usbinfo.pid = *(int *) (ldata(usbpid)); + pgm->fd.usb.max_xfer = USB_PK5_MAX_XFER; + pgm->fd.usb.rep = USB_PK5_CMD_READ_EP; // Command read + pgm->fd.usb.wep = USB_PK5_CMD_WRITE_EP; // Command write + pgm->fd.usb.eep = 0x00; + + pgm->port = port; + rv = serial_open(port, pinfo, &pgm->fd); + } + } + + // Make USB serial number available to programmer + if(serdev && serdev->usbsn) { + pgm->usbsn = serdev->usbsn; + my.pk_op_mode = PK_OP_FOUND; + + if(pinfo.usbinfo.pid == USB_DEVICE_PICKIT5) + my.pgm_type = PGM_TYPE_PK5; + else if(pinfo.usbinfo.pid == USB_DEVICE_PICKIT4_PIC_MODE) + my.pgm_type = PGM_TYPE_PK4; + else if(pinfo.usbinfo.pid == USB_DEVICE_SNAP_PIC_MODE) + my.pgm_type = PGM_TYPE_SNAP; + } + + return rv; +} + +static void pickit5_close(PROGRAMMER *pgm) { + pmsg_debug("%s()\n", __func__); + pickit5_set_vtarget(pgm, 0.0); // Switches off PICkit voltage regulator if enabled + + serial_close(&pgm->fd); +} + +static void pickit5_disable(const PROGRAMMER *pgm) { + return; +} + +static void pickit5_enable(PROGRAMMER *pgm, const AVRPART *p) { + // Overwrite page sizes so that avrdude uses pages read/writes + // This will reduce overhead and increase speed + AVRMEM *mem; + + if((mem = avr_locate_sram(p))) + mem->page_size = mem->size < 256? mem->size: 256; + if((mem = avr_locate_eeprom(p))) + mem->page_size = mem->size < 32? mem->size: 32; + if((mem = avr_locate_sib(p))) { // This is mandatory as PICkit is reading all 32 bytes at once + mem->page_size = 32; + mem->readsize = 32; + } +} + +static void pickit5_display(const PROGRAMMER *pgm, const char *p) { + unsigned char *app = my.app_version; + unsigned char *sn = my.sernum_string; + + if(pickit5_get_fw_info(pgm) < 0) { + msg_error("failed to get firmware info\n"); + return; + } + + msg_info("Application version : %02x.%02x.%02x\n", app[0], app[1], app[2]); + msg_info("Serial number : %s\n", sn); + my.pk_op_mode = PK_OP_RESPONDS; +} + +static void pickit5_print_parms(const PROGRAMMER *pgm, FILE *fp) { + pickit5_get_vtarget(pgm, NULL); + fmsg_out(fp, "UPDI clock : %u kHz\n", my.actual_updi_clk / 1000); + fmsg_out(fp, "Target Vcc : %1.2f V\n", my.measured_vcc); + fmsg_out(fp, "Target current : %3u mA\n", my.measured_current); +} + +static int pickit5_initialize(const PROGRAMMER *pgm, const AVRPART *p) { + pmsg_debug("%s()\n", __func__); + if(!pgm->cookie) + return -1; + + if(my.pk_op_mode < PK_OP_FOUND) { + pmsg_error("failed to find a connected PICkit\n"); + return -1; + } + + int rc = -1; + + if(pgm->prog_modes == PM_UPDI) + rc = get_pickit_updi_script(&(my.scripts), p->desc); + + if(rc == -1) + return -1; + if(rc == -2) { + pmsg_error("failed to match scripts to %s, aborting\n", p->desc); + return -1; + } + + if(my.hvupdi_enabled > 0) { + if(p->hvupdi_variant == 0) + pmsg_notice("high-voltage SYSCFG0 override on UPDI Pin enabled\n"); + if(p->hvupdi_variant == 2) + pmsg_notice("high-voltage SYSCFG0 override on RST Pin enabled\n"); + } + + if(my.pk_op_mode < PK_OP_RESPONDS) { + if(pickit5_get_fw_info(pgm) < 0) // PK responds: we can try to enable voltage + return -1; + my.pk_op_mode = PK_OP_RESPONDS; + } + + pickit5_set_ptg_mode(pgm); + pickit5_set_vtarget(pgm, 0.0); // Avoid the edge case when avrdude was CTRL+C'd but still provides power + + // Now we try to figure out if we have to supply power from PICkit + double v_target; + + pickit5_get_vtarget(pgm, &v_target); + if(v_target < 1.8) { + if(my.power_source == POWER_SOURCE_NONE) { + pmsg_warning("no external voltage detected but continuing anyway\n"); + } else if(my.power_source == POWER_SOURCE_INT) { + pmsg_notice("no extenal Voltage detected; trying to supply from PICkit\n"); + + if(pickit5_set_vtarget(pgm, my.target_voltage) < 0) + return -1; // Set requested voltage + + if(pickit5_get_vtarget(pgm, &v_target) < 0) + return -1; // Verify voltage + + if(v_target < my.target_voltage - 0.25 // Voltage supply is not accurate: allow some room + || v_target > my.target_voltage + 0.15) { + pmsg_error("target voltage out of range, aborting\n"); + return -1; + } + } else { + pmsg_error("no external voltage detected, aborting; overwrite this check with -x vtarg=0\n"); + return -1; + } + } else { + my.power_source = POWER_SOURCE_EXT; // Overwrite user input + pmsg_notice("external Voltage detected: will not supply power\n"); + } + + my.pk_op_mode = PK_OP_READY; + + // Target is powered, set the UPDI baudrate; adjust UPDICLKSEL if possible and neccessary + if(pickit5_program_enable(pgm, p) < 0) + return -1; + + // Get SIB so we can get the NVM Version + if(pickit5_read_sib(pgm, p, my.sib_string) < 0) { + pmsg_error("failed to obtain System Info Block\n"); + return -1; + } + + if(pickit5_read_dev_id(pgm, p) < 0) { + pmsg_error("failed to obtain device ID\n"); + return -1; + } + + double bitclock = pgm->bitclock; + unsigned int baud = pgm->baudrate; + + if(baud == 200000) { // If baud unchanged + if(bitclock > 0.0) { + baud = (unsigned int) (1.0 / pgm->bitclock); // Bitclock in us + } + } else { + if(bitclock > 0.0) { + pmsg_error("both -b baudrate and -B bitclock given; please use only one, aborting\n"); + return -1; + } + } + + if(baud < 300) { // Better be safe than sorry + pmsg_warning("UPDI needs a higher clock for operation, increasing UPDI to 300 Hz\n"); + baud = 300; + } + if(baud > 225000) { + if(v_target < 2.9) { + pmsg_warning("UPDI needs a voltage of more than 2.9 V for a faster baudrate, limiting UPDI to 225 kHz\n"); + baud = 225000; + } else { + if(baud > 900000) { + pmsg_warning("requested clock %u Hz too high, limiting UPDI to 900 kHz\n", baud); + baud = 900000; + } + pickit5_set_sck_period(pgm, 1.0 / 100000); // Start with 200 kHz + pickit5_write_cs_reg(pgm, UPDI_ASI_CTRLA, 0x01); // Change UPDI clock to 16 MHz + unsigned char ret_val = 0; + + pickit5_read_cs_reg(pgm, UPDI_ASI_CTRLA, &ret_val); + if(ret_val != 0x01) { + pmsg_warning("failed to change UPDI clock, falling back to 225 kHz\n"); + baud = 225000; + } + } + } + if(pickit5_set_sck_period(pgm, 1.0 / baud) >= 0) { + pmsg_notice("UPDI speed set to %i kHz\n", baud / 1000); + my.actual_updi_clk = baud; + } else { + pmsg_warning("failed to set UPDI speed, continuing\n"); + my.actual_updi_clk = 100000; // Default clock? + } + + pickit5_program_enable(pgm, p); + return 0; +} + +static int pickit5_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res) { + return -2; +} + +static int pickit5_program_enable(const PROGRAMMER *pgm, const AVRPART *p) { + pmsg_debug("%s()\n", __func__); + const unsigned char *enter_prog = my.scripts.EnterProgMode; + unsigned int enter_prog_len = my.scripts.EnterProgMode_len; + + if(my.hvupdi_enabled && (my.pgm_type != PGM_TYPE_SNAP)) { // SNAP has no HV generation + if(p->hvupdi_variant == HV_UPDI_VARIANT_0) { // High voltage generation on UPDI line + enter_prog = my.scripts.EnterProgModeHvSp; + enter_prog_len = my.scripts.EnterProgModeHvSp_len; + } else if(p->hvupdi_variant == HV_UPDI_VARIANT_2) { // High voltage generation on RST line + enter_prog = my.scripts.EnterProgModeHvSpRst; + enter_prog_len = my.scripts.EnterProgModeHvSpRst_len; + } + } + if(my.pk_op_mode == PK_OP_READY) { + if(pickit5_send_script(pgm, SCR_CMD, enter_prog, enter_prog_len, NULL, 0, 0) < 0) + return -1; + + if(pickit5_read_response(pgm, "Enter Programming Mode") < 0) + return -1; + } + return 0; +} + +static int pickit5_program_disable(const PROGRAMMER *pgm, const AVRPART *p) { + pmsg_debug("%s()\n", __func__); + const unsigned char *enter_prog = my.scripts.ExitProgMode; + unsigned int enter_prog_len = my.scripts.ExitProgMode_len; + + if(my.pk_op_mode == PK_OP_READY) { + if(pickit5_send_script(pgm, SCR_CMD, enter_prog, enter_prog_len, NULL, 0, 0) < 0) + return -1; + + if(pickit5_read_response(pgm, "Exit Programming Mode") < 0) + return -1; + } + return 0; +} + +static int pickit5_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) { + pmsg_debug("%s()\n", __func__); + + pickit5_program_enable(pgm, p); + const unsigned char *chip_erase = my.scripts.EraseChip; + unsigned int chip_erase_len = my.scripts.EraseChip_len; + + if(pickit5_send_script(pgm, SCR_CMD, chip_erase, chip_erase_len, NULL, 0, 0) >= 0) { + if(pickit5_read_response(pgm, "Erase Chip") >= 0) { + if(pickit5_array_to_uint32(&(my.rxBuf[16])) == 0x00) { + pmsg_info("target successfully erased\n"); + my.pk_op_mode = PK_OP_READY; + pickit5_program_enable(pgm, p); + return 0; + } + } + } + + pmsg_error("chip erase failed\n"); + return -1; +} + +static int pickit5_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned int page_size, unsigned int address, unsigned int n_bytes) { + + return pickit5_read_array(pgm, p, mem, address, n_bytes, &mem->buf[address]); +} + +static int pickit5_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, + unsigned int page_size, unsigned int address, unsigned int n_bytes) { + + return pickit5_write_array(pgm, p, mem, address, n_bytes, &mem->buf[address]); +} + +// Sets UPDI Frequency in kHz +static int pickit5_set_sck_period(const PROGRAMMER *pgm, double sckperiod) { + pmsg_debug("%s()\n", __func__); + double frq = (0.001 / sckperiod) + 0.5; // 1ms/period = kHz; round up + const unsigned char *set_speed = my.scripts.SetSpeed; + int set_speed_len = my.scripts.SetSpeed_len; + unsigned char buf[4]; + + pickit5_uint32_to_array(buf, frq); + if(pickit5_send_script(pgm, SCR_CMD, set_speed, set_speed_len, buf, 4, 0) < 0) + return -1; + if(pickit5_read_response(pgm, "Set UPDI Speed") < 0) + return -1; + return 0; +} + +static int pickit5_write_byte(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, unsigned char value) { + int rc = pickit5_write_array(pgm, p, mem, addr, 1, &value); + + if(rc < 0) + return rc; + return 0; +} + +static int pickit5_read_byte(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, unsigned char *value) { + int rc = pickit5_read_array(pgm, p, mem, addr, 1, value); + + if(rc < 0) + return rc; + return 0; +} + +// UPDI Specific function providing a reduced overhead when writing a single byte +static int pickit5_updi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, unsigned char value) { + + if(mem->size < 1 || addr > (unsigned long) mem->size) { + pmsg_error("address %i out of range for %s [0, %i]\n", (unsigned) addr, mem->desc, mem->size); + return -1; + } + addr += mem->offset; + pmsg_debug("%s(0x%4X, %i)\n", __func__, (unsigned) addr, value); + // This script is based on WriteCSreg; reduces overhead by avoiding writing data EP + const unsigned char h_len = 24; // 16 + 8 + const unsigned char p_len = 8; + const unsigned char s_len = 8; + const unsigned char m_len = h_len + p_len + s_len; + + unsigned char write8_fast[] = { + 0x00, 0x01, 0x00, 0x00, // [0] SCR_CMD + 0x00, 0x00, 0x00, 0x00, // [4] always 0 + m_len, 0x00, 0x00, 0x00, // [8] message length = 16 + 8 + param (8) + script (8) = 40 + 0x00, 0x00, 0x00, 0x00, // [12] keep at 0 to receive the data in the "response" + + p_len, 0x00, 0x00, 0x00, // [16] param length: 8 bytes + s_len, 0x00, 0x00, 0x00, // [20] length of script: 8 bytes + + 0x00, 0x00, 0x00, 0x00, // [24] param: address to write to, will be overwritten + 0x00, 0x00, 0x00, 0x00, // [28] param: byte to write, will be overwritten + + // Script itself: + 0x91, 0x00, // Copy first 4 bytes of param to reg 0 + 0x91, 0x01, // Copy second 4 bytes of param to reg 1 + 0x1E, 0x06, 0x00, 0x01, // Store to address in reg 0 the byte in reg 1 + }; + write8_fast[24] = (((unsigned char *) &addr)[0]); + write8_fast[25] = (((unsigned char *) &addr)[1]); + write8_fast[28] = value; + + serial_send(&pgm->fd, write8_fast, m_len); + unsigned char *buf = my.rxBuf; + + if(serial_recv(&pgm->fd, buf, 512) >= 0) { // Read response + if(buf[0] == 0x0D) { + return 0; + } + } + return -1; +} + +// UPDI-specific function providing a reduced overhead when reading a single byte +static int pickit5_updi_read_byte(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, unsigned char *value) { + if(mem_is_sram(mem) || mem_is_io(mem) + || mem_is_lock(mem) || mem_is_in_fuses(mem)) { + if(mem->size < 1 || addr > (unsigned long) mem->size) { + pmsg_error("address %i out of range for %s [0, %i]\n", (unsigned) addr, mem->desc, mem->size); + return -1; + } + addr += mem->offset; + pmsg_debug("%s(0x%4X)\n", __func__, (unsigned int) addr); + // This script is based on ReadSIB; reduces overhead by avoiding readind data EP + const unsigned char h_len = 24; // 16 + 8 + const unsigned char p_len = 4; + const unsigned char s_len = 6; + const unsigned char m_len = h_len + p_len + s_len; + + unsigned char read8_fast[] = { + 0x00, 0x01, 0x00, 0x00, // [0] SCR_CMD + 0x00, 0x00, 0x00, 0x00, // [4] always 0 + m_len, 0x00, 0x00, 0x00, // [8] message length = 16 + 8 + param (4) + script (6) = 34 + 0x00, 0x00, 0x00, 0x00, // [12] keep at 0 to receive the data in the "response" + + p_len, 0x00, 0x00, 0x00, // [16] param length: 4 bytes + s_len, 0x00, 0x00, 0x00, // [20] length of script: 6 bytes + + 0x00, 0x00, 0x00, 0x00, // [24] param: address to read from, will be overwritten + + // Script itself: + 0x91, 0x00, // Copy first 4 bytes of param to reg 0 + 0x1E, 0x03, 0x00, // Load byte from address in reg 0 + 0x9F // Send data from 0x1E to "response" + }; + read8_fast[24] = (((unsigned char *) &addr)[0]); + read8_fast[25] = (((unsigned char *) &addr)[1]); + + serial_send(&pgm->fd, read8_fast, m_len); + unsigned char *buf = my.rxBuf; + + if(serial_recv(&pgm->fd, buf, 512) >= 0) { // Read response + if(buf[0] == 0x0D) { + if(buf[20] == 0x01) { + *value = buf[24]; + return 0; + } + } + } + return -1; + } else { // Fall back to standard function + int rc = pickit5_read_array(pgm, p, mem, addr, 1, value); + + if(rc < 0) + return rc; + return 0; + } +} + +// Return numbers of byte written +static int pickit5_write_array(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, int len, unsigned char *value) { + pmsg_debug("%s(%s, 0x%04x, %i)", __func__, mem->desc, (unsigned int) addr, len); + + if(len > mem->size || mem->size < 1) { + pmsg_error("cannot write to %s %s owing to its size %d\n", p->desc, mem->desc, mem->size); + return -1; + } + if(addr >= (unsigned long) mem->size) { + pmsg_error("cannot write to %s %s as address 0x%04lx outside range [0, 0x%04x]\n", + p->desc, mem->desc, addr, mem->size - 1); + return -1; + } + + const unsigned char *write_bytes = NULL; + unsigned int write_bytes_len = 0; + + if((mem_is_in_flash(mem) && (len == mem->page_size))) { + write_bytes = my.scripts.WriteProgmem; + write_bytes_len = my.scripts.WriteProgmem_len; + } else if(mem_is_eeprom(mem)) { + write_bytes = my.scripts.WriteDataEEmem; + write_bytes_len = my.scripts.WriteDataEEmem_len; + } else if(mem_is_user_type(mem)) { + write_bytes = my.scripts.WriteIDmem; + write_bytes_len = my.scripts.WriteIDmem_len; + } else if(mem_is_in_fuses(mem)) { + write_bytes = my.scripts.WriteConfigmem; + write_bytes_len = my.scripts.WriteConfigmem_len; + } else if(!mem_is_readonly(mem)) { // SRAM, IO, LOCK + if((len == 1) && (pgm->prog_modes == PM_UPDI)) { + return pickit5_updi_write_byte(pgm, p, mem, addr, value[0]); + } + write_bytes = my.scripts.WriteMem8; + write_bytes_len = my.scripts.WriteMem8_len; + } else { + pmsg_error("unsupported memory %s\n", mem->desc); + return -2; + } + addr += mem->offset; + + unsigned char buf[8]; + + pickit5_uint32_to_array(&buf[0], addr); + pickit5_uint32_to_array(&buf[4], len); + + if(pickit5_send_script(pgm, SCR_DOWNLOAD, write_bytes, write_bytes_len, buf, 8, len) < 0) { + pmsg_error("sending script failed\n"); + return -1; + } + + if(pickit5_read_response(pgm, "Write Bytes") < 0) { + pmsg_error("reading script response failed\n"); + return -1; + } + if(usbdev_data_send(&pgm->fd, value, len) < 0) { + pmsg_error("failed when sending data\n"); + return -1; + } + if(pickit5_get_status(pgm, CHECK_ERROR) < 0) { + pmsg_error("error check failed\n"); + return -1; + } + if(pickit5_send_script_done(pgm, "Write Bytes") < 0) { + pmsg_error("sending script done message failed\n"); + return -1; + } + return len; +} + +// Return numbers of byte read +static int pickit5_read_array(const PROGRAMMER *pgm, const AVRPART *p, + const AVRMEM *mem, unsigned long addr, int len, unsigned char *value) { + pmsg_debug("%s(%u, %u)\n", __func__, (unsigned) addr, len); + + if(len > mem->size || mem->size < 1) { + pmsg_error("cannot read from %s %s owing to its size %d\n", p->desc, mem->desc, mem->size); + return -1; + } + if(addr >= (unsigned long) mem->size) { + pmsg_error("cannot read from %s %s as address 0x%04lx outside range [0, 0x%04x]\n", + p->desc, mem->desc, addr, mem->size - 1); + return -1; + } + + const unsigned char *read_bytes = NULL; + unsigned int read_bytes_len = 0; + + if(mem_is_in_flash(mem)) { + read_bytes = my.scripts.ReadProgmem; + read_bytes_len = my.scripts.ReadProgmem_len; + } else if(mem_is_eeprom(mem)) { + read_bytes = my.scripts.ReadDataEEmem; + read_bytes_len = my.scripts.ReadDataEEmem_len; + } else if(mem_is_user_type(mem)) { + read_bytes = my.scripts.ReadIDmem; + read_bytes_len = my.scripts.ReadIDmem_len; + } else if(mem_is_sib(mem)) { + if(len == 1) { + *value = my.sib_string[addr]; + return 0; + } else if(len == 32) { + memcpy(value, my.sib_string, 32); + return 32; + } + return -1; + } else if(mem_is_signature(mem)) { + if(len == 1) { + *value = my.devID[addr]; + return 0; + } + return -1; + } else if(mem_is_in_sigrow(mem) || mem_is_user_type(mem) || mem_is_a_fuse(mem)) { + read_bytes = my.scripts.ReadConfigmem; + read_bytes_len = my.scripts.ReadConfigmem_len; + } else if(!mem_is_readonly(mem)) { // SRAM, IO, LOCK, USERROW + if((len == 1) && (pgm->prog_modes == PM_UPDI)) { + return pickit5_updi_read_byte(pgm, p, mem, addr, value); + } + read_bytes = my.scripts.ReadMem8; + read_bytes_len = my.scripts.ReadMem8_len; + } else { + pmsg_error("unsupported memory %s\n", mem->desc); + return -2; + } + + addr += mem->offset; + unsigned char buf[8]; + + pickit5_uint32_to_array(&buf[0], addr); + pickit5_uint32_to_array(&buf[4], len); + + if(pickit5_send_script(pgm, SCR_UPLOAD, read_bytes, read_bytes_len, buf, 8, len) < 0) { + pmsg_error("sending script failed\n"); + return -1; + } + if(pickit5_read_response(pgm, "Read Bytes") < 0) { + pmsg_error("unexpected read response\n"); + return -1; + } + if(usbdev_data_recv(&pgm->fd, value, len) < 0) { + pmsg_error("reading data memory failed\n"); + return -1; + } + if(pickit5_send_script_done(pgm, "Read Bytes") < 0) { + pmsg_error("sending script done message failed\n"); + return -1; + } + return len; +} + +static int pickit5_read_dev_id(const PROGRAMMER *pgm, const AVRPART *p) { + pmsg_debug("%s()\n", __func__); + const unsigned char *read_id = my.scripts.GetDeviceID; // Defaults + unsigned int read_id_len = my.scripts.GetDeviceID_len; + + if(my.nvm_version >= '0' && my.nvm_version <= '9') { + read_id = get_devid_script_by_nvm_ver(my.nvm_version); // Only address changes, not length + } + + if(pickit5_send_script(pgm, SCR_CMD, read_id, read_id_len, NULL, 0, 0) < 0) + return -1; + if(pickit5_read_response(pgm, "Read Device ID") >= 0) { + if(my.rxBuf[0] == 0x0D) { + if(my.rxBuf[20] == 0x04) { + memcpy(my.devID, &my.rxBuf[24], 4); + return 0; + } else { + if(my.hvupdi_enabled && p->hvupdi_variant == HV_UPDI_VARIANT_2) { + pmsg_info("failed to get DeviceID with activated HV Pulse on RST\n"); + pmsg_info("if the wiring is correct, try connecting a 16 V, 1 uF cap between RST and GND\n"); + } + } + } + } + return -1; +} + +static int pickit5_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib) { + pmsg_debug("%s()\n", __func__); + const unsigned char *read_sib = my.scripts.ReadSIB; + unsigned int read_sib_len = my.scripts.ReadSIB_len; + + if(pickit5_send_script(pgm, SCR_CMD, read_sib, read_sib_len, NULL, 0, 0) < 0) + return -1; + if(pickit5_read_response(pgm, "Read SIB") < 0) + return -1; + unsigned int ret_len = pickit5_array_to_uint32(&(my.rxBuf[20])); + + if(ret_len == 32) { + memcpy(sib, &my.rxBuf[24], 32); + sib[31] = 0x00; // Known zero-terminator + my.nvm_version = sib[10]; + return 0; + } + my.nvm_version = 0xFF; + return -1; +} + +static int pickit5_read_chip_rev(const PROGRAMMER *pgm, const AVRPART *p, unsigned char *chip_rev) { + pmsg_debug("%s()\n", __func__); + *chip_rev = my.devID[3]; + return 0; +} + +static int pickit5_write_cs_reg(const PROGRAMMER *pgm, unsigned int addr, unsigned char value) { + pmsg_debug("%s(%u, %i)", __func__, addr, value); + const unsigned char *write_cs = my.scripts.WriteCSreg; + unsigned int write_cs_len = my.scripts.WriteCSreg_len; + + if(addr > 0x0C) { + pmsg_error("CS reg %i out of range [0x00, 0x0C], addr\n", addr); + return -1; + } + + unsigned char buf[2]; + + buf[0] = addr; + buf[1] = value; + + if(pickit5_send_script(pgm, SCR_CMD, write_cs, write_cs_len, buf, 2, 0) < 0) { + pmsg_error("sending script failed\n"); + return -1; + } + + if(pickit5_read_response(pgm, "Write CS reg") < 0) { + pmsg_error("reading script response failed\n"); + return -1; + } + return 1; +} + +static int pickit5_read_cs_reg(const PROGRAMMER *pgm, unsigned int addr, unsigned char *value) { + pmsg_debug("%s(%i)\n", __func__, addr); + const unsigned char *read_cs = my.scripts.ReadCSreg; + unsigned int read_cs_len = my.scripts.ReadCSreg_len; + + if(addr > 0x0C) { + pmsg_error("CS reg %i out of range [0x00, 0x0C], addr\n", addr); + return -1; + } + + unsigned char buf[1]; + + buf[0] = addr; + + if(pickit5_send_script(pgm, SCR_UPLOAD, read_cs, read_cs_len, buf, 1, 1) < 0) { + pmsg_error("sending script failed\n"); + return -1; + } + if(pickit5_read_response(pgm, "Read CS") < 0) { + pmsg_error("unexpected read response\n"); + return -1; + } + if(usbdev_data_recv(&pgm->fd, value, 1) < 0) { + pmsg_error("reading CS memory failed\n"); + return -1; + } + if(pickit5_send_script_done(pgm, "Read CS") < 0) { + pmsg_error("sending script done message failed\n"); + return -1; + } + return 0; +} + +static int pickit5_get_fw_info(const PROGRAMMER *pgm) { + pmsg_debug("%s()\n", __func__); + unsigned char *buf = my.rxBuf; + const unsigned char get_fw[] = { 0xE1 }; + + if(serial_send(&pgm->fd, get_fw, 1) < 0) { + pmsg_error("sending command via serial_send() failed\n"); + return -1; + } + + if(serial_recv(&pgm->fd, buf, 512) < 0) { + pmsg_error("receiving FW response failed\n"); + return -1; + } + + if(buf[0] != 0xE1) { + pmsg_error("unexpected device response for get firmware info command\n"); + return -1; + } + + memcpy(my.app_version, &(my.rxBuf[3]), 3); + memcpy(my.fw_info, &(my.rxBuf[7]), 16); + memcpy(my.sernum_string, &(my.rxBuf[32]), 20); + my.sernum_string[19] = 0; // Known zero-terminator + return 0; +} + +static int pickit5_set_vtarget(const PROGRAMMER *pgm, double v) { + if(my.pgm_type >= PGM_TYPE_SNAP) // SNAP can't supply power, ignore + return 0; + + unsigned char set_vtarget[] = { + 0x40, + 0x00, 0x00, 0x00, 0x00, // Vdd + 0x00, 0x00, 0x00, 0x00, // Vpp + 0x00, 0x00, 0x00, 0x00, // Vpp_op + 0x42, 0x43, + }; + unsigned char power_source[] = { + 0x46, 0x00, 0x00, 0x00, 0x00, + }; + unsigned char disable_power[] = { + 0x44 + }; + + if(v < 1.0) { // Anything below 1 V equals disabling Power + pmsg_debug("%s(disable)\n", __func__); + if(pickit5_send_script(pgm, SCR_CMD, power_source, 5, NULL, 0, 0) < 0) + return -1; + if(pickit5_read_response(pgm, "Select external power source") < 0) + return -1; + + if(pickit5_send_script(pgm, SCR_CMD, disable_power, 1, NULL, 0, 0) < 0) + return -1; + if(pickit5_read_response(pgm, "Disabling Power") < 0) + return -1; + usleep(50000); // There might be some caps, let them discharge + } else { + pmsg_debug("%s(%1.2f V)\n", __func__, v); + power_source[1] = 0x01; + if(pickit5_send_script(pgm, SCR_CMD, power_source, 5, NULL, 0, 0) < 0) + return -1; + if(pickit5_read_response(pgm, "Select internal power source") < 0) + return -1; + + int vtarg = (int) (v * 1000.0); + + pickit5_uint32_to_array(&set_vtarget[1], vtarg); + pickit5_uint32_to_array(&set_vtarget[5], vtarg); + pickit5_uint32_to_array(&set_vtarget[9], vtarg); + + if(pickit5_send_script(pgm, SCR_CMD, set_vtarget, 15, NULL, 0, 0) < 0) + return -1; + + if(pickit5_read_response(pgm, "set_vtarget") < 0) + return -1; + } + return 0; +} + +static int pickit5_get_vtarget(const PROGRAMMER *pgm, double *v) { + const unsigned char get_vtarget[] = { 0x47, }; + unsigned char *buf = my.rxBuf; + + pmsg_debug("%s()\n", __func__); + + if(pickit5_send_script(pgm, SCR_CMD, get_vtarget, 1, NULL, 0, 0) < 0) + return -1; + + if(pickit5_read_response(pgm, "get_vtarget") < 0) + return -1; + + // 24 - internal Vdd [mV] + // 28 - target Vdd [mV] + // 48 - Vdd Current Sense [mA] + my.measured_vcc = pickit5_array_to_uint32(&buf[28]) / 1000.0; + my.measured_current = pickit5_array_to_uint32(&buf[48]); + + pmsg_notice("target Vdd: %1.2f V, target current: %u mA\n", my.measured_vcc, my.measured_current); + + if(v != NULL) + *v = my.measured_vcc; + return 0; +} + +static int pickit5_set_ptg_mode(const PROGRAMMER *pgm) { + if(my.pgm_type >= PGM_TYPE_SNAP) // Don't bother if Programmer doesn't support PTG + return 0; // Side note: Bitmask would be probably better in the future + + unsigned char ptg_mode[] = { + 0x5E, 0x00, 0x00, 0x00, 0x00, + }; + unsigned char buf[8]; + + pmsg_debug("%s()\n", __func__); + + if(pickit5_send_script(pgm, SCR_UPLOAD, ptg_mode, 5, NULL, 0, 4) < 0) + return -1; + if(pickit5_read_response(pgm, "Set PTG mode") < 0) + return -1; + + if(usbdev_data_recv(&pgm->fd, buf, 4) < 0) + return -1; + if(pickit5_send_script_done(pgm, "Set PTG Mode") < 0) + return -1; + return 0; +} + +static int pickit5_get_status(const PROGRAMMER *pgm, unsigned char status) { + unsigned char *buf = my.txBuf; + const unsigned int type = 0x0105; + unsigned int key_len = 0; + + if(CHECK_ERROR == status) { + key_len = strlen("ERROR_STATUS_KEY") + 1; + memcpy(&buf[16], "ERROR_STATUS_KEY", key_len); + } else if(BIST_TEST == status) { + key_len = strlen("BIST Tested") + 1; + memcpy(&buf[16], "BIST Tested", key_len); + } else if(BIST_RESULT == status) { + key_len = strlen("BIST Results") + 1; + memcpy(&buf[16], "BIST Results", key_len); + } + if(0 == key_len) { + pmsg_error("unknown key type %d passed to %s()", status, __func__); + return -1; + } + unsigned int msg_len = 16 + key_len; + + pickit5_create_payload_header(buf, type, msg_len, 0); + serial_send(&pgm->fd, buf, msg_len); + serial_recv(&pgm->fd, my.rxBuf, 512); + if(pickit5_check_ret_status(pgm) < 0) { + return -1; + } + unsigned int status_len = pickit5_array_to_uint32(&(my.rxBuf[8])); + + if(status_len > 64) + status_len = 64; + my.rxBuf[16 + status_len] = 0x00; // Known zero-terminator + if(str_starts((const char *) &(my.rxBuf[16]), "NONE") == 0) { + pmsg_error("PICkit error status report: %s", buf); + return -1; + } + return 0; +} + +inline static int pickit5_check_ret_status(const PROGRAMMER *pgm) { + unsigned char ret = my.rxBuf[0]; + + if(0x0D != ret) { + pmsg_error("PICkit5 bad response %i", ret); + return -1; + } + return 0; +} + +void pickit5_initpgm(PROGRAMMER *pgm) { + strcpy(pgm->type, "pickit5"); + + // Mandatory functions + pgm->initialize = pickit5_initialize; + pgm->parseextparams = pickit5_parseextparms; + pgm->display = pickit5_display; + pgm->enable = pickit5_enable; + pgm->disable = pickit5_disable; + pgm->program_enable = pickit5_program_enable; + pgm->chip_erase = pickit5_chip_erase; + pgm->cmd = pickit5_cmd; + pgm->open = pickit5_open; + pgm->close = pickit5_close; + pgm->write_byte = pickit5_write_byte; + pgm->read_byte = pickit5_read_byte; + + // Optional functions + pgm->paged_write = pickit5_paged_write; + pgm->paged_load = pickit5_paged_load; + pgm->setup = pickit5_setup; + pgm->teardown = pickit5_teardown; + pgm->set_sck_period = pickit5_set_sck_period; + pgm->end_programming = pickit5_program_disable; + pgm->read_sib = pickit5_read_sib; + pgm->read_chip_rev = pickit5_read_chip_rev; + pgm->set_vtarget = pickit5_set_vtarget; + pgm->get_vtarget = pickit5_get_vtarget; + pgm->print_parms = pickit5_print_parms; + +} + +#if defined(HAVE_USB_H) +static int usb_fill_buf(const union filedescriptor *fd, int maxsize, int ep, int use_interrupt_xfer) { + int rv = (use_interrupt_xfer? usb_interrupt_read: usb_bulk_read)(fd->usb.handle, ep, cx->usb_buf, + maxsize, 10000); + + if(rv < 0) { + pmsg_notice2("%s(): usb_%s_read() error: %s\n", __func__, + use_interrupt_xfer? "interrupt": "bulk", usb_strerror()); + return -1; + } + + cx->usb_buflen = rv; + cx->usb_bufptr = 0; + + return 0; +} + +static int usbdev_data_recv(const union filedescriptor *fd, unsigned char *buf, size_t nbytes) { + int i, amnt; + unsigned char *p = buf; + + if(fd->usb.handle == NULL) + return -1; + + for(i = 0; nbytes > 0;) { + if(cx->usb_buflen <= cx->usb_bufptr) { + if(usb_fill_buf(fd, fd->usb.max_xfer, USB_PK5_DATA_READ_EP, fd->usb.use_interrupt_xfer) < 0) + return -1; + } + amnt = cx->usb_buflen - cx->usb_bufptr > (int) nbytes? (int) nbytes: cx->usb_buflen - cx->usb_bufptr; + memcpy(buf + i, cx->usb_buf + cx->usb_bufptr, amnt); + cx->usb_bufptr += amnt; + nbytes -= amnt; + i += amnt; + } + + if(verbose > 4) + trace_buffer(__func__, p, i); + + return 0; +} + +static int usbdev_data_send(const union filedescriptor *fd, const unsigned char *bp, size_t mlen) { + int rv; + int i = mlen; + const unsigned char *p = bp; + int tx_size; + + if(fd->usb.handle == NULL) + return -1; + + /* + * Split the frame into multiple packets. It's important to make sure we + * finish with a short packet, or else the device won't know the frame is + * finished. For example, if we need to send 64 bytes, we must send a packet + * of length 64 followed by a packet of length 0. + */ + do { + tx_size = ((int) mlen < fd->usb.max_xfer)? (int) mlen: fd->usb.max_xfer; + if(fd->usb.use_interrupt_xfer) + rv = usb_interrupt_write(fd->usb.handle, USB_PK5_DATA_WRITE_EP, (char *) bp, tx_size, 10000); + else + rv = usb_bulk_write(fd->usb.handle, USB_PK5_DATA_WRITE_EP, (char *) bp, tx_size, 10000); + if(rv != tx_size) { + pmsg_error("wrote %d out of %d bytes, err = %s\n", rv, tx_size, usb_strerror()); + return -1; + } + bp += tx_size; + mlen -= tx_size; + } while(mlen > 0); + + if(verbose > 3) + trace_buffer(__func__, p, i); + return 0; +} +#else + +/* + * Allow compiling without throwing dozen errors + * We need libusb so we can access specific Endpoints + * This does not seem to be possible with usbhid + */ + +static int usbdev_data_recv(const union filedescriptor *fd, unsigned char *buf, size_t nbytes) { + return -1; +} + +static int usbdev_data_send(const union filedescriptor *fd, const unsigned char *bp, size_t mlen) { + return -1; +} +#endif + +#else // defined(HAVE_LIBUSB) || defined(HAVE_LIBUSB_1_0) +static int pickit5_nousb_open(PROGRAMMER *pgm, const char *name); + +static int pickit5_nousb_open(PROGRAMMER *pgm, const char *name) { + pmsg_error("no usb support; please compile again with libusb installed\n"); + + return -1; +} + +void pickit5_initpgm(PROGRAMMER *pgm) { + strcpy(pgm->type, "pickit5"); + + pgm->open = pickit5_nousb_open; +} +#endif // defined(HAVE_USB_H) || defined(HAVE_LUSB0_USB_H) + +const char pickit5_desc[] = "Microchip's PICkit 5 Programmer/Debugger"; diff --git a/src/pickit5.h b/src/pickit5.h new file mode 100644 index 000000000..c6597073f --- /dev/null +++ b/src/pickit5.h @@ -0,0 +1,32 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2024 MX682X + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef pickit5_h +#define pickit5_h + +#ifdef __cplusplus +extern "C" { +#endif + +extern const char pickit5_desc[]; +void pickit5_initpgm(PROGRAMMER *pgm); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/pickit5_lut.h b/src/pickit5_lut.h new file mode 100644 index 000000000..27b4c3327 --- /dev/null +++ b/src/pickit5_lut.h @@ -0,0 +1,83 @@ +/* This file was auto-generated by scripts_decoder.py, any changes will be overwritten */ + +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2024 MX682X + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef pickit5_lut_h +#define pickit5_lut_h + +#ifdef __cplusplus + extern "C" { +#endif + +struct avr_script_lut { + const unsigned char *EnterProgMode; + unsigned int EnterProgMode_len; + const unsigned char *EnterProgModeHvSp; + unsigned int EnterProgModeHvSp_len; + const unsigned char *EnterProgModeHvSpRst; + unsigned int EnterProgModeHvSpRst_len; + const unsigned char *EnterProgModeHvUpt; + unsigned int EnterProgModeHvUpt_len; + const unsigned char *ExitProgMode; + unsigned int ExitProgMode_len; + const unsigned char *SetSpeed; + unsigned int SetSpeed_len; + const unsigned char *GetDeviceID; + unsigned int GetDeviceID_len; + const unsigned char *EraseChip; + unsigned int EraseChip_len; + const unsigned char *WriteProgmem; + unsigned int WriteProgmem_len; + const unsigned char *ReadProgmem; + unsigned int ReadProgmem_len; + const unsigned char *WriteDataEEmem; + unsigned int WriteDataEEmem_len; + const unsigned char *ReadDataEEmem; + unsigned int ReadDataEEmem_len; + const unsigned char *WriteCSreg; + unsigned int WriteCSreg_len; + const unsigned char *ReadCSreg; + unsigned int ReadCSreg_len; + const unsigned char *WriteMem8; + unsigned int WriteMem8_len; + const unsigned char *ReadMem8; + unsigned int ReadMem8_len; + const unsigned char *WriteConfigmem; + unsigned int WriteConfigmem_len; + const unsigned char *ReadConfigmem; + unsigned int ReadConfigmem_len; + const unsigned char *WriteIDmem; + unsigned int WriteIDmem_len; + const unsigned char *ReadIDmem; + unsigned int ReadIDmem_len; + const unsigned char *ReadSIB; + unsigned int ReadSIB_len; + +}; + +typedef struct avr_script_lut SCRIPT; +const unsigned char * get_devid_script_by_nvm_ver(unsigned char version); +int get_pickit_updi_script(SCRIPT *scr, const char *partdesc); + +#ifdef __cplusplus +} +#endif + +#endif // pickit5_lut_h diff --git a/src/pickit5_updi_lut.c b/src/pickit5_updi_lut.c new file mode 100644 index 000000000..d279f576f --- /dev/null +++ b/src/pickit5_updi_lut.c @@ -0,0 +1,1110 @@ +/* This file was auto-generated by scripts_decoder.py, any changes will be overwritten */ + +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2024 MX682X + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "pickit5_lut.h" + + +const unsigned char EnterProgMode_0[294] = { + 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x00, 0x1e, 0x01, 0x00, 0x01, 0xfd, 0x19, 0x00, 0x00, 0x00, 0x08, + 0x01, 0x94, 0x32, 0x00, 0x94, 0x40, 0x00, 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, 0x66, + 0x01, 0x08, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x08, 0x00, 0x00, 0x00, 0x26, 0x01, 0x9b, 0x00, 0x08, + 0x9b, 0x01, 0x59, 0x1e, 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x00, 0x65, 0x20, 0x67, 0x6f, 0x72, 0x04, + 0x65, 0x50, 0x4d, 0x56, 0x4e, 0x04, 0x1e, 0x11, 0x01, 0x9b, 0x02, 0x07, 0x1e, 0x0e, 0x02, 0x6c, + 0x03, 0x66, 0x03, 0x10, 0x00, 0x00, 0x00, 0x9b, 0x04, 0x10, 0xfc, 0x03, 0x04, 0x1e, 0x01, 0x9b, + 0x00, 0x08, 0x9b, 0x01, 0x59, 0x1e, 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x0b, 0xa2, 0x1e, 0x0e, 0x01, + 0xa5, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x9b, 0x00, 0x08, 0x9b, 0x01, + 0x00, 0x1e, 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x0b, 0xa2, 0x1e, 0x0e, 0x01, 0xa5, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x94, 0x48, 0x00, 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, + 0x6c, 0x01, 0x66, 0x01, 0x08, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x08, 0x00, 0x00, 0x00, 0x26, 0x01, + 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0xfe, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x13, 0x01, 0x6c, 0x01, 0x66, 0x01, 0x02, 0x00, 0x00, 0x00, 0xfe, 0x01, + 0x02, 0x00, 0x00, 0x00, 0x13, 0x01, 0x9b, 0x01, 0x0c, 0x1e, 0x0e, 0x01, 0x6c, 0x02, 0x66, 0x02, + 0x04, 0x00, 0x00, 0x00, 0xfe, 0x02, 0x04, 0x00, 0x00, 0x00, 0x13, 0x01, 0x94, 0xf4, 0x01, 0x9b, + 0x01, 0x0c, 0x1e, 0x0e, 0x01, 0x6c, 0x02, 0x66, 0x02, 0x04, 0x00, 0x00, 0x00, 0xfe, 0x02, 0x04, + 0x00, 0x00, 0x00, 0x13, 0x01, 0xfb, 0x1e, 0x01, 0x90, 0x01, 0x51, 0x00, 0x00, 0x00, 0x7f, 0x01, + 0xfb, 0x26, 0x01, 0x90, 0x01, 0x44, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xfb, 0x26, 0x01, 0x90, 0x01, + 0x00, 0x01, 0x00, 0x00, 0x7f, 0x01, +}; + +const unsigned char EnterProgModeHvSp_0[339] = { + 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x01, 0x1e, 0x01, 0x00, 0x01, 0xfd, 0x54, 0x00, 0x00, 0x00, 0x3a, + 0x01, 0xfd, 0x08, 0x03, 0x00, 0x00, 0x45, 0x01, 0xfd, 0x09, 0x03, 0x00, 0x00, 0x48, 0x01, 0xfd, + 0x19, 0x00, 0x00, 0x00, 0x24, 0x01, 0xfd, 0x1b, 0x00, 0x00, 0x00, 0x24, 0x01, 0x94, 0x32, 0x00, + 0x94, 0x40, 0x00, 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, 0x08, 0x00, 0x00, + 0x00, 0xfe, 0x01, 0x08, 0x00, 0x00, 0x00, 0x53, 0x01, 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x59, 0x1e, + 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x00, 0x65, 0x20, 0x67, 0x6f, 0x72, 0x04, 0x65, 0x50, 0x4d, 0x56, + 0x4e, 0x04, 0x1e, 0x11, 0x01, 0x9b, 0x02, 0x07, 0x1e, 0x0e, 0x02, 0x6c, 0x03, 0x66, 0x03, 0x10, + 0x00, 0x00, 0x00, 0x9b, 0x04, 0x10, 0xfc, 0x03, 0x04, 0x4b, 0x01, 0x9b, 0x00, 0x08, 0x9b, 0x01, + 0x59, 0x1e, 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x0b, 0xa2, 0x1e, 0x0e, 0x01, 0xa5, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x00, 0x1e, 0x0f, 0x00, + 0x01, 0x9b, 0x01, 0x0b, 0xa2, 0x1e, 0x0e, 0x01, 0xa5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x94, 0x48, 0x00, 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, + 0x08, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x08, 0x00, 0x00, 0x00, 0x53, 0x01, 0x9b, 0x00, 0x0b, 0x1e, + 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x2f, 0x01, 0x6c, 0x01, 0x66, 0x01, 0x02, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x2f, 0x01, 0x9b, 0x01, 0x0c, 0x1e, 0x0e, 0x01, 0x6c, 0x02, 0x66, 0x02, 0x04, 0x00, 0x00, 0x00, + 0xfe, 0x02, 0x04, 0x00, 0x00, 0x00, 0x2f, 0x01, 0x94, 0xf4, 0x01, 0x9b, 0x01, 0x0c, 0x1e, 0x0e, + 0x01, 0x6c, 0x02, 0x66, 0x02, 0x04, 0x00, 0x00, 0x00, 0xfe, 0x02, 0x04, 0x00, 0x00, 0x00, 0x2f, + 0x01, 0xfb, 0x4b, 0x01, 0x90, 0x01, 0x51, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xfb, 0x53, 0x01, 0x90, + 0x01, 0x44, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xfb, 0x53, 0x01, 0x90, 0x01, 0x54, 0x00, 0x00, 0x00, + 0x7f, 0x01, 0xfb, 0x53, 0x01, 0xfb, 0x53, 0x01, 0xfb, 0x53, 0x01, 0x90, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x7f, 0x01, +}; + +const unsigned char EnterProgModeHvSpRst_0[325] = { + 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x05, 0x1e, 0x01, 0x00, 0x01, 0xfd, 0x54, 0x00, 0x00, 0x00, 0x2c, + 0x01, 0xfd, 0x08, 0x03, 0x00, 0x00, 0x37, 0x01, 0xfd, 0x09, 0x03, 0x00, 0x00, 0x3a, 0x01, 0x94, + 0x32, 0x00, 0x94, 0x40, 0x00, 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, 0x08, + 0x00, 0x00, 0x00, 0xfe, 0x01, 0x08, 0x00, 0x00, 0x00, 0x45, 0x01, 0x9b, 0x00, 0x08, 0x9b, 0x01, + 0x59, 0x1e, 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x00, 0x65, 0x20, 0x67, 0x6f, 0x72, 0x04, 0x65, 0x50, + 0x4d, 0x56, 0x4e, 0x04, 0x1e, 0x11, 0x01, 0x9b, 0x02, 0x07, 0x1e, 0x0e, 0x02, 0x6c, 0x03, 0x66, + 0x03, 0x10, 0x00, 0x00, 0x00, 0x9b, 0x04, 0x10, 0xfc, 0x03, 0x04, 0x3d, 0x01, 0x9b, 0x00, 0x08, + 0x9b, 0x01, 0x59, 0x1e, 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x0b, 0xa2, 0x1e, 0x0e, 0x01, 0xa5, 0x20, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x00, 0x1e, + 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x0b, 0xa2, 0x1e, 0x0e, 0x01, 0xa5, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0a, 0x00, 0x94, 0x48, 0x00, 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, + 0x66, 0x01, 0x08, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x08, 0x00, 0x00, 0x00, 0x45, 0x01, 0x9b, 0x00, + 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x21, 0x01, 0x6c, 0x01, 0x66, 0x01, 0x02, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x02, 0x00, + 0x00, 0x00, 0x21, 0x01, 0x9b, 0x01, 0x0c, 0x1e, 0x0e, 0x01, 0x6c, 0x02, 0x66, 0x02, 0x04, 0x00, + 0x00, 0x00, 0xfe, 0x02, 0x04, 0x00, 0x00, 0x00, 0x21, 0x01, 0x94, 0xf4, 0x01, 0x9b, 0x01, 0x0c, + 0x1e, 0x0e, 0x01, 0x6c, 0x02, 0x66, 0x02, 0x04, 0x00, 0x00, 0x00, 0xfe, 0x02, 0x04, 0x00, 0x00, + 0x00, 0x21, 0x01, 0xfb, 0x3d, 0x01, 0x90, 0x01, 0x51, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xfb, 0x45, + 0x01, 0x90, 0x01, 0x44, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xfb, 0x45, 0x01, 0x90, 0x01, 0x54, 0x00, + 0x00, 0x00, 0x7f, 0x01, 0xfb, 0x45, 0x01, 0xfb, 0x45, 0x01, 0xfb, 0x45, 0x01, 0x90, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x7f, 0x01, +}; + +const unsigned char EnterProgModeHvUpt_0[339] = { + 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x03, 0x1e, 0x01, 0x00, 0x01, 0xfd, 0x54, 0x00, 0x00, 0x00, 0x3a, + 0x01, 0xfd, 0x08, 0x03, 0x00, 0x00, 0x45, 0x01, 0xfd, 0x09, 0x03, 0x00, 0x00, 0x48, 0x01, 0xfd, + 0x19, 0x00, 0x00, 0x00, 0x24, 0x01, 0xfd, 0x1b, 0x00, 0x00, 0x00, 0x24, 0x01, 0x94, 0x32, 0x00, + 0x94, 0x40, 0x00, 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, 0x08, 0x00, 0x00, + 0x00, 0xfe, 0x01, 0x08, 0x00, 0x00, 0x00, 0x53, 0x01, 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x59, 0x1e, + 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x00, 0x65, 0x20, 0x67, 0x6f, 0x72, 0x04, 0x65, 0x50, 0x4d, 0x56, + 0x4e, 0x04, 0x1e, 0x11, 0x01, 0x9b, 0x02, 0x07, 0x1e, 0x0e, 0x02, 0x6c, 0x03, 0x66, 0x03, 0x10, + 0x00, 0x00, 0x00, 0x9b, 0x04, 0x10, 0xfc, 0x03, 0x04, 0x4b, 0x01, 0x9b, 0x00, 0x08, 0x9b, 0x01, + 0x59, 0x1e, 0x0f, 0x00, 0x01, 0x9b, 0x01, 0x0b, 0xa2, 0x1e, 0x0e, 0x01, 0xa5, 0x20, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x00, 0x1e, 0x0f, 0x00, + 0x01, 0x9b, 0x01, 0x0b, 0xa2, 0x1e, 0x0e, 0x01, 0xa5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0a, 0x00, 0x94, 0x48, 0x00, 0x9b, 0x00, 0x0b, 0x1e, 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, + 0x08, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x08, 0x00, 0x00, 0x00, 0x53, 0x01, 0x9b, 0x00, 0x0b, 0x1e, + 0x0e, 0x00, 0x6c, 0x01, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x2f, 0x01, 0x6c, 0x01, 0x66, 0x01, 0x02, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x2f, 0x01, 0x9b, 0x01, 0x0c, 0x1e, 0x0e, 0x01, 0x6c, 0x02, 0x66, 0x02, 0x04, 0x00, 0x00, 0x00, + 0xfe, 0x02, 0x04, 0x00, 0x00, 0x00, 0x2f, 0x01, 0x94, 0xf4, 0x01, 0x9b, 0x01, 0x0c, 0x1e, 0x0e, + 0x01, 0x6c, 0x02, 0x66, 0x02, 0x04, 0x00, 0x00, 0x00, 0xfe, 0x02, 0x04, 0x00, 0x00, 0x00, 0x2f, + 0x01, 0xfb, 0x4b, 0x01, 0x90, 0x01, 0x51, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xfb, 0x53, 0x01, 0x90, + 0x01, 0x44, 0x00, 0x00, 0x00, 0x7f, 0x01, 0xfb, 0x53, 0x01, 0x90, 0x01, 0x54, 0x00, 0x00, 0x00, + 0x7f, 0x01, 0xfb, 0x53, 0x01, 0xfb, 0x53, 0x01, 0xfb, 0x53, 0x01, 0x90, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x7f, 0x01, +}; + +const unsigned char ExitProgMode_0[22] = { + 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x59, 0x1e, 0x0f, 0x00, 0x01, 0x9b, 0x00, 0x08, 0x9b, 0x01, 0x00, + 0x1e, 0x0f, 0x00, 0x01, 0x1e, 0x02, +}; + +const unsigned char SetSpeed_0[5] = { + 0x91, 0x00, 0x1e, 0x14, 0x00, +}; + +const unsigned char GetDeviceID_0[33] = { + 0x95, 0x90, 0x00, 0x00, 0x11, 0x00, 0x00, 0x1e, 0x09, 0x00, 0x9c, 0x01, 0x03, 0x00, 0x1e, 0x10, + 0x01, 0x9b, 0x02, 0x03, 0x1e, 0x0c, 0x02, 0x90, 0x02, 0x01, 0x0f, 0x00, 0x00, 0x1e, 0x03, 0x02, + 0x9f, +}; + +const unsigned char GetDeviceID_1[33] = { + 0x95, 0x90, 0x00, 0x80, 0x10, 0x00, 0x00, 0x1e, 0x09, 0x00, 0x9c, 0x01, 0x03, 0x00, 0x1e, 0x10, + 0x01, 0x9b, 0x02, 0x03, 0x1e, 0x0c, 0x02, 0x90, 0x02, 0x01, 0x0f, 0x00, 0x00, 0x1e, 0x03, 0x02, + 0x9f, +}; + +const unsigned char EraseChip_0[184] = { + 0x94, 0x32, 0x00, 0x94, 0x40, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x65, 0x65, 0x73, 0x61, + 0x72, 0x04, 0x65, 0x45, 0x4d, 0x56, 0x4e, 0x04, 0x1e, 0x11, 0x01, 0x90, 0x02, 0x07, 0x00, 0x00, + 0x00, 0x1e, 0x0e, 0x02, 0x6c, 0x03, 0x66, 0x03, 0x08, 0x00, 0x00, 0x00, 0x90, 0x04, 0x08, 0x00, + 0x00, 0x00, 0xfc, 0x03, 0x04, 0xaf, 0x00, 0x90, 0x00, 0x08, 0x00, 0x00, 0x00, 0x90, 0x01, 0x59, + 0x00, 0x00, 0x00, 0x1e, 0x0f, 0x00, 0x01, 0x90, 0x01, 0x0b, 0x00, 0x00, 0x00, 0xa2, 0x1e, 0x0e, + 0x01, 0xa5, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x90, 0x00, 0x08, 0x00, + 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0f, 0x00, 0x01, 0x90, 0x01, 0x0b, 0x00, + 0x00, 0x00, 0xa2, 0x1e, 0x0e, 0x01, 0xa5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x90, 0x01, 0x0b, 0x00, 0x00, 0x00, 0xa2, 0x94, 0x02, 0x00, 0x1e, 0x0e, 0x01, 0xa5, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x01, 0x1e, 0x0e, 0x01, 0x6c, 0x03, 0x66, 0x03, + 0x40, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x40, 0x00, 0x00, 0x00, 0xaf, 0x00, 0xfb, 0xb7, 0x00, 0x90, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x7f, 0x01, 0x5a, +}; + +const unsigned char WriteProgmem_0[231] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x02, 0x08, 0x10, 0x00, 0x00, 0x1e, 0x03, 0x02, 0x6c, 0x0a, 0x90, + 0x02, 0x09, 0x10, 0x00, 0x00, 0x1e, 0x03, 0x02, 0x6c, 0x0b, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x0f, 0x40, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0x2e, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, + 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, 0x04, 0x00, + 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x10, + 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x7c, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, + 0x04, 0x10, 0x67, 0x04, 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, + 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x6e, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x07, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x0c, 0x0d, 0xd3, 0x00, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, 0x01, + 0x11, 0x20, 0x00, 0x90, 0x02, 0x08, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x0a, 0x90, 0x02, 0x09, + 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x0b, +}; + +const unsigned char WriteProgmem_1[231] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x02, 0x08, 0x10, 0x00, 0x00, 0x1e, 0x03, 0x02, 0x6c, 0x0a, 0x90, + 0x02, 0x09, 0x10, 0x00, 0x00, 0x1e, 0x03, 0x02, 0x6c, 0x0b, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x0f, 0x80, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0x2e, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, + 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, 0x04, 0x00, + 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x10, + 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x7c, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, + 0x04, 0x10, 0x67, 0x04, 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, + 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x6e, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x07, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x0c, 0x0d, 0xd3, 0x00, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, 0x01, + 0x11, 0x20, 0x00, 0x90, 0x02, 0x08, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x0a, 0x90, 0x02, 0x09, + 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x0b, +}; + +const unsigned char WriteProgmem_2[272] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, + 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x11, 0x00, 0x00, + 0x00, 0x00, 0x90, 0x0f, 0x00, 0x02, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0x30, 0x00, 0x60, 0x0f, 0x01, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x06, 0xff, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x06, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, + 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, + 0x06, 0x07, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, + 0xfa, 0x0f, 0x10, 0xa8, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, + 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x9a, 0x00, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0x00, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x22, 0x00, 0x5a, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char WriteProgmem_3[231] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x02, 0x0c, 0x10, 0x00, 0x00, 0x1e, 0x03, 0x02, 0x6c, 0x0a, 0x90, + 0x02, 0x0d, 0x10, 0x00, 0x00, 0x1e, 0x03, 0x02, 0x6c, 0x0b, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x0f, 0x80, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0x2e, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, + 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, 0x0f, 0x00, + 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x10, + 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x7c, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, + 0x04, 0x10, 0x67, 0x04, 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, + 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x6e, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x07, 0x05, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x0c, 0x0d, 0xd3, 0x00, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, 0x01, + 0x11, 0x20, 0x00, 0x90, 0x02, 0x0c, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x0a, 0x90, 0x02, 0x0d, + 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x0b, +}; + +const unsigned char WriteProgmem_4[272] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, + 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x11, 0x00, 0x00, + 0x00, 0x00, 0x90, 0x0f, 0x00, 0x02, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0x30, 0x00, 0x60, 0x0f, 0x01, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x06, 0xff, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x06, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, + 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, + 0x06, 0x07, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, + 0xfa, 0x0f, 0x10, 0xa8, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, + 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x9a, 0x00, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0x00, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x22, 0x00, 0x5a, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char WriteProgmem_5[231] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x02, 0x0c, 0x10, 0x00, 0x00, 0x1e, 0x03, 0x02, 0x6c, 0x0a, 0x90, + 0x02, 0x0d, 0x10, 0x00, 0x00, 0x1e, 0x03, 0x02, 0x6c, 0x0b, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x90, 0x0f, 0x40, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0x2e, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, + 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, 0x0f, 0x00, + 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x10, + 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x7c, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, + 0x04, 0x10, 0x67, 0x04, 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, + 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x6e, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x07, 0x05, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, + 0x00, 0xfc, 0x0c, 0x0d, 0xd3, 0x00, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, 0x01, + 0x11, 0x20, 0x00, 0x90, 0x02, 0x0c, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x0a, 0x90, 0x02, 0x0d, + 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x0b, +}; + +const unsigned char WriteProgmem_6[272] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, + 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x11, 0x00, 0x00, + 0x00, 0x00, 0x90, 0x0f, 0x00, 0x02, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0x30, 0x00, 0x60, 0x0f, 0x01, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x06, 0xff, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x06, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, + 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, + 0x06, 0x07, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, + 0xfa, 0x0f, 0x10, 0xa8, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, + 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x9a, 0x00, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0x00, 0x01, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x22, 0x00, 0x5a, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char ReadProgmem_0[73] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x40, 0x00, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, 0x01, + 0x1e, 0x10, 0x04, 0x1e, 0x0d, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, + 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, 0x11, 0x0b, 0x00, +}; + +const unsigned char ReadProgmem_1[73] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x80, 0x00, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, 0x01, + 0x1e, 0x10, 0x04, 0x1e, 0x0d, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, + 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, 0x11, 0x0b, 0x00, +}; + +const unsigned char ReadProgmem_2[73] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x02, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, 0x01, + 0x1e, 0x10, 0x04, 0x1e, 0x0d, 0x04, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, + 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, 0x11, 0x0b, 0x00, +}; + +const unsigned char WriteDataEEmem_0[208] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x20, 0x00, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, + 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, + 0x04, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x7e, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, + 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x70, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x03, 0x00, 0x00, + 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0xcf, 0x00, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0xaf, +}; + +const unsigned char WriteDataEEmem_1[208] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x40, 0x00, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, + 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, + 0x04, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x7e, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, + 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x70, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x03, 0x00, 0x00, + 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0xcf, 0x00, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0xaf, +}; + +const unsigned char WriteDataEEmem_2[176] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x13, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x4e, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, + 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x40, 0x00, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0xa0, 0x00, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0x5a, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char WriteDataEEmem_3[208] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x08, 0x00, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x03, 0x1f, 0x00, 0x00, 0x00, 0xfe, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, + 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, + 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x7e, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, + 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x70, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x15, 0x00, 0x00, + 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0xcf, 0x00, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0xaf, +}; + +const unsigned char WriteDataEEmem_4[176] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x13, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x4e, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, + 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x40, 0x00, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0xa0, 0x00, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0x5a, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char WriteDataEEmem_5[176] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x01, 0x00, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x13, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x4e, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, + 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, + 0xfc, 0x0f, 0x11, 0x40, 0x00, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, + 0xa0, 0x00, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0x5a, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char ReadDataEEmem_0[67] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x20, 0x00, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0c, 0x10, + 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, + 0x11, 0x0b, 0x00, +}; + +const unsigned char ReadDataEEmem_1[67] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x40, 0x00, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0c, 0x10, + 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, + 0x11, 0x0b, 0x00, +}; + +const unsigned char ReadDataEEmem_2[67] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x01, 0x00, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0c, 0x10, + 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, + 0x11, 0x0b, 0x00, +}; + +const unsigned char ReadDataEEmem_3[67] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x08, 0x00, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0c, 0x10, + 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, + 0x11, 0x0b, 0x00, +}; + +const unsigned char WriteConfigmem_0[369] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x01, 0x00, 0x00, 0x00, + 0x93, 0x00, 0xad, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, + 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x60, 0x03, 0x00, 0x60, + 0x04, 0x00, 0x66, 0x03, 0xff, 0x00, 0x00, 0x00, 0x67, 0x04, 0x08, 0x66, 0x04, 0xff, 0x00, 0x00, + 0x00, 0x90, 0x06, 0x08, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x03, 0x90, 0x06, 0x09, 0x10, 0x00, + 0x00, 0x1e, 0x06, 0x06, 0x04, 0x90, 0x06, 0x06, 0x10, 0x00, 0x00, 0x99, 0x07, 0x1e, 0x06, 0x06, + 0x07, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x07, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, + 0x07, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x92, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, + 0xfb, 0x70, 0x01, 0xad, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, + 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x60, 0x03, 0x00, + 0x60, 0x04, 0x00, 0x66, 0x03, 0xff, 0x00, 0x00, 0x00, 0x67, 0x04, 0x08, 0x66, 0x04, 0xff, 0x00, + 0x00, 0x00, 0x90, 0x06, 0x08, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x03, 0x90, 0x06, 0x09, 0x10, + 0x00, 0x00, 0x1e, 0x06, 0x06, 0x04, 0x90, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, + 0x00, 0x00, 0xee, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, + 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, 0x04, 0x00, + 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x99, 0x07, + 0x1e, 0x06, 0x00, 0x07, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x03, 0x00, 0x00, 0x00, + 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0x70, + 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x92, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, + 0xaf, +}; + +const unsigned char WriteConfigmem_1[128] = { + 0x91, 0x00, 0x91, 0x01, 0xad, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, + 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x13, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x99, 0x03, + 0x1e, 0x06, 0x00, 0x03, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0x70, + 0x00, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x92, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char WriteConfigmem_2[369] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x03, 0x01, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x01, 0x00, 0x00, 0x00, + 0x93, 0x00, 0xad, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, + 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x60, 0x03, 0x00, 0x60, + 0x04, 0x00, 0x66, 0x03, 0xff, 0x00, 0x00, 0x00, 0x67, 0x04, 0x08, 0x66, 0x04, 0xff, 0x00, 0x00, + 0x00, 0x90, 0x06, 0x0c, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x03, 0x90, 0x06, 0x0d, 0x10, 0x00, + 0x00, 0x1e, 0x06, 0x06, 0x04, 0x90, 0x06, 0x08, 0x10, 0x00, 0x00, 0x99, 0x07, 0x1e, 0x06, 0x06, + 0x07, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, + 0x07, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x92, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, + 0xfb, 0x70, 0x01, 0xad, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, + 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x60, 0x03, 0x00, + 0x60, 0x04, 0x00, 0x66, 0x03, 0xff, 0x00, 0x00, 0x00, 0x67, 0x04, 0x08, 0x66, 0x04, 0xff, 0x00, + 0x00, 0x00, 0x90, 0x06, 0x0c, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x03, 0x90, 0x06, 0x0d, 0x10, + 0x00, 0x00, 0x1e, 0x06, 0x06, 0x04, 0x90, 0x03, 0x1f, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, + 0x00, 0x00, 0xee, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, + 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, 0x03, 0x0f, 0x00, + 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x99, 0x07, + 0x1e, 0x06, 0x00, 0x07, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x15, 0x00, 0x00, 0x00, + 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0x70, + 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x92, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, + 0xaf, +}; + +const unsigned char WriteConfigmem_3[128] = { + 0x91, 0x00, 0x91, 0x01, 0xad, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, + 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x13, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x99, 0x03, + 0x1e, 0x06, 0x00, 0x03, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0x70, + 0x00, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x92, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char WriteConfigmem_4[128] = { + 0x91, 0x00, 0x91, 0x01, 0xad, 0x01, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, + 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, + 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x13, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x99, 0x03, + 0x1e, 0x06, 0x00, 0x03, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0x70, + 0x00, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x92, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char ReadConfigmem_0[19] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0xad, 0x01, 0x1e, 0x03, 0x00, 0x9f, 0x92, 0x00, 0x01, 0x00, 0x00, + 0x00, 0xae, 0x5a, +}; + +const unsigned char WriteIDmem_0[421] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x03, 0x01, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x02, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0xfe, 0x03, 0x01, 0x00, 0x00, 0x00, 0xd9, 0x00, 0xfb, 0xa4, 0x01, 0x90, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x90, 0x0f, 0x20, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0xed, 0x00, 0x60, 0x0f, + 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x03, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, + 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x53, 0x01, 0x60, 0x10, 0x0f, 0x1e, + 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, + 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x45, 0x01, 0x90, 0x06, 0x00, 0x10, + 0x00, 0x00, 0x90, 0x07, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xa4, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, + 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0xfc, 0x01, 0x11, 0xdf, 0x00, 0xfb, 0xa4, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, + 0x0f, 0x20, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0xed, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x03, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x90, 0x02, 0x00, 0x10, 0x00, + 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, + 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, + 0x10, 0x00, 0x00, 0x90, 0x03, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, + 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x53, 0x01, + 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, + 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x45, 0x01, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xa4, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, + 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, + 0x01, 0x11, 0xdf, 0x00, 0xaf, +}; + +const unsigned char WriteIDmem_1[421] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x03, 0x01, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x02, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0xfe, 0x03, 0x01, 0x00, 0x00, 0x00, 0xd9, 0x00, 0xfb, 0xa4, 0x01, 0x90, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x90, 0x0f, 0x40, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0xed, 0x00, 0x60, 0x0f, + 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x03, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, + 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x53, 0x01, 0x60, 0x10, 0x0f, 0x1e, + 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, + 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x45, 0x01, 0x90, 0x06, 0x00, 0x10, + 0x00, 0x00, 0x90, 0x07, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xa4, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, + 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0xfc, 0x01, 0x11, 0xdf, 0x00, 0xfb, 0xa4, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, + 0x0f, 0x40, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0xed, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x03, 0x00, + 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x90, 0x02, 0x00, 0x10, 0x00, + 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, + 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, + 0x10, 0x00, 0x00, 0x90, 0x03, 0x04, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x02, + 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x53, 0x01, + 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, + 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x45, 0x01, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x03, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xa4, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, + 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, + 0x01, 0x11, 0xdf, 0x00, 0xaf, +}; + +const unsigned char WriteIDmem_2[266] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x20, 0x00, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x06, 0xff, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x06, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, + 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, + 0x06, 0x07, 0x90, 0x02, 0x02, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, + 0xfa, 0x0f, 0x10, 0xa8, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, + 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x9a, 0x00, 0x6c, + 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xfa, 0x00, 0x90, 0x02, 0x02, 0x10, + 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0x5a, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char WriteIDmem_3[421] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x03, 0x02, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x02, 0x00, 0x00, 0x00, + 0x1d, 0x00, 0xfe, 0x03, 0x01, 0x00, 0x00, 0x00, 0xd9, 0x00, 0xfb, 0xa4, 0x01, 0x90, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x90, 0x0f, 0x40, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0xed, 0x00, 0x60, 0x0f, + 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, 0x10, 0x00, 0x00, 0x90, + 0x03, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, + 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x53, 0x01, 0x60, 0x10, 0x0f, 0x1e, + 0x09, 0x00, 0x60, 0x04, 0x10, 0x67, 0x04, 0x01, 0x1e, 0x10, 0x04, 0x1e, 0x0b, 0x04, 0x6a, 0x0f, + 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x45, 0x01, 0x90, 0x06, 0x00, 0x10, + 0x00, 0x00, 0x90, 0x07, 0x05, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xa4, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, + 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, + 0x00, 0xfc, 0x01, 0x11, 0xdf, 0x00, 0xfb, 0xa4, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, + 0x0f, 0x40, 0x00, 0x00, 0x00, 0xfa, 0x01, 0x0f, 0xed, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x03, 0x1f, + 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x90, 0x02, 0x00, 0x10, 0x00, + 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, + 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x02, 0x00, + 0x10, 0x00, 0x00, 0x90, 0x03, 0x0f, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x02, 0x03, 0x90, 0x02, 0x06, + 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, 0x0f, 0x10, 0x53, 0x01, + 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, 0x10, 0x6a, 0x0f, 0x10, 0x6e, + 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x45, 0x01, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x15, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x6c, 0x0c, 0x90, 0x0d, 0x00, 0x00, + 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xa4, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, + 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xfc, + 0x01, 0x11, 0xdf, 0x00, 0xaf, +}; + +const unsigned char WriteIDmem_4[266] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x02, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x06, 0xff, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x06, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, + 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, + 0x06, 0x07, 0x90, 0x02, 0x06, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, + 0xfa, 0x0f, 0x10, 0xa8, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, + 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x9a, 0x00, 0x6c, + 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xfa, 0x00, 0x90, 0x02, 0x06, 0x10, + 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0x5a, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char WriteIDmem_5[266] = { + 0x91, 0x00, 0x91, 0x01, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x20, 0x00, 0x00, 0x00, + 0xfa, 0x01, 0x0f, 0x18, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, + 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x08, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, + 0x90, 0x06, 0xff, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x00, 0x06, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, + 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, + 0x06, 0x07, 0x90, 0x02, 0x07, 0x10, 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, + 0xfa, 0x0f, 0x10, 0xa8, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0a, + 0x10, 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x9a, 0x00, 0x6c, + 0x0c, 0x90, 0x0d, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0d, 0xfa, 0x00, 0x90, 0x02, 0x07, 0x10, + 0x00, 0x00, 0xa2, 0x1e, 0x03, 0x02, 0x94, 0x02, 0x00, 0xa5, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x14, 0x00, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, + 0x1e, 0x06, 0x06, 0x07, 0xfc, 0x01, 0x11, 0x0a, 0x00, 0x5a, 0x90, 0x06, 0x00, 0x10, 0x00, 0x00, + 0x90, 0x07, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x06, 0x06, 0x07, +}; + +const unsigned char ReadIDmem_0[67] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x20, 0x00, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0c, 0x10, + 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, + 0x11, 0x0b, 0x00, +}; + +const unsigned char ReadIDmem_1[67] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x40, 0x00, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0c, 0x10, + 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, + 0x11, 0x0b, 0x00, +}; + +const unsigned char ReadIDmem_2[67] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0x90, 0x11, 0x00, 0x00, 0x00, 0x00, 0x90, 0x0f, 0x00, 0x02, 0x00, + 0x00, 0xfa, 0x01, 0x0f, 0x19, 0x00, 0x60, 0x0f, 0x01, 0x90, 0x10, 0x00, 0x01, 0x00, 0x00, 0xfa, + 0x0f, 0x10, 0x27, 0x00, 0x60, 0x10, 0x0f, 0x1e, 0x09, 0x00, 0x1e, 0x10, 0x10, 0x1e, 0x0c, 0x10, + 0x6a, 0x0f, 0x10, 0x6e, 0x00, 0x10, 0x6a, 0x01, 0x10, 0xfc, 0x0f, 0x11, 0x19, 0x00, 0xfc, 0x01, + 0x11, 0x0b, 0x00, +}; + +const unsigned char WriteCSreg_0[8] = { + 0x99, 0x00, 0x99, 0x01, 0x1e, 0x0f, 0x00, 0x01, +}; + +const unsigned char ReadCSreg_0[6] = { + 0x99, 0x00, 0x1e, 0x0e, 0x00, 0x9f, +}; + +const unsigned char WriteMem8_0[20] = { + 0x91, 0x00, 0x91, 0x01, 0xad, 0x01, 0x99, 0x03, 0x1e, 0x06, 0x00, 0x03, 0x92, 0x00, 0x01, 0x00, + 0x00, 0x00, 0xae, 0x5a, +}; + +const unsigned char ReadMem8_0[19] = { + 0x91, 0x00, 0x91, 0x01, 0x95, 0xad, 0x01, 0x1e, 0x03, 0x00, 0x9f, 0x92, 0x00, 0x01, 0x00, 0x00, + 0x00, 0xae, 0x5a, +}; + +const unsigned char ReadSIB_0[7] = { + 0x95, 0x9b, 0x00, 0x02, 0x1e, 0x12, 0x00, +}; + + + + +static void pickit_updi_script_init(SCRIPT *scr); +static void pickit_updi_script_init(SCRIPT *scr) { + scr->EnterProgMode = EnterProgMode_0; + scr->EnterProgModeHvSp = EnterProgModeHvSp_0; + scr->EnterProgModeHvSpRst = EnterProgModeHvSpRst_0; + scr->EnterProgModeHvUpt = EnterProgModeHvUpt_0; + scr->ExitProgMode = ExitProgMode_0; + scr->SetSpeed = SetSpeed_0; + scr->GetDeviceID = NULL; + scr->EraseChip = EraseChip_0; + scr->WriteProgmem = NULL; + scr->ReadProgmem = NULL; + scr->WriteDataEEmem = NULL; + scr->ReadDataEEmem = NULL; + scr->WriteConfigmem = NULL; + scr->ReadConfigmem = ReadConfigmem_0; + scr->WriteIDmem = NULL; + scr->ReadIDmem = NULL; + scr->WriteCSreg = WriteCSreg_0; + scr->ReadCSreg = ReadCSreg_0; + scr->WriteMem8 = WriteMem8_0; + scr->ReadMem8 = ReadMem8_0; + scr->ReadSIB = ReadSIB_0; + + scr->EnterProgMode_len = sizeof(EnterProgMode_0); + scr->EnterProgModeHvSp_len = sizeof(EnterProgModeHvSp_0); + scr->EnterProgModeHvSpRst_len = sizeof(EnterProgModeHvSpRst_0); + scr->EnterProgModeHvUpt_len = sizeof(EnterProgModeHvUpt_0); + scr->ExitProgMode_len = sizeof(ExitProgMode_0); + scr->SetSpeed_len = sizeof(SetSpeed_0); + scr->GetDeviceID_len = 0; + scr->EraseChip_len = sizeof(EraseChip_0); + scr->WriteProgmem_len = 0; + scr->ReadProgmem_len = 0; + scr->WriteDataEEmem_len = 0; + scr->ReadDataEEmem_len = 0; + scr->WriteConfigmem_len = 0; + scr->ReadConfigmem_len = sizeof(ReadConfigmem_0); + scr->WriteIDmem_len = 0; + scr->ReadIDmem_len = 0; + scr->WriteCSreg_len = sizeof(WriteCSreg_0); + scr->ReadCSreg_len = sizeof(ReadCSreg_0); + scr->WriteMem8_len = sizeof(WriteMem8_0); + scr->ReadMem8_len = sizeof(ReadMem8_0); + scr->ReadSIB_len = sizeof(ReadSIB_0); +} + + +const char * const pickit5_updi_chip_lut[] = { + "ATtiny416auto", "ATmega1608", "ATmega1609", "ATmega3208", "ATmega3209", "ATmega4808", "ATmega4809", "ATmega808", + "ATmega809", "ATtiny1604", "ATtiny1606", "ATtiny1607", "ATtiny1614", "ATtiny1616", "ATtiny1617", "ATtiny1624", + "ATtiny1626", "ATtiny1627", "ATtiny202", "ATtiny204", "ATtiny212", "ATtiny214", "ATtiny3216", "ATtiny3217", + "ATtiny3224", "ATtiny3226", "ATtiny3227", "ATtiny402", "ATtiny404", "ATtiny406", "ATtiny412", "ATtiny414", + "ATtiny416", "ATtiny417", "ATtiny424", "ATtiny426", "ATtiny427", "ATtiny804", "ATtiny806", "ATtiny807", + "ATtiny814", "ATtiny816", "ATtiny817", "ATtiny824", "ATtiny826", "ATtiny827", "AVR128DA28", "AVR128DA32", + "AVR128DA48", "AVR128DA64", "AVR128DB28", "AVR128DB32", "AVR128DB48", "AVR128DB64", "AVR16DD14", "AVR16DD20", + "AVR16DD28", "AVR16DD32", "AVR32DA28", "AVR32DA32", "AVR32DA48", "AVR32DB28", "AVR32DB32", "AVR32DB48", + "AVR32DD14", "AVR32DD20", "AVR32DD28", "AVR32DD32", "AVR64DA28", "AVR64DA32", "AVR64DA48", "AVR64DA64", + "AVR64DB28", "AVR64DB32", "AVR64DB48", "AVR64DB64", "AVR64DD14", "AVR64DD20", "AVR64DD28", "AVR64DD32", + "AVR64EA28", "AVR64EA32", "AVR64EA48", "AVR16DA28", "AVR16DA32", "AVR16DA48", "AVR16DB28", "AVR16DB32", + "AVR16DB48", "AVR16DU14", "AVR16DU20", "AVR16DU28", "AVR16DU32", "AVR32DU14", "AVR32DU20", "AVR32DU28", + "AVR32DU32", "AVR64DU28", "AVR64DU32", "AVR16EA28", "AVR16EA32", "AVR16EA48", "AVR32EA28", "AVR32EA32", + "AVR32EA48", "AVR8EA28", "AVR8EA32", "AVR16EB14", "AVR16EB20", "AVR16EB28", "AVR16EB32", "AVR32EB28", + "AVR32EB32", "AVR64EC48", "AVR32SD32", "AVR64SD48", +}; + + +const unsigned char * get_devid_script_by_nvm_ver(unsigned char version) { + if (version >= '0') version -= '0'; // allow chars + if (version > 9) return NULL; // Not a valid number + if (version <= 3) // tiny, mega, DA, DB, DD, EA + return GetDeviceID_0; + else // DU, EB + return GetDeviceID_1; +} + +int get_pickit_updi_script(SCRIPT *scr, const char* partdesc) { + if ((scr == NULL) || (partdesc == NULL)) + return -1; + + int namepos = -1; + for (int i = 0; i < 116; i++) { + if (strncmp(pickit5_updi_chip_lut[i], partdesc, 10) == 0) { + namepos = i; + break; + } + } + if (namepos == -1) { + return -2; + } + + pickit_updi_script_init(scr); // load common functions + + switch (namepos) { + case 0: /* ATtiny416auto */ + case 1: /* ATmega1608 */ + case 2: /* ATmega1609 */ + case 7: /* ATmega808 */ + case 8: /* ATmega809 */ + case 9: /* ATtiny1604 */ + case 10: /* ATtiny1606 */ + case 11: /* ATtiny1607 */ + case 12: /* ATtiny1614 */ + case 13: /* ATtiny1616 */ + case 14: /* ATtiny1617 */ + case 15: /* ATtiny1624 */ + case 16: /* ATtiny1626 */ + case 17: /* ATtiny1627 */ + case 18: /* ATtiny202 */ + case 19: /* ATtiny204 */ + case 20: /* ATtiny212 */ + case 21: /* ATtiny214 */ + case 27: /* ATtiny402 */ + case 28: /* ATtiny404 */ + case 29: /* ATtiny406 */ + case 30: /* ATtiny412 */ + case 31: /* ATtiny414 */ + case 32: /* ATtiny416 */ + case 33: /* ATtiny417 */ + case 34: /* ATtiny424 */ + case 35: /* ATtiny426 */ + case 36: /* ATtiny427 */ + case 37: /* ATtiny804 */ + case 38: /* ATtiny806 */ + case 39: /* ATtiny807 */ + case 40: /* ATtiny814 */ + case 41: /* ATtiny816 */ + case 42: /* ATtiny817 */ + case 43: /* ATtiny824 */ + case 44: /* ATtiny826 */ + case 45: /* ATtiny827 */ + scr->GetDeviceID = GetDeviceID_0; + scr->GetDeviceID_len = sizeof(GetDeviceID_0); + scr->WriteProgmem = WriteProgmem_0; + scr->WriteProgmem_len = sizeof(WriteProgmem_0); + scr->ReadProgmem = ReadProgmem_0; + scr->ReadProgmem_len = sizeof(ReadProgmem_0); + scr->WriteDataEEmem = WriteDataEEmem_0; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_0); + scr->ReadDataEEmem = ReadDataEEmem_0; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_0); + scr->WriteConfigmem = WriteConfigmem_0; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_0); + scr->WriteIDmem = WriteIDmem_0; + scr->WriteIDmem_len = sizeof(WriteIDmem_0); + scr->ReadIDmem = ReadIDmem_0; + scr->ReadIDmem_len = sizeof(ReadIDmem_0); + break; + case 3: /* ATmega3208 */ + case 4: /* ATmega3209 */ + case 5: /* ATmega4808 */ + case 6: /* ATmega4809 */ + case 22: /* ATtiny3216 */ + case 23: /* ATtiny3217 */ + scr->GetDeviceID = GetDeviceID_0; + scr->GetDeviceID_len = sizeof(GetDeviceID_0); + scr->WriteProgmem = WriteProgmem_1; + scr->WriteProgmem_len = sizeof(WriteProgmem_1); + scr->ReadProgmem = ReadProgmem_1; + scr->ReadProgmem_len = sizeof(ReadProgmem_1); + scr->WriteDataEEmem = WriteDataEEmem_1; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_1); + scr->ReadDataEEmem = ReadDataEEmem_1; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_1); + scr->WriteConfigmem = WriteConfigmem_0; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_0); + scr->WriteIDmem = WriteIDmem_1; + scr->WriteIDmem_len = sizeof(WriteIDmem_1); + scr->ReadIDmem = ReadIDmem_1; + scr->ReadIDmem_len = sizeof(ReadIDmem_1); + break; + case 24: /* ATtiny3224 */ + case 25: /* ATtiny3226 */ + case 26: /* ATtiny3227 */ + scr->GetDeviceID = GetDeviceID_0; + scr->GetDeviceID_len = sizeof(GetDeviceID_0); + scr->WriteProgmem = WriteProgmem_1; + scr->WriteProgmem_len = sizeof(WriteProgmem_1); + scr->ReadProgmem = ReadProgmem_1; + scr->ReadProgmem_len = sizeof(ReadProgmem_1); + scr->WriteDataEEmem = WriteDataEEmem_1; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_1); + scr->ReadDataEEmem = ReadDataEEmem_1; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_1); + scr->WriteConfigmem = WriteConfigmem_0; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_0); + scr->WriteIDmem = WriteIDmem_0; + scr->WriteIDmem_len = sizeof(WriteIDmem_0); + scr->ReadIDmem = ReadIDmem_0; + scr->ReadIDmem_len = sizeof(ReadIDmem_0); + break; + case 46: /* AVR128DA28 */ + case 47: /* AVR128DA32 */ + case 48: /* AVR128DA48 */ + case 49: /* AVR128DA64 */ + case 50: /* AVR128DB28 */ + case 51: /* AVR128DB32 */ + case 52: /* AVR128DB48 */ + case 53: /* AVR128DB64 */ + case 54: /* AVR16DD14 */ + case 55: /* AVR16DD20 */ + case 56: /* AVR16DD28 */ + case 57: /* AVR16DD32 */ + case 58: /* AVR32DA28 */ + case 59: /* AVR32DA32 */ + case 60: /* AVR32DA48 */ + case 61: /* AVR32DB28 */ + case 62: /* AVR32DB32 */ + case 63: /* AVR32DB48 */ + case 64: /* AVR32DD14 */ + case 65: /* AVR32DD20 */ + case 66: /* AVR32DD28 */ + case 67: /* AVR32DD32 */ + case 68: /* AVR64DA28 */ + case 69: /* AVR64DA32 */ + case 70: /* AVR64DA48 */ + case 71: /* AVR64DA64 */ + case 72: /* AVR64DB28 */ + case 73: /* AVR64DB32 */ + case 74: /* AVR64DB48 */ + case 75: /* AVR64DB64 */ + case 76: /* AVR64DD14 */ + case 77: /* AVR64DD20 */ + case 78: /* AVR64DD28 */ + case 79: /* AVR64DD32 */ + case 83: /* AVR16DA28 */ + case 84: /* AVR16DA32 */ + case 85: /* AVR16DA48 */ + case 86: /* AVR16DB28 */ + case 87: /* AVR16DB32 */ + case 88: /* AVR16DB48 */ + scr->GetDeviceID = GetDeviceID_0; + scr->GetDeviceID_len = sizeof(GetDeviceID_0); + scr->WriteProgmem = WriteProgmem_2; + scr->WriteProgmem_len = sizeof(WriteProgmem_2); + scr->ReadProgmem = ReadProgmem_2; + scr->ReadProgmem_len = sizeof(ReadProgmem_2); + scr->WriteDataEEmem = WriteDataEEmem_2; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_2); + scr->ReadDataEEmem = ReadDataEEmem_2; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_2); + scr->WriteConfigmem = WriteConfigmem_1; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_1); + scr->WriteIDmem = WriteIDmem_2; + scr->WriteIDmem_len = sizeof(WriteIDmem_2); + scr->ReadIDmem = ReadIDmem_0; + scr->ReadIDmem_len = sizeof(ReadIDmem_0); + break; + case 80: /* AVR64EA28 */ + case 81: /* AVR64EA32 */ + case 82: /* AVR64EA48 */ + scr->GetDeviceID = GetDeviceID_0; + scr->GetDeviceID_len = sizeof(GetDeviceID_0); + scr->WriteProgmem = WriteProgmem_3; + scr->WriteProgmem_len = sizeof(WriteProgmem_3); + scr->ReadProgmem = ReadProgmem_1; + scr->ReadProgmem_len = sizeof(ReadProgmem_1); + scr->WriteDataEEmem = WriteDataEEmem_3; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_3); + scr->ReadDataEEmem = ReadDataEEmem_3; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_3); + scr->WriteConfigmem = WriteConfigmem_2; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_2); + scr->WriteIDmem = WriteIDmem_3; + scr->WriteIDmem_len = sizeof(WriteIDmem_3); + scr->ReadIDmem = ReadIDmem_1; + scr->ReadIDmem_len = sizeof(ReadIDmem_1); + break; + case 89: /* AVR16DU14 */ + case 90: /* AVR16DU20 */ + case 91: /* AVR16DU28 */ + case 92: /* AVR16DU32 */ + case 93: /* AVR32DU14 */ + case 94: /* AVR32DU20 */ + case 95: /* AVR32DU28 */ + case 96: /* AVR32DU32 */ + case 97: /* AVR64DU28 */ + case 98: /* AVR64DU32 */ + scr->GetDeviceID = GetDeviceID_1; + scr->GetDeviceID_len = sizeof(GetDeviceID_1); + scr->WriteProgmem = WriteProgmem_4; + scr->WriteProgmem_len = sizeof(WriteProgmem_4); + scr->ReadProgmem = ReadProgmem_2; + scr->ReadProgmem_len = sizeof(ReadProgmem_2); + scr->WriteDataEEmem = WriteDataEEmem_4; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_4); + scr->ReadDataEEmem = ReadDataEEmem_2; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_2); + scr->WriteConfigmem = WriteConfigmem_3; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_3); + scr->WriteIDmem = WriteIDmem_4; + scr->WriteIDmem_len = sizeof(WriteIDmem_4); + scr->ReadIDmem = ReadIDmem_2; + scr->ReadIDmem_len = sizeof(ReadIDmem_2); + break; + case 99: /* AVR16EA28 */ + case 100: /* AVR16EA32 */ + case 101: /* AVR16EA48 */ + case 102: /* AVR32EA28 */ + case 103: /* AVR32EA32 */ + case 104: /* AVR32EA48 */ + case 105: /* AVR8EA28 */ + case 106: /* AVR8EA32 */ + scr->GetDeviceID = GetDeviceID_0; + scr->GetDeviceID_len = sizeof(GetDeviceID_0); + scr->WriteProgmem = WriteProgmem_5; + scr->WriteProgmem_len = sizeof(WriteProgmem_5); + scr->ReadProgmem = ReadProgmem_0; + scr->ReadProgmem_len = sizeof(ReadProgmem_0); + scr->WriteDataEEmem = WriteDataEEmem_3; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_3); + scr->ReadDataEEmem = ReadDataEEmem_3; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_3); + scr->WriteConfigmem = WriteConfigmem_2; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_2); + scr->WriteIDmem = WriteIDmem_3; + scr->WriteIDmem_len = sizeof(WriteIDmem_3); + scr->ReadIDmem = ReadIDmem_1; + scr->ReadIDmem_len = sizeof(ReadIDmem_1); + break; + case 107: /* AVR16EB14 */ + case 108: /* AVR16EB20 */ + case 109: /* AVR16EB28 */ + case 110: /* AVR16EB32 */ + case 111: /* AVR32EB28 */ + case 112: /* AVR32EB32 */ + scr->GetDeviceID = GetDeviceID_1; + scr->GetDeviceID_len = sizeof(GetDeviceID_1); + scr->WriteProgmem = WriteProgmem_5; + scr->WriteProgmem_len = sizeof(WriteProgmem_5); + scr->ReadProgmem = ReadProgmem_0; + scr->ReadProgmem_len = sizeof(ReadProgmem_0); + scr->WriteDataEEmem = WriteDataEEmem_3; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_3); + scr->ReadDataEEmem = ReadDataEEmem_3; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_3); + scr->WriteConfigmem = WriteConfigmem_2; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_2); + scr->WriteIDmem = WriteIDmem_3; + scr->WriteIDmem_len = sizeof(WriteIDmem_3); + scr->ReadIDmem = ReadIDmem_1; + scr->ReadIDmem_len = sizeof(ReadIDmem_1); + break; + case 113: /* AVR64EC48 */ + scr->GetDeviceID = GetDeviceID_1; + scr->GetDeviceID_len = sizeof(GetDeviceID_1); + scr->WriteProgmem = WriteProgmem_3; + scr->WriteProgmem_len = sizeof(WriteProgmem_3); + scr->ReadProgmem = ReadProgmem_1; + scr->ReadProgmem_len = sizeof(ReadProgmem_1); + scr->WriteDataEEmem = WriteDataEEmem_3; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_3); + scr->ReadDataEEmem = ReadDataEEmem_3; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_3); + scr->WriteConfigmem = WriteConfigmem_2; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_2); + scr->WriteIDmem = WriteIDmem_3; + scr->WriteIDmem_len = sizeof(WriteIDmem_3); + scr->ReadIDmem = ReadIDmem_1; + scr->ReadIDmem_len = sizeof(ReadIDmem_1); + break; + case 114: /* AVR32SD32 */ + case 115: /* AVR64SD48 */ + scr->GetDeviceID = GetDeviceID_1; + scr->GetDeviceID_len = sizeof(GetDeviceID_1); + scr->WriteProgmem = WriteProgmem_6; + scr->WriteProgmem_len = sizeof(WriteProgmem_6); + scr->ReadProgmem = ReadProgmem_2; + scr->ReadProgmem_len = sizeof(ReadProgmem_2); + scr->WriteDataEEmem = WriteDataEEmem_5; + scr->WriteDataEEmem_len = sizeof(WriteDataEEmem_5); + scr->ReadDataEEmem = ReadDataEEmem_2; + scr->ReadDataEEmem_len = sizeof(ReadDataEEmem_2); + scr->WriteConfigmem = WriteConfigmem_4; + scr->WriteConfigmem_len = sizeof(WriteConfigmem_4); + scr->WriteIDmem = WriteIDmem_5; + scr->WriteIDmem_len = sizeof(WriteIDmem_5); + scr->ReadIDmem = ReadIDmem_0; + scr->ReadIDmem_len = sizeof(ReadIDmem_0); + break; + } + return 0; +} \ No newline at end of file diff --git a/src/usbdevs.h b/src/usbdevs.h index 6fc6b773d..7213badd0 100644 --- a/src/usbdevs.h +++ b/src/usbdevs.h @@ -40,6 +40,7 @@ #define USB_DEVICE_PICKIT4_AVR_MODE 0x2177 #define USB_DEVICE_PICKIT4_PIC_MODE 0x9012 #define USB_DEVICE_PICKIT4_PIC_MODE_BL 0x9017 // PICkit4 in bootloader mode +#define USB_DEVICE_PICKIT5 0x9036 #define USB_DEVICE_SNAP_AVR_MODE 0x2180 #define USB_DEVICE_SNAP_PIC_MODE 0x9018 #define USB_DEVICE_SNAP_PIC_MODE_BL 0x9019 // SNAP in bootloader mode diff --git a/tools/scripts_decoder.py b/tools/scripts_decoder.py new file mode 100644 index 000000000..83c357465 --- /dev/null +++ b/tools/scripts_decoder.py @@ -0,0 +1,675 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# +# avrdude - A Downloader/Uploader for AVR device programmers +# Copyright (C) 2024 MX682X +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# this is a small python sketch that tries to find the PICkit5_TP folder +# created by MPLAB X that contains the scripts.xml file. +# Works on Windows and Linux (MacOS untested), as long as the default installation +# folder was not changed. If it was changed, and the program is unable to locate +# the scripts.xml file, you should be promted to enter a path. You can +# either provide the path to the file, or to the directory providing the file. +# +# This file contains some functions that were used in initial develeopment +# but are not needed anymore. However, they might provide useful, thus they +# can be enabled by setting "user_input" to 1. +# +# The idea behind this program is to extract the sub-programs defined in the +# script.xml. The original file has a size of about 300MB, containing a lot of +# redundand information as well as sub-programs for chips avrdude doesn't +# support, like ARM MCUs. +# This python scripts iterates through all functions, removing identical ones, +# and indexes those. The index is then used to connect the MCUs with those functions +# so that the correct array pointers can be loaded. +# Warning: If you run this python program, the previously generated files will be +# overwritten without warning. +# +# As the XML file is fairly large, a machine with at least 16GB RAM is recommended + +import os, fnmatch, mmap +from pathlib import Path +from xml.etree import ElementTree as ET + +user_input = 0 + +# The list of functions, as a Python Dictionary, that will be used by avr-dude +# The complete list of available functions can be found below +c_dict = { + "EnterProgMode" : [], + "EnterProgModeHvSp" : [], # High Voltage Pulse on UPDI line + "EnterProgModeHvSpRst" : [], # High Voltage Pulse on Reset Pin + "EnterProgModeHvUpt" : [], + "ExitProgMode" : [], + "SetSpeed" : [], + "GetDeviceID" : [], + "EraseChip" : [], + "WriteProgmem" : [], + "ReadProgmem" : [], + "WriteDataEEmem" : [], + "ReadDataEEmem" : [], + "WriteCSreg" : [], + "ReadCSreg" : [], + "WriteMem8" : [], + "ReadMem8" : [], + "WriteConfigmem" : [], + "ReadConfigmem" : [], + "WriteIDmem" : [], + "ReadIDmem" : [], + "ReadSIB" : [], +} + +# List of MCUs that should not end up in the lookup-table, +# preferably only those that are known not be released in the future +mcu_blacklist = [ + "AVR16DV14", "AVR16DV20" +] + +# A complete list of Functions defined in the scripts.xml +# This string was used to generate an intermediate python file +dict_header = \ +''' +func_dict = { + "EnterProgMode" : [], + "EnterProgModeHvSp" : [], + "EnterProgModeHvSpRst" : [], + "EnterProgModeHvUpt" : [], + "ExitProgMode" : [], + "SetSpeed" : [], + "GetDeviceID" : [], + "EraseChip" : [], + "WriteProgmem" : [], + "ReadProgmem" : [], + "WriteDataEEmem" : [], + "ReadDataEEmem" : [], + "WriteConfigmem" : [], + "WriteConfigmemFuse" : [], + "WriteConfigmemLock" : [], + "ReadConfigmem" : [], + "ReadConfigmemFuse" : [], + "ReadConfigmemLock" : [], + "WriteIDmem" : [], + "ReadIDmem" : [], + "WriteCSreg" : [], + "ReadCSreg" : [], + "WriteMem8" : [], + "WriteMem16" : [], + "ReadMem8" : [], + "ReadMem16" : [], + "ReadSIB" : [], + "HoldInReset" : [], + "ReleaseFromReset" : [], + "EnterDebugMode" : [], + "EnterDebugModeHvSp" : [], + "EnterDebugModeHvSpRst" : [], + "EnterDebugModeHvUpt" : [], + "ExitDebugMode" : [], + "SetPC" : [], + "GetPC" : [], + "Run" : [], + "Halt" : [], + "DebugReset" : [], + "GetHaltStatus" : [], + "SingleStep" : [], + "SetHWBP" : [], + "ClearHWBP" : [], +}\n +''' + + +import platform + +work_dir = os.path.abspath(os.getcwd()) +cache_dir = os.path.join(work_dir, "scripts_cache") + +print(work_dir) +print(cache_dir) + + +# Tries to locate the xml file in a known location +def find_xml(): + home_dir = str(Path.home()) + print("Home Path: {0}".format(home_dir)) + if home_dir == None: + return + home_dir = os.path.join(home_dir, ".mchp_packs", "Microchip") + home_dir_A = os.path.join(home_dir, "PICkit5_TP") + result = [] + for root, dirs, files in os.walk(home_dir_A): + for name in files: + if fnmatch.fnmatch(name, "scripts.xml"): + result.append(os.path.join(root, name)) + + print("List of scripts.xml files:") + print(result) + return result[-1] + # EOF + +# extracts only the functions from the scripts.xml that end with "UPDI" +def cache_xml(file): + if file == None: + return + print("Opening file {0}".format(file)) + global cache_dir + origin_tree = ET.parse(file) + origin_root = origin_tree.getroot() + work_root = ET.Element("scripts") + old_chip_name = "" + print("List of UPDI MCUs:") + for script in origin_root.findall('script'): + function_name = script[0].text # the function name is always on the first place + if (function_name.endswith("UPDI")): + chip_name = script[1].text + if (old_chip_name != chip_name): + print(chip_name) + old_chip_name = chip_name + work_root.append(script) # copy UPDI entries to our working element + + + work_tree = ET.ElementTree(work_root) + work_tree.write(os.path.join(cache_dir, "scripts_updi.xml")) + # EOF + + +# generates a python file out of the reduced scripts.xml file +def decode_xml_cache(xml_path): + global cache_dir + dict_path = os.path.join(cache_dir, "scripts_dict.py") + + xml_tree = ET.parse(xml_path) + xml_root = xml_tree.getroot() + + if (os.path.exists(dict_path)): + os.remove(dict_path) + + with open(dict_path, 'w') as dict_file: + dict_list = [] + dict_iterator = -1 + old_chip_name = "" + old_function_name = "" + for script in xml_root: + function_string = "" + function_name = script[0].text + chip_name = script[1].text + if (old_chip_name != chip_name): + if (dict_iterator >= 0): + dict_list[dict_iterator] += " },\n" # trailing bracket + print("{0} generated".format(old_chip_name)) + + dict_iterator += 1 + dict_list.append("") + dict_list[dict_iterator] = " \"{0}\" : ".format(chip_name) # thisdict : { + dict_list[dict_iterator] += "{\n" + old_chip_name = chip_name + + if (old_function_name != function_name): + dict_list[dict_iterator] += " \"{0}\" : ".format(function_name[0:-5]) # "function_name" : + old_function_name = function_name + + scrbytes = script[3] + for bytes in scrbytes: + function_string += bytes.text + function_string += ", " + + dict_list[dict_iterator] += "[{0}],\n".format(function_string[0:-2]) # "function string", + + dict_file.write(dict_header) + dict_file.write("scripts = {\n") + for x in range (dict_iterator): + dict_file.write(dict_list[x]) # store decoded dictionary + dict_file.write("}") + + + + +# tries to reduce file size, reuires the previous function to be executed +# in order to provide the python file +def optimize_dict(): + import scripts_cache.scripts_dict as dict + global cache_dir + for chip_name in dict.scripts: # Go through every chip + for func_name in dict.scripts[chip_name]: # Go through every function for each chip + if func_name in dict.func_dict: # Only handle the function if we care + func_array = dict.func_dict[func_name] # Use the array + position = -1 + for x in range (len(func_array)): # go through + if func_array[x] == dict.scripts[chip_name][func_name]: + position = x + break + if position >= 0: + dict.scripts[chip_name][func_name] = position + else: + func_array.append(dict.scripts[chip_name][func_name]) + dict.scripts[chip_name][func_name] = position + 1 + + lut_path = os.path.join(cache_dir, "scripts_lut.py") + if (os.path.exists(lut_path)): + os.remove(lut_path) + + with open(lut_path, 'w') as lut_file: # Create file + lut_file.write("func_dict = {\n") # start with function look-up Table + for func in dict.func_dict: + lut_file.write(" \"{0}\" : [\n".format(func)) # function start + func_array = dict.func_dict[func] + + for array_elem in func_array: # function list start + func_string = " [" + for i in array_elem: # iterate through the sub-function elements + func_string += "0x{0:02X}, ".format(i) # format for readability + func_string += "],\n" # end of sub-function + lut_file.write(func_string) # write to file + lut_file.write(" ],\n") # end of function + lut_file.write("}\n\n\n") # end of lut + + lut_file.write("scripts = {\n") + for chip_name in dict.scripts: # Go through every chip + lut_file.write(" \""+ chip_name + "\" : {\n") + for func_name in dict.scripts[chip_name]: # Go through every function for each chip + lut_file.write(" \"{0}\" : {1},\n".format(func_name, dict.scripts[chip_name][func_name])) + lut_file.write(" },\n") + lut_file.write("}") # close dict + print("done") + #EOF + + +# Beginning of C and H Files +common_header = \ +'''/* This file was auto-generated by scripts_decoder.py, any changes will be overwritten */ + +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2024 MX682X + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +''' + +# generates the h-file. generates the struct definition +def generate_h_file(c_dict, file_dir): + h_header = \ +''' +#ifndef pickit5_lut_h +#define pickit5_lut_h + +#ifdef __cplusplus + extern "C" { +#endif + +struct avr_script_lut { +''' + + h_trailer = \ +''' +}; + +typedef struct avr_script_lut SCRIPT; +const unsigned char * get_devid_script_by_nvm_ver(unsigned char version); +int get_pickit_updi_script(SCRIPT *scr, const char *partdesc); + +#ifdef __cplusplus +} +#endif + +#endif // pickit5_lut_h +''' + global common_header + if file_dir is None: + return + + h_lut_path = os.path.join(file_dir, "pickit5_lut.h") # first - handle defining the structure + if (os.path.exists(h_lut_path)): + os.remove(h_lut_path) + with open(h_lut_path, 'w') as h_file: + h_file.write(common_header) + h_file.write(h_header) + for func_name in c_dict: + h_file.write(" const unsigned char *{0};\n unsigned int {0}_len;\n".format(func_name)) + h_file.write(h_trailer) + print("h-File generated") + #EOF + + + +# generates the c-file out of a previously generated python file +def generate_c_file(c_dict, file_dir): + import scripts_cache.scripts_lut as lut + + if file_dir is None: + return + + c_lut_path = os.path.join(file_dir, "pickit5_lut.c") + if (os.path.exists(c_lut_path)): + os.remove(c_lut_path) + with open(c_lut_path, 'w') as c_file: + non_unique_func = [] + c_file.write("/* this file was auto-generated */\n") + c_file.write("#include \n") + c_file.write("#include \n") + c_file.write("#include \n") + c_file.write("#include \"pickit5_lut.h\"\n\n\n") + struct_init_func = "" + struct_init_len = "" + for func_name in lut.func_dict: # for each function in our database + if func_name in c_dict: # if the function exists in our c-list + function = lut.func_dict[func_name] # load data associated with the function + array_iterator = 0 + for array in function: # for each array in function + array_str = "const unsigned char {0}_{1}[{2}]".format(func_name, array_iterator, len(array)) + array_str += " = {\n " # begin array + for i in range (len(array)): # go through every byte + array_str += "0x{0:02x}, ".format(array[i]) # and generate String + array_str += "\n};\n" # complete array + array_iterator += 1 + c_file.write(array_str) + + if array_iterator == 1: + struct_init_func += " .{0} = {0}_0,\n".format(func_name) + struct_init_len += " .{0}_len = sizeof({0}_0),\n".format(func_name) + else: + struct_init_func += " .{0} = NULL,\n".format(func_name) + struct_init_len += " .{0}_len = 0,\n".format(func_name) + non_unique_func.append(func_name) + + + c_file.write("\n\n\nstruct avr_script_lut avr_scripts = {\n") + c_file.write(struct_init_func) + c_file.write(struct_init_len) + c_file.write("};\n\n\n") + + chip_lut_str = "const char *chip_lut[] = {\n " + chip_name_iterator = 0 + for chip_name in lut.scripts: + chip_lut_str += "\"" + chip_lut_str += chip_name + chip_lut_str += "\", " + chip_name_iterator += 1 + if chip_name_iterator % 8 == 0: + chip_lut_str += "\n " + chip_lut_str += "\n};\n\n\n" + c_file.write(chip_lut_str) + + c_func_str = "struct avr_script_lut* get_pickit_script(const char* partdesc) { \n" + c_func_str += " int namepos = -1;\n" + c_func_str += " for (int i = 0; i < {0}; i++)".format(chip_name_iterator) + c_func_str += " {\n" + c_func_str += " if (strncmp(chip_lut[i], partdesc, 10) == 0) {\n" + c_func_str += " namepos = i;\n break;\n }\n }\n" + c_func_str += " if (namepos == -1) {\n return NULL;\n }\n" + c_file.write(c_func_str) + + switch_iterator = 0 + c_file.write(" switch (namepos) {\n") + for chip_name in lut.scripts: + case_str = " case {0}:\n".format(switch_iterator) + chip_func = lut.scripts[chip_name] + for func_lut in chip_func: + if func_lut in non_unique_func: + case_str += " avr_scripts.{0} = {0}_{1};\n".format(func_lut, chip_func[func_lut]) + case_str += " avr_scripts.{0}_len = sizeof({0}_{1});\n".format(func_lut, chip_func[func_lut]) + case_str += " break;\n" + switch_iterator += 1 + c_file.write(case_str) + c_file.write(" }\n return &avr_scripts;\n }") + print("c-File generated") + #EOF + + +def convert_to_c(c_dict, file_dir): + + generate_h_file(c_dict, file_dir) + generate_c_file(c_dict, file_dir) + #EOF + + + +# A sum of the previous functions, generating the c/h files +# without needing any intermediate files +def convert_xml(xml_path, c_dict): + if xml_path == None: + print("No Path to XML file provided") + return + + mcu_dict = dict() + + # Prepare directories + parent_dir = os.getcwd() + src_dir = os.path.join(parent_dir, "src") + print("Opening file {0}".format(xml_path)) + print("Parent Dir: {0}".format(parent_dir)) + print("Src directory: {0}".format(src_dir)) + + # open XML file + origin_tree = ET.parse(xml_path) + origin_root = origin_tree.getroot() + work_root = ET.Element("scripts") + print ("XML File loaded") + + # scan scripts file + for script in origin_root.findall('script'): + function_name = script[0].text # the function name is always on the first place + if (function_name.endswith("UPDI")): # We're only intrested in UPDI functions + function_name = function_name[0:-5] # remove "_UPDI" from function name + if (function_name in c_dict): # filter out unneded functions + chip_name = script[1].text # get chip name + if (chip_name in mcu_blacklist): # filter out chips in blacklist + continue + if (chip_name not in mcu_dict): + mcu_dict[chip_name] = dict() + if (function_name not in mcu_dict[chip_name]): + mcu_dict[chip_name][function_name] = [] + scrbytes = script[3] + for bytes in scrbytes: + mcu_dict[chip_name][function_name].append(int(bytes.text, 16)) + # the mcu dict has following layout "mcu_name" : "function1" : [], "function2" : [] + print("XML File processed") + + # reorder mcu_dict to a func_dict + func_dict = dict() + for mcu_name in mcu_dict: # Go through every MCU + for function_name in mcu_dict[mcu_name]: # Go through every Function for every CPU + if (function_name not in func_dict): + func_dict[function_name] = [] + + funct_bytes = mcu_dict[mcu_name][function_name] # get Function bytes + entries = len(func_dict[function_name]) + for x in range (entries + 1): # try to find an existing entry + if x == entries: # if we reached the end + func_dict[function_name].append(funct_bytes) # add an entry to our dict + mcu_dict[mcu_name][function_name] = x # remember the postion in dict + break + if func_dict[function_name][x] == funct_bytes: # if match found + mcu_dict[mcu_name][function_name] = x # remember the postion + break + # the funct dict has following layout: "function1" : [[], []], "function2" : [[], []], + # the mcu dict has following layout "mcu_name" : "function1" : 1, "function2" : 0 + + # create h-File + generate_h_file(c_dict, src_dir) + + # create c-File + global common_header + c_lut_path = os.path.join(src_dir, "pickit5_updi_lut.c") + if (os.path.exists(c_lut_path)): + os.remove(c_lut_path) + with open(c_lut_path, 'w') as c_file: + non_unique_func = [] + c_file.write(common_header) + c_file.write("#include \n") + c_file.write("#include \n") + c_file.write("#include \n") + c_file.write("#include \"pickit5_lut.h\"\n\n\n") + + # Generate the arrays for the functions + struct_init_func = "" + struct_init_len = "" + for func_name in func_dict: # for each function in our database + function = func_dict[func_name] # load data associated with the function + array_iterator = 0 + for array in function: # for each array in function + array_str = "const unsigned char {0}_{1}[{2}]".format(func_name, array_iterator, len(array)) + array_str += " = {" # begin array + for i in range (len(array)): # go through every byte + if (i % 16 == 0): + array_str += "\n " # new line after 16 bytes + array_str += "0x{0:02x}, ".format(array[i]) # and generate String + array_str += "\n};\n\n" # complete array + array_iterator += 1 + c_file.write(array_str) + + if array_iterator == 1: + struct_init_func += " scr->{0} = {0}_0;\n".format(func_name) + struct_init_len += " scr->{0}_len = sizeof({0}_0);\n".format(func_name) + else: + struct_init_func += " scr->{0} = NULL;\n".format(func_name) + struct_init_len += " scr->{0}_len = 0;\n".format(func_name) + non_unique_func.append(func_name) + + + c_file.write("\n\n\nstatic void pickit_updi_script_init(SCRIPT *scr);\n") # declaration + c_file.write("static void pickit_updi_script_init(SCRIPT *scr) {\n") # definition + c_file.write(struct_init_func) + c_file.write("\n") # improve readability + c_file.write(struct_init_len) + c_file.write("}\n\n\n") + + # Lookup Table for Chip Names + chip_lut_str = "const char * const pickit5_updi_chip_lut[] = {\n " + chip_name_iterator = 0 + for chip_name in mcu_dict: + chip_lut_str += "\"" + chip_lut_str += chip_name + chip_lut_str += "\", " + chip_name_iterator += 1 + if chip_name_iterator % 8 == 0: + chip_lut_str += "\n " + chip_lut_str += "\n};\n\n\n" + c_file.write(chip_lut_str) + + # Provide a way to get the DevID Script by NVM Version stored in SIB + devid_str = "const unsigned char * get_devid_script_by_nvm_ver(unsigned char version) {\n" + devid_str += " if (version >= '0') version -= '0'; // allow chars\n" + devid_str += " if (version > 9) return NULL; // Not a valid number\n" + devid_str += " if (version <= 3) // tiny, mega, DA, DB, DD, EA\n" + devid_str += " return GetDeviceID_0;\n" + devid_str += " else // DU, EB\n" + devid_str += " return GetDeviceID_1;\n}\n\n" + c_file.write(devid_str) + + # Main Function to load the data into the structure + c_func_str = "int get_pickit_updi_script(SCRIPT *scr, const char* partdesc) { \n" + c_func_str += " if ((scr == NULL) || (partdesc == NULL))\n return -1;\n\n" + c_func_str += " int namepos = -1;\n" + c_func_str += " for (int i = 0; i < {0}; i++)".format(chip_name_iterator) + c_func_str += " {\n" + c_func_str += " if (strncmp(pickit5_updi_chip_lut[i], partdesc, 10) == 0) {\n" + c_func_str += " namepos = i;\n break;\n }\n }\n" + c_func_str += " if (namepos == -1) {\n return -2;\n }\n\n" + c_func_str += " pickit_updi_script_init(scr); // load common functions\n\n" + c_file.write(c_func_str) + + + switch_iterator = 0 + c_file.write(" switch (namepos) {\n") + case_str_list = [] + break_str_list = [] + for chip_name in mcu_dict: + case_str_list.append("") + break_str_list.append("") + case_str_list[switch_iterator] = " case {0}: /* {1} */\n".format(switch_iterator, chip_name) + chip_func = mcu_dict[chip_name] + for func_lut in chip_func: + if func_lut in non_unique_func: + break_str_list[switch_iterator] += " scr->{0} = {0}_{1};\n".format(func_lut, chip_func[func_lut]) + break_str_list[switch_iterator] += " scr->{0}_len = sizeof({0}_{1});\n".format(func_lut, chip_func[func_lut]) + break_str_list[switch_iterator] += " break;\n" + switch_iterator += 1 + + + for x in range (0, switch_iterator): + if (case_str_list[x] != ""): # ignore already "filtered" out cases + file_str = case_str_list[x] # start with a case + temp_str = break_str_list[x] # buffer the content of the case + for y in range(x + 1, switch_iterator): # go through all future entries + if temp_str == break_str_list[y]: # if we find one that is identical + file_str += case_str_list[y] # add it to the case at the beginning + case_str_list[y] = "" # clear case entry + break_str_list[y] = "" # clear content entry to speed up filtering + file_str += temp_str # add the content of the case + c_file.write(file_str) + + + c_file.write(" }\n return 0;\n}") + print("c-File generated") + pass + + + +if not user_input: + xml_path = find_xml() + if xml_path == None: + print("Unable to find scripts.xml in the default location.") + print("Please Enter a Path to the File or Directory:") + xml_path = input(">") + if (os.path.isdir(xml_path)): + os.path.join(xml_path, "scripts.xml") + if (os.path.exists(xml_path) == False): + print("File not found, exiting") + quit() + convert_xml(xml_path, c_dict) + quit() + + +while user_input: + user_in = input(">") + + if (user_in == "cache"): + xml_path = find_xml() + cache_xml(xml_path) + elif (user_in == "decode"): + xml_path = os.path.join(cache_dir, "scripts_updi.xml") + decode_xml_cache(xml_path) + elif (user_in == "optimize"): + optimize_dict() + elif (user_in == "cfy"): + convert_to_c(c_dict, cache_dir) + elif (user_in == "dude"): + xml_path = find_xml() + if xml_path == None: + print("Unable to find scripts.xml in the default location.") + print("Please Enter a Path to the File or Directory:") + xml_path = input(">") + if (os.path.isdir(xml_path)): + os.path.join(xml_path, "scripts.xml") + if (os.path.exists(xml_path) == False): + print("File not found, exiting") + quit() + convert_xml(xml_path, c_dict) + quit() + pass