Propeller Education kit Lab 4 Question
reppig
Posts: 35
I am working through the Education kit lab manual. I could not figure out how to do one of program assignments, so I looked at the answer in the back. The answer just made things worse.
I understand the program flow and I have written my own program based on the answer but, I really want to understand the answer. The code is below. This is supposed to make leds blink at different freq. without using more than one cog. My questions are
1) In the CON section, Why use values shown for the LEDs?? Like 2310 @ 80 MHz = 57.75e-6 sec??? I just do not understand the timing.
2) In the update LED state at the bottom, Why does LED16 change state?? My understanding is since count is pre-incremented the if statement checks the equality first then increments. So, at 2309 not equal count goes to 2310, next time it is equal and count is set to 0??
BTW - in case you have a book the leds are labeled different here because I re-wrote the code to my setup to see if it works.
Thanks in advance.
CON 'Declaration of Constants Block
_clkmode = xtal1 + pll16x ' Feedback and PLL multiplier time 16 = 80MHz Clk
_xinfreq = 5_000_000 ' External oscillator = 5 MHz Crystal on X0 & X1
' cnt = .0125 usec or 1 sec = 80e6
LED16 = 2310 '1 hz
LED17 = 1155 '2 hz
LED18 = 770 '3 hz
LED19 = 462 '5 hz
LED20 = 330 '7 hz
LED21 = 210 '11 hz -- 2310 / 210 = 11
PUB Lab4_3 | T, dT, count 'Declaration of Public Modules
dira[noparse][[/noparse]16..21]~~
dT := clkfreq / 4620 '80e6 / 4620 = 17_316.01732 = 57.75e-6
T := cnt
repeat 'repeats for 2310 x 57.75e-6 = .1334 sec.
T += dT
waitcnt(T) 'wait 57.75e-6 sec
if ++count == 2310 'Pre-Increment = increment before checking == count increments once every 57.75e-6 secs.
count := 0
if count // LED16 == 0 '1st thru
!outa[noparse][[/noparse]16]
if count // LED17 == 0
!outa[noparse][[/noparse]17]
if count // LED18 == 0
!outa[noparse][[/noparse]18]
if count // LED19 == 0
!outa[noparse][[/noparse]19]
if count // LED20 == 0
!outa[noparse][[/noparse]20]
if count // LED21 == 0
!outa[noparse][[/noparse]21]
I understand the program flow and I have written my own program based on the answer but, I really want to understand the answer. The code is below. This is supposed to make leds blink at different freq. without using more than one cog. My questions are
1) In the CON section, Why use values shown for the LEDs?? Like 2310 @ 80 MHz = 57.75e-6 sec??? I just do not understand the timing.
2) In the update LED state at the bottom, Why does LED16 change state?? My understanding is since count is pre-incremented the if statement checks the equality first then increments. So, at 2309 not equal count goes to 2310, next time it is equal and count is set to 0??
BTW - in case you have a book the leds are labeled different here because I re-wrote the code to my setup to see if it works.
Thanks in advance.
CON 'Declaration of Constants Block
_clkmode = xtal1 + pll16x ' Feedback and PLL multiplier time 16 = 80MHz Clk
_xinfreq = 5_000_000 ' External oscillator = 5 MHz Crystal on X0 & X1
' cnt = .0125 usec or 1 sec = 80e6
LED16 = 2310 '1 hz
LED17 = 1155 '2 hz
LED18 = 770 '3 hz
LED19 = 462 '5 hz
LED20 = 330 '7 hz
LED21 = 210 '11 hz -- 2310 / 210 = 11
PUB Lab4_3 | T, dT, count 'Declaration of Public Modules
dira[noparse][[/noparse]16..21]~~
dT := clkfreq / 4620 '80e6 / 4620 = 17_316.01732 = 57.75e-6
T := cnt
repeat 'repeats for 2310 x 57.75e-6 = .1334 sec.
T += dT
waitcnt(T) 'wait 57.75e-6 sec
if ++count == 2310 'Pre-Increment = increment before checking == count increments once every 57.75e-6 secs.
count := 0
if count // LED16 == 0 '1st thru
!outa[noparse][[/noparse]16]
if count // LED17 == 0
!outa[noparse][[/noparse]17]
if count // LED18 == 0
!outa[noparse][[/noparse]18]
if count // LED19 == 0
!outa[noparse][[/noparse]19]
if count // LED20 == 0
!outa[noparse][[/noparse]20]
if count // LED21 == 0
!outa[noparse][[/noparse]21]
Comments
there is a minimum-time for the waitcnt-command
everything below waitcnt(385) will fail because the SPIN-interpreter needs some time to execute the interpreting overhead
before he can execute the PASM-command waitcnt.
If code waitcnt(383) the systemcounter has gone beyond the matching value and then it will take time until the 32-bit-systemcounter has rolled-over from max to zero and
counted up again to the matching value
in easy values
at start of executing the SPIN-command WaitCnt (383) actual-cnt-value 1000
this means match-value is 1383
now when the interpreter executes the pasm-command waitcnt the actual actual-cnt-value at 1384
no matching until counter rolls over to zero (and that needs time to count up to from 1384 to 4.294.967.296 rollover to zero and count from 0 up to the matching-value 1383 (about 53 seconds at 80 MHz)
As this code would like to have 11 Hz as the maximum blink-frequency the time-base is 385*12= 4260 clock-ticks
by toggling a pin you get half the frequency
wait 0.1 seconds toggle => pin is ON
wait 0.1 seconds toggle => pin is OFF
wait 0.1 seconds toggle => pin is ON
wait 0.1 seconds toggle => pin is OFF
so from ON to ON it is 0.2 seconds
this explains the divider 4620 / 2 = 2310
all the dividisions must result in remainder 0
2310 / 11 = 210 remainder 0
2310 / 7 = 330 remainder 0
2310 / 5 = 462 remainder 0
2310 / 3 = 770 remainder 0
2310 / 2 = 1155 remainder 0
the following democode shows how this if ++count ==2310 condition works
you can use this debug-method everytime you have difficulties to understand what is going on
best regards
Stefan
When I did the program I set waitcnt to 1 msec. and work in msec and the program worked fine. I was lucky 385 is approx. .0048 msec.
so I was above the min time.
Thanks again I will make note of the min time for future ref.
The project asks for 6 pins to be pulse modulated at different frequencies. The minimum waitcnt value of 385 doesn't come in to play. Instead the user has to be aware of how long all of the spin statements after the waitcnt(T). I measured this to be 130uS at 80MHz. So the dT :=clkfreq/MagicNumber has to be bigger than 10400 in order for this code to work.
The MagicNumber turns out to be pretty simple to figure out. You need a number that is divisible by all of the frequencies so that you don't miss any pulses. So in this case: 1*2*3*5*7*11 = 2310 Multiple this by 2 to get the 4620. Each trigger value is then 4620/2/freq. Example: 4620/2/7=330
This will work for several different values such as 1,2,3,4,5,6 since the MagicNumber in this case is 720x2=1440. And...this is important...80_000_000/1440 = 55555 and is bigger than the cycle time of 10400.
However, if you chose 1,3,5,7,9,11 = 10395x2=20790 then 80_000_000/20790=3848 and is not greater than the cycle time of 10400. You will be stuck waiting for the counter to cycle all the way back around (53sec at 80MHz)!
Project 3 in the chapter 4 (page 66) originally asks for 1,2,3,7,12,13 Hz. This will not work with the solution supplied and is possibly the reason that the author of the program solution chose different frequencies.
Another approach is just to use PWM_32_v2.spin on the OBEX or write it in ASM or use more cogs! The project does an excellent job achieving its goal of making you glad you are using a Propeller and not those things we used in the olden days with only one processor.