What HIDmaker's generated code for Microchip C18 looks like
Let's take a look at parts of the actual source code that HIDmaker FS has generated for our Varty16 sample project. You will notice that HIDmaker's USB Advisor tends to leave helpful notes at various places in the generated source code, to aid your understanding and to suggest places where you might want to put code for certain important operations.
This page shows what the generated code for Microchip C18 looks like:
Test value declarations
HIDmaker cannot know what I/O pins your device is going to use. So, to give you maximum flexibility, HIDmaker's generated code does no hardware dependent I/O other than USB. The generated code will compile and run and send data back and forth between the PC and the PIC device, but the generated code only sends test values: numeric constants.
(That's OK, you'll see below how you can fix that by adding a little bit of "real I/O" code. )
Toward the top of your C18 program, you will see place where these test value constants are declared in your project:
and so on, for all the data items and array elements in your project.
Data item declararations
Since HIDmaker FS works on a Principle of Direct Transfer of Variables , for every data item that you define in HIDmaker's Visual Data Designer , you will see a variable declared in the generated source code on both sides.
Recall that this project uses a mixture of odd-sized data items:
Input Report A :
In8bit - 8 bit simple variable
In9bit - 9 bit simple variable
In16bitArray - array variable, 15 elements, each 16 bits long
In13bit - 13 bit simple variable
In5bit - 5 bit simple variable
In8bitArray - array variable, 63 elements, each 8 bits long
Output Report B :
Out8bitArray - array variable, 6 elements, each 8 bits long
Out7bit - 7 bit simple variable
Here are the actual declarations for these variables in C18, as generated for this specific project by HIDmaker FS :
Initializing USB variables
HIDmaker creates a special routine where you can initialize your USB data items if you need to. (It is especially important for you to initialize any bi-directional Feature Report variables that your project may have.)
I/O Pin declarations
HIDmaker FS has no way of knowing what I/O pins you plan to use in your project, which ones will be digital, which will be analog, or whether some pins will be dedicated for use by PIC modules such as the USART, PWM, or whatever.
As a convenience to you, HIDmaker's generated C18 code provides, in commented out form, some lines initialization codes for the PIC registers that set these choices:
These lines are placed close to the beginning of the executable part of the C18 program, as shown above. Simply uncomment these lines and modify them according to the needs of your project.
Sending and Using Data with HIDmaker's USB Variables
Remember that HIDmaker's USB variables are transfer variables, each one being sort of like a shipping create with a label on it, showing the variable's name.
This is just like the situation when you receive a package containing the copy of HIDmaker FS that you ordered. You can't DO much with it until you actually take it out of the package and use it: install it on your PC and run it.
That's the way it is with HIDmaker's USB variables. A HID class Report (an Input Report, an Output Report, or a Feature Report) is like a truckload of packages that you send or receive. Each HIDmaker variable is like one of the packages. If a truckload of packages arrives, you want to open each package and use whatever was inside.
If an Output Report arrives, you want to make use of whatever data was contained in each of the USB variables in that Output Report. HIDmaker FS makes that really simple.
Suppose one of the data items in an Output Report (of a different HIDmaker project) is a 1-bit variable that is supposed to turn on an LED on your board. We'll call that data item LED1 in HIDmaker's Visual Data Item. For our project, we expect that when the PC sets LED1 = 1 and sends it to our peripheral, the peripheral is supposed to turn the LED on. Sending LED1 = 0 should turn off the LED on our board.
If the LED on your board is connected to pin RB0 or PORTBbits.RB0, all you need to do to turn the LED on or off is to assign the value in transfer variable LED1 to the I/O pin, like this:
PORTBbits.RB0 = LED1
That copies the 1 or 0 value from the LED1 transfer variable to the digital pin connected to the LED on your board, turning it on or off.
Over time, if you haven't looked at your project software for a few months, you may find it hard to remember just what PORTB.0 is connected to. As a suggestion to make your code easier to read and maintain, HIDmaker FS creates a commented section for defining variables that you may want to use help:
The variable realLED1 is the same as PORTB.0, but a lot more helpful in telling us what it actually DOES. Then, our assignment statement that turns the LED on or off becomes
realLED1 = LED1
which is a little easier to read and understand.
This comment block shown above is just placed in the generated code as a suggestion for your optional use. Just add some similar lines if you want to make your code more readable and maintainable.
The Developers Guide to USB HID Peripherals, in the HIDmaker FS Users Guide, shows that HIDmaker's peripheral side code can be set up to operate in several different Operating Models. The code that is generated by HIDmaker FS uses Peripheral Model, which assumes that the device is powered by, and always connected to, the USB cable. (Other operating models are explained in the Developers Guide, such as the Data Logger Operating Model, for devices that are self powered and only connected to the USB occasionally. The Developers Guide to USB HID Peripherals shows you how to convert HIDmaker's generated peripheral code to these other operating models.)
The main loop of HIDmaker's generated C18 code is where the USB I/O occurs.
Where you handle Output Variables
For a device that only has a single USB Interface , the top half of the main loop contains code that:
- receives an Output Report from the PC whenever one is sent,
- unpacks it to the individual HIDmaker USB transfer variables you have defined for your project,
- and provides a well marked area for you to handle the data that has just arrived.
Here is how that well-marked area looks in C18 for our Varty16 project:
This is where you add your own code to USE all the variables that have just been sent to your peripheral device in the Output Report.
Example: How to light an LED
Our Varty16 project doesn't have a variable called LED1, but if it did, this is where we would place a line of code to use it to light up an LED on our board. If we also had defined a local variable realLED1 that sets which I/O pin is actually connected to our hardware LED, as discussed above, we could just use the same code as shown in the comment, like so:
It's that simple in HIDmaker FS !
Where you prepare Input Variables
- prepares data,
- and then packs it together and sends it to the PC in an Input Report.
"Preparing data" is done by you: it is where you would add your own code to read buttons on your board, or read A/D channels, read sensors, or do whatever you need to do to get a fresh set of data to send to the PC. There is a clearly marked section in the generated main loop, where you should add this code:
Since HIDmaker FS cannot know what real I/O resources your project will use, the generated code only sends those test values we saw defined above.
You should replace these test value assignments with your own "real I/O" code, that reads data from the sensors used by your own hardware.
Example: How to read a pot and a button & send values to the PC
If your USB project contained a pot and a button that you wanted to read and send to the PC, you could use the sort of code that is shown in the comment block:
USB HID class defines 3 different types of data report:Output Reports only send data items OUT from the PC, toward your device.
Input Reports only send data items IN to the PC, from your device
Feature Reports can send the data items in either direction
Then the collection of all Output data items becomes the Output Report, and so on for Input and Feature Reports.
HIDmaker's data items are identified to the PC in the Report Descriptor, so a data item's direction cannot be changed on the fly.
You almost never see support for bidirectional Feature Reports in those demo programs you find on the web, or from semiconductor manufacturers or compiler makers.
HIDmaker supports Feature Reports fully, and can pack and unpack Feature Reports that have any mixture of odd sized data items, and which can span multiple packets.
When your HIDmaker FS project uses Feature Reports (which our Varty16 example project does not), it generates some special functions to handle them. These functions contain specially marked sections, similar to the ones shown above for Output Reports and Input Reports, where you handle Feature Report data sent from the PC, and where you send data to the PC.
Feature Reports are often used for parameter settings like a volume control, that you want to occasionally check and maybe send a new value from the PC.