Embedded Artists
We are the leading providers of products and services around prototyping, evaluation and OEM platforms using NXP's ARM-based microcontrollers.
LPC4088DM Using USBHost
Warning
This documentation was written for mbed OS 2 and not mbed OS 5. There is no official USB support for LPC4088 in mbed OS 5.
The display modules can be used in either USB Host or USB Device mode.
The DMSupport library contains a fork of mbed's official USBHost library. The reason for forking the library is to make it work on the LPC4088 (the original library only works on LPC1768) as well as adapting some parts of the library to work better in an RTOS.
The USB Host stack contains support for the following USB classes:
Class Name | Status |
---|---|
3GModule | Untested & Unsupported |
HID | Tested OK with both mouse and keyboard |
Hub | Tested OK |
MIDI | Untested & Unsupported |
MassStorage | Tested OK, but slow |
Serial | Untested & Unsupported |
Using USBHost¶
The USB Host library has been modified to send a signal when something is added to or removed from the USB bus. This allows the user program to respond to only those events instead of endlessly polling the status of the bus and using resources while doing so.
The pseudo code for handling USB disconnect/connect looks like this:
// This identifier can be any 2^x number but must be same on sender and receiver side #define USB_CONNECTION_EVENT (1<<4) // The thread: void usbTask(void const* args) { // Create classes for MassStorage, Keyboard, Mouse etc... // Register as a listener for events USBHost* host = USBHost::getHostInst(); host->signalOnConnections(Thread::gettid(), USB_CONNECTION_EVENT); while (true) { // wait for connect/disconnect message from USBHost Thread::signal_wait(USB_CONNECTION_EVENT); // something happened on the USB bus, see if it affects USB Mass Storage // check if a USB memory stick was inserted or removed... // check if a USB keyboard was inserted or removed... // check if a USB mouse was inserted or removed... } } void main(void) { // Initialize DMBoard as usual... // Start other threads... // Start the USB thread Thread tUSBHandler(usbTask, NULL, osPriorityNormal, 8192); // Do other stuff ... }
USB Mass Storage¶
See this wiki page describing how to use USB MassStorage.
USB Keyboard¶
The USB Host stack supports the use of a USB keyboard. Once connected it is possible to attach a callback function to receive everything that is typed.
This is an example showing how print each received character:
#include "mbed.h" #include "DMBoard.h" #include "USBHostKeyboard.h" // Called for each typed key void keyEvent(uint8_t key) { DMBoard::instance().logger()->printf("Typed '%c' (0x%02x)\n", key, key); } // This identifier can be any 2^x number but must be same on sender and receiver side #define USB_CONNECTION_EVENT (1<<4) void usbTask(void const* args) { RtosLog* log = DMBoard::instance().logger(); bool keyboardConnected = false; // create the needed USB classes USBHostKeyboard* keyboard = new USBHostKeyboard(); // register for events when devices are added/removed USBHost* host = USBHost::getHostInst(); host->signalOnConnections(Thread::gettid(), USB_CONNECTION_EVENT); while (true) { // wait for connect/disconnect message from USBHost Thread::signal_wait(USB_CONNECTION_EVENT); // something happened on the USB bus, see if it affects USB keyboard if (keyboard->connected()) { if (!keyboardConnected) { keyboardConnected = true; log->printf("USB Keyboard - Connected\n"); keyboard->attach(keyEvent); } } else { if (keyboardConnected) { keyboardConnected = false; log->printf("USB Keyboard - Ejected\n"); } if (keyboard->connect()) { keyboardConnected = true; log->printf("USB Keyboard - Connected\n"); keyboard->attach(keyEvent); } } } } void main(void) { // Initialize DMBoard as usual... // Start other threads... // Start the USB thread Thread tUSBHandler(usbTask, NULL, osPriorityNormal, 8192); // Do other stuff ... }
USB Mouse¶
The USB Host stack supports the use of a USB mouse. Once connected it is possible to attach a callback function to receive everything that is typed.
This is an example showing how print each received character:
#include "mbed.h" #include "DMBoard.h" #include "USBHostMouse.h" // Called for each mouse action (click and/or move) void mouseEvent(uint8_t buttons, int8_t x, int8_t y, int8_t z) { DMBoard::instance().logger()->printf("Mouse: buttons 0x%02x, x,y,z = %d,%d,%d\n", buttons, x, y, z); } // This identifier can be any 2^x number but must be same on sender and receiver side #define USB_CONNECTION_EVENT (1<<4) void usbTask(void const* args) { RtosLog* log = DMBoard::instance().logger(); bool mouseConnected = false; // create the needed USB classes USBHostMouse* mouse = new USBHostMouse(); // register for events when devices are added/removed USBHost* host = USBHost::getHostInst(); host->signalOnConnections(Thread::gettid(), USB_CONNECTION_EVENT); while (true) { // wait for connect/disconnect message from USBHost Thread::signal_wait(USB_CONNECTION_EVENT); // something happened on the USB bus, see if it affects USB mouse if (mouse->connected()) { if (!mouseConnected) { mouseConnected = true; log->printf("USB Mouse - Connected\n"); mouse->attachEvent(mouseEvent); } } else { if (mouseConnected) { mouseConnected = false; log->printf("USB Mouse - Ejected\n"); } if (mouse->connect()) { mouseConnected = true; log->printf("USB Mouse - Connected\n"); mouse->attachEvent(mouseEvent); } } } } void main(void) { // Initialize DMBoard as usual... // Start other threads... // Start the USB thread Thread tUSBHandler(usbTask, NULL, osPriorityNormal, 8192); // Do other stuff ... }
The LPC4088 comes with support for a cursor on the display. You can read more about it in the LPC4088 User Manual which can be downloaded from lpcware.
To use that instead of just printing the coordinates:
#include "mbed.h" #include "DMBoard.h" #include "USBHostMouse.h" // Variables to keep track of the latest received data (to be printed in another thread maybe?) static volatile int8_t mouse_button, mouse_x, mouse_y, mouse_z; // As all movements are relative, these two variables contains the absolute position static uint16_t cursor_x=0, cursor_y=0; // Called for each mouse action (click and/or move) void mouseEvent(uint8_t buttons, int8_t x, int8_t y, int8_t z) { mouse_button = buttons; mouse_x = x; mouse_y = y; mouse_z = z; if (x < 0) { if (cursor_x > -x) { cursor_x += x; } else { cursor_x = 0; } } else { if ((cursor_x + x) >= 480) { cursor_x = 479; } else { cursor_x += x; } } y = y/8; if (y < 0) { if (cursor_y > -y) { cursor_y += y; } else { cursor_y = 0; } } else { if ((cursor_y + y) >= 272) { cursor_y = 271; } else { cursor_y += y; } } //Chip_LCD_Cursor_SetPos(LPC_LCD, cursor_x, cursor_y); LPC_LCD->CRSR_XY = (cursor_x & 0x3FF) | ((cursor_y & 0x3FF) << 16); } // Data about the cursor to show #define LCD_CURSOR_32x32 0 #define LCD_CURSOR_64x64 1 #define CURSOR_SIZE LCD_CURSOR_32x32 #define CURSOR_H_SIZE 32 #define CURSOR_V_SIZE 32 #define CURSOR_NUM 0 #define CURSOR_H_OFS (10) #define CURSOR_V_OFS (6) // Cursor image const unsigned char __attribute__ ((aligned(4))) Cursor[(CURSOR_H_SIZE / 4) * CURSOR_V_SIZE] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFF, 0xEA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFE, 0xAA, 0xAA, 0xAA, 0xAB, 0xFB, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xBF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xBF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAF, 0xFF, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAF, 0xFF, 0xFF, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA, 0xAB, 0xFF, 0xFF, 0xFE, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xFF, 0xFF, 0xFA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA }; // Code to enable/disable the cursor void prepareCursor(bool enable) { //Chip_LCD_Cursor_Disable(LPC_LCD, 0); LPC_LCD->CRSR_CTRL = (CURSOR_NUM << 4); if (enable) { //Chip_LCD_Cursor_Config(LPC_LCD, LCD_CURSOR_32x32, true); LPC_LCD->CRSR_CFG = ((true ? 1 : 0) << 1) | CURSOR_SIZE; //Chip_LCD_Cursor_WriteImage(LPC_LCD, 0, (void *) Cursor); { int i, j; uint32_t *fifoptr, *crsr_ptr = (uint32_t *) Cursor; /* Check if Cursor Size was configured as 32x32 or 64x64*/ if (CURSOR_SIZE == LCD_CURSOR_32x32) { i = CURSOR_NUM * 64; j = i + 64; } else { i = 0; j = 256; } fifoptr = (uint32_t *) &(LPC_LCD->CRSR_IMG[0]); /* Copy Cursor Image content to FIFO */ for (; i < j; i++) { *fifoptr = *crsr_ptr; crsr_ptr++; fifoptr++; } } //Chip_LCD_Cursor_SetClip(LPC_LCD, CURSOR_H_OFS, CURSOR_V_OFS); LPC_LCD->CRSR_CLIP = (CURSOR_H_OFS & 0x3F) | ((CURSOR_V_OFS & 0x3F) << 8); //Chip_LCD_Cursor_SetPos(LPC_LCD, cursor_x, cursor_y); //Chip_LCD_Cursor_Enable(LPC_LCD, 0); LPC_LCD->CRSR_CTRL = (CURSOR_NUM << 4) | 1; } } // This identifier can be any 2^x number but must be same on sender and receiver side #define USB_CONNECTION_EVENT (1<<4) void usbTask(void const* args) { RtosLog* log = DMBoard::instance().logger(); bool mouseConnected = false; // create the needed USB classes USBHostMouse* mouse = new USBHostMouse(); // register for events when devices are added/removed USBHost* host = USBHost::getHostInst(); host->signalOnConnections(Thread::gettid(), USB_CONNECTION_EVENT); // make sure that the cursor is not shown until a mouse is connected prepareCursor(false); while (true) { // wait for connect/disconnect message from USBHost Thread::signal_wait(USB_CONNECTION_EVENT); // something happened on the USB bus, see if it affects USB mouse if (mouse->connected()) { if (!mouseConnected) { mouseConnected = true; log->printf("USB Mouse - Connected\n"); mouse->attachEvent(mouseEvent); prepareCursor(true); } } else { if (mouseConnected) { prepareCursor(false); mouseConnected = false; log->printf("USB Mouse - Ejected\n"); } if (mouse->connect()) { mouseConnected = true; log->printf("USB Mouse - Connected\n"); mouse->attachEvent(mouseEvent); prepareCursor(true); } } } } void main(void) { // Initialize DMBoard as usual... // Start other threads... // Start the USB thread Thread tUSBHandler(usbTask, NULL, osPriorityNormal, 8192); // Do other stuff ... }