Faster Serial Data Sending
gwilli3
Posts: 3
Hello,
I am using the Propeller to serially drive 2 A6762 ICs to light up some LEDs.· I have not been able to get the LEDs to function (doing more than just staying lit or not turning on) without stalling for 381 clock cycles, which really limits my ability to fade colors.··I have been·loading·data to the·A6276 serially. ·Is there a way I can do this faster?· Here is my code.
PUB writeLong( _illuminate ) | illuminator
··· templumination := _illuminate
··· outa[noparse][[/noparse]outputenable] := 1················· 'disable LED output
··
··· illuminator := 0······
··· repeat illuminator from 0 to 15··········· ' sends eight bits as serial communication while pulsing latch enable
······ outa[noparse][[/noparse]serialoutpin] := templumination······· ' set data out pin to data
······ templumination >>= 1······················· ' shift to next bit····
······ outa[noparse][[/noparse]clockpin] := 1····················· ' set clock pin High
·
······ outa[noparse][[/noparse]clockpin] := 0····················· ' set clock pin Low
······ outa[noparse][[/noparse]latchenable] := 1·················· ' set latch enable high
······ outa[noparse][[/noparse]latchenable] := 0·················· ' set latch enable low
··· outa[noparse][[/noparse]outputenable] := 0················· 'enable LED output
I am using the Propeller to serially drive 2 A6762 ICs to light up some LEDs.· I have not been able to get the LEDs to function (doing more than just staying lit or not turning on) without stalling for 381 clock cycles, which really limits my ability to fade colors.··I have been·loading·data to the·A6276 serially. ·Is there a way I can do this faster?· Here is my code.
PUB writeLong( _illuminate ) | illuminator
··· templumination := _illuminate
··· outa[noparse][[/noparse]outputenable] := 1················· 'disable LED output
··
··· illuminator := 0······
··· repeat illuminator from 0 to 15··········· ' sends eight bits as serial communication while pulsing latch enable
······ outa[noparse][[/noparse]serialoutpin] := templumination······· ' set data out pin to data
······ templumination >>= 1······················· ' shift to next bit····
······ outa[noparse][[/noparse]clockpin] := 1····················· ' set clock pin High
·
······ outa[noparse][[/noparse]clockpin] := 0····················· ' set clock pin Low
······ outa[noparse][[/noparse]latchenable] := 1·················· ' set latch enable high
······ outa[noparse][[/noparse]latchenable] := 0·················· ' set latch enable low
··· outa[noparse][[/noparse]outputenable] := 0················· 'enable LED output
Comments
I don't really know the mentioned IC, but do you really have to set the latch enable to high/low after each bit? I'd expect that you first shift in your 16 bits and then do the latch-cycle.
Do you want the LEDs have different brightness? Otherwise it might be a solution to let a counter do the dimming by enable/disable the shift register outputs with PWM.
What you have to do is to shift 16 bits into your 2 registers by:
1. Set/Clear the data out pin
2. Wait for 50ns
3. Set clock to high
4. Wait for 50ns
5. set clock to low
6. Wait for 50ns
7. Repeat with 1 until the 16 bits have been shifted
8. Wait for 50ns
9. set latch to high
10. wait 100ns
11. set latch to low
Of course this is only the minimum time you have to wait. If your program is slower (and spin is much slower) there is no problem. With PASM it's possible to shift the data with the maximum speed. That would allow round about 300000 updates per second. Enough for a PWM.
The general brightness can be controlled by the output enable as well.
Thanks a lot,
gwilli3
cognew( @A6762_driver, @parameter_block)
As you see in the name, for a lot of devices that need to be driven by PASM-code, the model of a driver is used. The driver is started once and runs in the COG for the whole time. You use the parameter block to pass commands to it and for data-exchange.
Well, the implementation depends a little bit on what you want/need. 50ns waittime means you don't have to wait in the propeller at all because runtime of one instruction is exactly 50ns. So, I would simply repeat the sequence set pin, clock high, clock low 16 times. If you use a loop you loose speed for jumping.
Here is the first bunch of code. This is currently only test code, not driving an A6276. But it's the sceleton of the dirver code. The only part which is missing is shifting out the signals.
Please note, I use a 10MHz crystal, so please change the constants accordingly, if you want to run the code. The code is build for driving 9 LED's on pins 0-8. If you remove/change the lines marked with comment 'debug code' you can adopt it to your setup.
The functionality currently is to get the startup-parameters, which are all passed in one long variable. The high-word of the long is the wait-time. If a value other than 0 is given there, the driver waits after each unsucessful check of the parameter. A wait will decrease power consumption. If the parameter is 0, the startup routine moves some code to skip waiting.
In the two bytes of the low-word the pins have to be passed.
For synchronization the parameter is set to zero as soon as the driver is done with the work. If you have other things to do there is of course no need to sync.
The word to be send has to be passed in the high word. As the value can be zero and zero means 'nothing to do' for the driver, at least one bit of the low word should be set to start transmission.
Try to check out how this code works. Maybe you can try to do the rest by yourself. I'll continue tomorrow.
Bye
Post Edited (MagIO2) : 4/11/2009 10:58:54 PM GMT
I have deleted the extra latching and unlatching each loop iteration , but I am still having the same problem. I am trying to decipher the code that you have here, but I do not completely understand all of it. I am having problems with the PASM. The manual is not very demonstrative in its explanations of Pasm code. I have a few questions as well that may give you a better idea:
1) I see that you have the _xinfreq at 10_000_000. Is this from the A6276?
2) I do not know how to invoke PASM coding from another method or from another object. I know how to invoke methods from other or the same object in Spin. Can you tell me the difference.
3) I think that I am having problems somewhere in my data manipulation between sending serial data to the A6276. I can get the LEDs to blink at rates faster than the eye can detect when I just send some 1's and then all zeros in a repeating loop with minimal delay. But, when I try to manipualte the bits before sending them out, there seems to be some problem that causes ther to be a minimum wait time between iterations. Is spin too slow even at 80MHz? Do I need to do all the manipulations AND the sending of the data to the A6276 in PASM instead?
Thanks a lot.
--Glenn
a cog can run PASM OR SPIN.
it is NOT possible to mix PASM and SPIN on ONE cog
The reason is if you execute SPIN the SPIN-interpreter occupies the COMPLETE RAM of the cog (2kB).
SPIN-bytecode is stored in the HUB-RAM (32kB) The spin-interpreter fetches bytecode from HUB-RAM and
is interpreting it running PASM-interpreter code
PASM has to be in COG-RAM for execution
PASM is low-level programming compared to SPIN
The commands that you have are much simpler than a
"repeat X from 0 to 255"
or
"IF Var1 > 10) and (Var2 == 70) or (Var3 < 10)"
To see if it could be done in SPIN it would be interesting how many bits you have to shift-out as maximum
and if some calculations have to be done
maybe it is possible to do the calculations in one cog and the shifting-out in a second cog or a second method
best regards
Stefan
2) cognew is starting a new COG with the SPIN or PASM code you hand as first parameter. In SPIN you simply use the name of the SPIN-method. In PASM you pass the adress of the code using the @ as adress operator. But the PASM code I gave you is only called during initialisation at startup-time. From this time on, the PASM code is running endlessly. You communicate with it by using the A6276_par variable. What it really does still has to be defined in the ' this part is missing currently' -part.
So the difference is that if you are using a different COG for shifting out the bits to the A6276, your main program can go on without waiting and do something else. The A6276 code running in that COG of course can be in SPIN as well, but PASM will do it as fast as possible.
3) In your original post you said you want to fade colors. The A6276 will drive all LED's with a constant current, so you have to use PWM for fading. For a good PWM you will need a minimum speed. For a 8 bit PWM at a refresh rate of 40Hz and with independent PWM values per LED you need to send 256x40x16 bits per second (163840 bits/second). And a 8 bit PWM is not what you would call 'full color fading'. The problem is the eye, which does not recognizes the brightnes linear to the light emitted. So the effective number of different brightness values will be much smaller than 256.