Cannot pass data between a cog running spin and a cog runnig pasm
vetter
Posts: 8
in Propeller 1
Hello everyone, I've been struggling with this problem for some time now and hopping that someone is able to lend a hand as I'm new to propeller. I'm struggling with passing data between a cog running spin and another cog running pasm. I'm writing a driver for an touchscreen display and have gotten basic functionality with it. The problem is that I cannot print even a small image (50x50 pixels) without it taking 2 seconds. To fix this I'm writing the function that sends data to the LCD in pasm in the hopes that I can print a large image almost instantly instead of a few seconds. The SPIN code sets a flag that indicates to the PASM code that it needs to draw an image and waits until it is cleared. The pasm code is currently able to realize that a flag is being set but nothing else. The pixel info and the flag is stored in Dat labeled datablock. If you have any ideas how to fix this issue or general ways to improve the code please let me know as I'm not yet familiar with proper propeller programming standards. Thanks in advance.
This is the slow spin code that is able to print an image which is what I'm trying to convert
pub LCD_Datawrite(Data)
pin.High(rd)
pin.Low(cs)
pin.Low(rs)
pin.Outs(dataend,datastart, data)
pin.Low(write)
pin.High(write)
pin.High(cs)
pin.Outs(dataend,datastart, $ff)
pin.High(rs)
This is what i have converted it into. The testloop is there only to check if i can write back to the datablock and will be removed later
DAT
org 0
asm_enter MOV memptr, PAR 'passing the first address of the data block to the counter
RDLONG flag, memptr 'passing the value that memptr points to into flag
TJZ flag, dataWrite 'if the flag is set then enter the loop
:testloop WRLONG lng, memptr 'loop to check if data can be written to the flag location
JMP :testloop
:skipflags add memptr, #4 'incrementing the counter past the flag, pointing to the first pixel in the dat blcok
WRLONG memptr, 0
:loop OR OUTA, ard 'set rd high
MOV pins, INA 'store the pin states in pins
AND pins, lowcs 'clear the bit that corresponds to the cs pin
MOV OUTA, pins 'output the new OUTA value
MOV pins, INA 'set rs low
AND pins, lowrs
MOV OUTA, pins
RDBYTE pixel, memptr 'accesing the PIC data block and storing the data in pixel
AND OUTA, pixel ' sending the data out. data bus is pins 0-7
MOV pins, INA 'set write low
AND pins, lowwrite
MOV OUTA, pins
OR pins, awrite 'set write high
OR OUTA, acs 'set cs high
OR OUTA, #$000FF 'set the data buss high
OR OUTA, ars ' set ars high
ADD memptr, #2 'the next memory location being accessed is one byte higher
djnz loopcount, #:loop 'jump back to loop
WRLONG memptr lng 'loop has finished clear the flag
JMP dataWrite 'start checking for the next image to draw
A sample of the datablock that PAR is pointing to is:
datablock long $ffffff byte $ff,$ff,$ff......(more pixel data)
the long is is the flag being checked in the pasm code and the bytes are pixels. I realize the flag could be just a byte however I'm not sure if the data block needed to be long aligned
This is the slow spin code that is able to print an image which is what I'm trying to convert
pub LCD_Datawrite(Data)
pin.High(rd)
pin.Low(cs)
pin.Low(rs)
pin.Outs(dataend,datastart, data)
pin.Low(write)
pin.High(write)
pin.High(cs)
pin.Outs(dataend,datastart, $ff)
pin.High(rs)
This is what i have converted it into. The testloop is there only to check if i can write back to the datablock and will be removed later
DAT
org 0
asm_enter MOV memptr, PAR 'passing the first address of the data block to the counter
RDLONG flag, memptr 'passing the value that memptr points to into flag
TJZ flag, dataWrite 'if the flag is set then enter the loop
:testloop WRLONG lng, memptr 'loop to check if data can be written to the flag location
JMP :testloop
:skipflags add memptr, #4 'incrementing the counter past the flag, pointing to the first pixel in the dat blcok
WRLONG memptr, 0
:loop OR OUTA, ard 'set rd high
MOV pins, INA 'store the pin states in pins
AND pins, lowcs 'clear the bit that corresponds to the cs pin
MOV OUTA, pins 'output the new OUTA value
MOV pins, INA 'set rs low
AND pins, lowrs
MOV OUTA, pins
RDBYTE pixel, memptr 'accesing the PIC data block and storing the data in pixel
AND OUTA, pixel ' sending the data out. data bus is pins 0-7
MOV pins, INA 'set write low
AND pins, lowwrite
MOV OUTA, pins
OR pins, awrite 'set write high
OR OUTA, acs 'set cs high
OR OUTA, #$000FF 'set the data buss high
OR OUTA, ars ' set ars high
ADD memptr, #2 'the next memory location being accessed is one byte higher
djnz loopcount, #:loop 'jump back to loop
WRLONG memptr lng 'loop has finished clear the flag
JMP dataWrite 'start checking for the next image to draw
A sample of the datablock that PAR is pointing to is:
datablock long $ffffff byte $ff,$ff,$ff......(more pixel data)
the long is is the flag being checked in the pasm code and the bytes are pixels. I realize the flag could be just a byte however I'm not sure if the data block needed to be long aligned
Comments
Welcome to the forum.
Insert the # symbol for immediate addresses as follows
I see code for setting pins high using "or outa" but I don't see where the I/O pins have been set as outputs.
When you post your code, it would help a lot if you use code tags. If you quote ozpropdev's post, you'll see the code tags used. You can either manually add code tags or you can click the "C" icon in the text editor to add code tags.
You can archive your program by, after compiling your program, selecting File\Archive "MyProgram"\Project..." This will produce a zip file with all the object used in the program. If you attach the archive then we can take a look of your code.
I've attached the full code below, most of it is commented out because they are working functions that print text and simple shapes. Thanks for the help
Should be:
The line:
Should be:
The following line is correct:
As I mentioned earlier, your "or outa, ..." commands in your PASM code will not set any of the I/O pins high. The pins must be set as outputs using "dira" somewhere in your PASM code in order drive the I/O pins with the "outa" command.
The direction of the I/O pins need to be set from the same cog as the one setting the I/O pins high or low.
The object "Input Output Pins" will set pin states in the cog calling the methods in the object. You can't use this object to set the direction of I/O pins for a cog running PASM code.
For example, in order for the line below to set any I/O pin high you must first set the I/O pin as an output from within your PASM code.
Somewhere early in your PASM code use the following line to set "ard" as an output:
BTW, the following code will set "ard" low.
In the above examples, both jumps will go to the label "here". In the first, the instruction stores the address of "here" and sets the immediate bit (#). In the second jump, the instruction stores the address of "there" without the immediate bit. When it executes, it fetches the contents of the long "there" which stores the 9-bit address of "here", and used that ("here") as the jump to address.
If you make a mistake and leave out the "#" in the first jump, then the program will go to wherever the lower 9-bits of "here" points to. That means your program will go somewhere you didn't mean it to go!!!
It looks like your test loop correctly uses the hub address of your flag but other places in your code you have the data and address reversed.
I think you have this line correct:
However other places you have the address located in the destination field like this line.
I'm pretty sure you want to write the value "lng" to the address "memptr". Right?
If so, you should use:
Both reads and writes require the address to be located in the source field.
It would seem like the hub address should be the destination with a write but this is not the case. The data to be written is the destination and the address to write the data is the source. Apparently there are hardware reasons why these fields are used this way.
This is what I currently have in the assembly program
This is the current spin code
Do you realize the program never exits the above loop?
I think you are using "DIRA" incorrectly. You set the dira states the same way you do with outa states, using a mask. I provided an example earlier using your "ard" mask. It looks like you're setting the masks correctly already, you just need to treat dira statements with the same syntax as the outa statements.
When I first learned to use the Propeller I was terribly confused about pointers and PASM. It was thanks to many forum members such as Cluso99 that I eventually understood how things worked.
I have a list of links to Propeller related tutorials in my (non-alphabetical) "index." Here's a link to the post with this list of links.
JonnyMac's SpinZone articles were a big help with my attempt to understand PASM and DeSilva's PASM tutorial was also a big help. I had to come back to DeSilva's tutorial several different times. Each time I read it, I understood more of what he was saying. (I never interacted with DeSilva but I sure miss his input around here.)
I thought Cluso99 explained things better than I could but I'll attempt to add what I understand about pointers in PASM. The "#" symbol indicates the value stored in the "source" section of the PASM line should be acted on directly. When "#4" is used, the value four is used as the source field. If instead of "#4", one used "4" then the value located in cog memory position 4 would be used as the source field.
As I learned from DeSilva's tutorial, each line of PASM is also a 32 bit register. These registers can either contain data or instructions. The Propeller doesn't care if the information in each memory slot (register) is an instruction or a numeric value used in calculations. When a memory slot is used as an instruction, it's broken into multiple fields. The last nine bits is the "source" field. One of the remaining 23 bits (32-9 = 23) is a bit indicating if the value in the source field should be treated as value (as in the case of "#4") or if the field should be used to indicate which memory position should be used as the source of the PASM instruction. I don't recall the correct terms for the direct rather than indirect source field. DeSilva's tutorial uses the correct terminology.
I have a feeling what I just wrote didn't make any sense. I encourage you to read DeSilva's tutorial (a couple of times). There's also a tutorial by Graham Stabler which I have heard good things about. I haven't read Graham's tutorial myself because by the time I learned it existed, I felt like I understood how PASM worked reasonably well.
I'm going to make sure these links I suggest following are still good.