Simple spin questions
turbosupra
Posts: 1,088
If I want to say variable1 = variable2, how do I do that? Every time I do this, I get inconsistent results, and so I thought I'd just ask.
The purpose is to have them both be the same value, so that if variable2 changes, variable1 still has its old value. I do not want it to be a pointer that says to check the value of variable2, when you query variable1.
Also, I'm having a very hard time with knowing what data type I want with pst.Str or pst.Char. How do I know when to put the @ symbol in front of a variable name when using pst.Str(@variable) or pst.Str(variable) ?
The purpose is to have them both be the same value, so that if variable2 changes, variable1 still has its old value. I do not want it to be a pointer that says to check the value of variable2, when you query variable1.
Also, I'm having a very hard time with knowing what data type I want with pst.Str or pst.Char. How do I know when to put the @ symbol in front of a variable name when using pst.Str(@variable) or pst.Str(variable) ?
Comments
variable1 := variable2
should be enough.
pst.Char needs a single byte as an argument.
pst.Str needs a pointer to an array of bytes with a terminating zero. This is why you would usually use the @ symbol. If you had a variable that you were using as a pointer so it already held the address of an array of bytes you wouldn't use the @ symbol.
For example:
The output (untested) should be:
Duane
The first line returns a Boolean value (TRUE or FALSE) indicating whether or not the variable pattern has a value of 0. If it does, then the second line assigns the value %11000000 to the variable pattern.
Re. the "@", a variable preceded by that symbol gives the memory address of the variable, not the contents at that address. A lot of Spin methods require that for their arguments.
A well-documented method should indicate as clearly as this one does that the argument you need to send is the address and not the variable's contents.
The @/non @ explanation is good and hopefully a cornerstone for me to start building on. I was able to get the second code block to work, thank you!
I tried to insert the line below instead, but it did not work, any idea as to why?
That counting starting with zero gets me a lot too.
strsize is evaluated every loop. You could speed up the code by using a temporary variable to hold the size and use that as a parameter.
The above code should execute faster than the code in the first code block.
Duane
The code example I was trying to write, was the following, and I would send "test=4" to it. I believe my code is failing because I'm not sure how to send b_RxString to DelimiterFinder. Whenever I send it, it seems to come out as gibberish. Since I pass it originally as a reference with DelimiterFinder(@b_RxString) on line 40, I should not have to use the @ symbol anymore, based on variable assignments, correct? On line 46, the value does not print out correctly inside of the PST either, what am I doing wrong there? And finally, why do I have to put the long "l_localindex" in the line of code repeat l_localindex from 0 to strsize(b_Ptr2b_RxString) -1 in line 51?
Thanks again.
You declare b_PosOfDelimiter as an array but never use an index with it.
I'm pretty sure Spin treats b_PosOfDelimiter as b_PosOfDelimiter[0] but I don't think it's good programming style to do it that way.
The method DelimiterFinder returns b_PosOfDelimiter which is also a bit strange to use a global variable as a return value since the calling method will know its value without the need for it to be returned.
repeat l_localindex from 0 to strsize(b_Ptr2b_RxString) -1
could be written as
repeat strsize(b_Ptr2b_RxString)
since your code doesn't use l_localIndex
Duane
does not fit with the way you use it:
b_Ptr2b_RxString := RxStringAddr
pst.Str(b_Ptr2b_RxString)
First of all I don't see the benefit of storing the address in just another variable. And if you want to store an address you at least need a word (which is the main problem):
word b_Ptr2b_RxString
Because b_Ptr2b_RxString was defined as byte only the byte will be passed to pst.Str, which cuts away parts of the real address.
But pst.str( RxStringAddr ) will work just fine!
there is also no need to have b_pos because l_localindex is aleady counting from 0 upwards.
Ah, yes. I didn't catch that.
Duane
So if all strings are byte arrays, why would I want to store and address to a word or long. I think me not knowing this is the crux, or part of the crux of why I'm having such a hard time with this. I thought it would store it as an array, and then pst.Str would receive the array and display it from the memory address of the first byte b_Ptr2b_RxString[0] to the 0 terminator at the end. Is that logic wrong? Your explanation makes sense with the results I was experiencing, I would just like to understand why so I can cement it into my brain
Thank you for the reply. This might be asking a lot, but would you mind showing me how you would write DelimiterFinder so that I can compare style and learn to write in a more "industry standard" way? If not, I understand, but if so I would really appreciate it and anticipate that I would be able to learn a lot from it.
Come on, you already know the answer will be yes. I'm a sucker for writing other people's code. Their problems are always easier then the ones I'm having.
I am headed of to the store with my wife right now. I'll likely write it later tonight (perhaps tomorrow). It shouldn't take long.
Duane
Here's an example of the output.
I started counting the positions with zero. The code could easily be modified to use one as the first position.
In case you don't know, 34 is the ASCII number for double quotes. You could asign a constant name to 34, but I personally think it's just as easy to use the ASCII numbers for many of the none printed and not easily printed characters.
Duane
Would you mind explaining this please?
So if all strings are byte arrays, why would I want to store and address to a word or long. I think me not knowing this is the crux, or part of the crux of why I'm having such a hard time with this. I thought it would store it as an array, and then pst.Str would receive the array and display it from the memory address of the first byte b_Ptr2b_RxString[0] to the 0 terminator at the end. Is that logic wrong?
I have gotten it to parse the data correctly now, thanks to your help.
The only thing that isn't making sense is when I change the value of "flashes" to a different number, my code ignores it (or at the very least does not use it properly). Any idea why this is happening? I initially set the value of flashes to 1, so it will flash once and then pause for 2 seconds. When I try and reset the value to say "flashes=4" it will just flash for forever?
Change the method "DelimiterFinder" in the code I posted above to this version.
Here's the output when I typed "Fred=10".
The first byte "F" was stored in the memory location 1596. 1596 would not fit in a byte so a word or a long must be used to store it.
Local variables are all longs so the variable "localPtr" is a long and can hold the value 1596 without a problem.
You might have noticed I commented out "quit". This keeps the loop going even after the delimiter was found. I wanted the loop to continue so all the addresses in the string would be displayed.
This concept of addresses is very important (as you can tell). The modified method I just posted is giving the location of each item in the array. Just the address of the first member of the array is enough for the method to know where to start reading the data.
The line
is both checking to see if an equals sign is in the memory location localPtr and incrementing the value of localPtr (see Post-Increment p.152).
Something that helped me get strings straight in my brain was something like this.
Make sure temp is at least a word in size and you'll see where the temporary string "hello world" is stored in memory.
One of the reasons I've changed
to
is because of the overhead required by the Propeller to hold the new line characters as a string which PST then needs to break apart. If I'm only displaying two characters, I usually send the characters individually rather than combining them to a string before sending them to a serial object. This is also a matter of personal preference.
Hopefully some of this is making sense. Keep the questions coming.
Duane
So it is setting it to a char value of 4 or 5 instead of a decimal value. Is there a native way to correct that?
[edit, I see you posted while I was writing (thank you), I will try and comprehend that now]
I made some changes.
A single byte will do as long as you don't want to flash the LED more than 255 times.
I'm surprised your original code worked as well as it did. I think since all the strings you entered were relatively small the memory wasn't corrupted to the point of not working.
Remember to store strings in byte arrays. All local variables are longs.
The value four is not the same as the character "4". You need to convert the string to a number. I used the method "StrToBase" from PST to convert the string to number value.
The program in my previous post shows the difference between a number value and a numeric character. For example the character "4" is held as 52 in a single byte in memory.
You had delimiter[1] := 0 in the DelimiterFinder method. Strings need a terminating zero not single characters. Since delimiter isn't an array the index [1] moved the zero into the next byte.
I'll look through the PEK material to see if there's a section that explains all this.
Duane
Ok, so methods accept and return longs, which then I can store into a byte array if it is a string ... which is really a pointer to a memory address with a numerical value next to it that says how many consecutive memory addresses are part of that variables (strings) value? I can view this memory address through the command pst.Dec(name of long), which is different then pst.Dec(byte[name of long]) of which then gives you the byte binary mathematical value. Then there is the command pst.Char(byte[name of long]) which gives the ascii character value, converted from the decimal byte value at the decimal location? Pst.Dec will give a numerical value when used with a byte or byte array, but a memory address when used with a long? If I wanted to have 260 flashes, could I just change it to a byte array, or would there be many other code changes required as well? If setting delimiter[1] := 0, does not create a terminating zero, because it actually sets it to a value of 48? What is an index[1]?
Is it safe to copy back and forth between between bytes and longs? Since all methods return a long, I can bytemove that long into a bytearray? Will bytearray := long not work, is that why I had to use bytemove instead of an assignment?
To use delimiter[1] without cause a problem with the next byte variable, you need
But you don't need a terminating zero anyway since you where just comparing a single character.
Is the same as
Is the same as
Spin uses longs as arguments and return values. The method determines what is returned.
Normally you would not store a long into a byte array. A byte array is multiple sequential bytes. A method may return a memory location of a byte. A string is a byte array holding ASCII values of characters you may wish to send to a terminal. Many string commands and methods assume there is a terminating zero indicating the end of the string.
Each character is a single byte. In the Help menu of the Propeller Tool their is a menu item "View Character Chart..." this tells you the ASCII values of each character.
This will get you into trouble fast.
If the method returns the address of a byte array, you can use bytemove to move the bytes from the location returned to another location.
The location can be a large value since there are 32K bytes of RAM. The location tells you where in memory those bytes are located. You use the location in many of the string methods since you can only pass and receive a single value.
In an earlier post I had the program list the memory locations of each character.
"F" in "Fred" was located in memory location 1596.
Since "Fred" is stored in rxString we know the location of the first byte in rxString is 1596.
In the main method you have the line
We could have used
since 1596 and @rxString are the same value.
Although just by changing the code from
to
may change the location in memory where rxString is located when the program is recompiled. This make using @rxString much more practical to using 1596 since we didn't know the value 1596 was the same as @rxString until after the program was ran.
The method PosOfDelimiter returned how far from the start of the string the delimiter was located (starting counting with zero).
If we changed DelimiterFinder to
Then the output would be changed to
Duane