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 PICBASIC PRO 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 contstants.

Toward the top of your PICBASIC PRO program, you will see place where these test value constants are declared in your project:

 

' Test values for Endpoint 1 IN Variables:

' =======================================

TEST_IN9BIT con 106

TEST_IN16BITARRAY_0 con 0

TEST_IN16BITARRAY_1 con 1

TEST_IN16BITARRAY_2 con 2

TEST_IN16BITARRAY_3 con 3

TEST_IN16BITARRAY_4 con 4

TEST_IN16BITARRAY_5 con 5

TEST_IN16BITARRAY_6 con 6

TEST_IN16BITARRAY_7 con 7

TEST_IN16BITARRAY_8 con 8

TEST_IN16BITARRAY_9 con 9

TEST_IN16BITARRAY_10 con 10

TEST_IN16BITARRAY_11 con 11

TEST_IN16BITARRAY_12 con 12

TEST_IN16BITARRAY_13 con 13

TEST_IN16BITARRAY_14 con 14

TEST_IN13BIT con 1476

TEST_IN8BIT con 240

TEST_IN5BIT con 10

TEST_IN8BITARRAY_0 con 0

TEST_IN8BITARRAY_1 con 1

 

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 PICBASIC PRO, as generated for this specific project by HIDmaker FS :

 

' ************************************************************************

' Report Variables, which you defined in HIDmaker's Visual Data Designer ,

' to be sent to/from PC via USB:

' ************************************************************************

'

' For your convenience, multi-bit data items are declared as byte or word

' size variables, even if only a few bits are needed. Single-bit data items

' are declared as bit variables. Subroutines like UnPackData and PackData

' are created by HIDmaker to pack this data into the small packets needed for

' USB transmission.


' Declare the actual storage for the Report variables


' Endpoint 1 IN variables:

' ========================

In9bit var word

In16bitArray var word[15]

In13bit var word

In8bit var byte

In5bit var byte

In8bitArray var byte[63]


' Endpoint 1 OUT variables:

' =========================

Out8bitArray var byte[6]

Out7bit var byte

 

 

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.)

 

' ************************************************************************

' InitUSBVars:

' Initializes all data items that will be transferred over USB. This is

' especially important for Feature items, that can be read and written

' by the PC.

'

' HIDmaker will automatically initialize certain variables here, if needed.

' You may add other initialization code here if you choose.

' ************************************************************************


InitUSBVars:


USB_Enum_Complete = 0

return


' ************************************************************************

' USB Init Code:

' ************************************************************************


start:


gosub InitUSBVars

 

 

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 PICBASIC PRO code provides, in commented out form, some lines initialization codes for the PIC registers that set these choices:

 

start:


gosub InitUSBVars


' USB Advisor: You may wish to initialize some things here, before the

' USB initialization happens. Initialization code placed here is sure

' to run, even if the USB initialization fails (perhaps because the

' device was never connected to a USB cable).

' For example:


' The following 5 lines initialize real I/O on a Pic Proto USB board

' INTCON2.7 = 0 ' Enable PortB Pullups

' TRISB = %11111100 ' PORTB to all inputs except LED1 and LED2

' TRISA = %11111111 ' PORTA to all inputs, esp POT1 and POT2

' ADCON0 = 0

' ADCON1 = %00001101 ' Only A/D channels 0 and 1 are enabled

 

 

These lines are placed close to the beginning of the executable part of the PICBASIC PRO 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 PORTB.0, 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:

 

PORTB.0 = 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:

 

' ************************************************************************

' Declare other variables you will need HERE:

' ************************************************************************


' USB Advisor: This would be a good place to define app-specific variables

' for your particular device. For example:


' Defines for "Real I/O" on a Pic Proto USB board

'realLED1 var PORTB.0

'realLED2 var PORTB.1

'realButton1 var PORTB.4

'realButton2 var PORTB.5

 

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.

 

 

Main loop

 

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 PICBASIC PRO code is where the USB I/O occurs.

 

 

' ************************************************************************

' Main loop:

' This code is structured so that it looks for data to receive, or send,

' without getting stuck on any one of the endpoints until a report

' from or to the PC has been started.

' ************************************************************************


MainLoop:

USBService ; Must service USB regularly



' This is a NORMAL or "simple" device. It has a single

' USB Configuration, which contains a single USB Interface .


' Look for USB data coming to PIC


' If a Report is coming to us via Endpoint 1 Out, get it all...

'

HandleEp1Rcv = FALSE

 

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 PICBASIC PRO for our Varty16 project:

 

DoHandleEp1Rcv:

HandleEp1Rcv = TRUE ' Indicate that we have data to handle


' --------------- ADD USER "EP1 RCV" CODE HERE: ------------------


' Add code here to handle the newly-received data from Endpoint 1 Out

' C1 I0


' USB Advisor: Here is where you add code to make use of the data that

' has arrived from the PC.

' For example:


' The following 2 lines provide real I/O for a PicProto USB board

' realLED1 = LED1 ' Light the LEDs

' realLED2 = LED2




' --------------- END USER "EP1 RCV" CODE: ------------------


HandleEp1Rcv = FALSE ' Indicate that received EP1 data has been handled now

 

 

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:

 

' --------------- ADD USER "EP1 RCV" CODE HERE: ------------------


' Add code here to handle the newly-received data from Endpoint 1 Out

' C1 I0


' USB Advisor: Here is where you add code to make use of the data that

' has arrived from the PC.

' For example:


' The following 2 lines provide real I/O for a PicProto USB board

' realLED1 = LED1 ' Light the LEDs

' realLED2 = LED2


realLED1 = LED1 ' Light the LED on our board


' --------------- END USER "EP1 RCV" CODE: ------------------

 

 

It's that simple in HIDmaker FS !

 

 

 

Where you prepare Input Variables

 

In a HIDmaker FS project that has a single USB Interface , the bottom half of the main loop contains code that

  • 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 look, where you should add this code:

 

' --------------- ADD USER "EP1 XMT" CODE HERE: ------------------


' C1 I0

' Add code here to generate data to transmit to PC via Endpoint 1 In

' This code should:

' set flag EP1XmtDataReady = TRUE if there is new data to send out, or

' set flag EP1XmtDataReady = FALSE if data has NOT changed


' USB Advisor: This is where you add code to generate data that gets

' send to the PC over the USB. Use the variables you defined in HIDmaker's

' Visual Data Designer . Variables having the correct names and convenient

' sizes (e.g. word, byte, bit) have been allocated for your use.

' Here is an example:

'

' The following lines provide real I/O for a PicProto USB board

' ADCIN 0, POT1 ' Read the pots

' ADCIN 1, POT2

' Button1 = ~ realButton1 ' Read the buttons (pullup R, so invert)

' Button2 = ~ realButton2




' Test values for EP1 In (In to PC host):

In9bit = TEST_IN9BIT

In16bitArray[0] = TEST_IN16BITARRAY_0

In16bitArray[1] = TEST_IN16BITARRAY_1

In16bitArray[2] = TEST_IN16BITARRAY_2

In16bitArray[3] = TEST_IN16BITARRAY_3

In16bitArray[4] = TEST_IN16BITARRAY_4

In16bitArray[5] = TEST_IN16BITARRAY_5

In16bitArray[6] = TEST_IN16BITARRAY_6

In16bitArray[7] = TEST_IN16BITARRAY_7

In16bitArray[8] = TEST_IN16BITARRAY_8

In16bitArray[9] = TEST_IN16BITARRAY_9

In16bitArray[10] = TEST_IN16BITARRAY_10

In16bitArray[11] = TEST_IN16BITARRAY_11

In16bitArray[12] = TEST_IN16BITARRAY_12

In16bitArray[13] = TEST_IN16BITARRAY_13

In16bitArray[14] = TEST_IN16BITARRAY_14

In13bit = TEST_IN13BIT

In8bit = TEST_IN8BIT

In5bit = TEST_IN5BIT

In8bitArray[0] = TEST_IN8BITARRAY_0

In8bitArray[1] = TEST_IN8BITARRAY_1

In8bitArray[2] = TEST_IN8BITARRAY_2

In8bitArray[3] = TEST_IN8BITARRAY_3


' etc . . .


In8bitArray[59] = TEST_IN8BITARRAY_59

In8bitArray[60] = TEST_IN8BITARRAY_60

In8bitArray[61] = TEST_IN8BITARRAY_61

In8bitArray[62] = TEST_IN8BITARRAY_62


EP1XmtDataReady = TRUE


' --------------- END USER "EP1 XMT" 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

 

 

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:

 

 

' --------------- ADD USER "EP1 XMT" CODE HERE: ------------------


' C1 I0

' Add code here to generate data to transmit to PC via Endpoint 1 In

' This code should:

' set flag EP1XmtDataReady = TRUE if there is new data to send out, or

' set flag EP1XmtDataReady = FALSE if data has NOT changed


' USB Advisor: This is where you add code to generate data that gets

' send to the PC over the USB. Use the variables you defined in HIDmaker's

' Visual Data Designer . Variables having the correct names and convenient

' sizes (e.g. word, byte, bit) have been allocated for your use.

' Here is an example:

'

' The following lines provide real I/O for a PicProto USB board

' ADCIN 0, POT1 ' Read the pots

' ADCIN 1, POT2

' Button1 = ~ realButton1 ' Read the buttons (pullup R, so invert)

' Button2 = ~ realButton2


ADCIN 0, POT1 ' Read the pot on YOUR board

Button1 = ~ realButton1 ' Read the buttons on YOUR board (pullup R, so invert)


EP1XmtDataReady = TRUE


' --------------- END USER "EP1 XMT" CODE ------------------

 

 

 

Feature Reports

 

USB Human Interface Device (or 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

 

In HIDmaker FS , you set the direction of each data item (Input, Output, or Feature) when you define the data item in the HIDmaker's Visual Data Designer .

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 FS 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.