Added HID etc code
This commit is contained in:
parent
388e8efeb6
commit
ff15d4815a
|
@ -1,5 +1,7 @@
|
|||
# STM32 Boards
|
||||
|
||||
|
||||
menu.usb = USB Type
|
||||
menu.device_variant=Variant
|
||||
menu.bootloader_version=Bootloader version
|
||||
menu.upload_method=Upload method
|
||||
|
@ -12,7 +14,7 @@ mapleMini.build.board=MAPLE_MINI
|
|||
mapleMini.vid.0=0x1EAF
|
||||
mapleMini.pid.0=0x0004
|
||||
mapleMini.build.core=maple
|
||||
mapleMini.build.cpu_flags=-DMCU_STM32F103CB -DSERIAL_USB
|
||||
mapleMini.build.cpu_flags=-DMCU_STM32F103CB -DUSB_HARDWARE
|
||||
mapleMini.build.variant=maple_mini
|
||||
mapleMini.upload.usbID=1EAF:0003
|
||||
|
||||
|
@ -21,6 +23,18 @@ mapleMini.upload.protocol=maple_dfu
|
|||
mapleMini.upload.use_1200bps_touch=false
|
||||
mapleMini.upload.file_type=bin
|
||||
mapleMini.upload.auto_reset=true
|
||||
mapleMini.menu.usb.serial=Serial
|
||||
mapleMini.menu.usb.serial.build.usbtype=USB_SERIAL
|
||||
mapleMini.menu.usb.hid_kmj=Keyboard + Mouse + Joystick
|
||||
mapleMini.menu.usb.hid_kmj.build.usbtype=USB_HID_KMJ
|
||||
mapleMini.menu.usb.hid_km=Keyboard + Mouse
|
||||
mapleMini.menu.usb.hid_km.build.usbtype=USB_HID_KM
|
||||
mapleMini.menu.usb.hid_j=Joystick
|
||||
mapleMini.menu.usb.hid_j.build.usbtype=USB_HID_J
|
||||
mapleMini.menu.usb.midi=MIDI
|
||||
mapleMini.menu.usb.midi.build.usbtype=USB_MIDI
|
||||
mapleMini.menu.usb.no_usb=No USB
|
||||
mapleMini.menu.usb.no_usb.build.usbtype=NO_USB
|
||||
|
||||
mapleMini.menu.bootloader_version.original = Original (17k RAM,108k Flash)
|
||||
mapleMini.menu.bootloader_version.original.build.vect=VECT_TAB_ADDR=0x8005000
|
||||
|
@ -56,7 +70,7 @@ maple.upload.auto_reset=true
|
|||
|
||||
maple.build.board=MAPLE_REV3
|
||||
maple.build.core=maple
|
||||
maple.build.cpu_flags=-DMCU_STM32F103RB -DSERIAL_USB
|
||||
maple.build.cpu_flags=-DMCU_STM32F103RB -DUSB_HARDWARE
|
||||
maple.build.ldscript=ld/flash.ld
|
||||
maple.build.variant=maple
|
||||
maple.build.vect=VECT_TAB_ADDR=0x8005000
|
||||
|
@ -68,7 +82,7 @@ mapleRET6.vid.0=0x1EAF
|
|||
mapleRET6.pid.0=0x0004
|
||||
mapleRET6.build.board=MAPLE_RET6
|
||||
mapleRET6.build.core=maple
|
||||
mapleRET6.build.cpu_flags=-DMCU_STM32F103RE -DSERIAL_USB
|
||||
mapleRET6.build.cpu_flags=-DMCU_STM32F103RE -DUSB_HARDWARE
|
||||
|
||||
mapleRET6.build.ldscript=ld/stm32f103re-bootloader.ld
|
||||
mapleRET6.build.variant=maple_ret6
|
||||
|
@ -106,7 +120,7 @@ microduino32_flash.build.mcu=cortex-m3
|
|||
microduino32_flash.build.f_cpu=72000000L
|
||||
microduino32_flash.build.board=MICRODUINO_CORE_STM32
|
||||
microduino32_flash.build.core=maple
|
||||
microduino32_flash.build.extra_flags=-DMCU_STM32F103CB -mthumb -DSERIAL_USB -march=armv7-m -D__STM32F1__
|
||||
microduino32_flash.build.extra_flags=-DMCU_STM32F103CB -mthumb -DUSB_HARDWARE -march=armv7-m -D__STM32F1__
|
||||
microduino32_flash.build.ldscript=ld/flash.ld
|
||||
microduino32_flash.build.variant=microduino
|
||||
microduino32_flash.build.variant_system_lib=libmaple.a
|
||||
|
@ -169,6 +183,13 @@ genericSTM32F103C.upload.use_1200bps_touch=false
|
|||
genericSTM32F103C.upload.file_type=bin
|
||||
genericSTM32F103C.upload.auto_reset=true
|
||||
|
||||
## STM32F103CB -------------------------
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB=STM32F103CB (20k RAM. 128k Flash)
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.build.cpu_flags=-DMCU_STM32F103CB
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.build.ldscript=ld/jtag.ld
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.upload.maximum_size=131072
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.upload.ram.maximum_size=20480
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.upload.flash.maximum_size=131072
|
||||
## STM32F103C8 -------------------------
|
||||
genericSTM32F103C.menu.device_variant.STM32F103C8=STM32F103C8 (20k RAM. 64k Flash)
|
||||
genericSTM32F103C.menu.device_variant.STM32F103C8.build.cpu_flags=-DMCU_STM32F103C8
|
||||
|
@ -177,20 +198,12 @@ genericSTM32F103C.menu.device_variant.STM32F103C8.upload.maximum_size=65536
|
|||
genericSTM32F103C.menu.device_variant.STM32F103C8.upload.ram.maximum_size=20480
|
||||
genericSTM32F103C.menu.device_variant.STM32F103C8.upload.flash.maximum_size=65536
|
||||
|
||||
## STM32F103CB -------------------------
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB=STM32F103CB (20k RAM. 128k Flash)
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.build.cpu_flags=-DMCU_STM32F103CB
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.build.ldscript=ld/jtag.ld
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.upload.maximum_size=131072
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.upload.ram.maximum_size=20480
|
||||
genericSTM32F103C.menu.device_variant.STM32F103CB.upload.flash.maximum_size=131072
|
||||
|
||||
#---------------------------- UPLOAD METHODS ---------------------------
|
||||
|
||||
genericSTM32F103C.menu.upload_method.DFUUploadMethod=STM32duino bootloader
|
||||
genericSTM32F103C.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu
|
||||
genericSTM32F103C.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload
|
||||
genericSTM32F103C.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103C.menu.upload_method.DFUUploadMethod.build.upload_flags=-DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103C.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000
|
||||
genericSTM32F103C.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_20.ld
|
||||
genericSTM32F103C.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003
|
||||
|
@ -199,18 +212,30 @@ genericSTM32F103C.menu.upload_method.DFUUploadMethod.upload.altID=2
|
|||
genericSTM32F103C.menu.upload_method.serialMethod=Serial
|
||||
genericSTM32F103C.menu.upload_method.serialMethod.upload.protocol=maple_serial
|
||||
genericSTM32F103C.menu.upload_method.serialMethod.upload.tool=serial_upload
|
||||
genericSTM32F103C.menu.upload_method.serialMethod.build.upload_flags=-DUSB_HARDWARE
|
||||
|
||||
|
||||
genericSTM32F103C.menu.upload_method.STLinkMethod=STLink
|
||||
genericSTM32F103C.menu.upload_method.STLinkMethod.upload.protocol=STLink
|
||||
genericSTM32F103C.menu.upload_method.STLinkMethod.upload.tool=stlink_upload
|
||||
genericSTM32F103C.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103C.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
|
||||
genericSTM32F103C.menu.upload_method.BMPMethod=BMP (Black Magic Probe)
|
||||
genericSTM32F103C.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp
|
||||
genericSTM32F103C.menu.upload_method.BMPMethod.upload.tool=bmp_upload
|
||||
genericSTM32F103C.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG
|
||||
genericSTM32F103C.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG -DUSB_HARDWARE
|
||||
|
||||
#--USB
|
||||
genericSTM32F103C.menu.usb.serial=Serial
|
||||
genericSTM32F103C.menu.usb.serial.build.usbtype=USB_SERIAL
|
||||
genericSTM32F103C.menu.usb.hid_kmj=Keyboard + Mouse + Joystick
|
||||
genericSTM32F103C.menu.usb.hid_kmj.build.usbtype=USB_HID_KMJ
|
||||
genericSTM32F103C.menu.usb.hid_km=Keyboard + Mouse
|
||||
genericSTM32F103C.menu.usb.hid_km.build.usbtype=USB_HID_KM
|
||||
genericSTM32F103C.menu.usb.hid_j=Joystick
|
||||
genericSTM32F103C.menu.usb.hid_j.build.usbtype=USB_HID_J
|
||||
genericSTM32F103C.menu.usb.midi=MIDI
|
||||
genericSTM32F103C.menu.usb.midi.build.usbtype=USB_MIDI
|
||||
########################### Generic STM32F103R ###########################
|
||||
|
||||
genericSTM32F103R.name=Generic STM32F103R series
|
||||
|
@ -261,7 +286,7 @@ genericSTM32F103R.menu.device_variant.STM32F103RE.build.ldscript=ld/stm32f103re.
|
|||
genericSTM32F103R.menu.upload_method.DFUUploadMethod=STM32duino bootloader
|
||||
genericSTM32F103R.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu
|
||||
genericSTM32F103R.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload
|
||||
genericSTM32F103R.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103R.menu.upload_method.DFUUploadMethod.build.upload_flags=-DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103R.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000
|
||||
genericSTM32F103R.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader.ld
|
||||
genericSTM32F103R.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003
|
||||
|
@ -274,7 +299,7 @@ genericSTM32F103R.menu.upload_method.serialMethod.upload.tool=serial_upload
|
|||
genericSTM32F103R.menu.upload_method.STLinkMethod=STLink
|
||||
genericSTM32F103R.menu.upload_method.STLinkMethod.upload.protocol=STLink
|
||||
genericSTM32F103R.menu.upload_method.STLinkMethod.upload.tool=stlink_upload
|
||||
genericSTM32F103R.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103R.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
|
||||
genericSTM32F103R.menu.upload_method.BMPMethod=BMP (Black Magic Probe)
|
||||
genericSTM32F103R.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp
|
||||
|
@ -315,7 +340,7 @@ genericSTM32F103T.menu.device_variant.STM32F103TB.upload.flash.maximum_size=1310
|
|||
genericSTM32F103T.menu.upload_method.DFUUploadMethod=STM32duino bootloader
|
||||
genericSTM32F103T.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu
|
||||
genericSTM32F103T.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload
|
||||
genericSTM32F103T.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103T.menu.upload_method.DFUUploadMethod.build.upload_flags=-DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103T.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000
|
||||
genericSTM32F103T.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_20.ld
|
||||
genericSTM32F103T.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003
|
||||
|
@ -328,7 +353,7 @@ genericSTM32F103T.menu.upload_method.serialMethod.upload.tool=serial_upload
|
|||
genericSTM32F103T.menu.upload_method.STLinkMethod=STLink
|
||||
genericSTM32F103T.menu.upload_method.STLinkMethod.upload.protocol=STLink
|
||||
genericSTM32F103T.menu.upload_method.STLinkMethod.upload.tool=stlink_upload
|
||||
genericSTM32F103T.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103T.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
|
||||
genericSTM32F103T.menu.upload_method.BMPMethod=BMP (Black Magic Probe)
|
||||
genericSTM32F103T.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp
|
||||
|
@ -377,7 +402,7 @@ genericSTM32F103V.menu.device_variant.STM32F103VE.build.ldscript=ld/stm32f103ve.
|
|||
genericSTM32F103V.menu.upload_method.DFUUploadMethod=STM32duino bootloader
|
||||
genericSTM32F103V.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu
|
||||
genericSTM32F103V.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload
|
||||
genericSTM32F103V.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103V.menu.upload_method.DFUUploadMethod.build.upload_flags=-DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103V.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000
|
||||
genericSTM32F103V.menu.upload_method.DFUUploadMethod.build.ldscript=ld/stm32f103veDFU.ld
|
||||
genericSTM32F103V.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003
|
||||
|
@ -390,7 +415,7 @@ genericSTM32F103V.menu.upload_method.serialMethod.upload.tool=serial_upload
|
|||
genericSTM32F103V.menu.upload_method.STLinkMethod=STLink
|
||||
genericSTM32F103V.menu.upload_method.STLinkMethod.upload.protocol=STLink
|
||||
genericSTM32F103V.menu.upload_method.STLinkMethod.upload.tool=stlink_upload
|
||||
genericSTM32F103V.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103V.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
|
||||
genericSTM32F103V.menu.upload_method.BMPMethod=BMP (Black Magic Probe)
|
||||
genericSTM32F103V.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp
|
||||
|
@ -436,7 +461,7 @@ genericSTM32F103Z.menu.device_variant.STM32F103ZE.build.ldscript=ld/stm32f103ze.
|
|||
genericSTM32F103Z.menu.upload_method.DFUUploadMethod=STM32duino bootloader
|
||||
genericSTM32F103Z.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu
|
||||
genericSTM32F103Z.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload
|
||||
genericSTM32F103Z.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103Z.menu.upload_method.DFUUploadMethod.build.upload_flags=-DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103Z.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000
|
||||
genericSTM32F103Z.menu.upload_method.DFUUploadMethod.build.ldscript=ld/stm32f103z_dfu.ld
|
||||
genericSTM32F103Z.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003
|
||||
|
@ -449,7 +474,7 @@ genericSTM32F103Z.menu.upload_method.serialMethod.upload.tool=serial_upload
|
|||
genericSTM32F103Z.menu.upload_method.STLinkMethod=STLink
|
||||
genericSTM32F103Z.menu.upload_method.STLinkMethod.upload.protocol=STLink
|
||||
genericSTM32F103Z.menu.upload_method.STLinkMethod.upload.tool=stlink_upload
|
||||
genericSTM32F103Z.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericSTM32F103Z.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
|
||||
genericSTM32F103Z.menu.upload_method.BMPMethod=BMP (Black Magic Probe)
|
||||
genericSTM32F103Z.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp
|
||||
|
@ -490,7 +515,7 @@ genericGD32F103C.menu.upload_method.DFUUploadMethod=GD32duino bootloader
|
|||
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.build.upload_flags=-DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_20.ld
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003
|
||||
|
@ -504,7 +529,7 @@ genericGD32F103C.menu.upload_method.serialMethod.upload.tool=serial_upload
|
|||
genericGD32F103C.menu.upload_method.STLinkMethod=STLink
|
||||
genericGD32F103C.menu.upload_method.STLinkMethod.upload.protocol=STLink
|
||||
genericGD32F103C.menu.upload_method.STLinkMethod.upload.tool=stlink_upload
|
||||
genericGD32F103C.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericGD32F103C.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DUSB_HARDWARE -DGENERIC_BOOTLOADER
|
||||
|
||||
|
||||
genericGD32F103C.menu.upload_method.BMPMethod=BMP (Black Magic Probe)
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
BOARD_USART##n##_TX_PIN, \
|
||||
BOARD_USART##n##_RX_PIN)
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
#if BOARD_HAVE_USART1
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
#endif
|
||||
|
|
|
@ -181,7 +181,7 @@ private:
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
#if BOARD_HAVE_USART1
|
||||
extern HardwareSerial Serial1;
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
//
|
||||
// MinSysex.c
|
||||
// LibMaple4Midi
|
||||
//
|
||||
// Created by Donald D Davis on 4/11/13.
|
||||
// Copyright (c) 2013 Suspect Devices. All rights reserved.
|
||||
// Modified BSD Liscense
|
||||
/*
|
||||
0xF0 SysEx
|
||||
0x7E Non-Realtime
|
||||
0x7F The SysEx channel. Could be from 0x00 to 0x7F.
|
||||
Here we set it to "disregard channel".
|
||||
0x06 Sub-ID -- General Information
|
||||
0x01 Sub-ID2 -- Identity Request
|
||||
0xF7 End of SysEx
|
||||
---- response
|
||||
0xF0 SysEx
|
||||
0x7E Non-Realtime
|
||||
0x7F The SysEx channel. Could be from 0x00 to 0x7F.
|
||||
Here we set it to "disregard channel".
|
||||
0x06 Sub-ID -- General Information
|
||||
0x02 Sub-ID2 -- Identity Reply
|
||||
0xID Manufacturer's ID
|
||||
0xf1 The f1 and f2 bytes make up the family code. Each
|
||||
0xf2 manufacturer assigns different family codes to his products.
|
||||
0xp1 The p1 and p2 bytes make up the model number. Each
|
||||
0xp2 manufacturer assigns different model numbers to his products.
|
||||
0xv1 The v1, v2, v3 and v4 bytes make up the version number.
|
||||
0xv2
|
||||
0xv3
|
||||
0xv4
|
||||
0xF7 End of SysEx
|
||||
*/
|
||||
|
||||
|
||||
#ifdef USB_MIDI
|
||||
|
||||
// change this to packets
|
||||
#define STANDARD_ID_RESPONSE_LENGTH 7
|
||||
|
||||
#include <libmaple/usb_midi_device.h>
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/delay.h>
|
||||
#include <MinSysex.h>
|
||||
//#include <wirish/wirish.h>
|
||||
|
||||
|
||||
#define MAX_SYSEX_SIZE 256
|
||||
|
||||
/********************************* ACHTUNG! ignores usbmidi cable ********************************/
|
||||
/*const MIDI_EVENT_PACKET_t standardIDResponse[]={
|
||||
{ DEFAULT_MIDI_CABLE,
|
||||
CIN_SYSEX,
|
||||
MIDIv1_SYSEX_START,
|
||||
USYSEX_NON_REAL_TIME,
|
||||
USYSEX_ALL_CHANNELS},
|
||||
{ DEFAULT_MIDI_CABLE,
|
||||
CIN_SYSEX,
|
||||
USYSEX_GENERAL_INFO,
|
||||
USYSEX_GI_ID_RESPONSE,
|
||||
LEAFLABS_MMA_VENDOR_1},
|
||||
{ DEFAULT_MIDI_CABLE,
|
||||
CIN_SYSEX,
|
||||
LEAFLABS_MMA_VENDOR_2, // extended ID
|
||||
LEAFLABS_MMA_VENDOR_3, // extended ID
|
||||
1}, // family #1
|
||||
{ DEFAULT_MIDI_CABLE,
|
||||
CIN_SYSEX,
|
||||
2, // family #2
|
||||
1, // part #1
|
||||
2}, // part #2
|
||||
{ DEFAULT_MIDI_CABLE,
|
||||
CIN_SYSEX,
|
||||
0, // version 1
|
||||
0, // version 2
|
||||
1}, // version 3
|
||||
{ DEFAULT_MIDI_CABLE,
|
||||
CIN_SYSEX_ENDS_IN_2,
|
||||
'!', // lgl compatible
|
||||
MIDIv1_SYSEX_END,
|
||||
0}
|
||||
};
|
||||
*/
|
||||
const uint8 standardIDResponse[]={
|
||||
CIN_SYSEX,
|
||||
MIDIv1_SYSEX_START,
|
||||
USYSEX_NON_REAL_TIME,
|
||||
USYSEX_ALL_CHANNELS,
|
||||
CIN_SYSEX,
|
||||
USYSEX_GENERAL_INFO,
|
||||
USYSEX_GI_ID_RESPONSE,
|
||||
LEAFLABS_MMA_VENDOR_1,
|
||||
CIN_SYSEX,
|
||||
LEAFLABS_MMA_VENDOR_2, // extended ID
|
||||
LEAFLABS_MMA_VENDOR_3, // extended ID
|
||||
1, // family #1
|
||||
CIN_SYSEX,
|
||||
2, // family #2
|
||||
1, // part #1
|
||||
2, // part #2
|
||||
CIN_SYSEX,
|
||||
0, // version 1
|
||||
0, // version 2
|
||||
1, // version 3
|
||||
CIN_SYSEX_ENDS_IN_2,
|
||||
'!', // lgl compatible
|
||||
MIDIv1_SYSEX_END,
|
||||
0
|
||||
};
|
||||
//#define STANDARD_ID_RESPONSE_LENGTH (sizeof(standardIDResponse))
|
||||
|
||||
typedef enum {NOT_IN_SYSEX=0,COULD_BE_MY_SYSEX,YUP_ITS_MY_SYSEX,ITS_NOT_MY_SYSEX} sysexStates;
|
||||
volatile uint8 sysexBuffer[MAX_SYSEX_SIZE];
|
||||
volatile sysexStates sysexState;
|
||||
volatile int sysexFinger=0;
|
||||
|
||||
/*
|
||||
0xF0 SysEx
|
||||
0x?? LEAFLABS_MMA_VENDOR_1
|
||||
0x?? LEAFLABS_MMA_VENDOR_2
|
||||
|
||||
0x?? LEAFLABS_MMA_VENDOR_3
|
||||
0x10 LGL_DEVICE_NUMBER
|
||||
0xLE CMD: REBOOT
|
||||
|
||||
0xf7 EOSysEx
|
||||
*/
|
||||
#define STACK_TOP 0x20000800
|
||||
#define EXC_RETURN 0xFFFFFFF9
|
||||
#define DEFAULT_CPSR 0x61000000
|
||||
#define RESET_DELAY 100000
|
||||
static void wait_reset(void) {
|
||||
delay_us(RESET_DELAY);
|
||||
nvic_sys_reset();
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------dealWithItQuickly()
|
||||
* Note: at this point we have established that the sysex belongs to us.
|
||||
* So we need to respond to any generic requests like information requests.
|
||||
* We also need to handle requests which are meant for us. At the moment this is just the
|
||||
* reset request.
|
||||
*
|
||||
*/
|
||||
void dealWithItQuickly(){
|
||||
switch (sysexBuffer[1]) {
|
||||
case USYSEX_NON_REAL_TIME:
|
||||
switch (sysexBuffer[3]) {
|
||||
case USYSEX_GENERAL_INFO:
|
||||
if (sysexBuffer[4]==USYSEX_GI_ID_REQUEST) {
|
||||
usb_midi_tx((uint32 *) standardIDResponse, STANDARD_ID_RESPONSE_LENGTH);
|
||||
}
|
||||
}
|
||||
case USYSEX_REAL_TIME:
|
||||
break;
|
||||
case LEAFLABS_MMA_VENDOR_1:
|
||||
if (sysexBuffer[5]==LGL_RESET_CMD) {
|
||||
uintptr_t target = (uintptr_t)wait_reset | 0x1;
|
||||
asm volatile("mov r0, %[stack_top] \n\t" // Reset stack
|
||||
"mov sp, r0 \n\t"
|
||||
"mov r0, #1 \n\t"
|
||||
"mov r1, %[target_addr] \n\t"
|
||||
"mov r2, %[cpsr] \n\t"
|
||||
"push {r2} \n\t" // Fake xPSR
|
||||
"push {r1} \n\t" // PC target addr
|
||||
"push {r0} \n\t" // Fake LR
|
||||
"push {r0} \n\t" // Fake R12
|
||||
"push {r0} \n\t" // Fake R3
|
||||
"push {r0} \n\t" // Fake R2
|
||||
"push {r0} \n\t" // Fake R1
|
||||
"push {r0} \n\t" // Fake R0
|
||||
"mov lr, %[exc_return] \n\t"
|
||||
"bx lr"
|
||||
:
|
||||
: [stack_top] "r" (STACK_TOP),
|
||||
[target_addr] "r" (target),
|
||||
[exc_return] "r" (EXC_RETURN),
|
||||
[cpsr] "r" (DEFAULT_CPSR)
|
||||
: "r0", "r1", "r2");
|
||||
/* Can't happen. */
|
||||
ASSERT_FAULT(0);
|
||||
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
;//turn the led on?
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------LglSysexHandler()
|
||||
* The idea here is to identify which Sysex's belong to us and deal with them.
|
||||
*/
|
||||
void LglSysexHandler(uint32 *midiBufferRx, uint32 *rx_offset, uint32 *n_unread_packets) {
|
||||
MIDI_EVENT_PACKET_t * midiPackets = (MIDI_EVENT_PACKET_t *) (midiBufferRx+(*rx_offset));
|
||||
uint8 nPackets=((*n_unread_packets)-(*rx_offset));
|
||||
int cPacket;
|
||||
uint8 soPackets=0;
|
||||
/********************************* ACHTUNG! ignores usbmidi cable ********************************/
|
||||
MIDI_EVENT_PACKET_t *packet;
|
||||
for (cPacket=0;cPacket<nPackets;cPacket++){
|
||||
packet=midiPackets+cPacket;
|
||||
if (!CIN_IS_SYSEX(packet->cin)) {
|
||||
continue;
|
||||
} // else {
|
||||
if (!soPackets) {
|
||||
soPackets=cPacket*4;
|
||||
}
|
||||
if ((sysexState==YUP_ITS_MY_SYSEX) && ((sysexFinger+3)>=MAX_SYSEX_SIZE)){
|
||||
sysexState=ITS_NOT_MY_SYSEX; //eisenhower policy. Even if its mine I cant deal with it.
|
||||
}
|
||||
switch (packet->cin) {
|
||||
case CIN_SYSEX:
|
||||
switch (sysexState) {
|
||||
case NOT_IN_SYSEX : // new sysex.
|
||||
sysexFinger=0;
|
||||
if (packet->midi0 == MIDIv1_SYSEX_START) {
|
||||
if (packet->midi1==USYSEX_REAL_TIME
|
||||
||packet->midi1==USYSEX_NON_REAL_TIME) {
|
||||
if ((packet->midi2==myMidiChannel)
|
||||
||(packet->midi2==USYSEX_ALL_CHANNELS)
|
||||
) {
|
||||
sysexState=YUP_ITS_MY_SYSEX;
|
||||
sysexBuffer[sysexFinger++]=MIDIv1_SYSEX_START;
|
||||
sysexBuffer[sysexFinger++]=packet->midi1;
|
||||
sysexBuffer[sysexFinger++]=packet->midi2;
|
||||
break;
|
||||
}
|
||||
} else if ((packet->midi1==myMidiID[0])
|
||||
&& (packet->midi2==myMidiID[1])
|
||||
){
|
||||
sysexState=COULD_BE_MY_SYSEX;
|
||||
sysexBuffer[sysexFinger++]=MIDIv1_SYSEX_START;
|
||||
sysexBuffer[sysexFinger++]=packet->midi1;
|
||||
sysexBuffer[sysexFinger++]=packet->midi2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case COULD_BE_MY_SYSEX:
|
||||
if (packet->midi0==myMidiID[2]) {
|
||||
sysexState=YUP_ITS_MY_SYSEX;
|
||||
sysexBuffer[sysexFinger++]=packet->midi0;
|
||||
sysexBuffer[sysexFinger++]=packet->midi1;
|
||||
sysexBuffer[sysexFinger++]=packet->midi2;
|
||||
} else {
|
||||
sysexState=ITS_NOT_MY_SYSEX;
|
||||
sysexFinger=0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case CIN_SYSEX_ENDS_IN_1:
|
||||
case CIN_SYSEX_ENDS_IN_2:
|
||||
case CIN_SYSEX_ENDS_IN_3:
|
||||
sysexBuffer[sysexFinger++]=packet->midi0;
|
||||
sysexBuffer[sysexFinger++]=packet->midi1;
|
||||
sysexBuffer[sysexFinger++]=packet->midi2;
|
||||
if (sysexState==YUP_ITS_MY_SYSEX) {
|
||||
if(cPacket>=(*n_unread_packets)){
|
||||
*n_unread_packets = soPackets;
|
||||
*rx_offset = soPackets;
|
||||
} else {
|
||||
uint8 c = cPacket;
|
||||
uint32 *s;
|
||||
uint32 *d = midiBufferRx + soPackets;
|
||||
for (s = midiBufferRx+c;
|
||||
((*n_unread_packets) && (s <= midiBufferRx+(USB_MIDI_RX_EPSIZE/4)));
|
||||
d++,s++
|
||||
) {
|
||||
(*d)=(*s);
|
||||
(*n_unread_packets)--;
|
||||
(*rx_offset)++;
|
||||
|
||||
}
|
||||
// we need to reset the for loop variables to re process remaining data.
|
||||
nPackets=((*n_unread_packets)-(*rx_offset));
|
||||
cPacket=(*rx_offset);
|
||||
}
|
||||
dealWithItQuickly();
|
||||
|
||||
}
|
||||
sysexFinger=0;
|
||||
sysexState=NOT_IN_SYSEX;
|
||||
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
|
||||
}
|
||||
// its our sysex and we will cry if we want to
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// lgl_min_sysex.h
|
||||
// LibMaple4Midi
|
||||
//
|
||||
// Created by Donald D Davis on 4/11/13.
|
||||
// Copyright (c) 2013 Suspect Devices. All rights reserved.
|
||||
//
|
||||
|
||||
#ifdef USB_MIDI
|
||||
|
||||
|
||||
#ifndef __LGL_MIN_SYSEX_H__
|
||||
#define __LGL_MIN_SYSEX_H__ 1
|
||||
|
||||
|
||||
#include "MidiSpecs.h"
|
||||
//#include "LGL.h"
|
||||
|
||||
#define LEAFLABS_MMA_VENDOR_1 0x7D
|
||||
#define LEAFLABS_MMA_VENDOR_2 0x1E
|
||||
#define LEAFLABS_MMA_VENDOR_3 0x4F
|
||||
|
||||
// move to LGL.h
|
||||
#define LGL_RESET_CMD 0x1e
|
||||
|
||||
#define DEFAULT_MIDI_CHANNEL 0x0A
|
||||
#define DEFAULT_MIDI_DEVICE 0x0A
|
||||
#define DEFAULT_MIDI_CABLE 0x00
|
||||
|
||||
// eventually all of this should be in a place for settings which can be written to flash.
|
||||
extern volatile uint8 myMidiChannel;
|
||||
extern volatile uint8 myMidiDevice;
|
||||
extern volatile uint8 myMidiCable;
|
||||
extern volatile uint8 myMidiID[];
|
||||
|
||||
|
||||
void LglSysexHandler(uint32 *midiBufferRx,uint32 *rx_offset,uint32 *n_unread_bytes);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -33,6 +33,8 @@
|
|||
* the result made cleaner.
|
||||
*/
|
||||
|
||||
#ifdef USB_SERIAL
|
||||
|
||||
#include <libmaple/usb_cdcacm.h>
|
||||
|
||||
#include <libmaple/usb.h>
|
||||
|
@ -749,3 +751,5 @@ static void usbSetConfiguration(void) {
|
|||
static void usbSetDeviceAddress(void) {
|
||||
USBLIB->state = USB_ADDRESSED;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,746 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/usb/stm32f1/usb_hid.c
|
||||
* @brief USB HID (human interface device) support
|
||||
*
|
||||
* FIXME: this works on the STM32F1 USB peripherals, and probably no
|
||||
* place else. Nonportable bits really need to be factored out, and
|
||||
* the result made cleaner.
|
||||
*/
|
||||
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J)
|
||||
|
||||
|
||||
#include <libmaple/usb_hid.h>
|
||||
|
||||
#include <libmaple/usb.h>
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/delay.h>
|
||||
|
||||
/* Private headers */
|
||||
#include "usb_lib_globals.h"
|
||||
#include "usb_reg_map.h"
|
||||
|
||||
/* usb_lib headers */
|
||||
#include "usb_type.h"
|
||||
#include "usb_core.h"
|
||||
#include "usb_def.h"
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
***
|
||||
*** HACK ALERT! FIXME FIXME FIXME FIXME!
|
||||
***
|
||||
*** A bunch of LeafLabs-specific configuration lives in here for
|
||||
*** now. This mess REALLY needs to get teased apart, with
|
||||
*** appropriate pieces moved into Wirish.
|
||||
***
|
||||
******************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
#if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \
|
||||
defined(BOARD_maple_mini) || defined(BOARD_maple_native))
|
||||
#warning USB HID relies on LeafLabs board-specific configuration.\
|
||||
You may have problems on non-LeafLabs boards.
|
||||
#endif
|
||||
|
||||
|
||||
uint32 ProtocolValue;
|
||||
|
||||
static void hidDataTxCb(void);
|
||||
static void hidDataRxCb(void);
|
||||
|
||||
static void usbInit(void);
|
||||
static void usbReset(void);
|
||||
static RESULT usbDataSetup(uint8 request);
|
||||
static RESULT usbNoDataSetup(uint8 request);
|
||||
static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting);
|
||||
static uint8* usbGetDeviceDescriptor(uint16 length);
|
||||
static uint8* usbGetConfigDescriptor(uint16 length);
|
||||
static uint8* usbGetStringDescriptor(uint16 length);
|
||||
static void usbSetConfiguration(void);
|
||||
static void usbSetDeviceAddress(void);
|
||||
|
||||
/*
|
||||
* Descriptors
|
||||
*/
|
||||
|
||||
|
||||
const uint8_t hid_report_descriptor[] = {
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_KM)
|
||||
// Mouse
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
|
||||
0x09, 0x02, // USAGE (Mouse)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, 0x01, // REPORT_ID (1)
|
||||
0x09, 0x01, // USAGE (Pointer)
|
||||
0xa1, 0x00, // COLLECTION (Physical)
|
||||
0x05, 0x09, // USAGE_PAGE (Button)
|
||||
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
||||
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x05, // REPORT_SIZE (5)
|
||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
||||
0x09, 0x30, // USAGE (X)
|
||||
0x09, 0x31, // USAGE (Y)
|
||||
0x09, 0x38, // USAGE (Wheel)
|
||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
||||
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x95, 0x03, // REPORT_COUNT (3)
|
||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
||||
0xc0, // END_COLLECTION
|
||||
0xc0, // END_COLLECTION
|
||||
|
||||
// Keyboard
|
||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
|
||||
0x09, 0x06, // USAGE (Keyboard)
|
||||
0xa1, 0x01, // COLLECTION (Application)
|
||||
0x85, 0x02, // REPORT_ID (2)
|
||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||
|
||||
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
||||
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
||||
0x75, 0x01, // REPORT_SIZE (1)
|
||||
|
||||
0x95, 0x08, // REPORT_COUNT (8)
|
||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
||||
0x95, 0x01, // REPORT_COUNT (1)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
||||
|
||||
0x95, 0x06, // REPORT_COUNT (6)
|
||||
0x75, 0x08, // REPORT_SIZE (8)
|
||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
||||
0x25, 0x65, // LOGICAL_MAXIMUM (101)
|
||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
||||
|
||||
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
||||
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
|
||||
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
||||
0xc0, // END_COLLECTION
|
||||
#endif
|
||||
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_J)
|
||||
// Joystick
|
||||
0x05, 0x01, // Usage Page (Generic Desktop)
|
||||
0x09, 0x04, // Usage (Joystick)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x85, 0x03, // REPORT_ID (3)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x20, // Report Count (32)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (Button #1)
|
||||
0x29, 0x20, // Usage Maximum (Button #32)
|
||||
0x81, 0x02, // Input (variable,absolute)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x07, // Logical Maximum (7)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||
0x75, 0x04, // Report Size (4)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x65, 0x14, // Unit (20)
|
||||
0x05, 0x01, // Usage Page (Generic Desktop)
|
||||
0x09, 0x39, // Usage (Hat switch)
|
||||
0x81, 0x42, // Input (variable,absolute,null_state)
|
||||
0x05, 0x01, //Usage Page (Generic Desktop)
|
||||
0x09, 0x01, //Usage (Pointer)
|
||||
0xA1, 0x00, //Collection ()
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x03, // Logical Maximum (1023)
|
||||
0x75, 0x0A, // Report Size (10)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x81, 0x02, // Input (variable,absolute)
|
||||
0xC0, // End Collection
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x03, // Logical Maximum (1023)
|
||||
0x75, 0x0A, // Report Size (10)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0x09, 0x36, // Usage (Slider)
|
||||
0x09, 0x36, // Usage (Slider)
|
||||
0x81, 0x02, // Input (variable,absolute)
|
||||
0xC0, // End Collection
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USB_RAWHID
|
||||
// RAW HID
|
||||
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
|
||||
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
|
||||
|
||||
0xA1, 0x01, // Collection 0x01
|
||||
0x85, 0x03, // REPORT_ID (3)
|
||||
0x75, 0x08, // report size = 8 bits
|
||||
0x15, 0x00, // logical minimum = 0
|
||||
0x26, 0xFF, 0x00, // logical maximum = 255
|
||||
|
||||
0x95, 64, // report count TX
|
||||
0x09, 0x01, // usage
|
||||
0x81, 0x02, // Input (array)
|
||||
|
||||
0x95, 64, // report count RX
|
||||
0x09, 0x02, // usage
|
||||
0x91, 0x02, // Output (array)
|
||||
0xC0 // end collection
|
||||
#endif
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
#define LEAFLABS_ID_VENDOR 0x1EAF
|
||||
#define MAPLE_ID_PRODUCT 0x0024
|
||||
static const usb_descriptor_device usbHIDDescriptor_Device =
|
||||
USB_HID_DECLARE_DEV_DESC(LEAFLABS_ID_VENDOR, MAPLE_ID_PRODUCT);
|
||||
|
||||
|
||||
typedef struct {
|
||||
usb_descriptor_config_header Config_Header;
|
||||
usb_descriptor_interface HID_Interface;
|
||||
HIDDescriptor HID_Descriptor;
|
||||
usb_descriptor_endpoint DataInEndpoint;
|
||||
usb_descriptor_endpoint DataOutEndpoint;
|
||||
} __packed usb_descriptor_config;
|
||||
|
||||
|
||||
#define MAX_POWER (100 >> 1)
|
||||
static const usb_descriptor_config usbHIDDescriptor_Config =
|
||||
{
|
||||
.Config_Header = {
|
||||
.bLength = sizeof(usb_descriptor_config_header),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION,
|
||||
.wTotalLength = sizeof(usb_descriptor_config),//0,
|
||||
.bNumInterfaces = 0x01,
|
||||
.bConfigurationValue = 0x01,
|
||||
.iConfiguration = 0x00,
|
||||
.bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED |
|
||||
USB_CONFIG_ATTR_SELF_POWERED),
|
||||
.bMaxPower = MAX_POWER,
|
||||
},
|
||||
|
||||
.HID_Interface = {
|
||||
.bLength = sizeof(usb_descriptor_interface),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
|
||||
.bInterfaceNumber = 0x00,
|
||||
.bAlternateSetting = 0x00,
|
||||
.bNumEndpoints = 0x02,
|
||||
.bInterfaceClass = USB_INTERFACE_CLASS_HID,
|
||||
.bInterfaceSubClass = USB_INTERFACE_SUBCLASS_HID,
|
||||
.bInterfaceProtocol = 0x00, /* Common AT Commands */
|
||||
.iInterface = 0x00,
|
||||
},
|
||||
|
||||
.HID_Descriptor = {
|
||||
.len = 9,//sizeof(HIDDescDescriptor),
|
||||
.dtype = HID_DESCRIPTOR_TYPE,
|
||||
.versionL = 0x10,
|
||||
.versionH = 0x01,
|
||||
.country = 0x00,
|
||||
.numDesc = 0x01,
|
||||
.desctype = REPORT_DESCRIPTOR,//0x22,
|
||||
.descLenL = sizeof(hid_report_descriptor),
|
||||
.descLenH = 0x00,
|
||||
},
|
||||
|
||||
.DataInEndpoint = {
|
||||
.bLength = sizeof(usb_descriptor_endpoint),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | USB_HID_TX_ENDP),//0x81,//USB_HID_TX_ADDR,
|
||||
.bmAttributes = USB_ENDPOINT_TYPE_INTERRUPT,
|
||||
.wMaxPacketSize = USB_HID_TX_EPSIZE,//0x40,//big enough for a keyboard 9 byte packet and for a mouse 5 byte packet
|
||||
.bInterval = 0x0A,
|
||||
},
|
||||
|
||||
.DataOutEndpoint = {
|
||||
.bLength = sizeof(usb_descriptor_endpoint),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT | USB_HID_RX_ENDP),
|
||||
.bmAttributes = USB_EP_TYPE_BULK,
|
||||
.wMaxPacketSize = USB_HID_RX_EPSIZE,
|
||||
.bInterval = 0x00,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
String Descriptors:
|
||||
|
||||
we may choose to specify any or none of the following string
|
||||
identifiers:
|
||||
|
||||
iManufacturer: LeafLabs
|
||||
iProduct: Maple
|
||||
iSerialNumber: NONE
|
||||
iConfiguration: NONE
|
||||
iInterface(CCI): NONE
|
||||
iInterface(DCI): NONE
|
||||
|
||||
*/
|
||||
|
||||
/* Unicode language identifier: 0x0409 is US English */
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbHIDDescriptor_LangID = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(1),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {0x09, 0x04},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbHIDDescriptor_iManufacturer = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(8),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0,
|
||||
'L', 0, 'a', 0, 'b', 0, 's', 0},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbHIDDescriptor_iProduct = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(5),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbHIDDescriptor_iInterface = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(3),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {'H', 0, 'I', 0, 'D', 0},
|
||||
};
|
||||
|
||||
static ONE_DESCRIPTOR Device_Descriptor = {
|
||||
(uint8*)&usbHIDDescriptor_Device,
|
||||
sizeof(usb_descriptor_device)
|
||||
};
|
||||
|
||||
static ONE_DESCRIPTOR Config_Descriptor = {
|
||||
(uint8*)&usbHIDDescriptor_Config,
|
||||
sizeof(usbHIDDescriptor_Config)
|
||||
};
|
||||
|
||||
static ONE_DESCRIPTOR HID_Report_Descriptor = {
|
||||
(uint8*)&hid_report_descriptor,
|
||||
sizeof(hid_report_descriptor)
|
||||
};
|
||||
|
||||
#define N_STRING_DESCRIPTORS 3
|
||||
static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = {
|
||||
{(uint8*)&usbHIDDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)},
|
||||
{(uint8*)&usbHIDDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)},
|
||||
{(uint8*)&usbHIDDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(5)},
|
||||
{(uint8*)&usbHIDDescriptor_iInterface, USB_DESCRIPTOR_STRING_LEN(3)}
|
||||
};
|
||||
|
||||
/*
|
||||
* Etc.
|
||||
*/
|
||||
|
||||
/* I/O state */
|
||||
|
||||
#define HID_BUFFER_SIZE 512
|
||||
|
||||
/* Received data */
|
||||
static volatile uint8 hidBufferRx[HID_BUFFER_SIZE];
|
||||
/* Read index into hidBufferRx */
|
||||
static volatile uint32 rx_offset = 0;
|
||||
/* Number of bytes left to transmit */
|
||||
static volatile uint32 n_unsent_bytes = 0;
|
||||
/* Are we currently sending an IN packet? */
|
||||
static volatile uint8 transmitting = 0;
|
||||
/* Number of unread bytes */
|
||||
static volatile uint32 n_unread_bytes = 0;
|
||||
|
||||
/*
|
||||
* Endpoint callbacks
|
||||
*/
|
||||
|
||||
static void (*ep_int_in[7])(void) =
|
||||
{hidDataTxCb,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process};
|
||||
|
||||
static void (*ep_int_out[7])(void) =
|
||||
{NOP_Process,
|
||||
hidDataRxCb,//NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process};
|
||||
|
||||
/*
|
||||
* Globals required by usb_lib/
|
||||
*
|
||||
* Mark these weak so they can be overriden to implement other USB
|
||||
* functionality.
|
||||
*/
|
||||
|
||||
#define NUM_ENDPTS 0x02
|
||||
__weak DEVICE Device_Table = {
|
||||
.Total_Endpoint = NUM_ENDPTS,
|
||||
.Total_Configuration = 1
|
||||
};
|
||||
|
||||
#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */
|
||||
__weak DEVICE_PROP Device_Property = {
|
||||
.Init = usbInit,
|
||||
.Reset = usbReset,
|
||||
.Process_Status_IN = NOP_Process,
|
||||
.Process_Status_OUT = NOP_Process,
|
||||
.Class_Data_Setup = usbDataSetup,
|
||||
.Class_NoData_Setup = usbNoDataSetup,
|
||||
.Class_Get_Interface_Setting = usbGetInterfaceSetting,
|
||||
.GetDeviceDescriptor = usbGetDeviceDescriptor,
|
||||
.GetConfigDescriptor = usbGetConfigDescriptor,
|
||||
.GetStringDescriptor = usbGetStringDescriptor,
|
||||
.RxEP_buffer = NULL,
|
||||
.MaxPacketSize = MAX_PACKET_SIZE
|
||||
};
|
||||
|
||||
__weak USER_STANDARD_REQUESTS User_Standard_Requests = {
|
||||
.User_GetConfiguration = NOP_Process,
|
||||
.User_SetConfiguration = usbSetConfiguration,
|
||||
.User_GetInterface = NOP_Process,
|
||||
.User_SetInterface = NOP_Process,
|
||||
.User_GetStatus = NOP_Process,
|
||||
.User_ClearFeature = NOP_Process,
|
||||
.User_SetEndPointFeature = NOP_Process,
|
||||
.User_SetDeviceFeature = NOP_Process,
|
||||
.User_SetDeviceAddress = usbSetDeviceAddress
|
||||
};
|
||||
|
||||
/*
|
||||
* HID interface
|
||||
*/
|
||||
|
||||
void usb_hid_enable(gpio_dev *disc_dev, uint8 disc_bit) {
|
||||
/* Present ourselves to the host. Writing 0 to "disc" pin must
|
||||
* pull USB_DP pin up while leaving USB_DM pulled down by the
|
||||
* transceiver. See USB 2.0 spec, section 7.1.7.3. */
|
||||
gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP);
|
||||
gpio_write_bit(disc_dev, disc_bit, 0);
|
||||
|
||||
/* Initialize the USB peripheral. */
|
||||
usb_init_usblib(USBLIB, ep_int_in, ep_int_out);
|
||||
}
|
||||
|
||||
void usb_hid_disable(gpio_dev *disc_dev, uint8 disc_bit) {
|
||||
/* Turn off the interrupt and signal disconnect (see e.g. USB 2.0
|
||||
* spec, section 7.1.7.3). */
|
||||
nvic_irq_disable(NVIC_USB_LP_CAN_RX0);
|
||||
gpio_write_bit(disc_dev, disc_bit, 1);
|
||||
}
|
||||
|
||||
void usb_hid_putc(char ch) {
|
||||
while (!usb_hid_tx((uint8*)&ch, 1))
|
||||
;
|
||||
}
|
||||
|
||||
/* This function is non-blocking.
|
||||
*
|
||||
* It copies data from a usercode buffer into the USB peripheral TX
|
||||
* buffer, and returns the number of bytes copied. */
|
||||
uint32 usb_hid_tx(const uint8* buf, uint32 len) {
|
||||
/* Last transmission hasn't finished, so abort. */
|
||||
if (usb_hid_is_transmitting()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We can only put USB_HID_TX_EPSIZE bytes in the buffer. */
|
||||
if (len > USB_HID_TX_EPSIZE) {
|
||||
len = USB_HID_TX_EPSIZE;
|
||||
}
|
||||
|
||||
/* Queue bytes for sending. */
|
||||
if (len) {
|
||||
usb_copy_to_pma(buf, len, GetEPTxAddr(USB_HID_TX_ENDP));//USB_HID_TX_ADDR);
|
||||
}
|
||||
// We still need to wait for the interrupt, even if we're sending
|
||||
// zero bytes. (Sending zero-size packets is useful for flushing
|
||||
// host-side buffers.)
|
||||
usb_set_ep_tx_count(USB_HID_TX_ENDP, len);
|
||||
n_unsent_bytes = len;
|
||||
transmitting = 1;
|
||||
usb_set_ep_tx_stat(USB_HID_TX_ENDP, USB_EP_STAT_TX_VALID);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint32 usb_hid_data_available(void) {
|
||||
return n_unread_bytes;
|
||||
}
|
||||
|
||||
uint8 usb_hid_is_transmitting(void) {
|
||||
return transmitting;
|
||||
}
|
||||
|
||||
uint16 usb_hid_get_pending(void) {
|
||||
return n_unsent_bytes;
|
||||
}
|
||||
|
||||
/* Nonblocking byte receive.
|
||||
*
|
||||
* Copies up to len bytes from our private data buffer (*NOT* the PMA)
|
||||
* into buf and deq's the FIFO. */
|
||||
uint32 usb_hid_rx(uint8* buf, uint32 len) {
|
||||
/* Copy bytes to buffer. */
|
||||
uint32 n_copied = usb_hid_peek(buf, len);
|
||||
|
||||
/* Mark bytes as read. */
|
||||
n_unread_bytes -= n_copied;
|
||||
rx_offset = (rx_offset + n_copied) % HID_BUFFER_SIZE;
|
||||
|
||||
/* If all bytes have been read, re-enable the RX endpoint, which
|
||||
* was set to NAK when the current batch of bytes was received. */
|
||||
if (n_unread_bytes <= (HID_BUFFER_SIZE - USB_HID_RX_EPSIZE)) {
|
||||
usb_set_ep_rx_count(USB_HID_RX_ENDP, USB_HID_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_HID_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
rx_offset = 0;
|
||||
}
|
||||
|
||||
return n_copied;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callbacks
|
||||
*/
|
||||
|
||||
static void hidDataTxCb(void) {
|
||||
n_unsent_bytes = 0;
|
||||
transmitting = 0;
|
||||
}
|
||||
|
||||
static void hidDataRxCb(void) {
|
||||
uint32 ep_rx_size;
|
||||
uint32 tail = (rx_offset + n_unread_bytes) % HID_BUFFER_SIZE;
|
||||
uint8 ep_rx_data[USB_HID_RX_EPSIZE];
|
||||
uint32 i;
|
||||
|
||||
usb_set_ep_rx_stat(USB_HID_RX_ENDP, USB_EP_STAT_RX_NAK);
|
||||
ep_rx_size = usb_get_ep_rx_count(USB_HID_RX_ENDP);
|
||||
/* This copy won't overwrite unread bytes, since we've set the RX
|
||||
* endpoint to NAK, and will only set it to VALID when all bytes
|
||||
* have been read. */
|
||||
usb_copy_from_pma((uint8*)ep_rx_data, ep_rx_size,
|
||||
USB_HID_RX_ADDR);
|
||||
|
||||
for (i = 0; i < ep_rx_size; i++) {
|
||||
hidBufferRx[tail] = ep_rx_data[i];
|
||||
tail = (tail + 1) % HID_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
n_unread_bytes += ep_rx_size;
|
||||
|
||||
if (n_unread_bytes <= (HID_BUFFER_SIZE - USB_HID_RX_EPSIZE)) {
|
||||
usb_set_ep_rx_count(USB_HID_RX_ENDP, USB_HID_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_HID_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbInit(void) {
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
USB_BASE->CNTR = USB_CNTR_FRES;
|
||||
|
||||
USBLIB->irq_mask = 0;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
USB_BASE->ISTR = 0;
|
||||
USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
|
||||
USB_BASE->ISTR = 0;
|
||||
USBLIB->irq_mask = USB_ISR_MSK;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
|
||||
nvic_irq_enable(NVIC_USB_LP_CAN_RX0);
|
||||
USBLIB->state = USB_UNCONNECTED;
|
||||
}
|
||||
|
||||
#define BTABLE_ADDRESS 0x00
|
||||
static void usbReset(void) {
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
/* current feature is current bmAttributes */
|
||||
pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED |
|
||||
USB_CONFIG_ATTR_SELF_POWERED);
|
||||
|
||||
USB_BASE->BTABLE = BTABLE_ADDRESS;
|
||||
|
||||
/* setup control endpoint 0 */
|
||||
usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL);
|
||||
usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL);
|
||||
usb_set_ep_rx_addr(USB_EP0, USB_HID_CTRL_RX_ADDR);
|
||||
usb_set_ep_tx_addr(USB_EP0, USB_HID_CTRL_TX_ADDR);
|
||||
usb_clear_status_out(USB_EP0);
|
||||
|
||||
usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize);
|
||||
usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID);
|
||||
|
||||
/* TODO figure out differences in style between RX/TX EP setup */
|
||||
|
||||
/* set up data endpoint OUT (RX) */
|
||||
usb_set_ep_type(USB_HID_RX_ENDP, USB_EP_EP_TYPE_BULK);
|
||||
usb_set_ep_rx_addr(USB_HID_RX_ENDP, USB_HID_RX_ADDR);
|
||||
usb_set_ep_rx_count(USB_HID_RX_ENDP, USB_HID_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_HID_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
|
||||
/* set up data endpoint IN (TX) */
|
||||
usb_set_ep_type(USB_HID_TX_ENDP, USB_EP_EP_TYPE_BULK);
|
||||
usb_set_ep_tx_addr(USB_HID_TX_ENDP, USB_HID_TX_ADDR);
|
||||
usb_set_ep_tx_stat(USB_HID_TX_ENDP, USB_EP_STAT_TX_NAK);
|
||||
usb_set_ep_rx_stat(USB_HID_TX_ENDP, USB_EP_STAT_RX_DISABLED);
|
||||
|
||||
USBLIB->state = USB_ATTACHED;
|
||||
SetDeviceAddress(0);
|
||||
|
||||
/* Reset the RX/TX state */
|
||||
n_unread_bytes = 0;
|
||||
n_unsent_bytes = 0;
|
||||
rx_offset = 0;
|
||||
transmitting = 0;
|
||||
}
|
||||
|
||||
static RESULT usbDataSetup(uint8 request) {
|
||||
uint8* (*CopyRoutine)(uint16) = 0;
|
||||
|
||||
if ((request == GET_DESCRIPTOR)
|
||||
&& (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
|
||||
&& (pInformation->USBwIndex0 == 0)){
|
||||
|
||||
if (pInformation->USBwValue1 == REPORT_DESCRIPTOR){
|
||||
CopyRoutine = HID_GetReportDescriptor;
|
||||
} else if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE){
|
||||
CopyRoutine = HID_GetHIDDescriptor;
|
||||
}
|
||||
|
||||
} /* End of GET_DESCRIPTOR */
|
||||
/*** GET_PROTOCOL ***/
|
||||
else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))//){
|
||||
&& request == GET_PROTOCOL){
|
||||
CopyRoutine = HID_GetProtocolValue;
|
||||
}
|
||||
|
||||
if (CopyRoutine == NULL){
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
pInformation->Ctrl_Info.CopyData = CopyRoutine;
|
||||
pInformation->Ctrl_Info.Usb_wOffset = 0;
|
||||
(*CopyRoutine)(0);
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
static RESULT usbNoDataSetup(uint8 request) {
|
||||
if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
|
||||
&& (request == SET_PROTOCOL)){
|
||||
uint8 wValue0 = pInformation->USBwValue0;
|
||||
ProtocolValue = wValue0;
|
||||
return USB_SUCCESS;
|
||||
//return HID_SetProtocol();
|
||||
}else{
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
}
|
||||
|
||||
static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) {
|
||||
if (alt_setting > 0) {
|
||||
return USB_UNSUPPORT;
|
||||
} else if (interface > 1) {
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
static uint8* usbGetDeviceDescriptor(uint16 length) {
|
||||
return Standard_GetDescriptorData(length, &Device_Descriptor);
|
||||
}
|
||||
|
||||
static uint8* usbGetConfigDescriptor(uint16 length) {
|
||||
return Standard_GetDescriptorData(length, &Config_Descriptor);
|
||||
}
|
||||
|
||||
static uint8* usbGetStringDescriptor(uint16 length) {
|
||||
uint8 wValue0 = pInformation->USBwValue0;
|
||||
|
||||
if (wValue0 > N_STRING_DESCRIPTORS) {
|
||||
return NULL;
|
||||
}
|
||||
return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]);
|
||||
}
|
||||
|
||||
/*
|
||||
static RESULT HID_SetProtocol(void){
|
||||
uint8 wValue0 = pInformation->USBwValue0;
|
||||
ProtocolValue = wValue0;
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
*/
|
||||
static uint8* HID_GetProtocolValue(uint16 Length){
|
||||
if (Length == 0){
|
||||
pInformation->Ctrl_Info.Usb_wLength = 1;
|
||||
return NULL;
|
||||
} else {
|
||||
return (uint8 *)(&ProtocolValue);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8* HID_GetReportDescriptor(uint16 Length){
|
||||
return Standard_GetDescriptorData(Length, &HID_Report_Descriptor);
|
||||
}
|
||||
|
||||
static uint8* HID_GetHIDDescriptor(uint16 Length)
|
||||
{
|
||||
return Standard_GetDescriptorData(Length, &Config_Descriptor);
|
||||
}
|
||||
|
||||
static void usbSetConfiguration(void) {
|
||||
if (pInformation->Current_Configuration != 0) {
|
||||
USBLIB->state = USB_CONFIGURED;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbSetDeviceAddress(void) {
|
||||
USBLIB->state = USB_ADDRESSED;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,768 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 LeafLabs LLC.
|
||||
* Copyright (c) 2013 Magnus Lundin.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/usb/stm32f1/usb_midi_device.c
|
||||
* @brief USB MIDI.
|
||||
*
|
||||
* FIXME: this works on the STM32F1 USB peripherals, and probably no
|
||||
* place else. Nonportable bits really need to be factored out, and
|
||||
* the result made cleaner.
|
||||
*/
|
||||
|
||||
#ifdef USB_MIDI
|
||||
|
||||
#include <libmaple/usb_midi_device.h>
|
||||
#include <MidiSpecs.h>
|
||||
#include <MinSysex.h>
|
||||
|
||||
#include <libmaple/usb.h>
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/delay.h>
|
||||
|
||||
/* Private headers */
|
||||
#include "usb_lib_globals.h"
|
||||
#include "usb_reg_map.h"
|
||||
|
||||
/* usb_lib headers */
|
||||
#include "usb_type.h"
|
||||
#include "usb_core.h"
|
||||
#include "usb_def.h"
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
***
|
||||
*** HACK ALERT! FIXME FIXME FIXME FIXME!
|
||||
***
|
||||
*** A bunch of LeafLabs-specific configuration lives in here for
|
||||
*** now. This mess REALLY needs to get teased apart, with
|
||||
*** appropriate pieces moved into Wirish.
|
||||
***
|
||||
******************************************************************************
|
||||
*****************************************************************************/
|
||||
#warning passt alles
|
||||
#if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \
|
||||
defined(BOARD_maple_mini) || defined(BOARD_maple_native))
|
||||
#warning USB MIDI relies on LeafLabs board-specific configuration.\
|
||||
You may have problems on non-LeafLabs boards.
|
||||
#endif
|
||||
|
||||
static void midiDataTxCb(void);
|
||||
static void midiDataRxCb(void);
|
||||
|
||||
static void usbInit(void);
|
||||
static void usbReset(void);
|
||||
static RESULT usbDataSetup(uint8 request);
|
||||
static RESULT usbNoDataSetup(uint8 request);
|
||||
static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting);
|
||||
static uint8* usbGetDeviceDescriptor(uint16 length);
|
||||
static uint8* usbGetConfigDescriptor(uint16 length);
|
||||
static uint8* usbGetStringDescriptor(uint16 length);
|
||||
static void usbSetConfiguration(void);
|
||||
static void usbSetDeviceAddress(void);
|
||||
|
||||
/*
|
||||
* Descriptors
|
||||
*/
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
#define LEAFLABS_ID_VENDOR 0x1EAF
|
||||
#define MAPLE_ID_PRODUCT 0x0014
|
||||
/* 0x7D = ED/FREE next two DIGITS MUST BE LESS THAN 0x7f */
|
||||
|
||||
static const usb_descriptor_device usbMIDIDescriptor_Device =
|
||||
USB_MIDI_DECLARE_DEV_DESC(LEAFLABS_ID_VENDOR, MAPLE_ID_PRODUCT);
|
||||
|
||||
typedef struct {
|
||||
usb_descriptor_config_header Config_Header;
|
||||
/* Control Interface */
|
||||
usb_descriptor_interface AC_Interface;
|
||||
AC_CS_INTERFACE_DESCRIPTOR(1) AC_CS_Interface;
|
||||
/* Control Interface */
|
||||
usb_descriptor_interface MS_Interface;
|
||||
MS_CS_INTERFACE_DESCRIPTOR MS_CS_Interface;
|
||||
MIDI_IN_JACK_DESCRIPTOR MIDI_IN_JACK_1;
|
||||
MIDI_IN_JACK_DESCRIPTOR MIDI_IN_JACK_2;
|
||||
MIDI_OUT_JACK_DESCRIPTOR(1) MIDI_OUT_JACK_3;
|
||||
MIDI_OUT_JACK_DESCRIPTOR(1) MIDI_OUT_JACK_4;
|
||||
usb_descriptor_endpoint DataOutEndpoint;
|
||||
MS_CS_BULK_ENDPOINT_DESCRIPTOR(1) MS_CS_DataOutEndpoint;
|
||||
usb_descriptor_endpoint DataInEndpoint;
|
||||
MS_CS_BULK_ENDPOINT_DESCRIPTOR(1) MS_CS_DataInEndpoint;
|
||||
} __packed usb_descriptor_config;
|
||||
|
||||
#define MAX_POWER (100 >> 1)
|
||||
static const usb_descriptor_config usbMIDIDescriptor_Config = {
|
||||
.Config_Header = {
|
||||
.bLength = sizeof(usb_descriptor_config_header),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION,
|
||||
.wTotalLength = sizeof(usb_descriptor_config),
|
||||
.bNumInterfaces = 0x02,
|
||||
.bConfigurationValue = 0x01,
|
||||
.iConfiguration = 0x00,
|
||||
.bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED |
|
||||
USB_CONFIG_ATTR_SELF_POWERED),
|
||||
.bMaxPower = MAX_POWER,
|
||||
},
|
||||
|
||||
.AC_Interface = {
|
||||
.bLength = sizeof(usb_descriptor_interface),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
|
||||
.bInterfaceNumber = 0x00,
|
||||
.bAlternateSetting = 0x00,
|
||||
.bNumEndpoints = 0x00,
|
||||
.bInterfaceClass = USB_INTERFACE_CLASS_AUDIO,
|
||||
.bInterfaceSubClass = USB_INTERFACE_AUDIOCONTROL,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.iInterface = 0x00,
|
||||
},
|
||||
|
||||
.AC_CS_Interface = {
|
||||
.bLength = AC_CS_INTERFACE_DESCRIPTOR_SIZE(1),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
|
||||
.SubType = 0x01,
|
||||
.bcdADC = 0x0100,
|
||||
.wTotalLength = AC_CS_INTERFACE_DESCRIPTOR_SIZE(1),
|
||||
.bInCollection = 0x01,
|
||||
.baInterfaceNr = {0x01},
|
||||
},
|
||||
|
||||
.MS_Interface = {
|
||||
.bLength = sizeof(usb_descriptor_interface),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
|
||||
.bInterfaceNumber = 0x01,
|
||||
.bAlternateSetting = 0x00,
|
||||
.bNumEndpoints = 0x02,
|
||||
.bInterfaceClass = USB_INTERFACE_CLASS_AUDIO,
|
||||
.bInterfaceSubClass = USB_INTERFACE_MIDISTREAMING,
|
||||
.bInterfaceProtocol = 0x00,
|
||||
.iInterface = 0x04,
|
||||
},
|
||||
|
||||
.MS_CS_Interface = {
|
||||
.bLength = sizeof(MS_CS_INTERFACE_DESCRIPTOR),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
|
||||
.SubType = 0x01,
|
||||
.bcdADC = 0x0100,
|
||||
.wTotalLength = sizeof(MS_CS_INTERFACE_DESCRIPTOR)
|
||||
+sizeof(MIDI_IN_JACK_DESCRIPTOR)
|
||||
+sizeof(MIDI_IN_JACK_DESCRIPTOR)
|
||||
+MIDI_OUT_JACK_DESCRIPTOR_SIZE(1)
|
||||
+MIDI_OUT_JACK_DESCRIPTOR_SIZE(1)
|
||||
+sizeof(usb_descriptor_endpoint)
|
||||
+MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1)
|
||||
+sizeof(usb_descriptor_endpoint)
|
||||
+MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1)
|
||||
/* 0x41-4 */,
|
||||
},
|
||||
|
||||
.MIDI_IN_JACK_1 = {
|
||||
.bLength = sizeof(MIDI_IN_JACK_DESCRIPTOR),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
|
||||
.SubType = MIDI_IN_JACK,
|
||||
.bJackType = MIDI_JACK_EMBEDDED,
|
||||
.bJackId = 0x01,
|
||||
.iJack = 0x05,
|
||||
},
|
||||
|
||||
.MIDI_IN_JACK_2 = {
|
||||
.bLength = sizeof(MIDI_IN_JACK_DESCRIPTOR),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
|
||||
.SubType = MIDI_IN_JACK,
|
||||
.bJackType = MIDI_JACK_EXTERNAL,
|
||||
.bJackId = 0x02,
|
||||
.iJack = 0x00,
|
||||
},
|
||||
|
||||
.MIDI_OUT_JACK_3 = {
|
||||
.bLength = MIDI_OUT_JACK_DESCRIPTOR_SIZE(1),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
|
||||
.SubType = MIDI_OUT_JACK,
|
||||
.bJackType = MIDI_JACK_EMBEDDED,
|
||||
.bJackId = 0x03,
|
||||
.bNrInputPins = 0x01,
|
||||
.baSourceId = {0x02},
|
||||
.baSourcePin = {0x01},
|
||||
.iJack = 0x00,
|
||||
},
|
||||
|
||||
.MIDI_OUT_JACK_4 = {
|
||||
.bLength = MIDI_OUT_JACK_DESCRIPTOR_SIZE(1),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CS_INTERFACE,
|
||||
.SubType = MIDI_OUT_JACK,
|
||||
.bJackType = MIDI_JACK_EXTERNAL,
|
||||
.bJackId = 0x04,
|
||||
.bJackId = 0x03,
|
||||
.bNrInputPins = 0x01,
|
||||
.baSourceId = {0x01},
|
||||
.baSourcePin = {0x01},
|
||||
.iJack = 0x00,
|
||||
},
|
||||
|
||||
.DataOutEndpoint = {
|
||||
.bLength = sizeof(usb_descriptor_endpoint),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT |
|
||||
USB_MIDI_RX_ENDP),
|
||||
.bmAttributes = USB_EP_TYPE_BULK,
|
||||
.wMaxPacketSize = USB_MIDI_RX_EPSIZE,
|
||||
.bInterval = 0x00,
|
||||
},
|
||||
|
||||
.MS_CS_DataOutEndpoint = {
|
||||
.bLength = MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CS_ENDPOINT,
|
||||
.SubType = 0x01,
|
||||
.bNumEmbMIDIJack = 0x01,
|
||||
.baAssocJackID = {0x01},
|
||||
},
|
||||
|
||||
.DataInEndpoint = {
|
||||
.bLength = sizeof(usb_descriptor_endpoint),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | USB_MIDI_TX_ENDP),
|
||||
.bmAttributes = USB_EP_TYPE_BULK,
|
||||
.wMaxPacketSize = USB_MIDI_TX_EPSIZE,
|
||||
.bInterval = 0x00,
|
||||
},
|
||||
|
||||
.MS_CS_DataInEndpoint = {
|
||||
.bLength = MS_CS_BULK_ENDPOINT_DESCRIPTOR_SIZE(1),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CS_ENDPOINT,
|
||||
.SubType = 0x01,
|
||||
.bNumEmbMIDIJack = 0x01,
|
||||
.baAssocJackID = {0x03},
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
String Descriptors:
|
||||
we may choose to specify any or none of the following string
|
||||
identifiers:
|
||||
iManufacturer: LeafLabs
|
||||
iProduct: Maple
|
||||
iSerialNumber: NONE
|
||||
iConfiguration: NONE
|
||||
iInterface(CCI): NONE
|
||||
iInterface(DCI): NONE
|
||||
*/
|
||||
|
||||
/* Unicode language identifier: 0x0409 is US English */
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbMIDIDescriptor_LangID = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(1),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {0x09, 0x04},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbMIDIDescriptor_iManufacturer = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(8),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {'D', 0, 'i', 0, 'r', 0, 'o', 0,
|
||||
' ', 0, ' ', 0, ' ', 0, ' ', 0},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbMIDIDescriptor_iProduct = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(10),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
// .bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0, ' ', 0, 'M', 0, 'I', 0, 'D', 0, 'I', 0},
|
||||
.bString = {'D', 0, 'i', 0, 'r', 0, 'o', 0, ' ', 0, 'S', 0, 'y', 0, 'n', 0, 't', 0, 'h', 0},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbMIDIDescriptor_iInterface = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(4),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {'M', 0, 'I', 0, 'D', 0, 'I', 0},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbMIDIDescriptor_iJack1 = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(5),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {'J', 0, 'a', 0, 'c', 0, 'k', 0, '1', 0},
|
||||
};
|
||||
|
||||
|
||||
static ONE_DESCRIPTOR Device_Descriptor = {
|
||||
(uint8*)&usbMIDIDescriptor_Device,
|
||||
sizeof(usb_descriptor_device)
|
||||
};
|
||||
|
||||
static ONE_DESCRIPTOR Config_Descriptor = {
|
||||
(uint8*)&usbMIDIDescriptor_Config,
|
||||
sizeof(usb_descriptor_config)
|
||||
};
|
||||
|
||||
#define N_STRING_DESCRIPTORS 5
|
||||
static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = {
|
||||
{(uint8*)&usbMIDIDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)},
|
||||
{(uint8*)&usbMIDIDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)},
|
||||
{(uint8*)&usbMIDIDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(10)},
|
||||
{(uint8*)&usbMIDIDescriptor_iInterface, USB_DESCRIPTOR_STRING_LEN(4)},
|
||||
{(uint8*)&usbMIDIDescriptor_iJack1, USB_DESCRIPTOR_STRING_LEN(5)}
|
||||
};
|
||||
|
||||
/*
|
||||
* Etc.
|
||||
*/
|
||||
|
||||
/* I/O state */
|
||||
|
||||
/* Received data */
|
||||
static volatile uint32 midiBufferRx[USB_MIDI_RX_EPSIZE/4];
|
||||
/* Read index into midiBufferRx */
|
||||
static volatile uint32 rx_offset = 0;
|
||||
/* Transmit data */
|
||||
static volatile uint32 midiBufferTx[USB_MIDI_TX_EPSIZE/4];
|
||||
/* Write index into midiBufferTx */
|
||||
static volatile uint32 tx_offset = 0;
|
||||
/* Number of bytes left to transmit */
|
||||
static volatile uint32 n_unsent_packets = 0;
|
||||
/* Are we currently sending an IN packet? */
|
||||
static volatile uint8 transmitting = 0;
|
||||
/* Number of unread bytes */
|
||||
static volatile uint32 n_unread_packets = 0;
|
||||
|
||||
|
||||
// eventually all of this should be in a place for settings which can be written to flash.
|
||||
volatile uint8 myMidiChannel = DEFAULT_MIDI_CHANNEL;
|
||||
volatile uint8 myMidiDevice = DEFAULT_MIDI_DEVICE;
|
||||
volatile uint8 myMidiCable = DEFAULT_MIDI_CABLE;
|
||||
volatile uint8 myMidiID[] = { LEAFLABS_MMA_VENDOR_1,LEAFLABS_MMA_VENDOR_2,LEAFLABS_MMA_VENDOR_3,0};
|
||||
|
||||
/*
|
||||
* Endpoint callbacks
|
||||
*/
|
||||
|
||||
static void (*ep_int_in[7])(void) =
|
||||
{midiDataTxCb,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process};
|
||||
|
||||
static void (*ep_int_out[7])(void) =
|
||||
{NOP_Process,
|
||||
midiDataRxCb,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process};
|
||||
|
||||
/*
|
||||
* Globals required by usb_lib/
|
||||
*
|
||||
* Mark these weak so they can be overriden to implement other USB
|
||||
* functionality.
|
||||
*/
|
||||
|
||||
#define NUM_ENDPTS 0x04
|
||||
__weak DEVICE Device_Table = {
|
||||
.Total_Endpoint = NUM_ENDPTS,
|
||||
.Total_Configuration = 1
|
||||
};
|
||||
|
||||
#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */
|
||||
__weak DEVICE_PROP Device_Property = {
|
||||
.Init = usbInit,
|
||||
.Reset = usbReset,
|
||||
.Process_Status_IN = NOP_Process,
|
||||
.Process_Status_OUT = NOP_Process,
|
||||
.Class_Data_Setup = usbDataSetup,
|
||||
.Class_NoData_Setup = usbNoDataSetup,
|
||||
.Class_Get_Interface_Setting = usbGetInterfaceSetting,
|
||||
.GetDeviceDescriptor = usbGetDeviceDescriptor,
|
||||
.GetConfigDescriptor = usbGetConfigDescriptor,
|
||||
.GetStringDescriptor = usbGetStringDescriptor,
|
||||
.RxEP_buffer = NULL,
|
||||
.MaxPacketSize = MAX_PACKET_SIZE
|
||||
};
|
||||
|
||||
__weak USER_STANDARD_REQUESTS User_Standard_Requests = {
|
||||
.User_GetConfiguration = NOP_Process,
|
||||
.User_SetConfiguration = usbSetConfiguration,
|
||||
.User_GetInterface = NOP_Process,
|
||||
.User_SetInterface = NOP_Process,
|
||||
.User_GetStatus = NOP_Process,
|
||||
.User_ClearFeature = NOP_Process,
|
||||
.User_SetEndPointFeature = NOP_Process,
|
||||
.User_SetDeviceFeature = NOP_Process,
|
||||
.User_SetDeviceAddress = usbSetDeviceAddress
|
||||
};
|
||||
|
||||
/*
|
||||
* MIDI interface
|
||||
*/
|
||||
|
||||
void usb_midi_enable(gpio_dev *disc_dev, uint8 disc_bit) {
|
||||
/* Present ourselves to the host. Writing 0 to "disc" pin must
|
||||
* pull USB_DP pin up while leaving USB_DM pulled down by the
|
||||
* transceiver. See USB 2.0 spec, section 7.1.7.3. */
|
||||
gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP);
|
||||
gpio_write_bit(disc_dev, disc_bit, 0);
|
||||
|
||||
/* Initialize the USB peripheral. */
|
||||
usb_init_usblib(USBLIB, ep_int_in, ep_int_out);
|
||||
}
|
||||
|
||||
void usb_midi_disable(gpio_dev *disc_dev, uint8 disc_bit) {
|
||||
/* Turn off the interrupt and signal disconnect (see e.g. USB 2.0
|
||||
* spec, section 7.1.7.3). */
|
||||
nvic_irq_disable(NVIC_USB_LP_CAN_RX0);
|
||||
gpio_write_bit(disc_dev, disc_bit, 1);
|
||||
}
|
||||
|
||||
//void usb_midi_putc(char ch) {
|
||||
// while (!usb_midi_tx((uint8*)&ch, 1))
|
||||
// ;
|
||||
//}
|
||||
|
||||
/* This function is non-blocking.
|
||||
*
|
||||
* It copies data from a usercode buffer into the USB peripheral TX
|
||||
* buffer, and returns the number of bytes copied. */
|
||||
uint32 usb_midi_tx(const uint32* buf, uint32 packets) {
|
||||
uint32 bytes=packets*4;
|
||||
/* Last transmission hasn't finished, so abort. */
|
||||
if (usb_midi_is_transmitting()) {
|
||||
/* Copy to TxBuffer */
|
||||
|
||||
return 0; /* return len */
|
||||
}
|
||||
|
||||
/* We can only put USB_MIDI_TX_EPSIZE bytes in the buffer. */
|
||||
if (bytes > USB_MIDI_TX_EPSIZE) {
|
||||
bytes = USB_MIDI_TX_EPSIZE;
|
||||
packets=bytes/4;
|
||||
}
|
||||
|
||||
/* Queue bytes for sending. */
|
||||
if (packets) {
|
||||
usb_copy_to_pma((uint8 *)buf, bytes, USB_MIDI_TX_ADDR);
|
||||
}
|
||||
// We still need to wait for the interrupt, even if we're sending
|
||||
// zero bytes. (Sending zero-size packets is useful for flushing
|
||||
// host-side buffers.)
|
||||
usb_set_ep_tx_count(USB_MIDI_TX_ENDP, bytes);
|
||||
n_unsent_packets = packets;
|
||||
transmitting = 1;
|
||||
usb_set_ep_tx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_TX_VALID);
|
||||
|
||||
return packets;
|
||||
}
|
||||
|
||||
uint32 usb_midi_data_available(void) {
|
||||
return n_unread_packets;
|
||||
}
|
||||
|
||||
uint8 usb_midi_is_transmitting(void) {
|
||||
return transmitting;
|
||||
}
|
||||
|
||||
uint16 usb_midi_get_pending(void) {
|
||||
return n_unsent_packets;
|
||||
}
|
||||
|
||||
/* Nonblocking byte receive.
|
||||
*
|
||||
* Copies up to len bytes from our private data buffer (*NOT* the PMA)
|
||||
* into buf and deq's the FIFO. */
|
||||
uint32 usb_midi_rx(uint32* buf, uint32 packets) {
|
||||
/* Copy bytes to buffer. */
|
||||
uint32 n_copied = usb_midi_peek(buf, packets);
|
||||
|
||||
/* Mark bytes as read. */
|
||||
n_unread_packets -= n_copied;
|
||||
rx_offset += n_copied;
|
||||
|
||||
/* If all bytes have been read, re-enable the RX endpoint, which
|
||||
* was set to NAK when the current batch of bytes was received. */
|
||||
if (n_unread_packets == 0) {
|
||||
usb_set_ep_rx_count(USB_MIDI_RX_ENDP, USB_MIDI_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
rx_offset = 0;
|
||||
}
|
||||
|
||||
return n_copied;
|
||||
}
|
||||
|
||||
/* Nonblocking byte lookahead.
|
||||
*
|
||||
* Looks at unread bytes without marking them as read. */
|
||||
uint32 usb_midi_peek(uint32* buf, uint32 packets) {
|
||||
int i;
|
||||
if (packets > n_unread_packets) {
|
||||
packets = n_unread_packets;
|
||||
}
|
||||
|
||||
for (i = 0; i < packets; i++) {
|
||||
buf[i] = midiBufferRx[i + rx_offset];
|
||||
}
|
||||
|
||||
return packets;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callbacks
|
||||
*/
|
||||
|
||||
static void midiDataTxCb(void) {
|
||||
n_unsent_packets = 0;
|
||||
transmitting = 0;
|
||||
}
|
||||
|
||||
static void midiDataRxCb(void) {
|
||||
|
||||
usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_NAK);
|
||||
n_unread_packets = usb_get_ep_rx_count(USB_MIDI_RX_ENDP) / 4;
|
||||
/* This copy won't overwrite unread bytes, since we've set the RX
|
||||
* endpoint to NAK, and will only set it to VALID when all bytes
|
||||
* have been read. */
|
||||
|
||||
usb_copy_from_pma((uint8*)midiBufferRx, n_unread_packets * 4,
|
||||
USB_MIDI_RX_ADDR);
|
||||
|
||||
LglSysexHandler(midiBufferRx,&rx_offset,&n_unread_packets);
|
||||
|
||||
if (n_unread_packets == 0) {
|
||||
usb_set_ep_rx_count(USB_MIDI_RX_ENDP, USB_MIDI_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
rx_offset = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* NOTE: Nothing specific to this device class in this function, move to usb_lib */
|
||||
static void usbInit(void) {
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
USB_BASE->CNTR = USB_CNTR_FRES;
|
||||
|
||||
USBLIB->irq_mask = 0;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
USB_BASE->ISTR = 0;
|
||||
USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
|
||||
USB_BASE->ISTR = 0;
|
||||
USBLIB->irq_mask = USB_ISR_MSK;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
|
||||
nvic_irq_enable(NVIC_USB_LP_CAN_RX0);
|
||||
USBLIB->state = USB_UNCONNECTED;
|
||||
}
|
||||
|
||||
#define BTABLE_ADDRESS 0x00
|
||||
static void usbReset(void) {
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
/* current feature is current bmAttributes */
|
||||
pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED |
|
||||
USB_CONFIG_ATTR_SELF_POWERED);
|
||||
|
||||
USB_BASE->BTABLE = BTABLE_ADDRESS;
|
||||
|
||||
/* setup control endpoint 0 */
|
||||
usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL);
|
||||
usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL);
|
||||
usb_set_ep_rx_addr(USB_EP0, USB_MIDI_CTRL_RX_ADDR);
|
||||
usb_set_ep_tx_addr(USB_EP0, USB_MIDI_CTRL_TX_ADDR);
|
||||
usb_clear_status_out(USB_EP0);
|
||||
|
||||
usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize);
|
||||
usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID);
|
||||
|
||||
/* TODO figure out differences in style between RX/TX EP setup */
|
||||
|
||||
/* set up data endpoint OUT (RX) */
|
||||
usb_set_ep_type(USB_MIDI_RX_ENDP, USB_EP_EP_TYPE_BULK);
|
||||
usb_set_ep_rx_addr(USB_MIDI_RX_ENDP, USB_MIDI_RX_ADDR);
|
||||
usb_set_ep_rx_count(USB_MIDI_RX_ENDP, USB_MIDI_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_MIDI_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
|
||||
/* set up data endpoint IN (TX) */
|
||||
usb_set_ep_type(USB_MIDI_TX_ENDP, USB_EP_EP_TYPE_BULK);
|
||||
usb_set_ep_tx_addr(USB_MIDI_TX_ENDP, USB_MIDI_TX_ADDR);
|
||||
usb_set_ep_tx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_TX_NAK);
|
||||
usb_set_ep_rx_stat(USB_MIDI_TX_ENDP, USB_EP_STAT_RX_DISABLED);
|
||||
|
||||
USBLIB->state = USB_ATTACHED;
|
||||
SetDeviceAddress(0);
|
||||
|
||||
/* Reset the RX/TX state */
|
||||
n_unread_packets = 0;
|
||||
n_unsent_packets = 0;
|
||||
rx_offset = 0;
|
||||
}
|
||||
|
||||
static RESULT usbDataSetup(uint8 request) {
|
||||
uint8* (*CopyRoutine)(uint16) = 0;
|
||||
|
||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) {
|
||||
|
||||
}
|
||||
|
||||
if (CopyRoutine == NULL) {
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
pInformation->Ctrl_Info.CopyData = CopyRoutine;
|
||||
pInformation->Ctrl_Info.Usb_wOffset = 0;
|
||||
(*CopyRoutine)(0);
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
static RESULT usbNoDataSetup(uint8 request) {
|
||||
RESULT ret = USB_UNSUPPORT;
|
||||
|
||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) {
|
||||
if (alt_setting > 0) {
|
||||
return USB_UNSUPPORT;
|
||||
} else if (interface > 1) {
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
static uint8* usbGetDeviceDescriptor(uint16 length) {
|
||||
return Standard_GetDescriptorData(length, &Device_Descriptor);
|
||||
}
|
||||
|
||||
static uint8* usbGetConfigDescriptor(uint16 length) {
|
||||
return Standard_GetDescriptorData(length, &Config_Descriptor);
|
||||
}
|
||||
|
||||
static uint8* usbGetStringDescriptor(uint16 length) {
|
||||
uint8 wValue0 = pInformation->USBwValue0;
|
||||
|
||||
if (wValue0 > N_STRING_DESCRIPTORS) {
|
||||
return NULL;
|
||||
}
|
||||
return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]);
|
||||
}
|
||||
|
||||
static void usbSetConfiguration(void) {
|
||||
if (pInformation->Current_Configuration != 0) {
|
||||
USBLIB->state = USB_CONFIGURED;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbSetDeviceAddress(void) {
|
||||
USBLIB->state = USB_ADDRESSED;
|
||||
}
|
||||
// .............THIS IS NOT WORKING YET................
|
||||
// send debugging information to
|
||||
static uint8_t sysexbuffer[80]={CIN_SYSEX,0xF0,0x7D,0x33,CIN_SYSEX,0x33,0x00,0xf7}; // !!!bad hardcoded number foo !!!
|
||||
uint8_t iSysHexLine(uint8_t rectype, uint16_t address, uint8_t *payload,uint8_t payloadlength, uint8_t *buffer);
|
||||
void sendThroughSysex(char *printbuffer, int bufferlength) {
|
||||
int i,n;
|
||||
n = iSysHexLine(1, 0 , (uint8_t *) printbuffer, (uint8_t) bufferlength , sysexbuffer+6);
|
||||
usb_midi_tx((uint32*)sysexbuffer,n/4);
|
||||
}
|
||||
|
||||
#define HIGHBYTE(x) ((uint8_t) (((x) >> 8) & 0x00ff) )
|
||||
#define LOWBYTE(x) ((uint8_t) ((x) & 0x00ff) )
|
||||
#define HIGHNIBBLE(x) ((((uint8_t)(x)) & 0xF0) >> 4)
|
||||
#define LOWNIBBLE(x) (((uint8_t)(x)) & 0x0F)
|
||||
#define HEXCHAR(c) ((c>9)?55+c:48+c)
|
||||
|
||||
|
||||
uint8_t iSysHexLine(uint8_t rectype, uint16_t address, uint8_t *payload,uint8_t payloadlength, uint8_t *buffer) {
|
||||
|
||||
int i=0; int j; int thirdone;
|
||||
uint8_t n=0;
|
||||
uint16_t checksum=0;
|
||||
//uint16_t length=0;
|
||||
|
||||
buffer[i++]=':';
|
||||
|
||||
checksum+=payloadlength;
|
||||
buffer[i++]=HEXCHAR(HIGHNIBBLE(payloadlength));
|
||||
buffer[i++]=HEXCHAR(LOWNIBBLE(payloadlength));
|
||||
buffer[i++]=CIN_SYSEX;
|
||||
|
||||
n=HIGHBYTE(address);
|
||||
checksum+=n;
|
||||
buffer[i++]=HEXCHAR(HIGHNIBBLE(n));
|
||||
buffer[i++]=HEXCHAR(LOWNIBBLE(n));
|
||||
|
||||
n=LOWBYTE(address);
|
||||
checksum+=n;
|
||||
buffer[i++]=HEXCHAR(HIGHNIBBLE(n));
|
||||
buffer[i++]=CIN_SYSEX;
|
||||
buffer[i++]=HEXCHAR(LOWNIBBLE(n));
|
||||
|
||||
n=rectype;
|
||||
checksum+=n;
|
||||
buffer[i++]=HEXCHAR(HIGHNIBBLE(n));
|
||||
buffer[i++]=HEXCHAR(LOWNIBBLE(n));
|
||||
buffer[i++]=CIN_SYSEX;
|
||||
thirdone=0;
|
||||
for (j=0; j<payloadlength ; j++) {
|
||||
n=payload[j];
|
||||
checksum+=n;
|
||||
buffer[i++]=HEXCHAR(HIGHNIBBLE(n));
|
||||
if (++thirdone==3) {
|
||||
buffer[i++]=CIN_SYSEX;
|
||||
thirdone=0;
|
||||
}
|
||||
buffer[i++]=HEXCHAR(LOWNIBBLE(n));
|
||||
if (++thirdone==3) {
|
||||
buffer[i++]=CIN_SYSEX;
|
||||
thirdone=0;
|
||||
}
|
||||
}
|
||||
if (thirdone==0) {
|
||||
buffer[i-1]=CIN_SYSEX_ENDS_IN_3;
|
||||
}
|
||||
n=~((uint8_t) checksum&0x00ff)+1;
|
||||
buffer[i++]=HEXCHAR(HIGHNIBBLE(n));
|
||||
if (thirdone==1) {
|
||||
buffer[i++]=CIN_SYSEX_ENDS_IN_2;
|
||||
}
|
||||
buffer[i++]=HEXCHAR(LOWNIBBLE(n));
|
||||
if (thirdone==2) {
|
||||
buffer[i++]=CIN_SYSEX_ENDS_IN_1;
|
||||
}
|
||||
buffer[i++]=0xf7;
|
||||
return i+thirdone;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -31,6 +31,8 @@ cppSRCS_$(d) += Print.cpp
|
|||
cppSRCS_$(d) += pwm.cpp
|
||||
ifeq ($(MCU_SERIES), stm32f1)
|
||||
cppSRCS_$(d) += usb_serial.cpp # HACK: this is currently STM32F1 only.
|
||||
cppSRCS_$(d) += usb_hid_device.cpp # HACK: this is currently STM32F1 only.
|
||||
cppSRCS_$(d) += usb_midi.cpp # HACK: this is currently STM32F1 only.
|
||||
cppSRCS_$(d) += HardwareSPI.cpp # FIXME: port to F2 and fix wirish.h
|
||||
endif
|
||||
cppSRCS_$(d) += wirish_analog.cpp
|
||||
|
|
|
@ -0,0 +1,454 @@
|
|||
/* Copyright (c) 2011, Peter Barrett
|
||||
**
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND 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, DIRECT, 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief USB HID Keyboard device
|
||||
*/
|
||||
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J)
|
||||
|
||||
#include <usb_hid_device.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/usb_hid.h>
|
||||
#include <libmaple/usb.h>
|
||||
|
||||
#include <wirish.h>
|
||||
|
||||
/*
|
||||
* USB HID interface
|
||||
*/
|
||||
|
||||
#define USB_TIMEOUT 50
|
||||
|
||||
HIDDevice::HIDDevice(void){
|
||||
|
||||
}
|
||||
|
||||
void HIDDevice::begin(void){
|
||||
if(!enabled){
|
||||
usb_hid_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HIDDevice::end(void){
|
||||
if(enabled){
|
||||
usb_hid_disable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Mouse
|
||||
|
||||
HIDMouse::HIDMouse(void) : _buttons(0){
|
||||
}
|
||||
|
||||
void HIDMouse::begin(void){
|
||||
HID.begin();
|
||||
}
|
||||
|
||||
void HIDMouse::end(void){
|
||||
HID.end();
|
||||
}
|
||||
|
||||
void HIDMouse::click(uint8_t b)
|
||||
{
|
||||
_buttons = b;
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
move(0,0,0);
|
||||
_buttons = 0;
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
move(0,0,0);
|
||||
}
|
||||
|
||||
void HIDMouse::move(signed char x, signed char y, signed char wheel)
|
||||
{
|
||||
uint8_t m[4];
|
||||
m[0] = _buttons;
|
||||
m[1] = x;
|
||||
m[2] = y;
|
||||
m[3] = wheel;
|
||||
|
||||
uint8_t buf[1+sizeof(m)];
|
||||
buf[0] = 1;//report id
|
||||
uint8_t i;
|
||||
for(i=0;i<sizeof(m);i++){
|
||||
buf[i+1] = m[i];
|
||||
}
|
||||
|
||||
usb_hid_tx(buf, sizeof(buf));
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
/* flush out to avoid having the pc wait for more data */
|
||||
usb_hid_tx(NULL, 0);
|
||||
}
|
||||
|
||||
void HIDMouse::buttons(uint8_t b)
|
||||
{
|
||||
if (b != _buttons)
|
||||
{
|
||||
_buttons = b;
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
move(0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
void HIDMouse::press(uint8_t b)
|
||||
{
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
buttons(_buttons | b);
|
||||
}
|
||||
|
||||
void HIDMouse::release(uint8_t b)
|
||||
{
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
buttons(_buttons & ~b);
|
||||
}
|
||||
|
||||
bool HIDMouse::isPressed(uint8_t b)
|
||||
{
|
||||
if ((b & _buttons) > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
HIDKeyboard::HIDKeyboard(void){
|
||||
|
||||
}
|
||||
|
||||
void HIDKeyboard::sendReport(KeyReport* keys)
|
||||
{
|
||||
//HID_SendReport(2,keys,sizeof(KeyReport));
|
||||
uint8_t buf[9];//sizeof(_keyReport)+1;
|
||||
buf[0] = 2; //report id;
|
||||
buf[1] = _keyReport.modifiers;
|
||||
buf[2] = _keyReport.reserved;
|
||||
|
||||
uint8_t i;
|
||||
for(i=0;i<sizeof(_keyReport.keys);i++){
|
||||
buf[i+3] = _keyReport.keys[i];
|
||||
}
|
||||
usb_hid_tx(buf, sizeof(buf));
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
/* flush out to avoid having the pc wait for more data */
|
||||
usb_hid_tx(NULL, 0);
|
||||
}
|
||||
|
||||
void HIDKeyboard::begin(void){
|
||||
HID.begin();
|
||||
}
|
||||
|
||||
void HIDKeyboard::end(void) {
|
||||
HID.end();
|
||||
}
|
||||
|
||||
size_t HIDKeyboard::press(uint8_t k)
|
||||
{
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers |= (1<<(k-128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = _asciimap[k];
|
||||
if (!k) {
|
||||
//setWriteError();
|
||||
return 0;
|
||||
}
|
||||
if (k & SHIFT) { // it's a capital letter or other character reached with shift
|
||||
_keyReport.modifiers |= 0x02; // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
// Add k to the key report only if it's not already present
|
||||
// and if there is an empty slot.
|
||||
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
|
||||
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
|
||||
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
|
||||
|
||||
for (i=0; i<6; i++) {
|
||||
if (_keyReport.keys[i] == 0x00) {
|
||||
_keyReport.keys[i] = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 6) {
|
||||
//setWriteError();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// release() takes the specified key out of the persistent key report and
|
||||
// sends the report. This tells the OS the key is no longer pressed and that
|
||||
// it shouldn't be repeated any more.
|
||||
size_t HIDKeyboard::release(uint8_t k)
|
||||
{
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers &= ~(1<<(k-128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = _asciimap[k];
|
||||
if (!k) {
|
||||
return 0;
|
||||
}
|
||||
if (k & 0x80) { // it's a capital letter or other character reached with shift
|
||||
_keyReport.modifiers &= ~(0x02); // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the key report to see if k is present. Clear it if it exists.
|
||||
// Check all positions in case the key is present more than once (which it shouldn't be)
|
||||
for (i=0; i<6; i++) {
|
||||
if (0 != k && _keyReport.keys[i] == k) {
|
||||
_keyReport.keys[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void HIDKeyboard::releaseAll(void)
|
||||
{
|
||||
_keyReport.keys[0] = 0;
|
||||
_keyReport.keys[1] = 0;
|
||||
_keyReport.keys[2] = 0;
|
||||
_keyReport.keys[3] = 0;
|
||||
_keyReport.keys[4] = 0;
|
||||
_keyReport.keys[5] = 0;
|
||||
_keyReport.modifiers = 0;
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
|
||||
sendReport(&_keyReport);
|
||||
}
|
||||
|
||||
size_t HIDKeyboard::write(uint8_t c)
|
||||
{
|
||||
uint8_t p = 0;
|
||||
|
||||
p = press(c); // Keydown
|
||||
release(c); // Keyup
|
||||
|
||||
return (p); // Just return the result of press() since release() almost always returns 1
|
||||
}
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Joystick
|
||||
|
||||
void HIDJoystick::sendReport(void){
|
||||
usb_hid_tx(joystick_Report, sizeof(joystick_Report));
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
/* flush out to avoid having the pc wait for more data */
|
||||
usb_hid_tx(NULL, 0);
|
||||
}
|
||||
|
||||
HIDJoystick::HIDJoystick(void){
|
||||
|
||||
}
|
||||
|
||||
void HIDJoystick::begin(void){
|
||||
HID.begin();
|
||||
}
|
||||
|
||||
void HIDJoystick::end(void){
|
||||
HID.end();
|
||||
}
|
||||
|
||||
void HIDJoystick::button(uint8_t button, bool val){
|
||||
button--;
|
||||
uint8_t mask = (1 << (button & 7));
|
||||
if (val) {
|
||||
if (button < 8) joystick_Report[1] |= mask;
|
||||
else if (button < 16) joystick_Report[2] |= mask;
|
||||
else if (button < 24) joystick_Report[3] |= mask;
|
||||
else if (button < 32) joystick_Report[4] |= mask;
|
||||
} else {
|
||||
mask = ~mask;
|
||||
if (button < 8) joystick_Report[1] &= mask;
|
||||
else if (button < 16) joystick_Report[2] &= mask;
|
||||
else if (button < 24) joystick_Report[3] &= mask;
|
||||
else if (button < 32) joystick_Report[4] &= mask;
|
||||
}
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::X(uint16_t val){
|
||||
if (val > 1023) val = 1023;
|
||||
joystick_Report[5] = (joystick_Report[5] & 0x0F) | (val << 4);
|
||||
joystick_Report[6] = (joystick_Report[6] & 0xC0) | (val >> 4);
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::Y(uint16_t val){
|
||||
if (val > 1023) val = 1023;
|
||||
joystick_Report[6] = (joystick_Report[6] & 0x3F) | (val << 6);
|
||||
joystick_Report[7] = (val >> 2);
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::position(uint16_t x, uint16_t y){
|
||||
if (x > 1023) x = 1023;
|
||||
if (y > 1023) y = 1023;
|
||||
joystick_Report[5] = (joystick_Report[5] & 0x0F) | (x << 4);
|
||||
joystick_Report[6] = (x >> 4) | (y << 6);
|
||||
joystick_Report[7] = (y >> 2);
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::Z(uint16_t val){
|
||||
if (val > 1023) val = 1023;
|
||||
joystick_Report[8] = val;
|
||||
joystick_Report[9] = (joystick_Report[9] & 0xFC) | (val >> 8);
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::Zrotate(uint16_t val){
|
||||
if (val > 1023) val = 1023;
|
||||
joystick_Report[9] = (joystick_Report[9] & 0x03) | (val << 2);
|
||||
joystick_Report[10] = (joystick_Report[10] & 0xF0) | (val >> 6);
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::sliderLeft(uint16_t val){
|
||||
if (val > 1023) val = 1023;
|
||||
joystick_Report[10] = (joystick_Report[10] & 0x0F) | (val << 4);
|
||||
joystick_Report[11] = (joystick_Report[11] & 0xC0) | (val >> 4);
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::sliderRight(uint16_t val){
|
||||
if (val > 1023) val = 1023;
|
||||
joystick_Report[11] = (joystick_Report[11] & 0x3F) | (val << 6);
|
||||
joystick_Report[12] = (val >> 2);
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::slider(uint16_t val){
|
||||
if (val > 1023) val = 1023;
|
||||
joystick_Report[10] = (joystick_Report[10] & 0x0F) | (val << 4);
|
||||
joystick_Report[11] = (val >> 4) | (val << 6);
|
||||
joystick_Report[12] = (val >> 2);
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void HIDJoystick::hat(int16_t dir){
|
||||
uint8_t val;
|
||||
if (dir < 0) val = 15;
|
||||
else if (dir < 23) val = 0;
|
||||
else if (dir < 68) val = 1;
|
||||
else if (dir < 113) val = 2;
|
||||
else if (dir < 158) val = 3;
|
||||
else if (dir < 203) val = 4;
|
||||
else if (dir < 245) val = 5;
|
||||
else if (dir < 293) val = 6;
|
||||
else if (dir < 338) val = 7;
|
||||
joystick_Report[5] = (joystick_Report[5] & 0xF0) | val;
|
||||
|
||||
|
||||
while (usb_hid_is_transmitting() != 0) {
|
||||
}
|
||||
sendReport();
|
||||
}
|
||||
|
||||
|
||||
HIDDevice HID;
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_KM)
|
||||
HIDMouse Mouse;
|
||||
HIDKeyboard Keyboard;
|
||||
#endif
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_J)
|
||||
HIDJoystick Joystick;
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
Copyright (c) 2012 Arduino. All right reserved.
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This library 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 Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Wirish USB HID port (HID USB).
|
||||
*/
|
||||
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J)
|
||||
|
||||
#ifndef _WIRISH_USB_HID_H_
|
||||
#define _WIRISH_USB_HID_H_
|
||||
|
||||
#include <Print.h>
|
||||
#include <boards.h>
|
||||
|
||||
class HIDDevice{
|
||||
private:
|
||||
bool enabled = false;
|
||||
public:
|
||||
HIDDevice(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
};
|
||||
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Mouse
|
||||
|
||||
#define MOUSE_LEFT 1
|
||||
#define MOUSE_RIGHT 2
|
||||
#define MOUSE_MIDDLE 4
|
||||
#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)
|
||||
|
||||
class HIDMouse{
|
||||
private:
|
||||
uint8_t _buttons;
|
||||
void buttons(uint8_t b);
|
||||
public:
|
||||
HIDMouse(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
void click(uint8_t b = MOUSE_LEFT);
|
||||
void move(signed char x, signed char y, signed char wheel = 0);
|
||||
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
|
||||
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
|
||||
bool isPressed(uint8_t b = MOUSE_ALL); // check all buttons by default
|
||||
};
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
#define SHIFT 0x80
|
||||
const uint8_t _asciimap[128] =
|
||||
{
|
||||
0x00, // NUL
|
||||
0x00, // SOH
|
||||
0x00, // STX
|
||||
0x00, // ETX
|
||||
0x00, // EOT
|
||||
0x00, // ENQ
|
||||
0x00, // ACK
|
||||
0x00, // BEL
|
||||
0x2a, // BS Backspace
|
||||
0x2b, // TAB Tab
|
||||
0x28, // LF Enter
|
||||
0x00, // VT
|
||||
0x00, // FF
|
||||
0x00, // CR
|
||||
0x00, // SO
|
||||
0x00, // SI
|
||||
0x00, // DEL
|
||||
0x00, // DC1
|
||||
0x00, // DC2
|
||||
0x00, // DC3
|
||||
0x00, // DC4
|
||||
0x00, // NAK
|
||||
0x00, // SYN
|
||||
0x00, // ETB
|
||||
0x00, // CAN
|
||||
0x00, // EM
|
||||
0x00, // SUB
|
||||
0x00, // ESC
|
||||
0x00, // FS
|
||||
0x00, // GS
|
||||
0x00, // RS
|
||||
0x00, // US
|
||||
|
||||
0x2c, // ' '
|
||||
0x1e|SHIFT, // !
|
||||
0x34|SHIFT, // "
|
||||
0x20|SHIFT, // #
|
||||
0x21|SHIFT, // $
|
||||
0x22|SHIFT, // %
|
||||
0x24|SHIFT, // &
|
||||
0x34, // '
|
||||
0x26|SHIFT, // (
|
||||
0x27|SHIFT, // )
|
||||
0x25|SHIFT, // *
|
||||
0x2e|SHIFT, // +
|
||||
0x36, // ,
|
||||
0x2d, // -
|
||||
0x37, // .
|
||||
0x38, // /
|
||||
0x27, // 0
|
||||
0x1e, // 1
|
||||
0x1f, // 2
|
||||
0x20, // 3
|
||||
0x21, // 4
|
||||
0x22, // 5
|
||||
0x23, // 6
|
||||
0x24, // 7
|
||||
0x25, // 8
|
||||
0x26, // 9
|
||||
0x33|SHIFT, // :
|
||||
0x33, // ;
|
||||
0x36|SHIFT, // <
|
||||
0x2e, // =
|
||||
0x37|SHIFT, // >
|
||||
0x38|SHIFT, // ?
|
||||
0x1f|SHIFT, // @
|
||||
0x04|SHIFT, // A
|
||||
0x05|SHIFT, // B
|
||||
0x06|SHIFT, // C
|
||||
0x07|SHIFT, // D
|
||||
0x08|SHIFT, // E
|
||||
0x09|SHIFT, // F
|
||||
0x0a|SHIFT, // G
|
||||
0x0b|SHIFT, // H
|
||||
0x0c|SHIFT, // I
|
||||
0x0d|SHIFT, // J
|
||||
0x0e|SHIFT, // K
|
||||
0x0f|SHIFT, // L
|
||||
0x10|SHIFT, // M
|
||||
0x11|SHIFT, // N
|
||||
0x12|SHIFT, // O
|
||||
0x13|SHIFT, // P
|
||||
0x14|SHIFT, // Q
|
||||
0x15|SHIFT, // R
|
||||
0x16|SHIFT, // S
|
||||
0x17|SHIFT, // T
|
||||
0x18|SHIFT, // U
|
||||
0x19|SHIFT, // V
|
||||
0x1a|SHIFT, // W
|
||||
0x1b|SHIFT, // X
|
||||
0x1c|SHIFT, // Y
|
||||
0x1d|SHIFT, // Z
|
||||
0x2f, // [
|
||||
0x31, // bslash
|
||||
0x30, // ]
|
||||
0x23|SHIFT, // ^
|
||||
0x2d|SHIFT, // _
|
||||
0x35, // `
|
||||
0x04, // a
|
||||
0x05, // b
|
||||
0x06, // c
|
||||
0x07, // d
|
||||
0x08, // e
|
||||
0x09, // f
|
||||
0x0a, // g
|
||||
0x0b, // h
|
||||
0x0c, // i
|
||||
0x0d, // j
|
||||
0x0e, // k
|
||||
0x0f, // l
|
||||
0x10, // m
|
||||
0x11, // n
|
||||
0x12, // o
|
||||
0x13, // p
|
||||
0x14, // q
|
||||
0x15, // r
|
||||
0x16, // s
|
||||
0x17, // t
|
||||
0x18, // u
|
||||
0x19, // v
|
||||
0x1a, // w
|
||||
0x1b, // x
|
||||
0x1c, // y
|
||||
0x1d, // z
|
||||
0x2f|SHIFT, //
|
||||
0x31|SHIFT, // |
|
||||
0x30|SHIFT, // }
|
||||
0x35|SHIFT, // ~
|
||||
0 // DEL
|
||||
};
|
||||
|
||||
#define KEY_LEFT_CTRL 0x80
|
||||
#define KEY_LEFT_SHIFT 0x81
|
||||
#define KEY_LEFT_ALT 0x82
|
||||
#define KEY_LEFT_GUI 0x83
|
||||
#define KEY_RIGHT_CTRL 0x84
|
||||
#define KEY_RIGHT_SHIFT 0x85
|
||||
#define KEY_RIGHT_ALT 0x86
|
||||
#define KEY_RIGHT_GUI 0x87
|
||||
|
||||
#define KEY_UP_ARROW 0xDA
|
||||
#define KEY_DOWN_ARROW 0xD9
|
||||
#define KEY_LEFT_ARROW 0xD8
|
||||
#define KEY_RIGHT_ARROW 0xD7
|
||||
#define KEY_BACKSPACE 0xB2
|
||||
#define KEY_TAB 0xB3
|
||||
#define KEY_RETURN 0xB0
|
||||
#define KEY_ESC 0xB1
|
||||
#define KEY_INSERT 0xD1
|
||||
#define KEY_DELETE 0xD4
|
||||
#define KEY_PAGE_UP 0xD3
|
||||
#define KEY_PAGE_DOWN 0xD6
|
||||
#define KEY_HOME 0xD2
|
||||
#define KEY_END 0xD5
|
||||
#define KEY_CAPS_LOCK 0xC1
|
||||
#define KEY_F1 0xC2
|
||||
#define KEY_F2 0xC3
|
||||
#define KEY_F3 0xC4
|
||||
#define KEY_F4 0xC5
|
||||
#define KEY_F5 0xC6
|
||||
#define KEY_F6 0xC7
|
||||
#define KEY_F7 0xC8
|
||||
#define KEY_F8 0xC9
|
||||
#define KEY_F9 0xCA
|
||||
#define KEY_F10 0xCB
|
||||
#define KEY_F11 0xCC
|
||||
#define KEY_F12 0xCD
|
||||
|
||||
typedef struct{
|
||||
uint8_t modifiers;
|
||||
uint8_t reserved;
|
||||
uint8_t keys[6];
|
||||
} KeyReport;
|
||||
|
||||
class HIDKeyboard : public Print{
|
||||
private:
|
||||
KeyReport _keyReport;
|
||||
void sendReport(KeyReport* keys);
|
||||
public:
|
||||
HIDKeyboard(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
virtual size_t write(uint8_t k);
|
||||
virtual size_t press(uint8_t k);
|
||||
virtual size_t release(uint8_t k);
|
||||
virtual void releaseAll(void);
|
||||
};
|
||||
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
// Joystick
|
||||
|
||||
class HIDJoystick{
|
||||
private:
|
||||
uint8_t joystick_Report[13] = {3,0,0,0,0,0x0F,0x20,0x80,0x00,0x02,0x08,0x20,0x80};
|
||||
void sendReport(void);
|
||||
public:
|
||||
HIDJoystick(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
void button(uint8_t button, bool val);
|
||||
void X(uint16_t val);
|
||||
void Y(uint16_t val);
|
||||
void position(uint16_t x, uint16_t y);
|
||||
void Z(uint16_t val);
|
||||
void Zrotate(uint16_t val);
|
||||
void sliderLeft(uint16_t val);
|
||||
void sliderRight(uint16_t val);
|
||||
void slider(uint16_t val);
|
||||
void hat(int16_t dir);
|
||||
};
|
||||
|
||||
extern HIDDevice HID;
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_KM)
|
||||
extern HIDMouse Mouse;
|
||||
extern HIDKeyboard Keyboard;
|
||||
#endif
|
||||
#if defined(USB_HID_KMJ) || defined(USB_HID_J)
|
||||
extern HIDJoystick Joystick;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,533 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2013 Magnus Lundin.
|
||||
* Copyright (c) 2013 Donald Delmar Davis, Suspect Devices.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* This is a munging of Tymm's arduino Midi Library into the Libusb class.
|
||||
* I am not sure this is the right way to go especially since its licensed differently.
|
||||
*
|
||||
* Midi.cpp: Code for MIDI processing library, Arduino version
|
||||
*
|
||||
* (c) 2003-2008 Tymm Twillman <tymm@booyaka.com>
|
||||
*
|
||||
* This file is part of Tymm's Arduino Midi Library.
|
||||
*
|
||||
* Tymm's Arduino Midi Library is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation, either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* Tymm's Arduino Midi Library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Tymm's Arduino Midi Library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief USB MIDI device with a class compatible with maplemidi
|
||||
*/
|
||||
|
||||
#ifdef USB_MIDI
|
||||
|
||||
#include <usb_midi.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/usb_midi_device.h>
|
||||
#include <libmaple/usb.h>
|
||||
|
||||
#include <wirish.h>
|
||||
|
||||
/*
|
||||
* USBMidi interface
|
||||
*/
|
||||
|
||||
#define USB_TIMEOUT 50
|
||||
|
||||
USBMidi::USBMidi(void) {
|
||||
|
||||
}
|
||||
|
||||
// Constructor -- set up defaults for variables, get ready for use (but don't
|
||||
// take over serial port yet)
|
||||
|
||||
void USBMidi::begin(unsigned int channel) {
|
||||
|
||||
usb_midi_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
|
||||
/* Not in proprietary stream */
|
||||
recvMode_ = 0;
|
||||
/* No bytes recevied */
|
||||
recvByteCount_ = 0;
|
||||
/* Not processing an event */
|
||||
recvEvent_ = 0;
|
||||
/* No arguments to the event we haven't received */
|
||||
recvArg0_ = 0;
|
||||
/* Not waiting for bytes to complete a message */
|
||||
recvBytesNeeded_ = 0;
|
||||
// There was no last event.
|
||||
lastStatusSent_ = false;
|
||||
// Don't send the extra bytes; just send deltas
|
||||
sendFullCommands_ = false;
|
||||
|
||||
}
|
||||
|
||||
void USBMidi::end(void) {
|
||||
|
||||
usb_midi_disable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
|
||||
|
||||
}
|
||||
|
||||
void USBMidi::writePacket(uint32 p) {
|
||||
this->writePackets(&p, 1);
|
||||
}
|
||||
|
||||
void USBMidi::writePackets(const void *buf, uint32 len) {
|
||||
if (!this->isConnected() || !buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 txed = 0;
|
||||
uint32 old_txed = 0;
|
||||
uint32 start = millis();
|
||||
|
||||
uint32 sent = 0;
|
||||
|
||||
while (txed < len && (millis() - start < USB_TIMEOUT)) {
|
||||
sent = usb_midi_tx((const uint32*)buf + txed, len - txed);
|
||||
txed += sent;
|
||||
if (old_txed != txed) {
|
||||
start = millis();
|
||||
}
|
||||
old_txed = txed;
|
||||
}
|
||||
|
||||
|
||||
if (sent == USB_MIDI_TX_EPSIZE) {
|
||||
while (usb_midi_is_transmitting() != 0) {
|
||||
}
|
||||
/* flush out to avoid having the pc wait for more data */
|
||||
usb_midi_tx(NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 USBMidi::available(void) {
|
||||
return usb_midi_data_available();
|
||||
}
|
||||
|
||||
uint32 USBMidi::readPackets(void *buf, uint32 len) {
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 rxed = 0;
|
||||
while (rxed < len) {
|
||||
rxed += usb_midi_rx((uint32*)buf + rxed, len - rxed);
|
||||
}
|
||||
|
||||
return rxed;
|
||||
}
|
||||
|
||||
/* Blocks forever until 1 byte is received */
|
||||
uint32 USBMidi::readPacket(void) {
|
||||
uint32 p;
|
||||
this->readPackets(&p, 1);
|
||||
return p;
|
||||
}
|
||||
|
||||
uint8 USBMidi::pending(void) {
|
||||
return usb_midi_get_pending();
|
||||
}
|
||||
|
||||
uint8 USBMidi::isConnected(void) {
|
||||
return usb_is_connected(USBLIB) && usb_is_configured(USBLIB);
|
||||
}
|
||||
|
||||
|
||||
USBMidi MidiUSB;
|
||||
|
||||
|
||||
|
||||
// This is used for tracking when we're processing a proprietary stream of data
|
||||
// The assigned value is arbitrary; just for internal use.
|
||||
static const int MODE_PROPRIETARY = 0xff;
|
||||
|
||||
|
||||
// These are midi status message types are defined in MidiSpec.h
|
||||
|
||||
union EVENT_t {
|
||||
uint32 i;
|
||||
uint8 b[4];
|
||||
MIDI_EVENT_PACKET_t p;
|
||||
};
|
||||
|
||||
// Handle decoding incoming MIDI traffic a byte at a time -- remembers
|
||||
// what it needs to from one call to the next.
|
||||
//
|
||||
// This is a private function & not meant to be called from outside this class.
|
||||
// It's used whenever data is available from the serial port.
|
||||
//
|
||||
void USBMidi::dispatchPacket(uint32 p)
|
||||
{
|
||||
union EVENT_t e;
|
||||
|
||||
e.i=p;
|
||||
// !!!!!!!!!!!!!!!! Add a sysex handler FIX THIS VERY VERY SHORTLY !!!!!!!!!!!!!!
|
||||
if (recvMode_ & MODE_PROPRIETARY
|
||||
&& CIN_IS_SYSEX(e.p.cin))
|
||||
{
|
||||
/* If sysex handling compiled in, just pass all data received
|
||||
* to the sysex handler
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_MIDI_PROPRIETARY
|
||||
// handleSysex(p);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.p.cin) {
|
||||
case CIN_3BYTE_SYS_COMMON:
|
||||
if (e.p.midi0 == MIDIv1_SONG_POSITION_PTR) {
|
||||
handleSongPosition(((uint16)e.p.midi2)<<7|((uint16)e.p.midi1));
|
||||
}
|
||||
break;
|
||||
|
||||
case CIN_2BYTE_SYS_COMMON:
|
||||
switch (e.p.midi0) {
|
||||
case MIDIv1_SONG_SELECT:
|
||||
handleSongSelect(e.p.midi1);
|
||||
break;
|
||||
case MIDIv1_MTC_QUARTER_FRAME:
|
||||
// reference library doesnt handle quarter frame.
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CIN_NOTE_OFF:
|
||||
handleNoteOff(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
|
||||
break;
|
||||
case CIN_NOTE_ON:
|
||||
handleNoteOn(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
|
||||
break;
|
||||
case CIN_AFTER_TOUCH:
|
||||
handleVelocityChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
|
||||
break;
|
||||
case CIN_CONTROL_CHANGE:
|
||||
handleControlChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1, e.p.midi2);
|
||||
break;
|
||||
case CIN_PROGRAM_CHANGE:
|
||||
handleProgramChange(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1);
|
||||
break;
|
||||
case CIN_CHANNEL_PRESSURE:
|
||||
handleAfterTouch(MIDIv1_VOICE_CHANNEL(e.p.midi0), e.p.midi1);
|
||||
break;
|
||||
|
||||
case CIN_PITCH_WHEEL:
|
||||
handlePitchChange(((uint16)e.p.midi2)<<7|((uint16)e.p.midi1));
|
||||
break;
|
||||
case CIN_1BYTE:
|
||||
switch (e.p.midi0) {
|
||||
case MIDIv1_CLOCK:
|
||||
handleSync();
|
||||
break;
|
||||
case MIDIv1_TICK:
|
||||
break;
|
||||
case MIDIv1_START:
|
||||
handleStart();
|
||||
break;
|
||||
case MIDIv1_CONTINUE:
|
||||
handleContinue();
|
||||
break;
|
||||
case MIDIv1_STOP:
|
||||
handleStop();
|
||||
break;
|
||||
case MIDIv1_ACTIVE_SENSE:
|
||||
handleActiveSense();
|
||||
break;
|
||||
case MIDIv1_RESET:
|
||||
handleReset();
|
||||
break;
|
||||
case MIDIv1_TUNE_REQUEST:
|
||||
handleTuneRequest();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Try to read data at serial port & pass anything read to processing function
|
||||
void USBMidi::poll(void)
|
||||
{ while(available()) {
|
||||
dispatchPacket(readPacket());
|
||||
}
|
||||
}
|
||||
|
||||
static union EVENT_t outPacket; // since we only use one at a time no point in reallocating it
|
||||
|
||||
// Send Midi NOTE OFF message to a given channel, with note 0-127 and velocity 0-127
|
||||
void USBMidi::sendNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_NOTE_OFF;
|
||||
outPacket.p.midi0=MIDIv1_NOTE_OFF|(channel & 0x0f);
|
||||
outPacket.p.midi1=note;
|
||||
outPacket.p.midi2=velocity;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Send Midi NOTE ON message to a given channel, with note 0-127 and velocity 0-127
|
||||
void USBMidi::sendNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_NOTE_ON;
|
||||
outPacket.p.midi0=MIDIv1_NOTE_ON|(channel & 0x0f);
|
||||
outPacket.p.midi1=note;
|
||||
outPacket.p.midi2=velocity;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
// Send a Midi VELOCITY CHANGE message to a given channel, with given note 0-127,
|
||||
// and new velocity 0-127
|
||||
// Note velocity change == polyphonic aftertouch.
|
||||
// Note aftertouch == channel pressure.
|
||||
void USBMidi::sendVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_AFTER_TOUCH;
|
||||
outPacket.p.midi0=MIDIv1_AFTER_TOUCH |(channel & 0x0f);
|
||||
outPacket.p.midi1=note;
|
||||
outPacket.p.midi2=velocity;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Send a Midi CC message to a given channel, as a given controller 0-127, with given
|
||||
// value 0-127
|
||||
void USBMidi::sendControlChange(unsigned int channel, unsigned int controller, unsigned int value)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_CONTROL_CHANGE;
|
||||
outPacket.p.midi0=MIDIv1_CONTROL_CHANGE |(channel & 0x0f);
|
||||
outPacket.p.midi1=controller;
|
||||
outPacket.p.midi2=value;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
// Send a Midi PROGRAM CHANGE message to given channel, with program ID 0-127
|
||||
void USBMidi::sendProgramChange(unsigned int channel, unsigned int program)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_PROGRAM_CHANGE;
|
||||
outPacket.p.midi0=MIDIv1_PROGRAM_CHANGE |(channel & 0x0f);
|
||||
outPacket.p.midi1=program;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
// Send a Midi AFTER TOUCH message to given channel, with velocity 0-127
|
||||
void USBMidi::sendAfterTouch(unsigned int channel, unsigned int velocity)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_CHANNEL_PRESSURE;
|
||||
outPacket.p.midi0=MIDIv1_CHANNEL_PRESSURE |(channel & 0x0f);
|
||||
outPacket.p.midi1=velocity;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
// Send a Midi PITCH CHANGE message, with a 14-bit pitch (always for all channels)
|
||||
void USBMidi::sendPitchChange(unsigned int pitch)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_PITCH_WHEEL;
|
||||
outPacket.p.midi0=MIDIv1_PITCH_WHEEL;
|
||||
outPacket.p.midi1= (uint8) pitch & 0x07F;
|
||||
outPacket.p.midi2= (uint8) (pitch<<7) & 0x7f;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
// Send a Midi SONG POSITION message, with a 14-bit position (always for all channels)
|
||||
void USBMidi::sendSongPosition(unsigned int position)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_3BYTE_SYS_COMMON;
|
||||
outPacket.p.midi0=MIDIv1_SONG_POSITION_PTR;
|
||||
outPacket.p.midi1= (uint8) position & 0x07F;
|
||||
outPacket.p.midi2= (uint8) (position<<7) & 0x7f;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
// Send a Midi SONG SELECT message, with a song ID of 0-127 (always for all channels)
|
||||
void USBMidi::sendSongSelect(unsigned int song)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_2BYTE_SYS_COMMON;
|
||||
outPacket.p.midi0=MIDIv1_SONG_SELECT;
|
||||
outPacket.p.midi1= (uint8) song & 0x07F;
|
||||
writePacket(outPacket.i);
|
||||
|
||||
}
|
||||
|
||||
// Send a Midi TUNE REQUEST message (TUNE REQUEST is always for all channels)
|
||||
void USBMidi::sendTuneRequest(void)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_1BYTE;
|
||||
outPacket.p.midi0=MIDIv1_TUNE_REQUEST;
|
||||
writePacket(outPacket.i);
|
||||
}
|
||||
|
||||
|
||||
// Send a Midi SYNC message (SYNC is always for all channels)
|
||||
void USBMidi::sendSync(void)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_1BYTE;
|
||||
outPacket.p.midi0=MIDIv1_CLOCK;
|
||||
writePacket(outPacket.i);
|
||||
}
|
||||
|
||||
// Send a Midi START message (START is always for all channels)
|
||||
void USBMidi::sendStart(void)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_1BYTE;
|
||||
outPacket.p.midi0=MIDIv1_START ;
|
||||
writePacket(outPacket.i);
|
||||
}
|
||||
|
||||
|
||||
// Send a Midi CONTINUE message (CONTINUE is always for all channels)
|
||||
void USBMidi::sendContinue(void)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_1BYTE;
|
||||
outPacket.p.midi0=MIDIv1_CONTINUE ;
|
||||
writePacket(outPacket.i);
|
||||
}
|
||||
|
||||
|
||||
// Send a Midi STOP message (STOP is always for all channels)
|
||||
void USBMidi::sendStop(void)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_1BYTE;
|
||||
outPacket.p.midi0=MIDIv1_STOP ;
|
||||
writePacket(outPacket.i);
|
||||
}
|
||||
|
||||
// Send a Midi ACTIVE SENSE message (ACTIVE SENSE is always for all channels)
|
||||
void USBMidi::sendActiveSense(void)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_1BYTE;
|
||||
outPacket.p.midi0=MIDIv1_ACTIVE_SENSE ;
|
||||
writePacket(outPacket.i);
|
||||
}
|
||||
|
||||
// Send a Midi RESET message (RESET is always for all channels)
|
||||
void USBMidi::sendReset(void)
|
||||
{
|
||||
outPacket.p.cable=DEFAULT_MIDI_CABLE;
|
||||
outPacket.p.cin=CIN_1BYTE;
|
||||
outPacket.p.midi0=MIDIv1_RESET ;
|
||||
writePacket(outPacket.i);
|
||||
}
|
||||
|
||||
|
||||
// Set (package-specific) parameters for the Midi instance
|
||||
void USBMidi::setParam(unsigned int param, unsigned int val)
|
||||
{
|
||||
if (param == PARAM_SEND_FULL_COMMANDS) {
|
||||
if (val) {
|
||||
sendFullCommands_ = true;
|
||||
} else {
|
||||
sendFullCommands_ = false;
|
||||
}
|
||||
} else if (param == PARAM_CHANNEL_IN) {
|
||||
channelIn_ = val;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get (package-specific) parameters for the Midi instance
|
||||
unsigned int USBMidi::getParam(unsigned int param)
|
||||
{
|
||||
if (param == PARAM_SEND_FULL_COMMANDS) {
|
||||
return sendFullCommands_;
|
||||
} else if (param == PARAM_CHANNEL_IN) {
|
||||
return channelIn_;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Placeholders. You should subclass the Midi base class and define these to have your
|
||||
// version called.
|
||||
/*
|
||||
void USBMidi::handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity) {
|
||||
digitalWrite(33,0);
|
||||
}
|
||||
|
||||
void USBMidi::handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity) {
|
||||
digitalWrite(33,1);
|
||||
}
|
||||
|
||||
void USBMidi::handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity) {}
|
||||
void USBMidi::handleControlChange(unsigned int channel, unsigned int controller, unsigned int value) {}
|
||||
void USBMidi::handleProgramChange(unsigned int channel, unsigned int program) {}
|
||||
void USBMidi::handleAfterTouch(unsigned int channel, unsigned int velocity) {}
|
||||
void USBMidi::handlePitchChange(unsigned int pitch) {}
|
||||
void USBMidi::handleSongPosition(unsigned int position) {}
|
||||
void USBMidi::handleSongSelect(unsigned int song) {}
|
||||
void USBMidi::handleTuneRequest(void) {}
|
||||
void USBMidi::handleSync(void) {}
|
||||
void USBMidi::handleStart(void) {}
|
||||
void USBMidi::handleContinue(void) {}
|
||||
void USBMidi::handleStop(void) {}
|
||||
void USBMidi::handleActiveSense(void) {}
|
||||
void USBMidi::handleReset(void) {}
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,222 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2013 Magnus Lundin.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Wirish USB MIDI port (MidiUSB).
|
||||
*/
|
||||
|
||||
#ifdef USB_MIDI
|
||||
|
||||
#ifndef _WIRISH_USB_MIDI_H_
|
||||
#define _WIRISH_USB_MIDI_H_
|
||||
|
||||
#include <Print.h>
|
||||
#include <boards.h>
|
||||
|
||||
/*
|
||||
* This is the Midi class. If you are just sending Midi data, you only need to make an
|
||||
* instance of the class, passing it your serial port -- in most cases it looks like
|
||||
*
|
||||
* USBMidi midi(channel);
|
||||
*
|
||||
* then you don't need to do anything else; you can start using it to send Midi messages,
|
||||
* e.g.
|
||||
*
|
||||
* midi.sendNoteOn(1, note, velocity);
|
||||
*
|
||||
* If you are using it to receive Midi data, it's a little more complex & you will need
|
||||
* to subclass the Midi class.
|
||||
*
|
||||
* For people not used to C++ this may look confusing, but it's actually pretty easy.
|
||||
* Note that you only need to write the functions for event types you want to handle.
|
||||
* They should match the names & prototypes of the functions in the class; look at
|
||||
* the functions in the Midi class below that have the keyword "virtual" to see which
|
||||
* ones you can use.
|
||||
*
|
||||
* Here's an example of one that takes NOTE ON, NOTE OFF, and CONTROL CHANGE:
|
||||
*
|
||||
* class MyMidi : public USBMidi {
|
||||
* public:
|
||||
*
|
||||
* // Need this to compile; it just hands things off to the Midi class.
|
||||
* MyMidi() : USBMidi(s) {}
|
||||
*
|
||||
* void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity)
|
||||
* {
|
||||
* if (note == 40) {digitalWrite(13, HIGH); }
|
||||
* }
|
||||
*
|
||||
* void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity)
|
||||
* {
|
||||
* if (note == 40) { digitalWrite(13, LOW); }
|
||||
* }
|
||||
*
|
||||
* void handleControlChange(unsigned int channel, unsigned int controller,
|
||||
* unsigned int value)
|
||||
* {
|
||||
* analogWrite(6, value * 2);
|
||||
* }
|
||||
*
|
||||
* Then you need to make an instance of this class:
|
||||
*
|
||||
* MyMidi midi();
|
||||
*
|
||||
* If receiving Midi data, you also need to call the poll function every time through
|
||||
* loop(); e.g.
|
||||
*
|
||||
* void loop() {
|
||||
* midi.poll();
|
||||
* }
|
||||
*
|
||||
* This causes the Midi class to read data from the serial port and process it.
|
||||
*/
|
||||
|
||||
class USBMidi {
|
||||
private:
|
||||
// The serial port used by this Midi instance (it takes complete control over the port)
|
||||
|
||||
/* Private Receive Parameters */
|
||||
|
||||
// The channel this Midi instance receives data for (0 means all channels)
|
||||
int channelIn_;
|
||||
|
||||
// These are for keeping track of partial Midi messages as bytes come in
|
||||
int recvMode_;
|
||||
int recvByteCount_;
|
||||
int recvEvent_;
|
||||
int recvArg0_;
|
||||
int recvBytesNeeded_;
|
||||
int lastStatusSent_;
|
||||
|
||||
/* Private Send Parameters */
|
||||
|
||||
// This controls whether every Midi message gets a command byte sent with it
|
||||
// (Midi can just send a single command byte and then stream events without
|
||||
// sending the command each time)
|
||||
bool sendFullCommands_;
|
||||
|
||||
/* Internal functions */
|
||||
|
||||
// Called whenever data is read from the serial port
|
||||
void dispatchPacket(uint32 packet);
|
||||
|
||||
// This doesn't work -- by making it private, we ensure nobody ever calls it
|
||||
//Midi();
|
||||
|
||||
public:
|
||||
// Set this parameter to anything other than 0 to cause every MIDI update to
|
||||
// include a copy of the current event (e.g. for every note off to include
|
||||
// the NOTE OFF event) -- by default, if an event is the same type of event as
|
||||
// the last one sent, the event byte isn't sent; just the new note/velocity
|
||||
static const unsigned int PARAM_SEND_FULL_COMMANDS = 0x1000;
|
||||
|
||||
// Use this parameter to update the channel the MIDI code is looking for messages
|
||||
// to. 0 means "all channels".
|
||||
static const unsigned int PARAM_CHANNEL_IN = 0x1001;
|
||||
|
||||
|
||||
// Constructor -- generally just use e.g. "Midi midi(Serial);"
|
||||
USBMidi();
|
||||
|
||||
// Call to start the serial port, at given baud. For many applications
|
||||
// the default parameters are just fine (which will cause messages for all
|
||||
// MIDI channels to be delivered)
|
||||
void begin(unsigned int channel = 0);
|
||||
//void begin();
|
||||
void end();
|
||||
|
||||
uint32 available(void);
|
||||
|
||||
uint32 readPackets(void *buf, uint32 len);
|
||||
uint32 readPacket(void);
|
||||
|
||||
void writePacket(uint32);
|
||||
// void write(const char *str);
|
||||
void writePackets(const void*, uint32);
|
||||
|
||||
uint8 isConnected();
|
||||
uint8 pending();
|
||||
|
||||
|
||||
// Changes the updateable parameters (params are Midi::PARAM_SEND_FULL_COMMANDS or
|
||||
// Midi::PARAM_CHANNEL_IN -- see above for what they mean)
|
||||
void setParam(unsigned int param, unsigned int val);
|
||||
|
||||
// Get current values for the user updateable parameters (params, etc same as above)
|
||||
unsigned int getParam(unsigned int param);
|
||||
|
||||
|
||||
// poll() should be called every time through loop() IF dealing with incoming MIDI
|
||||
// (if you're only SENDING MIDI events from the Arduino, you don't need to call
|
||||
// poll); it causes data to be read from the serial port and processed.
|
||||
void poll();
|
||||
|
||||
// Call these to send MIDI messages of the given types
|
||||
void sendNoteOff(unsigned int channel, unsigned int note, unsigned int velocity);
|
||||
void sendNoteOn(unsigned int channel, unsigned int note, unsigned int velocity);
|
||||
void sendVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity);
|
||||
void sendControlChange(unsigned int channel, unsigned int controller, unsigned int value);
|
||||
void sendProgramChange(unsigned int channel, unsigned int program);
|
||||
void sendAfterTouch(unsigned int channel, unsigned int velocity);
|
||||
void sendPitchChange(unsigned int pitch);
|
||||
void sendSongPosition(unsigned int position);
|
||||
void sendSongSelect(unsigned int song);
|
||||
void sendTuneRequest(void);
|
||||
void sendSync(void);
|
||||
void sendStart(void);
|
||||
void sendContinue(void);
|
||||
void sendStop(void);
|
||||
void sendActiveSense(void);
|
||||
void sendReset(void);
|
||||
|
||||
// Overload these in a subclass to get MIDI messages when they come in
|
||||
virtual void handleNoteOff(unsigned int channel, unsigned int note, unsigned int velocity);
|
||||
virtual void handleNoteOn(unsigned int channel, unsigned int note, unsigned int velocity);
|
||||
virtual void handleVelocityChange(unsigned int channel, unsigned int note, unsigned int velocity);
|
||||
virtual void handleControlChange(unsigned int channel, unsigned int controller, unsigned int value);
|
||||
virtual void handleProgramChange(unsigned int channel, unsigned int program);
|
||||
virtual void handleAfterTouch(unsigned int channel, unsigned int velocity);
|
||||
virtual void handlePitchChange(unsigned int pitch);
|
||||
virtual void handleSongPosition(unsigned int position);
|
||||
virtual void handleSongSelect(unsigned int song);
|
||||
virtual void handleTuneRequest(void);
|
||||
virtual void handleSync(void);
|
||||
virtual void handleStart(void);
|
||||
virtual void handleContinue(void);
|
||||
virtual void handleStop(void);
|
||||
virtual void handleActiveSense(void);
|
||||
virtual void handleReset(void);
|
||||
};
|
||||
|
||||
|
||||
extern USBMidi MidiUSB;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -27,6 +27,8 @@
|
|||
/**
|
||||
* @brief USB virtual serial terminal
|
||||
*/
|
||||
|
||||
#ifdef USB_SERIAL
|
||||
|
||||
#include "usb_serial.h"
|
||||
|
||||
|
@ -216,7 +218,7 @@ uint8 USBSerial::getRTS(void) {
|
|||
}
|
||||
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
USBSerial Serial;
|
||||
#endif
|
||||
#endif
|
||||
|
@ -244,7 +246,7 @@ static void ifaceSetupHook(unsigned hook, void *requestvp) {
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
// We need to see a negative edge on DTR before we start looking
|
||||
// for the in-band magic reset byte sequence.
|
||||
uint8 dtr = usb_cdcacm_get_dtr();
|
||||
|
@ -280,7 +282,7 @@ static void ifaceSetupHook(unsigned hook, void *requestvp) {
|
|||
}
|
||||
|
||||
#define RESET_DELAY 100000
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
static void wait_reset(void) {
|
||||
delay_us(RESET_DELAY);
|
||||
nvic_sys_reset();
|
||||
|
@ -298,7 +300,7 @@ static void rxHook(unsigned hook, void *ignored) {
|
|||
|
||||
if (usb_cdcacm_data_available() >= 4) {
|
||||
// The magic reset sequence is "1EAF".
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
static const uint8 magic[4] = {'1', 'E', 'A', 'F'};
|
||||
#else
|
||||
#if defined(BOOTLOADER_robotis)
|
||||
|
@ -319,7 +321,7 @@ static void rxHook(unsigned hook, void *ignored) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
// Got the magic sequence -> reset, presumably into the bootloader.
|
||||
// Return address is wait_reset, but we must set the thumb bit.
|
||||
uintptr_t target = (uintptr_t)wait_reset | 0x1;
|
||||
|
@ -357,3 +359,5 @@ static void rxHook(unsigned hook, void *ignored) {
|
|||
}
|
||||
|
||||
#endif // BOARD_HAVE_SERIALUSB
|
||||
|
||||
#endif //USB_SERIAL
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
* @brief Wirish USB virtual serial port (SerialUSB).
|
||||
*/
|
||||
|
||||
#ifdef USB_SERIAL
|
||||
|
||||
#ifndef _WIRISH_USB_SERIAL_H_
|
||||
#define _WIRISH_USB_SERIAL_H_
|
||||
|
||||
|
@ -73,9 +75,11 @@ public:
|
|||
uint8 pending();
|
||||
};
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
extern USBSerial Serial;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -69,6 +69,8 @@
|
|||
#include <HardwareSerial.h>
|
||||
#include <HardwareTimer.h>
|
||||
#include <usb_serial.h>
|
||||
#include <usb_hid_device.h>
|
||||
#include <usb_midi.h>
|
||||
#include <wirish_types.h>
|
||||
|
||||
#include <libmaple/libmaple.h>
|
||||
|
|
|
@ -47,6 +47,8 @@ build.upload_flags=
|
|||
build.extra_flags= {build.upload_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags}
|
||||
|
||||
|
||||
# added this line so the compiler receives a valid argument for usb type even if the selected board has no usb type menu
|
||||
build.usbtype=NO_USB
|
||||
|
||||
# These can be overridden in platform.local.txt
|
||||
compiler.c.extra_flags=
|
||||
|
@ -75,10 +77,10 @@ compiler.libs.c.flags="-I{build.system.path}/libmaple" "-I{build.system.path}/li
|
|||
# ---------------------
|
||||
|
||||
## Compile c files
|
||||
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}"
|
||||
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -D{build.usbtype} {compiler.c.extra_flags} {build.extra_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile c++ files
|
||||
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}"
|
||||
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -D{build.usbtype} {compiler.cpp.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile S files
|
||||
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.cpu_flags} {build.hs_flag} {build.common_flags} {compiler.libs.c.flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
|
|
@ -124,7 +124,7 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
|
|||
* Maps to which hardware serial port on the microprocessor
|
||||
*/
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
#include <boards.h>
|
||||
#include <usb_serial.h>
|
||||
#include <usb_hid_device.h>
|
||||
#include <usb_midi.h>
|
||||
|
||||
// Generic GD32 boards seem to have a 12Mhz crystal rather than the 8Mhz common on STM32 boards, hence the PLL multiplier settings are different.
|
||||
// Additionally the GD32 has a 4 USB PLL divider settings, rather than the 2 settings in the STM32, which allow it to operate on frequencies of 48,72,96 and 120Mhz and still have USB functioning
|
||||
|
@ -89,7 +91,6 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
|
||||
#ifdef GENERIC_BOOTLOADER
|
||||
//Reset the USB interface on generic boards - developed by Victor PV
|
||||
|
@ -99,7 +100,16 @@ namespace wirish {
|
|||
for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed, and USB pins will get configured in Serial.begin
|
||||
gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
#endif
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
|
|||
* Maps to which hardware serial port on the microprocessor
|
||||
*/
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
|
||||
|
||||
#ifdef GENERIC_BOOTLOADER
|
||||
//Reset the USB interface on generic boards - developed by Victor PV
|
||||
|
@ -90,7 +90,16 @@ namespace wirish {
|
|||
for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed, and USB pins will get configured in Serial.begin
|
||||
gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
#endif
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
|
|||
};
|
||||
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
DEFINE_HWSERIAL(Serial3, 3);
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
|
||||
|
||||
#ifdef GENERIC_BOOTLOADER
|
||||
//Reset the USB interface on generic boards - developed by Victor PV
|
||||
|
@ -91,8 +91,18 @@ namespace wirish {
|
|||
gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
#endif
|
||||
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__weak void series_init(void) {
|
||||
|
|
|
@ -139,7 +139,7 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
|
|||
* Maps to which hardware serial port on the microprocessor
|
||||
*/
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
|
||||
|
||||
#ifdef GENERIC_BOOTLOADER
|
||||
//Reset the USB interface on generic boards - developed by Victor PV
|
||||
|
@ -89,9 +89,18 @@ namespace wirish {
|
|||
|
||||
for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed, and USB pins will get configured in Serial.begin
|
||||
gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
#endif
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__weak void series_init(void) {
|
||||
|
|
|
@ -109,7 +109,7 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
|
|||
* Maps to which hardware serial port on the microprocessor
|
||||
*/
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
|
|
|
@ -80,7 +80,6 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
|
||||
#ifdef GENERIC_BOOTLOADER
|
||||
//Reset the USB interface on generic boards - developed by Victor PV
|
||||
|
@ -90,7 +89,16 @@ namespace wirish {
|
|||
for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed, and USB pins will get configured in Serial.begin
|
||||
gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
#endif
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -184,7 +184,7 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
|
|||
};
|
||||
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
DEFINE_HWSERIAL(Serial3, 3);
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
|
||||
|
||||
|
||||
#ifdef GENERIC_BOOTLOADER
|
||||
|
@ -91,8 +91,18 @@ namespace wirish {
|
|||
for(volatile unsigned int i=0;i<512;i++);// Only small delay seems to be needed, and USB pins will get configured in Serial.begin
|
||||
gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
#endif
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__weak void series_init(void) {
|
||||
|
|
|
@ -219,7 +219,7 @@ extern const uint8 boardUsedPins[BOARD_NR_USED_PINS] __FLASH__ = {
|
|||
};
|
||||
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
DEFINE_HWSERIAL(Serial3, 3);
|
||||
|
|
|
@ -93,8 +93,18 @@ namespace wirish {
|
|||
gpio_set_mode(PIN_MAP[PA12].gpio_device, PIN_MAP[PA12].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
#endif
|
||||
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__weak void series_init(void) {
|
||||
|
|
|
@ -80,9 +80,18 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__weak void series_init(void) {
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
#include <boards.h>
|
||||
#include <usb_serial.h>
|
||||
#include <usb_hid_device.h>
|
||||
#include <usb_midi.h>
|
||||
|
||||
// Allow boards to provide a PLL multiplier. This is useful for
|
||||
// e.g. STM32F100 value line MCUs, which use slower multipliers.
|
||||
|
@ -80,9 +82,16 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
// SerialUSB.begin();
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -80,9 +80,18 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__weak void series_init(void) {
|
||||
|
|
|
@ -248,7 +248,7 @@ MOSI alternate functions on the GPIO ports.
|
|||
* Maps to which hardware serial port on the microprocessor
|
||||
*/
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
DEFINE_HWSERIAL(Serial3, 3);
|
||||
|
|
|
@ -88,9 +88,18 @@ namespace wirish {
|
|||
}
|
||||
|
||||
__weak void board_setup_usb(void) {
|
||||
#ifdef SERIAL_USB
|
||||
#ifdef USB_HARDWARE
|
||||
#ifdef USB_SERIAL
|
||||
Serial.begin();// Roger Clark. Changed SerialUSB to Serial for Arduino sketch compatibility
|
||||
#endif
|
||||
#if defined(USB_HARDWARE) && (defined(USB_HID_KMJ) || defined(USB_HID_KM) || defined(USB_HID_J))
|
||||
HID.begin();
|
||||
#endif
|
||||
#ifdef USB_MIDI
|
||||
MidiUSB.begin();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
__weak void series_init(void) {
|
||||
|
|
Loading…
Reference in New Issue