RuudNL
- 10th November 2017, 11:53
Hello,
I would like to try to do this, but I don't know if this is possible...
I would like to behave a PIC based circuit as an (USB) MIDI (receiver) interface.
In the past I have managed to create circuits with a PIC that behaved like a HID device, that didn't need any drivers.
The point of this is, that most software applications need to 'see' a MIDI port, in order to send information to that port.
I suppose I have to change some values in the USB descriptors, but I have no idea where to start.
Most commercial USB to MIDI interfaces don't need a driver, so I suppose this must be possible.
Maybe somebody has experimented with this, and is willing to share some code with me?
Many thanks in advance!
(Just to be clear: I only need communication FROM the PC to the PIC circuit.)
DaveC3
- 11th November 2017, 13:14
I did a USB Midi back in 2009, Here is the code. It has been too long ago for me to remember the specifics. Maybe it will help you get started.
' ************************************************** **********
' * Auto generated EasyHID file. PBP 2.60 and above *
' ************************************************** **********
' include the HID descriptor
INCLUDE "DESCUSB_MIDI.bas"
DEFINE WRITE_INT 1
Define LOADER_USED 1
DEFINE RESET_ORG 800h ' For Microchip USB Bootloader
DEFINE INTERRUPT_ORG 808h ' For Microchip USB Bootloader
DEFINE OSC 48 ' tell program we are using a 20mhz oscillator
DEFINE HSER_RCSTA 90h ' enable serial receive
DEFINE HSER_TXSTA 24h ' enable serial transmit
DEFINE HSER_BAUD 31250 ' set baud rate for MIDI transmission
DEFINE ADC_BITS 8 ' set the number of bits in the sample
DEFINE ADC_SAMPLEUS 50 ' set the sample time
I2C_Data var PORTD.1
I2C_CLK var PORTD.0
USBBufferSizeMax CON 16 ' maximum buffer size
USBBufferSizeTX CON 16 ' input
USBBufferSizeRX CON 16 ' output
' the USB buffer...
USBBuffer VAR BYTE[USBBufferSizeMax]
USBBufferCount VAR BYTE
Portb = %11111111
ADCON1 = %00000101 ' AN0 - AN9 analog
TRISA = %00101111 ' Set PORTA to inputs
TRISB = %00001100
TRISC = %00000000
TRISD = %11110000
TRISE = %00000111 ' Porte 1,2 ,3 inputs,
CMCON = 7 'PortA Digital
INTCON2.7 = 0 'weak pullups portB = 0, disable = 1
PORTE.7 = 1 ' weak pullups portd enabled
'================================================= =====================================
' Port A Registers (8 Bit Mode)
IODIRA con $00 ' Direction Bit Control Reg
IOBITSA con %11111111 ' Direction Bit Settings Reg (0 = output, 1 = input)
IPOLA con $01 ' Interrupt Polarity Control Reg
GPINTENA con $02 'Interrupt Enable Reg
DEFVALA con $03
INTCONA con $04
IOCONA con $05 ' I/O Configuration Reg
IOCONSETA con %10111000 ' IOCON register setting
GPPUA con $06 ' Pull-Up Control Reg
INTFA con $07 ' Interrupt Flag Register
INTCAPA con $08
GPIOA con $09 ' General Purpose I/O
IOLATA con $0A ' Output Latch Reg
'Port B Registers (8 Bit Mode)
IODIRB con $10 ' Port B Direction Bit Control Address
IOBITSB con %00000000 ' Port B Direction Bit Settings (0 = output, 1 = input)
IPOLB con $11 ' Interrupt Polarity Control
GPINTENB con $12 ' Interrupt Enable Reg
DEFVALB con $13
INTCONB con $14
IOCONB con $15 ' I/O Configuration Reg
IOCONSETB con %10111000 ' IOCON register setting
GPPUB con $16 ' Pull-Up Control Reg
INTFB con $17 ' Interrupt Flag Register
INTPOLB con $18
GPIOB con $19 ' General Purpose I/O Reg
IOLATB con $1A ' Output Latch Reg
'================================================= =======================================
' Port A Reguisters (16 Bit Mode)
IODIRA16 con $00
IODIRB16 con $01
IOCONA16 con $0A
IOCONB16 con $0B
GPIOA16 con $12
GPIOB16 con $13
OLATA16 con $14
OLATB16 con $15
IO_EXP0WR con $40 ' MCP23017 Write
IO_EXP0RD con $40 ' MCP23017 Read
IO_DAT var byte ' MCP23017 Data read
IO_DAT_OLD var byte
IO_DATA var byte ' MCP23017 Data read
IO_DAT_OLDA var byte
IO_DATB var byte ' MCP23017 Data read
IO_DAT_OLDB var byte
Out_Dat var byte
Enc1 var byte
Enc1_Old var byte
Enc1_Mask con %00000011
Enc2 var byte
Enc2_Old var byte
Enc2_Mask con %00001100
Enc3 var byte
Enc3_Old var byte
Enc3_Mask con %00110000
Enc4 var byte
Enc4_Old var byte
Enc4_Mask con %11000000
EncTemp var byte
Enc1_val var byte
Enc2_val var byte
Enc3_val var byte
Enc4_val var byte
CPS1 var byte
CPS2 var byte
CPS3 var byte
CPS4 var byte
CPS5 var byte
CPS6 var byte
'================================================= ============================
' The control code assignments for the 6 switches
'================================================= ============================
CPS1_CC VAR BYTE ' con 30
CPS2_CC VAR BYTE ' con 31
CPS3_CC VAR BYTE ' con 66
CPS4_CC VAR BYTE ' con 41
CPS5_CC VAR BYTE ' con 42
CPS6_CC VAR BYTE ' con 43
'================================================= ============================
' The control code assignments for the 4 encoders
'================================================= ============================
CPENC1_CC VAR BYTE ' con 84
CPENC2_CC VAR BYTE ' con 76
CPENC3_CC VAR BYTE ' con 68
CPENC4_CC VAR BYTE ' con 80
' Flags
SW1_Flag var bit
CPS1_Flag var bit
CPS2_Flag var bit
CPS3_Flag var bit
CPS4_Flag var bit
CPS5_Flag var bit
CPS6_Flag var bit
sl_ADC var word[9]
sl_Old var byte[9]
Channel var byte
Control var byte
Value var byte
j var byte
C0 Var word
C1 Var word
EXP var word
EXP1 var byte
EXPOld var byte
EXP_CC var byte
volout Var byte
Channel = 176
Control = 0
Upper var byte
Lower VAR BYTE
Bass VAR BYTE
SwitchBank var byte
SwitchBank1 var byte
SwitchBankOld var byte
RSS var byte
RSSOld var byte
CounterA var Byte
RawData var Byte [16]
k var byte
i var byte
LED1 var PORTC.2
upper = 12
lower = 0 '9
bass = 0 '
PORTD = $FF
FOR j = 0 TO 15
READ j, USBBuffer[j]
NEXT j
CPS1_CC = USBBuffer[0]
CPS2_CC = USBBuffer[1]
CPS3_CC = USBBuffer[2]
CPS4_CC = USBBuffer[3]
CPS5_CC = USBBuffer[4]
CPS6_CC = USBBuffer[5]
CPENC1_CC = USBBuffer[6]
CPENC2_CC = USBBuffer[7]
CPENC3_CC = USBBuffer[8]
CPENC4_CC = USBBuffer[9]
PAUSE 500
gosub InitMPC23017
goto MainLoop 'jump over subs to main loop
' ************************************************** **********
' Start of Subs
' ************************************************** **********
' * receive data from the USB bus *
' ************************************************** **********
DoUSBIn:
USBBufferCount = USBBufferSizeRX ' RX buffer size
USBIN 1, USBBuffer, USBBufferCount, DoUSBIn ' read data, if available
RETURN
' ************************************************** **********
' * wait for USB interface to attach *
' ************************************************** **********
DoUSBOut:
USBBufferCount = USBBufferSizeTX ' TX buffer size
USBOUT 1, USBBuffer, USBBufferCount, DoUSBOut ' if bus available, transmit data
RETURN
' ************************************************** **********
' * USB Attach detach *
' ************************************************** **********
Program:
led1 = 1
INCLUDE "USB_ASM_Service.pbp"
PAUSE 500
GOSUB DoUSBIn
FOR k = 0 TO 15
READ k , USBBuffer[k]
NEXT k
PAUSE 250
GOSUB DoUSBOut
PAUSE 250
GOSUB DoUSBIn
FOR k = 0 TO 15
WRITE k, USBBuffer[k]
NEXT k
CPS1_CC = USBBuffer[0]
CPS2_CC = USBBuffer[1]
CPS3_CC = USBBuffer[2]
CPS4_CC = USBBuffer[3]
CPS5_CC = USBBuffer[4]
CPS6_CC = USBBuffer[5]
CPENC1_CC = USBBuffer[6]
CPENC2_CC = USBBuffer[7]
CPENC3_CC = USBBuffer[8]
CPENC4_CC = USBBuffer[9]
PAUSE 1000
GOSUB DoUSBOut
PAUSE 1000
UCON.3 = 0
for i = 0 to 20
toggle led1
pause 200
next i
led1 = 0
RETURN
'************************************************* ******************************
'************************************************* *****************************
InitMPC23017:
Pause 100
'=================== PORTA ================================================== ==
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IOCONA,IOCONSETA] 'IOCON register setting
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IODIRA,$FF] 'PortA inputs
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IOLATA,$FF] 'PortA = 0
'i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IPOLA,0] 'Input polarity 1= opposite 0 = normal
'i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[DEFVALA,0] 'Default value register
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[GPPUA,$FF] 'pull-ups enabled 1 = enable 0 = disable
'i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[INTCONA,0] 'INTERRUPT-ON-CHANGE CONTROL REGISTER
'i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[GPINTENA,$FF] 'interupt on change 1= enable 0 = disable
'==================== PORTB ================================================== ==
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IOCONB,IOCONSETB]
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IODIRB,$FF] 'PortB inputs
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IOLATB,$FF]
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[GPPUB,$FF] 'pull-ups enabled 1 = enable 0 = disable
'i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IPOLB,0]
'i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[DEFVALB,0]
'i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[INTCONB,0]
'i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[GPINTENB,0]
return
ReInitPortA:
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IOCONA,IOCONSETA]
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[IODIRA,$FF]
i2cwrite I2C_Data,I2C_CLK,IO_EXP0WR,[GPPUA,$FF] 'pull-ups enabled
return
'************************************************* *****************************
Scale:
select case sl_ADC[j]
case 126
volout = 0
case 114
volout = 15
case 110, 112
volout = 30
case 104, 106
volout = 45
case 98
volout = 60
case 86
volout = 75
case 62
volout = 90
case 38
volout = 105
case 0
volout = 125
case else
end select
Control = j + Upper + lower + bass ' drawbars are CC 12-20
HSEROUT [channel,control,volout] ' send data out serial port as midi information
sl_old[j] = sl_ADC[j]
return
'************************************************* ******************************
SortArray: 'Soer data small to large
CounterA=0
SortLoop:
If RawData(CounterA+1) < RawData(CounterA) then
RawData(CounterA) = RawData(CounterA) ^ RawData(CounterA+1)
RawData(CounterA+1+0) = RawData(CounterA) ^ RawData(CounterA+1)
RawData(CounterA) = RawData(CounterA) ^ RawData(CounterA+1)
If CounterA > 0 then CounterA=CounterA-2
endif
CounterA=CounterA+1
If CounterA < 15 then goto SortLoop
' Take the middle eight and average
' C1 = (RAWDATA[4] + RAWDATA[5] + RAWDATA[6] + RAWDATA[7] + RAWDATA[8] + RAWDATA[9] + RAWDATA[10] + RAWDATA[11]) / 8
c1 = 0
for i = 6 to 9
c1 = c1 + rawdata[i]
next i
c1 = c1 / 4
Return
'************************************************* *****************************
'
' Main Loop
'
'************************************************* *****************************
MainLoop:
'SLIDERS 1-9
for j = 0 to 8
'Take 16 samoles
for k = 0 to 15
ADCIN j,c0 ' read Volume pot and place value in C0
rawdata[k] = c0
next k
gosub sortarray
sl_ADC[j] = (C1 >>2)*2 ' convert reading to a midi value from 1-127
If sl_ADC[j] <> sl_old[j] Then ' check to see if the value has changed
gosub scale
Endif
next j
' EXPRESSION Pedal
ADCIN 9,exp
exp1 = exp >> 1
if expold <> exp1 then
HSEROUT [177,11,exp1]
expold = exp1
endif
switchbank = PORTD & %11110000
if switchbank <> switchbankold then
if switchbank.7 = 0 then '
if sw1_flag = 0 then
sw1_flag = 1: led1 = 1: exp_cc = 127
elseif sw1_flag = 1 then
sw1_flag = 0: led1 = 0: exp_cc = 0
endif
HSEROUT [177,1,EXP_CC]
endif
'Slider bank selection
if switchbank.4 = 0 then
Upper = 12: lower = 0: bass = 0 'Select upper bank
elseif switchbank.5 = 0 then
Upper = 12: lower = 9: bass = 0 'select lower bank
elseif switchbank.6 = 0 then
Upper = 12: lower = 9: bass = 12 'select bass bank
endif
switchbankold = switchbank
endif
'================ MCP23017 Decoder ============================================
i2cread I2C_Data,I2C_CLK,IO_EXP0rd,gpioa,[IO_data] 'read 23017
if io_data != io_dat_olda then
'-----------------------------------------------------------------------------
if io_data.0 = 0 and io_data.5 = 0 then
gosub program
endif
'-----------------------------------------------------------------------------
if io_data.0 = 0 then
if cps1_flag = 0 then
cps1_flag = 1: CPS1 = 127
elseif cps1_flag = 1 then
cps1_flag = 0: CPS1 = 0
endif
HSEROUT [177,cps1_cc, CPS1] '"SW1"
endif
'-----------------------------------------------------------------------------
if io_data.1 = 0 then
if cps2_flag = 0 then
cps2_flag = 1: CPS2 = 127
elseif cps2_flag = 1 then
cps2_flag = 0: CPS2 = 0
endif
HSEROUT [177,cps2_cc, cps2] '"SW2"
endif
'-----------------------------------------------------------------------------
if io_data.2 = 0 then
if cps3_flag = 0 then
cps3_flag = 1: CPS3 = 127
elseif cps3_flag = 1 then
cps3_flag = 0: CPS3 = 0
endif
HSEROUT [177,cps3_cc, cps3] '"SW3"
endif
'-----------------------------------------------------------------------------
if io_data.3 = 0 then
if cps4_flag = 0 then
cps4_flag = 1: CPS4 = 127
elseif cps4_flag = 1 then
cps4_flag = 0: CPS4 = 0
endif
HSEROUT [177,cps4_cc, cps4] '"SW4"
endif
'-----------------------------------------------------------------------------
if io_data.4 = 0 then
if cps5_flag = 0 then
cps5_flag = 1: CPS5 = 127
elseif cps5_flag = 1 then
cps5_flag = 0: CPS5 = 0
endif
HSEROUT [177,cps5_cc, cps5] ' "SW5"
endif
'-----------------------------------------------------------------------------
if io_data.5 = 0 then
if cps6_flag = 0 then
cps6_flag = 1: CPS6 = 127
elseif cps6_flag = 1 then
cps6_flag = 0: CPS6 = 0
endif
HSEROUT [177,cps6_cc, cps6] ' "SW6"
endif
pause 250
endif
'-----------------------------------------------------------------------------
i2cread I2C_Data,I2C_CLK,IO_EXP0rd,gpiob,[IO_datb] 'read 23017
if io_datb != io_dat_oldb then
enc1 = io_datb & enc1_mask
if enc1_old = enc1 then goto Encoder2
enctemp = enc1.bit1 ^ enc1_old.bit0
if enctemp = 1 then goto Inc1
Enc1_val = Enc1_val - 1
if enc1_val < 1 then enc1_val = 1
HSEROUT [177,cpenc1_cc,enc1_val]
goto Encoder2
Inc1:
Enc1_val = Enc1_val + 1
if enc1_val => 127 then enc1_val = 127
HSEROUT [177,cpenc1_cc,enc1_val]
'---------------------------------------------------------------------------
Encoder2:
enc2 = io_datb & enc2_mask
if enc2_old = enc2 then goto Encoder3
enctemp = enc2.bit3 ^ enc2_old.bit2
if enctemp = 1 then goto Inc2
Enc2_val = Enc2_val - 1
if enc2_val < 1 then enc2_val = 1
HSEROUT [177,cpenc2_cc,enc2_val]
goto encoder3
Inc2:
Enc2_val = Enc2_val + 1
if enc2_val => 127 then enc2_val = 127
HSEROUT [177,cpenc2_cc,enc2_val]
'---------------------------------------------------------------------------
Encoder3:
enc3 = io_datb & enc3_mask
if enc3_old = enc3 then goto Encoder4
enctemp = enc3.bit5 ^ enc3_old.bit4
if enctemp = 1 then goto Inc3
Enc3_val = Enc3_val - 1
if enc3_val < 1 then enc3_val = 1
HSEROUT [177,cpenc3_cc,enc3_val]
goto encoder4
Inc3:
Enc3_val = Enc3_val + 1
if enc3_val => 127 then enc3_val = 127
HSEROUT [177,cpenc3_cc,enc3_val]
'---------------------------------------------------------------------------
Encoder4:
enc4 = io_datb & enc4_mask
if enc4_old = enc4 then goto Encend
enctemp = enc4.bit7 ^ enc4_old.bit6
if enctemp = 1 then goto Inc4
Enc4_val = Enc4_val - 1
if enc4_val < 1 then enc4_val = 1
HSEROUT [177,cpenc4_cc,enc4_val]
goto encend
Inc4:
Enc4_val = Enc4_val + 1
if enc4_val => 127 then enc4_val = 127
HSEROUT [177,cpenc4_cc,enc4_val]
EncEnd:
'-----------------------------------------------------------------------------
enc1_old = enc1
enc2_old = enc2
enc3_old = enc3
enc4_old = enc4
io_dat_olda = io_data
io_dat_oldb = io_datb
endif
'================================================= ==============================
goto MainLoop
end
' USB descriptors for a HID device
'USBMEMORYADDRESS Con $400 ' USB RAM starts here (set in device header file)
USBMEMORYSIZE Con 256 ' USB RAM size in bytes
USBReservedMemory Var Byte[USBMEMORYSIZE] USBMEMORYADDRESS ' Reserve memory used by USB assembler code
goto hid_desc_end ' Skip over all of the USB assembler code
asm
#define USB_EP0_BUFF_SIZE 64 ; 8, 16, 32, or 64
#define USB_MAX_NUM_INT 1 ; For tracking Alternate Setting
#define USB_MAX_EP_NUMBER 1 ; UEP1
#define NUM_CONFIGURATIONS 1
#define NUM_INTERFACES 1
#define UCFG_VAL USB_PULLUP_ENABLE|USB_INTERNAL_TRANSCEIVER|USB_FUL L_SPEED|USB_PING_PONG__NO_PING_PONG
;#define UCFG_VAL USB_PULLUP_ENABLE|USB_INTERNAL_TRANSCEIVER|USB_LOW _SPEED|USB_PING_PONG__NO_PING_PONG
;#define USE_SELF_POWER_SENSE_IO
;#define USE_USB_BUS_SENSE_IO
#define USB_POLLING
; HID
; Endpoints Allocation
#define HID_INTF_ID 0x00
#define HID_EP 1
#define HID_INT_OUT_EP_SIZE 64
#define HID_INT_IN_EP_SIZE 64
#define HID_NUM_OF_DSC 1
include "usb_hid.asm" ; Include rest of USB files, starting with HID class code
; ************************************************** ****************
; This table is polled by the host immediately after USB Reset has been released.
; This table defines the maximum packet size EP0 can take.
; See section 9.6.1 of the Rev 1.0 USB specification.
; These fields are application DEPENDENT. Modify these to meet
; your specifications.
; ************************************************** ****************
DeviceDescriptor
retlw (EndDeviceDescriptor-DeviceDescriptor)/2 ; bLength Length of this descriptor
retlw USB_DESCRIPTOR_DEVICE ; bDescType This is a DEVICE descriptor
retlw 0x10 ; bcdUSBUSB Revision 1.10 (low byte)
retlw 0x01 ; high byte
retlw 0x00 ; bDeviceClass zero means each interface operates independently
retlw 0x00 ; bDeviceSubClass
retlw 0x00 ; bDeviceProtocol
retlw USB_EP0_BUFF_SIZE ; bMaxPacketSize for EP0
; idVendor (low byte, high byte)
retlw 0xA6
retlw 0x01
; idProduct (low byte, high byte)
retlw 0xDB
retlw 0x07
retlw 0x00 ; bcdDevice (low byte)
retlw 0x00 ; (high byte)
retlw 0x01 ; iManufacturer (string index)
retlw 0x02 ; iProduct (string index)
; iSerialNumber (string index)
retlw 0x03
retlw NUM_CONFIGURATIONS ; bNumConfigurations
EndDeviceDescriptor
; ************************************************** ****************
; This table is retrieved by the host after the address has been set.
; This table defines the configurations available for the device.
; See section 9.6.2 of the Rev 1.0 USB specification (page 184).
; These fields are application DEPENDENT.
; Modify these to meet your specifications.
; ************************************************** ****************
; Configuration pointer table
USB_CD_Ptr
Configs
db low Config1, high Config1
db upper Config1, 0
; Configuration Descriptor
Config1
retlw (Interface1-Config1)/2 ; bLength Length of this descriptor
retlw USB_DESCRIPTOR_CONFIGURATION ; bDescType 2=CONFIGURATION
Config1Len
retlw low ((EndConfig1 - Config1)/2) ; Length of this configuration
retlw high ((EndConfig1 - Config1)/2)
retlw 0x01 ; bNumInterfaces Number of interfaces
retlw 0x01 ; bConfigValue Configuration Value
retlw 0x00 ; iConfig (string index)
retlw _DEFAULT|_SELF ; bmAttributes attributes - bus powered
; Max power consumption (2X mA)
retlw 0x32
Interface1
retlw (HIDDescriptor1-Interface1)/2 ; length of descriptor
retlw USB_DESCRIPTOR_INTERFACE
retlw 0x00 ; number of interface, 0 based array
retlw 0x00 ; alternate setting
retlw 0x02 ; number of endpoints used in this interface
retlw 0x03 ; interface class - assigned by the USB
retlw 0x00 ; boot device
retlw 0x00 ; interface protocol
retlw 0x00 ; index to string descriptor that describes this interface
HIDDescriptor1
retlw (Endpoint1In-HIDDescriptor1)/2 ; descriptor size (9 bytes)
retlw DSC_HID ; descriptor type (HID)
retlw 0x11 ; HID class release number (1.11)
retlw 0x01
retlw 0x00 ; Localized country code (none)
retlw 0x01 ; # of HID class descriptor to follow (1)
retlw 0x22 ; Report descriptor type (HID)
ReportDescriptor1Len
retlw low ((EndReportDescriptor1-ReportDescriptor1)/2)
retlw high ((EndReportDescriptor1-ReportDescriptor1)/2)
Endpoint1In
retlw (EndPoint1Out-Endpoint1In)/2 ; length of descriptor
retlw USB_DESCRIPTOR_ENDPOINT
retlw HID_EP|_EP_IN ; EP1, In
retlw _INT ; Interrupt
retlw low (HID_INT_IN_EP_SIZE) ; This should be the size of the endpoint buffer
retlw high (HID_INT_IN_EP_SIZE)
retlw 0x0A ; Polling interval
EndPoint1Out
retlw (EndConfig1-EndPoint1Out)/2 ; Length of this Endpoint Descriptor
retlw USB_DESCRIPTOR_ENDPOINT ; bDescriptorType = 5 for Endpoint Descriptor
retlw HID_EP|_EP_OUT ; Endpoint number & direction
retlw _INT ; Transfer type supported by this Endpoint
retlw low (HID_INT_OUT_EP_SIZE) ; This should be the size of the endpoint buffer
retlw high (HID_INT_OUT_EP_SIZE)
retlw 0x0A ; Polling interval
EndConfig1
ReportDescriptor1
; vendor defined usage page
retlw 0x06
retlw 0x00
retlw 0xFF
; vendor defined usage
retlw 0x09
retlw 0x00
; collection(application)
retlw 0xA1
retlw 0x01
; *** INPUT REPORT ***
; vendor defined usage
retlw 0x09
retlw 0x01
retlw 0x15 ; logical minimum (-128)
retlw 0x80 ;
retlw 0x25 ; logical maximum (127)
retlw 0x7F ;
retlw 0x35 ; Physical Minimum (0)
retlw 0x00 ;
retlw 0x45 ; Physical Maximum (255)
retlw 0xFF ;
; report size in bits
retlw 0x75
retlw 0x08
; report count (number of fields)
retlw 0x95
retlw 0x10
; Input (Data, Variable, Absolute)
retlw 0x81
retlw 0x02
; *** OUTPUT REPORT ***
; vendor defined usage
retlw 0x09 ; usage (Vendor Defined)
retlw 0x02 ;
retlw 0x15 ; logical minimum (-128)
retlw 0x80 ;
retlw 0x25 ; logical maximum (127)
retlw 0x7F ;
retlw 0x35 ; Physical Minimum (0)
retlw 0x00 ;
retlw 0x45 ; Physical Maximum (255)
retlw 0xFF ;
; report size in bits
retlw 0x75
retlw 0x08
; report count (number of fields)
retlw 0x95
retlw 0x10
; Output (Data, Variable, Absolute)
retlw 0x91
retlw 0x02
retlw 0xC0 ; end collection
EndReportDescriptor1
; String pointer table
USB_SD_Ptr
Strings
db low String0, high String0
db upper String0, 0
db low String1, high String1
db upper String1, 0
db low String2, high String2
db upper String2, 0
db low String3, high String3
db upper String3, 0
String0
retlw (String1-String0)/2 ; Length of string
retlw USB_DESCRIPTOR_STRING ; Descriptor type 3
retlw 0x09 ; Language ID (as defined by MS 0x0409)
retlw 0x04
; company name
String1
retlw (String2-String1)/2
retlw USB_DESCRIPTOR_STRING
retlw 'D'
retlw 0x00
retlw 'L'
retlw 0x00
retlw 'C'
retlw 0x00
retlw 'I'
retlw 0x00
retlw 'N'
retlw 0x00
retlw 'C'
retlw 0x00
; product name
String2
retlw (String3-String2)/2
retlw USB_DESCRIPTOR_STRING
retlw 'U'
retlw 0x00
retlw 'S'
retlw 0x00
retlw 'B'
retlw 0x00
retlw '_'
retlw 0x00
retlw 'M'
retlw 0x00
retlw 'I'
retlw 0x00
retlw 'D'
retlw 0x00
retlw 'I'
retlw 0x00
; serial number
String3
retlw (String4-String3)/2
retlw USB_DESCRIPTOR_STRING
retlw '1'
retlw 0x00
retlw '0'
retlw 0x00
retlw '0'
retlw 0x00
retlw '2'
retlw 0x00
String4
endasm
hid_desc_end
DaveC3
- 11th November 2017, 23:33
I think I used a 18F4550 for this project. if you haven't already, I would suggest you first make simple HID project to see if you can get your PC to recognize your device. If you send me your e-mail address I will send you the whole project in a zip file.
Here is the .LST file for the project, you can see the fuse setting I used.
MPASM 5.43 USB_MIDI.ASM 2-3-2012 20:25:46 PAGE 1
LOC OBJECT CODE LINE SOURCE TEXT
VALUE
00001
00002 ; PICBASIC PRO(TM) Compiler 3.0.4.4, (c) 1998, 2011 microEngineering Labs, Inc. All Rights Reserved.
00000001 00003 MPASMWIN_USED EQU 1
00004
00005 #define PBP_PATH C:\PBP3\
00006
00007
00008
00009
00016 LIST
00017 LIST p = 18F4550, r = dec, w = -311, w = -230, f = inhx32
00018 INCLUDE "P18F4550.INC" ; MPASM Header
00001 LIST
00002
00003 ;================================================= =========================
00004 ; MPASM PIC18F4550 processor include
00005 ;
00006 ; (c) Copyright 1999-2011 Microchip Technology, All rights reserved
00007 ;================================================= =========================
00008
01764 LIST
00021 LIST
00F00000 00022 EEPROM_START EQU 0F00000h
00000020 00023 BLOCK_SIZE EQU 32
00024
00025
00026 PBP_HARDWAREDEF macro
00027 endm
00028
00029
00030 __CONFIG _CONFIG1L, _PLLDIV_5_1L & _CPUDIV_OSC1_PLL2_1L & _USBDIV_2_1L
300000 3EE4 00031 __CONFIG _CONFIG1H, _FOSC_HSPLL_HS_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
00032 __CONFIG _CONFIG2L, _PWRT_OFF_2L & _BOR_ON_2L & _BORV_3_2L & _VREGEN_ON_2L
300002 F3FF 00033 __CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
300004 F9FF 00034 __CONFIG _CONFIG3H, _CCP2MX_ON_3H & _PBADEN_OFF_3H & _LPT1OSC_OFF_3H & _MCLRE_ON_3H
300006 FF9B 00035 __CONFIG _CONFIG4L, _STVREN_ON_4L & _LVP_OFF_4L & _ICPRT_OFF_4L & _XINST_OFF_4L
00036
00037
00038
00039 ; Define statements.
00040 ; C:\PBP3\USB18\USB_MIDI\PICBASICPRO\USB_MIDI.PBP 00007 DEFINE WRITE_INT 1
00041 #define WRITE_INT 1
00042 ; C:\PBP3\USB18\USB_MIDI\PICBASICPRO\USB_MIDI.PBP 00008 Define LOADER_USED 1
00043 #define LOADER_USED 1
00044 ; C:\PBP3\USB18\USB_MIDI\PICBASICPRO\USB_MIDI.PBP 00009 DEFINE RESET_ORG 800h ' For Microchip US
B Bootloader
00045 #define RESET_ORG 800h
00046 ; C:\PBP3\USB18\USB_MIDI\PICBASICPRO\USB_MIDI.PBP 00010 DEFINE INTERRUPT_ORG 808h ' For Microchi
p USB Bootloader
00047 #define INTERRUPT_ORG 808h
00048 ; C:\PBP3\USB18\USB_MIDI\PICBASICPRO\USB_MIDI.PBP 00012 DEFINE OSC 48 ' tell p
rogram we are using a 20mhz oscillator
00049 #define OSC 48
MPASM 5.43 USB_MIDI.ASM 2-3-2012 20:25:46 PAGE 2
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.