I have been using a K8055 USB demo board converted to use a PIC18F flash programmable device with firmware written using Micrchip’s C18 compiler and their USB framework. As there has been some inteset in this I will publish the details in this thread. Hopefully other people will contribute to this project as well. I need to tidy up the firmware a little before I release it but I will start with the details of how the HID protocol is used by the K8055 - please note that this information was not supplied by Velleman and may contain errors.
I have exported my notes to an html file here:
I think I am half way there.
… (forget all the rest I wrote earlier in case you read it).
Looking at the bootloader code, I see that I need my own io_cfg.h, matching how the K8055 actually uses the ports. Well, that is going to be fun …
Update:
I now have a PIC18F2550 running with a 20 MHz xtal. I modified the “HID Bootloader PIC18 Non J” project slightly so that it uses Jumper SK6 to determine if to run the HID Bootloader or jump into the “firmware application”. Since I compiled it with the free “C18 lite” compiler, I had to move the application start address from 0x1000 to 0x1100. It probably should check for both jumpers (SK5 and SK6) being removed to activate the bootloader. That way it only sacrifices the 4th board.
Anyhow, I created a trivial “firmware”, that simply lets LED1 blink. When SK6 is removed during power up of the K8055, I can flash that “firmware” into the PIC with HIDBootloader(Windows).exe and when SK6 is in place, LED1 blinks. So I have a working hardware conversion and a working HID bootloader.
That was easy!
[size=150]Do not follow these instructions any longer![/size]
Since this was posted, we made significant progress on the K8055 Open Source project. We have fully functioning firmware and there have been changes to the bootloader as well. Some of the links in this post will no longer work.
Please visit jannicash.info/k8055 for the current work in progress.
J_Holland,
in the meantime I have been looking into writing some K8055 compatibility firmware for this project. Mainly to get familiar with all the PIC functionality. Working off the HID Custom Demo code, I have something that can report the digital inputs and sets the digital outputs with the original K8055 protocol. So the rest is just figuring out the analog and debounce parts.
About that debounce value, I was thinking that the algorithm in the PIC, that turns that 0…255 back into 0…7450ms, must be rather simple code, not based on any exponential function at all, and the Velleman DLL code is a rather imprecise approximation of that algorithm’s reversal.
Using
milliseconds = val * (val / 9 + 1);
with integers is getting suspiciously close to your lookup table. And people (like the libk8055 developers) have claimed for a long time that the DLL doesn’t get it right.
I wondered if there was a simpler equation, I wonder why they would choose equation, I think that if I had done this I would have used a log function. The counter is the function that I haven’t so far implemented, think that it needs to be done using a timer overflowing at, say, 0.5ms and incrementing the counter either in an interrupt or by polling. An interupt would be preffereable but some thought would need to go into determining the interrupt latency.
If you send me an email I will send you the firmware that I am currently running.
james dot holland at rhinopower dot org
James,
eMail will be on its way shortly.
Since the demo code I was working from (the HID Custom Device) uses USB_INTERRUPT, using a timer interrupt seemed natural.
I used Timer2 configured for internal clock, which I believe is always 12 MHz if the PLL is configured properly for the crystal used. If I understand it right, then for a 16 MHz crystal you are using a divider of 4 to get to the 4 MHz input of the PLL, and I am using 5 with my 20 MHz crystal.
To be as fast as possible, the interrupt handler only adds 0x48 to TMR1L and 0xF4 to TMR1H, then increments a volatile char and clears TMR1IF. 0xF448 is 65536 - 3000, which at 12 MHz means the interrupt handler is called every 0.25 ms. The mainloop then does
while (ticker > 0) {ticker–; }
That way the debounce counters are unsigned ints that are set to debouncetime x 4 when the input port status changes and the mainloop counts them down according to the ticker. This method seems pretty accurate. I will have to study the resulting assembler code to be sure no ticks can be missed, but for now it’s good enough.
I turned on IPEN and the timer interrupt is using low priority. I read somewhere that under C18, using function calls inside of interrupt handlers causes very expensive context saving to happen and the USB framework is called from inside the high priority handler already.
Anyhow, as of right now I have a fully functioning K8055 board again. I am not sure if I did the PWM configuration correct. I don’t have a scope, so I don’t know if the PWM frequency is right. However, all inputs and outputs plus the two counters and their debounce time work.
The only thing missing at this point is being able to control the board address from 0 to 2 with the jumpers (3 is activating the HID bootloader). But stuff like that can certainly wait until after we merged our code.
Had a glimpse over the generated assembly code and it looks we are in the clear. The C code
TMR1L += 0x48;
TMR1H += 0xF4;
results in the assembly code
85( 263): movlw 72
86( 263): addwf TMR1L, 1, 0
87( 264): movlw 244
88( 264): addwf TMR1H, 1, 0
Unless it can take more than 72 cycles after Timer2 raised the interrupt to get to that code, this looks overflow safe to me.
Likewise the ticker increments/decrements result in INCF/DECF operations, so there should be no problems of missing ticks there either.
I need some ideas and I would appreciate any input.
First some good news though. We succeeded in building a firmware that fully emulates the behavior of the original K8055 (except for card address selection). It gets loaded with the K8055_PIC18F2550_Bootloader. All digital and analog inputs and outputs function, including the two counters and their debounce configuration.
One thing I was thinking about adding to it is I2C communication. There are ton’s of neat sensor modules on the market, that use that bus. GPS, compass, accelerometer, ultrasound distance measuring … you name it.
The C18 libraries have ready to use I2C functionality. All they need are 2 IO ports that can be used both ways. Unfortunately the K8055 uses all ports strictly as either input, or output. I would not like to do many more hardware modifications to the board because I assume so far that what I have should be largely compatible with the “coming soon” K8055N. Being able to run right off the bat on the new K8055N is of course a big priority and it is not a good idea to require people to modify their latest toy right away.
There are however two ports that I believe are tremendously underutilized. These are the ones that are connected to the jumpers sk5 and sk6 for selecting the card address. If my analysis is correct so far, those four jumper pins could be exactly the two IO ports and GND required to implement I2C. So it may be possible to add I2C communication without doing any hardware modification and without even using any of the normal inputs and outputs. Sounds good, doesn’t it?
Well, here is the dilemma. The bootloader code uses these inputs to determine if it should enter bootloading mode or if it should activate the loaded firmware. So if we were to use those ports, we need another way to signal the bootloader to activate.
Any ideas to solve this dilemma?
[quote=“MostlyHarmless”]
First some good news though. We succeeded in building a firmware that fully emulates the behavior of the original K8055 (except for card address selection). Any ideas to solve this dilemma?[/quote]
I’m pretty sure that the card address selection should be done by the driver, on the firmware that I sent you the card address is returned by the K8055 and was functional with the original Velleman DLL.
I will have a think about the I2C, it may be possible to implement it by using three pins and connecting an output back to an input, obviously the library code would need to be modified or new code written.
Looking at the schematic I think that it may be posible to run a low speed I2C connection, by using three connections instead of two. Any of the digital outputs could be used for the clock and a PWM output could be used to drive the I2C data line, that output would then be connected to one of the digital inputs to monitor comms from the peripheral device. The reson that I state low speed is becaue the digital inputs have two 10k resistors which would act as a single 20k pull up to 5V, this is quite a large value for I2C and is likely to slow the rise and fall times on the signal.
The card select jumpers could be used but that would limit the functionality of the board.
[quote=“J_Holland”][quote=“MostlyHarmless”]
First some good news though. We succeeded in building a firmware that fully emulates the behavior of the original K8055 (except for card address selection). Any ideas to solve this dilemma?[/quote]
I’m pretty sure that the card address selection should be done by the driver, on the firmware that I sent you the card address is returned by the K8055 and was functional with the original Velleman DLL.[/quote]
Agreed. I believe only very few people are using multiple cards at the same time (speak up everyone if that isn’t the case). Programming that address with the firmware itself is reasonable with HID available.
[quote=“J_Holland”]Looking at the schematic I think that it may be posible to run a low speed I2C connection, by using three connections instead of two. Any of the digital outputs could be used for the clock and a PWM output could be used to drive the I2C data line, that output would then be connected to one of the digital inputs to monitor comms from the peripheral device. The reson that I state low speed is becaue the digital inputs have two 10k resistors which would act as a single 20k pull up to 5V, this is quite a large value for I2C and is likely to slow the rise and fall times on the signal.
The card select jumpers could be used but that would limit the functionality of the board.[/quote]
With the card address fixed in the firmware at compile time, the pins RA2, RA3 are basically unused.
Also, using a digital output as clock makes it impossible to detect slave clock stretching.
Maybe this could work:
Under normal circumstances, SCL and SDA of an idle I2C bus are pulled high. In our case, the 47K pull up resistors on RA2 and RA3 would do the same when disconnected. So connected to an idle I2C bus or disconnected would look the same to us. When an I2C bus is busy, the SCL line is constantly changing. What if we don’t just read the input once on startup, treating it like a switch, but check it in a loop for an entire millisecond? An I2C bus where SCL is pulled low for an entire millisecond would be an awfully slow bus. The only way this can ever happen would be if we are not the (only) master on the bus and another slave uses clock stretching for that long while the K8055 powers up.
That would mean to enter the HID bootloader, one would disconnect the card from the I2C bus (if used) and put the sk5/sk6 jumper in place (whichever is used for SCL). Then connect or reset the card.
I guess that would work, I don’t think that I have any I2C sensors to play with, only SEEPROMs.
I think we should publish the current version of the software before we add the ‘extras’ to baseline it.
Agreed. I just try to avoid having obstacles for the most likely extras in that baseline.
Hi J_Holland
I’m interested in your code for 18f2550, can you send me?
thanks
FYI: After setting up that repository I stumbled across some important information.
The new K8055N board apparently ships with a PIC18F24J50, not the 2550. They are slightly different, but it may be possible to support both chip families. I therefore renamed the repository to k8055-pic18f in order to not cement a particular chip into the name.
The microchip application library should support both devices so it should just be a case of rebuilding the firmware.
MAL has different source directories for the 46J50 and non-J family bootloaders. It may be necessary to add a second bootloader to the project. That won’t bother me. I only hope that the firmware can be kept compatible with both families without causing major headaches.
I have created a snapshot of binaries and a source code zip archive for easy download.