.BYTE[n] syntax
Erlend
Posts: 612
in Propeller 1
I want to put a number of parameters for program execution into the BYTE elements of a LONG array. Say Sequence[4]. Each LONG array element comprises 4 BYTEs, and I want to read and write to these BYTEs individually, something like:
Sequence[step].BYTE[param]:= value
So far I can only find LONGVAR.BYTE[n]:= value. Probably that can just be extended by adding 4 (BYTEs) to n to get me into the next LONG array element, ie. use LONGVAR.BYTE[n+4]:=value.
Am I right, or is there a more elegant (which in my world means descriptive and readable) way to do it?
Relend
Sequence[step].BYTE[param]:= value
So far I can only find LONGVAR.BYTE[n]:= value. Probably that can just be extended by adding 4 (BYTEs) to n to get me into the next LONG array element, ie. use LONGVAR.BYTE[n+4]:=value.
Am I right, or is there a more elegant (which in my world means descriptive and readable) way to do it?
Relend
Comments
Erlend
... doesn't work. (I wish it did).
Here's what you can do to get around this limitation.
In this case you're treating an array of longs as an array of bytes. I do this in a couple programs.
E.g. Maybe this format even improves legibility.
Erlend
Where this can save time later is when you want to pull those four values. If they're in a single long, and you have these (global) variables:
...you can do this:
Mind you, this is a suggestion based on having no idea what your program is doing.
Then either refer to each by name,
speed0 := 20
or
byte[@duration0][SPEEDIDX] := 20 ' CON SPEEDIDX=1
or
byte[@sequence][4*index + SPEEDIDX] := 20
or
longpacket := long[@sequence][index]
The long value might be useful for something like a controller that requires fast transmission of the packets. When I've used this format, it's been for transmission of 100 byte packets via xBee, a structure with mixed header and data bytes, words longs, that are filled in by the program and then passed as a packet for transmission.
Not a bad suggestion based on having no idea of what my program is doing. It controls the brewing process of a coffee machine.
For readability each step in the sequence has a name, presently as a {comment}, but the above approach means I could (and will) do it like this (showing only a few of the assignments I will use: and then
Elegance achieved!
Erlend
With this style all your initial control values are in one place which makes editing easy, you can use bytemove to grab all four elements, or if you only need one of the bytes you can treat each stage like a simple array.
This gives you a lot of flexibility. If your program has an HMI that lets you change values, adding an EEPROM object will let you save those values such that they're available at next power-up. In my EE object that would look something like this:
PS: I love coffee!
So I think the table needs to stay 'soft', agree?
Love coffee too.
And now you can grab the phase variables like this:
I like that, I'll just add some comment headers for better readability: And the program will calculate preheat duration and move that number into the Duration byte of Preheat (showed as 99 here).
Erlend
Edit
This code grabs all 4 bytes/parameters, right? So it is more like: -and then I have to extract byte 0, 1, 2, 3 to get the individual parameters.
Each coffee style requires 16 bytes (four phases of four bytes), so you can update elements like this: Some people don't like one-line methods, but I think it's okay because it will enhance the readability of the code that calls these methods. To help with the set_ methods I would suggest named constants for each style and phase:
Now you have method calls that look like this:
Note that I updated the name of the table -- because simple things like that double entendre make me laugh.
These methods return a pointer for a .str() method. By padding the end of short strings with spaces so that all are the same length, finding the address of the string in a table is easy and the display cleans itself.
to
which will effectively make your table long-aligned. Then you can use longmove() instead
Whatever coding method(s) you use, one liners, DATs, etc... be sure to document the heck-out-of-it so even a newbie could understand it, perhaps in a separate document for the entire project, so your source file doesn't get overwhelmed. While you are working the project now it all seems so simple and elegant. But if you are like me, going back to the code/project n months later after working with other languages, you will keep asking yourself "What am I doing this for?" "How does this work?" Never assume "Oh, I'll remember that trick..."
Case in point for us old farts who grew up using Korn shell in UNIX environments, you would frequently see these kinds of incantations (this is a simple one compared to some I've seen/created):
And all it does is determine whether or not the shell is running interactively or not.
You're right that longmove is faster (by about 1.8us), but I don't think manipulating the code to use it is worth the trouble in this particular case.
I just ran another test. It seems like longmove masks off the lower two bits of the destination address before running. This can cause a problem if the destination is not long-aligned, because the longmove will overwrite values that precede the destination.
Test data: Without the z, y, and x line, longmove(@a, @Values, 1) works fine. Adding variables ahead of a is an issue -- and trying to force alignment into a group of byte variables (not DAT) elements would probably confuse newcomers.
This allows the table entry of -1 to be easier for humans to spot. Yep, it's wading through the minutia, but sometimes we do this to create high-quality code.
Good point! I wasn't thinking about the destination.
(edit: the mobile interface quotes differently, which makes things hard to read. updated now that I'm at a computer. no substantive changes.)
Thanks. I actually do this in my code, but I wish I could use the obj#value syntax to access and maintain those strings where they belong - in the brew object.
Erlend
Yes. I prefer a very visual style of code, so I always use CONs for constants. Nice also that the TURKISH... constants can be accessed from the calling (top level) code.
Is superior to my own when duration is the only parameter I ever need to change?
Erlend
I stand corrected Promise never again to use 99, when -1 is indeed the closest you can get to a nil character.
Erlend
Agree. I love it when I can tease the Masters into sharing gold nuggets like these. Agree 2. I always try to write the code so that it is easy to read (also for non-Spin'ers), and even inefficient if that is what it takes to make it easy on the eye. This particular project has been idle for several years, but thanks to myself (!) I had no problem picking it up and now bringing it to completion.
Erlend
The trouble of posting too late at night. I do know this, now I know it double.
Erlend