Chapter 1 – The concept and initial execution


Tools I used:
-Microchip’s PICDEM FS USB demo board (newer model with 18F4550, and a USB A-to-B cable)
-Microchip’s MPLAB ICD 2 (with power supply, USB A-to-B cable and phone-jack-like ICD cable)
-full version of Proton’s IDE
-the Proton forums (the most essential ingredient)
-a great deal of time and gumption

I bought PICBASIC with the intent of making some USB peripherals for my personal use, and potentially to develop into commercial products. I have decades of BASIC experience, mostly from antiques like TRS-80, PET, C64 and so on, so I understand the general theory of programming in BASIC fairly well but I knew that PICBASIC would require a modest re-learning of programming techniques. I had little trouble creating some simple apps for the 16F628A (in the free version of Proton), and I had read about the USB support so I figured I would go for it and buy the full package. A couple of stupid n00b questions I had were answered quickly and knowledgeable by members of the Proton forum community, so I felt especially good about the future of my newly purchased dev system. As it turns out, USB just about stopped me dead in my tracks, and in researching the subject I felt that there was no where near enough information to successfully allow the averaged n00b to ever hope to make their device work on a USB computer. Since I know that people HAVE used PICBASIC to make USB peripherals, I know that it is just a question of gathering the needed information and skill, so I figured I might as well try to document it and save future n00bz the pain.

The ultimate intent of this tutorial is to give you a better grasp of setting up and using USB on the PIC 18F4550 as implemented on the PICDEM FS USB board. This tutorial will be lacking in an area many people may find key, and that is the USB desktop software side of things. Sorry, I don’t care. I am not a software programmer, and all I wish to know about USB communication is how to push and pull data on the bus. There will be very little desktop code discussion here, although I will be detailing my efforts to get my hardware recognized by an experienced desktop programmer I work with, who has graciously volunteered to help me get my hardware “compliant” so that any decent programmer can access it.

A visual scan of the PICDEM FS USB board shows there is a 20MHz crystal onboard, but the info I have seen for USB PICs seemed to indicate you had to use either a 6MHz or 48MHz clock in order to talk to the USB bus. Since the PICDEM board DOES talk to the USB bus I assumed there was some trickery going on with clock multipliers, and a perusal of the ‘4550 data sheet seemed to indicate that there was a standard setting for this combination of clock and multiplier. I think I found some reference on a PICBASIC forum that said the default CONFIG options for the ‘4550 in PICBASIC would give me the right multiplier, so I decided to just try it and see what happens.

Rather than dive right in to USB, which I am totally unfamiliar with, I decided to verify that I had control of the board with these default clock settings. I reasoned that if I could get an LED blinker to work it would prove I was set up correctly. There are several accessible LEDs on the PICDEM FS board, so all I had to do was figure out which one was likely to give me the least trouble due to unforeseen complexities (like trying to use PORTA.4 on a 16F628A without using a pullup). I traced the schematic of the PICDEM board and decided that PORTD.2 and PORTD.3 were likely to behave as expected, so I wrote a short “LED_port = 0 : DelayMS 500 : LED_port = 1” kind of test loop. It didn’t work. This was nigh-inconceivable to me. After some dicking around I decided to explicitly set up the ports with a ALL_DIGITAL = 1 and TRISD = %00000000, and suddenly it all worked. A new lesson to me: never, EVER assume the ports are set the way you want them. SET THEM. So, my hard work to this point got me a PICDEM FS USB board that blinked two LEDs, pretty much proving the basic setup was correct. The interesting thing to me was that even though the board was plugged in to a USB port and was receiving bus power to drive my test, it was not enumerating on the PC. Not even an error, which is what I expected. I wasn’t concerned at all, since I knew I was not using ANY USB commands yet, and therefore I probably wasn’t even enabling the USB bus in the PIC. Just for chuckles I tried messing with the XTAL declare, changing it from 20 to 6 or 48, and as expected this did not work. I feel confident that these current CONFIG settings will work, although I am not at all comfortable not having any idea what those settings are. The 16F628A was easy to figure out, but this will take much more reading and comparing to known examples. I did mess around with the XTAL declare a little, but since the clock on the board is 20MHz and XTAL = 20 does allow the LED blinky to work I guess it is all ready to go. So, it must be time to “turn on” the USB.

EasyHID is a plugin that comes with Proton’s suite, and purports to make it easy on a developer by asking some basic configuration questions and creating two directories of code, one for VB and one for PICBASIC, that are tailored to your desired configuration. Since I have a passing familiarity with how USB works, and since the PICBASIC commands for USBIN and USBOUT seemed so straightforward I figured I didn’t really need it, and I should learn how to do it from scratch. Heh. Riiiiiiiight. After beating my head against the wall for a few days, and noticing that most of the people on the Proton forums appeared to be using EasyHID, I decided to try it. So, I selected EasyHID from the Proton IDE and started in. I had a lot of trouble getting the EasyHID plugin to create a framework for me. It would get to the stage where it would compile all the data it asked you for and then die, with a big nasty red stoplight indicating it didn’t work. I did upgrade from the free Proton suite to the standard pay version, so perhaps there are some path variables or reg keys that are hosed and/or pointing to the wrong places? I downloaded the standalone version of EasyHID, let it install where it wanted to go, and ran it. I was able to get all the way through the wizard and generate the two code directories, one for VB and one for PICBASIC. While I intend eventually to figure out how to better integrate EasyHID into the development system I don’t need to worry about it right now since I can finally use it to generate code. The PICBASIC code generated by EasyHID compiled as-is, which I took as a good sign. The code generated is well-commented and appears to implement everything you need for USB I/O. It seems the code generated is a bit generic, perhaps more targeted to the 745/765 than the 18F parts, and appeared to include stuff I didn’t need (like USBInit stuff, supposedly not needed for 18F parts but required by the 745/765). I trimmed back all the code I thought I didn’t need, recompiled, and it still didn’t generate errors so I assumed the stuff I removed was no longer needed. At this point I tried to code up a really simple “put a particular byte on the USB bus, have the PIC read it, and set the appropriate LED” test, but I kept hitting a syntax error that made no sense to me.

EasyHID had defined data to be pulled off or put on the bus as a variable called “USBBuffer”, which was easy to spot in their code. I tried a really simple comparison I though would work, “IF USBBuffer = 16 Then LED_port = 1”, which was supposed to light an LED when decimal 16 was placed on the USB bus, but this always caused the compiler to complain about a syntax error in that line. I moved the line around and error followed it. And still it would not show up on a USB bus, not even an error. I put out a call for help on the Proton forums, and while pondering the problem I stumbled into the solution, which was confirmed a couple hours later when someone responded to my problem with an answer much like the one I had guessed at! I noticed in the EasyHID code that USBBuffer was not actually declared “as such”, but instead as “Dim USBBuffer [USBBufferSizeMax] As Byte”, and I also noticed that “USBBufferSizeMax" was looked like it was defined as a byte (Symbol USBBufferSizeMax = 8)… so perhaps that meant I had to ASK for the specific byte I wanted! So, a quick change of my code to “If USBBuffer[1] = 16” would compile with no syntax error! Now the PICDEM board showed up on the USB bus!! Unfortunately, it showed up as the long-predicted “unknown device”, but at least it was there! Good thing I do this under Windows, because plugging it into a Mac yielded no obvious response, and the device was not shown in the Apple System Profiler. This would have been more than a little discouraging, so I am lucky that Windows acts the way it does.

I figured that since I appeared to have SOME form of functional code I would see if I could hand the board over to an experienced desktop software programmer I work with, to see if he could control the LEDs I theoretically set up. I assume that what he needs to know is my VID/PID and which endpoint I think I am using, and he should be able to place a byte on the endpoint and have it magically read by the PIC. Unfortunately, since I could not find a VID/PID on either Macs or PCs so I believe I have some more work to do, something that may not be obvious to me yet. I also may have issues getting it to run with Macs in general, as I think I stumbled across a forum posting somewhere that indicated that a guy couldn’t get his PC-recognized board to enumerate on a Mac, and he has to do something special to enable it. Of course, I didn’t bookmark it or save the info. :( Since I thought it was EasyHID’s job to set the chip up with a VID/PID I decided to look at the EasyHID project files, to see if I could see the spot the VID and PID were configured. Because of my earlier problems getting the EasyHID plugin to work I elected to use ALL default values in the standalone’s setup wizard, and I THINK I see where they are in the EasyHID files, so I cannot figure out why the board “shows up” on Windows with no VID/PID (and doesn’t show up at all on a Mac).

LAST MINUTE ADDENDUM: Just as I was getting ready to quit screwing with it for the day I got an idea. It looked like the EasyHID framework wanted to declare my XTAL as 48, but my tests at 20MHz of an LED blinky "proved" it worked. I knew that USB comms required 48MHz, but I believed that was accomplished internally by specifying the right multiplier on a 20MHz clock, which I believed the default config setup for the '4550 happend to be set up this way. Well, NO! I changed the XTAL from 20 to 48 in the code I had been fighting with for days, and suddenly it showed up with a VID/PID! I could run a full descriptor report! w00t!

I took the theoretically-working dev board to one of the programmers at the company I work for, complete with my descriptor reports and a copy of my PICBASIC source (in case he had questions about my methodology). He agreed to smack it around a little, and created a custom piece of software that would theoretically allow me to put some data on the bus, which would in turn theoretically light an LED on the dev board. When I came out of a meeting at work he had already stabbed at it repeatedly and created the app to try to talk to it. Nothing works YET, but it sure seems promising.





And now, the meat of it, the latest version of the PICBASIC code. Experienced users are encouraged to laugh at my pathetic attempts and totally 0wn me by providing substantially better solutions, which I will integrate into future chapters.

Device = 18F4550
XTAL = 48   ;not 20 as I thought AND tested, 20 likely means CORE speed only while 48 is USB
USB_DESCRIPTOR = "USBProjectDESC.inc"
ALL_DIGITAL = true
TRISD =%00000000    'set PORTD to outputs
PORTD = 0

Symbol LED_3 PORTD.2
Symbol LED_4 PORTD.3

' USB Buffer...
Symbol USBBufferSizeMax = 8
Symbol USBBufferSizeTX  = 8
Symbol USBBufferSizeRX  = 8
Dim    USBBuffer[USBBufferSizeMax] As Byte

' some useful flags...
Dim PP0 As Byte SYSTEM        ' USBPOLL status return
Symbol CARRY_FLAG = STATUS.0  ' high if microcontroller does not have control over the buffer
Symbol ATTACHED_STATE = 6     ' is USB attached

PORTD.3 = 0 : DelayMS 500 : PORTD.3 = 1 : DelayMS 500 : PORTD.3 = 0
PORTD.2 = 0 : DelayMS 500 : PORTD.2 = 1 : DelayMS 500 : PORTD.2 = 0
     
' ************************************************************
' * main program loop - remember, you must keep the USB      *
' * connection alive with a call to USBPoll, USBIn or USBOut *
' * every couple of milliseconds or so                       *
' ************************************************************
GoSub AttachToUSB

ProgramLoop:
   GoSub DoUSBIn
   GoSub DoUSBOut
   GoTo ProgramLoop

If USBBuffer[0] = 16 Then LED_3 = 1
;Else LEDByte = 32 Then LED_3 = 1
;endif
;ElseIf LEDByte = 64 Then LED_4 = 0
;ElseIf LEDByte = 128 Then LED_4 = 1

GoTo ProgramLoop   
   
;Stop   
  
' ************************************************************
' * receive data from the USB bus                            *
' ************************************************************
DoUSBIn:
   USBIn 1, USBBuffer, USBBufferSizeRX, DoUSBIn
   Return
' ************************************************************
' * transmit data                                            *
' ************************************************************
DoUSBOut:   
   USBOut 1, USBBuffer, USBBufferSizeTX, DoUSBOut
   Return
' ************************************************************
' * wait for USB interface to attach                         *
' ************************************************************
AttachToUSB:
   Repeat								
      USBPoll		
   Until PP0 = ATTACHED_STATE
   Return	
   






Back to the PICBASIC USB tutorial TOC

 
L10 Web Stats Reporter 3.15 LevelTen Hit Counter - Free PHP Web Analytics Script
LevelTen dallas web development firm - website design, flash, graphics & marketing