Am I wrong in thinking I can take a stored byte containing $00 - $FF, read it one bit at a time, and get 00000000 - 11111111? Using each bit simply as a 1 or a 0, and use that 1 or 0 for something as simple as an OUTA[#]~~ or OUTA[#]~?
Is there any reason this would not work desirably?
The thought is to store the data and send it to the pc terminal efficiently and fast enough so I don't miss pieces.
Hi Vadoo, the way I have done file reading in the past when the file was larger than my receive buffer was to read the file data in small packets.
To do this with the Vmusic the first thing is to get the file size of the file you want to read.
Assuming you are reading ten byte packets then Repeat count = file size / 10.
You would also need another small routine to read a remainder if any ( which would be the modulus of filesize/10 )
Having the above information your repeat loop reads ten bytes at a time, stores them, reads the next ten, appends them to the stored value etc etc
To try and give a better picture of what I am talking about check the attached file which was written with the BS2 in mind ,Step 4 should not be to hard to follow.
One thing that may be confusing in the previous attachment is that everything is done with the shortened command set. To put that straight I have another attachment, a spin method using the extended command set, that will read the size of a file and display it to a debug terminal. The method is called Check_Size and will require the two serial objects (VMusic2 and Debug) configuring and starting by you. At the beginning of the method I set the input to IPH followed by a loop that waits for the prompt, you may not need to do this depending on your configuration. Replace the text "FILENAME" with the file you wish to check the size of. As your program grows using a seperate method or sub routine for each VMusic instruction will keep your main code manageable.
As a side note I think you are doing the right thing by using the default 9600 baud while you put your program together, somewhere down the road you may feel the need for speed and increase your baud rate
I like the FileSize object. Thanks for the help Unsoundcode! It may be the weekend before I get to dive too deep into it, but i have some thoughts to try out. Can you please explain this part of the code. I mostly understand it, but not entirely confidently More the last two lines.
I have success!!! Well a little. After playing with the settings of the Parallax Serial Terminal, I can sort see my file being read. Problem is, the file contains a series of 00 and FF. The serial terminal is showing a bunch of ÿ, which seem to represent the FF locations. Also its not showing the 00, it doesn't even show a space, just all of the FF as ÿ with no spaces. Now if I set it to clear screen on 0, I see the ÿ quickly flash and disappear, and they certainly seem to accurately represent the positions of the FFs. So that's good! Thoughts?
I often add a couple of methods to my programs to make sure the output is legitimate ASCII characters.
PUB SafeBug(localPtr, localSize)
repeat result from 0 to localSize - 1
TbugTx(byte[localPtr + result])
PRI TbugTx(localCharacter)
if (localCharacter > 31 and localCharacter < 127) or localCharacter == 13
Com.tx(_DebugCom, localCharacter)
else
Com.tx(_DebugCom, 60)
Com.tx(_DebugCom, 36)
TbugHex(localCharacter, 2)
Com.tx(_DebugCom, 62)
PRI TbugHex(localHex, localSize)
Com.hex(_DebugCom, localHex, localSize)
You'll need to change the syntax to match the serial object you're using.
I call SafeBug with a pointer to the text I want to display and include the number of bytes to display since it isn't watching for a terminating zero like most string methods.
Vadoo, in answer to the file size instruction the VMusic returns a 32 bit long which is the value of the file size. The 32 bit long is divided into four bytes that are 8 bits long and it sends the lowest byte first. It is our job to put those bytes back into one single value when we receive them. One thing to note is that the way I coded it I am assuming the value of file size will always be below 65535 so I only need to grab the first 2 of the 4 bytes (lowbyte and highbyte). The first line you asked about shifts the highbyte 8 positions to the left in our filesize variable, the second line is a bitwise OR of filesize and lowbyte which combines highbyte and lowbyte into one single value . The 2 previous lines are just receive instructions with a time out of 10mS, I gave it the time out to make sure I did not skip the incoming data.
Did you manage to get it to work for you, I got it to work but I have a tendency to do everything using the SCS so you will have to play around a little to get it working maybe. When you do we can look at the read loops required.
Duane's point about checking for ASCII v receiving bytes as binary values between 0-255 is crucial in how you treat the data, are your files text files or binary files.
repeat {Read and display}
x:=VMusic2.rxcheck
if x<> -1
if x== $20
....
The if x == $20. What is it doing? I assume an input from the VMusic2, but I can't find anywhere that it says it sends any kind of initiator type signal. My understanding is it just starts sending data and a prompt when complete. Ill test it out this weekend, but I would think the if x== $20 is not needed, it could go straight to lowbyte highbyte? Though an initiating byte, or some sort of "Hey here comes your data" from the VMusic2 would be greatly helpfull, I just can't find it written anywhere!
I guess a binary file? I didn't make the file so not sure. But I use WebHex to view it, and it just contains $00 - $FF. And a -d at the beginning.
so I know that once I have issued the filesize instruction all I have to do is wait for the first space character ( $20 ) and the next two bytes are the ones I want to grab, the order is always the same no matter what the filename.
If there is no data to read in the serial buffer the value in the buffer will be -1, I only want to use data from the buffer when there is data to read, therefore if x is not equal to -1 ( x<> -1 ) there is data there I need to do something with.
File size has a benefit not at first obvious, if the file size instruction does not return a value then you would know that the file does not exist or has been corrupted in some way. If the instruction fails it has no detrimental effect on your hardware providing you are aware of it and handle it accordingly. This is not true with many of the other VDAP instructions.
Do you have a copy of the VDAP firmware, I think it's an important reference.
I'm pleased you took the time to figure it out and get it working for yourself, I also hope the above clarified a few points for you.
so I know that once I have issued the filesize instruction all I have to do is wait for the first space character ( $20 ) and the next two bytes are the ones I want to grab, the order is always the same no matter what the filename.
If there is no data to read in the serial buffer the value in the buffer will be -1, I only want to use data from the buffer when there is data to read, therefore if x is not equal to -1 ( x<> -1 ) there is data there I need to do something with.
File size has a benefit not at first obvious, if the file size instruction does not return a value then you would know that the file does not exist or has been corrupted in some way. If the instruction fails it has no detrimental effect on your hardware providing you are aware of it and handle it accordingly. This is not true with many of the other VDAP instructions.
Do you have a copy of the VDAP firmware, I think it's an important reference.
I'm pleased you took the time to figure it out and get it working for yourself, I also hope the above clarified a few points for you.
Jeff T.
Yes greatly, thank you! As for the firmware, yes. I have been using it a lot.
I'm still fighting with this data reading and storage problem though. Ultimately I need to read and store a decent amount of data. I'm aiming for a 512 buffer. That way I can do other things for a while before refilling the buffer. But everything I write either gives me jarbled information or my code is too long and I miss pieces of data because of it. Not to mention I still need to figure out how to use that buffer a bit at a time for the shift register...
I am slowly making progress on storing the data though I think. I feel I'm close to figuring it out....
Vadoo, attached is a method that makes use of filesize to read a file and then display the results on a terminal in decimal and hexadecimal. Add this method and call it from the filesize code you have already. There is a change and an addition that needs to be included in your spin file, the change is to place the filesize variable in the VAR section eg: Word filesize. The addition is to add an array of 500 bytes to the VAR section eg: Byte buffer[512].
I ran it a couple of times and it seemed ok, see what results it gives you it may need a tweak or two.
Jeff T.
Vadoo, in haste I forgot to include the instruction to close the file, you could make this the last instruction of the method.
I have read somewhere in my search, a recommendation to connect the VMusic2 reset pin to the Prop reset. But I can't seem to find this pin! Is there any other way? The issue/annoyance is each time I make a change to a program, I often have to change which instruction I send the
Vmusic. For example if I had previously read 8 bytes of a file, the next time it will read the next 8 bytes rather then the first as I may want it to.
Vadoo, attached is a method that makes use of filesize to read a file and then display the results on a terminal in decimal and hexadecimal. Add this method and call it from the filesize code you have already. There is a change and an addition that needs to be included in your spin file, the change is to place the filesize variable in the VAR section eg: Word filesize. The addition is to add an array of 500 bytes to the VAR section eg: Byte buffer[512].
I ran it a couple of times and it seemed ok, see what results it gives you it may need a tweak or two.
Jeff T.
Vadoo, in haste I forgot to include the instruction to close the file, you could make this the last instruction of the method.
This seems to be working... I have gone all the way to adding in shift register control, and it is functional, not correctly, but expectedly as my code is a little off. I just haven't fixed that part yet.
Right now I'm trying to figure out WHY it works... I tried so many variations of ways to read, store and re read the stored data. And many of them closely mimicked what you wrote, but mine didn't work! Anywho, I will post what I have done with what you sent once I refine It a little better. It's a bit messy right now.
Thanks!!
This object is working great! It gets file size, reads to a 512 buffer and shifts it out. I can read entire sequence files now and control the shift registers! It does have one issue. It has to pause every couple seconds to refill the buffer. I'm working on a more complex program with multiple objects to fix that. I'll post that in a moment...
Here is my attempt to use one main object to manage two 512 buffers, and one object to shift out one buffer at a time and let the main object know when to refill one buffer while the other is being read. And so on.
Its not working at all(as far as passing the data from cog to the other). I think I am passing the buffer (and other) addresses incorrectly. I know my shift object is working in some way. My heartbeat led does flash, but nothing on the shift registers.
I'm trying to get this data, address stuff sorted out in my brain.
Please tell me where I am off track.
VAR
byte temp1
PUB Main
temp1:= %11110000
Temp is now equal to 11110000.
Say I use:
VAR
long stack
OBJ
Shift: Shift_Out
PUB
.......................
cognew(Shift.start(@temp1), @stack)
To start in its own cog:
{Shift_Out.spin}
PUB start(temp)
At Shift_Out, temp is equal to the address of the data stored in temp1, not the data itself. Which could be something like $1AFF.
To use the data store at that address I have to do something like:
Since you passed the address of temp1, temp equals the address so you don't want to use the @ operator. @temp is the location of temp. temp holds the location of temp1.
Since you passed the address of temp1, temp equals the address so you don't want to use the @ operator. @temp is the location of temp. temp holds the location of temp1.
So temp is equal to byte(temp) which is %11110000, correct?
VAR
long stack[32]
PUB Start
cognew(MainLoop, @stack)
PUB MainLoop
repeat
' Do stuff in a different cog
One question. If (using your example) I had PUB MainLoop(data), and needed cognew to send the address of the data stored in temp1 (our original object which originally stored the data to be used in our new cog), I can still just say cognew(MainLoop(temp), @stack) Because (temp) is the address, and saying @temp would give me the address of temp not the adddress stored in temp?
I think I may have answered my own question but did that make sense?
One question. If (using your example) I had PUB MainLoop(data), and needed cognew to send the address of the data stored in temp1 (our original object which originally stored the data to be used in our new cog), I can still just say cognew(MainLoop(temp), @stack) Because (temp) is the address, and saying @temp would give me the address of temp not the adddress stored in temp?
I think I may have answered my own question but did that make sense?
Yes, it made sense and yes, you answered your own question.
This looks OK but who knows why it doesn't do what one thinks it should do? Anyway, this particular case will do the method call and collect the result but will treat said result as an address to a PASM blob, i.e. like using cognew(@entry, 0). There are other oddities involving brackets but this isn't the thread for it.
Comments
Is there any reason this would not work desirably?
The thought is to store the data and send it to the pc terminal efficiently and fast enough so I don't miss pieces.
To do this with the Vmusic the first thing is to get the file size of the file you want to read.
Assuming you are reading ten byte packets then Repeat count = file size / 10.
You would also need another small routine to read a remainder if any ( which would be the modulus of filesize/10 )
Having the above information your repeat loop reads ten bytes at a time, stores them, reads the next ten, appends them to the stored value etc etc
To try and give a better picture of what I am talking about check the attached file which was written with the BS2 in mind ,Step 4 should not be to hard to follow.
Jeff T.
As a side note I think you are doing the right thing by using the default 9600 baud while you put your program together, somewhere down the road you may feel the need for speed and increase your baud rate
Jeff T.
Thanks!
I often add a couple of methods to my programs to make sure the output is legitimate ASCII characters.
You'll need to change the syntax to match the serial object you're using.
I call SafeBug with a pointer to the text I want to display and include the number of bytes to display since it isn't watching for a terminating zero like most string methods.
Duane
Did you manage to get it to work for you, I got it to work but I have a tendency to do everything using the SCS so you will have to play around a little to get it working maybe. When you do we can look at the read loops required.
Duane's point about checking for ASCII v receiving bytes as binary values between 0-255 is crucial in how you treat the data, are your files text files or binary files.
Jeff T.
The if x == $20. What is it doing? I assume an input from the VMusic2, but I can't find anywhere that it says it sends any kind of initiator type signal. My understanding is it just starts sending data and a prompt when complete. Ill test it out this weekend, but I would think the if x== $20 is not needed, it could go straight to lowbyte highbyte? Though an initiating byte, or some sort of "Hey here comes your data" from the VMusic2 would be greatly helpfull, I just can't find it written anywhere!
I guess a binary file? I didn't make the file so not sure. But I use WebHex to view it, and it just contains $00 - $FF. And a -d at the beginning.
Works great.
Not sure I understand how with the $20 part in there....
"data.hlx" $20 <filesize byte 1> <filesize byte 2> <filesize byte 3> <filesize byte 4>
so I know that once I have issued the filesize instruction all I have to do is wait for the first space character ( $20 ) and the next two bytes are the ones I want to grab, the order is always the same no matter what the filename.
If there is no data to read in the serial buffer the value in the buffer will be -1, I only want to use data from the buffer when there is data to read, therefore if x is not equal to -1 ( x<> -1 ) there is data there I need to do something with.
File size has a benefit not at first obvious, if the file size instruction does not return a value then you would know that the file does not exist or has been corrupted in some way. If the instruction fails it has no detrimental effect on your hardware providing you are aware of it and handle it accordingly. This is not true with many of the other VDAP instructions.
Do you have a copy of the VDAP firmware, I think it's an important reference.
I'm pleased you took the time to figure it out and get it working for yourself, I also hope the above clarified a few points for you.
Jeff T.
Yes greatly, thank you! As for the firmware, yes. I have been using it a lot.
I'm still fighting with this data reading and storage problem though. Ultimately I need to read and store a decent amount of data. I'm aiming for a 512 buffer. That way I can do other things for a while before refilling the buffer. But everything I write either gives me jarbled information or my code is too long and I miss pieces of data because of it. Not to mention I still need to figure out how to use that buffer a bit at a time for the shift register...
I am slowly making progress on storing the data though I think. I feel I'm close to figuring it out....
I ran it a couple of times and it seemed ok, see what results it gives you it may need a tweak or two.
Jeff T.
Vadoo, in haste I forgot to include the instruction to close the file, you could make this the last instruction of the method.
Vmusic. For example if I had previously read 8 bytes of a file, the next time it will read the next 8 bytes rather then the first as I may want it to.
This seems to be working... I have gone all the way to adding in shift register control, and it is functional, not correctly, but expectedly as my code is a little off. I just haven't fixed that part yet.
Right now I'm trying to figure out WHY it works... I tried so many variations of ways to read, store and re read the stored data. And many of them closely mimicked what you wrote, but mine didn't work! Anywho, I will post what I have done with what you sent once I refine It a little better. It's a bit messy right now.
Thanks!!
Its not working at all(as far as passing the data from cog to the other). I think I am passing the buffer (and other) addresses incorrectly. I know my shift object is working in some way. My heartbeat led does flash, but nothing on the shift registers.
Please tell me where I am off track.
Temp is now equal to 11110000.
Say I use: To start in its own cog: At Shift_Out, temp is equal to the address of the data stored in temp1, not the data itself. Which could be something like $1AFF.
To use the data store at that address I have to do something like: Now data is equal to %11110000.
Am I on the right track at all?
You can start a method in a different object with new cog.
You need to put the cognew call in the start method of your Shift object.
Should be :
Since you passed the address of temp1, temp equals the address so you don't want to use the @ operator. @temp is the location of temp. temp holds the location of temp1.
So temp is equal to byte(temp) which is %11110000, correct?
Sorry there were a couple of typos in my reply.
You can not start a method in a different object in a new cog.
You can't use MyObject.start with the cognew call.
The method has to be part of the object where you use cognew. Cognew can not access a method within a child object.
Instead you call the start method in a child object.
Then in the start method of MyObject you use cognew.
Hopefully and example and my not stating the opposite of what I mean, will help.
This time I think you made the typo.
You mean data equals %11110000, right? If so, yes.
temp is set equal to the address of temp1.
Also you need to use square brackets with byte[location] not ().
Yes. That too. Thank you!!
Though my intention was to say temp1 is the same as byte[temp]. Both statements would equal %11110000.
I think I may have answered my own question but did that make sense?
I hope kuroneko doesn't mind if I quote him.
I'll let someone who understands this better take it up.
I'm trying to remember where I read the information about starting cogs in a child object. So far I don't remember.
Duane
Yes, it made sense and yes, you answered your own question.
This looks OK but who knows why it doesn't do what one thinks it should do? Anyway, this particular case will do the method call and collect the result but will treat said result as an address to a PASM blob, i.e. like using cognew(@entry, 0). There are other oddities involving brackets but this isn't the thread for it.