Adventures in Spin
cavelamb
Posts: 720
In our last episode we (and I mean plural there!) got the buttons working
on my QuickStart board. Thank you kindly, neighbors.
This thing begs to be my first adventure in parallelism.
Load that puppy into another cog and let it buck!
Then anybody that wants to see if buttons are happening need only asks nicely.
But no.
I'm not having much getting this to work.
I've studied several of the objects from the exchange and read the book.
Tried a bunch of wrong ways.
But I haven't stumbled blindly on a right way yet.
Both of these have been debugged in terms of single cog methodology,
and work correctly.
But what do they need to succeed in parallel land?
[ugly code removed to save room]
on my QuickStart board. Thank you kindly, neighbors.
This thing begs to be my first adventure in parallelism.
Load that puppy into another cog and let it buck!
Then anybody that wants to see if buttons are happening need only asks nicely.
But no.
I'm not having much getting this to work.
I've studied several of the objects from the exchange and read the book.
Tried a bunch of wrong ways.
But I haven't stumbled blindly on a right way yet.
Both of these have been debugged in terms of single cog methodology,
and work correctly.
But what do they need to succeed in parallel land?
[ugly code removed to save room]
Comments
There is also some potential for optimizing this code. You can easily get rid of the whole inner repeat-loop because you have 8 bit input and 8 bit output. Do you want to try yourself?
Let me know if you have any problems running/compiling the code - what I posted is not tested, as I don't have my Prop Tool at hand.
Without separating the compiler will really create 2 copies of this function in your executable. When you put it in a SPIN-file of it's own and use this SPIN-file in each place where it's needed, there will only be one copy in the executable.
But I think you should try this by yourself as an excerzise as well ;o)
You set me on the straight and narrow path.
I appreciate that. Maybe it will help someone get started else as well?
I still had a few minor issues to work out.
One was that for some fool reason I was trying to use CogID as a variable.
That didn't work very well (well duh!)
After it was up and running I went though it and did a bit of housekeeping,
so there are a lot of name changes to make it read better (at least to my eye).
TP for touchpads? In 6 months will I remember what the heck that's about?
So it's Buttons now. Keep it simple...
The bit manipulation suggestion was timely.
That was going to be my very next concern.
And, since you brought it up...
There are only 8 buttons, so why take up a whole long?
Sure, it's an improvement over an 8 byte array, but longs are rare and precious...
So I tried this:
BYTE[Buttons] |= |< B ' bit set Bth bit = 1
which compiled and ran fine.
But was that because of the BYTE specifier? over ride?
Or just because I was only dinking with 8 bits?
Would it have happily written the higher bits if B said to?
I'll start trying to puzzle out how to break out the common code.
save the longs!
Anyway, sharing the current state of the art...
the Demo:
and the scanner:
[edit] corrected Buttons to WORD for proper address alignment (Per Mr. K)
I did get this part working.
It is in a file named QS_Util.spin
In the Demo.spin file I added:
OBJ util:"QS_Utilities"
So I can call that method with util.WaitMS(milliseconds).
The burr under my saddle is that I haven't figured out how to initialize MS001 in the utility file.
Even including the CONstant section and adding MS001 := ClkFreq/1000 to a start.util method didn't help.
It does work if hard coded... but that's not exactly elegant, is it...
Anybody have a page reference in the manual where this kind of stuff is discussed?
.
Corrected that...
Thank you.
Same problem you have in Button_Scanner.spin!
If you want to make the variable names speak more for themselves, you should consider to rename Buttons in Button_Scanner.spin to ButtonsAdr. Oh ... and Buttons in Button_Demo.spin can live with just one byte. It's only ButtonsAdr which NEEDs to be 16bit.
What I meant with "You can easily get rid of the whole inner repeat-loop because you have 8 bit input and 8 bit output" is:
I'd also change the comments for
BYTE[Buttons] |= |< B
BYTE[Buttons] &= !|< B
it's set a single bit for the first and clear single bit for the second
About LONG MS001 ... you should move it into the QS_Utilities.spin file and I'd simply introduce an init-function which calculates the right amount like you currently do it. But here is also something to think about! You could add it in a VAR section which means that each instance of the QS_Utilites will have it's own copy. For this variable I'd say it makes no sense to have an individual copy per instance, as the clockfreq is a global setting anyway! So, add it to a DAT section. This on the other hand means that you only have to call init once! (Having an init which needs to initialize a VAR variable would have to be called per instance).
Well ... it does not hurt to call it twice ..
But starting a Utilities.spin-file propably leads to a collection of different functions and you need to be aware of these little differences in VAR vs. DAT at latest when you add functions that also need initialization.
About your question:
SPIN makes sure that values assigned to BYTE[] or a byte-size-variable only effect exactly these 8 bits meant. So, if you do a BYTE[ x ] := |<10 a zero would actually be assigned as the 11th bit is out of sight for this operation.
CogId of course can also be a byte variable. Using long is just dreaming of 2^32-2 COGs ;o)
I still need to work on my key driver, but in the mean time I'm using a cut down version from the
object exchange so I could get one with a different project.