HIDImplementation
HID Implementation
Audience
This document is intended for DJ controller manufacturers, who are not familiar yet with the HID protocol.
Purpose
As it is explained here, the HID protocol is much better than MIDI for DJ controllers that have high-resolution scratch wheels.
In fact, manufacturers should always choose HID instead of MIDI whenever possible.
The main reason why some manufacturers still use MIDI, is because their engineers are familiar with MIDI and don't know HID (the price of a HID chipset is often cheaper than a MIDI chipset).
Hence this document, to help manufacturers switch to HID, and help produce better DJ equipments for the end-users.
HID Concept
Unlike MIDI, HID works as a "pull" model:
Your firmware writes in a small block of memory (usually located in the HID chipset) bits and bytes corresponding to the state of your device (positions of sliders, state of buttons, etc).
When something changes in this memory block, the HID chipset will signal the computer to read it.
Then, as soon as the DJ software on the computer is ready, it will read the memory block and react to the changes found within.
(it means that a slider can change several times while the computer is busy, the computer will read only the current position when it has time to do so).
The whole memory block is transmitted to the computer every times, even if only one bit changed.
But the memory blocks are small enough (usually 32 or 16 bytes), that the bandwidth used is not much more than sending a 4 bytes MIDI message.
In real-life situations, the extra 12 or 28 bytes per message are ridiculously small compared to the bandwidth of USB 1.0.
And anyway, if a controller were to send enough messages per seconds that the difference between MIDI and HID would be noticeable, the Windows MIDI stack would have been crashed long ago by such a fast MIDI stream.
HID Implementation
When you design your firmware for HID, you first need to decide on the location of the elements in your memory block.
You usually end up with a table looking like this:
bit | ||||||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
byte 0 | LEFT_PLAY | LEFT_PAUSE | LEFT_CUE | LEFT_STOP | LEFT_LOOPIN | LEFT_LOOPOUT | LEFT_CUE1 | LEFT_CUE2 |
byte 1 | LEFT_CUE3 | LEFT_SYNC | LEFT_FX | - | - | - | - | - |
byte 2 | RIGHT_PLAY | RIGHT_PAUSE | RIGHT_CUE | RIGHT_STOP | RIGHT_LOOPIN | RIGHT_LOOPOUT | RIGHT_CUE1 | RIGHT_CUE2 |
byte 3 | RIGHT_CUE3 | RIGHT_SYNC | RIGHT_FX | - | BROWSER_FOLDER | BROWSER_UP | BROWSER_DOWN | BROWSER_ENTER |
byte 5 | LEFT_PITCH | |||||||
byte 6 | RIGHT_PITCH | |||||||
byte 7 | LEFT_VOLUME | |||||||
byte 8 | RIGHT_VOLUME | |||||||
byte 9 | CROSSFADER | |||||||
byte 10 | LEFT_JOG (16bit counter) | |||||||
byte 11 | ||||||||
byte 12 | RIGHT_JOG (16bit counter) | |||||||
byte 13 | ||||||||
byte 14 | - | |||||||
byte 15 | - |
This table is just a simple example. Your implementation may be different, depending on your device.
There is no required order for the buttons and sliders, you can arrange them just as you want.
VirtualDJ will know how to read your table from the definition file.
Once you have decided on the memory table, you can then write your firmware to change the bits and bytes in the HID memory block according to your table.
Then, you can write the definition file so that VirtualDJ can read the HID blocks from your device and react accordingly.
(or, you can just send this table to our engineers, who will write the definition file for you).
LEDs
In order to implement LEDs, you use the same concept of "memory block", but this time it's the computer software who writes in the table, and your firmware reads from it.
So first, you need to implement a second table:
bit | ||||||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
byte 0 | LEFT_PLAY | - | LEFT_CUE | LEFT_STOP | - | LEFT_LOOPOUT | LEFT_CUE1 | LEFT_CUE2 |
byte 1 | LEFT_CUE3 | LEFT_SYNC | LEFT_FX | - | - | - | - | - |
byte 2 | RIGHT_PLAY | - | RIGHT_CUE | RIGHT_STOP | - | RIGHT_LOOPOUT | RIGHT_CUE1 | RIGHT_CUE2 |
byte 3 | RIGHT_CUE3 | RIGHT_SYNC | RIGHT_FX | - | BROWSER_FOLDER | - | - | - |
Then, your firmware just reads from the memory block the corresponding bits to know if a LED needs to be lit or not.
Advanced devices
If your device is more complex (LCD screens, motorized wheels, etc), it's still very easy to implement in HID.
Just use bigger memory blocks to accommodate for ASCII characters for the LCD screens, timestamp and speed for the motor, etc.
If your memory blocks get bigger than 256 bytes, you might want to divide them in several blocks.
The HID protocol lets you define different blocks (called "pages"), and transmit only the page or pages that have been modified.
Refer to the documentation of your HID chipset to know how to work with HID pages.
If you have any questions, of course you can still contact our engineers, who will be happy to assist you with your implementation.
Related Topics:
- FAQ: Implementing new controllers in VirtualDJ
- FAQ : Writing a defintion file for HID controllers
- FAQ : HID vs MIDI