In one of the previous projects – Atmega 32u4 Based Composite Keyboard Mouse Project, a composite device was made. A composite device is a device that has functions of two devices on the same hardware like the composite keyboard mouse was able to operate as generic keyboard as well as generic mouse. In this project, again a composite device – Virtual Serial Mouse is designed. The device works like a mouse as well as an UART to USB converter. The making of a mouse has been already explained in the Atmega 32u4 Based USB Mouse Project. Similarly, making of an UART to USB converter has been explained in Atmega 32u4 Based UART to USB Converter Project. The 8-bit USB AVR – Atmega 32u4 is used as the controller chip in this project. The AVR based Lightweight USB Framework (LUFA) is used as the firmware which is modified and loaded to the Arduino board for making the project.
The device uses both the Communication Device Class (CDC) and Human Interface Device (HID) type interfaces of the USB protocol. The drivers for both the interfaces are taken from the LUFA framework. By using the LUFA firmware, the device driver code to implement USB protocol for CDC and HID class as well as the UART protocol is not needed to be written explicitly. By using APIs provided in the open source framework, the CDC and HID class protocols are implemented.
Fig. 1: Prototype of Arduino based Composite USB Serial Mouse
For operating as Serial device the project device receives the USB data from the USB port of the Arduino Pro Micro. For connecting to UART interface, Tx and Rx pins of the Arduino Pro Micro are connected with the UART interface of any other embedded device. For working as mouse the device is provided with buttons. The tactile switches are used as buttons which are interfaced to Port B of the Arduino Board. As a mouse, the device has buttons for the following functions – :
• Move Pointer Left
• Move Pointer Right
• Move Pointer Upwards
• Move Pointer Down
• Right Click
• Left Click
PREREQUISITES
This project is based on Arduino Pro Micro which has the USB AVR – Atmega 32u4 as the sitting MCU. In order to understand this project, one must have basic knowledge of the AVR microcontrollers and the embedded C programming for AVRs. WinAVR Studio is used to write, edit and compile the project code, so closely following the project shall require familiarizing with the above stated IDE as well. Though LUFA framework takes care of implementing the USB protocol for CDC as well as HID Class and the UART protocol. Though the framework has APIs to abstract the lower level codes, understanding USB protocol is recommended to understand how actually the project is working. In fact, if anyone has already worked on some other microcontroller, it will not be much pain to understand and follow the project. The project is based on using APIs of the LUFA framework and modifying the demo files that comes with the framework itself.
Fig. 2: Screenshot of Virtual Serial Function
COMPONENTS REQUIRED
1. Arduino Pro Micro
2. Breadboard
3. Connecting wires
4. Push buttons
5. Micro USB cable
6. 10K resistors
SOFTWARE TOOLS REQUIRED
1. WinAVR Studio
2. AVR Dude
BLOCK DIAGRAM
Fig. 3: Block Diagram of Arduino based Composite USB Serial Mouse
CIRCUIT CONNECTIONS
The project is built on Arduino Pro Micro in which Atmega 32u4 works as the controller chip. The USB to UART and UART to USB protocol conversion is carried out on the Arduino board itself. The Arduino board has in-built USB port to connect with the personal computer and has Tx and Rx pins for serial communication on UART. For working as serial device only the Arduino board is sufficient and connecting wires for connecting with embedded device having UART interface and USB cable for connecting with the PC are required.
For working as mouse, a set of six tactile switches are connected at the port B of the Arduino. The switches are connected at pins 1, 3, 2, 6, 5 and 4 of the port B with functions assigned to them according to the following table – :
Fig. 4: Table listing Arduino pins and respective mouse functions
The Program code for the project is burnt to the Arduino Pro Micro using AVR Dude. The Arduino board is connected to the USB port of a PC by a USB cable and for connecting to UART interface of another embedded device, RS-232 cable is needed.
HOW THE PROJECT WORKS
In this project both USB protocol for CDC as well as HID class and the UART protocol are used and an API of virtual serial mouse from the LUFA framework is used to implement the project. The device is configured to communication device class (CDC) as well as HID class device. For USB to USART and USART to USB conversion, the device is configured to Abstract Control Model Subclass.
The project is USB CDC as well as HID class device. In the LUFA framework CDC class related modules along with HID and other class related modules are in the LUFA-Source-Folder /LUFA/Drivers/USB/Class/Device folder. The LUFA framework has demo projects for different USB device classes in the LUFA-Source-FolderDemosDeviceClassDriver folder. For implementing the project, demo project for virtual serial mouse provided in the LUFA framework will be modified and complied. The demo project for virtual serial mouse is in the LUFA-Source-FolderDemosDeviceClassDriverVirtualSerialMouse folder. The folder contains VirtualSerialMouse.c file which will be modified to implement the project.
Fig. 5: Image showing characters sent from Arduino to PC via Serial Device
How VirtualSerialMouse.c identifies device as a composite CDC and HID Device
The VirtualSerialMouse.c uses two interfaces – VirtualSerial_CDC_Interface interface called in CDC_Device_USBTask () function where the function is imported from the CDCDeviceClass.c (from LUFA-Source-Folder LUFADriversUSBClassDevice) to configure the device as USB CDC device and Mouse_HID_Interface interface called in HID_Device_USBTask() function where the function is imported from the HIDDeviceClass.c (file located in LUFA-Source-Folder LUFADriversUSBClassDevice) to configure the device as mouse. The interfaces abstract the low-level descriptor codes and identifies the device as CDC device or HID device through an InterfaceNumber variable.
USB CDC Specific Descriptors
Any USB device configure and exchange data with the host by sending descriptors in response to requests from the host device. At application layer descriptors are structured in the form of reports. Every report descriptor has a report structure. A report descriptor contains the information needed by host to determine the data format and how the data should be processed by the host. Therefore, a report descriptor basically structure the data that needs to be exchanged with the host according to the USB protocol.
When a USB device is connected to the host computer, the host sends request for configuration in the form of control transfer. This is common for all USB peripherals or devices irrespective of their configuration to any specific USB device class. Any CDC device for configuring with a host has to respond with Class Request, Class Notification and Endpoint Configuration. These information are passed through the Usage report to the host as the Usage Report informs the Host about the features or functionality of the USB device.
Similarly for configuring as mouse, like a mouse, the device will have to send usage report and data report descriptors specific to mouse HID Class to the host. The Usage or Feature report for mouse contains the information related to the HID features of the mouse. For example, a Mouse feature report generally contains information about number of buttons used, number of axis, scroll wheel, size of Data Report, minimum/maximum movement etc. In other words, this report informs the Host about the type of features needed in the device. The Host can access this report by requesting the device using GET_REPORT request. This report is transmitted using Control Transfer Type of the USB protocol.
The usage and data report associated with CDC USB devices are defined in the CDCClassCommon.h file in the LUFA framework. The file is located in the LUFA-Source-Folder/LUFA/Drivers/USB/Class/Common folder. In the usage report, a CDC device has to acknowledge its class, subclass and protocol values. To learn more about the usage report and data report associated with CDC class USB devices and how various descriptors are formatted and sent to the host on request for CDC device, refer to the Atmega 32u4 Based UART to USB Converter Project.
Similarly, to learn about the usage and data report associated with mouse device, refer to Atmega 32u4 Based USB Mouse Project.
From Where VirtualSerialMouse.C gets the USAGE and Data Report Descriptors
In the LUFA framework’s demo project for Virtual Serial, VirtualSerialMouse.c file imports VirtualSerialMouse.h where the descriptors.h is imported. The descriptor.h has the structures defining CDC class related descriptors. The VirtualSerialMouse.c imports VirtualSerialMouse.h which imports usb.h. USB.h imports CDCCLass.h and HIDClass.h. In CDCClass.h is imported CDCClassDevice.h. The CDCClassDevice.h imports CDCClassCommon.h where the CDC device specific descriptor fields have been defined. In HIDClass.h is imported HIDClassDevice.h. The HIDClassDevice.h imports HIDClassCommon.h where the HID device specific descriptor fields for keyboard, mouse and joystick have been defined.
HOW THE DEVICE WORKS
The device needs to be connected between the PC and the embedded system having UART interface. By default the device works as a mouse but when another embedded system is connected through UART, it becomes UART to USB converter. In the project code additional library for UART is imported for UART functionality. The main() function of the VirtualSerialMouse.c is modified to work the device like a protocol changer. In the main function itself, the device is also configured to HID mouse. The CALLBACK_HID_Device_CreateHIDReport() function is modified to make the device work as generic mouse. Check out the program code to see the modifications implemented for building the project.
Fig. 6: Image of Arduino based Composite USB Serial Mouse
PROGRAMMING GUIDE
For building the project download the LUFA framework from the github.com. The demo project provided with the LUFA framework is modified to make the device. In the extracted LUFA zip file, open Demos/Device/ClassDriver/VirtualSerialMouse folder. The folder has the following files and folders.
Fig. 7: Screenshot of LUFA Library Folder on Windows
Of these, VirtualSerialMouse.h, VirtualSerialMouse.c and Makefile needs to be modified for the project.The modified files (provided at the bottom of the article in zip format) can also be downloaded from the engineersgarage and replaced with the original files. Either open the files in WinAVR Studio or Notepad++ and modify original files or replace files with the already modified one. The modified or replaced VirtualSerialMouse.c needs to be compiled from within the LUFA’s Source folder to get the object code.
Modifying VirtualSerialMouse.h
The VirtualSerialMouse.h library file is imported in the VirtualSerialMouse.c file and includes a set of additional libraries and defines the constants and functions for the joystick device. These include the additional libraries for the joystick, button and LEDs which should be commented out as the project is not using these features. So open VirtualSerialMouse.h and make the following changes – :
• Comment the #include library statements for Joystick.h, LEDS.h, and (We are commenting these libraries as we are not using any joystick, buttons board and LED board)
• Comment the #define statements for LEDMASK_USB_NOTREADY, LEDMASK_USB_ENUMERATING, LEDMASK_USB_READY, LEDMASK_USB_ERROR
• Delete the function declaration for CheckJoystickMovement Save the file with changes
Modifying VirtualSerialMouse.C fileAgain in the VirtualSerialMouse.c, the code sections for Joystick, button board and LEDs need to be commented out. So open VirtualSerialMouse.c and make the following changes – :
• In the main loop, comment the LEDs_SetAllLEDs()
• In SetupHardware() function, comment the Joystick_Init(), LEDs_Init()
• In EVENT_USB_Device_Connect() function, comment the LEDs_SetAllLEDs()
• In EVENT_USB_Device_Disconnect() function, comment LEDs_SetAllLEDs()
• In EVENT_USB_Device_ConfigurationChanged() function, comment the LEDs_SetAllLEDs()
• Also delete the CheckJoystickMovement function completely
In VirtualSerialMouse.c the main() function executes the functioning of the protocol convertor device and also configures the device to HID mouse. First uart.h has to be included in the VirtualSerialMouse.c So add the following statements in the beginning of file.
#include “VirtualSerial.h”
The following functions defined in the uart.h will be used in the program code – :
Fig. 8: Table listing functions defined in uart.h
In the main() function, a variable OUT_Data to hold data sent by the host needs to be defined and a character buffer buff[] to hold data from UART has to be defined. The array representing character buffer has to set its last element as NULL character and UART has to be initialized using uart_init() function. A file variable has to be defined to contain data received from the USB port. This has to be used as parameter in CDC_Device_CreateStream() function. The CDC_Device_CreateStream() function is defined in the CDCClassDevice.c file where other CDC Class Device related functions are also defined. The CDCClassDevice.c is located in the LUFA-Source-FolderLUFAUSBClassDevice folder. An infinite for loop is called in which data from USB port is assigned to OUT_Data variable using getc() function and is sent Tx pin of UART using uart_char() function. If any data from embedded device through UART is available, it is read through uart_read() function and is assigned to the buff[]. The data in buff[] is taken into ReportString pointer and sent to the computer using fputs() function.
For configuring to HID mouse, Port B where the tactile switches have been connected needs to be defined as input and all the pins of port B has to be raised to HIGH logic by default as the microcontroller will need to detect LOW logic for input from tactile switches. So replace the original body of the main function from the following code – :
int main(void)