On Mon, 4 Jan 2021 17:15:45 -0000 (UTC), Martin Gregorie <
martin@mydomain.invalid> declaimed the following:
Out of pure curiosity: have you any idea how much work it would be to
convert a fully debugged BS2 BASIC program into a running SPIN program?
Probably a lot. One concept with the Propeller is that one assigns cores to do what would have been an interrupt in other chips (instead of
having an interrupt, that core is in a polling loop). Also using cores for dedicated I/O protocols. The GPIOs are shared by all cogs.
Manual for the P1 is at
https://www.parallax.com/package/propeller-manual/ Besides SPIN and
Propeller ASM, there is a third-party "SimpleIDE" which provides "Propeller
C" (
https://www.parallax.com/downloads/propeller-c-software/)
An old demo program:
-=-=-
{{
Welcome.spin
Welcome to the OpenSource PropellerIDE.
To run this program:
* Make sure the FTDI Chip USB driver is installed.
* Connect the USB Propeller board.
* Debug (F8)
The program should pause a moment, print Hello, and
then toggle Propeller IO P27 repeatedly.
}}
CON
_clkmode = XTAL1 + PLL16X
_clkfreq = 80_000_000
OBJ
ser : "Parallax Serial Terminal"
PUB start
ser.start(115200)
waitcnt(CLKFREQ/2+CNT) '' Wait for start up
ser.str(string($d,"Hello.",$d))
blink
''
'' Blink ActivityBoard LED
''
PUB blink '' The start method
DIRA[27] |= 1 '' Set P27 to output
repeat '' Repeat forever
OUTA[27] ^= 1 '' Toggle LED pin
waitcnt(CLKFREQ/2+CNT) '' Wait
-=-=-
And the source code for the main file from DefCon22 badge (the badge uses
all cogs, one file per cog)
-=-=-
'' =================================================================================================
''
'' File....... dc22_badge_master.spin
'' -- for internal use only!
'' -- no changes unless approved/reviewed by JonnyMac/Ryan
''
'' Authors.... Jon "JonnyMac" McPhalen and Ryan "1o57" Clarke
'' MIT License
'' -- see below for terms of use
''
'' E-mail.....
jon@jonmcphalen.com
''
1o57@10000100001.org
''
'' Modified for Propeller Quickstart Board (touch pads and LEDs) with Human Interface
'' Device board (I/R emitter/receiver, LEDs). Also modified to read
pads to set "Goon"
'' mode on start-up
'' Dennis L Bieber
''
'' =================================================================================================
{{
Welcome to Defcon 22. This year we would like to invite you to experiment more fully with your
badge -- feel free to play around with code.
You can load directly to RAM [F10] if you don't want to blast your
firmware, but even if you do,
we are giving you the source from the start. The source provides a nice
badge template with extra
objects so that you can experiment with LEDs, buttons, IR (in and out), timing, speed changes, etc.
Completing the challenge will at some point require you to 'update' your badge -- but for now, how
about changing your LED pattern? It's easier than you think! If you need help, feel free to stop
by the Hardware Hacking Village, or simply ask someone who has a
different pattern than yours.
Create a new pattern -- have fun!
}}
con { timing }
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000 ' use 5MHz crystal
CLK_FREQ = ((_clkmode - xtal1) >> 6) * _xinfreq ' system
freq as a constant
MS_001 = CLK_FREQ / 1_000 ' ticks in
1ms
US_001 = CLK_FREQ / 1_000_000 ' ticks in
1us
' speed settings for power control/reduction
' -- use with clkset() instruction
XT1_P16 = %0_1_1_01_111 ' 16x
crystal (5MHz) = 80MHz
XT1_PL8 = %0_1_1_01_110
XT1_PL4 = %0_1_1_01_101
XT1_PL2 = %0_1_1_01_100
XT1_PL1 = %0_1_1_01_011
RC_SLOW = %0_0_0_00_001 ' 20kHz
' program speed and terminal baud
B_SPEED = 20 { MHz }
T_BAUD = 57_600 { for terminal io }
IR_FREQ = 36_000 { matches receiver on DC22 badge }
IR_BAUD = 2400 { max supported using IR connection }
IR_BLAST = $DC22
'con
'
#0, HUMAN, ARTIST, PRESS, SPEAKER, VENDOR, CONTEST, GOON, UBER, LO57
'
' BADGE_TYPE = HUMAN
con { io pins }
RX1 = 31 '
programming / terminal
TX1 = 30
SDA = 29 ' eeprom /
i2c
SCL = 28
PAD3 = 4 '27 ' touch
pads
PAD2 = 5 '26 ' HID SD
slot uses 0-3, sems to conflict
PAD1 = 6 '25
PAD0 = 7 '24
LED7 = 23 ' leds
LED6 = 22
LED5 = 21
LED4 = 20
LED3 = 19
LED2 = 18
LED1 = 17
LED0 = 16
IR_IN = 9 '15 ' ir input
IR_OUT = 8 '14 ' ir output
con { io configuration }
IS_OFF = 0 ' all bits
off
IS_ON = -1 ' all bits
on
IS_LOW = 0
IS_HIGH = -1
IS_INPUT = 0
IS_OUTPUT = -1
con { pst formatting }
#1, HOME, GOTOXY, #8, BKSP, TAB, LF, CLREOL, CLRDN, CR
#14, GOTOX, GOTOY, CLS
obj
term : "cryptofullduplexserial64" ' serial io
for terminal
irtx : "jm_sircs_tx" ' SIRCS
output
irrx : "jm_sircs_rx" ' SIRCS
input
prng : "jm_prng" ' random #s
tmr1 : "jm_eztimer" '
asynchronous timer
ee : "jm_24xx512" ' eeprom
access
pwm : "jm_pwm8" ' pwm for
LEDs
btn : "touch buttons" ' QuickStart buttons are more sensitive?
var
long ms001 ' system
ticks per millisecond
long us001 ' system
ticks per microsecond
byte BADGE_TYPE 'TBD --
change type on boot
pub main | idx, last, button
setup ' setup
badge io and objects
term.tx(CLS) ' clear the terminal
if (BADGE_TYPE => GOON) ' check
badge type
alien_badge
' non-Goon badge code here
repeat until (read_pads <> %0000) ' wait for
a pad press
idx := (prng.random >> 1) // 13
repeat (idx << 1)
term.tx(" ")
idx := (prng.random >> 1) // 13
term.caesar(@@Commands[idx])
if (check_ir)
quit
pause(250)
term.tx(CLS)
term.caesar(@Greets)
term.tx(CR)
term.otp(@Test3, @Test4)
term.tx(CR)
last := -1 ' any
button to start
repeat
repeat
check_ir ' check ir process
button := read_pads ' wait for input
until ((button <> %0000) and (button <> last)) ' must be
new
last := button ' save for
next check
case button
%0001:
start_animation(@Cylon, 0) ' start animation
term.caesar(@Detective) ' display crypto string
pause(250) ' allow
clean button release
%0101:
start_animation(@Chaser, 0)
term.otp(@Scientist, @Driver)
pause(250)
%0111:
start_animation(@Police, 0)
term.caesar(@Diver)
pause(250)
%1000:
start_animation(@InOut, 0)
term.otp(@Politician, @Football)
pause(250)
%1001:
stop_animation
term.otp(@RayNelson, @Mystery)
pause(250)
pub check_ir | code
code := irrx.rxcheck ' check ir input
if (code < 0) ' abort if waiting
return
if (code == IR_BLAST)
start_animation(@Blasted, 3) term.caesar(string($0A, "DROI VSFO GO CVOOZ", CR)) ' THEY LIVE WE SLEEP
repeat while (anicog) ' let
animation finish
irrx.enable
if (code == IR_BLAST)
return TRUE
pub alien_badge | btns, delay
'' Badge code for >= Goon
delay := -1 ' force immediate broadcast
repeat
btns := read_pads
if ((read_pads) or (tmr1.seconds => delay)) ' pad input
or delay expired?
irtx.tx(IR_BLAST, 16, 3) ' blast the humans!
'term.caesar(string($0C, "IQ XUHQ FTQK EXQQB", CR)) ' WE LIVE
THEY SLEEP
start_animation(@Blasted, 3) ' play
blaster animation
tmr1.start ' restart
timer
delay := ||(prng.random) // 11 + 10 ' new delay
pub setup
'' Setup badge IO and objects
'' -- set speed before starting other objects
set_speed(B_SPEED) ' set badge speed (MHz)
set_leds(%00000000) ' LEDs off
term.start(RX1, TX1, %0000, T_BAUD) ' start terminal
prng.seed(cnt << 2, cnt, $1057, -cnt, cnt ~> 2) ' seed prng (random #s)
btn.Start(CLK_FREQ / 100) ' start button
reading process
BADGE_TYPE := HUMAN 'read_pads ' somehow need to
set up on pads
if (BADGE_TYPE < GOON)
irrx.start(IR_IN) ' start ir input
irrx.enable ' accept ir input now
else
irtx.start(IR_OUT, IR_FREQ) ' start ir output
tmr1.start ' start
timer
con
{ ----------------------------- }
{ B A D G E F E A T U R E S }
{ ----------------------------- }
pub set_speed(mhz)
'' Sets badge clock speed
'' -- sets timing variables ms001 and us001
'' -- note: objects may require restart after speed change
case mhz
0: clkset(RC_SLOW, 20_000) ' super low power -- sleep mode only!
5: clkset(XT1_PL1, 5_000_000)
10: clkset(XT1_PL2, 10_000_000)
20: clkset(XT1_PL4, 20_000_000)
40: clkset(XT1_PL8, 40_000_000)
80: clkset(XT1_P16, 80_000_000)
waitcnt(cnt + (clkfreq / 100)) ' wait
~10ms
ms001 := clkfreq / 1_000 ' set ticks
per millisecond for waitcnt
us001 := clkfreq / 1_000_000 ' set ticks
per microsecond for waitcnt
pub set_leds(pattern)
'' Sets LED pins to output and writes pattern to them
'' -- swaps LSB/MSB for correct binary output
outa[LED0..LED7] := pattern ' write
pattern to LEDs
dira[LED0..LED7] := IS_HIGH ' make LED
pins outputs
pub read_pads | btns, lwr, upr, wid
lwr := PAD3 <# PAD0 'determine lowest
pad in set
upr := PAD3 #> PAD0 'determine highest
pad in set
wid := upr - lwr + 1 'determine width of used pads
btns := btn.state >> lwr ' shift buttons by lower of
PAD specification
btns := btns & !($FFFF << wid) ' generate bitmask for only
the desired set
return btns
' outa[PAD0..PAD3] := IS_HIGH ' charge
pads (all output high)
' dira[PAD0..PAD3] := IS_OUTPUT
' dira[PAD0..PAD3] := IS_INPUT ' float
pads
' pause(50) ' -- allow touch to discharge
' return (!ina[PAD0..PAD3] & $0F)' >< 4 ' return
"1" for touched pads
con
{ --------------- }
{ L E D F U N }
{ --------------- }
var
long anicog ' cog
running animation
long anistack[32] ' stack
space for Spin cog
pri start_animation(p_table, cycles)
'' Start animation in background cog
'' -- allows LED animation while doing other processes
'' -- p_table is pointer (address of) animation table
'' -- set cycles to 0 to run without stopping
stop_animation
anicog := cognew(run_animation(p_table, cycles), @anistack) + 1
return anicog ' return
cog used
pri stop_animation
'' Stop animation if currently running
if (anicog) ' if
running
cogstop(anicog - 1) ' stop the
cog
anicog := 0 ' mark
stopped
pri run_animation(p_table, cycles) | p_leds
'' Run animation
'' -- p_table is pointer (address of) animation table
'' -- cycles is number of iterations to run
'' * 0 cycles runs "forever"
'' -- usually called with start_animation()
if (cycles =< 0)
cycles := POSX ' run
"forever"
repeat cycles
p_leds := p_table ' point to table
repeat byte[p_leds++] ' repeat
for steps in table
set_leds(byte[p_leds++]) ' update
leds
pause(byte[p_leds++]) ' hold
anicog := 0 ' mark
stopped
cogstop(cogid) ' stop this
cog
dat
' Animation tables for LEDs
' -- 1st byte is number of steps in animation sequence
' -- each step holds pattern and hold time (ms)
' -- for delays > 255, duplicate pattern + delay
Cylon byte (@Cylon_X - @Cylon) / 2 + 1
byte %10000000, 125
byte %01000000, 125
byte %00100000, 125
byte %00010000, 125
byte %00001000, 125
byte %00000100, 125
byte %00000010, 125
byte %00000001, 125
byte %00000010, 125
byte %00000100, 125
byte %00001000, 125
byte %00010000, 125
byte %00100000, 125
Cylon_X byte %01000000, 125
Chaser byte (@Chaser_X - @Chaser) / 2 + 1
byte %10010010, 75
byte %00100100, 75
Chaser_X byte %01001001, 75
InOut byte (@InOut_X - @InOut) / 2 + 1
byte %10000001, 100
byte %01000010, 100
byte %00100100, 100
byte %00011000, 100
byte %00100100, 100
InOut_X byte %01000010, 100
Police byte (@Police_X - @Police) / 2 + 1
byte %11001100, 75
byte %11110000, 75
byte %11001100, 75
byte %11110000, 75
byte %00001111, 75
byte %00110011, 75
byte %00001111, 75
Police_X byte %00110011, 75
Blasted byte (@Blasted_X - @Blasted) / 2 + 1
byte %00000000, 50
byte %00011000, 50
byte %00111100, 50
byte %01111110, 50
byte %11111111, 50
byte %00000000, 50
byte %00011000, 50
byte %00111100, 50
byte %01111110, 50
byte %11111111, 50
byte %00000000, 50
byte %00011000, 50
byte %00111100, 50
byte %01111110, 50
byte %11111111, 50
byte %00000000, 50
byte %11111111, 50
byte %00000000, 50
byte %11111111, 50
byte %00000000, 50
byte %11111111, 50
byte %00000000, 50
byte %11111111, 50
byte %00000000, 50
byte %11111111, 50
Blasted_X byte %00000000, 50
con
{ ------------- }
{ B A S I C S }
{ ------------- }
pub pause(ms) | t
'' Delay program in milliseconds
'' -- ensure set_speed() used before calling
t := cnt ' sync to system counter
repeat (ms #>= 0) ' delay > 0
waitcnt(t += ms001) ' hold 1ms
pub high(pin)
'' Makes pin output and high
outa[pin] := IS_HIGH
dira[pin] := IS_OUTPUT
pub low(pin)
'' Makes pin output and low
outa[pin] := IS_LOW
dira[pin] := IS_OUTPUT
pub toggle(pin)
'' Toggles pin state
!outa[pin]
dira[pin] := IS_OUTPUT
pub input(pin)
'' Makes pin input and returns current state
dira[pin] := IS_INPUT
return ina[pin]
pub pulse_out(pin, us) | state
'' Generate pulse on pin for us microseconds
'' -- ensure set_speed() used before calling
'' -- makes pin output
'' -- pulse out is opposite of pin's input state
'' -- blocks until pulse is finished (to clear counter)
us *= us001 ' convert
us to system ticks
state := ina[pin] ' read
incoming state of pin
if (ctra == 0) ' ctra available?
if (state == 0) '
low-high-low
low(pin) ' set to
output
frqa := 1
phsa := -us ' set
timing
ctra := (%00100 << 26) | pin ' start the pulse
repeat
until (phsa => 0) ' let pulse finish
else '
high-low-high
high(pin)
frqa := -1
phsa := us
ctra := (%00100 << 26) | pin
repeat
until (phsa < 0)
ctra := IS_OFF ' release counter
return true
elseif (ctrb == 0)
if (state == 0)
low(pin)
frqb := 1
phsb := -us
ctrb := (%00100 << 26) | pin
repeat
until (phsb => 0)
else
high(pin)
frqb := -1
phsb := us
ctrb := (%00100 << 26) | pin
repeat
until (phsb < 0)
ctrb := IS_OFF
return true
else
return false ' alert
user of error
pub set_freq(ctrx, px, fx)
'' Sets ctrx to frequency fx on pin px (NCO/SE mode)
'' -- fx in hz
'' -- use fx of 0 to stop counter that is running
if (fx > 0)
fx := ($8000_0000 / (clkfreq / fx)) << 1 ' convert
freq for NCO mode
case ctrx
"a", "A":
ctra := ((%00100) << 26) | px ' configure ctra for NCO on pin
frqa := fx ' set
frequency
dira[px] := IS_OUTPUT
"b", "B":
ctrb := ((%00100) << 26) | px
frqb := fx
dira[px] := IS_OUTPUT
else
case ctrx
"a", "A":
ctra := IS_OFF ' disable counter
outa[px] := IS_OFF ' clear pin/driver
dira[px] := IS_INPUT
"b", "B":
ctrb := IS_OFF
outa[px] := IS_OFF
dira[px] := IS_INPUT
dat
RayNelson byte "IAIHG TPJNU QU CZR GALWXK DC MHR LANK FOTLA OTN
LOYOC HPMPB PX HKICW",0
Test4 byte "DID YOU REALLY THINK THAT IT WOULD BE SO EASY?
Really? Just running strings?",0
Greets byte 16,77,85,66,83,69,67,85,32,74,69,32,84,85,86,83,69,68,32,74,77,85,68,74,79,32,74,77,69,13,0
Detective byte 13,74,85,82,69,82,32,71,66,32,79,82,84,86,65,32,86,32,88,65,66,74,32,83,86,65,81,32,85,78,69,66,89,81,13,0
Scientist byte 76,81,84,89,86,70,32,82,75,66,32,83,78,90,32,83,81,87,83,85,32,87,82,65,32,73,77,82,66,32,67,70,72,82,32,90,65,65,65,65,32,73,89,77,87,90,32,80,32,69,65,74,81,86,68,32,89,79,84,80,32,76,71,65,87,32,89,75,90,76,13,0
Diver byte 10,"DBI DRO PSBCD RKVP YP RSC ZRYXO XEWLOB PYVVYGON
LI RSC VKCD XKWO DROX DRO COMYXN RKVP YP RSC XEWLOB",CR,0
Driver byte "SOMETIMES WE HAVE ANSWERS AND DONT EVEN KNOW IT SO ENJOY THE VIEW JUST BE HAPPY",0
Politician byte 83,83,80,87,76,77,32,84,72,67,65,80,32,81,80,32,74,84,32,73,87,69,32,87,68,88,70,90,32,89,85,90,88,32,85,77,86,72,88,72,32,90,65,32,67,66,32,80,65,69,32,88,82,79,76,32,70,65,89,32,73,80,89,75,13,0
Test3 byte "ZGJG MTM LLPN C NTER MPMH TW",CR,0
Football byte "IT MIGHT BE HELPFUL LATER IF YOU KNOW HOW TO GET
TO EDEN OR AT LEAST THE WAY",0
Mystery byte "OH A MYSTERY STRING I SHOULD HANG ON TO THIS FOR
LATER I WONDER WHAT ITS FOR OR WHAT IT DECODES TO?",0
dat
Cmd00 byte $05, $42, $54, $57, $50, $20, $4A, $4E, $4C, $4D,
$59, $20, $4D, $54
byte $5A, $57, $58, $0D, $00, $4C, $4F, $56, $45, $00
Cmd01 byte $04, $41, $45, $58, $47, $4C, $20, $58, $5A, $0D,
$00
Cmd02 byte $0E, $47, $49, $50, $41, $57, $48, $0D, $00, $4C,
$49, $46, $45, $00
Cmd03 byte $0C, $45, $46, $4D, $4B, $20, $4D, $45, $58, $51,
$51, $42, $0D, $00
Cmd04 byte $04, $53, $46, $49, $43, $0D, $00, $47, $69, $47,
$21, $00
Cmd05 byte $14, $48, $49, $20, $43, $48, $58, $59, $4A, $59,
$48, $58, $59, $48
byte $4E, $20, $4E, $42, $49, $4F, $41, $42, $4E, $0D,
$00
Cmd06 byte $02, $50, $51, $20, $4B, $4F, $43, $49, $4B, $50,
$43, $56, $4B, $51
byte $50, $0D, $00, $4A, $6F, $6E, $6E, $79, $4D, $61,
$63, $00
Cmd07 byte $0C, $59, $4D, $44, $44, $4B, $20, $4D, $5A, $50,
$20, $44, $51, $42
byte $44, $41, $50, $47, $4F, $51, $0D, $00, $48, $41,
$50, $50, $59, $00
Cmd08 byte $05, $4A, $46, $59, $0D, $00, $48, $45, $41, $4C,
$54, $48, $00
Cmd09 byte $09, $4D, $58, $20, $57, $58, $43, $20, $5A, $44,
$4E, $42, $43, $52
byte $58, $57, $20, $4A, $44, $43, $51, $58, $41, $52,
$43, $48, $0D, $00
Cmd10 byte $0F, $52, $44, $43, $48, $4A, $42, $54, $0D, $00
Cmd11 byte $02, $45, $51, $50, $48, $51, $54, $4F, $0D, $00
Cmd12 byte $19, $41, $54, $58, $0D, $00, $57, $45, $41, $4C,
$54, $48, $00
byte $31, $6F, $35, $37, $00
Commands word @Cmd00, @Cmd01, @Cmd02, @Cmd03, @Cmd04, @Cmd05
word @Cmd06, @Cmd07, @Cmd08, @Cmd09, @Cmd10, @Cmd11
word @Cmd12
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.
}}
--
Wulfraed Dennis Lee Bieber AF6VN
wlfraed@ix.netcom.com http://wlfraed.microdiversity.freeddns.org/
--- SoupGate-Win32 v1.05
* Origin: Agency HUB, Dunedin - New Zealand | Fido<>Usenet Gateway (3:770/3)