Spin - WHILE?
cavelamb
Posts: 720
More lessons from a blinkin' LED...
I've been messing with this one on and off for several days.
I'm trying to get the Repeat/While loop working.
I could code around it, but that doesn't teach me how to do it the right way...
Wha-zup?
I've been messing with this one on and off for several days.
I'm trying to get the Repeat/While loop working.
I could code around it, but that doesn't teach me how to do it the right way...
Wha-zup?
{{ Blinky6.spin }} CON _CLKMODE=XTAL1+PLL2X _XINFREQ =5_000_000 HI, ON, ONE,P_OUT = 1 LO, OFF, ZERO, P_IN = 0 PO_LED = 07 PI_SWITCH = 06 SlowWait = 5_000_000 FastWait = 1_000_000 VAR BYTE X,Y,Z PUB MAIN dira [PO_LED] := P_OUT 'output pin for LED outa [PO_LED] := LO dira [PI_SWITCH] := P_IN 'input pin for button X:=0 Repeat x+=1 if X==8 X:=1 Z := byte [NUMS[X]] Repeat Z BlinkFast Repeat y := ina[PI_Switch] While Y > 0 ' page 41, 107 in the manual!! PUB BlinkFast outa[PO_LED] := HI waitCNT (FastWait+cnt) outa[PO_LED] := LO waitCNT (FastWait+cnt) DAT NUMS Byte 1,2,3,4,5,6,7
Comments
-Phil
Andy
repeat while Y>0
?
Z := byte...
is not on the same indent level.
Indentation is vital in spin. Get it wrong and you will get all sorts of problems.
I suggest you turn on the indentation markers in PropTool to check you have what you expect.
4x5n:
When the while is at the end of the repeat loop, the loop is executed once before the while test. If the while test is at the beginning of the repeat loop, if the alue does not satisfy the while test, then the loop will not be executed. Each have their own valid use in coding.
it makes the code more readable
it makes the code configrable
it removes runtime calculations
If you use constants for timing you should think about making these constanst depend on _CLKFREQ. Then it's easier to modify the code for a board that uses a different chrystal or that uses RCFast/Slow.
By the way .. it's very usual that constants are written in UPPERCASE. This way you easily know whether you're looking at a constant or a variable.
So, what I would not do is replace the operators ~ and ~~ by constants. Why? Because ~ and ~~ are well known by each SPIN-programmer and there is no need to lookup the value of P_IN or P_OUT in the constant block.
From brain-debugging I would say that your code does not work. The problems are
Z := byte [NUMS[X]]
and
X:=0
Repeat
x+=1
byte[] needs an address which points to some data in memory. But you feed it with NUMS[X] which goes from 2 to 7. So, actually your blink funktion will blink depending on the content of HUB-RAM addresses 2 - 7 which is not really in your hand ;oP
What you could write is byte[ @NUMS[X] ] or byte[ @NUMS + X ] or simply NUMS[X].
An array starts with index 0, but your code sets X to 1 minimum. So, here are my corrections:
OK, indentation thingie turned on and yeah, that's probably a good idea.
It would be better if indented blocks could be block-moved, but ...
For some reason the code is just not seeing the button.
If works (right even!) in the other little programs, so I know the hardware is ok.
But since I'm not getting the pause there, I wasn't at all sure the Repeat/While was ok.
The button has a 10k pull-up on port 6, hence SW_ON and SW_OFF logic.
The LED has a 33 to +3.3 on port 7.
Simplifying the code, It _should_
Fetch the 4th number in NUMS,
Then Repeat Z should blink the light that many times.
Then wait for a Button to be pressed.
But it just blinks it's fool head off... (bad habits are hard to break)
Setting pin direction to INPUT for the switch...
but
dira [PI_SWITCH] :=P_IN doesn't
Underscore not allowed there?
Or limit for definitions on one line?
If you use the PropTool you can place the cursor on a constant (after successful compilation). The status line will show you its value.
I'm a sloppy old Assembly programmer from the dark ages and haven't done any programming in years.
My style (or lack there of) may be painful for a while.
But I'll work on it.
~ and ~~ still look totally mysterious to me. Which is ~ and which is ~~ ??
To my eye it's unreadable... But maybe it will come... I just need to stay at it.
Your suggestion actually worked - after a couple of things.
_CLKFREQ came up undefined - so I changed it to _XINFREQ
and you left one of my Constants in place - which was then also undefined.
So I changed that to ~ and it worked - perfectly.
So...
byte[ @NUMS[X] ] or byte[ @NUMS + X ] or simply NUMS[X] to access my local data
and
Z := byte [NUMS[X]] will read from hub memory.
(and get comfortable with ~ and ~~)
Now THAT is mighty useful to know...
Arigato kuroneko-san
"So...
byte[ @NUMS[X] ] or byte[ @NUMS + X ] or simply NUMS[X] to access my local data
and
Z := byte [NUMS[X]] will read from hub memory."
SPIN only has access to HUB memory. Only PASM code has access to COG RAM.
The point is, when doing Z := byte [NUMS[X]] the value that ends up in Z is not taken from your array. What does the propeller do in this case:
1. it has a look into X and finds a 1 for the first iteration
2. it has a look into NUM[ X ] which is actually NUM[ 1 ] and finds 2 - remember indexes start from 0
3. it then can resolve byte[] ... but it's doing it with byte[ 2 ]. This means it's reading byte 2 of the whole HUB-RAM which is not where your array is stored! And that's why you got some crazy blinking.
_CLKFREQ specifies the System Clock frequency for start-up. It is a pre-defined constant symbol whose value is determined by the top object file of an application. _CLKFREQ is either set directly by the application itself, or is set indirectly as the result of the _CLKMODE and _XINFREQ settings.
So, I currently don't understand why it should not be available.
But for sure it is better to use _CLKFREQ instead of _XINFREQ if you want to create constants for certain waittimes, because _CLKFREQ is really the number of clocks per second. When using _XINFREQ you also need to consider the clock-mode (especially the PLL settings).
If you are using the Prop Tool, you can move (and indent) blocks of code. See the " Code Block Indenting" section of the prop manual. Pg 71 in my printed v1.0 manual.
I've always thought that the "while" went on the repeat line and only ever used it that way. Being able to put it at the end of the block could have saved me some trouble. :-)
Thank you for expanding on that.
I'm trying to understand the difference between the forms, and obviously got it wrong.
It was late over here and I was getting punchy.
I remember that the program and all data is stored in the hub.
The cog gets the Spin interpreter.
And, yes, I do understand your point about the 0th index.
The real problem though was how to access MY data.
In playing around with it, I had moved the index to 1 just to see if I could return a reasonable number.
I was getting a couple of hundred blinks where I was expecting only 1 or 2.
Were you were saying that my mistake was in forming the expression...
Z := byte[NUMS[x]] instead of using Z := NUMS[X] ?
I just tried it again.
_CLKFREQ is shown in BOLD, so Spin Tool is recognizing the term.
but using it as below generates an Undefined Symbol error.
Back to the manual...
But it works if you define _CLKFREQ yourself:
And after that you can use _CLKFREQ for calculating your waitcnt-values.
There is a way of setting wait times as constants using some trick. JonnyMac has written about it in his SpinZone articles and it's also used in the Prop Library's "Clock.spin" object.