I think I will put together a YouTube video so people can follow along where turn single led on, and final step is a full-blown pwm trailing led knightrider
Here is step3, (it does not use OR/ANDN for pins yet) Questions?
CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000
VAR
long symbol 'not used yet
PUB StartRider
cognew(@entry,0) 'cognew needs two varibles, the start address of pasm code and a (optional) varible to pass along
DAT
org 0
entry mov DIRA,_mypins 'set LED control pins P16-P23 as output
main mov t1,#7 'run loop 7 times, so set varible t1 to 7
loop mov OUTA,_pin 'set the LED we want on
mov t2,cnt 'copy current Prop Master Counter value to t2
add t2,_delay 'add a 1/16sec delay
waitcnt t2,0 'tell cog to wait until MasterCounter match t2
shifter shl _pin,#1 'shift left 7 times and then shift right 7 times.
djnz t1,#loop 'so do 7 in a row, if not at at 0 jmp to loop
xor shifter,_bit26 'self-mod the shl into a shr
jmp #main 'jmp to main, don't forget the #
_bit26 long 1<<26 'same as |<26
_mypins long %11111111<<16 'same as %00000000_11111111_00000000_00000000
_pin long |<16 'same as %00000000_00000001_00000000_00000000
_delay long 80_000_000/16 '80 mill (MHz) divided by 16 = 1/16sec
t1 res 'reserve a temp var, will be initiated to a value by code
t2 res
With everyone help, I have decided to put this board away for a little bit, and use PSAM to get me started learning. Then after I start getting the hang of it, bringing out the Atmel board and start playing with it.
A useful way to learn Assembler (on any micro), is with a Good Simulator.
Some of the better tool flows let you mix HLL and the created Assembler, in the Simulator/Debug, but most will give listings of Source and created-Assembler.
I think the AVR Studio includes a Simulator.
Another easy-access path into small micros (which can be useful next to a Prop ) is something like TOOLSTICK850-B-SK
That is ~ $10, and gives you USB-hardware debug access, into a small, sub $1 uC with 12b ADC UART SPI i2c PWM Timers etc.
Tools are all free.
I agree with jmg. An alternative is to use a framework, or template where things like getting output or taking input are solved, leaving just the important guts to learn about.
One of the reasons I did character drivers on the Prop, was to build a little PASM framework like I always had or did on older machines.
This is also why blinking the LED, then controlling the blink, and finally, blinking in response to input is the "coming of age" trifecta usually able to get somebody going in assembly language.
On the P1, SPIN is really awesome in how PASM gets loaded onto a COG, making extremely lean, simple and effective PASM programs possible.
We will very likely have in-line PASM on the next chip, which is the only easier thing I have ever encountered.
(more, I just realized I need to change batteries... brb, don't want to lose what I have written)
The next best thing really is a starter template or two. The one TonyP put out there is a nice start. Adding the basic code to take a value from PAR would flesh it out to be a nice starting point for almost anything.
From there, it's a one or two strategy approach.
If you've got a simulator, great! Use it to run your template and understand everything it does. Then, you can take that template, drop new instructions into it and learn what they do.
If you don't have a simulator, then you work through the template, changing things, and following all of what it does through, until you understand what it's doing. Then, you drop new instructions in, and output results you can use to understand them.
One basic skill is thinking up quick, clever tests to determine whether or not something is happening. This is the debug LED basically. Based on this, or that, it can be turned on, or off, and with just that LED, you can understand the instructions pretty well, and find out what your program is doing.
To be a good asm programmer you must be able to see that it must be a bit pattern somewhere.
Here is the above code again, but without a loop as it ANDs (TEST) pin variable with %10000001 to see if result is 0.
DAT
org 0
entry mov DIRA,_mypins 'set LED control pins P16-P23 as output
main mov OUTA,_pin 'set the LED we want on
mov t2,cnt 'copy current Prop Master Counter value to t2
add t2,_delay 'add a 1/16sec delay
waitcnt t2,0 'tell cog to wait until MasterCounter match t2
shifter shl _pin,#1 'shift left 7 times and then shift right 7 times.
test _pin,_ends wz 'if pin is at any place of x in 0xxxxxxx0, the result is that z is set
if_nz xor shifter,_bit26 'self-mod the shl into a shr
jmp #main 'jmp to main, don't forget the #
_bit26 long 1<<26 'same as |<26
_mypins long %11111111<<16 'same as %00000000_11111111_00000000_00000000
_pin long |<16 'same as %00000000_00000001_00000000_00000000
_ends long %10000001<<16 'same as %00000000_10000001_00000000_00000000
_delay long 80_000_000/16 '80 mill (MHz) divided by 16 = 1/16sec
t2 res 'reserve a temp var, will be initiated to a value by code
It certainly doesn't hurt to focus on programing in just one Cog until you see an obvious need for more.
Assembly language focuses on what the CPU is doing and you have 8 of them available. Too many CPUs doing many things may get you caught up in passing data back and forth rather than in learning to control the CPU.
When you do move on to more than one CPU, spending a lot of time with just TWO may make sense to fully leaarn how Cogs do share.
In other words, try to have a study model that offers you the ability to clearly visualize what is going on, and what your resources are really doing.
Same function as above, but with a look-up table (resulting that any/many LEDs could be on at the same time as you have complete animation control)
DAT
org 0
entry mov DIRA,_mypins 'set LED control pins P16-P23 as output
main mov t1,#14 'run loop 14 times, so set varible t1 to 14
movs animator,#_pin_table 'reset the look-up-table address in self-mod code 0-0, don't forget the mov[b]s[/b] and the #
loop mov t2,cnt 'copy current Prop Master Counter value to t2
add t2,_delay 'add a 1/14sec delay
waitcnt t2,0 'tell cog to wait until MasterCounter match t2
animator mov OUTA,0-0 'set the LED we want on
add animator,#1 'next table byte (longs are "bytes" in cogs)
djnz t1,#loop 'so do 14 in a row, if not at at 0 jmp to loop
jmp #main 'jmp to main, don't forget the #
_pin_table long %00000001<<16, %00000010<<16, %00000100<<16, %00001000<<16, %00010000<<16, %00100000<<16, %01000000<<16
long %10000000<<16, %01000000<<16, %00100000<<16, %00010000<<16, %00001000<<16, %00000100<<16, %00000010<<16
_mypins long %11111111<<16 'same as %00000000_11111111_00000000_00000000
_delay long 80_000_000/14 '80 mill (MHz) divided by 14 = 1/14sec
t1 res 'reserve a temp var, will be initiated to a value by code
t2 res 'reserve a temp var, will be initiated to a value by code
Same look-up table, but it's in HUB and the array's start @address is passed along with PAR, Spin can now modify the table on the fly as this memory space is continuously read by the cog
CON
_clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz
_xinfreq = 5_000_000
VAR
long pin_table[14] ' reserve a 14 long array
PUB StartRider
PrepareTable 'run the subroutine below to setup a knightrider animation
cognew(@entry,@pin_table) 'cognew needs two varibles, the start address of pasm code and a (optional) varible to pass along
PUB PrepareTable
pin_table[0] := %00000001<<16
pin_table[1] := %00000010<<16
pin_table[2] := %00000100<<16
pin_table[3] := %00001000<<16
pin_table[4] := %00010000<<16
pin_table[5] := %00100000<<16
pin_table[6] := %01000000<<16
pin_table[7] := %10000000<<16
pin_table[8] := %01000000<<16
pin_table[9] := %00100000<<16
pin_table[10]:= %00010000<<16
pin_table[11]:= %00001000<<16
pin_table[12]:= %00000100<<16
pin_table[13]:= %00000010<<16
DAT
org 0
entry mov DIRA,_mypins 'set LED control pins P16-P23 as output
main mov t1,#14 'run loop 14 times, so set varible t1 to 14
mov hubpnt,PAR 'use the address in PAR that was passed along when cognew
loop mov t2,cnt 'copy current Prop Master Counter value to t2
add t2,_delay 'add a 1/12sec delay
waitcnt t2,0 'tell cog to wait until MasterCounter match t2
rdlong OUTA,hubpnt 'set the LED we want on
add hubpnt,#4 'next table long (longs are 4 bytes in hub)
djnz t1,#loop 'so do 14 in a row, if not at at 0 jmp to loop
jmp #main 'jmp to main, don't forget the #
_mypins long %11111111<<16 'same as %00000000_11111111_00000000_00000000
_delay long 80_000_000/12 '80 mill (MHz) divided by 14 = 1/12sec
hubpnt res 'PAR is read-only and can not be incremented, plus we need its original value later on anyway
t1 res 'reserve a temp var, will be initiated to a value by code
t2 res 'reserve a temp var, will be initiated to a value by code
Comments
Here is step3, (it does not use OR/ANDN for pins yet) Questions?
A useful way to learn Assembler (on any micro), is with a Good Simulator.
Some of the better tool flows let you mix HLL and the created Assembler, in the Simulator/Debug, but most will give listings of Source and created-Assembler.
I think the AVR Studio includes a Simulator.
Another easy-access path into small micros (which can be useful next to a Prop ) is something like TOOLSTICK850-B-SK
That is ~ $10, and gives you USB-hardware debug access, into a small, sub $1 uC with 12b ADC UART SPI i2c PWM Timers etc.
Tools are all free.
useful simulators for this 8 bit core are
http://www.ieap.uni-kiel.de/surface/ag-berndt/lehre/fpmc/index-e.html
and
http://turbo51studio.orgfree.com/downloads/turbo51studio-latest-setup.zip
One of the reasons I did character drivers on the Prop, was to build a little PASM framework like I always had or did on older machines.
This is also why blinking the LED, then controlling the blink, and finally, blinking in response to input is the "coming of age" trifecta usually able to get somebody going in assembly language.
On the P1, SPIN is really awesome in how PASM gets loaded onto a COG, making extremely lean, simple and effective PASM programs possible.
We will very likely have in-line PASM on the next chip, which is the only easier thing I have ever encountered.
(more, I just realized I need to change batteries... brb, don't want to lose what I have written)
http://www.iar.com/Products/IAR-Embedded-Workbench/
From there, it's a one or two strategy approach.
If you've got a simulator, great! Use it to run your template and understand everything it does. Then, you can take that template, drop new instructions into it and learn what they do.
If you don't have a simulator, then you work through the template, changing things, and following all of what it does through, until you understand what it's doing. Then, you drop new instructions in, and output results you can use to understand them.
One basic skill is thinking up quick, clever tests to determine whether or not something is happening. This is the debug LED basically. Based on this, or that, it can be turned on, or off, and with just that LED, you can understand the instructions pretty well, and find out what your program is doing.
Here is the above code again, but without a loop as it ANDs (TEST) pin variable with %10000001 to see if result is 0.
Assembly language focuses on what the CPU is doing and you have 8 of them available. Too many CPUs doing many things may get you caught up in passing data back and forth rather than in learning to control the CPU.
When you do move on to more than one CPU, spending a lot of time with just TWO may make sense to fully leaarn how Cogs do share.
In other words, try to have a study model that offers you the ability to clearly visualize what is going on, and what your resources are really doing.