From 4dbdffc3376f24749e76877c7c6015d9575d4912 Mon Sep 17 00:00:00 2001 From: William Toohey Date: Sat, 4 Mar 2017 15:44:38 +1000 Subject: [PATCH] Add forgotten bootloader files --- Firmware/Bootloader/Bootloader.c | 172 ++++++++++++++++++ Firmware/Bootloader/Bootloader.h | 77 ++++++++ .../PocketVoltex/DFU/control_bootloader.py | 145 +++++++++++++++ Firmware/PocketVoltex/LogCurveGen.py | 18 ++ Firmware/PocketVoltex/fader.xlsx | Bin 0 -> 29213 bytes 5 files changed, 412 insertions(+) create mode 100644 Firmware/Bootloader/Bootloader.c create mode 100644 Firmware/Bootloader/Bootloader.h create mode 100644 Firmware/PocketVoltex/DFU/control_bootloader.py create mode 100644 Firmware/PocketVoltex/LogCurveGen.py create mode 100644 Firmware/PocketVoltex/fader.xlsx diff --git a/Firmware/Bootloader/Bootloader.c b/Firmware/Bootloader/Bootloader.c new file mode 100644 index 0000000..99192be --- /dev/null +++ b/Firmware/Bootloader/Bootloader.c @@ -0,0 +1,172 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Main source file for the HID class bootloader. This file contains the complete bootloader logic. + */ + +#include "Bootloader.h" + +/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run + * via a soft reset. When cleared, the bootloader will abort, the USB interface will shut down and the application + * started via a forced watchdog reset. + */ +static bool RunBootloader = true; + +uint16_t MagicBootKey ATTR_NO_INIT; + + +/** Special startup routine to check if the bootloader was started via a watchdog reset, and if the magic application + * start key has been loaded into \ref MagicBootKey. If the bootloader started via the watchdog and the key is valid, + * this will force the user application to start via a software jump. + */ +void Application_Jump_Check(void) +{ + /* Always boot bootloader if RESET held + * NOTE: This makes the assumption that + * A) No code on the device uses RESET as an output + * B) The RSTDISBL fuse is set, and this value is valid + * C) There is an external pullup on the RESET pin + */ + if(!(PINC & _BV(1))) + return; + /* If power on boot or magic key set */ + if ((MCUSR & _BV(PORF)) || MagicBootKey == MAGIC_BOOT_KEY) + { + // If there's no code, this avoids an infinite reboot loop + MCUSR &= ~_BV(PORF); + // cppcheck-suppress constStatement + ((void (*)(void))0x0000)(); + } +} + +/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously + * runs the bootloader processing routine until instructed to soft-exit. + */ +int main(void) +{ + /* Setup hardware required for the bootloader */ + SetupHardware(); + + /* Enable global interrupts so that the USB stack can function */ + GlobalInterruptEnable(); + + while (RunBootloader) + USB_USBTask(); + + /* Disconnect from the host - USB interface will be reset later along with the AVR */ + USB_Detach(); + + /* Unlock the forced application start mode of the bootloader if it is restarted */ + MagicBootKey = MAGIC_BOOT_KEY; + + /* Enable the watchdog and force a timeout to reset the AVR */ + wdt_enable(WDTO_250MS); + + for (;;); +} + +/** Configures all hardware required for the bootloader. */ +static void SetupHardware(void) +{ + /* Disable watchdog if enabled by bootloader/fuses */ + MCUSR &= ~(1 << WDRF); + wdt_disable(); + + /* Relocate the interrupt vector table to the bootloader section */ + MCUCR = (1 << IVCE); + MCUCR = (1 << IVSEL); + + /* Initialize USB subsystem */ + USB_Init(); +} + +/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready + * to relay data to and from the attached USB host. + */ +void EVENT_USB_Device_ConfigurationChanged(void) +{ + +} + +/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to + * the device from the USB host before passing along unhandled control requests to the library for processing + * internally. + */ +void EVENT_USB_Device_ControlRequest(void) +{ + Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); + if(!Endpoint_IsSETUPReceived()) { + return; + } + if(USB_ControlRequest.bRequest == CONFIG_ID) { + Endpoint_ClearSETUP(); + uint16_t PageAddress = USB_ControlRequest.wValue; + if(USB_ControlRequest.wIndex == COMMAND_PROGRAM) { + /* Wait until the command has been sent by the host */ + while (!(Endpoint_IsOUTReceived())); + /* Erase the given FLASH page, ready to be programmed */ + boot_page_erase(PageAddress); + boot_spm_busy_wait(); + + /* Write each of the FLASH page's bytes in sequence */ + for (uint8_t PageWord = 0; PageWord < (SPM_PAGESIZE / 2); PageWord++) + { + /* Check if endpoint is empty - if so clear it and wait until ready for next packet */ + if (!(Endpoint_BytesInEndpoint())) + { + Endpoint_ClearOUT(); + while (!(Endpoint_IsOUTReceived())); + } + + /* Write the next data word to the FLASH page */ + boot_page_fill(PageAddress + ((uint16_t)PageWord << 1), Endpoint_Read_16_LE()); + } + + /* Write the filled FLASH page to memory */ + boot_page_write(PageAddress); + boot_spm_busy_wait(); + + /* Re-enable RWW section */ + boot_rww_enable(); + } else if(USB_ControlRequest.wIndex == COMMAND_VERSION) { + Endpoint_Write_16_LE(65000); + Endpoint_ClearIN(); + } else if(USB_ControlRequest.wIndex == COMMAND_STARTAPPLICATION) { + RunBootloader = false; + } + Endpoint_ClearOUT(); + Endpoint_ClearStatusStage(); + return; + } + + USB_Process_BOS(); +} \ No newline at end of file diff --git a/Firmware/Bootloader/Bootloader.h b/Firmware/Bootloader/Bootloader.h new file mode 100644 index 0000000..c6aaa90 --- /dev/null +++ b/Firmware/Bootloader/Bootloader.h @@ -0,0 +1,77 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaims all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Header file for BootloaderHID.c. + */ + +#ifndef _BOOTLOADERHID_H_ +#define _BOOTLOADERHID_H_ + + /* Includes: */ + #include + #include + #include + #include + #include + #include + + #include "Descriptors.h" + + #include + #include + + /* Preprocessor Checks: */ + #if !defined(__OPTIMIZE_SIZE__) + #error This bootloader requires that it be optimized for size, not speed, to fit into the target device. Change optimization settings and try again. + #endif + + /* Macros: */ + /** Bootloader special address to start the user application */ + #define COMMAND_VERSION 0x03 + #define COMMAND_STARTAPPLICATION 0x04 + #define COMMAND_PROGRAM 0x05 + + #define BOOTLOADER_VERSION 65000 + + /** Magic bootloader key to unlock forced application start mode. */ + #define MAGIC_BOOT_KEY 0xDC42 + + /* Function Prototypes: */ + static void SetupHardware(void); + + void Application_Jump_Check(void) ATTR_INIT_SECTION(3); + + void EVENT_USB_Device_ConfigurationChanged(void); + void EVENT_USB_Device_UnhandledControlRequest(void); + +#endif + diff --git a/Firmware/PocketVoltex/DFU/control_bootloader.py b/Firmware/PocketVoltex/DFU/control_bootloader.py new file mode 100644 index 0000000..68b5881 --- /dev/null +++ b/Firmware/PocketVoltex/DFU/control_bootloader.py @@ -0,0 +1,145 @@ +""" + LUFA Library + Copyright (C) Dean Camera, 2014. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +""" + +""" + Front-end programmer for the LUFA HID class bootloader. + + Usage: + python hid_bootloader_loader.py .hex + + Example: + python hid_bootloader_loader.py at90usb1287 Mouse.hex + + Requires the pywinusb (https://pypi.python.org/pypi/pywinusb/) and + IntelHex (http://bialix.com/intelhex/) libraries. +""" + +import sys +from intelhex import IntelHex +import time + +# new bootloader +import usb1 + +ENDPOINT_SIZE = 32 + +WEBUSB_ID = 0x01 +MS_OS_ID = 0x02 +CONFIG_ID = 0x03 + +COMMAND_VERSION = 0x03 +COMMAND_STARTAPPLICATION = 0x04 +COMMAND_PROGRAM = 0x05 + +BOOTLOADER_VERSION = 65000 + +# Device information table +device_info_map = dict() +device_info_map['at90usb1287'] = {'page_size': 256, 'flash_kb': 128} +device_info_map['at90usb1286'] = {'page_size': 256, 'flash_kb': 128} +device_info_map['at90usb647'] = {'page_size': 256, 'flash_kb': 64} +device_info_map['at90usb646'] = {'page_size': 256, 'flash_kb': 64} +device_info_map['atmega32u4'] = {'page_size': 128, 'flash_kb': 32} +device_info_map['atmega32u2'] = {'page_size': 128, 'flash_kb': 32} +device_info_map['atmega16u4'] = {'page_size': 128, 'flash_kb': 16} +device_info_map['atmega16u2'] = {'page_size': 128, 'flash_kb': 16} +device_info_map['at90usb162'] = {'page_size': 128, 'flash_kb': 16} +device_info_map['atmega8u2'] = {'page_size': 128, 'flash_kb': 8} +device_info_map['at90usb82'] = {'page_size': 128, 'flash_kb': 8} + +def get_version(device): + ver = device.controlRead(usb1.libusb1.LIBUSB_REQUEST_TYPE_VENDOR | usb1.libusb1.LIBUSB_RECIPIENT_DEVICE, CONFIG_ID, 0, COMMAND_VERSION, 2) + return ver[0] | ver[1] << 8 + +def get_device_handle(context): + voltex = None + for dev in context.getDeviceList(): + if dev.getVendorID() == 0x16D0 and dev.getProductID() == 0x0A6D: + # because there is the pseudo-composite-parent we ignore + try: + voltex = dev.open() + print "Open success!" + except: + print "Open fail" + return voltex + +def bootloader_boot(device): + with device.claimInterface(0): + device.bulkWrite(1, [42] + [0]*(ENDPOINT_SIZE-1)) + return True + +def send_page_data(device, address, data): + device.controlWrite(usb1.libusb1.LIBUSB_REQUEST_TYPE_VENDOR | usb1.libusb1.LIBUSB_RECIPIENT_DEVICE, + CONFIG_ID, address, COMMAND_PROGRAM, data) + + +def program_device(hex_data, device_info): + context = usb1.USBContext() + device = get_device_handle(context) + + if device is None: + print("No valid device found.") + sys.exit(1) + + if get_version(device) != BOOTLOADER_VERSION: + print("Device not in bootloader. TODO: reboot") + sys.exit(1) + + try: + print("Connected to bootloader.") + + # Program in all data from the loaded HEX file, in a number of device + # page sized chunks + for addr in range(0, hex_data.maxaddr(), device_info['page_size']): + # Compute the address range of the current page in the device + current_page_range = range(addr, addr+device_info['page_size']) + + # Extract the data from the hex file at the specified start page + # address and convert it to a regular list of bytes + page_data = [hex_data[i] for i in current_page_range] + + print("Writing address 0x%04X-0x%04X" % (current_page_range[0], current_page_range[-1])) + + # Devices with more than 64KB of flash should shift down the page + # address so that it is 16-bit (page size is guaranteed to be + # >= 256 bytes so no non-zero address bits are discarded) + if device_info['flash_kb'] < 64: + send_page_data(device, addr, page_data) + else: + send_page_data(device, addr >> 8, page_data) + + # Once programming is complete, start the application via a dummy page + # program to the page address 0xFFFF + print("Programming complete, starting application.") + try: + device.controlWrite(usb1.libusb1.LIBUSB_REQUEST_TYPE_VENDOR | usb1.libusb1.LIBUSB_RECIPIENT_DEVICE, + CONFIG_ID, 0, COMMAND_STARTAPPLICATION, []) # reboot, ignore pipe error + except usb1.USBErrorPipe: + pass + + finally: + device.close() + context.close() + + +if __name__ == '__main__': + # Load the specified HEX file + try: + hex_data = IntelHex(sys.argv[2]) + except: + print("Could not open the specified HEX file.") + sys.exit(1) + + # Retrieve the device information entry for the specified device + try: + device_info = device_info_map[sys.argv[1]] + except: + print("Unknown device name specified.") + sys.exit(1) + + program_device(hex_data, device_info) diff --git a/Firmware/PocketVoltex/LogCurveGen.py b/Firmware/PocketVoltex/LogCurveGen.py new file mode 100644 index 0000000..8781c94 --- /dev/null +++ b/Firmware/PocketVoltex/LogCurveGen.py @@ -0,0 +1,18 @@ +from __future__ import print_function +import math + +BRIGHTNESS_LEVELS = 64 + +print("// Generated by LogCurveGen.py") +print("PROGMEM const static uint8_t ledLogCurve[] = {", end='') +for i in range(BRIGHTNESS_LEVELS): + # newline every 8 + if i % 8 == 0: + print("\n\t", end='') + if i == 0: + mapped = 0 + else: + mapped = int(math.log(i,BRIGHTNESS_LEVELS-1) * BRIGHTNESS_LEVELS) + # map to the different order in the board + print('{}, '.format(mapped), end='') +print("};") diff --git a/Firmware/PocketVoltex/fader.xlsx b/Firmware/PocketVoltex/fader.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..f63fae4bb0cbad18c21312121d7a115576e31c2d GIT binary patch literal 29213 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 literal 0 HcmV?d00001