mirror of
https://github.com/mon/PocketVoltex.git
synced 2026-09-22 22:57:58 +03:00
Initial commit
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
Hardware/History/
|
||||
Hardware/__Previews/
|
||||
*.d
|
||||
*.sym
|
||||
*.o
|
||||
*.lss
|
||||
*.map
|
||||
*.eep
|
||||
*.bin
|
||||
*.elf
|
||||
Firmware/Bootloader/
|
||||
*.hex
|
||||
Firmware/LUFA/
|
||||
Hardware/Project Outputs for SDVX_Mini/
|
||||
Hardware/Project Logs for SDVX_Mini/
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <Config.h>
|
||||
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define MAGIC_NUMBER 43
|
||||
|
||||
static sdvx_config_t defaults PROGMEM = {
|
||||
.switches = {
|
||||
HID_KEYBOARD_SC_Z,
|
||||
HID_KEYBOARD_SC_X,
|
||||
HID_KEYBOARD_SC_DOT_AND_GREATER_THAN_SIGN,
|
||||
HID_KEYBOARD_SC_SLASH_AND_QUESTION_MARK,
|
||||
HID_KEYBOARD_SC_C,
|
||||
HID_KEYBOARD_SC_M,
|
||||
HID_KEYBOARD_SC_ENTER},
|
||||
.ledsOn = true,
|
||||
.debounce = 30
|
||||
};
|
||||
|
||||
uint8_t firstRun EEMEM; // init to 255
|
||||
sdvx_config_t eeConfig EEMEM;
|
||||
|
||||
sdvx_config_t sdvxConfig;
|
||||
|
||||
void InitConfig(void) {
|
||||
if (eeprom_read_byte(&firstRun) != MAGIC_NUMBER) { // store defaults
|
||||
memcpy_P(&sdvxConfig, &defaults, sizeof(sdvx_config_t));
|
||||
eeprom_write_block(&sdvxConfig, &eeConfig, sizeof(sdvx_config_t));
|
||||
eeprom_write_byte(&firstRun, MAGIC_NUMBER); // defaults set
|
||||
}
|
||||
eeprom_read_block(&sdvxConfig, &eeConfig, sizeof(sdvx_config_t));
|
||||
sdvxConfig.version = FIRMWARE_VERSION;
|
||||
}
|
||||
|
||||
void SetConfig(uint8_t* config) {
|
||||
memcpy(&sdvxConfig, config, sizeof(sdvx_config_t));
|
||||
// Version is set in firmware, not software
|
||||
sdvxConfig.version = FIRMWARE_VERSION;
|
||||
|
||||
eeprom_write_block(&sdvxConfig, &eeConfig, sizeof(sdvx_config_t));
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef _CONFIG_H
|
||||
#define _CONFIG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
|
||||
// For ease of code sharing with the OsuPad
|
||||
#define SWITCH_COUNT 7
|
||||
// essentially sizeof the config type + 1 for some reason
|
||||
// TODO: what is the reason
|
||||
#define CONFIG_BYTES (SWITCH_COUNT + 4)
|
||||
#define MAGIC_RESET_NUMBER 42
|
||||
#define FIRMWARE_VERSION 1
|
||||
|
||||
typedef struct {
|
||||
// SWITCH ORDER: A-D, FXL-R, START
|
||||
uint8_t switches[SWITCH_COUNT];
|
||||
bool ledsOn;
|
||||
uint8_t debounce;
|
||||
uint8_t version;
|
||||
} sdvx_config_t;
|
||||
|
||||
extern sdvx_config_t sdvxConfig;
|
||||
|
||||
extern void InitConfig(void);
|
||||
extern void SetConfig(uint8_t* config);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
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
|
||||
* \brief LUFA Library Configuration Header File
|
||||
*
|
||||
* This header file is used to configure LUFA's compile time options,
|
||||
* as an alternative to the compile time constants supplied through
|
||||
* a makefile.
|
||||
*
|
||||
* For information on what each token does, refer to the LUFA
|
||||
* manual section "Summary of Compile Tokens".
|
||||
*/
|
||||
|
||||
#ifndef _LUFA_CONFIG_H_
|
||||
#define _LUFA_CONFIG_H_
|
||||
/* Non-USB Related Configuration Tokens: */
|
||||
// #define DISABLE_TERMINAL_CODES
|
||||
|
||||
/* USB Class Driver Related Tokens: */
|
||||
// #define HID_HOST_BOOT_PROTOCOL_ONLY
|
||||
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_MAX_COLLECTIONS {Insert Value Here}
|
||||
// #define HID_MAX_REPORTITEMS {Insert Value Here}
|
||||
// #define HID_MAX_REPORT_IDS {Insert Value Here}
|
||||
// #define NO_CLASS_DRIVER_AUTOFLUSH
|
||||
|
||||
/* General USB Driver Related Tokens: */
|
||||
// #define ORDERED_EP_CONFIG
|
||||
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
|
||||
#define USB_DEVICE_ONLY
|
||||
// #define USB_HOST_ONLY
|
||||
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
|
||||
// #define NO_LIMITED_CONTROLLER_CONNECT
|
||||
// #define NO_SOF_EVENTS
|
||||
|
||||
/* USB Device Mode Driver Related Tokens: */
|
||||
// #define USE_RAM_DESCRIPTORS
|
||||
#define USE_FLASH_DESCRIPTORS
|
||||
// #define USE_EEPROM_DESCRIPTORS
|
||||
// #define NO_INTERNAL_SERIAL
|
||||
#define FIXED_CONTROL_ENDPOINT_SIZE 8
|
||||
// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
|
||||
#define FIXED_NUM_CONFIGURATIONS 1
|
||||
// #define CONTROL_ONLY_DEVICE
|
||||
// #define INTERRUPT_CONTROL_ENDPOINT
|
||||
// #define NO_DEVICE_REMOTE_WAKEUP
|
||||
// #define NO_DEVICE_SELF_POWER
|
||||
|
||||
/* USB Host Mode Driver Related Tokens: */
|
||||
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
|
||||
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
|
||||
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
|
||||
// #define NO_AUTO_VBUS_MANAGEMENT
|
||||
// #define INVERTED_VBUS_ENABLE_LINE
|
||||
#endif
|
||||
@@ -0,0 +1,120 @@
|
||||
"""
|
||||
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 <Device> <Input>.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 pywinusb import hid
|
||||
from intelhex import IntelHex
|
||||
|
||||
|
||||
# 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_hid_device_handle():
|
||||
hid_device_filter = hid.HidDeviceFilter(vendor_id=0x03EB,
|
||||
product_id=0x2067)
|
||||
|
||||
valid_hid_devices = hid_device_filter.get_devices()
|
||||
|
||||
if len(valid_hid_devices) is 0:
|
||||
return None
|
||||
else:
|
||||
return valid_hid_devices[0]
|
||||
|
||||
|
||||
def send_page_data(hid_device, address, data):
|
||||
# Bootloader page data should be the HID Report ID (always zero) followed
|
||||
# by the starting address to program, then one device's flash page worth
|
||||
# of data
|
||||
output_report_data = [0]
|
||||
output_report_data.extend([address & 0xFF, address >> 8])
|
||||
output_report_data.extend(data)
|
||||
|
||||
hid_device.send_output_report(output_report_data)
|
||||
|
||||
|
||||
def program_device(hex_data, device_info):
|
||||
hid_device = get_hid_device_handle()
|
||||
|
||||
if hid_device is None:
|
||||
print("No valid HID device found.")
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
hid_device.open()
|
||||
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(hid_device, addr, page_data)
|
||||
else:
|
||||
send_page_data(hid_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.")
|
||||
send_page_data(hid_device, 0xFFFF, [0] * device_info['page_size'])
|
||||
|
||||
finally:
|
||||
hid_device.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)
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
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
|
||||
*
|
||||
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
|
||||
* computer-readable structures which the host requests upon device enumeration, to determine
|
||||
* the device's capabilities and functions.
|
||||
*/
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
/** HID class report descriptor. This is a special descriptor constructed with values from the
|
||||
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
|
||||
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
|
||||
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
|
||||
* more details on HID report descriptors.
|
||||
*/
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM GenericReport[] =
|
||||
{
|
||||
HID_RI_USAGE_PAGE(16, 0xFFDC), /* Vendor Page 0xDC */
|
||||
HID_RI_USAGE(8, 0xFB), /* Vendor Usage 0xFB */
|
||||
HID_RI_COLLECTION(8, 0x01), /* Vendor Usage 1 */
|
||||
HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
|
||||
HID_RI_REPORT_SIZE(8, 8),
|
||||
HID_RI_REPORT_COUNT(8, CONFIG_BYTES),
|
||||
HID_RI_OUTPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
|
||||
HID_RI_USAGE(8, 0x02), /* Vendor Usage 2 */
|
||||
HID_RI_LOGICAL_MINIMUM(8, 0x00),
|
||||
HID_RI_LOGICAL_MAXIMUM(8, 0xFF),
|
||||
HID_RI_REPORT_SIZE(8, 8),
|
||||
HID_RI_REPORT_COUNT(8, CONFIG_BYTES),
|
||||
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE | HID_IOF_NON_VOLATILE),
|
||||
HID_RI_END_COLLECTION(0),
|
||||
};
|
||||
|
||||
/** HID class report descriptor. This is a special descriptor constructed with values from the
|
||||
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
|
||||
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
|
||||
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
|
||||
* more details on HID report descriptors.
|
||||
*/
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
||||
{
|
||||
// Use the HID class driver's standard Keyboard report
|
||||
HID_DESCRIPTOR_KEYBOARD(SWITCH_COUNT)
|
||||
};
|
||||
|
||||
/** HID class report descriptor. This is a special descriptor constructed with values from the
|
||||
* USBIF HID class specification to describe the reports and capabilities of the HID device. This
|
||||
* descriptor is parsed by the host and its contents used to determine what data (and in what encoding)
|
||||
* the device will send, and what it may be sent back from the host. Refer to the HID specification for
|
||||
* more details on HID report descriptors.
|
||||
*
|
||||
* This descriptor describes the mouse HID interface's report structure.
|
||||
*/
|
||||
const USB_Descriptor_HIDReport_Datatype_t PROGMEM MouseReport[] =
|
||||
{
|
||||
/* Use the HID class driver's standard Mouse report.
|
||||
* Min X/Y Axis values: -128
|
||||
* Max X/Y Axis values: 127
|
||||
* Min physical X/Y Axis values (used to determine resolution): -128
|
||||
* Max physical X/Y Axis values (used to determine resolution): 127
|
||||
* NOTE: need at least 1 button or report does not work
|
||||
* Buttons: 1
|
||||
* Absolute screen coordinates: false
|
||||
*/
|
||||
HID_DESCRIPTOR_MOUSE(-128, 127, -128, 127, 1, false)
|
||||
};
|
||||
|
||||
/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
|
||||
* device characteristics, including the supported USB version, control endpoint size and the
|
||||
* number of device configurations. The descriptor is read out by the USB host when the enumeration
|
||||
* process begins.
|
||||
*/
|
||||
const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
|
||||
|
||||
.USBSpecification = VERSION_BCD(1,1,0),
|
||||
.Class = USB_CSCP_NoDeviceClass,
|
||||
.SubClass = USB_CSCP_NoDeviceSubclass,
|
||||
.Protocol = USB_CSCP_NoDeviceProtocol,
|
||||
|
||||
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
|
||||
// mon.im VID/PID pair, unique!
|
||||
.VendorID = 0x16D0,
|
||||
.ProductID = 0x0A6D,
|
||||
.ReleaseNumber = VERSION_BCD(0,0,1),
|
||||
|
||||
.ManufacturerStrIndex = STRING_ID_Manufacturer,
|
||||
.ProductStrIndex = STRING_ID_Product,
|
||||
.SerialNumStrIndex = STRING_ID_Product,
|
||||
|
||||
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
|
||||
};
|
||||
|
||||
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
|
||||
* of the device in one of its supported configurations, including information about any device interfaces
|
||||
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
|
||||
* a configuration so that the host may correctly communicate with the USB device.
|
||||
*/
|
||||
const USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
{
|
||||
.Config =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration},
|
||||
|
||||
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t),
|
||||
.TotalInterfaces = 3,
|
||||
|
||||
.ConfigurationNumber = 1,
|
||||
.ConfigurationStrIndex = NO_DESCRIPTOR,
|
||||
|
||||
.ConfigAttributes = USB_CONFIG_ATTR_RESERVED,
|
||||
|
||||
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
|
||||
},
|
||||
|
||||
.HID1_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = INTERFACE_ID_Keyboard,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
|
||||
.InterfaceStrIndex = STRING_ID_Product
|
||||
},
|
||||
|
||||
.HID1_KeyboardHID =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||
|
||||
.HIDSpec = VERSION_BCD(1,1,1),
|
||||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(KeyboardReport)
|
||||
},
|
||||
|
||||
.HID1_ReportINEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = KEYBOARD_EPADDR,
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = KEYBOARD_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
|
||||
.HID2_MouseInterface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = INTERFACE_ID_Mouse,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_BootSubclass,
|
||||
.Protocol = HID_CSCP_MouseBootProtocol,
|
||||
|
||||
.InterfaceStrIndex = STRING_ID_Product
|
||||
},
|
||||
|
||||
.HID2_MouseHID =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||
|
||||
.HIDSpec = VERSION_BCD(1,1,1),
|
||||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(MouseReport)
|
||||
},
|
||||
|
||||
.HID2_ReportINEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = MOUSE_IN_EPADDR,
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = MOUSE_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
|
||||
.HID3_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = INTERFACE_ID_Generic,
|
||||
.AlternateSetting = 0x00,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = HID_CSCP_HIDClass,
|
||||
.SubClass = HID_CSCP_NonBootSubclass,
|
||||
.Protocol = HID_CSCP_NonBootProtocol,
|
||||
|
||||
.InterfaceStrIndex = STRING_ID_Config
|
||||
},
|
||||
|
||||
.HID3_VendorHID =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_HID_Descriptor_HID_t), .Type = HID_DTYPE_HID},
|
||||
|
||||
.HIDSpec = VERSION_BCD(1,1,1),
|
||||
.CountryCode = 0x00,
|
||||
.TotalReportDescriptors = 1,
|
||||
.HIDReportType = HID_DTYPE_Report,
|
||||
.HIDReportLength = sizeof(GenericReport)
|
||||
},
|
||||
|
||||
.HID3_ReportINEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = GENERIC_EPADDR,
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = GENERIC_EPSIZE,
|
||||
.PollingIntervalMS = 255
|
||||
},
|
||||
};
|
||||
|
||||
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
|
||||
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
|
||||
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
|
||||
*/
|
||||
const USB_Descriptor_String_t PROGMEM LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);
|
||||
|
||||
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
|
||||
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
|
||||
* Descriptor.
|
||||
*/
|
||||
const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR(L"mon.im");
|
||||
|
||||
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
|
||||
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
|
||||
* Descriptor.
|
||||
*/
|
||||
const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"Pocket Voltex");
|
||||
|
||||
|
||||
const USB_Descriptor_String_t PROGMEM ConfigString = USB_STRING_DESCRIPTOR(L"SDVX Config");
|
||||
|
||||
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
|
||||
* documentation) by the application code so that the address and size of a requested descriptor can be given
|
||||
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
|
||||
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
|
||||
* USB host.
|
||||
*/
|
||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||
const uint8_t wIndex,
|
||||
const void** const DescriptorAddress)
|
||||
{
|
||||
const uint8_t DescriptorType = (wValue >> 8);
|
||||
const uint8_t DescriptorNumber = (wValue & 0xFF);
|
||||
|
||||
const void* Address = NULL;
|
||||
uint16_t Size = NO_DESCRIPTOR;
|
||||
|
||||
switch (DescriptorType)
|
||||
{
|
||||
case DTYPE_Device:
|
||||
Address = &DeviceDescriptor;
|
||||
Size = sizeof(USB_Descriptor_Device_t);
|
||||
break;
|
||||
case DTYPE_Configuration:
|
||||
Address = &ConfigurationDescriptor;
|
||||
Size = sizeof(USB_Descriptor_Configuration_t);
|
||||
break;
|
||||
case DTYPE_String:
|
||||
switch (DescriptorNumber)
|
||||
{
|
||||
case STRING_ID_Language:
|
||||
Address = &LanguageString;
|
||||
Size = pgm_read_byte(&LanguageString.Header.Size);
|
||||
break;
|
||||
case STRING_ID_Manufacturer:
|
||||
Address = &ManufacturerString;
|
||||
Size = pgm_read_byte(&ManufacturerString.Header.Size);
|
||||
break;
|
||||
case STRING_ID_Product:
|
||||
Address = &ProductString;
|
||||
Size = pgm_read_byte(&ProductString.Header.Size);
|
||||
break;
|
||||
case STRING_ID_Config:
|
||||
Address = &ConfigString;
|
||||
Size = pgm_read_byte(&ConfigString.Header.Size);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case HID_DTYPE_HID:
|
||||
Size = sizeof(USB_HID_Descriptor_HID_t);
|
||||
switch (wIndex) {
|
||||
case INTERFACE_ID_Keyboard:
|
||||
Address = &ConfigurationDescriptor.HID1_KeyboardHID;
|
||||
break;
|
||||
case INTERFACE_ID_Mouse:
|
||||
Address = &ConfigurationDescriptor.HID2_MouseHID;
|
||||
break;
|
||||
case INTERFACE_ID_Generic:
|
||||
Address = &ConfigurationDescriptor.HID3_VendorHID;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HID_DTYPE_Report:
|
||||
switch (wIndex) {
|
||||
case INTERFACE_ID_Keyboard:
|
||||
Address = &KeyboardReport;
|
||||
Size = sizeof(KeyboardReport);
|
||||
break;
|
||||
case INTERFACE_ID_Mouse:
|
||||
Address = &MouseReport;
|
||||
Size = sizeof(MouseReport);
|
||||
break;
|
||||
case INTERFACE_ID_Generic:
|
||||
Address = &GenericReport;
|
||||
Size = sizeof(GenericReport);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*DescriptorAddress = Address;
|
||||
return Size;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
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 Descriptors.c.
|
||||
*/
|
||||
|
||||
#ifndef _DESCRIPTORS_H_
|
||||
#define _DESCRIPTORS_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for the device configuration descriptor structure. This must be defined in the
|
||||
* application code, as the configuration descriptor contains several sub-descriptors which
|
||||
* vary between devices, and which describe the device's usage to the host.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
USB_Descriptor_Configuration_Header_t Config;
|
||||
|
||||
// Keyboard HID Interface
|
||||
USB_Descriptor_Interface_t HID1_Interface;
|
||||
USB_HID_Descriptor_HID_t HID1_KeyboardHID;
|
||||
USB_Descriptor_Endpoint_t HID1_ReportINEndpoint;
|
||||
|
||||
// Mouse HID Interface
|
||||
USB_Descriptor_Interface_t HID2_MouseInterface;
|
||||
USB_HID_Descriptor_HID_t HID2_MouseHID;
|
||||
USB_Descriptor_Endpoint_t HID2_ReportINEndpoint;
|
||||
|
||||
// Generic HID Interface for configuration
|
||||
USB_Descriptor_Interface_t HID3_Interface;
|
||||
USB_HID_Descriptor_HID_t HID3_VendorHID;
|
||||
USB_Descriptor_Endpoint_t HID3_ReportINEndpoint;
|
||||
} USB_Descriptor_Configuration_t;
|
||||
|
||||
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
|
||||
* should have a unique ID index associated with it, which can be used to refer to the
|
||||
* interface from other descriptors.
|
||||
*/
|
||||
enum InterfaceDescriptors_t
|
||||
{
|
||||
INTERFACE_ID_Keyboard = 0, /**< Keyboard interface descriptor ID */
|
||||
INTERFACE_ID_Mouse = 1, /**< Mouse interface descriptor ID */
|
||||
INTERFACE_ID_Generic = 2 /**< Generic interface descriptor ID */
|
||||
};
|
||||
|
||||
/** Enum for the device string descriptor IDs within the device. Each string descriptor should
|
||||
* have a unique ID index associated with it, which can be used to refer to the string from
|
||||
* other descriptors.
|
||||
*/
|
||||
enum StringDescriptors_t
|
||||
{
|
||||
STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
|
||||
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
|
||||
STRING_ID_Product = 2, /**< Product string ID */
|
||||
STRING_ID_Config = 3 /**< Config string ID */
|
||||
};
|
||||
|
||||
/* Macros: */
|
||||
/** Endpoint address of the Keyboard HID reporting IN endpoint. */
|
||||
#define KEYBOARD_EPADDR (ENDPOINT_DIR_IN | 1)
|
||||
|
||||
#define MOUSE_IN_EPADDR (ENDPOINT_DIR_IN | 2)
|
||||
|
||||
#define GENERIC_EPADDR (ENDPOINT_DIR_IN | 3)
|
||||
|
||||
/** Size in bytes of the Keyboard HID reporting IN endpoint. */
|
||||
#define KEYBOARD_EPSIZE 8
|
||||
#define MOUSE_EPSIZE 8
|
||||
#define GENERIC_EPSIZE CONFIG_BYTES
|
||||
|
||||
/* Function Prototypes: */
|
||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||
const uint8_t wIndex,
|
||||
const void** const DescriptorAddress)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
#include "Encoder.h"
|
||||
|
||||
// SDVX Controller - PD0-3
|
||||
#define ENCODER_COUNT 2
|
||||
|
||||
#define ENCODER_PORT PORTD
|
||||
#define ENCODER_PIN PIND
|
||||
#define ENCODER_DDR DDRD
|
||||
|
||||
#define GET_ENCODER_0() (ENCODER_PIN & 0b11)
|
||||
#define GET_ENCODER_1() ((ENCODER_PIN >> 2) & 0b11)
|
||||
|
||||
typedef struct {
|
||||
int8_t position;
|
||||
uint8_t state;
|
||||
} encoder_t;
|
||||
|
||||
static volatile encoder_t encoders[ENCODER_COUNT] = {};
|
||||
|
||||
void encoder_init(void) {
|
||||
// inputs
|
||||
ENCODER_DDR &= ~0x0F;
|
||||
// pullups
|
||||
ENCODER_PORT |= 0x0F;
|
||||
|
||||
encoders[0].state = GET_ENCODER_0();
|
||||
encoders[1].state = GET_ENCODER_1();
|
||||
|
||||
// Edge interrupts on all INT pins
|
||||
EICRA = _BV(ISC30) | _BV(ISC20) | _BV(ISC10) | _BV(ISC00);
|
||||
// Enable the interrupts
|
||||
EIMSK = _BV(INT3) | _BV(INT2) | _BV(INT1) | _BV(INT0);
|
||||
// Clear interrupt flags
|
||||
EIFR = _BV(INTF3) | _BV(INTF2) | _BV(INTF1) | _BV(INTF0);
|
||||
}
|
||||
|
||||
int8_t encoder_get(uint8_t num) {
|
||||
return encoders[num].position;
|
||||
}
|
||||
|
||||
void encoder_set(uint8_t num, int8_t val) {
|
||||
encoders[num].position = val;
|
||||
}
|
||||
|
||||
// Adapted from the wonderful Encoder.h by PJRC
|
||||
void update(uint8_t num, uint8_t newState) {
|
||||
int8_t position = encoders[num].position;
|
||||
uint8_t state = encoders[num].state | (newState << 2);
|
||||
encoders[num].state = newState;
|
||||
switch (state) {
|
||||
case 1: case 7: case 8: case 14:
|
||||
if(position < 127)
|
||||
encoders[num].position++;
|
||||
return;
|
||||
case 2: case 4: case 11: case 13:
|
||||
if(position > -128)
|
||||
encoders[num].position--;
|
||||
return;
|
||||
case 3: case 12:
|
||||
if(position < 125)
|
||||
encoders[num].position += 2;
|
||||
return;
|
||||
case 6: case 9:
|
||||
if(position > -126)
|
||||
encoders[num].position -= 2;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ISR(INT0_vect) { update(0, GET_ENCODER_0()); }
|
||||
ISR(INT1_vect) { update(0, GET_ENCODER_0()); }
|
||||
ISR(INT2_vect) { update(1, GET_ENCODER_1()); }
|
||||
ISR(INT3_vect) { update(1, GET_ENCODER_1()); }
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef Encoder_h_
|
||||
#define Encoder_h_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
void encoder_init(void);
|
||||
int8_t encoder_get(uint8_t num);
|
||||
void encoder_set(uint8_t num, int8_t val);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
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 Keyboard demo. This file contains the main tasks of
|
||||
* the demo and is responsible for the initial application hardware configuration.
|
||||
*/
|
||||
|
||||
#include "Keyboard.h"
|
||||
#include "Config.h"
|
||||
#include "Encoder.h"
|
||||
|
||||
#define READ_SWITCH(x) (!(*pins[switches[x].switchPort] & _BV(switches[x].switchPin)))
|
||||
#define SET_LED(x) (*ports[switches[x].lightPort] |= _BV(switches[x].lightPin))
|
||||
#define CLEAR_LED(x) (*ports[switches[x].lightPort] &= ~_BV(switches[x].lightPin))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Modifier; // Keyboard modifier byte indicating pressed modifier keys (\c HID_KEYBOARD_MODIFER_* masks)
|
||||
uint8_t Reserved; // Reserved for OEM use, always set to 0.
|
||||
uint8_t KeyCode[SWITCH_COUNT]; // Length determined by the number of keys that can be reported
|
||||
} Keyboard_Report_t;
|
||||
|
||||
/** Buffer to hold the previously generated Keyboard HID report, for comparison purposes inside the HID class driver. */
|
||||
static uint8_t PrevKeyboardHIDReportBuffer[sizeof(Keyboard_Report_t)];
|
||||
static uint8_t PrevMouseHIDReportBuffer[sizeof(USB_MouseReport_Data_t)];
|
||||
static uint8_t PrevGenericHIDReportBuffer[CONFIG_BYTES];
|
||||
|
||||
/** LUFA HID Class driver interface configuration and state information. This structure is
|
||||
* passed to all HID Class driver functions, so that multiple instances of the same class
|
||||
* within a device can be differentiated from one another.
|
||||
*/
|
||||
USB_ClassInfo_HID_Device_t Keyboard_HID_Interface =
|
||||
{
|
||||
.Config =
|
||||
{
|
||||
.InterfaceNumber = INTERFACE_ID_Keyboard,
|
||||
.ReportINEndpoint =
|
||||
{
|
||||
.Address = KEYBOARD_EPADDR,
|
||||
.Size = KEYBOARD_EPSIZE,
|
||||
.Banks = 1,
|
||||
},
|
||||
.PrevReportINBuffer = PrevKeyboardHIDReportBuffer,
|
||||
.PrevReportINBufferSize = sizeof(PrevKeyboardHIDReportBuffer),
|
||||
},
|
||||
};
|
||||
|
||||
/** LUFA HID Class driver interface configuration and state information. This structure is
|
||||
* passed to all HID Class driver functions, so that multiple instances of the same class
|
||||
* within a device can be differentiated from one another. This is for the mouse HID
|
||||
* interface within the device.
|
||||
*/
|
||||
USB_ClassInfo_HID_Device_t Mouse_HID_Interface =
|
||||
{
|
||||
.Config =
|
||||
{
|
||||
.InterfaceNumber = INTERFACE_ID_Mouse,
|
||||
.ReportINEndpoint =
|
||||
{
|
||||
.Address = MOUSE_IN_EPADDR,
|
||||
.Size = MOUSE_EPSIZE,
|
||||
.Banks = 1,
|
||||
},
|
||||
.PrevReportINBuffer = PrevMouseHIDReportBuffer,
|
||||
.PrevReportINBufferSize = sizeof(PrevMouseHIDReportBuffer),
|
||||
},
|
||||
};
|
||||
|
||||
USB_ClassInfo_HID_Device_t Generic_HID_Interface =
|
||||
{
|
||||
.Config =
|
||||
{
|
||||
.InterfaceNumber = INTERFACE_ID_Generic,
|
||||
.ReportINEndpoint =
|
||||
{
|
||||
.Address = GENERIC_EPADDR,
|
||||
.Size = GENERIC_EPSIZE,
|
||||
.Banks = 1,
|
||||
},
|
||||
.PrevReportINBuffer = PrevGenericHIDReportBuffer,
|
||||
.PrevReportINBufferSize = sizeof(PrevGenericHIDReportBuffer),
|
||||
},
|
||||
};
|
||||
|
||||
// NOTE: atemga16u2 does not have a PORTA
|
||||
typedef enum {
|
||||
B = 0,
|
||||
C,
|
||||
D
|
||||
} port_t;
|
||||
|
||||
static volatile uint8_t *ports[] = {&PORTB, &PORTC, &PORTD};
|
||||
static volatile uint8_t *pins[] = {&PINB, &PINC, &PIND};
|
||||
static volatile uint8_t *ddrs[] = {&DDRB, &DDRC, &DDRD};
|
||||
|
||||
typedef struct {
|
||||
port_t switchPort;
|
||||
uint8_t switchPin;
|
||||
port_t lightPort;
|
||||
uint8_t lightPin;
|
||||
uint8_t state;
|
||||
uint8_t lastReport;
|
||||
uint8_t debounce;
|
||||
} switch_t;
|
||||
|
||||
static switch_t switches[SWITCH_COUNT] = {
|
||||
{C, 7, C, 6}, // A
|
||||
{B, 4, B, 5}, // B
|
||||
{B, 2, B, 3}, // C
|
||||
{D, 6, D, 7}, // D
|
||||
{B, 6, B, 7}, // FX L
|
||||
{B, 0, B, 1}, // FX R
|
||||
{D, 5, D, 4} // START
|
||||
};
|
||||
static uint8_t switchesChanged = 1;
|
||||
|
||||
uint32_t Boot_Key ATTR_NO_INIT;
|
||||
#define MAGIC_BOOT_KEY 0xDEADBE7A
|
||||
// offset * word size
|
||||
#define BOOTLOADER_START_ADDRESS (0x1c00 * 2)
|
||||
|
||||
void Bootloader_Jump_Check(void) ATTR_INIT_SECTION(3);
|
||||
void Bootloader_Jump_Check(void)
|
||||
{
|
||||
// If the reset source was the bootloader and the key is correct, clear it and jump to the bootloader
|
||||
if ((MCUSR & (1 << WDRF)) && (Boot_Key == MAGIC_BOOT_KEY))
|
||||
{
|
||||
Boot_Key = 0;
|
||||
((void (*)(void))BOOTLOADER_START_ADDRESS)();
|
||||
}
|
||||
}
|
||||
|
||||
void RebootToBootloader(void) {
|
||||
// With this uncommented, reboot fails. Odd.
|
||||
//USB_Disable();
|
||||
cli();
|
||||
|
||||
// Back to the bootloader
|
||||
Boot_Key = MAGIC_BOOT_KEY;
|
||||
wdt_enable(WDTO_250MS);
|
||||
while(1);
|
||||
}
|
||||
|
||||
void update_switches(void) {
|
||||
uint8_t i, newState;
|
||||
|
||||
for(i = 0; i < SWITCH_COUNT; i++) {
|
||||
// The I2C data starts at the 6th bit and goes down
|
||||
newState = READ_SWITCH(i);
|
||||
if(newState) {
|
||||
SET_LED(i);
|
||||
} else {
|
||||
CLEAR_LED(i);
|
||||
}
|
||||
if(!switches[i].debounce && newState != switches[i].lastReport) {
|
||||
switches[i].state = newState;
|
||||
switches[i].debounce = sdvxConfig.debounce;
|
||||
switchesChanged = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Main program entry point. This routine contains the overall program flow, including initial
|
||||
* setup of all components and the main program loop.
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
GlobalInterruptDisable();
|
||||
|
||||
uint8_t i;
|
||||
|
||||
InitConfig();
|
||||
|
||||
SetupHardware();
|
||||
|
||||
// FX_L held while plugging in
|
||||
if(READ_SWITCH(4)) {
|
||||
RebootToBootloader();
|
||||
}
|
||||
|
||||
// Blink to show we're not in bootloader
|
||||
for(i = 0; i < SWITCH_COUNT; i++) {
|
||||
*ports[switches[i].lightPort] |= _BV(switches[i].lightPin);
|
||||
_delay_ms(50);
|
||||
*ports[switches[i].lightPort] &= ~_BV(switches[i].lightPin);
|
||||
}
|
||||
|
||||
GlobalInterruptEnable();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
HID_Device_USBTask(&Keyboard_HID_Interface);
|
||||
HID_Device_USBTask(&Mouse_HID_Interface);
|
||||
HID_Device_USBTask(&Generic_HID_Interface);
|
||||
USB_USBTask();
|
||||
}
|
||||
}
|
||||
|
||||
/** Configures the board hardware and chip peripherals for the demo's functionality. */
|
||||
void SetupHardware()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/* Disable watchdog if enabled by bootloader/fuses */
|
||||
MCUSR &= ~(1 << WDRF);
|
||||
wdt_disable();
|
||||
|
||||
for(i = 0; i < SWITCH_COUNT; i++) {
|
||||
switches[i].state = 0;
|
||||
switches[i].lastReport = 0;
|
||||
switches[i].debounce = 0;
|
||||
// setup switches to be inputs
|
||||
*ddrs[switches[i].switchPort] &= ~_BV(switches[i].switchPin);
|
||||
// with internal pullups
|
||||
*ports[switches[i].switchPort] |= _BV(switches[i].switchPin);
|
||||
// setup LEDs to be outputs
|
||||
*ddrs[switches[i].lightPort] |= _BV(switches[i].lightPin);
|
||||
// off by default
|
||||
*ports[switches[i].lightPort] &= ~_BV(switches[i].lightPin);
|
||||
}
|
||||
|
||||
/* Hardware Initialization */
|
||||
encoder_init();
|
||||
USB_Init();
|
||||
}
|
||||
|
||||
/** HID class driver callback function for the creation of HID reports to the host.
|
||||
*
|
||||
* \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced
|
||||
* \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID
|
||||
* \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature
|
||||
* \param[out] ReportData Pointer to a buffer where the created report should be stored
|
||||
* \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent)
|
||||
*
|
||||
* \return Boolean \c true to force the sending of the report, \c false to let the library determine if it needs to be sent
|
||||
*/
|
||||
bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
|
||||
uint8_t* const ReportID,
|
||||
const uint8_t ReportType,
|
||||
void* ReportData,
|
||||
uint16_t* const ReportSize)
|
||||
{
|
||||
if(ReportType != HID_REPORT_ITEM_In) {
|
||||
*ReportSize = 0;
|
||||
return false;
|
||||
}
|
||||
if (HIDInterfaceInfo == &Keyboard_HID_Interface) {
|
||||
Keyboard_Report_t* KeyboardReport = (Keyboard_Report_t*)ReportData;
|
||||
update_switches();
|
||||
|
||||
if(!switchesChanged) {
|
||||
*ReportSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < SWITCH_COUNT; i++) {
|
||||
KeyboardReport->KeyCode[i] = switches[i].state ? sdvxConfig.switches[i] : 0;
|
||||
switches[i].lastReport = switches[i].state;
|
||||
// Update blinkenlights
|
||||
if(switches[i].state) {
|
||||
if(sdvxConfig.ledsOn) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ReportSize = sizeof(Keyboard_Report_t);
|
||||
|
||||
switchesChanged = 0;
|
||||
return true;
|
||||
} else if(HIDInterfaceInfo == &Mouse_HID_Interface) {
|
||||
USB_MouseReport_Data_t* MouseReport = (USB_MouseReport_Data_t*)ReportData;
|
||||
|
||||
MouseReport->X = encoder_get(0);
|
||||
MouseReport->Y = -encoder_get(1);
|
||||
|
||||
encoder_set(0, 0);
|
||||
encoder_set(1, 0);
|
||||
|
||||
*ReportSize = sizeof(USB_MouseReport_Data_t);
|
||||
return true;
|
||||
} else if(HIDInterfaceInfo == &Generic_HID_Interface) {
|
||||
uint8_t* ConfigReport = (uint8_t*)ReportData;
|
||||
memcpy(ConfigReport, &sdvxConfig, sizeof(sdvx_config_t));
|
||||
*ReportSize = CONFIG_BYTES;
|
||||
return true;
|
||||
}
|
||||
*ReportSize = 0;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/** HID class driver callback function for the processing of HID reports from the host.
|
||||
*
|
||||
* \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced
|
||||
* \param[in] ReportID Report ID of the received report from the host
|
||||
* \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature
|
||||
* \param[in] ReportData Pointer to a buffer where the received report has been stored
|
||||
* \param[in] ReportSize Size in bytes of the received HID report
|
||||
*/
|
||||
void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
|
||||
const uint8_t ReportID,
|
||||
const uint8_t ReportType,
|
||||
const void* ReportData,
|
||||
const uint16_t ReportSize)
|
||||
{
|
||||
if(HIDInterfaceInfo == &Generic_HID_Interface && ReportType == HID_REPORT_ITEM_Out) {
|
||||
uint8_t* ConfigReport = (uint8_t*)ReportData;
|
||||
// So we can upgrade firmware without having to hit the button
|
||||
if(ConfigReport[CONFIG_BYTES-1] == MAGIC_RESET_NUMBER) {
|
||||
RebootToBootloader();
|
||||
}
|
||||
SetConfig(ConfigReport);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Event handler for the library USB Connection event. */
|
||||
void EVENT_USB_Device_Connect(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** Event handler for the library USB Disconnection event. */
|
||||
void EVENT_USB_Device_Disconnect(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** Event handler for the library USB Configuration Changed event. */
|
||||
void EVENT_USB_Device_ConfigurationChanged(void)
|
||||
{
|
||||
HID_Device_ConfigureEndpoints(&Keyboard_HID_Interface);
|
||||
HID_Device_ConfigureEndpoints(&Mouse_HID_Interface);
|
||||
HID_Device_ConfigureEndpoints(&Generic_HID_Interface);
|
||||
|
||||
USB_Device_EnableSOFEvents();
|
||||
}
|
||||
|
||||
/** Event handler for the library USB Control Request reception event. */
|
||||
void EVENT_USB_Device_ControlRequest(void)
|
||||
{
|
||||
HID_Device_ProcessControlRequest(&Keyboard_HID_Interface);
|
||||
HID_Device_ProcessControlRequest(&Mouse_HID_Interface);
|
||||
HID_Device_ProcessControlRequest(&Generic_HID_Interface);
|
||||
}
|
||||
|
||||
/** Event handler for the USB device Start Of Frame event. */
|
||||
void EVENT_USB_Device_StartOfFrame(void)
|
||||
{
|
||||
HID_Device_MillisecondElapsed(&Keyboard_HID_Interface);
|
||||
HID_Device_MillisecondElapsed(&Mouse_HID_Interface);
|
||||
HID_Device_MillisecondElapsed(&Generic_HID_Interface);
|
||||
|
||||
for(int i = 0; i < SWITCH_COUNT; i++) {
|
||||
if(switches[i].debounce) {
|
||||
switches[i].debounce--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
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 Keyboard.c.
|
||||
*/
|
||||
|
||||
#ifndef _KEYBOARD_H_
|
||||
#define _KEYBOARD_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/power.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
#include <LUFA/Platform/Platform.h>
|
||||
|
||||
/* Function Prototypes: */
|
||||
void SetupHardware(void);
|
||||
|
||||
void EVENT_USB_Device_Connect(void);
|
||||
void EVENT_USB_Device_Disconnect(void);
|
||||
void EVENT_USB_Device_ConfigurationChanged(void);
|
||||
void EVENT_USB_Device_ControlRequest(void);
|
||||
void EVENT_USB_Device_StartOfFrame(void);
|
||||
|
||||
bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
|
||||
uint8_t* const ReportID,
|
||||
const uint8_t ReportType,
|
||||
void* ReportData,
|
||||
uint16_t* const ReportSize);
|
||||
void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,
|
||||
const uint8_t ReportID,
|
||||
const uint8_t ReportType,
|
||||
const void* ReportData,
|
||||
const uint16_t ReportSize);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// https://github.com/SFE-Chris/UNO-HIDKeyboard-Library/blob/master/HIDKeyboard.h
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// HID Values of Function Keys
|
||||
#define F1 0x3a
|
||||
#define F2 0x3b
|
||||
#define F3 0x3c
|
||||
#define F4 0x3d
|
||||
#define F5 0x3e
|
||||
#define F6 0x3f
|
||||
#define F7 0x40
|
||||
#define F8 0x41
|
||||
#define F9 0x42
|
||||
#define F10 0x43
|
||||
#define F11 0x44
|
||||
#define F12 0x45
|
||||
|
||||
// HID Values of Special Keys
|
||||
#define ENTER 0x28
|
||||
#define ESCAPE 0x29
|
||||
#define BACKSPACE 0x2a
|
||||
#define TAB 0x2b
|
||||
#define SPACEBAR 0x2c
|
||||
#define CAPSLOCK 0x39
|
||||
#define PRINTSCREEN 0x46
|
||||
#define SCROLLLOCK 0x47
|
||||
#define PAUSE 0x48
|
||||
#define INSERT 0x49
|
||||
#define HOME 0x4a
|
||||
#define PAGEUP 0x4b
|
||||
#define DELETE 0x4c
|
||||
#define END 0x4d
|
||||
#define PAGEDOWN 0x4e
|
||||
#define RIGHTARROW 0x4f
|
||||
#define LEFTARROW 0x50
|
||||
#define DOWNARROW 0x51
|
||||
#define UPARROW 0x52
|
||||
|
||||
// HID Values of Keypad Keys
|
||||
#define NUMLOCK 0x53
|
||||
#define KEYPADSLASH 0x54
|
||||
#define KEYPADSTAR 0x55
|
||||
#define KEYPADMINUS 0x56
|
||||
#define KEYPADPLUS 0x57
|
||||
#define KEYPADENTER 0x58
|
||||
#define KEYPAD1 0x59
|
||||
#define KEYPAD2 0x5a
|
||||
#define KEYPAD3 0x5b
|
||||
#define KEYPAD4 0x5c
|
||||
#define KEYPAD5 0x5d
|
||||
#define KEYPAD6 0x5e
|
||||
#define KEYPAD7 0x5f
|
||||
#define KEYPAD8 0x60
|
||||
#define KEYPAD9 0x61
|
||||
#define KEYPAD0 0x62
|
||||
#define KEYPADPERIOD 0x63
|
||||
|
||||
// HID Values of System Keys
|
||||
#define KEYBOARDAPPLICATION 0x65
|
||||
#define KEYBOARDPOWER 0x66
|
||||
#define VOLUMEMUTE 0x7f
|
||||
#define VOLUMEUP 0x80
|
||||
#define VOLUMEDOWN 0x81
|
||||
|
||||
// Common-use modifiers
|
||||
#define CTRL 0x01
|
||||
#define SHIFT 0x02
|
||||
#define ALT 0x04
|
||||
#define GUI 0x08
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* ASCII->HID LOOKUP TABLE
|
||||
*
|
||||
* Taken from the HID Table definition at
|
||||
* http://www.usb.org/developers/devclass_docs/Hut1_11.pdf
|
||||
*
|
||||
* This array maps the ASCII value of a type-able character to its
|
||||
* corresponding HID value.
|
||||
*
|
||||
* Example:
|
||||
* 'a' = ASCII value 97 = HID value 0x04
|
||||
* HIDTable['a'] = HIDTable[97] = 0x04
|
||||
*
|
||||
* NOTE:
|
||||
* "Shift Modified" HID values are the same as the non Shift-Modified values
|
||||
* for any given character, e.g. the HID value for '2' is equal to the
|
||||
* HID value for '@'. The Shift-Modified value is sent by setting the
|
||||
* modifier value (buf[0]) to the corresponding modifier value in the
|
||||
* modifier table.
|
||||
*
|
||||
****************************************************************************/
|
||||
PROGMEM uint8_t HIDTable[] = {
|
||||
0x00, // 0
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x28, // 10
|
||||
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, // 30
|
||||
0x00, 0x2c, 0x1e, 0x34, 0x20, 0x21, 0x22, 0x24, 0x34, 0x26, // 40
|
||||
0x27, 0x25, 0x2e, 0x36, 0x2d, 0x37, 0x38, 0x27, 0x1e, 0x1f, // 50
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x33, 0x33, 0x36, // 60
|
||||
0x2e, 0x37, 0x38, 0x1f, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, // 70
|
||||
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // 80
|
||||
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, // 90
|
||||
0x2f, 0x31, 0x30, 0x23, 0x2d, 0x35, 0x04, 0x05, 0x06, 0x07, // 100
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // 110
|
||||
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, // 120
|
||||
0x1c, 0x1d, 0x2f, 0x31, 0x30, 0x35, 127 // 127
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* ASCII->MODIFIER LOOKUP TABLE
|
||||
*
|
||||
* Looks up whether or not the HID report should use the SHIFT modifier.
|
||||
*
|
||||
* Example:
|
||||
* The character '2' and the character '@' have different ASCII values but
|
||||
* the same HID value. This table uses the ASCII value to determine if
|
||||
* we should hold shift while sending the key. e.g.:
|
||||
*
|
||||
* HIDTable['2'] = 0x1f and modifierTable['2'] = 0
|
||||
* HIDTable['@'] = 0x1f and modifierTable['@'] = SHIFT
|
||||
*
|
||||
* There's probaly a better way to do this, but it's functional.
|
||||
*
|
||||
****************************************************************************/
|
||||
PROGMEM uint8_t modifierTable[] = {
|
||||
0x00, // 0
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 10
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 20
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 30
|
||||
0x00, 0x00, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 40
|
||||
SHIFT, 0x00, SHIFT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 50
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, SHIFT, 0x00, SHIFT, // 60
|
||||
0x00, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 70
|
||||
SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 80
|
||||
SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, SHIFT, // 90
|
||||
0x00, 0x00, 0x00, SHIFT, SHIFT, 0x00, 0x00, 0x00, 0x00, 0x00, // 100
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 110
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 120
|
||||
0x00, 0x00, SHIFT, SHIFT, SHIFT, SHIFT, 0x00 // 127
|
||||
};
|
||||
@@ -0,0 +1,69 @@
|
||||
#
|
||||
# LUFA Library
|
||||
# Copyright (C) Dean Camera, 2014.
|
||||
#
|
||||
# dean [at] fourwalledcubicle [dot] com
|
||||
# www.lufa-lib.org
|
||||
#
|
||||
# --------------------------------------
|
||||
# LUFA Project Makefile.
|
||||
# --------------------------------------
|
||||
|
||||
# Run "make help" for target help.
|
||||
|
||||
MCU = atmega16u2
|
||||
ARCH = AVR8
|
||||
BOARD = USER
|
||||
F_CPU = 8000000
|
||||
F_USB = $(F_CPU)
|
||||
OPTIMIZATION = s
|
||||
TARGET = Keyboard
|
||||
SRC = $(TARGET).c Descriptors.c Config.c Encoder.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
|
||||
LUFA_PATH = ../LUFA
|
||||
CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/
|
||||
LD_FLAGS =
|
||||
|
||||
AVRDUDE = avrdude -B 8 -c usbasp -p $(MCU)
|
||||
|
||||
|
||||
# Default target
|
||||
all:
|
||||
|
||||
# Include LUFA build script makefiles
|
||||
include $(LUFA_PATH)/Build/lufa_core.mk
|
||||
include $(LUFA_PATH)/Build/lufa_sources.mk
|
||||
include $(LUFA_PATH)/Build/lufa_build.mk
|
||||
include $(LUFA_PATH)/Build/lufa_cppcheck.mk
|
||||
include $(LUFA_PATH)/Build/lufa_doxygen.mk
|
||||
include $(LUFA_PATH)/Build/lufa_dfu.mk
|
||||
include $(LUFA_PATH)/Build/lufa_hid.mk
|
||||
include $(LUFA_PATH)/Build/lufa_avrdude.mk
|
||||
include $(LUFA_PATH)/Build/lufa_atprogram.mk
|
||||
|
||||
debug: CC_FLAGS += -DDEBUG
|
||||
debug: clean flash
|
||||
|
||||
init: erase wfuse flashboot flash
|
||||
|
||||
initboot: erase wfuse flashboot
|
||||
|
||||
erase:
|
||||
$(AVRDUDE) -e
|
||||
|
||||
rfuse:
|
||||
$(AVRDUDE) -U hfuse:r:-:h -U lfuse:r:-:h -U efuse:r:-:h
|
||||
|
||||
wfuse:
|
||||
$(AVRDUDE) -U lfuse:w:0xde:m -U hfuse:w:0xdb:m -U efuse:w:0xf6:m
|
||||
|
||||
# To make this hex, compile HID Bootloader in LUFA
|
||||
# FLASH_SIZE_KB := 16
|
||||
# BOOT_SECTION_SIZE_KB := 2
|
||||
# MCU = atmega16u2
|
||||
# ARCH = AVR8
|
||||
flashboot:
|
||||
$(AVRDUDE) -U flash:w:DFU/BootloaderHID.hex:i
|
||||
|
||||
flash: all
|
||||
sleep 1
|
||||
python DFU/hid_bootloader_loader.py atmega16u2 Keyboard.hex
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
Record=TopLevelDocument|FileName=SDVX_Mini.SchDoc
|
||||
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
Part/Designator,OPL SKU,Quantity,comment
|
||||
C1,302010003,1,0402 1uf
|
||||
C2,302010053,1,0402 10uf
|
||||
R1,301010289,1,0603 22r
|
||||
R2,301010052,1,0402 22r
|
||||
R3,301010004,1,0402 10k
|
||||
"R4,R5,R6,R7,R8,R9,R10",301010163,7,0603 220r
|
||||
U1,310010018,1,atmega
|
||||
J1,320010005,1,usb conn
|
||||
XT1,306030005,1,resonator
|
||||
|
Reference in New Issue
Block a user