Implementing a LPC13XX as a USB mouse [SOLVED - working code attached]

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Implementing a LPC13XX as a USB mouse [SOLVED - working code attached]

1,131 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Tue Sep 17 09:14:52 MST 2013
Hello All,

I'm researching the possibility of an LPC1343, via a USB port connected to an android tablet/ PC, controlling a mouse pointer & associated mouse buttons.

I've just read AN10904 but the demo program seems to control the LPC board, I'm looking for the other way around. Is it possible & if so are there examples around?

Thanks,

Leo
0 Kudos
15 Replies

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Fri Nov 29 10:56:37 MST 2013
Finally got this working, thanks in large part to Tsuneo who seems to know he's USB!

Anyway for others I've attached my code. It moves the mouse once every second & clicks the (left) mouse button.

It's successfully running on an LPC1343 Xpresso board. I've implemented soft connect on the board based on these links:

http://blog.ilektronx.com/2011/09/all-about-lpc1343-usb-bootloader.html

http://www.keil.com/support/docs/3141.htm

Hope this helps others!

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Wed Nov 27 02:44:15 MST 2013
Hello All,

I've attached a zip of my source files & accompanying CMSIS (v1.3). Any chance someone who knows USB could try it out & see if it works for them?

All the changes to the code have been marked with 'changed' to enable easier searching.

Thanks,

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Thu Nov 21 11:14:37 MST 2013
I've made some progress, implemented the soft-connect feature & can get my laptop to recognise the LPC board as a mouse:

[ 1966.839917] usb 3-1: USB disconnect, device number 22
[ 1971.497942] usb 3-1: new full-speed USB device number 23 using ohci_hcd
[ 1971.672939] usb 3-1: New USB device found, idVendor=fff0, idProduct=0001
[ 1971.672957] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1971.672966] usb 3-1: Product: LPC13xx USB HID 
[ 1971.672975] usb 3-1: Manufacturer: NXP SEMICOND 
[ 1971.672984] usb 3-1: SerialNumber: DEMO00000001
[ 1971.681803] input: NXP SEMICOND  LPC13xx USB HID  as /devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.0/input/input35
[ 1971.682183] hid-generic 0003:FFF0:0001.0018: input,hidraw2: USB HID v1.00 Mouse [NXP SEMICOND  LPC13xx USB HID ] on usb-0000:00:12.0-1/input0
[ 2136.392365] usb 3-1: USB disconnect, device number 23


However I'm trying to get the board to create mouse movement but no success. Any idea where I should look? I've got wireshark setup to look at USB packets but not sure what I should be looking for. This USB stuff is all new!

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Mon Nov 18 14:57:50 MST 2013
Actually,

I think I see the solution from a previous post of yours:

http://www.lpcware.com/content/forum/lpc1343-usb-hid-example#comment-1128132

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Mon Nov 18 14:29:36 MST 2013
Tsuneo,

Still working on your code. Just wondering how the USB_EndPoint1() should be handled, specifically the line:

USB_WriteEP(0x81, &InReport, sizeof(InReport));


As InReport is now an array?

Thanks,

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Tue Sep 24 02:08:39 MST 2013
Tsuneo,

Brilliant, many thanks indeed for this! It'll really help!

Regards,

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Tsuneo on Mon Sep 23 13:04:54 MST 2013
Hi Leo,

The USB ROM driver on LPC1343, described on AN10904, is an early version, which is impractical.

You may start with usbhid example for LPC1343 in,
C:\nxp\LPCXpresso_6.0.2_151\lpcxpresso\Examples\NXP\LPC1000\LPC13xx\examples.lpc13xx.new.zip

To make a HID mouse with this example, you have to apply a couple of modifications,
1) Descriptors
2) Request handlers
3) Endpoint handler
4) Suggestion for your application

1) Descriptors
HID device type (mouse, keyboard, joystick, etc) is determined by the report descriptor.
You'll find an example of mouse report descriptor in this tool.

"HID Descriptor Tool" on USB.org
http://www.usb.org/developers/hidpage/dt2_4.zip

The report descriptor of usbhid is entirely replaced with this example, as follows,
usbdesc.c

/* HID Report Descriptor */
const uint8_t HID_ReportDescriptor[] = {
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x02,                    // USAGE (Mouse)
    0xa1, 0x01,                    // COLLECTION (Application)
    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)
    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x06,                    //     INPUT (Data,Var,Rel)
    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
};


This report descriptor defines 3 bytes input report of this format,
byte offset
    0     button1 (LSB), button2, button3, and 5 bits padding
    1     X axis
    2     Y axis


Vendor/Product ID of your device should be changed, so that your mouse is recognized as a new device for your PC. You may assign temporary VID/PID like this one, just for development phase.

config.h
#define USB_VENDOR_ID NXP_VID // Vendor ID    <---- 0xFFF0
#define USB_PROD_ID   0x0003// Product ID   <---- 0x0001


On the endpoint descriptor,
- wMaxPacketSize is reduced to 3 bytes input report (not necessarily, because greater is allowed)
- polling interval (bInterval) is set to 1 ms, to get better response
usbdesc.c

/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) */
const uint8_t USB_ConfigDescriptor[] = {
  ...
/* Endpoint, HID Interrupt In */
  USB_ENDPOINT_DESC_SIZE,            /* bLength */
  USB_ENDPOINT_DESCRIPTOR_TYPE,      /* bDescriptorType */
  USB_ENDPOINT_IN(1),                /* bEndpointAddress */
  USB_ENDPOINT_TYPE_INTERRUPT,       /* bmAttributes */
  WBVAL(0x0004),                     /* wMaxPacketSize */    <---- WBVAL(0x0003)
  0x20,          /* 32ms */          /* bInterval */         <---- 0x01
  ...


Optionally, you may apply boot protocol, so that your mouse is recognized by BIOS at PC start up.

usbdesc.c

/* USB Configuration Descriptor */
/*   All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) */
const uint8_t USB_ConfigDescriptor[] = {
  ...
/* Interface 0, Alternate Setting 0, HID Class */
  USB_INTERFACE_DESC_SIZE,           /* bLength */
  USB_INTERFACE_DESCRIPTOR_TYPE,     /* bDescriptorType */
  0x00,                              /* bInterfaceNumber */
  0x00,                              /* bAlternateSetting */
  0x01,                              /* bNumEndpoints */
  USB_DEVICE_CLASS_HUMAN_INTERFACE,  /* bInterfaceClass */
  HID_SUBCLASS_NONE,                 /* bInterfaceSubClass */  <---- HID_SUBCLASS_BOOT
  HID_PROTOCOL_NONE,                 /* bInterfaceProtocol */  <---- HID_PROTOCOL_MOUSE
  0x00,                              /* iInterface */
  ...


2) Request handlers

USB_Configure_Event() is modified as follows.

usbuser.c

#define HID_BOOT_PROTOCOL     0
#define HID_REPORT_PROTOCOL   1

extern uint8_t HID_Protocol;
uint8_t hid_int_EP_busy;

#if USB_CONFIGURE_EVENT
void USB_Configure_Event (void) {

  if (USB_Configuration) {                  /* Check if USB is configured */
/*  comment these lines
    GetInReport();
    USB_WriteEP(0x81, &InReport, sizeof(InReport));
*/
    HID_Protocol = HID_REPORT_PROTOCOL;   // the default is report protocol
    hid_int_EP_busy = FALSE;
  }
}
#endif


3) Endpoint handler
The InReport buffer is extended to 3 bytes array, to hold the input report.
hiduser.c
uint8_t InReport;            <---- InReport[3]

demo.h
extern uint8_t InReport;     <---- InReport[3]


USB_EndPoint1(), which is called at endpoint interrupt, is modified so that it puts the input report to this endpoint.
usbuser.c

void USB_EndPoint1 (uint32_t event) {

  switch (event) {
    case USB_EVT_IN:
/*    comment this line
      GetInReport();
*/
      if ( hid_int_EP_busy ) {
        USB_WriteEP(0x81, &InReport, sizeof(InReport));
        hid_int_EP_busy = FALSE;
      }
      break;
  }
}


4) Suggestion for your application
Mouse movement and its buttons are regularly polled in a timer interrupt.
You have to set up a timer (or SysTick), to generate regular interrupt of around 10 ms interval.
In the timer ISR, input report is filled and EP1 interrupt is forced.

void timer_ISR( void )
{
  if ( ! hid_int_EP_busy ) {
    //
    // poll mouse movement and its buttons, here
    //
    InReport[0] = buttons;         // put input report to the buffer
    InReport[1] = x_relative_movement;
    InReport[2] = y_relative_movement;
    hid_int_EP_busy = TRUE;
    LPC_USB->DevIntSet = 1 << 2;   // force endpoint 1 interrupt
  }
  LPC_TMR32B0->IR = 1;/* clear interrupt flag */
}


We don't use GetInReport() routine any more. Ignore this routine.

Hope this helps you [;)]

Tsuneo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Sat Sep 21 06:59:36 MST 2013
Many thanks indeed for this explanation. Still finding my feet the LPCXpresso & USB so things clearer!

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wells on Thu Sep 19 13:42:00 MST 2013
The new v2 examples have the 'new' USBDLIB and the 'old' LPCUSBLIB examples.
USBDLIB is a library that provides USB device layer (hardware and class) abstraction functions from devices to the USB ROM API.
Just to be clear - LPCUSBLIB is not USBDLIB.

For devices without the USB ROM API functions, you can use the USBD library. But if you have a device with USB ROM support, you don't need the library.
Say for example you are using the LPC11U1x devices which doesn't have the USB ROM API functions - you would use the library here.
However, if you are using the LPC11U2x/3x devices, you don't need the library since the functions are already provided in ROM (and you save code space).

The same USBDLIB example will work the same on different devices, but for devices without the USB API functions in ROM, you need to use the library.
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by NXP_Paul on Thu Sep 19 12:26:00 MST 2013
Leo
The LPC11U14 doesn't have ROM drivers, so either should work.
An easier place to start would be to use the LPC1343 HID example, and then replace the generic HID descriptors with those from the HID mouse example.

- Paul
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Thu Sep 19 09:50:25 MST 2013
Paul,

Apologies but another question..

I've downloaded the LPCOpen v2.00 package & looked at some of the mouse examples for the LPC11U14. I take it I should be looking at the:

nxp_lpcxpresso_11u14_lpcusblib_MouseDevice

example & [u]not[/u] the:

nxp_lpcxpresso_11u14_usbd_lib_hid_mouse

which uses the USB ROM drivers?

Thanks,

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Wed Sep 18 10:37:34 MST 2013
Paul,

Thanks again for the reply, perhaps I should have spent an extra €3 for the '1347 board!

Anyway I'll give the example a try & perhaps post something here if I get it working.

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by NXP_Paul on Tue Sep 17 14:53:31 MST 2013
The LPC1342/43 have a very different USB peripheral than the LPC1345/46/47, so the LPCOpen examples will not work for the LPC1342/43.

- Paul
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by leo738 on Tue Sep 17 11:40:00 MST 2013
Paul,

Thanks for the quick reply.

I was looking at the LPCopen platform (v1.03), it includes a mouse example for the 1347, but from what you say about the ROM drivers I assume it won't work for the 1343?

Thanks again,

Leo
0 Kudos

901 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by NXP_Paul on Tue Sep 17 11:15:58 MST 2013
Implementing a mouse function with the LPC1343 should not be difficult.  The biggest difference will be the report descriptors.  You won't be able to use the ROM drivers in the LPC1343 (although you could use the ROM drivers in the LPC1345/46/47).  I would suggest looking at the LPC11U14 example code which includes USB mouse code.
You can download the USB mouse code for the LPC11U14 at: http://www.lpcware.com/content/nxpfile/lpcopen-platform

- Paul
0 Kudos