Easy HID Command -Response application


Closed Thread
Results 1 to 26 of 26

Hybrid View

  1. #1
    Join Date
    May 2005
    Location
    Ne ohio
    Posts
    21

    Default Easy HID Command -Response application

    Hi all,
    I've been working with some USB for a bit now.
    I have a 64byte array being sent both directions and I simply structure the array with the command for the PIC along with a 'sequence' number so I know the array coming back is the latest data.
    A typical command is a byte code that may do something like "get AD input AN0" an return it in the PC's Input array.
    I can command the PIC all day long as rapidly as possible but to use a command that expects a return result like an A/D reading, is most often delayed and I have to read the InputBuffer until the sequence number matches the latest command that went out. This results in delays of 100 to 300 msecs before I get the latest result back! I've use some toggling pins to check on the timing and the PIC is only using about 200-300uSecs to finish with its DoUSBIn and then DoUSBOut response. Yet on the PC side there is this delay.
    I've tried flushing the USB Buffers among other things and still I get these response delays. I've had this in both my HIDMaker code and in some code that Jan Axelson. has on her site.

    Has anyone encountered this phenomenon?

  2. #2
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    What do you have the "Polling" set to?

    With EasyHID, the defaults for both IN and OUT reports are 10ms.
    That's how often the PC will "Poll" the device to see if it needs to send/receive anything.
    They can be reduced to 1ms for each.

    How are you servicing USB?
    1. Sprinkling USBSERVICE statements around the program?
    2. Using a timer to call USBSERVICE periodically?
    3. Using USB interrupts?

    Are you using ON INTERRUPT? If so, are there any PAUSE statements in your program.

    I've use some toggling pins to check on the timing and the PIC is only using about 200-300uSecs to finish with its DoUSBIn and then DoUSBOut response.
    The USBIN and USBOUT statements execute very fast, because all they are doing is copying data to/from the USB buffers in RAM. Then it turns control of that RAM over to the SIE, which handles the actual transfers to the PC.

    Just because those statements have completed, doesn't mean the data has been sent/received yet.

    Also, any other devices on the USB bus like hard disks or web-cams may be using a big chunk of bus time too.
    There are no guarantees on when USB data will be delivered in either direction.

    DT

  3. #3
    Join Date
    May 2005
    Location
    Ne ohio
    Posts
    21

    Default

    Hi,
    My polling interval looks to be 1msec if I understand the polling interval
    in my DESCUSBFixture.asm file
    from that:

    Endpoint1In
    retlw (EndPoint1Out-Endpoint1In)/2 ; length of descriptor
    retlw DSC_EP
    retlw 0x81 ; EP1, In
    retlw 0x03 ; Interrupt
    retlw 0x40 ; This should be the size of the endpoint buffer
    retlw 0x00
    retlw 0x01 ; Polling interval
    EndPoint1Out
    retlw (EndConfig1-EndPoint1Out)/2 ; Length of this Endpoint Descriptor
    retlw DSC_EP ; bDescriptorType = 5 for Endpoint Descriptor
    retlw 0x01 ; Endpoint number & direction
    retlw 0x03 ; Transfer type supported by this Endpoint
    retlw 0x40 ; This should be the size of the endpoint buffer
    retlw 0x00
    retlw 0x01 ; Polling interval


    I've turned off my Interrupts for now and use USBService often.

    As for Pause, I am using "pauseus 1" for some SPI control of some chips on their Chip Enable lines. If it were much longer, I'd have it broken up with some USBSERVICE in there.

    I can send commands that don't expect response from the PIC very rapidly but it's just the Endpoint data that matches the most recent sequence byte that takes long in getting back.

    I've also tried the USB demo on: www.PICcoder.co.uk
    and using c# stopwatch in System.diagnostics shows about 45 msecs delay.

    http://www.piccoder.co.uk/content/view/42/26/

    I usually plug the device in near where my mouse is and I don't think I using the bandwidth on that Controller too heavily.

    I could try putting USBService into the Timer interrupt I was using for timing LEDs.

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    Yup, that looks right for 1ms polling.

    I find that I get the best response by using the USB interrupt to do the USBSERVICE.
    It's really easy to do since the USB routines are all in assembly language and can use ASM type interrupts.

    But I don't think that will make a 100-300ms difference. There's something else going on.

    I use Delphi on the PC side, so I don't know if VB or C# are the same or not, but if I try to send more than one report at a time ... control is not passed back to the program until they've all been sent. And during that time, anything coming back from the PIC gets stuck in the PC's buffer, and then suddenly you have a whole bunch of packets all at once.

    Have you timed the response for a single request? Or are there always multiple requests? Something similar could be happening.

    DT

  5. #5
    Join Date
    May 2005
    Location
    Ne ohio
    Posts
    21

    Default

    I'll try the Interrupt Service method. I did ask (Jan A. ) about the delays and she wrote back:

    "Every API call adds overhead. An alternative would be to define an IN Feature report for each command and have the device send the response in the Data stage. That way you get the command and response in a single control transfer."

    So I've been testing feature reports and now have 5msec response and faster depending on the PC, from the sample Feature Report given with the HIDMaker.
    Next, if possible, I'll expand the End point sizes in the Feature Report and structure them for my application.

    I just tested the timing with toggling pins:
    I see 300uSecs between the last toggle of DO19 and the next toggle of DO20
    and that was using INPUT and OUTPUT Reports.

    ProgramStart:
    gosub DoUSBIn 'Loops inside here until a command is received
    GOSUB Handle_Cmd 'Command Executioner of the 'deed'
    gosub DoUSBOut
    TOGGLE DO20
    goto ProgramStart

    '================ USB SUBROUTINES =========

    '************************************************* ********
    ' * receive data from the USB bus *
    '************************************************* ********
    DoUSBIn:
    TOGGLE DO19
    GOSUB Cycle_Leds
    USBBufferCount = USBBufferSizeRX ' RX buffer size
    USBService ' keep connection alive
    USBIn 1, USBBuffer, USBBufferCount, DoUSBIn ' read data, if available
    return
    ' ************************************************** *******
    ' * wait for USB interface to attach *
    ' ************************************************** *******
    DoUSBOut:
    GOSUB Cycle_Leds
    USBBufferCount = USBBufferSizeTX ' TX buffer size
    USBService ' keep connection alive
    USBOut 1, USBBuffer, USBBufferCount, DoUSBOut ' if bus available,transmit
    return

    So next I'll use interrupts for the USB service calls for the INPUT OUTPUT Report code, then if it's still slow I'll expand on the Feature report code and use interrupts for the USBService calls.

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959

    Default

    If there's anyone that knows about USB ... She's the one.
    I've never tried "feature reports" before, I'll have to look into that.

    But this might help with the USB interrupt part.
    It's an include file that services the USB via the USB interrupt.
    It works with programs derived from EasyHID or straight PBP with custom HID descriptors.
    I'm hoping it works with HIDmaker programs too.

    It also gives indications of when the device is connected to the PC, when a report has been received and when it's OK to transmit using the BIT variables ...

    Plugged indicates when the device is fully connected to the PC.
    RX_READY indicates when a report has been received.
    TX_READY indicates when it's OK to Send. The device is Plugged and the SIE is ready to accept data.

    It does everything required to handle the interrupts.
    All you have to do is INCLUDE the file.

    Well, you'll also need to comment out any USBSERVICE and USBINIT statements that may already be in your program, because they will conflict with the interrupt servicing.

    If you want to use other High Priority interrupts in your program, that can be done too. See INT_HOOK below.
    Low priority interrupts are still available.

    Code:
    '***************************************************************************
    '*  Name    : USB_ASM_Service.pbp                                          *
    '*  Author  : Darrel Taylor                                                *
    '*  Date    : 9/10/2009                                                    *
    '*  Version : 1.1                                                          *
    '*  Notes  1. DO NOT place ANY USBSERVICE or USBINIT statements ANYWHERE   *
    '*            in your program. They will conflict with interrupt Servicing *
    '*         2. To use other high priority interrupts you can add the define *
    '*            DEFINE  INT_HOOK  handlers                                   *
    '*            handlers will be called on each high priority interrupt      *
    '*            The handlers must be ASM Interrupt compatible                *
    '***************************************************************************
    DEFINE INTHAND _DoUSBSERVICE
    
    GIE                VAR INTCON.7      ; Global Interrupt Enable
    PEIE               VAR INTCON.6      ; Peripheral Interrupt Enable
    USBIE              VAR PIE2.5        ; USB funnel Interrupt Enable
    USBIF              VAR PIR2.5        ; USB Interrupt Flag
    IDLEIF             VAR UIR.4         ; USB Idle Interrupt Flag
    SOFIF              VAR UIR.6         ; USB Start Of Frame Flag
    SOFIE              VAR UIE.6         ; USB Start Of Frame Interrupt Enable
    USB_Flags          VAR BYTE BANK0
      Plugged          VAR USB_Flags.0   ; indicates Fully connected to PC
      RX_READY         VAR USB_Flags.1   ; indicates Report has been received
      TX_READY         VAR USB_Flags.2   ; indicates it's OK to Send
    CONFIGURED_STATE   CON EXT           ; state when PIC is connected to PC
    BD1STATOUT         VAR BYTE EXT      ; OUT report status byte
    BD1STATIN          VAR BYTE EXT      ; IN report status byte
    USBDeviceState     VAR BYTE EXT      ; USB drivers current State
    RXOWNED            VAR BD1STATOUT.7  ; Out report Owned (OUT is PC to PIC)
    TXOWNED            VAR BD1STATIN.7   ;  IN report Owned (IN is PIC to PC)
    
    ;----[Make it compatible with PBP versions previous to 2.60]----------------
    ASM
      ifndef _USBMEMORYADDRESS           ; only PBP 2.60+ has USBMEMORYADDRESS 
    _USBMEMORYADDRESS = 400h             ; fake it for 2.50-
      endif
    BD1STATOUT = _USBMEMORYADDRESS + 8   ; 408h or 208h
    BD1STATIN  = _USBMEMORYADDRESS + 0Ch ; 40Ch or 20Ch
    
      ifndef USBDeviceState              ; 2.60+ uses USBDeviceState
        ifdef usb_device_state           ; 2.50- uses usb_device_state
    USBDeviceState = usb_device_state
        else
          error "USBDeviceState not found" ; somethings not right if we get here
        endif 
      endif
    ENDASM
    
    ;----[Initialise USB and Interrupts]----------------------------------------
        PAUSE 100                    ; Allow VUSB to stabilize
        USBINIT                      ; initialize the USB driver
        USBSERVICE                   ; service it once
        UIE = $7F                    ; enable USB interrupts
        UEIE = $9F                   ; enable USB Error interrupts
        USBIE = 1                    ; enable USB funnel int
        PEIE = 1                     ; enable peripheral ints
        GIE = 1                      ; enable global ints
        USB_Flags = 0                ; clear the flags
    GOTO OverUSBservice              ; jump over the subroutines
    
    ;----[Interrupt handler -- Service USB]-------------------------------------
    DoUSBSERVICE:
      IF USBIE THEN
        IF USBIF THEN
          BSR = 0                      ; Make sure we're in BANK0
          IF IDLEIF THEN Plugged = 0   ; If the bus is Idle, we can't be Plugged
          IF SOFIF  THEN               ; On Start-Of-Frame
            IF (USBDeviceState = CONFIGURED_STATE) THEN ; Check for CONFIGURED
                Plugged = 1          ; if so, we're Plugged
            ENDIF
          ENDIF
          USBSERVICE                   ; Run the SERVICE routines
          USBIF = 0                    ; clear the USB flag
          IF !Plugged THEN UEIR = 0    ; prevents lock-ups when not terminated
                                         ;  from bit-stuff error
          RX_READY = !RXOWNED          ; indicate if report has been Received
          IF Plugged THEN
            TX_READY = !TXOWNED      ; indicate if ready to Send
          ELSE
            TX_READY = 0             ; don't try to send when not Plugged
          ENDIF
        ENDIF
      ENDIF
      
      ASM
        ifdef INT_HOOK
          L?CALL  INT_HOOK           ; call User Handlers if INT_HOOK is Defined
        endif                        ; User routines must be ASM INT compatible
        retfie 1                     ; Return from interrupt "Fast" with shadows
      ENDASM
    
    OverUSBservice:
    ADDED:
    I've added a define that let's you easliy use more high priority interrupts ...
    Code:
    DEFINE  INT_HOOK  _MyInts
    If defined, the MyInts: routine will be called on each high priority interrupt.
    It should end with a RETURN

    HTH,
    Attached Files Attached Files
    Last edited by Darrel Taylor; - 11th September 2009 at 05:50. Reason: Added some comments to make more sense. Added INT_HOOK define.

Similar Threads

  1. USB hid maker help please.
    By BobEdge in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 3rd April 2013, 14:49
  2. i cant get 18f2550 work as HID
    By Ahmadabuomar in forum mel PIC BASIC Pro
    Replies: 19
    Last Post: - 13th October 2009, 16:39
  3. Unusual Interrupts Application Problem
    By Joe Rocci in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 8th May 2009, 11:55
  4. Hid Maker FS Problems
    By BobEdge in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 24th April 2009, 21:27
  5. Making your own HID descriptor file
    By NL2TTL in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 27th April 2005, 12:35

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts