May 11, 2024, 09:53:21 AM

News:

Be sure to checkout our Vixen interfaces in the Library forum -- if you want PC automation at near zero cost, EFX-TEK and Vixen is a great combination of tools.


Propeller (Spin) program for the RC4

Started by bsnut, May 25, 2011, 12:03:27 PM

Previous topic - Next topic

bsnut

May 25, 2011, 12:03:27 PM Last Edit: May 25, 2011, 12:15:08 PM by JonnyMac
I am looking to use the RC4 that I have to test a Propeller based project that I am working on. I designed a I/O board that has been setup to do 2 bidirectional serial ports and think that the RC4 would perfect for testing and future expansion to this board.

William Stefan
The Basic Stamp Nut

JonnyMac

May 25, 2011, 12:07:36 PM #1 Last Edit: May 25, 2011, 12:15:41 PM by JonnyMac
I connected an RC-4 to a PPDB (Propeller PDB) and tested this code; it works as intended.

'' =================================================================================================
''
''   File....... efx_rc4_test.spin
''   Purpose....
''   Author..... Jon Williams, EFX-TEK
''               -- see below for terms of use
''   E-mail..... jwilliams@efx-tek.com
''   Started....
''   Updated.... 25 MAY 2011
''
'' =================================================================================================


con

 _clkmode = xtal1 + pll16x
 _xinfreq = 5_000_000                                          ' use 5MHz crystal

 CLK_FREQ = ((_clkmode - xtal1) >> 6) * _xinfreq
 MS_001   = CLK_FREQ / 1_000
 US_001   = CLK_FREQ / 1_000_000


con

 IS_ON    = 1
 IS_OFF   = 0
 

con

 RX1 = 31
 TX1 = 30
 SDA = 29
 SCL = 28

 SIO = 27                                                      ' serial IO to RC-4


con

  #1, HOME, GOTOXY, #8, BKSP, TAB, LF, CLREOL, CLRDN, CR       ' PST formmatting control
 #14, GOTOX, GOTOY, CLS


obj

 com1 : "fullduplexserial"                                     ' for RC-4
 term : "fullduplexserial"                                     ' for terminal (PST)


var


dat

rc4             byte    "!RC4", 0
version         byte    "???", 0


pub main | idx, c

 com1.start(SIO, SIO, %1100, 38_400)                           ' half-duplex for RC-4
 term.start(RX1, TX1, %0000, 115_200)                          ' full-duplex for terminal
 pause(250)                                                    ' let RC-4 power up

 term.str(string(CLS, "RC-4 Demo for the Propeller", CR, CR))

 ' demo code

 reset_rc4(%00)
 pause(25)

 get_version(%00)  
 term.str(string("Version... "))
 term.str(@version)
 term.tx(CR)
 term.tx(CR)

 term.str(string("Set Test", CR))
 term.str(string("---------------", CR))

 repeat idx from %0000 to %1111
   set_rc4(%00, idx)
   pause(3)                                                    ' let command send & finish
   show_status(get_status(%00), 4)                             ' show RC-4 status
   pause(500)

 reset_rc4(%00)
 pause(25)
 term.tx(CR)

 term.str(string("Relay Test", CR))
 term.str(string("---------------", CR))

 repeat idx from 1 to 4                                        ' cycle through relays
   set_relay(%00, idx, IS_ON)                                  ' turn it on
   pause(3)                                                    ' let command finish
   show_status(get_status(%00), 4)                             ' show outputs status
   pause(500)

 repeat idx from 1 to 4
   set_relay(%00, idx, IS_OFF)
   pause(3)
   show_status(get_status(%00), 4)
   pause(500)  

 term.tx(CR)
 term.str(string("Done!"))
   
 repeat
   waitcnt(0)                                                  ' wait here, low-power mode
   

pub pause(ms) | t

'' Delay program ms milliseconds

 t := cnt - 1088                                               ' sync with system counter
 repeat (ms #> 0)                                              ' delay must be > 0
   waitcnt(t += MS_001)


pub reset_rc4(addr)

' Reset RC-4 at "addr" (%00 to %11, $FF for all)

 com1.str(@rc4)                                                ' send header
 com1.tx(addr)                                                 ' send address
 com1.tx("X")                                                  ' send reset command


pub set_rc4(addr, relays)

'' Set RC-4 at "addr" to [lower 4] bits in "relays"

 com1.str(@rc4)
 com1.tx(addr)      
 com1.tx("S")                                                  ' send set command
 com1.tx(relays)


pub set_relay(addr, ch, status)

'' Sets relay channel on RC-4 at "addr" to status.0
'' -- 8 bytes @ 38.4K = 2.3ms

 com1.str(@rc4)
 com1.tx(addr)
 com1.tx("R")                                                  ' send relay command
 com1.tx(ch)                                                   ' send channel
 com1.tx(status & 1)                                           ' send bit0 of status

 
pub get_version(addr) | idx, c

'' Request and receive RC-4 version
'' -- 6 bytes @ 38.4K = 1.7ms

 com1.str(@rc4)
 com1.tx(addr)      
 com1.tx("V")                                                  ' request version

 pause(2)                                                      ' give time for command
 com1.rxflush                                                  ' clear rx buffer

 repeat idx from 0 to 2                                        ' wait for 3 characters
   c := com1.rxtime(10)                                        ' wait 10ms (max) for response
   if (c => 0)                                                 ' character received?
     byte[@version][idx] := c                                  ' save it
   else
     bytefill(@version, "?", 3)                                ' error, reset to unknown
     quit                                                      ' abort


pub get_status(addr)

'' Show status of RC-4 at "addr"
'' -- 6 bytes @ 38.4K = 1.7ms

 com1.str(@rc4)
 com1.tx(addr)      
 com1.tx("G")                                                  ' get status

 pause(2)                                                      ' give time for command
 com1.rxflush                                                  ' clear rx buffer

 return com1.rxtime(10)                                        ' return status (-1 if timeout)
 

pub show_status(status, width)

'' Show "width" bits (from LSB) in "status"

 term.str(string("Status.... "))
 if (status => 0)                                              ' valid?
   term.bin(status, width)                                     ' show bits
 else
   term.tx("?")                                                ' else indicate error
 term.tx(CR)


dat

{{

 Terms of Use: MIT License

 Permission is hereby granted, free of charge, to any person obtaining a copy of this
 software and associated documentation files (the "Software"), to deal in the Software
 without restriction, including without limitation the rights to use, copy, modify,
 merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 permit persons to whom the Software is furnished to do so, subject to the following
 conditions:

 The above copyright notice and this permission notice shall be included in all copies
 or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

}}



For those that chocked when the saw the listing above please keep in mind that it's just a new language.  The Propeller language, Spin, is massively more powerful than PBASIC1 or PBASIC2, and Spin was created by the same guy (Chip Gracey, owner of Parallax). 

The Propeller chip is the heart of the AP-16+, arguably our must popular product.  I programmed the AP-16+ in Spin, and its design has allowed me to make updates when requested by our customers.  The HC-8+ uses the Propeller as well, and any "hacking" (which we will enthusiastically support) should be done in Spin.  Yes, there are other languages for the Propeller, but we use and will only support Spin as it's built into the chip and we know it works.  Our design/build clients trust the Propeller and programming it in Spin.  It's different, but that difference brings you the power to have eight massively powerful brains working at the same time, fully cooperative, and not stepping on each other's toes.
Jon McPhalen
EFX-TEK Hollywood Office

bsnut

Jon,

Thanks for the Propeller program and can see it is a little different from the PBASIC.  Had the feeling that it would need to programed this way. I noticed that you used "fullduplexserial" object for bidirectional comms. I didn't know you could use it for bidirectional comms, I was going "simpleserial" object for my comms on my I/O board and you provided and shown me another way to do it. I hope, I am not shocking anyone with my posts.   
William Stefan
The Basic Stamp Nut

JonnyMac

May 25, 2011, 03:06:42 PM #3 Last Edit: May 25, 2011, 03:08:55 PM by JonnyMac
As you can see, FDS does support half-duplex serial and it doesn't fill its own RX buffer with anything that it transmits (this saves a lot of trouble).  The other great thing is that only one copy is loaded into the source code.  Since cogs run in round robin fashion the two serial cogs can access the same (Spin) code blocks.  Of course, each object launches its own PASM (Assembly) cog that handles the actual reception and transmission, and also has its own set of variables.

Yes, Spin is different.  It leans toward object orientation, though it's not a true OO language (there is no automatic inheritance of methods).  It's also structured and allows parameter passing and a return value.   You'll note that there are no global variables in the program, all are done with locals.

BTW, if you use Simple_Serial (which I helped write when at Parallax) you have to use 2400 baud and you can remove the delays as it is not buffered.  I don't like that last part, especially if the device does not respond.  I use FDS in the AP-16+ and the HC-8+ so that it can cleanly recover from a break in the comms link in the middle of a command.
Jon McPhalen
EFX-TEK Hollywood Office

bsnut

May 27, 2011, 07:28:43 PM #4 Last Edit: May 28, 2011, 06:38:57 AM by bsnut
Jon,

I ran your test code on my Propeller GGUSB board and it worked without any problems after I used better power supply, a 9v battery. I used a 12vdc wallwart and Propeller GGUSB caused the voltage regulators to shut down. I guess 16vdc is a little too much for the voltage regulators for the GGUSB. 

Can you show me the the test circuit that you used for your test on Propeller Demo Board? I would like to copy it to.



William Stefan
The Basic Stamp Nut

JonnyMac

There's no real circuit; I used a couple jumper wires to go from P27 on the Propeller into the W connection of the WRB extender, and from PPDB ground into the black wire.

The small SOT-223 regulators have a lower shutdown than the LM2940s that are used on a lot of products.
Jon McPhalen
EFX-TEK Hollywood Office

bsnut

That's easy. I was thinking you used a resistor or a level shifting FET like a NTE491 was needed to protect the Propeller pin.

Now, I can see why you use LM2940s on your products and not the SOT223s because of the higher voltages that Wallwart power supplies put out when loaded down.
William Stefan
The Basic Stamp Nut

JonnyMac

The serial mode used is open-collector and the RC-4 has a 10K pull-up on the serial line.  Even though it is pulling up to 5v, the 10K limits the current into the Propeller pin to a safe level.
Jon McPhalen
EFX-TEK Hollywood Office