Welcome to the Parallax Discussion Forums, sign-up to participate.
{
******** Propeller I/O assignments ***********
P0 RGB data
P1 RGB clock
}
CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000
numLEDs = 8
LEDdata = 0
LEDclock = 1
PUB startup
dira[LEDdata]~~ ' LED strip data line
outa[LEDdata]~
dira[LEDclock]~~ ' LED strip clock line
outa[LEDclock]~
colorTest
PRI colorTest | i
streamByte(0)
repeat i from 1 to 3*numLEDs ' turn off all LEDs
streamByte( $80 )
'waitcnt( clkfreq/60 + cnt )
repeat ' forever
streamByte(0) ' primes LED strip to receive new data
repeat i from 1 to numLEDs ' magenta
streamByte( $FF ) ' Blue . . . LED addressing order is Blue Red Green (not RGB)
streamByte( $FF ) ' Red
streamByte( $80 ) ' Green
waitcnt( clkfreq/2 + cnt ) ' 1/2 second between color changes
streamByte(0)
repeat i from 1 to numLEDs ' red
streamByte( $80 )
streamByte( $FF )
streamByte( $80 )
waitcnt( clkfreq/2 + cnt )
streamByte(0)
repeat i from 1 to numLEDs ' yellow
streamByte( $80 )
streamByte( $FF )
streamByte( $FF )
waitcnt( clkfreq/2 + cnt )
streamByte(0)
repeat i from 1 to numLEDs ' green
streamByte( $80 )
streamByte( $80 )
streamByte( $FF )
waitcnt( clkfreq/2 + cnt )
streamByte(0)
repeat i from 1 to numLEDs ' cyan
streamByte( $FF )
streamByte( $80)
streamByte( $FF )
waitcnt( clkfreq/2 + cnt )
streamByte(0)
repeat i from 1 to numLEDs ' blue
streamByte( $FF )
streamByte( $80 )
streamByte( $80 ) ' keep green on
waitcnt( clkfreq/2 + cnt )
PRI streamByte(d)
d ><= 8 ' reverse bit order to shift out MSB first
repeat 8
if (d & 1) <> 0
outa[LEDdata]~~
outa[LEDclock]~~ ' high
outa[LEDclock]~ ' low
outa[LEDdata]~
d >>= 1
Attempt at conversion to P2 spin:
{
LPD8806 LED Driver
******** Propeller I/O assignments ***********
P54 RGB data
P52 RGB clock
}
CON
CLK_FREQ = 200_000_000 ' system freq as a constant
_clkfreq = CLK_FREQ ' set system clock
numLEDs = 8
ledData = 54
ledClock = 52
PUB startup()
dirb[ledData]~~ ' LED strip data line
outb[ledData]~
dirb[ledClock]~~ ' LED strip clock line
outb[ledClock]~
colorTest()
PRI colorTest() | i
streamByte(0)
repeat i from 1 to 3*numLEDs ' turn off all LEDs
streamByte( $80 )
waitms(500) ' 1/2 second between color changes
repeat ' forever
streamByte(0) ' primes LED strip to receive new data
repeat i from 1 to numLEDs ' magenta
streamByte( $FF ) ' Blue . . . LED addressing order is Blue Red Green (not RGB)
streamByte( $FF ) ' Red
streamByte( $80 ) ' Green
waitms(500) ' 1/2 second between color changes
streamByte(0)
repeat i from 1 to numLEDs ' red
streamByte( $80 )
streamByte( $FF )
streamByte( $80 )
waitms(500) ' 1/2 second between color changes
streamByte(0)
repeat i from 1 to numLEDs ' yellow
streamByte( $80 )
streamByte( $FF )
streamByte( $FF )
waitms(500) ' 1/2 second between color changes
streamByte(0)
repeat i from 1 to numLEDs ' green
streamByte( $80 )
streamByte( $80 )
streamByte( $FF )
waitms(500) ' 1/2 second between color changes
streamByte(0)
repeat i from 1 to numLEDs ' cyan
streamByte( $FF )
streamByte( $80)
streamByte( $FF )
waitms(500) ' 1/2 second between color changes
streamByte(0)
repeat i from 1 to numLEDs ' blue
streamByte( $FF )
streamByte( $80 )
streamByte( $80 ) ' keep green on
waitms(500) ' 1/2 second between color changes
PRI streamByte(d)
d REV= d ' reverse bit order to shift out MSB first
repeat 8
if (d & 1) <> 0
outb[ledData]~~
outb[ledClock]~~ ' high
outb[ledClock]~ ' low
outb[ledData]~
d >>= 1
Comments
For low-level IO like this, it's best not to do a direct translation. The P2 has built-in IO commands that are in fact faster than the way you're trying to do it.
Give this a go: If you want even faster output, you can use inline PASM2. Try this, too.
BTW... when using the P1, I find it best to use direct assignments which are faster versus the cryptic post-set and clear operators. For you P1 version: This code is faster and easier to understand. Of course, LED_DATA and LED_CLOCK must be set to output mode before using this method.
Thanks for the code Jon! I tried the P2 Spin code first along with changing the clock to 20MHz. I'm getting a response finally from the LEDs, it seems to be a rapid flashing of the green and red portions of the RGBs but at least I'm finally getting some output! Interesting that it takes about 8 seconds after downloading before the LEDs start to flash.
I'll try out the PASM2 next. I've been reading up on PASM but still getting my head wrapped around it, the last assembly I did regularly was on a 1802 CMOS processor many years ago, finally getting a need to think at that level again. I've been using a nice driver object in the P1 library to run the LPD8806. That driver is all done using pasm but I need to learn more before I attempt to update that driver. In the meantime I thought I'd find a spin-based driver to convert and learn on.
Good catch, didn't even notice that part. It runs at 20Mhz but not 200Mhz.
This is my first attempt, got it to compile but I'm not getting any output to the LED strip. I know there are a couple of things in the assembly code (using dira for one) that compiles but should be another command instead. I think I got the code right for bringing in the parameters via the ptra register.
Suggestions?
Maybe should be "long led_data[10]" or so?
Also, in your assembly, you are reading in only the par1 value with the rdlong.
But, you need to read in the value of 3 more parameters with rdlongs...
Just change the assembly parameters from type "res" to type "long".
Then, set them in the Spin code before starting the cog...
While you *can* do a near direct translation of P1 to P2 PASM, the P2 instruction set is larger and has many instructions that simplify things. After looking at your code and the Adafruit driver, this is how I coded the P2 assembly section (compiles, but no hardware to test with). Notice that it's shorter due to the nice instructions in the P2.
I've attached my test file (object and test code in one place). If you can verify that this works, I'll break out the object code and get it posted. I'm guessing you already have some LPD8806 strips -- they don't seem particularly popular, and it's hard to find good info about them. The best info came from the comments of the Adafruit driver.
Okay... back to a P1 project that has been kicking my butt for far too long....
JonnyMac, I’ll try out your test file and see what happens. I want to go through each line to really understand what is happening there. I spent a lot of time reading and looking at P2 assembly code, is there any written in-depth descriptions for the P2 assembly code out there like what is available for the P1 assembly yet? So far my best resource has been searching the forum and reading applicable P2 threads.
There's a link at propeller.parallax.com
The only thing I know of is the OE object that I used in my P1 code. Not sure what you mean by a instructions spreadsheet? The data sheet from the manufacturer doesn’t give any usable info (most info I ever found was from the Adafruit website) on timing or protocols. The manufacturer was really trying to keep everything proprietary, probably that’s why it never became popular/wide spread.
-- https://docs.google.com/spreadsheets/d/1_vJk-Ad569UMwgXTKTdfJkHYHpc1rZwxB-DcIiAZNdk/edit#gid=0
I misunderstood what Ray was referring to! Yes, I have that spreadsheet up continuously on the screen while studying P2 assembly.
After verifying I had Clk and data on the right pins I ran the code. The results are that only the 8 red LEDs are active continuously. No sign of the green or blue LEDs being active. Interestingly P56-P59 on the P2 Eval board LEDs are pulsing between half and full brightness a little faster than once per second.
I'm going to put in some debugging code into this and see if I can figure out what is happening. I'm running this code using Propeller Tool version 2.3.00 Alpha in case that makes a difference.
The rdlong repeats, while both addresses internally are incremented (ie the addresses of clk and ptra get incremented)
So, reads 5 longs from hub pointed to by ptra, into cog registers starting at clk.
That is fantastic, this version worked right off the bat. Now I need to study the pasm code and understand what it is really doing and how. What logic analyzer are you using?
I really appreciate your help, this is my first real attempt at pasm, still have a lot to learn! Have a great Thanksgiving tomorrow!
Bob
When traveling as I am this week, I use this $13 logic analyzer:
-- https://www.amazon.com/gp/product/B077LSG5P2
It's not fancy, but for simple projects like this it works well.
The software that controls it is:
-- https://sigrok.org/wiki/PulseView
It even has built in protocol analyzers that I've used when developing P2 code for 1-Wire and my SPI object.
There is a set of color constants in this driver.
Thanks for trying this. I checked it with the logic analyzer and it appears to be working properly.
-- Jon