News:

Let's find out together what makes a PIC Tick!

Main Menu

How can create analog Joystick?

Started by Mapo, Jun 12, 2021, 01:27 PM

Previous topic - Next topic

Mapo

Hello everybody,

I start a new project to make a Joystick to use with a Windows program.
In the examples I've seen how to make a mouse, but I don't know how to tell Windows that it's a joystick.
Has anyone had any experiences?

Thank you

joesaliba

Some years ago we did a joystick with 8 analog inputs, 32 buttons and a hat switch.

Then there was some changes to the descriptor and it did not work anymore, and never had time to revisit this project.

If I find the files I will share them.

Regards

Joe

top204

That would be an excellent piece of code to see Joe.

I tried creating a HID joystick and it worked until I got more analogue inputs and buttons, then it stopped working because of something in the descriptor data that I simply could not get my head around.

Mapo

Thanks Joe, if you share the files I have a starting point.
In my project I need 3 analog inputs and 5 buttons, quite simple, but there is little documentation and unclear.

Mapo

Les, if you can share your experiment I would be grateful

Pepe

this is a joystick for 18f2550

joesaliba

Pepe, could it be the one that I posted on the old forum? It used to work.

@top204 I do not know why but I cannot compile for 18F2455 but I can for the 18F4550 or so.

I will try to dig out the code and post them to you maybe we get this thing going again. It will be a great addition to the libraries.

Regards

Joe

top204

If it is using the HID library I created all of those years ago, it will need:

$define USB_RAM 1024

At the beginning of the main program, before the include files, so they can see the $define.

It will also need the fuse configs for that device added to the "USB_Defs.inc" file. I originally created the HID files as a demo, and only placed the fuses in for the devices I had available to test at that time.

Pepe

#8
this is a binary compiled with an source in c and have 8 analogs chanels and 24 buttons

Pepe

this is proteus simulation

Mapo

Thanks Pepe,
but I want to make this joystick with my customizations.
I am always looking for information on HID joystick communication

Stephen Moss

Quote from: Mapo on Jun 12, 2021, 01:27 PMIn the examples I've seen how to make a mouse, but I don't know how to tell Windows that it's a joystick.
As I recall from reading some of the USB documentation many years ago, after enumeration the Host gets the device descriptor and it is that which identifies to the host what the device is. So I think you need to create the correct device descriptor first, there is a free HID Descriptor tool on the USB.ORG website that may be of use.
What that may not do is indicate in what order your data should be, i.e. X,Y,Z, buttons or Z, Buttons, Y, X. The USB documentation might tell you that otherwise you will either need to use a bus analyser to capture the Descriptor of another joystick or just experiment with different orders until the results look right with an existing driver. If you cannot get it to work with a generic Joystick driver you may be faced with having to write your own driver. 


Quote from: Mapo on Jun 14, 2021, 07:27 PMThanks Pepe,
but I want to make this joystick with my customizations.
I am always looking for information on HID joystick communication
I could be wrong but I think that may be determined more by the device configuration data then the HID descriptor, and as I recall devices can have more than one configuration, for example, a three button Mouse may have two configurations, 2 button (3 bytes, X, Y & Buttons) as legacy support for older programs and 3 button (4 bytes, X, Y, Scroll Wheel & Buttons) and that which configuration is used is determined by the host as applicable.
As you say you want 3 analogue inputs and 5 buttons the configuration of a 3 button mouse may do what you need so it may be that all you need to do is change the the part of the descriptor that identifies it as a mouse to that that which identifies it as a Joystick and possibly the number of data bytes if the example is for a two button mouse. 

If you have not done so try the USB 20 Specification document as that may contain an example of a joystick as an indication of what you need. I know 2.0 is not the latest specifications but the HID specifications has not changed so why look through a lager document most of which is irrelevant to you. All HID devices use the same communication as they are the same device type, so essentially Mouse and Joystick communications are the same in regards to speed and data transfer type, it is just the amount of bytes sent and the order of the bytes that may vary between them.

USB is complicated and messy and so not something you can just play around with, I would suggest reading the USB 2.0 specification to hopefully gain at least a basic understanding of how it works and how descriptors and configurations work together to have a better chance of getting something working.

Mapo

Thanks Stephen, you have been very helpful

Pepe

#13
I do this code for a Joystick with a pic18f2550 20mhz and in the attachment is proteus simulation

Joystick24.bas

Device = 18F2550
Declare Xtal = 48
Optimiser_Level = 3
Declare Bootloader off
Declare Create_Coff  On
Declare Onboard_USB On

'Declare PROTON_START_ADDRESS = $1000

Include  "joystick_desc.inc"
 
Declare Adin_Res = 10   
Declare Adin_Tad = FRC   
Declare Adin_Stime = 50
ADCON2bits_ADFM = 1
ADCON1 = 0x04

Symbol GIE = INTCON.7    ' Global Interrupt Enable

Symbol TMR0IE INTCON.5  ' TMR0 Overflow Interrupt Enable
Symbol TMR0IF INTCON.2  ' TMR0 Overflow Interrupt Flag
 
Dim fLeer As Bit
Dim  fTx As Bit

Dim BUFFER[19] As Byte

Dim CANAL1 As Word
Dim CANAL2 As Word
Dim CANAL3 As Word
Dim CANAL4 As Word
Dim CANAL5 As Word
Dim CANAL6 As Word
Dim CANAL7 As Word
Dim CANAL8 As Word

Dim temp As Byte
Dim temp1 As Byte

Dim Btn1a8 As Byte
Dim Btn9a16 As Byte
Dim Btn17a24 As Byte

On_Hardware_Interrupt GoTo Isr
           

' INICIO DEL PROGRAMA PRINCIPAL


Clear ' LIMPIAMOS LA RAM

TRISA=%11101111 ' PUERTO A COMO ENTRADAS
TRISB=%11111111 ' PUERTO B
TRISC=%00110111


TMR0L = 21    '1 ms interrup
   
T0CON = 0xC7 ' prescaler 256

DelayMS 500

'BUFFER[0] =0 ;  EJE x
'BUFFER[2] =0 ;  EJE y
'BUFFER[4] =0 ;  Throttle
'BUFFER[6] =0 ;  Rudder
'BUFFER[8] =0 ;  Rx
'BUFFER[10] =0 ; Ry
'BUFFER[12] =0 ; slider
'BUFFER[14] =0 ; dial
'BUFFER[16] =0 ; BOTONES 1 A 8
'BUFFER[17] =0 ; BOTONES 9 A 16
'BUFFER[18] =0 ; BOTONES 17 A 24


TMR0IE = 1   
 
GIE = 1
 
Repeat
USBPoll ' Wait for USB to become attached
Until USB_tConnected = 1 Or USB_tConfigured = 1

Do
 If fLeer = 1 Then
                  fLeer = 0
                  CANAL1 = ADIn 0
                  DelayUS 10

                  CANAL2 = ADIn 1
                  DelayUS 10

                  CANAL3 = ADIn 2
                  DelayUS 10

                  CANAL4 = ADIn 3
                  DelayUS 10

                  CANAL7 = ADIn 9
                  DelayUS 10

                  CANAL8 = ADIn 10
                  DelayUS 10

                  CANAL6 = ADIn 8
                  DelayUS 10

                  CANAL5 = ADIn 4
                  DelayUS 10

'LEO DIGITALES
                  'prepara para leer primeros  8 botones
                  PORTC.7 = 0
                  PORTA.4 = 1
                  PORTC.6 = 0
                  DelayUS 10
             
                  temp = PORTB
                  temp1 = PORTC
             
                  temp = temp & %11110001
                  temp1 = (temp1 & %00000111)<<1
                  Btn1a8 = temp | temp1
             
                  'prepara para leer los siguientes 8 botones
                  PORTC.7 = 0
                  PORTA.4 = 0
                  PORTC.6 = 1
                  DelayUS 10
             
                  temp = PORTB
                  temp1 = PORTC
       
                  temp = temp & %11110001
                  temp1 = (temp1 & %00000111)<<1
                  Btn9a16 = temp | temp1
                 
                  'prepara para leer los ultimos  8 botones
                  PORTC.7 = 1
                  PORTA.4 = 0
                  PORTC.6 = 0
                  DelayUS 10
             
                  temp = PORTB
                  temp1 = PORTC
       
                  temp = temp & %11110001
                  temp1 = (temp1 & %00000111)<<1
                  Btn17a24 = temp | temp1
                  PORTC.7 = 0
                  fTx=1
End If

If fTx = 1 Then
                BUFFER[0] = CANAL1 & 0xFF
                BUFFER[1] = CANAL1 >> 8
                BUFFER[2] = CANAL2 & 0xFF
                BUFFER[3] = CANAL2 >> 8
                BUFFER[4] = CANAL3 & 0xFF
                BUFFER[5] = CANAL3 >> 8
                BUFFER[6] = CANAL4 & 0xFF
                BUFFER[7] = CANAL4 >> 8
                BUFFER[8] = CANAL5 & 0xFF
                BUFFER[9] = CANAL5 >> 8
                BUFFER[10] = CANAL6 & 0xFF
                BUFFER[11] = CANAL6 >> 8
                BUFFER[12] = CANAL7 & 0xFF
                BUFFER[13] = CANAL7 >> 8
                BUFFER[14] = CANAL8 & 0xFF
                BUFFER[15] = CANAL8 >> 8
                BUFFER[16] = Btn1a8
                BUFFER[17] = Btn9a16
                BUFFER[18] = Btn17a24

DoUSBOut:
                USBOut 1,BUFFER,19, DoUSBOut
                fTx = 0   
End If
 
Loop

Isr:
 Context Save
 
 If TMR0IF = 1 Then
                  TMR0L = 21
                  fLeer = 1
                  TMR0IF = 0
 End If                         
Context Restore
End

;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings

Config_Start
  PLLDIV = 5 ;Divide by 5 (20 MHz oscillator input)
  CPUDIV = OSC1_PLL2 ;[Primary Oscillator Src: /1][96 MHz PLL Src: /2]
  USBDIV = 2 ;USB clock source comes from the 96 MHz PLL divided by 2
  FOSC = HSPLL_HS ;HS oscillator, PLL enabled (HSPLL)
  FCMEN = OFF ;Fail-Safe Clock Monitor disabled
  IESO = OFF ;Oscillator Switchover mode disabled
  PWRT = On    ;PWRT enabled
  BOR = OFF  ;Brown-out Reset disabled in hardware and software
  BORV = 3    ;Minimum setting 2.05V
  VREGEN = On ;USB voltage regulator enabled
  WDT = OFF  ;WDT disabled
  WDTPS = 1  ;1:32768
  CCP2MX = On ;CCP2 input/output is not multiplexed with RB3
  PBADEN = OFF ;PORTB<4:0> pins are configured as digital I/O on Reset
  LPT1OSC = OFF ;Timer1 configured for higher power operation
  MCLRE = OFF ;MCLR pin disabled
  STVREN = OFF ;Stack full/underflow will not cause Reset
  LVP = OFF    ;Single-Supply ICSP disabled
  XINST = OFF ;Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
  Debug = OFF ;Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
  Cp0 = On ;Block 0 (000800-001FFFh) is code-protected
  CP1 = On ;Block 1 (002000-003FFFh) is code-protected
  CP2 = On ;Block 2 (004000-005FFFh) is code-protected
  CP3 = On ;Block 3 (006000-007FFFh) is code-protected
  CPB = On ;Boot block (000000-0007FFh) is code-protected
  CPD = OFF ;Data EEPROM is not code-protected
  WRT0 = On ;Block 0 (000800-001FFFh) is write-protected
  WRT1 = On ;Block 1 (002000-003FFFh) is write-protected
  WRT2 = On ;Block 2 (004000-005FFFh) is write-protected
  WRT3 = On ;Block 3 (006000-007FFFh) is write-protected
  WRTC = On ;Configuration registers (300000-3000FFh) are write-protected
  WRTB = On ;Boot block (000000-0007FFh) is write-protected
  WRTD = OFF ;Data EEPROM is not write-protected
  EBTR0 = OFF ;Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks
  EBTR1 = OFF ;Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks
  EBTR2 = OFF ;Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks
  EBTR3 = OFF ;Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks
  EBTRB = OFF ;Boot block (000000-0007FFh) is not protected from table reads executed in other blocks
Config_End

;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------               

and the descriptor for 8 channels and 24 buttons

joystick_desc.inc


$ifndef _HID_DESC_INC_
$define _HID_DESC_INC_

'
$define cVID                    0x0461      ' Vendor ID (Keep to 0x format for Hex value)
$define cPID                    0x0057      ' Product ID (Keep to 0x format for Hex value)
$define cUSB_EP0_BUFF_SIZE      64          ' 8, 16, 32, or 64
$define cUSB_MAX_NUM_INT        1
$define cUSB_MAX_EP_NUMBER      1
$define cUSB_NUM_CONFIGS        1
$define cUSB_NUM_INTERFACES    1
$define cUSB_MAX_POWER          100        ' Maximum power consumption (in MilliAmps)
$define cUSB_POLLING_INTERVAL  10        ' Polling interval (in MilliSeconds)


$define cUSB_POLLING

' HID
' Endpoints Allocation
$define cHID_INTF_ID        0
$define cHID_EP              1
$define cHID_INT_IN_EP_SIZE  19
$define cHID_INT_OUT_EP_SIZE 8
$define cHID_NUM_OF_DSC      1

    Symbol cUSB_BUFFER_OUT_SIZE = cHID_INT_OUT_EP_SIZE
    Symbol cUSB_BUFFER_IN_SIZE  = cHID_INT_IN_EP_SIZE

    GoTo _DescriptorMain_              ' Jump over the USB code
    Include "USB_HID.inc"              ' Include the 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.
'
Desc_DeviceDescriptor:
    Dt (Desc_EndDeviceDescriptor - Desc_DeviceDescriptor) / 2    ' Size of this descriptor (in bytes)
    Dt cUSB_DESCRIPTOR_DEVICE          ' Device descriptor type
    Dt 0x11, 0x01                      ' USB Spec Release Number in BCD format - 1.10 (low byte, high byte)
    Dt 0x00                            ' Class Code
    Dt 0x00                            ' Subclass code
    Dt 0x00                            ' Protocol code
    Dt cUSB_EP0_BUFF_SIZE              ' Max packet size for EP0
    Dt Low(cVID), High(cVID)          ' Vendor ID
    Dt Low(cPID), High(cPID)          ' Product ID
    Dt 0x00,0x01                      ' Device release number in BCD format (low byte, high byte)
    Dt 0x01                            ' Manufacturer string index
    Dt 0x02                            ' Product string index
    Dt 0x00                            ' Device serial number string index
    Dt cUSB_NUM_CONFIGS                ' Number of possible configurations
Desc_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
Desc_USB_CD_Ptr:-
Desc_Configs:-
    CData As Dword Desc_Config1

' Configuration Descriptor
'
Desc_Config1:
    Dt (Desc_Interface1 - Desc_Config1) / 2        ' Size of this descriptor (in bytes)
    Dt cUSB_DESCRIPTOR_CONFIGURATION              ' Configuration descriptor type

Desc_Config1Len:
    Dt Low((Desc_EndConfig1 - Desc_Config1) / 2),High ((Desc_EndConfig1 - Desc_Config1) / 2)  ' Total length of data for this cfg
    Dt cUSB_NUM_INTERFACES                        ' Number of interfaces in this cfg
    Dt 0x01                                        ' Index value of this configuration
    Dt 0x00                                        ' Configuration string index
    Dt _cDEFAULT | _cSELF                          ' Attributes
    Dt (cUSB_MAX_POWER / 2)                        ' Max power consumption (in mA)
'
' Interface descriptor
'
Desc_Interface1:
    Dt (Desc_HIDDescriptor1 - Desc_Interface1) / 2 ' Size of this descriptor (in bytes)
    Dt cUSB_DESCRIPTOR_INTERFACE                  ' Interface descriptor type
    Dt 0x00                                        ' Interface Number
    Dt 0x00                                        ' Alternate Setting Number
    Dt 0x02                                        ' Number of endpoints in this intf
    Dt cHID_INTF                                  ' Class code
    Dt 0x00                                        ' Subclass code
    Dt 0x00                                        ' Protocol code
    Dt 0x00                                        ' Interface string index
'
' HID class-specific descriptor
'
Desc_HIDDescriptor1:
    Dt (Desc_Endpoint1In - Desc_HIDDescriptor1) / 2' Size of this descriptor (in bytes)
    Dt cDSC_HID                                    ' HID descriptor type
    Dt 0x00,0x01                                  ' HID Spec Release Number in BCD format - 1.00 (low byte,high byte)
    Dt 0x00                                        ' Country Code (0x00 for Not supported)
    Dt cHID_NUM_OF_DSC                            ' Number of class descriptors
    Dt cDSC_RPT                                    ' Report descriptor type (HID)

Desc_ReportDescriptor1Len:
    Dt Low((Desc_EndReportDescriptor1 - Desc_ReportDescriptor1)/ 2),High((Desc_EndReportDescriptor1 - Desc_ReportDescriptor1)/ 2)

'
' Enpoint descriptor (In)
'
Desc_Endpoint1In:
    Dt (Desc_Endpoint1Out - Desc_Endpoint1In) / 2  ' Size of this descriptor (in bytes)
    Dt cUSB_DESCRIPTOR_ENDPOINT                    ' EndPoint descriptor type
    Dt cHID_EP | _cEP_IN                          ' EndPoint Address
    Dt _cINT                                      ' Attributes
    Dt Low(cHID_INT_IN_EP_SIZE),High(cHID_INT_IN_EP_SIZE) ' Size of the EndPoint buffer (in bytes) (low byte,high byte)              ' Size of the EndPoint buffer (in bytes) (low byte, high byte)
    Dt cUSB_POLLING_INTERVAL                        ' Polling interval (in ms)

'
' Endpoint descriptor (Out)
'
Desc_Endpoint1Out:
    Dt (Desc_EndConfig1 - Desc_Endpoint1Out) / 2    ' Size of this descriptor (in bytes)
    Dt cUSB_DESCRIPTOR_ENDPOINT                    ' EndPoint descriptor type
    Dt cHID_EP | _cEP_OUT                          ' EndPoint Address
    Dt _cINT                                        ' Attributes
    Dt Low(cHID_INT_OUT_EP_SIZE),High(cHID_INT_OUT_EP_SIZE) ' Size of the EndPoint buffer (in bytes) (low byte,high byte)
    Dt cUSB_POLLING_INTERVAL                        ' Polling interval (in ms)
Desc_EndConfig1:

Desc_ReportDescriptor1:
Dt  0x05, 0x01                      ' USAGE_PAGE (Generic Desktop)
Dt  0x09, 0x04                      ' USAGE (Joystick)
Dt  0xa1, 0x01                      ' COLLECTION (Application)
Dt  0x05, 0x01                      ' USAGE_PAGE (Generic Desktop)
Dt  0x09, 0x01                      ' USAGE (Pointer)
Dt  0xa1, 0x00                      ' COLLECTION (Physical)
Dt  0x09, 0x30                      ' USAGE (X)
Dt  0x09, 0x31                      ' USAGE (Y)
Dt  0x15, 0x00                      ' LOGICAL_MINIMUM (0)
Dt  0x26, 0xff, 0x03                ' LOGICAL_MAXIMUM (1023)
Dt  0x75, 0x10                      ' REPORT_SIZE (16)
Dt  0x95, 0x02                      ' REPORT_COUNT (2)
Dt  0x81, 0x02                      ' INPUT (Data,Var,Abs)
Dt  0xc0                            ' END_COLLECTION
Dt  0x05, 0x02                      ' USAGE_PAGE (Simulation Controls)
Dt  0x09, 0x01                      ' USAGE (Flight Simulation Device)
Dt  0xa1, 0x00                      ' COLLECTION (Physical)
Dt  0x09, 0xbb                      ' USAGE (Throttle)
Dt  0x09, 0xba                      ' USAGE (Rudder)
Dt  0x15, 0x00                      ' LOGICAL_MINIMUM (0)
Dt  0x26, 0xff, 0x03                ' LOGICAL_MAXIMUM (1023)
Dt  0x75, 0x10                      ' REPORT_SIZE (16)
Dt  0x95, 0x02                      ' REPORT_COUNT (2)
Dt  0x81, 0x02                      ' INPUT (Data,Var,Abs)
Dt  0xc0                            ' END_COLLECTION
Dt  0x05, 0x01                      ' USAGE_PAGE (Generic Desktop)
Dt  0x09, 0x01                      ' USAGE (Pointer)
Dt  0xa1, 0x00                      ' COLLECTION (Physical)
Dt  0x09, 0x33                      ' USAGE (Rx)
Dt  0x09, 0x34                      ' USAGE (Ry)
Dt  0x15, 0x00                      ' LOGICAL_MINIMUM (0)
Dt  0x26, 0xff, 0x03                ' LOGICAL_MAXIMUM (1023)
Dt  0x75, 0x10                      ' REPORT_SIZE (16)
Dt  0x95, 0x02                      ' REPORT_COUNT (2)
Dt  0x81, 0x02                      ' INPUT (Data,Var,Abs)
Dt  0xc0                            ' END_COLLECTION
Dt  0x05, 0x01                      ' USAGE_PAGE (Generic Desktop)
Dt  0x09, 0x01                      ' USAGE (Pointer)
Dt  0xa1, 0x00                      ' COLLECTION (Physical)
Dt  0x09, 0x36                      ' USAGE (Slider)
Dt  0x09, 0x37                      ' USAGE (Dial)
Dt  0x15, 0x00                      ' LOGICAL_MINIMUM (0)
Dt  0x26, 0xff, 0x03                ' LOGICAL_MAXIMUM (1023)
Dt  0x75, 0x10                      ' REPORT_SIZE (16)
Dt  0x95, 0x02                      ' REPORT_COUNT (2)
Dt  0x81, 0x02                      ' INPUT (Data,Var,Abs)
Dt  0xc0                            ' END_COLLECTION
Dt  0x05, 0x09                      ' USAGE_PAGE (Button)
Dt  0x19, 0x01                      ' USAGE_MINIMUM (Button 1)
Dt  0x29, 0x18                      ' USAGE_MAXIMUM (Button 24)
Dt  0x15, 0x00                      ' LOGICAL_MINIMUM (0)
Dt  0x25, 0x01                      ' LOGICAL_MAXIMUM (1)
Dt  0x75, 0x01                      ' REPORT_SIZE (1)
Dt  0x95, 0x18                      ' REPORT_COUNT (24)
Dt  0x55, 0x00                      ' UNIT_EXPONENT (0)
Dt  0x65, 0x00                      ' UNIT (None)
Dt  0x81, 0x02                      ' INPUT (Data,Var,Abs)
Dt  0xC0                            ' End collection
Desc_EndReportDescriptor1:


' String pointer table
Desc_USB_SD_Ptr:-
Desc_Strings:-
    CData As Dword Desc_String0, Desc_String1, Desc_String2

'
' Language code string descriptor
'
Desc_String0:-
    dt (Desc_String1 - Desc_String0) / 2          ' Size of this descriptor (in bytes)
    dt cUSB_DESCRIPTOR_STRING                      ' String descriptor type
    dt 0x09, 0x04                                  ' Language ID as defined by MS - 0x0409
'
' Manufacturer string descriptor
'
Desc_String1:-
    dt (Desc_String2 - Desc_String1) / 2
    dt cUSB_DESCRIPTOR_STRING ; Descriptor string type
    CData As Dword "USB"
'
' Product string descriptor
'
Desc_String2:-
    dt (Desc_EndStringDescriptors - Desc_String2) / 2
    dt cUSB_DESCRIPTOR_STRING ; Descriptor string type
    CData As Dword "AMG Flight sim interface"
Desc_EndStringDescriptors:   

_DescriptorMain_:

$endif  ' _HID_DESC_INC_

I hope this work help something and I have tested in hardware.

Mapo

many many thanks Pepe
This will help me a lot

Pepe


John Lawton

Here is the Joystick code that Les has been working on, based on my requests.

My requirement is for a 2 axis analogue joystick and provision for up to 32 buttons and a 4 way HAT switch.

The test code seems to enumerate but then it gets stuck waiting for the USB transmit to be ready in Sub __WaitForTX() (in USB_UserHID.inc) and I don't know why.

To check operation, I'm using this Joystick tester, which works fine with an another joystick unit I'm using as a reference unit. http://www.mcrenox.com.ar/downloads/joytester.exe

Can anyone help me debug this please, I'm desperate now as I need to ship working boards to a customer asap!!

See this attachment for Les's code using an 18F4550 device @ 12MHz HID_Joystick_Mk1.zip (although my actual hardware actually uses a 18F24J50)

John Lawton

Update. To debug Les's code, I'm using this software USB analyser: http://www.usblyzer.com/ which can capture and analyse lots of stuff. 

So far I have found and fixed a small typo in the USB_DESCRIPTOR_DEVICE, namely the USB spec revision no. which now corrects the enumeration. There are also some Usage (undefined) items in the captured HID report, see attached, so this might not be quite correct.

The code still doesn't run properly, the USB transactions show an Internal USB Reset Port event every 5.5secs which isn't at all right. 

John

Captured HID report: After corrected USB version.txt

trastikata

#18
Quote from: John Lawton on Aug 26, 2021, 11:25 AMCan anyone help me debug this please, I'm desperate now as I need to ship working boards to a customer asap!!

I think you are waiting too long after the buffer is send (100ms) and the HID device disconnects - instead use delay procedure by pooling the bus every 1 MS . Also I think the device might have problems enumerating is some PCs, that's why I'd wait until it's connected and then start sending the data. Try this modified code instead:

'
' /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\ \/\\\    /\\\ /\\\
' \/\\\\\\\\\\\/   /\\\\\ /\\\\\\\\\\ /\\\\\\\\ /\\\\\\\\\\\  /\\\\\\\\\\\ /\\\\\\\\\
' \/\\\//////\\\ /\\\///\\\ \/\\\////// /\\\/////\\\ \////\\\////  \////\\\//// \////////\\\
'   \/\\\    \//\\\ /\\\  \//\\\ \/\\\\\\\\\\ /\\\\\\\\\\\ \/\\\    \/\\\ /\\\\\\\\\\
'    \/\\\ \//\\\ \//\\\ /\\\  \////////\\\ \//\\///////   \/\\\ /\\ \/\\\ /\\ /\\\/////\\\
' \/\\\    \//\\\  \///\\\\\/ /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\ \//\\\\\ \//\\\\\\\\/\\
' \/// \///   \///// \////////// \////////// \/////    \/////   \////////\//
'    Let's find out together what makes a PIC Tick!
'
' HID Joystick interface experiment.
' This code enumerates with my PC, but does not seem to transmit anything.
'
    Device = 18F4550                     ' Choose a device with on-board full speed USB
    Declare Xtal = 48                    ' Set the oscillator speed to 48MHz (using a 12MHz crystal)

$define _USB_RAM $0400

    Include "Joystick_Descriptor.inc"
'
' Create some variables
'
    Dim Buffer[13] As Byte = {110,      ' Z Axis -127 to +127
                              100,      ' R AXIS -127 to +127
                              -50,      ' Z AXIS -127 to +127
                              20,       ' Z AXIS -127 to +127
                              100,      ' Slider AXIS -127 to +127
                              50,       ' Dial AXIS -127 to +127
                              -50,      ' X AXIS -127 to +127
                              50,       ' Y AXIS -127 to +127
                              0,        ' Buttons 1 to 8
                              101,      ' Buttons 9 to 16
                              1,        ' Buttons 17 to 24
                              10,       ' Buttons 25 to 32
                              0}        ' Hat
    Dim bCounter As Byte
    Dim bIndex As Byte
    Dim i As Byte
   
'----------------------------------------------------------------------------------------------
' The main program loop starts here
'
Main:
    Do
        mUSBService()
        DelayUS 25
    Loop Until USB_tAttached = True

    bCounter = 0
    Do
        If USB_tAttached = True Then
            '
            ' Fill the buffer with some values to see if we can detect anything on the PC
            '
            For bIndex = 0 To 12
                Buffer[bIndex] = bCounter
            Next

            HID_WriteArray(Buffer, 12)
            Inc bCounter
            USBDelay(100)
        EndIf

    Loop
   
   
   
Proc USBDelay(bDelay As Byte)
    For i = 0 To bDelay - 1
        mUSBService()
        DelayMS 1   
    Next   
EndProc 


John Lawton

Hi,

thanks very much for looking at this.
I tried your code, and the main loop delay code works okay. The startup code completely stops enumeration, not sure why, so I've omitted that.
Do
      mUSBService()
      DelayUS 25
      Loop Until USB_tAttached = True

I had originally thought that the main loop 100ms delay would cause problems, but I think the low level interrupt keeps the USB connection alive.

It isn't the loop delay causing the USB Reset Port event, I've seen, I'm sure it's connected to the the 'frozen' USB transmit I mentioned earlier. But what is causing that?

John