 |
Using Spin
 |
Taking a look at SPIN code timing...
|
 |
Using WaitCnt (from Manual's Toggle example):
 |
PUB Toggle(Pin, Delay, Count)
{{Toggle Pin, Count times with Delay clock cycles in between.}}
dira[Pin]~~ 'Set I/O pin to output direction
repeat Count 'Repeat for Count iterations
!outa[Pin] ' Toggle I/O Pin
waitcnt(Delay + cnt) ' Wait for Delay cycles
|
 |
Turns out that minimum "Delay" is 381. This is due to the
time it takes the SPIN interpreter to process the command.
With a delay of 381 (4.762 us), the Toggle pulse is 21.00-us wide
and the period of the cycle is 42.00 us.
|
 |
This is no where near what we need!
|
|
 |
Using !OutA chain
 |
Instead of using WaitCnt, to insert delay, just using a chain of
!OutA commands. This is probably about the fastest that SPIN
can affect the output without using the counter module.
|
 | PUB Toggle2(Pin, Delay, Count)
{{Toggle Pin, Count times with Delay clock cycles in between.}}
dira[Pin]~~ 'Set I/O pin to output direction
!outa[Pin]
!outa[Pin]
!outa[Pin]
!outa[Pin]
!outa[Pin]
!outa[Pin]
!outa[Pin] |
 |
This produces a train of pulses with 9.20-us width and 18.40-us
period. Again, this is not fast enough to achieve 1-us timing.
|
|
 |
Using Counter Module
 |
This seems a little tricky, but maybe can program the counter
module with SPIN to get the desired output...
|
 |
Trying this code (adapted from the Propeller Counters App Note).
 |
PUB Toggle3(Pin)
'Use cog's counter module to toggle at clock speed
dira[Pin]~~ 'Set I/O pin to output direction
' mode PLL BPIN APIN
ctra := %00100_000 << 23 + 1 << 9 + Pin 'Establish mode and APIN
(BPIN is ignored)
frqa := $8000_0000 'Set FRQA so PHSA[31] toggles every clock
'repeat 'infinite loop, so counter
|
|
 |
This produces a 12.6-ns wide pulse with 25.0-ns period!
So, it seems we can get fast behavior with SPIN.
|
 |
But, what I really need is to control pulses on 2 pins.
One is on for 54 us, then off for the balance of 110-us period.
The other should be off for 55 us, then on for 54 us, then off for
the balance.
|
 |
Problem is that I want to be able to generate exactly 100 of
these pulses and then stop. I don't see an easy way to do this
precisely...
|
|
|
 |
Using Assembly
 |
Fast Toggle Loop
 |
This is a slightly modified version of the first example in
deSilva's assembly guide. It was modified to only affect pin7
instead of pins0..7
|
 | PUB Toggle4
'toggle with assembly
cognew(@ex01A, 0)
DAT
ORG 0
ex01A
MOV DIRA, #$80 '(Cell 0) Make P7 output
MOV pattern, #0 '(Cell 1) Initialize output parameter
loop
MOV OUTA, pattern '(Cell 2) Output the pattern to P7
ADD pattern, #$80 '(Cell 3) Toggle P7 output
JMP #loop '(Cell 4) repeat loop
pattern LONG $AAAAAAAA '(Cell 5)
FIT 496
|
 |
This produces a 150-ns pulse width 300-ns period
|
 |
Each instruction takes 50-ns, so this makes sense as there are 3
instructions in the toggle loop.
|
|
 |
Hard Coded Toggling
 |
In order to achieve 50-ns pulse width, we can hard code the
toggling: |
 |
PUB Toggle5
'toggle with assembly
cognew(@HardCode, 0)
DAT
ORG 0
HardCode
MOV DIRA, #$80 '(Cell 0) Make P7 output
MOV OUTA, #0 'init to 0
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
XOR OUTA, #$80 'toggle
'now stop
COGID thisCog
COGSTOP thisCog
thisCog LONG 5 '0=SPIN, 1=keyboard, 2=mouse, 3=VGA, 4=VGA, 5=This
FIT 496
|
 |
This produces 6 pulses with 50-ns width and 100-ns period. |
 |
But, we can only have 496 instructions, so the total possible burst
length is 24.8 us. But, I need about 200 ms of pulses, so this
won't work... |
|
 |
Using CMP n,CNT
 |
What I'd really like to do is control two (or more) pins, each with
pulse parameters:
 |
Delay: wait this long from start time before starting pulse
|
 |
Width: pulse is this long |
|
 |
And, global parameters:
 |
Period: start over again after this time |
 |
# in Burst: repeat for this number of periods |
|
 |
Because I only need 1-us precision, I can afford a few extra
instructions on the loop. Each instruction is 50 ns. So, I
need 20 instructions in the loop... |
 |
Finally, got it going with 1-us loop time! Here's the core
code: |
 | InitClock
'get initial clock time
MOV StartCNT,CNT
'Start period loop
CycleLoop
NOP 'to syncronize cycle and burst loops
NOP
BurstLoop
MOV pattern1, DMaskT0 '#$00 're-init output pattern
MOV thisCNT, CNT 'get current clock time
SUB thisCNT, StartCNT 'calc offset from period start time
'see if it is time to start pulse
CMP thisCNT, DelayA wz, wc
IF_AE OR pattern1,DMaskA
CMP thisCNT, DelayB wz, wc
IF_AE OR pattern1,DMaskB
CMP thisCNT, DelayC wz, wc
IF_AE OR pattern1,DMaskC
'see if time to end pulse
CMP thisCNT,WidthA wz, wc
IF_AE XOR pattern1,DMaskA
CMP thisCNT,WidthB wz, wc
IF_AE XOR pattern1,DMaskB
CMP thisCNT,WidthC wz, wc
IF_AE XOR pattern1,DMaskC
'output pattern
MOV OUTA, pattern1
'see if time to end period
CMP thisCNT,Period wz, wc
IF_B JMP #CycleLoop
'start new period
MOV StartCNT, CNT
DJNZ NBurst,#BurstLoop
|
 |
Sadly, can only control 3 channels this way
(was hoping for 4)
|
 |
Could probably do more channels with
more elaborate code, but this way is nice and simple.
|
 |
Have Implemented this and posted the "Delay
Generator Demo" to user forum. Can also be found here in the
programming section..
|
|
|