Using QuickStart Touch Buttons in Tachyon and a Tachyon (5.4) ROM building/usage tutorial
Jeff_Birt
Posts: 25
Introduction
About a week ago I started out trying to figure out how to use the Touch Buttons on the Quickstart board from Tachyon. I started a thread on that subject here: https://forums.parallax.com/discussion/169277/tachyon-v5-4-how-to-include-own-rom#latest . With a lot of help I was able to get the buttons working both in Forth directly and by using a ‘ROM’. Below is a bit of a ‘how to’ which hopefully will be a help to others.
So, you are using Tachyon Forth but have a bit of code that is so timing critical you need to use PASM. How can you do that? Fortunately, Tachyon includes the ability to do this using the ‘LOADROM’ word. The tricky part is understanding how to set up your PASM code to work with Tachyon. While it is not difficult there was not one thread or post or other source, I could find that described the whole process so I’m hoping this little guide will make it easier for other noobs and maybe save a bit of frustration. I am not an expert by any means but thanks to @"Peter Jakacki" and others I was able to figure this out.
I just got started with the Propeller 1 with the QuickStart board so after going through Peter’s introduction to tachyon guide, I thought I would figure out how to use the Touch Buttons on the QS board. The buttons are just closely spaced exposed traces to a buffered I/O pin and ground. The basic idea is that you set the pins output register to HI but set the data direction register (DDR) to an input. Then you toggle the DDR to an output then right back to an input. This puts a slight capacitive charge on these inputs. You wait a short period of time and then read the inputs. Touching the buttons will change the decay rate so you can tell which buttons are being touched.
Fortunately, there is some sample code for this written in Spin and PASM and it is fairly easy to understand thanks to the comments in the code. Below you will see the original touch button driver code (this is also loaded on the EEPROM for the QS board from Parallax). Here is a link to the source files: https://parallax.com/downloads/propeller-quickstart-touch-buttons-led-spin-demo-code
About a week ago I started out trying to figure out how to use the Touch Buttons on the Quickstart board from Tachyon. I started a thread on that subject here: https://forums.parallax.com/discussion/169277/tachyon-v5-4-how-to-include-own-rom#latest . With a lot of help I was able to get the buttons working both in Forth directly and by using a ‘ROM’. Below is a bit of a ‘how to’ which hopefully will be a help to others.
So, you are using Tachyon Forth but have a bit of code that is so timing critical you need to use PASM. How can you do that? Fortunately, Tachyon includes the ability to do this using the ‘LOADROM’ word. The tricky part is understanding how to set up your PASM code to work with Tachyon. While it is not difficult there was not one thread or post or other source, I could find that described the whole process so I’m hoping this little guide will make it easier for other noobs and maybe save a bit of frustration. I am not an expert by any means but thanks to @"Peter Jakacki" and others I was able to figure this out.
I just got started with the Propeller 1 with the QuickStart board so after going through Peter’s introduction to tachyon guide, I thought I would figure out how to use the Touch Buttons on the QS board. The buttons are just closely spaced exposed traces to a buffered I/O pin and ground. The basic idea is that you set the pins output register to HI but set the data direction register (DDR) to an input. Then you toggle the DDR to an output then right back to an input. This puts a slight capacitive charge on these inputs. You wait a short period of time and then read the inputs. Touching the buttons will change the decay rate so you can tell which buttons are being touched.
Fortunately, there is some sample code for this written in Spin and PASM and it is fairly easy to understand thanks to the comments in the code. Below you will see the original touch button driver code (this is also loaded on the EEPROM for the QS board from Parallax). Here is a link to the source files: https://parallax.com/downloads/propeller-quickstart-touch-buttons-led-spin-demo-code
CON BUTTON_PINS = $FF ' The QuickStart's touch buttons are on the eight LSBs SAMPLES = 32 ' Require 32 high readings to return true VAR long Results PUB Start(Rate) Results := Rate cognew(@Entry, @Results) ' Launch a new cog to read samples PUB State | Accumulator Accumulator := Results ' Sample multiple times and return true repeat constant(SAMPLES - 1) ' if every sample was high Accumulator &= Results return Accumulator DAT org Entry rdlong WaitTime, par mov outa, #BUTTON_PINS ' set TestPins high, but keep as inputs mov Wait, cnt ' preset the counter add Wait, WaitTime Loop or dira, #BUTTON_PINS ' set TestPins as outputs (high) andn dira, #BUTTON_PINS ' set TestPins as inputs (floating) mov Reading, #BUTTON_PINS ' create a mask of applicable pins waitcnt Wait, WaitTime ' wait for the voltage to decay andn Reading, ina ' clear decayed pins from the mask wrlong Reading, par ' write the result to RAM jmp #Loop Reading res 1 WaitTime res 1 Wait res 1
Comments
First the Forth Touch Button driver
I tried this basic idea in Forth, but it was too slow, or so I thought. Peter Jakacki, the man who brought us Tachyon, was clever enough to for see the need to twiddle I/O bits quickly, so he added some non-conventional Forth words that are fast as they do not manipulate the stack, i.e. they read the top of the stack but leave it alone. So, before delving into how to do this in a ROM consuming a whole COG let’s see how easy it is to do from Forth itself
The idea is that you pass in the pin-mask, which for the QuickStart board’s Touch Buttons is $FF (the lower 8 bits of INA. We DUP the pin-mask which gives us a proper starting point for an accumulator, i.e. we want to AND together 32 consecutive readings and those which remain HIGH the whole time are considered pressed. The FOR loop gives us our 32 consecutive readings.
The H word is a high-speed way to set the pins DDR to make them outputs and then the F word floats them, that is makes them inputs again. Both H and F do not alter the stack, so they are fast and leave the stack unchanged. We DUP out mask once more to preserve a copy and then wait 1ms before reading the state of the buttons.
The p@ word reads all of INA and the ANDN uses that DUP of the pin-mask we made to mask off all pins but our buttons. The ROT word brings the third stack item to the top, so we go from “ACCUMULATOR PINMASK READING’ to ‘PINMASK READING ACCUMULATOR’. We then AND the ACCUMULATOR and READING and SWAP their positions on the stack so we are ready for the next loop.
The QDEMO word accomplishes the same thing as the original Touch Button demo by lighting up the LED corresponding to the button(s) being touched. Peter suggests that could be run in the background as part of a KEYPOLL event or using the TIMER functionality in Tachyon. I plan to investigate both avenues in the near future.
A Touch Button driver as a Tachyon (5.4) ROM, a tutorial
So, back to doing the same task in a ROM. Note, this is not really the best use of a COG or the ROM functionality Tachyon provides, but it is a simple example and good for a tutorial like this. We can start with the touch button driver that Parallax provides. The link to the source for that is above. We just need to massage it a little to ‘ROM’ify it. The basic idea is that we need to add some a header so that Tachyon has some vital information it will need when loading it. We also need to set up a way to pass data between our Forth code and the PASM code in our ROM running in its own COG.
Peter has some information about ROMs (readme.txt) and samples here: https://dropbox.com/sh/yzrczasnorqp5i9/AAB_-bt2o_Z2CUoUKwzPUkfla/V5/ROMS?dl=0&subfolder_nav_tracking=1
We have a few constants declared up top for out pin mask and number of samples. The ‘PUB Start’ is required by Propeller IDE to properly compile the code. The header that Tachyon’s LOADROM word needs in after ‘DAT’ and between ‘org’ and ‘org 0’. This provides a signature to tell Tachyon this is a ROM, the length of the code by using a couple of labels and ‘word @TOUCHBTNend-@TOUCHBTN’, and the ROM name which must be exactly 10 characters long so pad it with trailing spaces if need be.
I won’t go through this code line by line, it is only slightly modified from the original demo code but combines the accumulation of 32 samples into the main loop and provides the result via a HUB RAM variable. For this simple example we only need one LONG variable in HUB RAM. We can use it to supply the scanning delay period since that is only needed at initialization, we can also use that same variable to allow the driver code to send the current keypress data back to HUB RAM.
Now that we have our PASM code with the needed header in place we can compile it with the Propeller IDE or your tool of choice. Then we need to convert it to the Intel HEX format that Tachyon expects, don’t worry it is fairly painless. In Peter’s drop box folder on ROMs linked to above there is a little Python file called ‘bh.py’ that will do this for us. The command is: python bh.py --binaries=0, TOUCHBTN.binary using our touch button program as an example.
Now that we have the HEX file, we need to open it in a TEXT EDITOR (not a word processor) and add a line to the top that says, ‘SAVEROM, as shown below. Save the file and now we are ready to load this ROM up in Tachyon.
The LOADCOG functionality in Tachyon is taking care of starting this code running in the COG we specify, we just have to give it the information it needs. An example for our little touch button driver is:
The ‘80,000’ is the clock frequency divided by 100 and is our button read delay we pass to the driver. To ask Tachyon to load this ROM for us we give it the name (without file type extension), remember it must be 10 characters so pad with trailing spaces if needed, the leading space is a Forth delimiter and not part of the filename. The ‘3’ is the COG to start in (3-7 are usually available in Tachyon, ‘touches’ is our shared HUB RAM variable of course and LOADCOG is what we want Tachyon to do. Now with all that out of the way we can just ask Tachyon to show us the current keypress data stored in ‘touches’ with ‘touches @ .’ .
Again, this is not a great use of a whole COG, but it is a fairly simple demonstration of the process or building and loading a ROM into Tachyon. If you have more than one variable to pass you can use a structure and pass the starting address of the structure. Also, I’m still a newbie at all of this and while I tried to present accurate information here, I’m sure I made an error or two. If you seen something that looks to be incorrect just shout it out and we’ll get to the bottom of it.