 |
|
 |
| Parallax Forums > Public Forums > Propeller Chip > Assembly Code Examples for the Beginner | Forum Quick Jump
|
|  Javalin Got a Propeller, need some SPIN?
        Date Joined Jul 2004 Total Posts : 768 | Posted 8/20/2006 3:35 AM (GMT -7) |   | | Morning all,
I've just started into Propeller Assembly and I am having some issues with controlling/reading pins.
I can set a pin high using
But how do I set it LOW? I would assume from SX assembler you'd need a AND of all the pin bits bar pin10 in this case - i.e %111111111111111011111111111 (etc) Is there an easier way to do this?
or dira, SPI_ASM_CLK ' output
or outa, SPI_ASM_CLK ' HIGH
....
SPI_ASM_CLK long |< 10
I assume the same applies to DIRA and setting input(0) and output(1) modes
Then reading pins - I am using the following code - to read INA state:
mov input, #0 ' Zero input or input, INA ' Place the state of all the pins into input and input, SPI_ASM_DI ' Place the state of SDA into input
test input, SPI_ASM_DI WC ' If input AND SDA = 0 WZ=1 else = 1 WZ=0 if_c shl spiASMData,#1 if_c or spiASMData,#1 if_nc shl spiASMData,#1
.....
SPI_ASM_DI long |< 11
I get values back from it, but wrong ones.
As always grateful for any help!
James
Moderator Edit: By popular request this thread is being made a sticky. Post Edited By Moderator (Chris Savage (Parallax)) : 8/21/2006 5:19:48 PM GMT | | Back to Top | | |
  |  Javalin Got a Propeller, need some SPIN?
        Date Joined Jul 2004 Total Posts : 768 | Posted 8/20/2006 5:32 AM (GMT -7) |   | Parsko,
Doesn't that mean that i would need to know the state of the pin before I try to set it high or low?
Im not looking to toggle, but to set the pin state.
Thanks,
James | | Back to Top | | |
 |  Mike Green Registered Member

       Date Joined Oct 2004 Total Posts : 15579 | Posted 8/20/2006 6:08 AM (GMT -7) |   | | Use the ANDN instruction with a bit mask to set the pin low (or direction to input) and the OR instruction with the same bit mask to set the pin high (or direction to output). You can use the XOR instruction (with the same bit mask) to toggle the state of the pin. | | Back to Top | | |
 |  Javalin Got a Propeller, need some SPIN?
        Date Joined Jul 2004 Total Posts : 768 | Posted 8/20/2006 6:28 AM (GMT -7) |   | | | |
 |  parsko Engineer
        Date Joined Mar 2006 Total Posts : 475 | Posted 8/20/2006 8:40 AM (GMT -7) |   | James,
Sorry, I thought you just wanted to toggle it. When you set a pin to output, doesn't mean it is high, only that it is an output. Mike, I think they should add something that explicit in the manual, you said it well.
-Luke | | Back to Top | | |
 |  Javalin Got a Propeller, need some SPIN?
        Date Joined Jul 2004 Total Posts : 768 | Posted 8/20/2006 8:49 AM (GMT -7) |   | Agreed, I did look but could'nt see anything in the manual for this. The ANDN was too well hidden!
A few more ASM examples in the manual would be helpful!
Thanks for your help!
James | | Back to Top | | |
 |  Beau Schwabe (Parallax) IC Layout Engineer

       Date Joined Aug 2004 Total Posts : 3967 | Posted 8/20/2006 9:11 PM (GMT -7) |   | My personal opinion on this matter is to use a data MASK for the PIN you want to affect via the Propeller MUX commands.
Example #1 (Set Pin as a OUTPUT - Preset with LOW)
mov t1, #1 wz ' Configure Pin shl t1, Pin ' Create Mask with t1 muxz outa, t1 ' PreSet DataPin LOW "0" muxnz dira, t1 ' Set DataPin to an OUTPUT "1"
Example #2 (Set Pin as a OUTPUT - Preset with HIGH)
mov t1, #1 wz ' Configure Pin shl t1, Pin ' Create Mask with t1 muxnz outa, t1 ' PreSet DataPin HIGH "1" muxnz dira, t1 ' Set DataPin to an OUTPUT "1"
Example #3 (Set Pin as a INPUT )
mov t1, #1 wz ' Configure Pin shl t1, Pin ' Create Mask with t1 muxz dira, t1 ' Set DataPin to an INPUT "0"
'Pin' holds a value ranging between 0 and 31 corresponding to the I/O pin you want to affect. Beau Schwabe
IC Layout Engineer Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 8/21/2006 4:19:52 AM GMT | | Back to Top | | |
 |  parsko Engineer
        Date Joined Mar 2006 Total Posts : 475 | Posted 8/21/2006 12:25 AM (GMT -7) |   | Beau,
I feel that it is about time that there was an Assembly Tutorial Sticky containing examples just like this, in the same manner that there is a Spin beginners guide. A logical orgainization of it would be nice, but to have one place to look for assy examples would be more nice. I know I could post a few after my "high speed Shiftin" experiences...
-Parsko | | Back to Top | | |
  |  Beau Schwabe (Parallax) IC Layout Engineer

       Date Joined Aug 2004 Total Posts : 3967 | Posted 8/21/2006 10:01 AM (GMT -7) |   | Using a data MASK for I/O control via the Propeller MUX commands:
{ Example #1 (Set Pin as a OUTPUT - Preset with LOW) } PUB start cognew(@entry, 0)
DAT
entry org
mov t1, #1 wz ' Configure Pin shl t1, Pin ' Create Mask with t1 muxz outa, t1 ' PreSet Pin LOW "0" muxnz dira, t1 ' Set Pin to an OUTPUT "1" Pin long 1 'I/O Pin t1 res 1 'Pin Mask
{ Example #2 (Set Pin as a OUTPUT - Preset with HIGH) } PUB start cognew(@entry, 0)
DAT
entry org
mov t1, #1 wz ' Configure Pin shl t1, Pin ' Create Mask with t1 muxnz outa, t1 ' PreSet Pin HIGH "1" muxnz dira, t1 ' Set Pin to an OUTPUT "1" Pin long 1 'I/O Pin t1 res 1 'Pin Mask
{ Example #3 (Set Pin as a INPUT ) } PUB start cognew(@entry, 0)
DAT
entry org
mov t1, #1 wz ' Configure Pin shl t1, Pin ' Create Mask with t1 muxz dira, t1 ' Set Pin to an INPUT "0" Pin long 1 'I/O Pin t1 res 1 'Pin Mask
{ 'Pin' holds a value ranging between 0 and 31 corresponding to the I/O pin you want to affect. What I have been doing recently is to preserve the "mask" associated to each pin that I am using... in this case 't1'. By preserving the "mask" you can use other commands to conviently read or write to a specific bit. }
{ Example #4 (Set P0 as an INPUT and Set P16 an OUTPUT ; Show status of P0 on P16) } PUB start cognew(@entry, 0)
DAT
entry org
Initialize mov t1, #1 wz ' Configure Output pin shl t1, #16 ' Create mask with t1 - #P16 LED muxz outa, t1 ' Preset Output Pin LOW "0" muxnz dira, t1 ' Set pin as Output "1"
mov t2, #1 wz ' Configure Input pin shl t2, #0 ' Create mask with t2 - #P0 I/O muxz dira, t2 ' Set pin as Input "0" Loop test t2, ina wc ' Read Input pin via 't2' mask muxc outa, t1 ' Write Output pin via 't1' mask jmp #Loop
t1 res 1 'Output Mask t2 res 1 'Input Mask
{ Example #5 (Simple ShiftIn routine) } PUB start cognew(@entry, 0)
DAT
entry org
Initialize mov t1, #1 wz ' Configure Output pin shl t1, #1 ' Create mask with t1 - #P1 Clock muxz outa, t1 ' Preset Output Pin LOW "0" muxnz dira, t1 ' Set pin as Output "1"
mov t2, #1 wz ' Configure Input pin shl t2, #0 ' Create mask with t2 - #P0 Data muxz dira, t2 ' Set pin as Input "0"
mov t3, #8 ' Set number of bits to 8
Loop mov t1, #0 wz,nr ' Clock Pin muxz outa, t1 ' Set ClockPin HIGH muxnz outa, t1 ' Set ClockPin LOW ' Shift Bits in test t2, ina wc ' Read Data Bit into 'C' flag rcl t4, #1 ' rotate "C" flag into return value
djnz t3, #Loop ' Decrement t3 ; jump if not Zero
t1 res 1 'Clock Mask t2 res 1 'Data Mask t3 res 1 'Number of Bits t4 res 1 'Received Data
Beau Schwabe
IC Layout Engineer Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 8/21/2006 7:21:59 PM GMT | | Back to Top | | |
 |  Javalin Got a Propeller, need some SPIN?
        Date Joined Jul 2004 Total Posts : 768 | Posted 8/21/2006 10:06 AM (GMT -7) |   | Beau,
Thanks for the post! Very useful!
James | | Back to Top | | |
 |  parsko Engineer
        Date Joined Mar 2006 Total Posts : 475 | Posted 8/21/2006 11:50 AM (GMT -7) |   | Beau,
Please include the minimum SPIN code. Your example is not so obvious to the beginners that other stuff is necessary. I've got an easy one that might be more ahead of what you suggested to start. It will toggle a pin endlessly...
con _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 pub Toggle_Main cognew (@Toggle, 0) dat org 0 Toggle mov dira, Pin 'Set Pin to output mov Time, cnt 'Place the value of cnt into Time add Time, #9 'Add 9 to time :loop waitcnt Time, Delay 'Set Pin high xor outa, Pin 'Toggle Pin waitcnt Time, Delay 'Set Pin Low xor outa, Pin 'Toggle Pin jmp #:loop
Pin long |< 1 Delay long 40_000_000 Time res 1
The waitcnt command KILLED me for what seemed to be weeks before the went off.
Short of what is happening to waitcnt goes like this, if one were to run through the program line for line:
con _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 pub Toggle_Main cognew (@Toggle, 0) dat org 0 Toggle 'This will indicate cnt=0 mov dira, Pin 'cnt=0-3 Set Pin to output mov Time, cnt 'cnt=4-7 Place the value of cnt into Time add Time, #9 'cnt=8-11 Add 9 to time :loop waitcnt Time, Delay 'cnt=12-15 wait until the system counter (cnt) is equal to Time 'then add the value of Delay to Time or Time=Time+Delay or Time=15+40_000_000 xor outa, Pin 'cnt=40_000_016-40_000_019 Toggle Pin waitcnt Time, Delay 'cnt=40_000_020-40_000_023 wait until cnt equals Time xor outa, Pin 'cnt=80_000_024-80_000_027 or cnt=24-27 because the counter wraps Toggle Pin jmp #:loop 'cnt=28-31 Jump to :loop
Pin long |< 1 Delay long 40_000_000 Time res 1
The important note is that you must set the time value of waitcnt before waiting for it. The system will wait until cnt = Time. If your value for Time is less than the system counter at the time the waitcnt command is executed, the COG will pause until CNT wraps around, or about 53 seconds at 80Mhz. So, it sits there waiting, then adds Delay to Time. This is the value that will be used in the NEXT waitcnt command (aka the value used at cnt=40_000_020 above).
Gotta go set the table, more to come...
-Parsko | | Back to Top | | |
 |  Beau Schwabe (Parallax) IC Layout Engineer

       Date Joined Aug 2004 Total Posts : 3967 | Posted 8/21/2006 11:59 AM (GMT -7) |   | Assembly Code Examples for the Beginner: SPI Engine Demo
This Assembly demo illustrates:
1) a Simple SPI Engine (Serial Periphial Interface) 2) Setting up an "Assembly Function" method to be used within Spin 3) A method for passing variables back-n-forth between Spin and Assembly
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000
#0,MSBPRE,LSBPRE,MSBPOST,LSBPOST 'Used for SHIFTIN routines #4,LSBFIRST,MSBFIRST 'Used for SHIFTOUT routines #0,Dpin,Cpin,SLpin,#8,Bits 'Set Dpin,Cpin,SLpin and Bit constant VAR long DataValue
OBJ SPI : "SPI Engine"
PUB start { Once called from Spin, SHIFTIN or SHIFTOUT remains running in its own COG. If SHIFTIN or SHIFTOUT are called with 'Bits' set to Zero, then the COG will shut down. Another way to shut the COG down is to call 'stop' from Spin. } '------------------------------------------------------------------------------------------------------------------------------ DataValue := %10001011 'DEBUG - Test value
SPI.SHIFTOUT(Dpin, Cpin, MSBFIRST, Bits, DataValue) 'Send SHIFTOUT DataVAlue 'DEBUG - Tested with 74HCT164 ' for MSBFIRST and LSBFIRST functions '------------------------------------------------------------------------------------------------------------------------------ dira[23..16] := %11111111 'DEBUG - Make ALL LED's outputs
dira[SLpin] := %1 'Set Shift / Load pin as an output repeat outa[SLpin] := %1 'Set Shift / Load pin in shift mode "1" DataValue := SPI.SHIFTIN(Dpin, Cpin, MSBPRE, Bits) 'Get SHIFTIN DataValue outa[SLpin] := %0 'Set Shift / Load pin in load mode "0" outa[23..16] := DataValue 'DEBUG - Lightup the LED's corresponding to the data ' LED23 = MSB ' LED16 = LSB '------------------------------------------------------------------------------------------------------------------------------ {{ Notes: Consecutive SHIFTIN/SHIFTOUT updates through Spin at 80 MHz is about 14kHz (Bit rate about 112k)
Consecutive SHIFTIN/SHIFTOUT updates through Assembly at 80 MHz is about 310kHz (Bit rate about 2.5M)
}}
{ ******************************************** SPI Engine V1.1 ******************************************** coded by Beau Schwabe (Parallax) ******************************************** Revision History: V1.0 - original program V1.1 - fixed problem with SHIFTOUT MSBFIRST option - fixed argument allocation in the SPI Engines main loop } CON #1,_SHIFTOUT,_SHIFTIN VAR long cog, command, Flag PUB SHIFTOUT(Dpin, Cpin, Mode, Bits, Value) 'Once called from Spin, SHIFTOUT remains running in its own COG. if Flag == 0 'If SHIFTOUT is called with 'Bits' set to Zero, then the COG will shut start 'down. Another way to shut the COG down is to call 'stop' from Spin. setcommand(_SHIFTOUT, @Dpin) PUB SHIFTIN(Dpin, Cpin, Mode, Bits)|Value 'Once called from Spin, SHIFTIN remains running in its own COG. if Flag == 0 'If SHIFTIN is called with 'Bits' set to Zero, then the COG will shut start 'down. Another way to shut the COG down is to call 'stop' from Spin. setcommand(_SHIFTIN, @Dpin) result := Value '------------------------------------------------------------------------------------------------------------------------------ PUB start : okay '' Start SPI Engine - starts a cog '' returns false if no cog available stop Flag := 1 okay := cog := cognew(@loop, @command) + 1 PUB stop '' Stop SPI Engine - frees a cog Flag := 0 if cog cogstop(cog~ - 1) command~ PRI setcommand(cmd, argptr) command := cmd << 16 + argptr 'write command and pointer repeat while command 'wait for command to be cleared, signifying receipt '################################################################################################################ DAT org ' ' SPI Engine - main loop ' loop rdlong t1,par wz 'wait for command if_z jmp #loop movd :arg,#arg0 'get 5 arguments ; arg0 to arg4 mov t2,t1 ' │ mov t3,#5 '───┘ :arg rdlong arg0,t2 add :arg,d0 add t2,#4 djnz t3,#:arg mov address,t1 'preserve address location for passing 'variables back to Spin language. wrlong zero,par 'zero command to signify command received ror t1,#16+2 'lookup command address add t1,#jumps movs :table,t1 rol t1,#2 shl t1,#3 :table mov t2,0 shr t2,t1 and t2,#$FF jmp t2 'jump to command jumps byte 0 '0 byte SHIFTOUT_ '1 byte SHIFTIN_ '2 byte NotUsed_ '3 NotUsed_ jmp #loop '################################################################################################################ SHIFTOUT_ 'SHIFTOUT Entry mov t4, arg3 wz ' Load number of data bits if_z jmp #Done ' '0' number of Bits = Done mov t1, #1 wz ' Configure DataPin shl t1, arg0 muxz outa, t1 ' PreSet DataPin LOW muxnz dira, t1 ' Set DataPin to an OUTPUT mov t2, #1 wz ' Configure ClockPin shl t2, arg1 muxz outa, t2 ' PreSet ClockPin LOW muxnz dira, t2 ' Set ClockPin to an OUTPUT sub LSBFIRST, arg2 wz,nr ' Detect LSBFIRST mode for SHIFTOUT if_z jmp #LSBFIRST_ sub MSBFIRST, arg2 wz,nr ' Detect MSBFIRST mode for SHIFTOUT if_z jmp #MSBFIRST_ jmp #loop ' Go wait for next command '------------------------------------------------------------------------------------------------------------------------------ SHIFTIN_ 'SHIFTIN Entry mov t4, arg3 wz ' Load number of data bits if_z jmp #Done ' '0' number of Bits = Done mov t1, #1 wz ' Configure DataPin shl t1, arg0 muxz dira, t1 ' Set DataPin to an INPUT mov t2, #1 wz ' Configure ClockPin shl t2, arg1 muxz outa, t2 ' PreSet ClockPin LOW muxnz dira, t2 ' Set ClockPin to an OUTPUT sub MSBPRE, arg2 wz,nr ' Detect MSBPRE mode for SHIFTIN if_z jmp #MSBPRE_ sub LSBPRE, arg2 wz,nr ' Detect LSBPRE mode for SHIFTIN if_z jmp #LSBPRE_ sub MSBPOST, arg2 wz,nr ' Detect MSBPOST mode for SHIFTIN if_z jmp #MSBPOST_ sub LSBPOST, arg2 wz,nr ' Detect LSBPOST mode for SHIFTIN if_z jmp #LSBPOST_ jmp #loop ' Go wait for next command '------------------------------------------------------------------------------------------------------------------------------ MSBPRE_ ' Receive Data MSBPRE MSBPRE_Sin test t1, ina wc ' Read Data Bit into 'C' flag rcl t3, #1 ' rotate "C" flag into return value call #Clock ' Send clock pulse djnz t4, #MSBPRE_Sin ' Decrement t4 ; jump if not Zero jmp #Update_SHIFTIN ' Pass received data to SHIFTIN receive variable '------------------------------------------------------------------------------------------------------------------------------ LSBPRE_ ' Receive Data LSBPRE LSBPRE_Sin test t1, ina wc ' Read Data Bit into 'C' flag rcr t3, #1 ' rotate "C" flag into return value call #Clock ' Send clock pulse djnz t4, #LSBPRE_Sin ' Decrement t4 ; jump if not Zero mov t4, #32 ' For LSB shift data right 32 - #Bits when done sub t4, arg3 shr t3, t4 jmp #Update_SHIFTIN ' Pass received data to SHIFTIN receive variable '------------------------------------------------------------------------------------------------------------------------------ MSBPOST_ ' Receive Data MSBPOST MSBPOST_Sin call #Clock ' Send clock pulse test t1, ina wc ' Read Data Bit into 'C' flag rcl t3, #1 ' rotate "C" flag into return value djnz t4, #MSBPOST_Sin ' Decrement t4 ; jump if not Zero jmp #Update_SHIFTIN ' Pass received data to SHIFTIN receive variable '------------------------------------------------------------------------------------------------------------------------------ LSBPOST_ ' Receive Data LSBPOST LSBPOST_Sin call #Clock ' Send clock pulse test t1, ina wc ' Read Data Bit into 'C' flag rcr t3, #1 ' rotate "C" flag into return value djnz t4, #LSBPOST_Sin ' Decrement t4 ; jump if not Zero mov t4, #32 ' For LSB shift data right 32 - #Bits when done sub t4, arg3 shr t3, t4 jmp #Update_SHIFTIN ' Pass received data to SHIFTIN receive variable '------------------------------------------------------------------------------------------------------------------------------ LSBFIRST_ ' Send Data LSBFIRST mov t3, arg4 ' Load t3 with DataValue LSB_Sout test t3, #1 wc ' Test LSB of DataValue muxc outa, t1 ' Set DataBit HIGH or LOW shr t3, #1 ' Prepare for next DataBit call #Clock ' Send clock pulse djnz t4, #LSB_Sout ' Decrement t4 ; jump if not Zero mov t3, #0 wz ' Force DataBit LOW muxnz outa, t1 jmp #loop ' Go wait for next command '------------------------------------------------------------------------------------------------------------------------------ MSBFIRST_ ' Send Data MSBFIRST mov t3, arg4 ' Load t3 with DataValue mov t5, #%1 ' Create MSB mask ; load t5 with "1" shl t5, arg3 ' Shift "1" N number of bits to the left. shr t5, #1 ' Shifting the number of bits left actually puts ' us one more place to the left than we want. To ' compensate we'll shift one position right. MSB_Sout test t3, t5 wc ' Test MSB of DataValue muxc outa, t1 ' Set DataBit HIGH or LOW shr t5, #1 ' Prepare for next DataBit call #Clock ' Send clock pulse djnz t4, #MSB_Sout ' Decrement t4 ; jump if not Zero mov t3, #0 wz ' Force DataBit LOW muxnz outa, t1 jmp #loop ' Go wait for next command '------------------------------------------------------------------------------------------------------------------------------ Update_SHIFTIN mov t1, address ' Write data back to Arg4 add t1, #16 ' Arg0 = #0 ; Arg1 = #4 ; Arg2 = #8 ; Arg3 = #12 ; Arg4 = #16 wrlong t3, t1 jmp #loop ' Go wait for next command '------------------------------------------------------------------------------------------------------------------------------ Clock mov t2, #0 wz,nr ' Clock Pin muxz outa, t2 ' Set ClockPin HIGH muxnz outa, t2 ' Set ClockPin LOW Clock_ret ret ' return '------------------------------------------------------------------------------------------------------------------------------ Done ' Shut COG down mov t2, #0 ' Preset temp variable to Zero mov t1, par ' Read the address of the first perimeter add t1, #4 ' Add offset for the second perimeter ; The 'Flag' variable wrlong t2, t1 ' Reset the 'Flag' variable to Zero CogID t1 ' Read CogID COGSTOP t1 ' Stop this Cog! '------------------------------------------------------------------------------------------------------------------------------ { ########################### Defined data ########################### } zero long 0 'constants d0 long $200
MSBPRE long $0 ' Applies to SHIFTIN LSBPRE long $1 ' Applies to SHIFTIN MSBPOST long $2 ' Applies to SHIFTIN LSBPOST long $3 ' Applies to SHIFTIN LSBFIRST long $4 ' Applies to SHIFTOUT MSBFIRST long $5 ' Applies to SHIFTOUT { ########################### Undefined data ########################### } 'temp variables t1 res 1 ' Used for DataPin mask and COG shutdown t2 res 1 ' Used for CLockPin mask and COG shutdown t3 res 1 ' Used to hold DataValue SHIFTIN/SHIFTOUT t4 res 1 ' Used to hold # of Bits t5 res 1 ' Used for temporary data mask address res 1 ' Used to hold return address of first Argument passed
arg0 res 1 'arguments passed to/from high-level Spin arg1 res 1 arg2 res 1 arg3 res 1 arg4 res 1
Edit: updated SPI engine.... fixed problem with SHIFTOUT MSBFIRST option fixed argument allocation in the SPI Engines main loop Beau Schwabe
IC Layout Engineer Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 8/24/2006 4:40:19 AM GMT
File Attachment : SPI Demo v1.0 (Aug 23rd 2006).zip 6KB (application/x-zip-compressed)This file has been downloaded 829 time(s). | | Back to Top | | |
 |  Phil Pilgrim (PhiPi) Registered Member

       Date Joined Feb 2006 Total Posts : 7744 | Posted 8/21/2006 1:07 PM (GMT -7) |   | Beau (and others),
I think we need to get this copyright thing straightened out. A lot of Propeller code origniating from Parallax (like the SPI Engine above) includes a copyright notice, but no licensing terms. The rules for the Propeller Object Exchange state "no copyrights", which implies public domain (and which is the reason I've never posted anything there). I think a copyright is important, along with a reasonable license for sharing the code. I prefer the General Public License (GPL) for this, and any significant code that I've originated and posted in various forum threads contains those terms of use.
The reasons for having a copyright are several:
1. It allows one to control the attributions that appear in the code, yielding a provenance than can be traced back to the originator.
2. It prevents someone else from copyiing the code and claiming it as their own, as could happen with code in the public domain.
3. It allows one to set restrictions on how the code may be used and distributed, keeping it "free", for example, as the GPL does.
But if copyrighted code is meant to be shared, it needs to say so, even though that intent in the context of the forum might seem clear. Once a program is copied from the forum context, any implied consent disappears. My vote would be to standardize on the GPL for shared Propeller code and to remove the "no copyrights" restriction from the object exchange in favor of that license.
I don't mean to stir up a hornet's nest here, but there are presently some inconsistencies and ambiguities that leave me a little uneasy.
Thanks, Phil | | Back to Top | | |
    |  Mike Green Registered Member

       Date Joined Oct 2004 Total Posts : 15579 | Posted 8/22/2006 3:52 PM (GMT -7) |   | '' Here's a simple example of table lookup in assembly. '' This particular example takes a table index in "ptr" '' and sets the "data" to the word value from the table. '' There's no range checking. If you want long values, '' just eliminate the shifts and masks (*). You can use '' the same kind of logic for byte values.
DAT org 0 test mov ptr,#2 ' for an example, get third value call #look ' note table indices are 0 to n-1 :stop jmp #:stop ' no checking for out of range
look mov data,ptr ' ptr is a table index (0 to n-1) shr data,#1 ' divide input value by 2 to get (*) add data,#table ' long word index, add table address movs :inline,data ' have to use instruction modification nop ' need pause here for pipelining :inline mov data,0-0 ' get long value from table test ptr,#1 wz ' do we want odd or even half (*) if_z and data,mask ' if even, take lower 16 bits (*) if_nz shr data,#16 ' if odd, take upper 16 bits (*) look_ret ret table word $0000 word $C0C1 word $C181 word $0140 word $C301 word $03C0 word $0280 mask long $FFFF data res 1 ptr res 1
Post Edited (Mike Green) : 8/23/2006 3:37:17 PM GMT | | Back to Top | | |
 |  Beau Schwabe (Parallax) IC Layout Engineer

       Date Joined Aug 2004 Total Posts : 3967 | Posted 8/30/2006 8:35 AM (GMT -7) |   | I had mentioned earlier that I preferred using the Propeller MUX operator to affect an I/O pin. I am still with this belief, however it is application dependent. There are certainly other times that it is better to use 'or' or 'andn' to affect an I/O bit. The savings can be a few clock cycles and an extra programming 'long' ...for large applications this can make a big difference. On smaller applications sometimes you just want to get the job done and it doesn't really matter one way or the other.
Typically to affect an I/O pin on a 32-bit register you need to create what's known as a 'mask' To set up a mask simply initialize a mask variable to "1" and then shift that variable left by the number of bits you wish. For an I/O this translates to the pin you want to access.
Example1:
mov PinMask, #1 ' Set Bit shl PinMask, IOpin ' Create PinMask
To define an I/O pin as an input we can use the 'andn' operator AFTER we have created a 'mask'.
Example2:
andn dira, PinMask ' Make Pin an Input
By using the 'or' operator instead, we can define the I/O pin as an output.
Example3:
or dira, PinMask ' Make Pin an Output
Using the same 'or' operator and directing it toward 'outa' instead of 'dira' we can define the pin state as HIGH if we also make the I/O pin an output.
Example4:
or outa, PinMask ' Make Pin HIGH
Likewise if we use the 'andn' operator we can define the pin state as being LOW if we also make the I/O pin an output.
Example5:
andn outa, PinMask ' Make Pin LOW
Suppose we want to affect an I/O pin based on a variable or another I/O pin. One way to do it using the 'andn' and 'or' operators is to test the variable or pin with a 'mask' and write to the 'z' flag using the 'if_z' and 'if_nz' conditionals.
Example6:
mov InPinMask, #1 ' Set Bit shl InPinMask, InPin ' Create PinMask andn dira, InPinMask ' Make Pin an input
mov OutPinMask, #1 ' Set Bit shl OutPinMask, OutPin ' Create PinMask or dira, OutPinMask ' Make Pin an output
test InPinMask, ina wz ' Test InpinMask against the I/O port if_z andn outa, OutPinMask ' If InPin = 0 set OutPin - LOW if_nz or outa, OutPinMask ' If InPin = 1 set OutPin - HIGH
Another way to accomplish the same task is to use the 'mux' operator.
Example7:
mov InPinMask, #1 ' Set Bit shl InPinMask, InPin ' Create PinMask andn dira, InPinMask ' Make Pin an input
mov OutPinMask, #1 ' Set Bit shl OutPinMask, OutPin ' Create PinMask or dira, OutPinMask ' Make Pin an output
test InPinMask, ina wz ' Test InpinMask against the I/O port muxnz outa, OutPinMask ' If InPin = 0 set OutPin - LOW ' If InPin = 1 set OutPin - HIGH
Now, this may not seem like a huge amount of savings, but this type of scenario has a way of multiplying itself as a program gets larger, and it can make a difference in the long run with some applications. Example 8 is a complete Propeller assembly program of Example 7.
Example8: I/O follower
PUB start cognew(@entry, 0)
DAT
entry org
mov InPinMask, #1 ' Set Bit shl InPinMask, InPin ' Create PinMask andn dira, InPinMask ' Make Pin an input
mov OutPinMask, #1 ' Set Bit shl OutPinMask, OutPin ' Create PinMask or dira, OutPinMask ' Make Pin an output
loop test InPinMask, ina wz ' Test Data bit at BitMask position muxnz outa, OutPinMask ' If InPin = 0 set OutPin - LOW ' If InPin = 1 set OutPin - HIGH jmp #loop
InPin long 0 'I/O pin 0 OutPin long 16 'I/o PIN 16 (DEMO Board LED) InPinMask res 1 OutPinMask res 1
Example9: MSB - SHIFTIN
PUB start cognew(@entry, 0)
DAT
entry org
Initialize mov ClockPinMask, #1 wz ' Configure Output pin shl ClockPinMask, ClockPin ' Create mask with ClockPin andn outa, ClockPinMask ' Preset Output Pin LOW "0" or dira, ClockPinMask ' Set pin as Output "1"
mov DataPinMask, #1 wz ' Configure Input pin shl DataPinMask, DataPin ' Create mask with DataPin andn dira, DataPinMask ' Set pin as Input "0"
SHIFTIN mov DataBitMask, #1 ' Create BitMask shl DataBitMask, DataBits ' Set number of Bits mov Data, #0 ' Clear Data _ReadNextBit or outa, ClockPinMask ' Set Clock pin HIGH - Start Clock test DataPinMask, ina wc ' Load "C" with DataPin value muxc Data, DataBitMask ' Move "C" into Data via DataBitMask position andn outa, ClockPinMask ' Set Clock pin LOW - End Clock shr DataBitMask, #1 wz ' Move BitMask position right by 1 ' if_nz jmp #_ReadNextBit ' Jump to '_ReadNextBit' if there are more bits
ClockPin long 0 ' Define I/O Clock Pin DataPin long 1 ' Define I/O Data Pin DataBits long 7 ' Set number of Data Bits ( N = Bits - 1 = [0 to 31] ) ClockPinMask res 1 ' ClockPin Mask DataPinMask res 1 ' DataPin Mask DataBitMask res 1 ' Data Mask Data res 1 ' Holds result value from SHIFTIN
Beau Schwabe
IC Layout Engineer Parallax, Inc.
| | Back to Top | | |
 |  LucidGuppy Registered Member

       Date Joined Jan 2005 Total Posts : 32 | Posted 11/7/2006 8:25 PM (GMT -7) |   | | How would I write an assembler routine that would add two numbers and return the result back to the spin object? | | Back to Top | | |
 |  Beau Schwabe (Parallax) IC Layout Engineer

       Date Joined Aug 2004 Total Posts : 3967 | Posted 11/7/2006 9:38 PM (GMT -7) |   | UPDATE TO THIS POST!!! 04 - 21 - 2007
please see the following thread for an update to this post
http://forums.parallax.com/forums/default.aspx?m=113109&f=25&p=9#m186870
LucidGuppy, This example will launch a cog just to run the Assembly, then add the two numbers and stop the cog after returning the result.
PUB AddNums(Num1,Num2) Num1_ := Num1 Num2_ := Num2 cognew(@entry, @Num1)
DAT org entry add Num1_,Num2_ 'Add Num1 to Num2 wrlong Num1_, par 'Return result to Num1 CogId CogNum 'Get COG ID CogStop CogNum 'Stop this COG
CogNum long 0 'Reserved variables Num1_ long 0 Num2_ long 0
Beau Schwabe IC Layout Engineer Parallax, Inc.
Post Edited (Beau Schwabe (Parallax)) : 4/21/2007 5:07:01 PM GMT File Attachment : AddNum_demo.zip 10KB (application/x-zip-compressed) This file has been downloaded 417 time(s). | | Back to Top | | |
 |  LucidGuppy Registered Member

       Date Joined Jan 2005 Total Posts : 32 | Posted 11/8/2006 5:32 AM (GMT -7) |   | Thanks Beau,
I'll give this a try tonight. Seems like a lot of people are way ahead of me and I need to catch up. | | Back to Top | | |
   | 71 posts in this thread. Viewing Page : 1 2 3 | | Forum Information | Currently it is Thursday, July 29, 2010 5:18 PM (GMT -7) There are a total of 462,440 posts in 62,066 threads. In the last 3 days there were 90 new threads and 803 reply posts. View Active Threads
| | Who's Online | This forum has 20143 registered members. Please welcome our newest member, ME01. 59 Guest(s), 10 Registered Member(s) are currently online. Details John Abshier, Rayman, Kevin Wood, BradC, prof_braino, Sapieha, Gene Bonin, laser-vector, localroger, Nick McClick |
Forum powered by dotNetBB v2.42EC SP2.02 dotNetBB © 2000-2010 |
|
|