By cog address do you mean which cog they are running in (or have been instructed to run in)?
Nope, I mean exactly what Eric so conveniently answered for you. If you have a loop in assembler the jump has to go somewhere. Normally we hide numeric values behind label names. Now, if we look at this one level down we get this picture:
This is what you'd actually see when you disassemble the binary file. After cognew(@C_og1, address) has finished the first 10 registers in the cog will look like this (location 9 will be more or less random depending on what your SPIN code looks like).
Is this OK so far? Can you see how the first loop works?
Sorry about the brevity to my response, but I tend to only answer the question.
I haven't read the whole thread, but I think I know where kuroneko is going with this.
DAT org 0 ' cog address
C_og1loop1 mov 9, $1F0 ' $000 move the contents of register $1F0 (aka PAR, i.e. the second parameter in the SPIN cognew statement) to register 9wrlong7, 9 ' $001 write the contents of register 7 to the HUB address pointed to by the contents of register 9jmp #0 ' $002 move the immediate value 0 to the program counter, execution continues with the instruction in register 0C_og2loop2 mov 9, $1F0 ' $003 move the contents of register $1F0 (aka PAR, i.e. the second parameter in the SPIN cognew statement) to register 9add9, #4 ' $004 add the immediate value 4 to the contents of register 9wrlong8, 9 ' $005 write the contents of register 8 to the HUB address pointed to by the contents of register 9jmp #3 ' $006 move the immediate value 3 to the program counter, execution continues with the instruction in register 3one long 1 ' $007 the contents of register 7 is the value 1two long 2 ' $008 the contents of register 8 is the value 2mem res 1 ' $009 the contents of register 9 is undefined as no data is stored in HUB RAM for this register
So if you did a cognew(@C_og1, @variable) the value of variable would be continuously overwritten with the value 1 after ~8K clock cycles. However, if you tried to cognew(@C_og2, @variable) the value of variable would be overwritten with an unknown value only once after ~8K clock cycles. This is because the C_og2 instruction would be loaded into register 0, not register 3 and would look like:
DAT org 0 ' cog address
C_og2loop2 mov 9, $1F0 ' $000 move the contents of register $1F0 (aka PAR, i.e. the second parameter in the SPIN cognew statement) to register 9add9, #4 ' $001 add the immediate value 4 to the contents of register 9wrlong8, 9 ' $002 write the contents of register 8 to the HUB address pointed to by the contents of register 9jmp #3 ' $003 move the immediate value 6 to the program counter, execution continues with the instruction in register 3one long 1 ' $004 the contents of register 4 is the value 1two long 2 ' $005 the contents of register 5 is the value 2mem res 1 ' $006 the contents of register 6 is undefined as no data is stored in HUB RAM for this register
Very interesting indeed. The point of interest (getting it right) seems to have been made by "jazzed" by pointing out that we need another DAT statement to end what is contained in Cog1 before starting Cog2. That aside, I appreciate your taking the time to spell it all out for me so that I can hopefully pass the information on the beginners without messing it up.
An interesting aside to this is that I did not appreciate what kureneko was trying to get across to me and you saw it right away. I do not even understand the jargon at this time!! One more indication that beginners need to really start in the beginning and there seems to be no indicator, as far as I can see, as to where the beginning needs to be. Maybe I can help in that direction.
I am finding that a long declared as a PASM program constant at the bottom of the program can have its value changed by the program.
So it is not a constant forever the same as constants that are declared under CON.
Is this true and is it a proper use of a variable.
Or is just one way to declare a variable.
H
They are not constants but initialized variables. It it quite normal as you will see in many objects.
You can also change their values before launching the associated assembly cog if I remember rightly which can be useful and avoids having to send set-up parameters via par.
A long in DAT is not any kind of constant. It is initialized with what ever value you put in your code but can be changed by Spin or PASM after. But beware that long may be loaded into COG with your PASM in which case that same LONG you wrote has a dual existance, in the COG or COGs and the original place it occupied in HUB.
No you do not need to start a new DAT section to have more than one COGs PASM in an object.
Well I don't have the fat lady singing yet as regards the use of PAR.
I cannot figure out a simple rule that tells me when the variables being pointed to by PAR will be cleared or not.
What does one have to do or not do to preserve the variables across all cogs
And what does one have to do the clear them either on purpose or by mistake.
I can make it work but I am not sure I am doing it right. And things get messed up inadvertently.
i.e. I still don't have the confidence to tell beginners what to do or not do.
PAR is typically a pointer to a long in HUB RAM (which may be the first long in an array or list of longs). Note: due to how coginit (PASM) works, only bits 2-15 of PAR are valid; the other bits are zero; therefore PAR cannot point to a byte or word. It's also a read-only register.
Because HUB RAM is shared by all cogs, any cog can make updates. Changing the long pointed to by PAR is done via WRLOG register, PAR (where register contains the desired value).
I don't meant be flipant but I guess the simple as to when variables pointed to by PAR are cleared or not is:
If you clear them they are cleared. If you don't they are not.
I think you should answere kureneko's little quiz questions in pozt #542 before proceeding as we are suspecting a confusion over the use of DAT and/or ORG and/or RES here.
Well I don't have the fat lady singing yet as regards the use of PAR.
I cannot figure out a simple rule that tells me when the variables being pointed to by PAR will be cleared or not.
What does one have to do or not do to preserve the variables across all cogs
And what does one have to do the clear them either on purpose or by mistake.
I can make it work but I am not sure I am doing it right. And things get messed up inadvertently.
i.e. I still don't have the confidence to tell beginners what to do or not do.
Ericball answered the question in # 542. Iresponded by mading the corrections and posted to jazzed that everything wored fine for the simp[le programs that I was running. I dont think I am doing thingsany different now!!
======
Well I do think I am getting a handle on things so its not totally blind on my part.
Here is what I have going
Program 1
Reads a potentiometer stores it at Par pointer 1st position. Variable passed is @P_Val
Performs a division and stores the result in PAR pointer +16 the 5th long location
One routine displays the data, One stores it via PAR pointers.
Everything works fine I can read the data and it is what I want where I want it to be.
Running the program shows everything just right on the PST
No problems.
Program 2
Calls the all of the program in program 1 and everything is fine
Running the program shows everything just right on the PST
No problems.
Next I call just the part of the program that stored the variables in program 1
I get zeroes.
All routines that refer to the data use @V_Pal as the passed variable
Here are the listings you can comment routines out as you see fit.
{{
022 PASM Read4Pots.spin
Program to read 4 pots
Repeats the program GOOD 006 PASM ReadPot 4 times
Installs in separate cog.
Reads resistances to 12 bits appears in POT_RES global variable
15 Dec 2011
By Harprit Sandhu
}}
CON_clkmode = xtal1 + pll16x_xinfreq = 5_000_000
bits=12
pots=8VARlong P_Val[7]
long pot_sub
long clear
OBJ
fds : "FullDuplexSerial"PUBMain(address)'P_VAL is a local variable here
fds.start(31,30,0,115200) 'start console at 115200 for debug output
read_Pots(@P_Val)
dira[0..2]~~
repeat'endless loop
pot_sub:=0'reset id of pot to be printed
fds.tx($1) 'home to 0,0repeat pots 'loop to display data
fds.bin(P_val[pot_sub], bits) 'print to the PST in binary repeat2'two spaces
fds.tx(" ") 'space to erase old data overflow
fds.dec(P_val[pot_sub]) 'print value as decimal value repeat2'two spaces
fds.tx(" ") 'space to erase old data overflow
fds.dec(pot_sub*4) 'print value as decimal value repeat3'three spaces
fds.tx(" ") 'space to erase old data overflow
fds.tx($d) 'new line
pot_sub:=(pot_sub)+1'increment display counterwaitcnt(clkfreq/60+cnt) 'flicker free wait
clear:=clear+1'increment counter. This routine clears up screenif clear>10'decision point by erasing extra lines of bot
fds.tx(16) 'clear screen of PST display every 10 loops
clear:=0'reset counterPUBRead_Pots(address)cognew(@Read_P, address)
'----------------------------------end of first Cog------------------------------------------DATorg0'sets the starting point in Cog
Read_P movdira, set_dira 'sets direction of the prop pimov pots_read, #1'number of pots to read [also change data]mov bits_read, #12'bit resolution of 3208 IC, can be lessmov mem, par'get address of mem for PARmov mem1, mem
mov pot_id, #0'first pot read is pot 0
Next_pot orouta , chs_Bit 'makes Chip select highandnouta, chs_Bit 'makes chip select low andnouta , clk_bit 'ANDN it with the Clock Bit to make loworouta , din_Bit 'makes the Din highcall #Tog_clk 'toggle clock line hi-low to read dataorouta , din_Bit 'makes the Din high call #Tog_Clk 'toggle clock line hi-low to read datamov temp2, pot_id 'we will read three bits from this potcall #get_third_bit 'get bitif_nzjmp #its_one 'jump to set it as neededjmp #its_zero 'jump to set it as needed
its_one call #Set_next_bit1 'setting bit subroutine calljmp #continue1 'go to next bit
its_zero call #Set_next_bit0 'setting bit subroutine call
continue1 call #get_second_bit 'get bitif_nzjmp #its_one1 'jump to set it as neededjmp #its_zero1 'jump to set it as needed
its_one1 call #Set_next_bit1 'setting bit subroutine calljmp #continue2 'go to next bit
its_zero1 call #Set_next_bit0 'setting bit subroutine call
continue2 call #get_first_bit 'get bitif_nzjmp #its_one2 'jump to set it as neededjmp #its_zero2 'jump to set it as needed
its_one2 call #Set_next_bit1 'setting bit subroutine calljmp #continue3 'go to next bit
its_zero2 call #Set_next_bit0 'setting bit subroutine call
continue3 andnouta , din_Bit 'makes Din low call #Tog_Clk 'toggle clock line hi-low to read datacall #Tog_Clk 'toggle clock line hi-low to read data mov Data_read, #0'clear register we will read data into mov bit_count, bits_read 'counter for number of bits we will read
read_bit mov temp, ina'read in what is in all the input linesandn temp, mask26 wz'mask off except Dout line. Set Z flag shl Data_read, #1'shift register left 1 bit for next bitif_nzadd Data_read, #1'if value + add 1 to data register call #Tog_Clk 'toggle clock get next bit ready in Doutsub bit_count, #1wz'decr the "bits read" counter. Set Z flagif_nzjmp #read_bit 'go up do it again if counter not yet 0 wrlong Data_read, mem wz'write it in PAR to share it as P.Valif_zjmp #next_pot
call #get_beat
skip add mem1,#16wrlong data_read, mem1
add mem, #4'add 4 to hub address for next longmov mem1, mem
add pot_id, #1'so we can look at next potmov temp2, pot_id 'recall what pot we are readingsub temp2, pots_Read wz'check if it is how many we want to readif_nzjmp #Next_pot 'if it is not 0 go up and read next potjmp #Read_P 'go back beginning and do all pots again'subroutines used
Set_next_bit0 andnouta , din_Bit 'makes Din low in 000 for linecall #Tog_Clk 'toggle clock line hi-low to read data
Set_next_bit0_ret ret'return from this subroutine
Set_next_bit1 orouta , din_Bit 'makes Din high in 000 for linecall #Tog_Clk 'toggle clock line hi-low to read data
Set_next_bit1_ret ret'return from this subroutine
Tog_Clk nop'nop to settle signalsorouta, clk_bit 'make clock bit highnop'nop to settle signalsandnouta, clk_bit 'make clock bit lownop'nop to settle signals
Tog_Clk_ret ret'return from this subroutine
Get_first_bit mov temp2, pot_id 'get current pot numberandn temp2, mask0 wz'get last bit
Get_first_bit_ret ret'return
Get_second_bit mov temp2, pot_id 'get current pot numbershr temp2, #1'shift right 1 bit to get second bitandn temp2, mask0 wz'return
Get_second_bit_ret ret
Get_third_bit mov temp2, pot_id 'get current pot numbershr temp2, #2'shift right 2 bits to get third bitandn temp2, mask0 wz'return
Get_third_bit_ret ret
Get_beat mov temp3, data_read
shl temp3, #3mov total, clkf
mov beat, #0
do_again sub total, temp3 wcadd beat, #1if_ncjmp #do_again
sub beat, #1mov data_read, beat
Get_beat_ret ret
Set_dira long001011_00000000_00000000_00000111'Set dira register
Chs_Bit long000001_00000000_00000000_00000000'Chip select bit 24
Din_Bit long000010_00000000_00000000_00000000'Data in bit 25
Dout_Bit long000100_00000000_00000000_00000000'Data out bit 26
Clk_Bit long001000_00000000_00000000_00000000'Clock bit 27
mask26 long111011_11111111_11111111_11111111'Mask to read Dout bit
mask0 long111111_11111111_11111111_11111110'Mask to read 0 bit
clkf long80_000_000
beat res1
mem res1'Par location
mem1 res1
temp res1'temporary storage variable, misc
temp2 res1'temporary storage variable, misc
temp3 res1
bit_count res1'temporary storage variable, read bit counter
Data_Read res1'temporary storage variable, data being read
pot_id res1'current pot id number
pots_read res1'total number of pots to be read.
bits_Read res1'resolution of data read, 12 bits max
total res1{
OSC for metronome
Read pot and display on PST through 022 PASM Rea4PotsX
And sets up basic count oscillator
}CON_clkmode = xtal1 + pll16x_xinfreq = 5_000_000'bits=32VARlong P_Val[7]
obj
RP : "ReadPots"'reads potsPUBMaindira[0..2]~~
RP.main(@P_val)
'RP.read_Pots(@P_val)
Oscillate (@P_val)
PUBOscillate(address)cognew(@Oscil, address)
DATorg0
Oscil movdira, set_dira 'sets direction of the prop pins
loop mov mem, par'get par addressadd mem, #16rdlong Pot, mem
mov delay, cnt'read in CNTadd delay, 50'add to skip over counter fillandnouta, bit_1 'bits lowwaitcnt delay, pot 'pausemov delay, cnt'read in CNTadd delay, 50'add to skip over counter fillorouta, bit_1 'bits highwaitcnt delay, pot 'pausejmp #loop 'loop back
Set_dira long001011_00000000_00000000_00000111'Set dira register
bit_1 long000000_00000000_00000000_00000001'output bit
pot res1
mem res1'memory location for PAR variable
delay res1'delay constant for CNT
What does get zeroes actually mean (you don't have PST output in this case AFAICS)? It would also help if you used a technique (to attach code) which doesn't destroy binary constants.
What goes on here?
That code in post #557 does not even compile.
There are binary constants with out %
There are two _clkmode and _xinfreq which at least BST does not like.
No they don't. It would make it easier (and faster) for us to help you if you'd actually answer questions posed to you. Otherwise people will stop responding.
My sincerest apologies. I try to answer all questions unless someone else does or they other wise get discussed.
Or if I think they are tangential to a beginner's interests at this time.
I copied the programs from code that I was running so they should have compiled.
The % indicators were stripped by the discussion software.
I was unaware that it does that.
No one has ever mentioned it before to my knowledge.
As regards #558 I am not getting any output on the PST but if I put in 0s for the variables, I get the same output on the O'scope as if I had read 0s
@Jazzed
I will call Tech support on Monday and report the results
@Heater
I store the variables, I never clear them and then later I cannot read them. Something is happening that is causing them to be cleared and I cannot
figure out what it is. Till I know I cannot proceed with the book because this affects everything about my understanding of what is going on and how I explain it.
I've been at it for two weeks!!
@All
Lets try again with less code in the examples. I stripped almost everything that I could think of as unnecessary.
My code had the % binary designators in it but they were stripped by the discussion forum.
I do not know the reason.
I have eliminated them and shortened the code many times over to show just the essence of the problem I am having
The following code in the first program has two routines in it.
This program should be saved as "ReadPots2" when you save it. It will be called in a later program.
The first routine lets you look at the 12 LS bits on 8 registers, as longs, pointed to by PAR on the Parallax Serial Terminal
{{
Name this program"ReadPots2"
}}
CON_clkmode = xtal1 + pll16x_xinfreq = 5_000_000
bits=12
pots=8VARlong P_Val[7]
long pot_sub
long clear
OBJ
fds : "FullDuplexSerial"PUBMain'P_VAL is a local variable here
fds.start(31,30,0,115200) 'start console at 115200 for debug output
read_Pots(@P_Val)
show
PUBShowdira[0..2]~~
repeat'endless loop
pot_sub:=0'reset id of pot to be printed
fds.tx($1) 'home to 0,0repeat pots 'loop to display data
fds.bin(P_val[pot_sub], bits) 'print to the PST in binary repeat2'two spaces
fds.tx(" ") 'space to erase old data overflow
fds.dec(P_val[pot_sub]) 'print value as decimal value repeat2'two spaces
fds.tx(" ") 'space to erase old data overflow
fds.dec(pot_sub*4) 'print value as decimal value repeat3'three spaces
fds.tx(" ") 'space to erase old data overflow
fds.tx($d) 'new line
pot_sub:=(pot_sub)+1'increment display counterwaitcnt(clkfreq/60+cnt) 'flicker free wait
clear:=clear+1'increment counter. This routine clears up screenif clear>10'decision point by erasing extra lines of bot
fds.tx(16) 'clear screen of PST display every 10 loops
clear:=0'reset counterPUBRead_Pots(address)cognew(@Read_P, address)
DATorg0'sets the starting point in Cog
Read_P movdira, set_dira 'sets direction of the prop pimov mem, par'get address of mem for PARwrlong data1, mem
mov mem1, mem
add mem1, #16wrlong data2, mem1
jmp #Read_P
Set_dira long7'Set dira register
data1 long2000
data2 long500
mem res1'Par location
mem1 res1
The second routine in the first program stores 2000 at the first PAR location and 500 at the fifth PAR location as longs
The second program reads the fifth PAR locations and uses it as a delay to turn bit 1 on the propeller on and off so I can look at it with a scope.
It does not
It should also allow you to look at the 8 PAR longs but it does not. The PST remains blank
I am at a complete loss as to why this is happening. And I know its something stupid on my part.
{
Name this [U]program[/U] "Oscillator" it calls "ReadPots2" as a OBJ
}CON_clkmode = xtal1 + pll16x_xinfreq = 5_000_000
bits=12
pots=8VARlong P_Val[7]
obj
RP : "ReadPots2"'reads pots
fds : "FullDuplexSerial"PUBMaindira[0..2]~~
fds.start(31,30,0,115200) 'start console at 115200 for debug output
RP.read_Pots(@P_val)
RP.show
Oscillate (@P_val)
PUBOscillate(address)cognew(@Oscil, address)
DATorg0
Oscil movdira, set_dira 'sets direction of the prop pins
loop mov mem, par'get par addressadd mem, #16rdlong Pot, mem
mov delay, cnt'read in CNTadd delay, #50'add to skip over counter fillandnouta, bit_1 'bits lowwaitcnt delay, pot 'pausemov delay, cnt'read in CNTadd delay, #50'add to skip over counter fillorouta, bit_1 'bits highwaitcnt delay, pot 'pausejmp #loop 'loop back
Set_dira long7'Set dira register
bit_1 long1'output bit
pot res1'read variable
mem res1'memory location for PAR variable
delay res1'delay variable usage
The way I understand things, this should all work but it does not.
I am at a loss to understand why.
Your Show "pot_sub" variable increments forever, which means your output will probably be bogus after a few loops.
You add the contents of register 50 to your delay in DAT Oscil. What is in 50? Did you mean to use the value #50?
Of course Oscillate is never called since Show repeats forever.
I believe Kuroneko is asking you questions to inspire you to solve your own problems.
New knowledge can be cemented by thinking about such questions and answers.
Seems like he's trying to teach you how to fish.
A conference call may allow you to quickly resolve some software barriers in maybe a few minutes -vs- a few days.
The repeat that Pot_sub is is in, repeats pot times, so it get reset after reaching 7. It starts at 0.
The 50 is indeed mistake. Its should be #50. But I fixed that and it still does not work.
MAIN call three public methods each of which loops on its own. If Oscillate did not execute, nor would show
But show does execute because you can see the display of the PST which is called in show
Then I made the oscillator software a part of the ReadPots program. At the tail end.
Now the display show garbage numbers for the first and 5th longs in PAR but the
oscillation starts to work but it is insensitive to data changes in the 5th variable.
Very strange. I am as confused as I have ever been.
This is really driving me up the wall.
I'm going to re write the whole metronome object as one PASM routine with PASM subroutines to see what happens.
So I can examine variable my way.
Re #568 it means that you can write to PAR only with the last Cog you open. EVER. You cannot open a cog after the writes.
But...You read from other cogs in loops so that you re read the data after it was written later in the game.
Since this is not the case with my code, I need to recode
Re #568 it means that you can write to PAR only with the last Cog you open. EVER. You cannot open a cog after the writes.
But...You read from other cogs in loops so that you re read the data after it was written later in the game.
Since this is not the case with my code, I need to recode
Am I right?
H
There is a PAR register for every COG, so there is no interdependence between opening COG1 and COG2 (unless the value PAR passed for both cognew is the same).
I mean only that when you use cognew(@somecode, @somelong) the value of PAR is set to the address of somelong. Alternatively, cognew(@somecode, someaddr) will set PAR to the value of someaddr with the 2 lower bits cleared. That is the only way to set the value of PAR for a COG. If you write to PAR from inside the COG code, it is not changing PAR. Once PAR is set using cognew, it will not change.
You can change the data of the variable passed to PAR with no problem and read the data in the COG with rdlong, etc.... You just can't change PAR.
Comments
- What's the (cog) address of labels C_og1 and loop1?
- What's the (cog) address of labels C_og2 and loop2?
- What's are the (cog) addresses of labels one, two and mem?
(all in the context of the listed DAT block)Once we established that I have some more questions.
By cog address do you mean which cog they are running in (or have been instructed to run in)?.
@Ericball
I did not understand your post completely.
Please expand.
It is important for me to understand this thread in detail.
@jazzed
I made the changes you suggested and it does indeed work now. Thanks
Now to understand exactly what is going on! And why.
H
DAT org 0 ' cog address C_og1 loop1 mov 9, $1F0 ' $000 wrlong 7, 9 ' $001 jmp #0 ' $002 C_og2 loop2 mov 9, $1F0 ' $003 add 9, #4 ' $004 wrlong 8, 9 ' $005 jmp #3 ' $006 one long 1 ' $007 two long 2 ' $008 mem res 1 ' $009 DAT
This is what you'd actually see when you disassemble the binary file. After cognew(@C_og1, address) has finished the first 10 registers in the cog will look like this (location 9 will be more or less random depending on what your SPIN code looks like).Is this OK so far? Can you see how the first loop works?
I haven't read the whole thread, but I think I know where kuroneko is going with this.
DAT org 0 ' cog address C_og1 loop1 mov 9, $1F0 ' $000 move the contents of register $1F0 (aka PAR, i.e. the second parameter in the SPIN cognew statement) to register 9 wrlong 7, 9 ' $001 write the contents of register 7 to the HUB address pointed to by the contents of register 9 jmp #0 ' $002 move the immediate value 0 to the program counter, execution continues with the instruction in register 0 C_og2 loop2 mov 9, $1F0 ' $003 move the contents of register $1F0 (aka PAR, i.e. the second parameter in the SPIN cognew statement) to register 9 add 9, #4 ' $004 add the immediate value 4 to the contents of register 9 wrlong 8, 9 ' $005 write the contents of register 8 to the HUB address pointed to by the contents of register 9 jmp #3 ' $006 move the immediate value 3 to the program counter, execution continues with the instruction in register 3 one long 1 ' $007 the contents of register 7 is the value 1 two long 2 ' $008 the contents of register 8 is the value 2 mem res 1 ' $009 the contents of register 9 is undefined as no data is stored in HUB RAM for this register
So if you did a cognew(@C_og1, @variable) the value of variable would be continuously overwritten with the value 1 after ~8K clock cycles. However, if you tried to cognew(@C_og2, @variable) the value of variable would be overwritten with an unknown value only once after ~8K clock cycles. This is because the C_og2 instruction would be loaded into register 0, not register 3 and would look like:DAT org 0 ' cog address C_og2 loop2 mov 9, $1F0 ' $000 move the contents of register $1F0 (aka PAR, i.e. the second parameter in the SPIN cognew statement) to register 9 add 9, #4 ' $001 add the immediate value 4 to the contents of register 9 wrlong 8, 9 ' $002 write the contents of register 8 to the HUB address pointed to by the contents of register 9 jmp #3 ' $003 move the immediate value 6 to the program counter, execution continues with the instruction in register 3 one long 1 ' $004 the contents of register 4 is the value 1 two long 2 ' $005 the contents of register 5 is the value 2 mem res 1 ' $006 the contents of register 6 is undefined as no data is stored in HUB RAM for this register
Very interesting indeed. The point of interest (getting it right) seems to have been made by "jazzed" by pointing out that we need another DAT statement to end what is contained in Cog1 before starting Cog2. That aside, I appreciate your taking the time to spell it all out for me so that I can hopefully pass the information on the beginners without messing it up.
An interesting aside to this is that I did not appreciate what kureneko was trying to get across to me and you saw it right away. I do not even understand the jargon at this time!! One more indication that beginners need to really start in the beginning and there seems to be no indicator, as far as I can see, as to where the beginning needs to be. Maybe I can help in that direction.
Thanks again I appreciated it.
H
So it is not a constant forever the same as constants that are declared under CON.
Is this true and is it a proper use of a variable.
Or is just one way to declare a variable.
H
You can also change their values before launching the associated assembly cog if I remember rightly which can be useful and avoids having to send set-up parameters via par.
Graham
No you do not need to start a new DAT section to have more than one COGs PASM in an object.
Well I don't have the fat lady singing yet as regards the use of PAR.
I cannot figure out a simple rule that tells me when the variables being pointed to by PAR will be cleared or not.
What does one have to do or not do to preserve the variables across all cogs
And what does one have to do the clear them either on purpose or by mistake.
I can make it work but I am not sure I am doing it right. And things get messed up inadvertently.
i.e. I still don't have the confidence to tell beginners what to do or not do.
H
Because HUB RAM is shared by all cogs, any cog can make updates. Changing the long pointed to by PAR is done via WRLOG register, PAR (where register contains the desired value).
If you clear them they are cleared. If you don't they are not.
I think you should answere kureneko's little quiz questions in pozt #542 before proceeding as we are suspecting a confusion over the use of DAT and/or ORG and/or RES here.
Ericball answered the question in # 542. Iresponded by mading the corrections and posted to jazzed that everything wored fine for the simp[le programs that I was running. I dont think I am doing thingsany different now!!
======
Well I do think I am getting a handle on things so its not totally blind on my part.
Here is what I have going
Program 1
Reads a potentiometer stores it at Par pointer 1st position. Variable passed is @P_Val
Performs a division and stores the result in PAR pointer +16 the 5th long location
One routine displays the data, One stores it via PAR pointers.
Everything works fine I can read the data and it is what I want where I want it to be.
Running the program shows everything just right on the PST
No problems.
Program 2
Calls the all of the program in program 1 and everything is fine
Running the program shows everything just right on the PST
No problems.
Next I call just the part of the program that stored the variables in program 1
I get zeroes.
All routines that refer to the data use @V_Pal as the passed variable
Here are the listings you can comment routines out as you see fit.
{{ 022 PASM Read4Pots.spin Program to read 4 pots Repeats the program GOOD 006 PASM ReadPot 4 times Installs in separate cog. Reads resistances to 12 bits appears in POT_RES global variable 15 Dec 2011 By Harprit Sandhu }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 bits=12 pots=8 VAR long P_Val[7] long pot_sub long clear OBJ fds : "FullDuplexSerial" PUB Main (address) 'P_VAL is a local variable here fds.start(31,30,0,115200) 'start console at 115200 for debug output read_Pots(@P_Val) dira[0..2]~~ repeat 'endless loop pot_sub:=0 'reset id of pot to be printed fds.tx($1) 'home to 0,0 repeat pots 'loop to display data fds.bin(P_val[pot_sub], bits) 'print to the PST in binary repeat 2 'two spaces fds.tx(" ") 'space to erase old data overflow fds.dec(P_val[pot_sub]) 'print value as decimal value repeat 2 'two spaces fds.tx(" ") 'space to erase old data overflow fds.dec(pot_sub*4) 'print value as decimal value repeat 3 'three spaces fds.tx(" ") 'space to erase old data overflow fds.tx($d) 'new line pot_sub:=(pot_sub)+1 'increment display counter waitcnt(clkfreq/60+cnt) 'flicker free wait clear:=clear+1 'increment counter. This routine clears up screen if clear>10 'decision point by erasing extra lines of bot fds.tx(16) 'clear screen of PST display every 10 loops clear:=0 'reset counter PUB Read_Pots(address) cognew(@Read_P, address) '----------------------------------end of first Cog------------------------------------------ DAT org 0 'sets the starting point in Cog Read_P mov dira, set_dira 'sets direction of the prop pi mov pots_read, #1 'number of pots to read [also change data] mov bits_read, #12 'bit resolution of 3208 IC, can be less mov mem, par 'get address of mem for PAR mov mem1, mem mov pot_id, #0 'first pot read is pot 0 Next_pot or outa , chs_Bit 'makes Chip select high andn outa, chs_Bit 'makes chip select low andn outa , clk_bit 'ANDN it with the Clock Bit to make low or outa , din_Bit 'makes the Din high call #Tog_clk 'toggle clock line hi-low to read data or outa , din_Bit 'makes the Din high call #Tog_Clk 'toggle clock line hi-low to read data mov temp2, pot_id 'we will read three bits from this pot call #get_third_bit 'get bit if_nz jmp #its_one 'jump to set it as needed jmp #its_zero 'jump to set it as needed its_one call #Set_next_bit1 'setting bit subroutine call jmp #continue1 'go to next bit its_zero call #Set_next_bit0 'setting bit subroutine call continue1 call #get_second_bit 'get bit if_nz jmp #its_one1 'jump to set it as needed jmp #its_zero1 'jump to set it as needed its_one1 call #Set_next_bit1 'setting bit subroutine call jmp #continue2 'go to next bit its_zero1 call #Set_next_bit0 'setting bit subroutine call continue2 call #get_first_bit 'get bit if_nz jmp #its_one2 'jump to set it as needed jmp #its_zero2 'jump to set it as needed its_one2 call #Set_next_bit1 'setting bit subroutine call jmp #continue3 'go to next bit its_zero2 call #Set_next_bit0 'setting bit subroutine call continue3 andn outa , din_Bit 'makes Din low call #Tog_Clk 'toggle clock line hi-low to read data call #Tog_Clk 'toggle clock line hi-low to read data mov Data_read, #0 'clear register we will read data into mov bit_count, bits_read 'counter for number of bits we will read read_bit mov temp, ina 'read in what is in all the input lines andn temp, mask26 wz 'mask off except Dout line. Set Z flag shl Data_read, #1 'shift register left 1 bit for next bit if_nz add Data_read, #1 'if value + add 1 to data register call #Tog_Clk 'toggle clock get next bit ready in Dout sub bit_count, #1 wz 'decr the "bits read" counter. Set Z flag if_nz jmp #read_bit 'go up do it again if counter not yet 0 wrlong Data_read, mem wz 'write it in PAR to share it as P.Val if_z jmp #next_pot call #get_beat skip add mem1,#16 wrlong data_read, mem1 add mem, #4 'add 4 to hub address for next long mov mem1, mem add pot_id, #1 'so we can look at next pot mov temp2, pot_id 'recall what pot we are reading sub temp2, pots_Read wz 'check if it is how many we want to read if_nz jmp #Next_pot 'if it is not 0 go up and read next pot jmp #Read_P 'go back beginning and do all pots again 'subroutines used Set_next_bit0 andn outa , din_Bit 'makes Din low in 000 for line call #Tog_Clk 'toggle clock line hi-low to read data Set_next_bit0_ret ret 'return from this subroutine Set_next_bit1 or outa , din_Bit 'makes Din high in 000 for line call #Tog_Clk 'toggle clock line hi-low to read data Set_next_bit1_ret ret 'return from this subroutine Tog_Clk nop 'nop to settle signals or outa, clk_bit 'make clock bit high nop 'nop to settle signals andn outa, clk_bit 'make clock bit low nop 'nop to settle signals Tog_Clk_ret ret 'return from this subroutine Get_first_bit mov temp2, pot_id 'get current pot number andn temp2, mask0 wz 'get last bit Get_first_bit_ret ret 'return Get_second_bit mov temp2, pot_id 'get current pot number shr temp2, #1 'shift right 1 bit to get second bit andn temp2, mask0 wz 'return Get_second_bit_ret ret Get_third_bit mov temp2, pot_id 'get current pot number shr temp2, #2 'shift right 2 bits to get third bit andn temp2, mask0 wz 'return Get_third_bit_ret ret Get_beat mov temp3, data_read shl temp3, #3 mov total, clkf mov beat, #0 do_again sub total, temp3 wc add beat, #1 if_nc jmp #do_again sub beat, #1 mov data_read, beat Get_beat_ret ret Set_dira long 001011_00000000_00000000_00000111 'Set dira register Chs_Bit long 000001_00000000_00000000_00000000 'Chip select bit 24 Din_Bit long 000010_00000000_00000000_00000000 'Data in bit 25 Dout_Bit long 000100_00000000_00000000_00000000 'Data out bit 26 Clk_Bit long 001000_00000000_00000000_00000000 'Clock bit 27 mask26 long 111011_11111111_11111111_11111111 'Mask to read Dout bit mask0 long 111111_11111111_11111111_11111110 'Mask to read 0 bit clkf long 80_000_000 beat res 1 mem res 1 'Par location mem1 res 1 temp res 1 'temporary storage variable, misc temp2 res 1 'temporary storage variable, misc temp3 res 1 bit_count res 1 'temporary storage variable, read bit counter Data_Read res 1 'temporary storage variable, data being read pot_id res 1 'current pot id number pots_read res 1 'total number of pots to be read. bits_Read res 1 'resolution of data read, 12 bits max total res 1 { OSC for metronome Read pot and display on PST through 022 PASM Rea4PotsX And sets up basic count oscillator } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 'bits=32 VAR long P_Val[7] obj RP : "ReadPots" 'reads pots PUB Main dira[0..2]~~ RP.main(@P_val) 'RP.read_Pots(@P_val) Oscillate (@P_val) PUB Oscillate (address) cognew(@Oscil, address) DAT org 0 Oscil mov dira, set_dira 'sets direction of the prop pins loop mov mem, par 'get par address add mem, #16 rdlong Pot, mem mov delay, cnt 'read in CNT add delay, 50 'add to skip over counter fill andn outa, bit_1 'bits low waitcnt delay, pot 'pause mov delay, cnt 'read in CNT add delay, 50 'add to skip over counter fill or outa, bit_1 'bits high waitcnt delay, pot 'pause jmp #loop 'loop back Set_dira long 001011_00000000_00000000_00000111 'Set dira register bit_1 long 000000_00000000_00000000_00000001 'output bit pot res 1 mem res 1 'memory location for PAR variable delay res 1 'delay constant for CNT
Harprit.
PUB Main dira[0..2]~~ RP.read_Pots(@P_val) Oscillate (@P_val)
What does get zeroes actually mean (you don't have PST output in this case AFAICS)? It would also help if you used a technique (to attach code) which doesn't destroy binary constants.That code in post #557 does not even compile.
There are binary constants with out %
There are two _clkmode and _xinfreq which at least BST does not like.
Each will compile
H
My sincerest apologies. I try to answer all questions unless someone else does or they other wise get discussed.
Or if I think they are tangential to a beginner's interests at this time.
I copied the programs from code that I was running so they should have compiled.
The % indicators were stripped by the discussion software.
I was unaware that it does that.
No one has ever mentioned it before to my knowledge.
As regards #558 I am not getting any output on the PST but if I put in 0s for the variables, I get the same output on the O'scope as if I had read 0s
@Jazzed
I will call Tech support on Monday and report the results
@Heater
I store the variables, I never clear them and then later I cannot read them. Something is happening that is causing them to be cleared and I cannot
figure out what it is. Till I know I cannot proceed with the book because this affects everything about my understanding of what is going on and how I explain it.
I've been at it for two weeks!!
@All
Lets try again with less code in the examples. I stripped almost everything that I could think of as unnecessary.
My code had the % binary designators in it but they were stripped by the discussion forum.
I do not know the reason.
I have eliminated them and shortened the code many times over to show just the essence of the problem I am having
The following code in the first program has two routines in it.
This program should be saved as "ReadPots2" when you save it. It will be called in a later program.
The first routine lets you look at the 12 LS bits on 8 registers, as longs, pointed to by PAR on the Parallax Serial Terminal
{{ Name this program"ReadPots2" }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 bits=12 pots=8 VAR long P_Val[7] long pot_sub long clear OBJ fds : "FullDuplexSerial" PUB Main 'P_VAL is a local variable here fds.start(31,30,0,115200) 'start console at 115200 for debug output read_Pots(@P_Val) show PUB Show dira[0..2]~~ repeat 'endless loop pot_sub:=0 'reset id of pot to be printed fds.tx($1) 'home to 0,0 repeat pots 'loop to display data fds.bin(P_val[pot_sub], bits) 'print to the PST in binary repeat 2 'two spaces fds.tx(" ") 'space to erase old data overflow fds.dec(P_val[pot_sub]) 'print value as decimal value repeat 2 'two spaces fds.tx(" ") 'space to erase old data overflow fds.dec(pot_sub*4) 'print value as decimal value repeat 3 'three spaces fds.tx(" ") 'space to erase old data overflow fds.tx($d) 'new line pot_sub:=(pot_sub)+1 'increment display counter waitcnt(clkfreq/60+cnt) 'flicker free wait clear:=clear+1 'increment counter. This routine clears up screen if clear>10 'decision point by erasing extra lines of bot fds.tx(16) 'clear screen of PST display every 10 loops clear:=0 'reset counter PUB Read_Pots(address) cognew(@Read_P, address) DAT org 0 'sets the starting point in Cog Read_P mov dira, set_dira 'sets direction of the prop pi mov mem, par 'get address of mem for PAR wrlong data1, mem mov mem1, mem add mem1, #16 wrlong data2, mem1 jmp #Read_P Set_dira long 7 'Set dira register data1 long 2000 data2 long 500 mem res 1 'Par location mem1 res 1
The second routine in the first program stores 2000 at the first PAR location and 500 at the fifth PAR location as longs
===================================================================
The second program reads the fifth PAR locations and uses it as a delay to turn bit 1 on the propeller on and off so I can look at it with a scope.
It does not
It should also allow you to look at the 8 PAR longs but it does not. The PST remains blank
I am at a complete loss as to why this is happening. And I know its something stupid on my part.
{ Name this [U]program[/U] "Oscillator" it calls "ReadPots2" as a OBJ } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 bits=12 pots=8 VAR long P_Val[7] obj RP : "ReadPots2" 'reads pots fds : "FullDuplexSerial" PUB Main dira[0..2]~~ fds.start(31,30,0,115200) 'start console at 115200 for debug output RP.read_Pots(@P_val) RP.show Oscillate (@P_val) PUB Oscillate (address) cognew(@Oscil, address) DAT org 0 Oscil mov dira, set_dira 'sets direction of the prop pins loop mov mem, par 'get par address add mem, #16 rdlong Pot, mem mov delay, cnt 'read in CNT add delay, #50 'add to skip over counter fill andn outa, bit_1 'bits low waitcnt delay, pot 'pause mov delay, cnt 'read in CNT add delay, #50 'add to skip over counter fill or outa, bit_1 'bits high waitcnt delay, pot 'pause jmp #loop 'loop back Set_dira long 7 'Set dira register bit_1 long 1 'output bit pot res 1 'read variable mem res 1 'memory location for PAR variable delay res 1 'delay variable usage
The way I understand things, this should all work but it does not.
I am at a loss to understand why.
H
- Your Show "pot_sub" variable increments forever, which means your output will probably be bogus after a few loops.
- You add the contents of register 50 to your delay in DAT Oscil. What is in 50? Did you mean to use the value #50?
- Of course Oscillate is never called since Show repeats forever.
I believe Kuroneko is asking you questions to inspire you to solve your own problems.New knowledge can be cemented by thinking about such questions and answers.
Seems like he's trying to teach you how to fish.
A conference call may allow you to quickly resolve some software barriers in maybe a few minutes -vs- a few days.
The repeat that Pot_sub is is in, repeats pot times, so it get reset after reaching 7. It starts at 0.
The 50 is indeed mistake. Its should be #50. But I fixed that and it still does not work.
MAIN call three public methods each of which loops on its own. If Oscillate did not execute, nor would show
But show does execute because you can see the display of the PST which is called in show
Then I made the oscillator software a part of the ReadPots program. At the tail end.
Now the display show garbage numbers for the first and 5th longs in PAR but the
oscillation starts to work but it is insensitive to data changes in the 5th variable.
Very strange. I am as confused as I have ever been.
H
You are right about the loop in show.
It has to be called after the other methods start.
H
OK.
Is it possible the encountering a DAT resets everything in the world of PAR
H
The contents of the long variable pointed to by PAR can change of course, but not by the DAT statement.
I'm going to re write the whole metronome object as one PASM routine with PASM subroutines to see what happens.
So I can examine variable my way.
H
Re #568 it means that you can write to PAR only with the last Cog you open. EVER. You cannot open a cog after the writes.
But...You read from other cogs in loops so that you re read the data after it was written later in the game.
Since this is not the case with my code, I need to recode
Am I right?
H
There is a PAR register for every COG, so there is no interdependence between opening COG1 and COG2 (unless the value PAR passed for both cognew is the same).
I mean only that when you use cognew(@somecode, @somelong) the value of PAR is set to the address of somelong. Alternatively, cognew(@somecode, someaddr) will set PAR to the value of someaddr with the 2 lower bits cleared. That is the only way to set the value of PAR for a COG. If you write to PAR from inside the COG code, it is not changing PAR. Once PAR is set using cognew, it will not change.
You can change the data of the variable passed to PAR with no problem and read the data in the COG with rdlong, etc.... You just can't change PAR.