This document is a Work In Progress, it is intended that it will describe how to upgrade the Velleman K8055 USB demo board to use an 18F2550 FS USB device with the Microchip HID bootloader built in. The PIC firmware is created using the C18 compiler and the Microchip USB library, the firmware can be built to use Microchip USB Bootloader.
TB095 Modifying the PICDEMTM USB Board for PIC18 Full-Speed USB Microcontrollers (note that I used a 16MHz crystal rather than a 20MHz)
MCHPFSUSB Library Help - Getting Started: Using the “USB Device – Bootloaders”
Pin |
Port |
Function |
Pin |
Port |
Function |
1 |
MCLR |
- |
15 |
RB7/PGD |
D8 |
2 |
RA0/AN0 |
A1 |
16 |
RB6/PGC |
D7 |
3 |
RA1/AN1 |
A2 |
17 |
RB5/PGM |
D6 |
4 |
RA2/AN2 |
ADDR0 |
18 |
RB4/AN11 |
D5 |
5 |
RA3/AN3 |
ADDR1 |
19 |
RB3 |
D4 |
6 |
RA4/T0CK1 |
I1 |
20 |
RB2 |
D3 |
7 |
RA5/AN4 |
I2 |
21 |
RB1 |
D2 |
8 |
VSS |
- |
22 |
RB0 |
D1 |
9 |
OSC1 |
- |
23 |
VDD |
- |
10 |
OSC2 |
- |
24 |
VSS1 |
- |
11 |
RC0 |
I3 |
25 |
RC7 |
I4 |
12 |
RC1/CCP2 |
PWM2/DAC2 |
26 |
RC6 |
I5 |
13 |
RC2/CCP1 |
PWM1/DAC1 |
27 |
D+ |
- |
14 |
Vusb |
- |
28 |
D- |
- |
Initialisation
RA0, RA1 = Analogue In
RA5..2 = Digital In
RB7..0 = All outputs
RC7, 6, 0 = Inputs
RC12, 13 = Outputs
PWM2, 1 = 25kHz ??
Timer2, 1 = 2kHz ??
OpenDevice(CardAddress) Opens the communication link to the K8055 device
CloseDevice Closes the link to the K8055 device
ReadAnalogChannel(Channelno) Reads the status of one analogue input-channel
ReadAllAnalog(Data1, Data2) Reads the status of both analogue input-channels
OutputAnalogChannel(Channel,Data) Sets the analogue output channel according to the data
OutputAllAnalog(Data1,Data2) Sets both analogue output channels according to the data
ClearAnalogChannel(Channel) Sets the analogue output channel to minimum
ClearAllAnalog Sets all analogue output channels to minimum
SetAnalogChannel(Channel) Sets the analogue output channel to maximum
SetAllAnalog Sets all analogue output channels to maximum
WriteAllDigital(Data) Sets the digital outputs according to the data
ClearDigitalChannel(Channel) Clears the output channel
ClearAllDigital Clears all output channels
SetDigitalChannel(Channel) Sets the output channel
SetAllDigital Sets all output channels
ReadDigitalChannel(Channel) Reads the status of the input channel
ReadAllDigital(Buffer) Reads the status of all the input channels
ResetCounter(CounterNr) Resets the 16 bit pulse counter number 1 or counter number 2
ReadCounter(CounterNr) Reads the content of the pulse counter number 1or counter number 2
SetCounterDebounceTime
(CounterNr, DebounceTime) Sets the debounce time to the pulse counter
The HID message contains one 8-byte report.
The K8055 transmits its status continually on a 10ms tick.
The PC sends a command message only when a change of status is required.
Byte |
Description |
0 |
Digital Input Flags (see bit descriptions below) |
1 |
Card Address |
2 |
ATT1 – Analogue Value |
3 |
ATT2 – Analogue Value |
4 |
Count 1 Low byte |
5 |
Count 1 High Byte |
6 |
Count 2 Low byte |
7 |
Count 2 High Byte |
Bit |
Description |
0 |
INP3 |
1 |
- |
2 |
- |
3 |
- |
4 |
INP1 |
5 |
INP2 |
6 |
INP4 |
7 |
INP5 |
Card Address – Card address is sent as the (card address+1), i.e. card 0 has address 1.
Analogue Value - ATTn is a value 00-FFh
Count –
Count n is a 16-bit value 0000-FFFFh
The TX report uses byte 0 as a header/control byte so there are 256 possible commands. The Velleman firmware utilises the commands 1 to 5 only.
Value |
Name |
Description |
0 |
0x00 |
|
1 |
- |
|
2 |
- |
|
3 |
- |
|
4 |
- |
|
5 |
- |
|
6 |
- |
|
7 |
- |
|
Value |
Name |
Description |
0 |
0x01 |
|
1 |
- |
|
2 |
- |
|
3 |
- |
|
4 |
- |
|
5 |
- |
|
6 |
DBT1 |
|
7 |
- |
|
Value |
Name |
Description |
0 |
0x02 |
|
1 |
- |
|
2 |
- |
|
3 |
- |
|
4 |
- |
|
5 |
- |
|
6 |
- |
|
7 |
DBT2 |
|
Value |
Name |
Description |
0 |
0x03 |
|
1 |
- |
|
2 |
- |
|
3 |
- |
|
4 |
- |
|
5 |
- |
|
6 |
- |
|
7 |
- |
|
Value |
Name |
Description |
0 |
0x04 |
|
1 |
- |
|
2 |
- |
|
3 |
- |
|
4 |
- |
|
5 |
- |
|
6 |
- |
|
7 |
- |
|
Value |
Name |
Description |
0 |
0x05 |
|
1 |
DOUT |
|
2 |
PWM1 |
|
3 |
PWM2 |
|
4 |
- |
|
5 |
- |
|
6 |
- |
|
7 |
- |
|
Byte |
Name |
Description |
0 |
0x6 |
Header |
1 |
DOUT |
Digital Outputs |
2 |
OC1ONH |
Output Compare 1 on period high byte |
3 |
OC1ONL |
Output Compare 1 on period low byte |
4 |
OC1OFFH |
Output Compare 1 off period high byte |
5 |
OC1OFFL |
Output Compare 1 off period low byte |
6 |
- |
|
7 |
- |
|
Byte |
Name |
Description |
0 |
0x6 |
Header |
1 |
DOUT |
Digital Outputs |
2 |
OC2ONH |
Output Compare 2 on period high byte |
3 |
OC2ONL |
Output Compare 2 on period low byte |
4 |
OC2OFFH |
Output Compare 2 off period high byte |
5 |
OC2OFFL |
Output Compare 2 off period low byte |
6 |
- |
|
7 |
- |
|
The USB configuration data in the Microchip USB framework (usb_descriptors_jh.c) must be modified so the K8055 board is correctly enumerated by the PC. The data below is a data capture taken using the USBLyzer software USB protocol analyser. To use the PIC18Fs additional performance capability bcdUSB should be set to 0200h (High Speed) and the interval (defined in reduced from 10ms to 1ms.
Connection Status |
Device connected |
Current Configuration |
1 |
Speed |
Low (1.5 Mbit/s) |
Device Address |
9 |
Number Of Open Pipes |
2 |
Offset |
Field |
Size |
Value |
Description |
0 |
bLength |
1 |
12h |
|
1 |
bDescriptorType |
1 |
01h |
Device |
2 |
bcdUSB |
2 |
0110h |
USB Spec 1.1 |
4 |
bDeviceClass |
1 |
00h |
Class info in Ifc Descriptors |
5 |
bDeviceSubClass |
1 |
00h |
|
6 |
bDeviceProtocol |
1 |
00h |
|
7 |
bMaxPacketSize0 |
1 |
08h |
8 bytes |
8 |
idVendor |
2 |
10CFh |
Velleman Components, Inc. |
10 |
idProduct |
2 |
5500h |
|
12 |
bcdDevice |
2 |
0000h |
0.00 |
14 |
iManufacturer |
1 |
01h |
|
15 |
iProduct |
1 |
02h |
|
16 |
iSerialNumber |
1 |
00h |
|
17 |
bNumConfigurations |
1 |
01h |
Interface 0 HID Report Descriptor Vendor-Defined 1
Item Tag (Value) |
Raw Data |
|
|
Usage Page (Vendor-Defined 1) |
06 00 FF |
|
|
Usage (Vendor-Defined 1) |
09 01 |
|
|
Collection (Application) |
A1 01 |
|
|
Usage Minimum (Vendor-Defined 1) |
19 01 |
|
|
Usage Maximum (Vendor-Defined 8) |
29 08 |
|
|
Logical Minimum (0) |
15 00 |
|
|
Logical Maximum (255) |
26 FF 00 |
|
|
Report Size (8) |
75 08 |
|
|
Report Count (8) |
95 08 |
|
|
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) |
81 02 |
|
|
Usage Minimum (Vendor-Defined 1) |
19 01 |
|
|
Usage Maximum (Vendor-Defined 8) |
29 08 |
|
|
Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) |
91 02 |
|
|
End Collection |
C0 |
|
|
|
|||
Modifications to Microchip’s usb_configuration.c
/* Device Descriptor */
ROM USB_DEVICE_DESCRIPTOR device_dsc=
{
0x12, // Size of this descriptor in bytes
USB_DESCRIPTOR_DEVICE, // DEVICE descriptor type
0x0200, // USB Spec Release Number in BCD format
0x03, // Class Code
0x00, // Subclass code
0x00, // Protocol code
USB_EP0_BUFF_SIZE, // Max packet size for EP0, see usb_config.h
0x10CF, // Vendor ID - Vellemen Components, Inc.
0x5500, // Product ID: K8055
0x0000, // Device release number in BCD format
0x01, // Manufacturer string index
0x02, // Product string index
0x00, // Device serial number string index
0x01 // Number of possible configurations
};
/* Configuration 1 Descriptor */
ROM BYTE configDescriptor1[]={
/* Configuration Descriptor */
0x09,//sizeof(USB_CFG_DSC), // Size of this descriptor in bytes
0x02, // CONFIGURATION descriptor type
0x29,0x00, // Total length of data for this cfg
1, // Number of interfaces in this cfg
1, // Index value of this configuration
0, // Configuration string index
0x80, // Bus Powered
50, // Max power consumption (2X mA)
/* Interface Descriptor */
0x09,//sizeof(USB_INTF_DSC), // Size of this descriptor in bytes
0x04, // INTERFACE descriptor type
0, // Interface Number
0, // Alternate Setting Number
2, // Number of endpoints in this intf
HID_INTF, // Class code =0x03
0, // Subclass code
0, // Protocol code
0, // Interface string index
/* HID Class-Specific Descriptor */
0x09,//sizeof(USB_HID_DSC)+3, // Size of this descriptor in bytes
DSC_HID, // HID descriptor type = 21h
0x11,0x01, // HID Spec Release Number in BCD format 1.11
0x00, // Country Code (0x00 for Not supported)
0x01, // Number of class descriptors, see usbcfg.h
DSC_RPT, // Report descriptor type
HID_RPT01_SIZE,0x00, //sizeof(hid_rpt01), 29 bytes // Size of the report descriptor
/* Endpoint Descriptor 81 */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor = 0x05
HID_EP | _EP_IN, //EndpointAddress = 0x01|0x80
_INTERRUPT, //Attributes - Interrupt 0x03
0x08,0x00, //size
0x0A, //Interval
/* Endpoint Descriptor 01 */
0x07,/*sizeof(USB_EP_DSC)*/
USB_DESCRIPTOR_ENDPOINT, //Endpoint Descriptor = 0x05
HID_EP | _EP_OUT, //EndpointAddress = 0x01|0x00
_INTERRUPT, //Attributes - Interrupt 0x03
0x08,0x00, //size
0x0A //Interval
};
We need to count a max. frequency of at least 2kHz (Velleman spec.) so we need to poll at 0.5ms periods minimum.
The Velleman board requires a debounce time so musing the PICs internal timer counter function is not feasible. A simple timer is implemented that uses timer 1 running at ???ms. On counter reset the current value of the timer is loaded into counter_start, on pin change the current timer value is tested, if the debounce time has elapsed then the counter is incremented.
The Velleman DLL gives the equation for the debounce time as:
round(0.9*2.4541*POWER((Time in ms),0.5328))
this presumably is to allow a max. debounce value of well over 255ms whilst maintaining good resolution at low values. Working backwards we can derive a lookup table for this:
Command |
Time(ms) |
0 |
0 |
15 |
37 |
31 |
143 |
47 |
312 |
63 |
541 |
79 |
827 |
95 |
1169 |
111 |
1566 |
127 |
2017 |
143 |
2520 |
159 |
3076 |
175 |
3682 |
191 |
4340 |
207 |
5048 |
223 |
5805 |
239 |
6612 |
255 |
7468 |
These values must be interpolated to get the required value. Its a 16-bit counter so we can count to 65535.
65535/7468 = 8.78 = 15.25us
15.25us/8 = 524590kHz
Set up:
Crystal Frequency = 16MHz, use /4 post-scaler to give bus clock of 4MHz.
Clock period = 25ns so we need to divide by 2000 to get 0.5ms