Advertisement
Guest User

BadgeDriver_v1_0.spin

a guest
Mar 9th, 2016
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.65 KB | None | 0 0
  1. {{
  2. ─────────────────────────────────────────────────
  3. File: BadgeDriver_v1_0.spin
  4. Version: 1.0
  5. Copyright (c) 2016 Tymkrs
  6. See end of file for terms of use.
  7.  
  8. Author: Whisker
  9. ─────────────────────────────────────────────────
  10. }}
  11.  
  12. {
  13. HISTORY:
  14. This driver is made as an example for using the Badge Bug to drive a Cyphercon2016 badge over a serial port
  15.  
  16. USAGE:
  17. • Desolder / remove the 0 Ohm default resistors from the back of the badge
  18. • Install Badge Bug
  19. • Flash this firmware to the Badge Bug (via Propeller Tool & Prop Plug, etc.)
  20. • Use a serial terminal emulator and a usb ttl serial cable to talk to Badge Bug at 115200 baud
  21. • Geekcred for not using an emulator (I got it running @300 baud over an acoustic coupler, just saying)
  22.  
  23. }
  24.  
  25. {{ CypherTTY
  26.  
  27. A minimal 3 bit character encoding standard designed for the Cyphercon 2016 Badge
  28.  
  29. 000 > > > > > >
  30. 001 SP 3 , N U B
  31. 010 E 4 ? S M V
  32. 011 T 5 ! H W K
  33. 100 . 6 " R F J
  34. 101 0 7 A D G X
  35. 110 1 8 O L Y Q
  36. 111 2 9 I C P Z
  37.  
  38. Encoding characters into a bit stream:
  39.  
  40. A message always starts from the first column.
  41. If the desired character exists on this column, note down the indicated 3 bit value from the matrix.
  42. If not, a value of 000 shifts to the next column.
  43. This is a 'Column Shift' character, and is unprintable.
  44. Shifting from the last column wraps back to the first column.
  45.  
  46. Special cases when CypherTTY encoding a ciphertext binary stream:
  47.  
  48. After encryption, if the last character in the ciphertext is a Column Shift, notate this with a "+" character.
  49. Replace any run of six Column Shift characters with a "=" character.
  50.  
  51. These rules avoid two situations where, without them,
  52. it would be possible to encode a stream of bits into a string that would decode to a different stream of bits.
  53. Which, while hilarious ... makes for a very short game of telephone.
  54.  
  55. }}
  56.  
  57. Con
  58.  
  59. _clkmode = xtal1 + pll16x 'Tell the hardware to run at 80Mhz
  60. _xinfreq = 5_000_000 '(important for solid serial communications)
  61.  
  62. Obj
  63.  
  64. fds : "FullDuplexSerial" 'Include software UART serial driver
  65.  
  66. Var
  67.  
  68. long P 'Column pointer while CypherTTY encoding
  69. long oP 'Column pointer while CypherTTY decoding
  70. long IsLast 'Flag for catching a hanging Column Shift character while CypherTTY encoding
  71. long FullLoop 'Counter for catching a run of six Column Shift characters while CypherTTY encoding
  72. long SR_ 'Variable for storing the working copy of the linear feedback shift register
  73. long BackupSR_ 'Variable for storing the user entered seed for the linear feedback shift register
  74.  
  75. long BufferPointer 'Pointer to current position in the message buffer while user enters data and upper bound while CypherTTY encoding
  76. byte Buffer[1024] 'Byte array buffer for storing the user entered message (you could make this larger if you need to)
  77.  
  78. Pub Main 'Program enters here
  79.  
  80. Init 'Call the initialization subroutine
  81.  
  82. 'Main Program Loop, this repeats over and over
  83. repeat
  84. ScanConsole 'Call the ScanConsole subroutine, execution does not return to here until the console scanner is finished
  85. waitcnt((clkfreq / 100) + cnt) 'Pause for 10ms
  86.  
  87. Pub Init | Index
  88.  
  89. dira[0..23] := %11111111_11111000_11100000 'Set the direction of the lower 24 input / output pins.
  90. 'We're not using all of these but some of the unused pins are set such so that they don't constantly sink current :)
  91. outa[9] := 0 'Pull the data input of the badge's hardware shift register low
  92. repeat Index from 0 to 7 'Clock and latch 8 of those lows into the badge's hardware shift register
  93. outa[8] := 1
  94. outa[8] := 0
  95. fds.Start(31, 30, 0, 115_200) 'Start up the software UART serial driver
  96. waitcnt((clkfreq / 2) + cnt) 'Pause for 500ms while the UART starts up
  97. PrintMenu 'Call the Print Menu subroutine
  98.  
  99. Pub PrintMenu 'Spam the serial console with some useful information
  100.  
  101. fds.Str(String("Cyphercon Badge Bug by @Whixr", 10, 13))
  102. fds.Str(String("--------------------------------------------------", 10, 13))
  103. fds.Str(String(" ~: set encryption seed", 10, 13))
  104. fds.Str(String(" Other: add a character to the buffer", 10, 13))
  105. fds.Str(String(" Backspace: remove last character from the buffer", 10, 13))
  106. fds.Str(String(" Enter: run encryption", 10, 13))
  107. fds.Str(String(" $: print current input buffer", 10, 13))
  108. fds.Str(String(" `: print this menu", 10, 13))
  109.  
  110.  
  111. Pub ScanConsole | Index, SubIndex, CheckByte, InputData, EncodeCheck
  112.  
  113. 'Serial Command Console
  114. CheckByte := fds.RxCheck 'Put incoming byte from the serial console into CheckByte, is -1 if nothing new is waiting
  115.  
  116. case CheckByte 'See what we got
  117.  
  118. 8, 127: 'We got a Backspace (standards for a backspace are strange, so I included two of them: 8, 127)
  119. if BufferPointer > 0
  120. BufferPointer-- 'Move the buffer pointer back, essentially erasing what ever they entered last
  121. fds.Tx(8) 'Print a backspace to the console to move the cursor back, the messy wrong way :D
  122.  
  123. 13: 'CR 'They hit Enter, so it's time to Encrypt All the Things
  124. PreEncrypt 'Call the PreEncrypt subroutine
  125. fds.Str(String(10, 13)) 'Print a CRLF to the serial console so we're starting on a new line
  126.  
  127. repeat Index from 0 to BufferPointer - 1 'Iterate through how ever much of the buffer they filled up while typing in their super secret messages
  128. if BufferPointer - 1 == Index 'If this is the last character from the buffer,
  129. IsLast := 1 'set the flag so that we're aware of it (in case after encryption we end in a trailing Column Shift character)
  130.  
  131. case BYTE[@Buffer][Index] 'Let's look at what kind of character we are dealing with at this position in the buffer
  132.  
  133. "=": 'a run of 6 000s 'Looks like this character is a "=", which is an escape code for six Column Shift characters in a row
  134. repeat SubIndex from 0 to 5
  135. Clock(0) 'Send six Column Shifts down the encoder>encrypter>decoder chain
  136.  
  137. "+": 'a hanging 000 'Looks like this character is a "+", which is an escape code for a handing Column Shift character
  138. Clock(0) 'Send a Column Shift down the encoder>encrypter>decoder chain
  139.  
  140. other: 'Looks like this character is not an escape code
  141. EncodeCheck := 0 'Flag to know when we've found a matching letter
  142. repeat while EncodeCheck == 0 'Loop until the flag goes high
  143.  
  144. repeat SubIndex from 0 to 6 'Loop through the 7 characters (rows) on the currently selected column in the CypherTTY matrix
  145. if BYTE[@Buffer][Index] == BYTE[@uCase][(P * 7) + SubIndex] 'Check to see if the character matches
  146. Clock(SubIndex + 1) 'Send the row value down the encoder>encrypter>decoder chain
  147. EncodeCheck := 1 'Raise the flag
  148. if EncodeCheck == 0 'Check if the flag was never raised
  149. P := P + 1 'No match in this column
  150. P := P // 6 'Move to the next column
  151. Clock(0) 'Send a Column Shift down the encoder>encrypter>decoder chain
  152.  
  153. fds.Str(String(10, 13)) 'We're ALL DONE with the buffer so send a CRLF to the serial console for a new line
  154.  
  155. "`": 'We got a "`" so we have to spit the help menu out to the serial console
  156. PrintMenu 'Call the PrintMenu subroutine
  157.  
  158. "$": 'Print Buffer 'We got a "$" so we have to print all of the message they have entered so far back to the serial console
  159. fds.Str(String(10, 13)) 'Send a CRLF to the serial console
  160. repeat Index from 0 to BufferPointer - 1 'Loop through all of the buffer that they have filled
  161. fds.Tx(BYTE[@Buffer][Index]) 'Send each character to the serial console
  162. fds.Str(String(10, 13)) 'Send another CRLF to the serial console
  163.  
  164. 126:'Tilde 'We got a "~" so we need to go into seed entry mode
  165. SeedEntry 'Call the SeedEntry subroutine
  166.  
  167. -1: 'We didn't get anything
  168. 'no bytes waiting 'Sit and spin :)
  169.  
  170. other: 'We got a character that isn't used to control the serial console
  171. 'This is probably something the user wants to add to the message buffer
  172.  
  173. case InputCheck(CheckByte) 'Pass it along to the InputCheck function to see if it is a CypherTTY character
  174.  
  175. -1: 'unsupported character 'It is not supported
  176. fds.Str(String(10, 13, "Character unsupported by CipherTTY ")) 'Spit out a helpful error message to the serial console
  177. fds.Dec(CheckByte)
  178. fds.Tx(32)
  179. fds.Tx(CheckByte)
  180. fds.Str(String(10, 13))
  181.  
  182. other: 'Yes, this is a CypherTTY character
  183. if BufferPointer < 1023 'Check to make sure the buffer isn't full
  184. Buffer[BufferPointer] := InputCheck(CheckByte) 'Put the character in the buffer
  185. fds.Tx(Buffer[BufferPointer]) 'Print the character to the serial console
  186. BufferPointer++ 'Increment the buffer pointer to the next slot up in the buffer
  187.  
  188. Pri SeedEntry | Index, SubIndex, InputData
  189.  
  190. dirb := 0 'Zero out the dirb register
  191. fds.Str(String(10, 13, "Input 8 seed bits", 10, 13)) 'Let serial console user know to enter a seed
  192.  
  193. repeat Index from 7 to 0 'Loop through all 8 bits of the seed. High bit to low bit.
  194.  
  195. InputData := fds.Rx 'Input a character from the serial console
  196. case InputData 'Look at what we got
  197.  
  198. "0": 'We got a 0
  199. fds.Tx(48) 'Print a 0 to the serial console
  200. dirb[Index] := 0 'Set this bit of seed to a 0 in the dirb register
  201.  
  202. "1": 'We got a 1
  203. fds.Tx(49) 'Print a 1 to the serial console
  204. dirb[Index] := 1 'Set this bit of seed to a 1 in the dirb register
  205.  
  206. other: 'We got something that isn't a 0 or a 1
  207. fds.Str(String(10, 13, "Binary is hard, try again ace.", 10, 13)) 'Provide life guidance to the serial console
  208. Index++ 'We need to enter for this bit of the seed again, so increment our loop variable (it counts down)
  209. repeat SubIndex from 7 to Index 'Print all of the seed that they have entered so far to the serial console
  210. case dirb[SubIndex]
  211. 0:
  212. fds.Tx(48)
  213. 1:
  214. fds.Tx(49)
  215. BackupSR_ := dirb 'Save a copy of the completed seed to the BackupSR_ global variable
  216. fds.Str(String(10, 13, "OK", 10, 13)) 'Send a victory message to the serial console
  217.  
  218. Pri PreEncrypt 'Time to reset some global variables before starting the encode/encrypt/decode chain
  219.  
  220. P := 0 'Encoder column pointer
  221. oP := 0 'Decoder column pointer
  222. FullLoop := 0 'Flag for detecting a run of six Column Shifts
  223. if BackupSR_ == 0 'Check to see if the user has entered a seed
  224. SeedEntry 'Make them enter a seed
  225. SR_ := BackupSR_ 'Copy the seed into the working linear feedback shift register variable
  226. IsLast := 0 'Flag for detecting a trailing Column Shift
  227.  
  228. Pub Clock(Character) | Index, X0R, NextBit 'The Encrypter
  229.  
  230. dirb := Character 'Load these three bits into the dirb register
  231. repeat Index from 2 to 0 'Loop through the three character bits
  232. outa[10 + Index] := dirb[Index] 'Set the three input indicator LEDs to match each bit
  233.  
  234. dirb := SR_ 'Load the value of the working linear feedback shift register into the dirb register
  235. outa[16..18] := dirb[1..3] 'Set the three Key Bit inputs on the badge to bits 1, 2, and 3 of the LFSR
  236.  
  237. X0R := Character ^ dirb[1..3] 'XOR the keybits with the three character bits (this is the encryption)
  238.  
  239. Decode(X0R) 'Pass the encrypted bits down the chain to the decoder
  240.  
  241. 'itterate to next lfsr state
  242. dirb := SR_ 'Load the value of the working linear feedback shift register into the dirb register
  243. NextBit := dirb[6] ^ dirb[7] 'Store the result of XORing the 6 and 7 bits of the LSFR (this is the feedback)
  244. repeat Index from 7 to 1 'Shift the contents of register dirb left by one
  245. dirb[Index] := dirb[Index - 1]
  246. dirb[0] := NextBit 'Put the stored feedback bit into bit 0 of the dirb register
  247. SR_ := dirb 'Store the value of the dirb register into the working linear feedback shift register
  248. UpdateDisplay 'Call the UpdateDisplay sub routine
  249.  
  250. outa[8] := 1 'Turn on the STEP LED on the badge
  251. waitcnt((clkfreq / 10) + cnt) 'Wait 100ms
  252. outa[8] := 0 'Turn off the STEP LED on the badge
  253. waitcnt((clkfreq / 10) + cnt) 'Wait 100ms
  254.  
  255. Pri Decode(Bits) 'The Decoder
  256.  
  257. case Bits 'Look at what character bits we're dealing with
  258.  
  259. 0: 'We got a Column Shift character
  260. case IsLast
  261. 0: 'Column Shift 'This Column Shift is not the final character of the message
  262. oP := (oP + 1) // 6 'Shift to the next column
  263. FullLoop++ 'Note that we've shifted again
  264. if FullLoop > 5 'Check if this is the 6th Column Shift in a row
  265. fds.Tx("=") 'Print a "=" character to the serial console
  266. FullLoop := 0 'Reset the Column Shift count to 0
  267.  
  268. 1: 'This Column Shift is the final character of the message
  269. fds.Tx("+") 'Print a "+" character to the serial console
  270.  
  271. other: 'We got a printable character
  272. FullLoop := 0 'Reset the Column Shift count to 0
  273. fds.Tx(BYTE[@uCase][(oP * 7) + (Bits - 1)]) 'Look up and print the printable character to the serial console
  274.  
  275. Pub UpdateDisplay | Index 'Linear feedback shift register indicator lights
  276.  
  277. dirb := SR_ 'Load the working linear feedback shift register into the dirb register
  278. outa[0..7] := dirb[0..7] 'Turn on or off the LFSR indicator lights to match the present states of the LFSR
  279.  
  280. Pri InputCheck(InputByte) | Index, OutputByte 'If character is supported, convert to uppercase
  281.  
  282. OutputByte := -1 'Set return to a default of unsupported
  283. repeat Index from 0 to 41 'Loop through the supported character table
  284. if InputByte == BYTE[@lCase][Index] or InputByte == BYTE[@uCase][Index] 'This InputByte was found
  285. OutputByte := BYTE[@uCase][Index] 'Set return to the uppercase version of this character
  286. if InputByte == "+" 'This InputByte is a hanging Column Shift escape code
  287. OutputByte := "+" 'Pass this character along
  288. if InputByte == "=" 'This InputByte is a Run of Six Column Shifts escape code
  289. OutputByte := "=" 'Pass this character along
  290. return OutputByte 'Return the result
  291.  
  292. Dat 'CypherTTY supported character table
  293.  
  294. lCase byte " et.0123456789,?!", 34, "aoinshrdlcumwfgypbvkjxqz"
  295. uCase byte " ET.0123456789,?!", 34, "AOINSHRDLCUMWFGYPBVKJXQZ"
  296.  
  297. {{
  298. ┌──────────────────────────────────────────────────────────────────────────────────────┐
  299. │ TERMS OF USE: MIT License │
  300. ├──────────────────────────────────────────────────────────────────────────────────────┤
  301. │Permission is hereby granted, free of charge, to any person obtaining a copy of this │
  302. │software and associated documentation files (the "Software"), to deal in the Software │
  303. │without restriction, including without limitation the rights to use, copy, modify, │
  304. │merge, publish, distribute, sublicense, and/or sell copies of the Software, and to │
  305. │permit persons to whom the Software is furnished to do so, subject to the following │
  306. │conditions: │
  307. │ │
  308. │The above copyright notice and this permission notice shall be included in all copies │
  309. │or substantial portions of the Software. │
  310. │ │
  311. │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, │
  312. │INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A │
  313. │PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT │
  314. │HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION │
  315. │OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE │
  316. │SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
  317. └──────────────────────────────────────────────────────────────────────────────────────┘
  318. }}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement