Skip to content

Instantly share code, notes, and snippets.

@p120ph37
Created August 10, 2014 03:21
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save p120ph37/621849dd66a4ab293dd4 to your computer and use it in GitHub Desktop.
Save p120ph37/621849dd66a4ab293dd4 to your computer and use it in GitHub Desktop.
Human and Goon badge code for DC22
'' =================================================================================================
''
'' File....... dc22_badge_human_full.spin
''
'' Authors.... Jon "JonnyMac" McPhalen and Ryan "1o57" Clarke
'' Unpublished portions reverse-engineered by Aaron "P120ph37" Meriwether
'' MIT License
'' -- see below for terms of use
''
'' E-mail..... jon@jonmcphalen.com
'' 1o57@10000100001.org
''
'' =================================================================================================
{{
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 }
con { io pins }
RX1 = 31 ' programming / terminal
TX1 = 30
SDA = 29 ' eeprom / i2c
SCL = 28
PAD3 = 27 ' touch pads
PAD2 = 26
PAD1 = 25
PAD0 = 24
LED7 = 23 ' leds
LED6 = 22
LED5 = 21
LED4 = 20
LED3 = 19
LED2 = 18
LED1 = 17
LED0 = 16
IR_IN = 15 ' ir input
IR_OUT = 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
con { badge types }
' Other values unknown so far, though UBER would be >= 6
#0, HUMAN, #6, GOON
BADGE_TYPE = HUMAN
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
var
long ms001 ' system ticks per millisecond
long us001 ' system ticks per microsecond
pub main | idx, last, button
setup ' setup badge io and objects
term.tx(CLS) ' clear the terminal
if(BADGE_TYPE => GOON)
control_humans
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(see_them)
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
see_them
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 see_them | ircode
ircode := irrx.rxcheck
if (ircode < 0)
return
if (ircode == $DC22)
start_animation(@Dalek, 3)
term.caesar(string(10,"DROI VSFO GO CVOOZ",CR))
repeat while (anicog)
irrx.enable
if (ircode == $DC22)
return true
pub control_humans | button, sleep
sleep := -1
repeat
button := read_pads
if(read_pads or (tmr1.seconds => sleep))
irtx.tx($DC22, 16, 3)
term.caesar(string(12,"IQ XUHQ FTQK EXQQB",CR))
start_animation(@Dalek, 3)
tmr1.start
sleep := (||prng.random) // 11 + 10
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)
if(BADGE_TYPE < GOON)
irrx.start(IR_IN) ' set up rx mode
irrx.enable
else
irtx.start(IR_OUT, IR_FREQ) ' set up tx mode
tmr1.start
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
'' Reads and returns state of touch pad inputs
'' -- swaps LSB/MSB for correct binary input
outa[PAD3..PAD0] := IS_HIGH ' charge pads (all output high)
dira[PAD3..PAD0] := IS_OUTPUT
dira[PAD3..PAD0] := IS_INPUT ' float pads
pause(50) ' -- allow touch to discharge
return (!ina[PAD3..PAD0] & $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
Dalek byte (@Dalek_X - @Dalek) / 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
Dalek_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
@p120ph37
Copy link
Author

I have added all of the missing (to be published by 1057 after the convention) Spin code. When used with Propeller Tool, this will produce a byte-for-byte identical EEPROM image to the factory Human badges. If you change the BADGE_TYPE constant to "GOON", it will produce a byte-for-byte identical EEPROM to the factory Goon badge.

Happy hacking!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment