Need some help with Assembly
Jennifer
Posts: 4
Hi,
I'm using the "spi_engine.spin" and I want to make a connection between two propellers. One should be the master and one should be the slave. Could someone help me writing SHIFTINSLV and SHIFTOUTSLV??
Maybe a lot to read but the purple code is what I use for the slave. What I'm most concerned about is the Clock2 part. Could someone help me with this.
Thanks a lot!
This is what I've done so far:
I'm using the "spi_engine.spin" and I want to make a connection between two propellers. One should be the master and one should be the slave. Could someone help me writing SHIFTINSLV and SHIFTOUTSLV??
Maybe a lot to read but the purple code is what I use for the slave. What I'm most concerned about is the Clock2 part. Could someone help me with this.
Thanks a lot!
This is what I've done so far:
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 [color=purple] byte SHIFTOUTSLV_ '3 byte SHIFTINSLV_ '4[/color] byte NotUsed_ '5 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 '------------------------------------------------------------------------------------------------------------------------------ SHIFTOUTSLV_ 'SHIFTOUT_slave 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 [color=purple]muxz dira, t2 ' Set ClockPin to an INPUT[/color] sub LSBFIRST, arg2 wz,nr ' Detect LSBFIRST mode for SHIFTOUT_slave if_z jmp #LSBFIRST2_ sub MSBFIRST, arg2 wz,nr ' Detect MSBFIRST mode for SHIFTOUT_slave if_z jmp #MSBFIRST2_ jmp #loop ' Go wait for next command '------------------------------------------------------------------------------------------------------------------------------ SHIFTINSLV_ 'SHIFTIN_slave 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 [color=purple]muxz dira, t2 ' Set ClockPin to an INPUT[/color] sub MSBPRE, arg2 wz,nr ' Detect MSBPRE mode for SHIFTIN [color=purple] if_z jmp #MSBPRE2_ sub LSBPRE, arg2 wz,nr ' Detect LSBPRE mode for SHIFTIN if_z jmp #LSBPRE2_ sub MSBPOST, arg2 wz,nr ' Detect MSBPOST mode for SHIFTIN if_z jmp #MSBPOST2_ sub LSBPOST, arg2 wz,nr ' Detect LSBPOST mode for SHIFTIN if_z jmp #LSBPOST2_[/color] 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 '------------------------------------------------------------------------------------------------------------------------------ [color=purple]MSBPRE2_ MSBPRE2_Sin test t1, ina wc ' Read Data Bit into 'C' flag rcl t3, #1 ' rotate "C" flag into return value call #Clock2 ' Send clock pulse djnz t4, #MSBPRE2_Sin ' Decrement t4 ; jump if not Zero jmp #Update_SHIFTIN ' Pass received data to SHIFTIN receive variable '------------------------------------------------------------------------------------------------------------------------------ LSBPRE2_ ' Receive Data LSBPRE LSBPRE2_Sin test t1, ina wc ' Read Data Bit into 'C' flag rcr t3, #1 ' rotate "C" flag into return value call #Clock2 ' Send clock pulse djnz t4, #LSBPRE2_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 '------------------------------------------------------------------------------------------------------------------------------ MSBPOST2_ ' Receive Data MSBPOST MSBPOST2_Sin call #Clock2 ' Send clock pulse test t1, ina wc ' Read Data Bit into 'C' flag rcl t3, #1 ' rotate "C" flag into return value djnz t4, #MSBPOST2_Sin ' Decrement t4 ; jump if not Zero jmp #Update_SHIFTIN ' Pass received data to SHIFTIN receive variable '------------------------------------------------------------------------------------------------------------------------------ LSBPOST2_ ' Receive Data LSBPOST LSBPOST2_Sin call #Clock2 ' Send clock pulse test t1, ina wc ' Read Data Bit into 'C' flag rcr t3, #1 ' rotate "C" flag into return value djnz t4, #LSBPOST2_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 '------------------------------------------------------------------------------------------------------------------------------ LSBFIRST2_ ' Send Data LSBFIRST mov t3, arg4 ' Load t3 with DataValue LSB2_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 #Clock2 ' Send clock pulse djnz t4, #LSB2_Sout ' Decrement t4 ; jump if not Zero mov t3, #0 wz ' Force DataBit LOW muxnz outa, t1 jmp #loop ' Go wait for next command '------------------------------------------------------------------------------------------------------------------------------ MSBFIRST2_ ' 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. MSB2_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 #Clock2 ' Send clock pulse djnz t4, #MSB2_Sout ' Decrement t4 ; jump if not Zero mov t3, #0 wz ' Force DataBit LOW muxnz outa, t1 jmp #loop ' Go wait for next command [/color]'------------------------------------------------------------------------------------------------------------------------------ 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 '------------------------------------------------------------------------------------------------------------------------------ [color=purple]Clock2 and t2, ina wz,nr if_z jmp #Clock2 Cup and t2, ina wz,nr if_nz jmp #Cup Clock2_ret ret[/color] ' 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
Comments
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBladeProp, SixBladeProp, website (Multiple propeller pcbs)
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: Micros eg Altair, and Terminals eg VT100 (Index)
· Search the Propeller forums (via Google)
My cruising website is: ·www.bluemagic.biz·· MultiBladeProp is: www.bluemagic.biz/cluso.htm
This SPI driver that you reference does not allow you to configure one of the Clocks as an INPUT... Which is what you would need in order to do Prop to Prop communication.
I'm working on a dynamic SPI that would allow you to configure the clock this way, but this will take awhile for me to finish.
As Cluso99 points out there are other more efficient ways to communicate Prop to Prop. There is a high speed driver that I wrote, and there is a FullDuplex object already mentioned. In order to determine which method is best, we need to know what your ultimate communication goal is for your project.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.
Thanks for your reply.
I'm working on a robot car that has a lot of sensors. The master needs to collect a lot of information and he will be communicating with a computer which decides what action should be taken. So the information needs to be send as fast as possible.
What is the high speed driver you refer to, Beau? Isn't the SPI engine in assembly the fastest way to do this? I also tried it with BS2_function (shiftout_slv en shiftin_slv) which worked perfect, but not fast enough.
All thoughts are welcome.
Jennifer
http://forums.parallax.com/forums/default.aspx?f=25&p=1&m=233212
Postedit: oops missed the "M" in Mbps · Thanks.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBladeProp, SixBladeProp, website (Multiple propeller pcbs)
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: Micros eg Altair, and Terminals eg VT100 (Index)
· Search the Propeller forums (via Google)
My cruising website is: ·www.bluemagic.biz·· MultiBladeProp is: www.bluemagic.biz/cluso.htm
Post Edited (Cluso99) : 4/2/2009 12:37:43 PM GMT
I forgot to mention something. For now I'm trying to connect two propellers, but eventually there need to be 1 master and 2 slaves. With SPI I can use SlaveSelect to indicate which slave should listen. That's why I think I need SPI.
Jennifer
Post Edited (Jennifer) : 4/2/2009 11:19:09 AM GMT
The advantage of using 'standard' serial ports is that debugging is made a lot easier. Just hang a PC port on your interconnect and you can trace the data comms.
My master simply sends...
<start of packet><slave address hi><slave address lo><data 1>.....<data n><crc><crc><end of packet>
...the slaves receive every packet but only the addressed slave responds with a similar packet. It feels to me that it should be possible to encapsulate the whole packet sending and receiving routine inside a COG which will hide the nitty gritty from the main routines.
Post Edited (Brian Fairchild) : 4/2/2009 12:44:52 PM GMT
Jennifer: I have to do exactly that with my TriBladeProp boards. I will use a different protocol because I dont need/want the clocking overhead. I've been thinking of using variable bit serial - 4/12/32/36 with the first 4 bits being a command. Even longer bit trains might be usable. Since you have a master, why not send out ultra high speed serial on P30 from the master to both slaves, and the slaves can send on P31 when instructed to.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBladeProp, SixBladeProp, website (Multiple propeller pcbs)
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: Micros eg Altair, and Terminals eg VT100 (Index)
· Search the Propeller forums (via Google)
My cruising website is: ·www.bluemagic.biz·· MultiBladeProp is: www.bluemagic.biz/cluso.htm
If you are looking for speed, you are much better off using synchronous communication such as Standard serial, or a high-speed derivative of Standard serial.
Either way, you can implement a serial protocol that allows anybody to be a master in turn. By defining a simple set of functions in the first couple of bytes that are sent in a way that everyone connected understands you can define transmitting, receiving, packet size, master requesting, etc. In hardware, one Propeller should be setup as the "default" master via a pin that can be tied to power or ground. From there the protocol can negotiate who can become a master.
With an 80MHz clock and 4 clock per instruction, SPI at it's best would be about 4MHz.
Loop:
read data bit (4)
set data bit (4)
toggle clock (4)
toggle clock (4)
jump to Loop (4)
Your talking 20 Clocks to shift out a single bit = 4MHz
You can stagger cogs to improve the efficiency and increase the frequency, and there are probably some counter tricks that you can do to shorten the code required to toggle the clock. Basically you set the counter to the Baud you want, and that's your clock... and then you begin transmitting the data as if it were Asynchronous data, but "step locked" to the counter so it effectively becomes synchronous data.
Loop:
read data bit (4)
set data bit (4)
jump to Loop (4)
12 Clocks to shift out a single bit ... 6.67MHz
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Beau Schwabe
IC Layout Engineer
Parallax, Inc.