Shop OBEX P1 Docs P2 Docs Learn Events
Propeller II update - BLOG - Page 51 — Parallax Forums

Propeller II update - BLOG

14849515354223

Comments

  • User NameUser Name Posts: 1,451
    edited 2012-11-09 17:21
    David Betz wrote: »
    Didn't he publish the source in an earlier message in this thread? I think we already know what he came up with. :-)
    Exactly! I read every word Chip wrote, four times over. I also copied the monitor code and examined every line carefully. I'm totally excited about the monitor in ROM, for all the reasons Chip has given. I've had enough of fancy chips that require a 2GB IDE and a $500 programming pod...just to squeeze out "Hello World." This one feature gives the Prop2 a giant leap forward in being able to host its own development system.
  • David BetzDavid Betz Posts: 14,516
    edited 2012-11-09 19:33
    User Name wrote: »
    Exactly! I read every word Chip wrote, four times over. I also copied the monitor code and examined every line carefully. I'm totally excited about the monitor in ROM, for all the reasons Chip has given. I've had enough of fancy chips that require a 2GB IDE and a $500 programming pod...just to squeeze out "Hello World." This one feature gives the Prop2 a giant leap forward in being able to host its own development system.
    I don't understand. A monitor is not a development system. You'll still need a tool on the host to compile or assemble code and download it into the P2 chip. This is really no different from the way P1 works. I guess you could use the monitor as a "development environment" if you like entering your code in hex. Is that what you mean?
  • rod1963rod1963 Posts: 752
    edited 2012-11-09 19:43
    One could do what Sun Microsystems did with their workstation. Allow users to boot up into a Forth system to run diagnostics and such. But I don't think that would be appropriate for the P2 since it has no flash and is just a micro controller. There are plenty of engineers who know how work with such chips using C and since it has not JTAG port, one doesn't have to worry about a expensive program dongle.
  • LeonLeon Posts: 7,620
    edited 2012-11-09 19:50
    IIRC, the Forth on Sun systems was primarily intended for I/O drivers.
  • cgraceycgracey Posts: 14,155
    edited 2012-11-09 23:56
    About the monitor...

    It is more universally accessible than the binary/HMAC-signed downloader because it sends and receives only standard ASCII characters $20..$7E (space.."~").

    Some programming languages, serial interfaces, and OS's have issues with sending and receiving full binary ($00..$FF). For this reason, you might have to jump through some hoops to get the more-efficient binary downloader working on a given host system. The monitor, on the other hand, can talk to anything that speaks serial, without concern over non-ASCII characters. It is so simple that it can't NOT work on any host machine that has a serial port. Plus, it doesn't force an ordered protocol, but is conversational in operation. I've been using the Parallax Serial Terminal program to talk to it as well as PUTTY, which is free on the 'net and very tidy.

    My thinking might be a little anachronistic, but I've seen many host-level systems which are big on brains and storage, but for which the serial interfaces were fleeting afterthoughts, and full binary can trigger unwanted events. The monitor will play politely and offer no offense to any host.

    The reason I put a help menu in the monitor was so that you could quickly get command syntax without having to refer to any documents. You might launch the monitor from within an app you want to debug and you'll need to search memory for a string of data to get your bearings. The help menu will be handy then.

    Here is the ROM now:
    === Propeller II Monitor ===
    
    >0.e7f
    00000- 50 72 6F 70 32 2E 30 20 00 20 7C 0C 03 D0 7C 0C   'Prop2.0 . |...|.'
    00010- 45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D   'E.........|...|.'
    00020- 01 C2 FC 80 1F C2 7C 62 01 E0 FC 30 66 0C A8 80   '......|b...0f...'
    00030- 01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0   '..|.*...[...|...'
    00040- 5B C0 FC 1C 7C FA BC 80 01 FA FC 28 FA F0 FC A0   '[...|......(....'
    00050- 5B C0 FC 1C 01 C8 7C 62 2A 00 64 1C B2 C8 7C 61   '[.....|b*.d...|a'
    00060- 01 C8 FC 34 10 F0 FC F6 02 F1 FC A0 08 F0 7C 86   '...4..........|.'
    00070- 52 C8 E8 A0 01 C8 7C 62 25 52 FC 1C DA B4 FC 0C   'R.....|b%R......'
    00080- 25 52 FC 1C DF B4 FC 0C 25 52 FC 1C DB B4 FC 0C   '%R......%R......'
    00090- 25 52 FC 1C B2 C8 7C 61 01 C8 FC 34 17 F0 FC F6   '%R....|a...4....'
    000A0- 35 00 7C 1C 0D F6 FC 0C 62 F6 BC 80 63 C6 BC FF   '5.|.....b...c...'
    000B0- 37 4F FC 0C 00 00 4C 1C 04 F0 FC A0 DB B2 FC 0C   '7O....L.........'
    000C0- DA B0 FC 0C 44 3E C0 0D DA B2 FC 0C 01 F0 7C E1   '....D>........|.'
    000D0- 01 CA CC 27 DC AE FC 0C DB B0 FC 0C DA B0 FC 0C   '...'............'
    000E0- 2B F0 FC F6 B2 D8 7C 0C 66 F0 BC A0 20 F2 FC A0   '+.....|.f... ...'
    000F0- 5B C0 E8 1C D6 AC D4 0D DB B0 D4 0C DA B0 D4 0C   '[...............'
    00100- 01 F4 FC 34 38 F2 FC F6 C1 F4 7C 08 37 F0 FC F6   '...48.....|.7...'
    00110- 40 0E C0 0D 70 00 04 E0 C1 EC 53 08 6B F0 3C 08   '@...p.....S.k.<.'
    00120- E0 02 FC 0C 6B D4 3C 0C 67 00 04 E0 03 F0 FC A0   '....k.<.g.......'
    00130- 6B EC 13 08 6B F4 BC 0A 49 F4 7C FA 48 F0 FC F6   'k...k...I.|.H...'
    00140- 03 1C 7C 0C 42 0E C0 0D E0 00 FC 0C 30 F2 FC 08   '..|.B.......0...'
    00150- C1 F4 FC 08 7A F2 28 86 6D D8 28 0C 41 FE FF 0F   '....z.(.m.(.A...'
    00160- 01 DC 7C 0C C1 F0 7C 08 C1 F0 7C 08 71 E0 BC 6A   '..|...|...|.q..j'
    00170- 73 E4 A8 6A 08 DC D4 A0 6F DC 3C 0C 25 52 FC 1C   's..j....o.<.%R..'
    00180- 0D F8 FC 0C 25 52 FC 1C 0C F8 FC 0C 7D F8 3C 85   '....%R......}.<.'
    00190- 00 00 7C 1C 00 02 00 00 C0 C6 2D 00 00 00 00 08   '..|.......-.....'
    001A0- 50 00 00 00 00 00 00 03 00 02 00 00 80 16 1E 40   'P..............@'
    001B0- 80 0E BE 8F A0 16 00 C0 D0 01 00 00 C0 16 00 00   '................'
    001C0- 80 0E 00 00 80 16 00 00 10 07 00 00 5B B4 00 00   '............[...'
    001D0- CA E0 FD 0C 46 96 FC 1C 00 9E FE 08 02 9E 7E F8   '....F.........~.'
    001E0- B3 9E 7E 0C 4F CB BD A0 02 CA FD 2C 13 CA FD 28   '..~.O......,...('
    001F0- 01 CA FD 80 1E 9E FE 28 08 00 7C 0C 10 9E FE F4   '.......(..|.....'
    00200- 1D 9E FE F4 21 9E FE F4 00 30 7D 08 02 00 7C 1C   '....!....0}...|.'
    00210- 35 96 FC 1C 00 9E FE A0 E4 CA 3D E1 C1 9F F2 01   '5.........=.....'
    00220- 36 9E FE 6C 4C A6 FC 1C 11 00 54 1C 41 1E C0 0D   '6..lL.....T.A...'
    00230- 07 CF 15 E0 F6 EF 87 A0 9A EE 93 6C 01 C6 FD A0   '...........l....'
    00240- 0E 00 7C 1C C1 9F FE 01 4C A6 FC 1C 1D CA FD F6   '..|.....L.......'
    00250- 0E 00 7C 1C 2C C6 7D F8 35 96 FC 1C 40 1E C0 0D   '..|.,.}.5...@...'
    00260- E7 0E 16 E0 F6 EF 97 A0 54 2E FD 1C 40 0E C0 0D   '........T...@...'
    00270- FF 0E 16 E0 F6 EF 97 A0 0F 99 FC 54 60 C8 FD A0   '...........T`...'
    00280- 35 96 FC 1C FF 00 04 E0 08 CA FD A0 41 06 C0 0D   '5...........A...'
    00290- F6 9F 86 A0 08 9E FE 24 C1 9F 7E 00 2F CA FD F6   '.......$..~./...'
    002A0- 0E 00 7C 1C E4 CC BD A0 03 CC FD 2C 80 9E FE A0   '..|........,....'
    002B0- 4C A6 FC 1C E4 9E BE A0 3F 9E FE 60 38 9E 7E 86   'L.......?..`8.~.'
    002C0- 00 9E FE A0 38 00 54 1C 04 C8 7D 61 08 CC F1 24   '....8.T...}a...$'
    002D0- E6 9E B2 A0 4C A6 FC 1C 3E 00 54 1C 40 0E C0 0D   '....L...>.T.@...'
    002E0- F7 FE 15 E0 F6 EF 97 A0 40 0E C0 0D 9B EE 15 E0   '........@.......'
    002F0- F6 EF 97 A0 00 C6 FD A0 00 C8 FD A0 00 00 7C 1C   '..............|.'
    00300- 4F 0F 3E 14 01 C8 FD 80 03 C8 7D 62 99 98 A8 80   'O.>.......}b....'
    00310- 3F C8 7D 62 07 99 E8 54 54 2E E9 1C 00 00 7C 1C   '?.}b...TT.....|.'
    00320- 53 5E C0 0D 0F 2F 16 E0 F9 01 0C E0 F6 EF 8B A0   'S^.../..........'
    00330- F7 9F 82 A0 0B 9E FE 24 F7 9F 82 6C 12 9E FE 20   '.......$...l... '
    00340- 03 EE C3 28 4F EF 83 6C F6 EF 83 80 0E 00 0C E0   '...(O..l........'
    00350- F6 9F 82 A0 4F A1 BE A0 02 A0 FE 24 4F A1 BE 6C   '....O......$O..l'
    00360- 13 A0 FE 20 0A 9E FE 28 50 9F BE 6C 4F EF 83 80   '... ...(P..lO...'
    00370- FB 01 0C E0 F6 EF 93 80 40 0E C0 0D F7 8E 16 E0   '........@.......'
    00380- F6 EF 97 A0 64 7E C0 0D 07 47 15 E0 4D 9F BE A0   '....d~...G..M...'
    00390- 4C 9F BE 6C 4B 9F BE 60 4D 9F BE 6C 4B A1 BE A0   'L..lK..`M..lK...'
    003A0- 05 A0 FE 24 4B A1 BE 6C 0E A0 FE 24 4B A1 BE 6C   '...$K..l...$K..l'
    003B0- 19 A0 FE 20 50 9F BE 80 F7 9F 86 80 F6 9F 86 80   '... P...........'
    003C0- 4E 9F BE 80 49 A1 BE A0 48 A1 BE 60 47 A1 BE 68   'N...I...H..`G..h'
    003D0- 49 9D BE A0 48 9D BE 68 4E A1 BE 60 47 9D BE A0   'I...H..hN..`G...'
    003E0- 0B 9C FE 24 47 9D BE 6C 09 9C FE 24 47 9D BE 6C   '...$G..l...$G..l'
    003F0- 16 9C FE 20 4E A1 BE 80 4D 9D BE A0 4C 9B BE A0   '... N...M...L...'
    00400- 4B 99 BE A0 4A 97 BE A0 49 95 BE A0 48 93 BE A0   'K...J...I...H...'
    00410- 47 91 BE A0 4F 97 BE 80 4F 8F BE A0 50 8F BE 80   'G...O...O...P...'
    00420- 40 0E C0 0D 47 EF 15 E0 F6 EF 97 80 00 00 7C 1C   '@...G.........|.'
    00430- 00 00 00 00 00 02 00 00 6A 6A 6A 6A 67 E6 09 6A   '........jjjjg..j'
    00440- 85 AE 67 BB 72 F3 6E 3C 3A F5 4F A5 7F 52 0E 51   '..g.r.n<:.O..R.Q'
    00450- 8C 68 05 9B AB D9 83 1F 19 CD E0 5B 98 2F 8A 42   '.h.........[./.B'
    00460- 91 44 37 71 CF FB C0 B5 A5 DB B5 E9 5B C2 56 39   '.D7q........[.V9'
    00470- F1 11 F1 59 A4 82 3F 92 D5 5E 1C AB 98 AA 07 D8   '...Y..?..^......'
    00480- 01 5B 83 12 BE 85 31 24 C3 7D 0C 55 74 5D BE 72   '.[....1$.}.Ut].r'
    00490- FE B1 DE 80 A7 06 DC 9B 74 F1 9B C1 C1 69 9B E4   '........t....i..'
    004A0- 86 47 BE EF C6 9D C1 0F CC A1 0C 24 6F 2C E9 2D   '.G.........$o,.-'
    004B0- AA 84 74 4A DC A9 B0 5C DA 88 F9 76 52 51 3E 98   '..tJ...\...vRQ>.'
    004C0- 6D C6 31 A8 C8 27 03 B0 C7 7F 59 BF F3 0B E0 C6   'm.1..'....Y.....'
    004D0- 47 91 A7 D5 51 63 CA 06 67 29 29 14 85 0A B7 27   'G...Qc..g))....''
    004E0- 38 21 1B 2E FC 6D 2C 4D 13 0D 38 53 54 73 0A 65   '8!...m,M..8STs.e'
    004F0- BB 0A 6A 76 2E C9 C2 81 85 2C 72 92 A1 E8 BF A2   '..jv.....,r.....'
    00500- 4B 66 1A A8 70 8B 4B C2 A3 51 6C C7 19 E8 92 D1   'Kf..p.K..Ql.....'
    00510- 24 06 99 D6 85 35 0E F4 70 A0 6A 10 16 C1 A4 19   '$....5..p.j.....'
    00520- 08 6C 37 1E 4C 77 48 27 B5 BC B0 34 B3 0C 1C 39   '.l7.LwH'...4...9'
    00530- 4A AA D8 4E 4F CA 9C 5B F3 6F 2E 68 EE 82 8F 74   'J..NO..[.o.h...t'
    00540- 6F 63 A5 78 14 78 C8 84 08 02 C7 8C FA FF BE 90   'oc.x.x..........'
    00550- EB 6C 50 A4 F7 A3 F9 BE F2 78 71 C6 12 00 2A 59   '.lP......xq...*Y'
    00560- 2B 57 2C 4E 32 2E 3B 2F 55 3A A1 4D AD 4C AE 48   '+W,N2.;/U:.M.L.H'
    00570- AF 54 B0 5A B1 52 9E 51 BD 3F 00 38 00 38 20 24   '.T.Z.R.Q.?.8.8 $'
    00580- 2E 3C 2F 53 3A 82 40 8F 2A 96 2B 9F 2D AD 4C AE   '.</S:.@.*.+.-.L.'
    00590- 48 AF 54 B0 5A B1 52 80 23 B6 7C BB 5C 00 39 00   'H.T.Z.R.#.|.\.9.'
    005A0- 39 20 3D 2F 51 3A 5F 3E 5F 3C 77 5E 00 0D 0D 3D   '9 =/Q:_>_<w^...='
    005B0- 3D 3D 20 50 72 6F 70 65 6C 6C 65 72 20 49 49 20   '== Propeller II '
    005C0- 4D 6F 6E 69 74 6F 72 20 3D 3D 3D 0D 0D 00 3F 20   'Monitor ===...? '
    005D0- 2D 20 48 65 6C 70 0D 07 00 48 69 74 20 53 50 41   '- Help...Hit SPA'
    005E0- 43 45 00 20 20 27 00 27 0D 00 20 2D 0D 80 7B 61   'CE.  '.'.. -..{a'
    005F0- 64 72 7B 2E 61 64 72 7D 7D 80 7B 64 61 74 7B 20   'dr{.adr}}.{dat{ '
    00600- 64 61 74 7D 7D 80 61 64 72 80 0D 7E 48 55 42 8E   'dat}}.adr..~HUB.'
    00610- 92 60 56 69 65 77 0D 92 2F 9E 60 53 65 61 72 63   '.`View../.`Searc'
    00620- 68 0D 92 3A 9E 60 45 6E 74 65 72 0D AA 2E AA 5B   'h..:.`Enter....['
    00630- 3C 2F 3E 5D AA 60 4D 6F 76 65 0D AA 2E AA 5E 60   '</>].`Move....^`'
    00640- 43 68 65 63 6B 73 75 6D 0D AA 40 60 57 61 74 63   'Checksum..@`Watc'
    00650- 68 0D 5B 59 2F 57 2F 4E 5D 60 42 79 74 65 2F 77   'h.[Y/W/N]`Byte/w'
    00660- 6F 72 64 2F 6C 6F 6E 67 0D 7E 43 4F 47 53 8E 63   'ord/long.~COGS.c'
    00670- 6F 67 2B AA 7B 2B AA 7D 60 53 74 61 72 74 0D 63   'og+.{+.}`Start.c'
    00680- 6F 67 2D 60 53 74 6F 70 0D 4D 60 4D 61 70 0D 7E   'og-`Stop.M`Map.~'
    00690- 50 49 4E 53 8E 7B 70 69 6E 7D 5B 48 2F 4C 2F 54   'PINS.{pin}[H/L/T'
    006A0- 2F 5A 2F 52 5D 60 48 69 67 68 2F 6C 6F 77 2F 74   '/Z/R]`High/low/t'
    006B0- 6F 67 67 6C 65 2F 6F 66 66 2F 72 65 61 64 0D 70   'oggle/off/read.p'
    006C0- 69 6E 23 60 57 61 74 63 68 0D 70 69 6E 7C 63 66   'in#`Watch.pin|cf'
    006D0- 67 60 43 6F 6E 66 69 67 75 72 65 0D 64 61 74 5C   'g`Configure.dat\'
    006E0- 60 53 65 74 20 44 41 43 73 0D 7E 4D 49 53 43 8E   '`Set DACs.~MISC.'
    006F0- 64 61 74 2A 60 53 65 74 20 63 6C 6F 63 6B 0D 27   'dat*`Set clock.''
    00700- 60 52 65 70 65 61 74 0D 51 60 51 75 69 74 0D 00   '`Repeat.Q`Quit..'
    00710- 00 00 00 00 40 3C C0 0D D7 01 04 E0 00 EC D3 A0   '....@<..........'
    00720- 12 CC FF 0C 12 CE FF 0C 09 CE FF 28 DB CE 7F 0C   '...........(....'
    00730- 92 74 FF 0C CB 22 FC 0C 0A E6 7F F8 94 56 FF 0C   '.t...".......V..'
    00740- CB 32 FC 0C 01 C6 FF A0 D2 BE FD 1C AA 00 FC 0C   '.2..............'
    00750- B2 A2 FC 0C 6F E3 FE 1C E9 1A FE 1C 2B 73 FE 1C   '....o.......+s..'
    00760- 2F B0 6B F8 19 00 7C 1C 0B 1B FE 1C A4 02 FC 0C   '/.k...|.........'
    00770- 2B 73 FE 1C 1F 00 54 1C DA 65 FD 54 B2 00 FC 0C   '+s....T..e.T....'
    00780- C0 84 FD 1C B2 E4 FC 0C 11 00 7C 1C DD B7 BF A0   '..........|.....'
    00790- E0 65 FD 54 B2 3E FC 0C C0 84 FD 1C 38 00 7C 1C   '.e.T.>......8.|.'
    007A0- 2A 73 FE 1C 35 00 68 1C DD B9 BF A0 B2 84 FC 0C   '*s..5.h.........'
    007B0- C0 84 FD 1C 39 00 7C 1C 01 C6 FF A2 02 C6 EB A2   '....9.|.........'
    007C0- 04 C6 EB A0 D2 BE FD 1C 17 00 7C 1C 0F B8 FF A0   '..........|.....'
    007D0- 49 DD FE 1C 12 00 7C 1C FF B8 FF A0 49 DD FE 1C   'I.....|.....I...'
    007E0- 17 00 7C 1C FF B8 FF A0 4A DD FE 1C 18 00 7C 1C   '..|.....J.....|.'
    007F0- DB B9 BF A0 4C DD FE 1C 18 00 7C 1C DE B7 BF A0   '....L.....|.....'
    00800- E5 B9 BF A0 C7 A2 FD 1C 0E 45 FE 1C B2 B6 7F 0C   '.........E......'
    00810- 00 00 04 E0 00 B0 FF A0 E5 CC FD 1C F6 BB 07 86   '................'
    00820- 4B 00 68 1C E3 B7 BF 80 DC B7 3F 87 3F 00 78 1C   'K.h.......?.?.x.'
    00830- DB BD BF A0 E5 BD BF 60 18 00 7C 1C E1 B1 BF E9   '.......`..|.....'
    00840- 42 00 4C 1C E1 B9 BF A0 E4 B9 BF 2C DB B9 BF 80   'B.L........,....'
    00850- 39 00 7C 1C C7 A2 FD 1C 01 B2 FF A0 DB BF BF A0   '9.|.............'
    00860- E5 BF BF 60 0E 45 FE 1C 59 B2 7F FA E1 B5 BF A0   '...`.E..Y.......'
    00870- 01 B4 FF 80 B3 BE 7F 0C F6 BB 87 A0 E7 D0 FD 1C   '................'
    00880- 5A B4 FF F6 13 BE FF 0C 18 00 7C 1C D8 B3 BF A0   'Z.........|.....'
    00890- C7 A2 FD 1C 27 53 FE 1C E5 BB BF 4C E5 BB BF 60   '....'S.....L...`'
    008A0- 3C B2 7F 86 DB B1 AB A0 DD B7 AB A0 D8 BB AB A0   '<...............'
    008B0- DD B7 3F 85 DA B1 B3 A0 E4 B1 B3 2C D8 B7 B3 80   '..?........,....'
    008C0- D8 BB B3 80 7E CA F1 6C 7E CE F1 6C B2 B6 7F 0C   '....~..l~..l....'
    008D0- B3 BA 7F 0C E5 CC FD 1C E7 D0 FD 1C 71 B4 FF F6   '............q...'
    008E0- 7E CA F1 6C 7E CE F1 6C 18 00 7C 1C C7 A2 FD 1C   '~..l~..l..|.....'
    008F0- B2 B6 7F 0C E5 CC FD 1C DD B3 BF 80 79 B4 FF F6   '............y...'
    00900- D9 BB BF A0 08 C4 FF A0 85 1B FF 1C 16 00 7C 1C   '..............|.'
    00910- E6 C6 FD 52 01 C4 FF A0 E4 C6 E9 50 E3 C5 AB A0   '...R.......P....'
    00920- 01 C4 EB 2C E0 CC FD 1C DD B5 BF A0 85 1B FF 1C   '...,............'
    00930- 90 3D FF 1C A2 55 FF 1C 16 00 54 1C E0 CC FD 1C   '.=...U....T.....'
    00940- DA BB 3F 86 89 00 68 1C 86 00 7C 1C B2 FA FC 0C   '..?...h...|.....'
    00950- 6F E3 FE 1C 00 B6 7F 0C 9F 43 FF 1C 20 B0 7F 86   'o........C.. ...'
    00960- 92 00 54 1C 16 00 7C 1C E0 B6 7F 0C 27 53 FE 1C   '..T...|.....'S..'
    00970- DD B3 BF A0 00 BA FF A0 2B B0 7F 86 27 53 EA 1C   '........+...'S..'
    00980- DD B3 3F 0C 18 00 7C 1C 01 B6 FF 0C 03 B6 7F 0C   '..?...|.........'
    00990- 17 00 7C 1C 07 B2 FF A0 90 3D FF 1C D9 B1 BF A0   '..|......=......'
    009A0- 01 B0 FF 0D D9 B1 3F 86 30 B0 CF A0 31 B0 F3 A0   '......?.0...1...'
    009B0- 4D B0 EB A0 96 3D FF 1C 01 B2 FF 85 A2 00 4C 1C   'M....=........L.'
    009C0- 16 00 7C 1C DA 66 FD 52 DB 66 E9 52 D9 66 E9 52   '..|..f.R.f.R.f.R'
    009D0- D8 66 E9 52 D6 66 E9 50 DB C1 BF A0 D6 C0 7F 0D   '.f.R.f.P........'
    009E0- A5 00 68 1C 17 00 7C 1C 27 53 FE 1C E3 B6 7F 0C   '..h...|.'S......'
    009F0- 23 B6 FF 0C DD B7 3F E8 18 00 7C 1C D5 B6 7F 0C   '#.....?...|.....'
    00A00- 17 00 7C 1C B2 5C FD 0C 6F E3 FE 1C 16 00 7C 1C   '..|..\..o.....|.'
    00A10- B4 A4 7F 0C C1 B4 FF 00 00 B4 7F F8 C1 B2 FF 00   '................'
    00A20- D8 B3 BF 6E C1 00 54 1C DA 01 3C 1C E5 B7 BF 4C   '...n..T...<....L'
    00A30- E5 B7 BF 60 E5 B9 BF 4C E5 B9 BF 60 DB B9 3F 85   '...`...L...`..?.'
    00A40- 1D 00 70 1C DC B5 BF A0 DB B5 BF 84 E4 B5 BF 28   '..p............('
    00A50- 01 B4 FF 80 00 00 7C 1C 02 C6 7F 61 9A CB FD 0C   '......|....a....'
    00A60- 9A CF FD 0C 04 C6 7F 61 9B CB FD 0C 9B CF FD 0C   '.......a........'
    00A70- E3 C9 BF A0 01 C8 FF 28 E3 CB BF A0 01 CA FF 84   '.......(........'
    00A80- D3 CB BF 6C E5 BD BF 60 E5 BF BF 60 00 00 7C 1C   '...l...`...`..|.'
    00A90- D6 B6 7F 0D 00 BA CF A0 01 BA F3 A0 E6 00 7C 1C   '..............|.'
    00AA0- B2 B6 7F 0C C1 BA FF 00 00 00 7C 1C C1 BB 7F 00   '..........|.....'
    00AB0- 00 00 7C 1C A2 00 FC 0C 3E B0 FF A0 96 3D FF 1C   '..|.....>....=..'
    00AC0- 9F 43 FF 1C 27 B0 7F 86 F4 00 54 1C 18 B0 FF 0E   '.C..'.....T.....'
    00AD0- 96 3D D7 1C EF 00 54 1C 0A 01 7C 1C 9F 43 FF 1C   '.=....T...|..C..'
    00AE0- 0D B0 7F 86 09 01 68 1C 08 B0 7F 86 7F B0 57 86   '......h.......W.'
    00AF0- 01 01 68 1C 20 B0 7F 85 7E B0 4F E1 F3 00 70 1C   '..h. ...~.O...p.'
    00B00- AA B0 7F 0C 16 00 7C 0D A6 02 F0 0C 96 3D CF 1C   '......|......=..'
    00B10- F3 00 7C 1C 16 00 7C 0E A8 B0 57 0C 96 3D D7 1C   '..|...|...W..=..'
    00B20- 90 3D D7 1C 18 B0 D7 0C 96 3D D7 1C A6 02 D4 0C   '.=.......=......'
    00B30- F3 00 7C 1C AA 00 FC 0C A2 00 FC 0C D4 B1 BF A0   '..|.............'
    00B40- 96 3D FF 1C 00 00 7C 1C 00 AE FF A0 00 00 04 E0   '.=....|.........'
    00B50- 2A 73 FE 1C 23 4D D6 1C 20 B0 7F 86 10 01 68 1C   '*s..#M.. .....h.'
    00B60- 27 B0 7F 86 1E 01 54 1C A4 04 FC 0C 1A B0 FF 0C   ''.....T.........'
    00B70- 27 B0 7F 86 10 01 68 1C 1E B1 7F F8 D8 BB BF A0   ''.....h.........'
    00B80- 23 4D FE 1C 16 01 7C 1C 01 AE FF 85 D7 C3 8F A0   '#M....|.........'
    00B90- E1 43 BE 54 00 00 04 E4 00 00 7C 1C 11 AE FF E9   '.C.T......|.....'
    00BA0- 1D 00 70 1C DD ED 93 A0 00 00 7C 1C 2A 73 FE 1C   '..p.......|.*s..'
    00BB0- 1D 00 68 1C 00 00 7C 1C A4 02 FC 0C 00 BA FF A2   '..h...|.........'
    00BC0- 3A 7D FE 1E 18 B0 FF 0C 3F 91 FE 1C 04 BA F3 2C   ':}......?......,'
    00BD0- D8 BB B3 68 2D 01 70 1E A6 02 FC 0C 3A 7D FE 1E   '...h-.p.....:}..'
    00BE0- 3F 91 FE 1C 1A B0 F3 0C 60 B0 7F E1 7B B0 73 85   '?.......`...{.s.'
    00BF0- 20 B0 F3 84 00 00 7C 1C 18 B0 FF 0C 20 B0 7F 86   ' .....|..... ...'
    00C00- 3A 01 68 1C A6 02 FC 0C 00 00 7C 1E 2F B0 7F E1   ':.h.......|./...'
    00C10- 3A B0 73 85 07 B0 F3 80 40 B0 4F E1 47 B0 73 85   ':.s.....@.O.G.s.'
    00C20- 20 B0 F3 80 60 B0 4F E1 67 B0 73 85 57 B0 F3 84   ' ...`.O.g.s.W...'
    00C30- 00 00 7C 1C DE B7 BF A0 E5 B9 BF 60 DB B9 BF 80   '..|........`....'
    00C40- C7 A2 FD 1C DB BD BF A0 DE BB BF A0 05 C4 FF A0   '................'
    00C50- 85 1B FF 1C 8E 3D FF 1C E3 B1 BF A0 1B B0 FF 3C   '.....=.........<'
    00C60- DA B7 BF A0 D8 B7 BF 4C DB B9 BF A0 E4 B9 BF 2C   '.......L.......,'
    00C70- DB B5 BF 84 B2 BC 7F 0C E5 CC FD 1C E3 C5 BF A0   '................'
    00C80- 01 C4 FF 2C 85 1B FF 1C 90 3D FF 1C 5A B7 FF F6   '...,.....=..Z...'
    00C90- B2 0E FD 0C 6F E3 FE 1C B2 BC 7F 0C C1 B0 FF 00   '....o...........'
    00CA0- 20 B0 7F 85 7E B0 4F E1 2E B0 F3 A0 96 3D FF 1C   ' ...~.O......=..'
    00CB0- 63 B9 FF F6 12 BC FF 0C B2 16 FD 0C 6F E3 FE 1C   'c...........o...'
    00CC0- A2 55 FF 1C 4E B5 6B FA 00 00 7C 1C B4 A4 7F 0C   '.U..N.k...|.....'
    00CD0- C1 B0 FF 00 00 B0 7F F8 80 B0 7F 62 28 E1 D6 0C   '...........b(...'
    00CE0- B3 B0 57 0C B5 A4 57 0C 70 01 54 1C 60 B0 7F 86   '..W...W.p.T.`...'
    00CF0- 10 B2 EB E0 7E B0 57 86 10 B2 EB 80 90 3D EB 1C   '....~.W......=..'
    00D00- 7B B3 EB F6 8E 3D EB 1C 70 01 68 1C 0D B0 7F 86   '{....=..p.h.....'
    00D10- 0B 1B EA 1C 00 B2 EB A0 96 3D D7 1C 01 B2 D7 80   '.........=......'
    00D20- 70 01 7C 1C E2 B3 BF A0 02 B2 FF 2C D9 BB BF 20   'p.|........,... '
    00D30- E2 B3 BF A0 04 BA FF 24 DD B1 BF A0 92 3D FF 1C   '.......$.....=..'
    00D40- 89 B3 FF F6 00 00 7C 1C D5 B1 BF A0 96 01 7C 1C   '......|.......|.'
    00D50- 20 B0 FF A0 96 01 7C 1C 0F B0 FF 60 0A B0 7F 85   ' .....|....`....'
    00D60- 30 B0 F3 80 37 B0 CF 80 01 B0 FF 2C 69 B1 FF 0C   '0...7......,i...'
    00D70- 0D AE FF 0C F3 AF BF 80 0D AE 7F 0C 01 B0 FF 29   '...............)'
    00D80- DC CE 7F 0C 99 B1 7F FA 00 00 7C 1C A2 55 FF 1C   '..........|..U..'
    00D90- 9F 01 68 1C 00 00 7C 1C 80 D0 FF 68 17 D2 FF 0E   '..h...|....h....'
    00DA0- E8 D3 17 86 16 D2 D7 0C A2 D0 57 0C 18 B0 D7 0C   '..........W.....'
    00DB0- 16 D0 D7 0C A2 D2 57 0C 00 00 7C 1C 17 00 7C 0E   '......W...|...|.'
    00DC0- A3 00 E9 0C 09 D8 FF A0 F3 D5 BF A4 01 D4 FF 38   '...............8'
    00DD0- B0 CD FF F8 0C D4 FF 0C 01 D6 FF 30 F3 D5 BF 80   '...........0....'
    00DE0- 0D D4 7F 0C D6 CC 7F 0D B2 D9 FF F6 18 D6 FF 28   '...............('
    00DF0- AB D6 7F 0C AB 01 7C 1C E6 AD BF 54 25 AD FF 0D   '......|....T%...'
    00E00- F0 AC 7F 0C ED E1 8F A0 04 E0 CF 28 F0 E3 8F A4   '...........(....'
    00E10- ED E1 8F 80 ED E3 8F 80 EE E5 8F A0 06 E4 CF 10   '................'
    00E20- F0 E5 0F E1 F1 E5 0F 85 EF E5 8F A0 03 E4 CF 10   '................'
    00E30- F0 E5 0F E1 F1 E5 0F 85 EF DB 8F 80 03 DA CF 28   '...............('
    00E40- ED E7 8F A0 EE DB BF A0 EF DD BF A0 3A DE FF 0C   '............:...'
    00E50- BB DF 7F FA CF 01 7C 1C 5C 05 00 00 FF FF 01 00   '......|.\.......'
    00E60- 0D 28 04 00 2D 80 04 00 89 00 00 00 78 CF 68 9D   '.(..-.......x.h.'
    00E70- 3D 3D 20 45 6E 64 20 6F 66 20 52 4F 4D 20 3D 3D   '== End of ROM =='
    

    It is now 128 bytes shorter than it used to be, since I've used this time during full-chip verification being done by Beau and Open Silicon to pack things more efficiently.

    Here is the binary/HMAC-signed loader (it's only $70 longs and starts at $000):
    '********************************************************
    '*							*
    '*		Propeller II ROM Booter			*
    '*							*
    '*		Version 0.1				*
    '*							*
    '*		11/01/2012				*
    '*							*
    '********************************************************
    
    CON
    
      rx_pin = 91
      tx_pin = 90
      spi_cs = 89
      spi_ck = 88
      spi_di = 87
      spi_do = 86
    
      base = $E80
    
    
    DAT
    '
    '
    ' Version (@$000)
    '
    			byte	"Prop2.0 "
    '
    '
    ' Shut down (@$008)
    '
    			org
    
    			clkset	h001+offset		'set clock to rc slow
    			cogstop	h200+offset		'stop cog0
    offset
    '
    '
    ' Entry, read fuses (@$010)
    '
    			org
    
    			reps	#256,@:fuse		'ready to read 256 fuses
    			setport	#rx_pin			'set rx_pin port for booting
    
    			cogid	fuse_read	nr	'read fuses (172 fuses + 84 zeros)
    			cogid	fuse_read	nr,wc	'(last iteration initializes cnt to $00000000_00000001)
    			add	fuse_read,#1
    			test	fuse_read,#$1F	wz
    :fusex			rcr	fuses,#1
    :fuse	if_z		add	:fusex,h200
    
    			cogid	spi_read	nr	'disable fuses and enable cnt (spi_read[10..0] = 0)
    '
    '
    ' Attempt to boot from serial
    '
    			jnp	monitor_ptr,#boot_flash	'if rx_pin is low, skip serial and boot from flash
    
    			call	#rx_bit			'measure low rx calibration pulses (host $F9 -> %1..010011111..)
    			mov	threshold,delta		'and calculate threshold
    			call	#rx_bit			'(any timeout results in flash boot)
    			add	threshold,delta
    h001			shr	threshold,#1		'(9 lsb's are $001)
    
    			mov	count,#250		'ready to receive/verify 250 lfsr bits
    :lfsrin			call	#rx_bit			'receive bit ($FE/$FF) into c
    			test	lfsr,#$01	wz	'get lfsr bit into nz
    	if_c_eq_z	jmp	#boot_flash		'if mismatch, boot from flash
    			test	lfsr,#$B2	wc	'advance lfsr
    			rcl	lfsr,#1
    			djnz	count,#:lfsrin		'loop for next bit in
    
    			mov	count,#250+8		'ready to transmit 250 lfsr bits + 8 version bits
    :lfsrout		cmp	count,#8	wz	'if last 8 bits, set lfsr so that version will be output
    	if_z		mov	lfsr,#$52		'$52 results in version $20 being sent (%00000100)
    			test	lfsr,#$01	wz	'get lfsr/version bit into nz, z=1 on last iteration
    			call	#wait_rx		'wait for rx low (convey incoming $F9 on rx_pin to $FE/$FF on tx_pin)
    			clrp	#tx_pin			'make tx low
    			call	#wait_rx		'wait for rx high
    			setpnz	#tx_pin			'make tx lfsr/version bit
    			call	#wait_rx		'wait for rx low
    			setp	#tx_pin			'make tx high
    			call	#wait_rx		'wait for rx high
    			test	lfsr,#$B2	wc	'advance lfsr
    			rcl	lfsr,#1
    			djnz	count,#:lfsrout		'loop for next bit out
    
    			jmp	#load			'serial handshake done, attempt to load from serial (z=1)
    '
    '
    ' Wait for rx low/high - if timeout, attempt to boot from flash
    '
    wait_rx			getcnt	time			'ready timeout
    			add	time,timeout
    
    :waitpxx		waitpne	rx_mask,rx_mask	wc	'wait for rx low/high with timeout
    
    			notb	:waitpxx,#23		'toggle waitpeq/waitpne
    
    wait_rx_ret	if_nc	ret				'return if not timeout (boot_flash follows)
    '
    '
    ' Attempt to boot from flash
    '
    boot_flash		mov	count,#4		'ready for 3 resets and 1 read command
    
    :cmd			setp	#spi_cs			'spi_cs high
    			clrp	#spi_ck			'spi_ck low
    
    			reps	#32,@:bit		'ready for 32 command bits
    			clrp	#spi_cs			'spi_cs low
    
    			cmpr	count,#1	wc	'first 3 commands = $FF_FF_FF_FF (reset)
    	if_nc		rol	spi_read,#1	wc,wz	'last command = $03_00_00_00 (read from 0), z=0
    			setpc	#spi_di
    			setp	#spi_ck			'cycle spi_ck
    :bit			clrp	#spi_ck
    
    			djnz	count,#:cmd		'loop for next spi command
    '
    '
    ' Load from serial (z=1) or flash (z=0)
    '
    load			setptra	loader_pgm		'load loader into base+$000..$7DF, HMAC into base+$7E0..$7FF
    
    			mov	count,h200		'ready to input $200 longs
    :long			mov	bits,#32		'ready to input 32 data bits
    
    :bit	if_z		call	#rx_bit			'input serial bit (serial mode)
    	if_nz		getp	#spi_do		wc	'input spi_do (flash mode)
    	if_nz		setp	#spi_ck			'high spi_ck (flash mode)
    	if_nz		clrp	#spi_ck			'low spi_ck (flash_mode)
    			rcl	data,#1			'shift bit into long
    			djnz	bits,#:bit		'loop, adequate time for next flash bit
    
    			wrlong	data,ptra++		'store long in hub ram (ptra=base+$800 after)
    			djnz	count,#:long		'loop for next long (count=0 after)
    '
    '
    ' Compute loader HMAC signature for loader authentication
    '
    ' base+$000..$7DF = loader				($1F8 longs)
    ' base+$7E0..$7FF = loader HMAC signature		(8 longs)
    ' base+$800..$81F = fuses, 1st half are HMAC key	(8 longs)
    ' base+$820..$83F = proper HMAC signature		(8 longs)
    ' base+$840..$843 = sha256 command interface		(1 long)
    '
    			reps	#8,#1			'store 128-bit key + 44 extra fuses + 84 zero bits
    			setinda	fuses			'into base+$800..$81F
    			wrlong	inda++,ptra++		'(ptra = base+$820, afterwards)
    
    			wrlong	count,sha256_ptr	'clear sha256 command
    
    			setcog	#1			'launch sha256 in cog1
    			coginit	sha256_pgm,sha256_ptr
    
    			setinda	begin_hmac		'do sha256 commands to compute proper loader hmac
    			mov	count,#3		'ready for 3 commands: begin_hmac, hash_bytes, read_hash
    :cmd			wrlong	inda++,sha256_ptr	'set command
    :wait			rdlong	data,sha256_ptr	wz	'wait for command done
    			tjnz	data,#:wait
    			djnz	count,#:cmd		'loop for next command (count=0, z=1 after)
    
    			cogstop	h001			'done with sha256, stop cog1
    '
    '
    ' If loader authenticates, run it
    '
    			reps	#8,@:cmp		'verify loader hmac signature (z=1 on entry)
    			setcog	#0			'ready to relaunch cog0 with loader/monitor
    
    			rdlong	bits,ptra[-$10]		'get loader hmac signature long
    			rdlong	data,ptra++		'get proper hmac signature long
    :cmp	if_z		cmp	bits,data	wz	'compare, z=1 if authenticated
    
    	if_z		coginit	loader_pgm,loader_ptr	'if loader authenticated, relaunch cog0 with loader
    '
    '
    ' Authentication failed, hide fuses and clear memory
    '
    			reps	#$20000/8,@:clr		'clear all memory
    			cogid	monitor_pgm	nr	'hide fuses (bit 10 set)
    
    			wrlong	count,ptra++		'(count=0)
    :clr			wrlong	count,ptra++
    '
    '
    ' If key <> 0, shut down - else, monitor
    '
    			or	fuses+0,fuses+1	wz	'check if 128-bit key = 0
    	if_z		or	fuses+2,fuses+3	wz
    
    	if_nz		mov	monitor_pgm,#$008	'if key <> 0, shut down
    
    			coginit	monitor_pgm,monitor_ptr	'relaunch cog0 with shut down or monitor
    '
    '
    ' Receive bit (c) - compare incoming pulse to threshold
    '
    rx_bit			call	#wait_rx		'wait for rx low
    			getcnt	delta			'get time
    
    			call	#wait_rx		'wait for rx high
    			subcnt	delta			'get time delta
    
    			cmp	delta,threshold	wc	'compare time delta to threshold
    
    rx_bit_ret		ret
    '
    '
    ' Constants
    '
    fuse_read		long	$200			'(gets modified to $300)
    timeout			long	20_000_000 / 1000 * 150	'150ms @20MHz (rcfast)
    rx_mask			long	1 << (rx_pin & $1F)
    lfsr			long	"P"
    spi_read		long	$03_000000
    h200			long	$200
    
    begin_hmac		long	1<<30 + (($004<<2)-1)<<17 + base+$800	'begin_hmac, loads key at base+$800 (4 longs)
    hash_bytes		long	2<<30 + (($1F8<<2)-1)<<17 + base+$000	'hash_bytes, hashes message at base+$000 ($1F8 longs)
    read_hash		long	3<<30			  + base+$820	'read_hash, writes hash at base+$820 (8 longs)
    
    sha256_pgm		long	$1D0			'sha256 program address
    sha256_ptr		long	base+$840		'sha256 parameter (points to command)
    
    loader_pgm		long	base+$000		'loader program address
    loader_ptr		long	base+$800		'loader parameter (points to fuses)
    
    monitor_pgm		long	$55C+$1B4		'monitor program address
    monitor_ptr		long	tx_pin<<9 + rx_pin	'monitor parameter (conveys pins)
    '
    '
    ' Variables
    '
    fuses			res	8
    count			res	1
    bits			res	1
    data			res	1
    time			res	1
    delta			res	1
    threshold		res	1
    

    Here is the SHA-256/HMAC program used to authenticate code (thanks to Pedward for making this happen):
    '********************************************************
    '*							*
    '*		Propeller II ROM SHA-256/HMAC		*
    '*							*
    '*		Version 0.1				*
    '*							*
    '*		11/01/2012				*
    '*							*
    '********************************************************
    
    '
    ' Usage:			commandlong := 0				'pre-clear command long
    '				cognew($1D0, @commandlong)			'start SHA-256/HMAC in new cog
    '
    ' Start here for HMAC:		commandlong := 1<<30 + (keysize-1)<<17 + @key	'start HMAC with key of keysize bytes (1..64)
    '				repeat while commandlong			'(wait for command done)
    '
    ' Start here for SHA-256:	commandlong := 2<<30 + (msgsize-1)<<17 + @msg	'hash msg of msgsize bytes (1..8192)
    '				repeat while commandlong			'(wait for command done)
    '
    '				{issue more 2<<30 commands if msg > 8192 bytes}
    '
    '				commandlong := 3<<30 + @hashbuffer		'read resulting hash into hashbuffer (32 bytes)
    '				repeat while commandlong			'(wait for command done)
    '
    '				{hasbuffer now contains result, ready for new 1<<30 or 2<<30 command}
    '
    
    DAT
    
    		org
    
    		setf	#%0_1111_0000	'configure movf for sbyte0 -> {dbyte3,dbyte2,dbyte1,dbyte0,dbyte3,...}
    
    		call	#init_hash	'init hash, clear hmac mode, reset byte count
    '
    '
    ' Command Loop
    '
    command		rdlong	x,ptra		'wait for command (%cc_nnnnnnnnnnnnn_ppppppppppppppppp)
    		tjz	x,#command
    
    		setptrb	x		'get pointer (%ppppppppppppppppp)
    
    		mov	count,x		'get count (%nnnnnnnnnnnnn)
    		shl	count,#2
    		shr	count,#2+17
    		add	count,#1	'+1 for 1..8192 range
    
    		shr	x,#32-2		'get command (%cc)
    
    		cachex			'invalidate cache for fresh rdbytec's
    
    		djz	x,#begin_hmac	'1 = begin hmac, pointer @key (count+1 bytes, 1..64)
    		djz	x,#hash_bytes	'2 = hash bytes, pointer @message (count+1 bytes, 1..8192)
    		djz	x,#read_hash	'3 = read hash, pointer @hashbuffer (32 bytes)
    
    done		wrlong	zero,ptra	'clear command to signal done
    
    		jmp	#command	'get next command
    '
    '
    ' Begin HMAC
    '
    begin_hmac	call	#end_hash	'end any hash in progress
    
    :ipad		mov	x,#$00		'get and hash ipad key (full block)
    		cmpr	count,bytes wc	'after key bytes, hash $00's to fill block
    	if_c	rdbytec	x,ptrb++
    		xor	x,#$36		'xor bytes with ipad ($36)
    		call	#hash_byte	'(last iteration triggers hash_block, z=1)
    	if_nz	jmp	#:ipad
    
    		reps	#16,#2		'save opad key
    		setinds	opad_key,w
    		mov	indb,inda++
    		xor	indb++,opad	'xor bytes with opad ($5C)
    
    		mov	hmac,#1		'set hmac mode
    
    		jmp	#done
    '
    '
    ' Hash Bytes
    '
    hash_bytes	rdbytec	x,ptrb++	'hash bytes
    		call	#hash_byte
    		djnz	count,#hash_bytes
    
    		jmp	#done
    '
    '
    ' Read Hash
    '
    read_hash	tjz	hmac,#:not	'if not hmac, output hash
    
    
    		call	#end_hash	'hmac, end current hash
    
    		reps	#16,#1		'get opad key into w[0..15] (full block)
    		setinds	w,opad_key
    		mov	indb++,inda++
    
    		call	#hash_block	'hash opad key
    
    		reps	#8,#1		'get hashx[0..7] into w[0..7]
    		setinds	w,hashx
    		mov	indb++,inda++
    
    		movd	hash_byte,#w+8	'account for opad key and hashx bytes
    		mov	bytes,#64+32	'(1-1/2 blocks, 1/2 block needs end_hash)
    
    
    :not		call	#end_hash	'end current hash
    
    		setinda	hashx		'store hashx[0..7] at pointer, big-endian
    		mov	count,#8
    :out		reps	#4,#2
    		mov	x,inda++
    		rol	x,#8
    		wrbyte	x,ptrb++
    		djnz	count,#:out
    
    		jmp	#done
    '
    '
    ' End Hash - hash $80, any $00's needed to get to offset $38, then 8-byte length
    '
    end_hash	mov	length,bytes	'get message length in bits
    		shl	length,#3
    
    		mov	x,#$80		'hash end-of-message byte ($80)
    :fill		call	#hash_byte	'(may trigger hash_block)
    		mov	x,bytes		'hash any $00's needed to get to offset $38
    		and	x,#$3F
    		cmp	x,#$38	wz
    		mov	x,#$00
    	if_nz	jmp	#:fill
    
    :len		test	bytes,#$04  wc	'hash 8-byte length, big-endian
    	if_c	rol	length,#8	'(hash four $00's, then four length bytes)
    	if_c	mov	x,length
    		call	#hash_byte	'(last iteration triggers hash_block)
    	if_nz	jmp	#:len
    
    		reps	#8,#1		'save hash[0..7] into hashx[0..7]
    		setinds	hashx,hash
    		mov	indb++,inda++
    
    init_hash	reps	#8,#1		'copy hash_init[0..7] into hash[0..7]
    		setinds	hash,hash_init
    		mov	indb++,inda++
    
    		mov	hmac,#0		'clear hmac mode
    		mov	bytes,#0	'reset byte count
    init_hash_ret
    end_hash_ret	ret
    '
    '
    ' Hash Byte - add byte to w[0..15] and hash block if full (z=1)
    '
    hash_byte	movf	w,x		'store byte into w[0..15], big-endian
    
    		add	bytes,#1	'increment byte count
    
    		test	bytes,#$03  wz	'every 4th byte, increment w pointer
    	if_z	add	hash_byte,d0
    
    		test	bytes,#$3F  wz	'every 64th byte, reset w pointer
    	if_z	movd	hash_byte,#w
    
    	if_z	call	#hash_block	'every 64th byte, hash block
    
    hash_byte_ret	ret
    '
    '
    ' Hash Block - first extend w[0..15] into w[16..63] to generate schedule
    '
    hash_block	reps	#48,@:sch	'i = 16..63
    		setinds	w+16,w+16-15+7	'indb = @w[i], inda = @w[i-15+7]
    
    		setinda	--7		's0 = (w[i-15] -> 7) ^ (w[i-15] -> 18) ^ (w[i-15] >> 3)
    		mov	indb,inda--
    		mov	x,indb
    		rol	x,#18-7
    		xor	x,indb
    		ror	x,#18
    		shr	indb,#3
    		xor	indb,x
    
    		add	indb,inda	'w[i] = s0 + w[i-16]
    
    		setinda	++14		's1 = (w[i-2] -> 17) ^ (w[i-2] -> 19) ^ (w[i-2] >> 10)
    		mov	x,inda
    		mov	y,x
    		rol	y,#19-17
    		xor	y,x
    		ror	y,#19
    		shr	x,#10
    		xor	x,y
    
    		add	indb,x		'w[i] = s0 + w[i-16] + s1
    
    		setinda	--5		'w[i] = s0 + w[i-16] + s1 + w[i-7]
    :sch		add	indb++,inda
    
    
    ' Load variables from hash
    
    		reps	#8,#1		'copy hash[0..7] into a..h
    		setinds	a,hash
    		mov	indb++,inda++
    
    
    ' Do 64 hash iterations on variables
    
    		reps	#64,@:itr	'i = 0..63
    		setinds	k+0,w+0		'indb = @k[i], inda = @w[i]
    
    		mov	x,g		'ch = (e & f) ^ (!e & g)
    		xor	x,f
    		and	x,e
    		xor	x,g
    
    		mov	y,e		's1 = (e -> 6) ^ (e -> 11) ^ (e -> 25)
    		rol	y,#11-6
    		xor	y,e
    		rol	y,#25-11
    		xor	y,e
    		ror	y,#25
    
    		add	x,y		't1 = ch + s1
    		add	x,indb++	't1 = ch + s1 + k[i]
    		add	x,inda++	't1 = ch + s1 + k[i] + w[i]
    		add	x,h		't1 = ch + s1 + k[i] + w[i] + h
    
    		mov	y,c		'maj = (a & b) ^ (b & c) ^ (c & a)
    		and	y,b
    		or	y,a
    		mov	h,c
    		or	h,b
    		and	y,h
    
    		mov	h,a		's0 = (a -> 2) ^ (a -> 13) ^ (a -> 22)
    		rol	h,#13-2
    		xor	h,a
    		rol	h,#22-13
    		xor	h,a
    		ror	h,#22
    
    		add	y,h		't2 = maj + s0
    
    		mov	h,g		'h = g
    		mov	g,f		'g = f
    		mov	f,e		'f = e
    		mov	e,d		'e = d
    		mov	d,c		'd = c
    		mov	c,b		'c = b
    		mov	b,a		'b = a
    
    		add	e,x		'e = e + t1
    
    		mov	a,x		'a = t1 + t2
    :itr		add	a,y
    
    
    ' Add variables back into hash
    
    		reps	#8,#1		'add a..h into hash[0..7]
    		setinds	hash,a
    		add	indb++,inda++
    
    hash_block_ret	ret
    '
    '
    ' Defined data
    '
    zero		long	0
    d0		long 	1 << 9
    
    opad		long	$36363636 ^ $5C5C5C5C
    
    hash_init	long	$6A09E667, $BB67AE85, $3C6EF372, $A54FF53A, $510E527F, $9B05688C, $1F83D9AB, $5BE0CD19	'fractionals of square roots of primes 2..19
    
    k		long	$428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1, $923F82A4, $AB1C5ED5	'fractionals of cube roots of primes 2..311
    		long	$D807AA98, $12835B01, $243185BE, $550C7DC3, $72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174
    		long	$E49B69C1, $EFBE4786, $0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DA
    		long	$983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147, $06CA6351, $14292967
    		long	$27B70A85, $2E1B2138, $4D2C6DFC, $53380D13, $650A7354, $766A0ABB, $81C2C92E, $92722C85
    		long	$A2BFE8A1, $A81A664B, $C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070
    		long	$19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A, $5B9CCA4F, $682E6FF3
    		long	$748F82EE, $78A5636F, $84C87814, $8CC70208, $90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2
    '
    '
    ' Undefined data
    '
    hmac		res	1
    bytes		res	1
    count		res	1
    length		res	1
    
    opad_key	res	16
    
    hash		res	8
    hashx		res	8
    
    w		res	64
    
    a		res	1
    b		res	1
    c		res	1
    d		res	1
    e		res	1
    f		res	1
    g		res	1
    h		res	1
    
    x		res	1
    y		res	1
    

    And here's the monitor, shrunk and improved:
    '********************************************************
    '*							*
    '*		Propeller II ROM Monitor		*
    '*							*
    '*		Version 0.1				*
    '*							*
    '*		11/01/2012				*
    '*							*
    '********************************************************
    
    '
    ' Usage:	cognew($738, tx_pin << 9 + rx_pin)	'start monitor in new cog
    '
    
    CON
    
      branch1_	= 0
      branch2_	= branch1_	+ 31
      branch3_	= branch2_	+ 35
      hello_	= branch3_	+ 15
      error_	= hello_	+ 33
      hitspace_	= error_	+ 11
      spquote_	= hitspace_	+ 10
      quotecr_	= spquote_	+ 4
      sub0_		= quotecr_	+ 3		'must be => $80
      sub1_		= sub0_		+ 4
      sub2_		= sub1_		+ 12
      sub3_		= sub2_		+ 12
      help_		= sub3_		+ 4
    
    
    DAT
    
    '********
    '* Data *
    '********
    
    branch1		byte	cmd_new,	0
    		byte	cmd_byte,	"Y"
    		byte	cmd_word,	"W"
    		byte	cmd_long,	"N"
    		byte	cmd_viewp,	"."
    		byte	cmd_search,	"/"
    		byte	cmd_enter,	":"
    		byte	cmd_map,	"M"
    		byte	cmd_clrp,	"L"
    		byte	cmd_setp,	"H"
    		byte	cmd_notp,	"T"
    		byte	cmd_offp,	"Z"
    		byte	cmd_getp,	"R"
    		byte	cmd_quit,	"Q"
    		byte	cmd_help,	"?"
    		byte	0			'31 bytes
    
    branch2		byte	cmd_view2,	0
    		byte	cmd_view2,	" "
    		byte	cmd_range,	"."
    		byte	cmd_search2,	"/"
    		byte	cmd_enter2,	":"
    		byte	cmd_watch,	"@"
    		byte	cmd_clkset,	"*"
    		byte	cmd_coginit,	"+"
    		byte	cmd_cogstop,	"-"
    		byte	cmd_clrp,	"L"
    		byte	cmd_setp,	"H"
    		byte	cmd_notp,	"T"
    		byte	cmd_offp,	"Z"
    		byte	cmd_getp,	"R"
    		byte	cmd_watchp,	"#"
    		byte	cmd_cfgp,	"|"
    		byte	cmd_setdacs,	"\"
    		byte	0			'35 bytes
    
    branch3		byte	cmd_view3,	0
    		byte	cmd_view3,	" "
    		byte	cmd_search3,	"/"
    		byte	cmd_enter3,	":"
    		byte	cmd_move,	">"
    		byte	cmd_move,	"<"
    		byte	cmd_checksum,	"^"
    		byte	0			'15 bytes
    
    hello		byte	13,13,"=== Propeller II Monitor ===",13,13
    		byte	0			'33 bytes
    
    error		byte	"? - Help"
    		byte	13,7,0			'11 bytes
    
    hitspace	byte	"Hit SPACE",0		'10 bytes
    
    spquote		byte	"  '",0			'4 bytes
    
    quotecr		byte	"'",13,0		'3 bytes
    
    sub0		byte	" -",13,$80		'4 bytes
    sub1		byte	"{adr{.adr}}",$80	'12 bytes
    sub2		byte	"{dat{ dat}}",$80	'12 bytes
    sub3		byte	"adr",$80		'4 bytes
    
    help		byte	13,		"~HUB",sub0_
    		byte	sub1_,				"`View",13
    		byte	sub1_,"/",sub2_,		"`Search",13
    		byte	sub1_,":",sub2_,		"`Enter",13
    		byte	sub3_,".",sub3_,"[</>]",sub3_,	"`Move",13
    		byte	sub3_,".",sub3_,"^",		"`Checksum",13
    		byte	sub3_,"@",			"`Watch",13
    		byte	"[Y/W/N]",			"`Byte/word/long",13
    		byte			"~COGS",sub0_
    		byte	"cog+",sub3_,"{+",sub3_,"}",	"`Start",13
    		byte	"cog-",				"`Stop",13
    		byte	"M",				"`Map",13
    		byte			"~PINS",sub0_
    		byte	"{pin}[H/L/T/Z/R]",		"`High/low/toggle/off/read",13
    		byte	"pin#",				"`Watch",13
    		byte	"pin|cfg",			"`Configure",13
    		byte	"dat\",				"`Set DACs",13
    		byte			"~MISC",sub0_
    		byte	"dat*",				"`Set clock",13
    		byte	"'",				"`Repeat",13
    		byte	"Q",				"`Quit",13	'(0 long follows)
    
    longs		long
    
    
    '*********
    '* Entry *
    '*********
    
    		org
    
    		long	0			'start of data string = 0/nop
    
    		reps	#$1F6-reserves,#1	'clear reserves
    		setinda	reserves
    		mov	inda++,#0
    
    		getptra	rx_pin			'get rx/tx pins
    		getptra	tx_pin
    		shr	tx_pin,#9
    		setp	tx_pin
    
    		jmptask	#baud_task,#%0010	'enable baud detector task
    		settask	#%%0101
    
    		tjz	period,#$		'wait for <space> to set period
    
    		jmptask	#rx_task,#%0100		'enable serial receiver task
    		settask	#%%0121
    
    		mov	wsize,#1		'init word size to byte
    		call	#set_size
    
    		pusha	#0			'init input line to <enter>
    
    		setptra	#hello_			'print hello message
    
    dmax						'end of data string
    
    
    '*************
    '* Main Task *
    '*************
    
    message		call	#tx_string		'print hello/error message
    
    cmd_new		call	#rx_line		'get input line
    
    		call	#parse			'parse first term
    	if_z	tjz	x,#cmd_viewl		'if no hex and eol, view data
    		jmp	#cmd_go			'else, process command
    
    
    cmd_next_crlf	call	#tx_crlf		'print cr/lf
    cmd_next	addspa	#1			'skip chr
    
    cmd_loop	call	#parse			'parse next term
    cmd_go	if_nz	jmp	#cmd_hex		'if hex, branch
    		movd	pinx,#z			'pin update redirected to z
    		setptra	#branch1_		'not hex, vector by chr
    		call	#vector			'if returns, no match
    
    cmd_error	setptra	#error_			'print error message
    		jmp	#message
    
    
    cmd_hex		mov	v1,value		'hex, save v1
    		movd	pinx,#pin		'pin update okay
    		setptra	#branch2_		'vector by chr
    		call	#vector			'if returns, no match
    		jmp	#cmd_view2		'view data
    
    
    cmd_range	call	#parse_next		'hex., get hex
    	if_z	jmp	#cmd_viewp2		'if no hex, view data
    
    		mov	v2,value		'hex.hex, save v2
    		setptra	#branch3_		'vector by chr
    		call	#vector			'if returns, no match
    		jmp	#cmd_view3		'view data
    '
    '
    ' Byte/word/long data
    '
    cmd_byte	mov	wsize,#1	wz	'set byte mode, z=0
    cmd_word if_z	mov	wsize,#2	wz	'set word mode, z=0
    cmd_long if_z	mov	wsize,#4		'set long mode
    
    		call	#set_size
    
    		jmp	#cmd_next		'next command
    '
    '
    ' View data
    '
    cmd_viewl	mov	v2,#$F			'<enter> (eol), show line of data
    		call	#tx_range1
    		jmp	#cmd_new
    
    cmd_viewp	mov	v2,#$FF			'. (more), show page of data
    		call	#tx_range1
    		jmp	#cmd_next
    
    cmd_viewp2	mov	v2,#$FF			'addr. (more), show page of data
    		call	#tx_range2
    		jmp	#cmd_loop
    
    cmd_view2	mov	v2,v1			'addr, show unit of data
    cmd_view3	call	#tx_range		'addr.addr, show range of data
    		jmp	#cmd_loop
    '
    '
    ' Search
    '
    cmd_search	mov	v1,view			'/, search from view to end
    cmd_search2	mov	v2,amask		'addr/, search from address to end
    cmd_search3	call	#check_range		'addr.addr/, search range
    
    		call	#parse_data		'parse data string
    
    :start		setptra	v1			'start search, point to search address
    		setinda	0			'point to search data
    		mov	x,#0			'reset word match counter
    
    :word		call	#rdxxxx			'get memory word
    		cmp	value,inda++	wz	'compare against search data word
    	if_z	jmp	#:match			'if word match, check if string match
    
    		add	v1,wsize		'word mismatch, advance search address
    		cmp	v1,v2		wz,wc	'at end of range?
    	if_be	jmp	#:start			'if not, start next search
    
    		mov	view,v1			'else, update view
    		and	view,amask
    		jmp	#cmd_loop		'next command
    
    :match		incmod	x,dsize		wc	'word match, increment match counter
    	if_nc	jmp	#:word			'if more words to match, compare next word
    
    		mov	v2,dsize		'got string match
    		shl	v2,shift		'v1 = start of found data
    		add	v2,v1			'v2 = end of found data
    		jmp	#cmd_view3		'show found data
    '
    '
    ' Enter data
    '
    cmd_enter3	call	#check_range		'addr.addr:, check range, z=words to fill
    		mov	y,#1			'set fill flag
    
    cmd_enter2	mov	enter,v1		'addr:, set enter address
    		and	enter,amask		'trim enter address (in case cmd_enter2)
    
    cmd_enter	call	#parse_data		':, parse data
    
    		tjnz	y,#:go			'if not fill, set z to data size
    		mov	z,dsize
    		add	z,#1
    
    :go		setptrb	enter			'get pointer
    
    :loop		mov	value,inda++		'get word from string data
    		call	#wrxxxx			'store value in memory
    		djnz	z,#:loop		'loop until enter done
    
    		getptrb	enter			'update pointer
    
    		jmp	#cmd_loop		'next command
    '
    '
    ' Move data
    '
    cmd_move	mov	y,x			'save ">"/"<"
    
    		call	#check_range		'check 1st address range, get number of words
    
    		call	#parse_hex		'get 2nd address
    
    		max	value,amask		'v1=1st, value=2nd, z=words, y=">"/"<"
    		and	value,amask
    
    		cmp	y,#"<"		wz	'if "<", swap v1 and value
    	if_z	mov	x,v1
    	if_z	mov	v1,value
    	if_z	mov	value,x			'v1=from, value=to, z=words
    
    		cmp	v1,value	wc	'if from < to, downward move
    	if_c	mov	x,z
    	if_c	shl	x,shift
    	if_c	add	v1,x
    	if_c	add	value,x
    	if_c	xor	rdxxxx,#%001_111110	'modify 'rdxxxx value,--ptra'
    	if_c	xor	wrxxxx,#%001_111110	'modify 'wrxxxx value,--ptrb'
    
    		setptra	v1			'set pointers
    		setptrb	value
    
    :loop		call	#rdxxxx			'move data
    		call	#wrxxxx
    		djnz	z,#:loop
    
    	if_c	xor	rdxxxx,#%001_111110	'restore 'rdxxxx value,ptra++'
    	if_c	xor	wrxxxx,#%001_111110	'restore 'wrxxxx value,ptrb++'
    
    		jmp	#cmd_loop		'next command
    '
    '
    ' Checksum
    '
    cmd_checksum	call	#check_range		'check range
    
    		setptra	v1			'sum bytes
    :loop		call	#rdxxxx
    		add	y,value
    		djnz	z,#:loop
    
    		mov	value,y			'print sum
    		mov	hsize,#8
    		call	#tx_hex
    
    		jmp	#cmd_next_crlf		'next command
    '
    '
    ' Watch
    '
    cmd_watchp	movs	rdxxxj,#rdxxxx_ret  wz	'set pin mode, z=0
    		mov	hsize,#1
    
    cmd_watch if_z	movs	rdxxxj,#rdxxxm		'set mem mode
    	  if_z	mov	hsize,wsize		'set hex size by word size
    	  if_z	shl	hsize,#1
    
    		call	#rdxxxp			'get initial value
    
    :loop		mov	z,value			'preserve value
    
    		call	#tx_hex			'print value
    		call	#tx_space		'print space
    
    :wait		call	#rx_check		'if key hit, exit
    	if_nz	jmp	#cmd_next_crlf
    
    		call	#rdxxxp			'get current value
    
    		cmp	value,z		wz	'if same, check again
    	if_z	jmp	#:wait
    
    		jmp	#:loop			'new value, loop
    '
    '
    ' Clkset
    '
    cmd_clkset	setptra	#hitspace_		'print hit-space message
    		call	#tx_string
    
    		clkset	v1			'set clk
    
    :wait		call	#rx			'wait for space
    		cmp	x,#" "		wz
    	if_nz	jmp	#:wait
    
    		jmp	#cmd_next_crlf		'next command
    '
    '
    ' Coginit
    '
    cmd_coginit	setcog	v1			'set cog
    
    		call	#parse_hex		'get program address
    
    		mov	y,value			'save program address
    		mov	value,#0		'clear pointer address
    
    		cmp	x,#"+"		wz	'if '+', get pointer address
    	if_z	call	#parse_hex
    
    		coginit	y,value			'do 'coginit program,pointer'
    
    		jmp	#cmd_loop		'next command
    '
    '
    ' Cogstop
    ' Quit
    '
    cmd_quit	cogid	v1			'quit
    
    cmd_cogstop	cogstop	v1			'stop cog
    
    		jmp	#cmd_next		'next command
    '
    '
    ' Map
    '
    cmd_map		mov	y,#7			'ready for 7..0
    
    cmd_map_loop	call	#tx_space		'print space
    		mov	x,y			'get cog status
    		cogid	x		wc
    cmd_map_c	cmp	x,y		wz
    	if_nc	mov	x,#"0"			'get 0/1/M chr
    	if_c	mov	x,#"1"
    	if_z	mov	x,#"M"
    		call	#tx			'print chr
    		sub	y,#1		wc
    	if_nc	jmp	#cmd_map_loop		'loop until done
    
    		jmp	#cmd_next_crlf		'next command
    '
    '
    ' Pin writes clrp/setp/notp/offp
    ' Pin read
    '
    cmd_clrp	movs	pinop,#$DA	wz	'clrp, z=0
    cmd_setp if_z	movs	pinop,#$DB	wz	'setp, z=0
    cmd_notp if_z	movs	pinop,#$D9	wz	'notp, z=0
    cmd_offp if_z	movs	pinop,#$D8	wz	'offp, z=0
    cmd_getp if_z	movs	pinop,#$D6		'getp, z=1
    
    pinx		mov	pin,v1			'if hex, get pin (d = pin/z)
    
    pinop		getp	pin		wc	'becomes clrp/setp/notp/offp/getp
    
    	if_z	jmp	#cmd_map_c		'if getp, show pin value
    
    		jmp	#cmd_next		'next command
    '
    '
    ' Pin configuration
    '
    cmd_cfgp	call	#parse_hex		'get configuration
    
    		setport	v1			'set pin port
    		decod5	v1			'get pin mask
    		cfgpins	v1,value		'configure pin
    
    		jmp	#cmd_loop		'next command
    '
    '
    ' Setdacs
    '
    cmd_setdacs	setdacs	v1			'set all four dacs with 8-bit values
    
    		jmp	#cmd_next		'next command
    '
    '
    ' Help
    '
    cmd_help	setptra	#help_			'print help message
    		call	#tx_string
    
    		jmp	#cmd_next_crlf		'next command
    
    
    '*************************
    '* Main Task Subroutines *
    '*************************
    '
    '
    ' Vector branch
    '
    vector		addptra	base			'add data base pointer
    
    vector_loop	rdbyte	z,ptra++		'get jump address
    vector_ret	tjz	z,#0			'if 0, no match found, return
    
    		rdbyte	y,ptra++		'get target
    		xor	y,x		wz	'compare to x
    	if_nz	jmp	#vector_loop		'if no match, loop
    
    		jmp	z			'match found, jump, y=0, z=1
    '
    '
    ' Check address range (v1..v2)
    '
    check_range	max	v1,amask		'trim v1
    		and	v1,amask
    
    		max	v2,amask		'trim v2
    		and	v2,amask
    
    		cmp	v2,v1		wc	'make sure v2 => v1
    	if_c	jmp	#cmd_error
    
    		mov	z,v2			'get number of words
    		sub	z,v1
    		shr	z,shift
    		add	z,#1
    
    check_range_ret	ret
    '
    '
    ' Set rdxxxx/wrxxxx and others by word size
    '
    set_size	test	wsize,#%010	wc	'set rdxxxx/wrxxxx by word size
    		setbc	rdxxxx,#26
    		setbc	wrxxxx,#26
    
    		test	wsize,#%100	wc
    		setbc	rdxxxx,#27
    		setbc	wrxxxx,#27
    
    		mov	shift,wsize		'set shift by word size
    		shr	shift,#1
    
    		mov	amask,wsize		'set amask by word size
    		sub	amask,#1
    		xor	amask,h0001FFFF
    
    		and	view,amask		'trim view
    		and	enter,amask		'trim enter
    
    set_size_ret	ret
    
    
    rdxxxp		getp	v1		wc	'read pin as "0" or "1"
    	if_nc	mov	value,#0
    	if_c	mov	value,#1
    rdxxxj		jmp	#rdxxxx_ret		'd = rdxxxx_ret/rdxxxm
    
    rdxxxm		setptra	v1			'read mem
    
    rdxxxx		rdbyte	value,ptra++		'rdbyte/rdword/rdlong
    rdxxxp_ret
    rdxxxx_ret	ret
    
    
    wrxxxx		wrbyte	value,ptrb++		'wrbyte/wrword/wrlong
    
    wrxxxx_ret	ret
    '
    '
    ' Input line
    '
    rx_line		setspa	#0			'point to start of line
    
    		mov	x,#">"			'show prompt
    		call	#tx
    
    		call	#rx			'get first chr
    		cmp	x,#"'"		wz	'check for repeat
    	if_nz	jmp	#:first			'if not repeat, first chr
    
    :show		popar	x		wz	'repeat, show line
    	if_nz	call	#tx
    	if_nz	jmp	#:show
    		jmp	#:done
    
    
    :loop		call	#rx			'get next chr
    
    :first		cmp	x,#13		wz	'cr?
    	if_z	jmp	#:cr
    
    		cmp	x,#8		wz	'backspace?
    	if_nz	cmp	x,#127		wz
    	if_z	jmp	#:bs
    
    		cmp	x,#" "		wc	'visible chr?
    	if_nc	cmpr	x,#"~"		wc
    	if_c	jmp	#:loop
    
    		pusha	x			'visible chr, append to line
    		chkspa			wc	'overflow?
    	if_c	subspa	#1			'if overflow, back up
    	if_nc	call	#tx			'if not overflow, print chr
    		jmp	#:loop
    
    :bs		chkspa			wz	'backspace, line empty?
    	if_nz	pushar	x			'if not empty,
    	if_nz	call	#tx			'..print backspace
    	if_nz	call	#tx_space		'..print space
    	if_nz	popar	x			'..print backspace
    	if_nz	call	#tx
    	if_nz	subspa	#1			'..back up
    		jmp	#:loop
    
    :cr		pusha	#0			'cr, end line with 0
    
    :done		setspa	#0			'point to start of line
    
    tx_crlf		mov	x,crlf			'print cr/lf
    		call	#tx
    tx_crlf_ret
    rx_line_ret	ret
    '
    '
    ' Parse hex/text data
    '
    parse_data	mov	w,#0			'reset data count
    		setinda	0			'point to string data
    
    :hex		call	#parse_next		'hex loop, check hex
    	if_nz	call	#enter_data		'if hex, enter value
    		cmp	x,#" "		wz	'check for space (more hex)
    	if_z	jmp	#:hex			'if more hex, loop
    
    		cmp	x,#"'"		wz	'not hex, "'"?
    	if_nz	jmp	#:done			'if not "'", done
    
    :text		addspa	#2			'text loop
    		popa	x			'get and point to next chr
    		cmp	x,#"'"		wz	'check for "'"
    	if_z	jmp	#:hex			'if "'", back to hex
    		tjz	x,#:done		'if eol, done
    		mov	value,x			'text chr
    		call	#enter_data		'enter chr
    		jmp	#:text			'loop
    
    :done		sub	w,#1		wc	'get data count
    	if_nc	mov	dsize,w			'if 0, reuse old data
    
    		movd	:fix,dsize		'form circular buffer
    :fix		fixinda	0,0			'(no instruction-modification problem with 1:4 threading)
    	
    parse_data_ret	ret
    
    
    enter_data	incmod	w,#dmax		wc	'check if data limit exceeded
    	if_c	jmp	#cmd_error		'if data limit exceeded, error
    		mov	inda++,value		'store value in data
    
    enter_data_ret	ret
    '
    '
    ' Parse hex
    '
    parse_hex	call	#parse_next		'try to parse hex
    	if_z	jmp	#cmd_error		'if no hex, error
    
    parse_hex_ret	ret
    '
    '
    ' Parse line (@spa), z=0 if hex (value)
    '
    parse_next	addspa	#1			'advance to next chr
    
    parse		mov	value,#0	wz	'z=1
    
    		call	#skip_spaces	wz	'skip any spaces (preserve z)
    
    :loop		popar	x			'get chr
    		call	#check_hex		'check hex
    	if_c	shl	value,#4		'if hex, append nibble and loop
    	if_c	or	value,x
    	if_c	jmp	#:loop		wz	'z=0
    
    		subspa	#1			'repoint to non-hex chr
    
    		call	#skip_spaces	wz	'skip any post-hex spaces (preserve z)
    
    		call	#check_hex		'check hex
    	if_c	popa	x			'if hex, back up to space chr
    
    		cmpr	x,#"a"-1	wc	'make non-hex chr uppercase
    	if_c	cmp	x,#"z"+1	wc
    	if_c	sub	x,#"a"-"A"
    parse_next_ret
    parse_ret	ret
    '
    '
    ' Skip spaces (@spa)
    '
    skip_spaces	popar	x			'skip space chr(s)
    		cmp	x,#" "		wz
    	if_z	jmp	#skip_spaces
    
    		subspa	#1			'back up to non-space chr
    
    skip_spaces_ret	ret			wz	'restore z
    '
    '
    ' Check hex (x), c=1 if hex (x)
    '
    check_hex	cmpr	x,#"0"-1	wc	'"0".."9" -> $0..$9
    	if_c	cmp	x,#"9"+1	wc
    	if_c	add	x,#"A"-"9"-1
    
    	if_nc	cmpr	x,#"A"-1	wc	'"A".."F" -> $A..$F
    	if_c	cmp	x,#"F"+1	wc
    	if_c	add	x,#"a"-"A"
    
    	if_nc	cmpr	x,#"a"-1	wc	'"a".."f" -> $A..$F
    	if_c	cmp	x,#"f"+1	wc
    	if_c	sub	x,#"a"-10
    
    check_hex_ret	ret
    '
    '
    ' Print range (v1..v2)
    '
    tx_range1	mov	v1,view			'view..view + v2
    tx_range2	and	v2,amask		'v1..v1 + v2
    		add	v2,v1
    
    tx_range	call	#check_range		'check range
    
    		mov	view,v1			'set address
    
    :line		mov	value,view		'print 5-digit address
    		mov	hsize,#5
    		call	#tx_hex
    
    		call	#tx_dspace		'print "- "
    
    		mov	x,wsize			'get number of words on line
    		rev	x,#32-5
    		mov	v1,z
    		max	v1,x
    
    		mov	v2,v1			'get number of ascii bytes on line
    		shl	v2,shift
    
    		sub	z,v1			'update number of words left
    
    		setptra	view			'print hex words
    :hex		call	#rdxxxx
    		mov	hsize,wsize
    		shl	hsize,#1
    		call	#tx_hex
    		call	#tx_space
    		djnz	v1,#:hex
    
    		setptra	#spquote_		'print "  '"
    		call	#tx_string
    
    		setptra	view			'print ascii bytes
    :ascii		rdbyte	x,ptra++
    		cmp	x,#" "		wc	'visible chr?
    	if_nc	cmpr	x,#"~"		wc
    	if_c	mov	x,#"."			'substitute "." for non-visible chrs
    		call	#tx
    		djnz	v2,#:ascii
    
    		getptra	view			'update address
    
    		setptra	#quotecr_		'print "'" + cr
    		call	#tx_string
    
    		call	#rx_check		'check key hit
    	if_z	tjnz	z,#:line		'if no key hit and more words left, print another line
    tx_range1_ret
    tx_range2_ret
    tx_range_ret	ret
    '
    '
    ' Print string (@ptra)
    '
    tx_string	addptra	base			'add data base pointer
    
    tx_string_loop	rdbyte	x,ptra++		'get chr
    
    tx_string_ret	tjz	x,#0			'if 0, done
    
    		test	x,#$80		wz	'substring?
    	if_nz	notb	tx_string_loop,#8	'toggle ptra/ptrb
    	if_nz	setptrb	x			'ptrb points to substring
    	if_nz	addptrb	base
    	if_nz	jmp	#tx_string_loop		'start substring or resume string
    
    		cmp	x,#"`"		wz	'long tab?
    	if_z	subr	y,#32-16
    	if_nz	cmp	x,#"~"		wz	'short tab?
    	if_z	add	y,#16
    :tab	if_z	call	#tx_space
    	if_z	djnz	y,#:tab
    	if_z	call	#tx_dspace
    	if_z	jmp	#tx_string_loop
    
    		cmp	x,#13		wz	'cr?
    	if_z	call	#tx_crlf
    	if_z	mov	y,#0
    
    	if_nz	call	#tx			'other?
    	if_nz	add	y,#1
    		jmp	#tx_string_loop
    '
    '
    ' Print hex (value)
    '
    tx_hex		mov	y,hsize			'pre-rotate to get 1st nibble in top
    		shl	y,#2
    		ror	value,y
    
    		mov	y,hsize			'print nibbles
    :loop		rol	value,#4
    		mov	x,value
    		call	#tx_nib
    		djnz	y,#:loop
    
    tx_hex_ret	ret
    '
    '
    ' Print "- "
    '
    tx_dspace	mov	x,dspace
    		jmp	#tx
    '
    '
    ' Print space
    '
    tx_space	mov	x,#" "
    		jmp	#tx
    '
    '
    ' Print nibble (x)
    '
    tx_nib		and	x,#$F			'isolate nibble
    
    		cmp	x,#$A		wc	'alpha or numeric?
    	if_c	add	x,#"0"			'numeric
    	if_nc	add	x,#"A"-$A		'alpha
    '
    '
    ' Transmit chr (x)
    '
    tx		shl	x,#1			'insert start bit
    		setb	x,#9			'set stop bit
    
    		getcnt	w			'get initial time
    
    :loop		add	w,period		'add bit period to time
    		passcnt	w			'loop until bit period elapsed
    		shr	x,#1		wc	'get next bit into c
    		setpc	tx_pin			'write c to tx pin
    		tjnz	x,#:loop		'loop until bits done
    tx_dspace_ret
    tx_space_ret
    tx_nib_ret
    tx_ret		ret
    '
    '
    ' Receive chr (x)
    '
    rx		call	#rx_check		'wait for rx chr
    	if_z	jmp	#rx
    
    rx_ret		ret
    '
    '
    ' Check receiver, z=0 if chr (x)
    '
    rx_check	or	rx_tail,#$80		'if start or rollover, reset tail
    
    		getspb	rx_temp		wz	'if head uninitialized, z=1
    	if_nz	cmp	rx_temp,rx_tail	wz	'if head-tail mismatch, byte ready, z=0
    
    	if_nz	getspa	rx_temp			'preserve spa
    	if_nz	setspa	rx_tail			'get tail
    	if_nz	popar	x			'get byte at tail
    	if_nz	getspa	rx_tail			'update tail
    	if_nz	setspa	rx_temp			'restore spa
    
    rx_check_ret	ret
    
    
    '************************
    '* Serial Receiver Task *
    '************************
    
    rx_task		chkspb			wz	'if start or rollover, reset head
    	if_z	setspb	#$80
    
    		mov	rx_bits,#9		'ready for 8 data bits + 1 stop bit
    
    		neg	rx_time,period		'get -0.5 period
    		sar	rx_time,#1
    
    		jp	rx_pin,#$		'wait for start bit
    
    		subcnt	rx_time			'get time + 0.5 period for initial 1.5 period delay
    
    :bit		rcr	rx_data,#1		'rotate c into byte
    		add	rx_time,period		'add 1 period
    		passcnt	rx_time			'wait for center of next bit
    		getp	rx_pin		wc	'read rx pin into c
    		djnz	rx_bits,#:bit		'loop until 8 data bits + 1 stop bit received
    
    		shr	rx_data,#32-8		'align byte
    		pushb	rx_data			'store byte at head, inc head
    
    		jmp	#rx_task		'wait for next byte
    
    
    '**********************
    '* Baud Detector Task *
    '**********************
    
    baud_task	movd	ctr,rx_pin		'set ctra to time rx pin states
    
    :loop		notb	ctr,#5		wc	'if 1,0 sample set, c=0
    		setctra	ctr			'($20 -> 10000001001 -> 1, 6x 0, 1x 1, 2x 0, 1)
    
    	if_nc	mov	limh,buff0		'if 1,0 sample set,
    	if_nc	shr	limh,#4			'..make window from 1st 0 (6x if $20)
    	if_nc	neg	liml,limh
    	if_nc	add	limh,buff0
    	if_nc	add	liml,buff0
    
    	if_nc	mov	comp,buff1		'if 1,0 sample set,
    	if_nc	mul	comp,#6			'..normalize 2nd 1 (1x if $20) to 6x
    	if_nc	cmpr	comp,limh	wc	'..check if within window
    	if_nc	cmp	comp,liml	wc
    
    	if_nc	mov	comp,buff2		'if 1,0 sample set,
    	if_nc	mul	comp,#3			'..normalize 2nd 0 (2x if $20) to 6x
    	if_nc	cmpr	comp,limh	wc	'..check if within window
    	if_nc	cmp	comp,liml	wc
    
    	if_nc	add	buff0,buff2		'if $20,
    	if_nc	shr	buff0,#3		'..compute period from 6x 0 and 2x 0
    	if_nc	mov	period,buff0		'..update period
    
    		mov	buff0,buff1		'scroll sample buffer
    		mov	buff1,buff2
    
    :wait		getcosa	buff2			'wait for next sample
    		tjnz	buff2,#:loop
    		jmp	#:wait
    
    
    '*************
    '* Constants *
    '*************
    
    base		long	$55C			'start of byte data
    h0001FFFF	long	$0001FFFF		'memory limit
    crlf		long	1<<18 + $0A<<10 + $0D	'cr/lf
    dspace		long	1<<18 + " "<<10 + "-"	'dash/space
    ctr		long	%100_01001		'ctr configuration for timing low on rx pin
    
    
    '*************
    '* Variables *
    '*************
    
    reserves
    
    w		res	1			'main task
    x		res	1
    y		res	1
    z		res	1
    v1		res	1
    v2		res	1
    value		res	1
    view		res	1
    enter		res	1
    pin		res	1
    dsize		res	1
    hsize		res	1
    wsize		res	1
    shift		res	1
    amask		res	1
    rx_pin		res	1
    tx_pin		res	1
    
    rx_tail		res	1			'serial receiver task
    rx_temp		res	1
    rx_time		res	1
    rx_data		res	1
    rx_bits		res	1
    
    buff0		res	1			'baud detector task
    buff1		res	1
    buff2		res	1
    limh		res	1
    liml		res	1
    comp		res	1
    period		res	1
    
  • SapiehaSapieha Posts: 2,964
    edited 2012-11-10 00:07
    Hi Chip.

    One thing I'm are curious Why You not implemented Intel HEX loader in monitor with checksum cheking.
    That have ben nice to use as Loader from any Terminal program.

    Ps. In 8080 assembly it is only some lines of code.


    cgracey wrote: »
    About the monitor...

    It is more universally accessible than the binary/HMAC-signed downloader because it sends and receives only standard ASCII characters $20..$7E (space.."~").

    Some programming languages, serial interfaces, and OS's have issues with sending and receiving full binary ($00..$FF). For this reason, you might have to jump through some hoops to get the more-efficient binary downloader working on a given host system. The monitor, on the other hand, can talk to anything that speaks serial, without concern over non-ASCII characters. It is so simple that it can't NOT work on any host machine that has a serial port. Plus, it doesn't force an ordered protocol, but is conversational in operation. I've been using the Parallax Serial Terminal program to talk to it as well as PUTTY, which is free on the 'net and very tidy.

    My thinking might be a little anachronistic, but I've seen many host-level systems which are big on brains and storage, but for which the serial interfaces were fleeting afterthoughts, and full binary can trigger unwanted events. The monitor will play politely and offer no offense to any host.

    The reason I put a help menu in the monitor was so that you could quickly get command syntax without having to refer to any documents. You might launch the monitor from within an app you want to debug and you'll need to search memory for a string of data to get your bearings. The help menu will be handy then.

    Here is the ROM now:
    === Propeller II Monitor ===
    
    >0.e7f
    00000- 50 72 6F 70 32 2E 30 20 00 20 7C 0C 03 D0 7C 0C   'Prop2.0 . |...|.'
    00010- 45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D   'E.........|...|.'
    00020- 01 C2 FC 80 1F C2 7C 62 01 E0 FC 30 66 0C A8 80   '......|b...0f...'
    00030- 01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0   '..|.*...[...|...'
    00040- 5B C0 FC 1C 7C FA BC 80 01 FA FC 28 FA F0 FC A0   '[...|......(....'
    00050- 5B C0 FC 1C 01 C8 7C 62 2A 00 64 1C B2 C8 7C 61   '[.....|b*.d...|a'
    00060- 01 C8 FC 34 10 F0 FC F6 02 F1 FC A0 08 F0 7C 86   '...4..........|.'
    00070- 52 C8 E8 A0 01 C8 7C 62 25 52 FC 1C DA B4 FC 0C   'R.....|b%R......'
    00080- 25 52 FC 1C DF B4 FC 0C 25 52 FC 1C DB B4 FC 0C   '%R......%R......'
    00090- 25 52 FC 1C B2 C8 7C 61 01 C8 FC 34 17 F0 FC F6   '%R....|a...4....'
    000A0- 35 00 7C 1C 0D F6 FC 0C 62 F6 BC 80 63 C6 BC FF   '5.|.....b...c...'
    000B0- 37 4F FC 0C 00 00 4C 1C 04 F0 FC A0 DB B2 FC 0C   '7O....L.........'
    000C0- DA B0 FC 0C 44 3E C0 0D DA B2 FC 0C 01 F0 7C E1   '....D>........|.'
    000D0- 01 CA CC 27 DC AE FC 0C DB B0 FC 0C DA B0 FC 0C   '...'............'
    000E0- 2B F0 FC F6 B2 D8 7C 0C 66 F0 BC A0 20 F2 FC A0   '+.....|.f... ...'
    000F0- 5B C0 E8 1C D6 AC D4 0D DB B0 D4 0C DA B0 D4 0C   '[...............'
    00100- 01 F4 FC 34 38 F2 FC F6 C1 F4 7C 08 37 F0 FC F6   '...48.....|.7...'
    00110- 40 0E C0 0D 70 00 04 E0 C1 EC 53 08 6B F0 3C 08   '@...p.....S.k.<.'
    00120- E0 02 FC 0C 6B D4 3C 0C 67 00 04 E0 03 F0 FC A0   '....k.<.g.......'
    00130- 6B EC 13 08 6B F4 BC 0A 49 F4 7C FA 48 F0 FC F6   'k...k...I.|.H...'
    00140- 03 1C 7C 0C 42 0E C0 0D E0 00 FC 0C 30 F2 FC 08   '..|.B.......0...'
    00150- C1 F4 FC 08 7A F2 28 86 6D D8 28 0C 41 FE FF 0F   '....z.(.m.(.A...'
    00160- 01 DC 7C 0C C1 F0 7C 08 C1 F0 7C 08 71 E0 BC 6A   '..|...|...|.q..j'
    00170- 73 E4 A8 6A 08 DC D4 A0 6F DC 3C 0C 25 52 FC 1C   's..j....o.<.%R..'
    00180- 0D F8 FC 0C 25 52 FC 1C 0C F8 FC 0C 7D F8 3C 85   '....%R......}.<.'
    00190- 00 00 7C 1C 00 02 00 00 C0 C6 2D 00 00 00 00 08   '..|.......-.....'
    001A0- 50 00 00 00 00 00 00 03 00 02 00 00 80 16 1E 40   'P..............@'
    001B0- 80 0E BE 8F A0 16 00 C0 D0 01 00 00 C0 16 00 00   '................'
    001C0- 80 0E 00 00 80 16 00 00 10 07 00 00 5B B4 00 00   '............[...'
    001D0- CA E0 FD 0C 46 96 FC 1C 00 9E FE 08 02 9E 7E F8   '....F.........~.'
    001E0- B3 9E 7E 0C 4F CB BD A0 02 CA FD 2C 13 CA FD 28   '..~.O......,...('
    001F0- 01 CA FD 80 1E 9E FE 28 08 00 7C 0C 10 9E FE F4   '.......(..|.....'
    00200- 1D 9E FE F4 21 9E FE F4 00 30 7D 08 02 00 7C 1C   '....!....0}...|.'
    00210- 35 96 FC 1C 00 9E FE A0 E4 CA 3D E1 C1 9F F2 01   '5.........=.....'
    00220- 36 9E FE 6C 4C A6 FC 1C 11 00 54 1C 41 1E C0 0D   '6..lL.....T.A...'
    00230- 07 CF 15 E0 F6 EF 87 A0 9A EE 93 6C 01 C6 FD A0   '...........l....'
    00240- 0E 00 7C 1C C1 9F FE 01 4C A6 FC 1C 1D CA FD F6   '..|.....L.......'
    00250- 0E 00 7C 1C 2C C6 7D F8 35 96 FC 1C 40 1E C0 0D   '..|.,.}.5...@...'
    00260- E7 0E 16 E0 F6 EF 97 A0 54 2E FD 1C 40 0E C0 0D   '........T...@...'
    00270- FF 0E 16 E0 F6 EF 97 A0 0F 99 FC 54 60 C8 FD A0   '...........T`...'
    00280- 35 96 FC 1C FF 00 04 E0 08 CA FD A0 41 06 C0 0D   '5...........A...'
    00290- F6 9F 86 A0 08 9E FE 24 C1 9F 7E 00 2F CA FD F6   '.......$..~./...'
    002A0- 0E 00 7C 1C E4 CC BD A0 03 CC FD 2C 80 9E FE A0   '..|........,....'
    002B0- 4C A6 FC 1C E4 9E BE A0 3F 9E FE 60 38 9E 7E 86   'L.......?..`8.~.'
    002C0- 00 9E FE A0 38 00 54 1C 04 C8 7D 61 08 CC F1 24   '....8.T...}a...$'
    002D0- E6 9E B2 A0 4C A6 FC 1C 3E 00 54 1C 40 0E C0 0D   '....L...>.T.@...'
    002E0- F7 FE 15 E0 F6 EF 97 A0 40 0E C0 0D 9B EE 15 E0   '........@.......'
    002F0- F6 EF 97 A0 00 C6 FD A0 00 C8 FD A0 00 00 7C 1C   '..............|.'
    00300- 4F 0F 3E 14 01 C8 FD 80 03 C8 7D 62 99 98 A8 80   'O.>.......}b....'
    00310- 3F C8 7D 62 07 99 E8 54 54 2E E9 1C 00 00 7C 1C   '?.}b...TT.....|.'
    00320- 53 5E C0 0D 0F 2F 16 E0 F9 01 0C E0 F6 EF 8B A0   'S^.../..........'
    00330- F7 9F 82 A0 0B 9E FE 24 F7 9F 82 6C 12 9E FE 20   '.......$...l... '
    00340- 03 EE C3 28 4F EF 83 6C F6 EF 83 80 0E 00 0C E0   '...(O..l........'
    00350- F6 9F 82 A0 4F A1 BE A0 02 A0 FE 24 4F A1 BE 6C   '....O......$O..l'
    00360- 13 A0 FE 20 0A 9E FE 28 50 9F BE 6C 4F EF 83 80   '... ...(P..lO...'
    00370- FB 01 0C E0 F6 EF 93 80 40 0E C0 0D F7 8E 16 E0   '........@.......'
    00380- F6 EF 97 A0 64 7E C0 0D 07 47 15 E0 4D 9F BE A0   '....d~...G..M...'
    00390- 4C 9F BE 6C 4B 9F BE 60 4D 9F BE 6C 4B A1 BE A0   'L..lK..`M..lK...'
    003A0- 05 A0 FE 24 4B A1 BE 6C 0E A0 FE 24 4B A1 BE 6C   '...$K..l...$K..l'
    003B0- 19 A0 FE 20 50 9F BE 80 F7 9F 86 80 F6 9F 86 80   '... P...........'
    003C0- 4E 9F BE 80 49 A1 BE A0 48 A1 BE 60 47 A1 BE 68   'N...I...H..`G..h'
    003D0- 49 9D BE A0 48 9D BE 68 4E A1 BE 60 47 9D BE A0   'I...H..hN..`G...'
    003E0- 0B 9C FE 24 47 9D BE 6C 09 9C FE 24 47 9D BE 6C   '...$G..l...$G..l'
    003F0- 16 9C FE 20 4E A1 BE 80 4D 9D BE A0 4C 9B BE A0   '... N...M...L...'
    00400- 4B 99 BE A0 4A 97 BE A0 49 95 BE A0 48 93 BE A0   'K...J...I...H...'
    00410- 47 91 BE A0 4F 97 BE 80 4F 8F BE A0 50 8F BE 80   'G...O...O...P...'
    00420- 40 0E C0 0D 47 EF 15 E0 F6 EF 97 80 00 00 7C 1C   '@...G.........|.'
    00430- 00 00 00 00 00 02 00 00 6A 6A 6A 6A 67 E6 09 6A   '........jjjjg..j'
    00440- 85 AE 67 BB 72 F3 6E 3C 3A F5 4F A5 7F 52 0E 51   '..g.r.n<:.O..R.Q'
    00450- 8C 68 05 9B AB D9 83 1F 19 CD E0 5B 98 2F 8A 42   '.h.........[./.B'
    00460- 91 44 37 71 CF FB C0 B5 A5 DB B5 E9 5B C2 56 39   '.D7q........[.V9'
    00470- F1 11 F1 59 A4 82 3F 92 D5 5E 1C AB 98 AA 07 D8   '...Y..?..^......'
    00480- 01 5B 83 12 BE 85 31 24 C3 7D 0C 55 74 5D BE 72   '.[....1$.}.Ut].r'
    00490- FE B1 DE 80 A7 06 DC 9B 74 F1 9B C1 C1 69 9B E4   '........t....i..'
    004A0- 86 47 BE EF C6 9D C1 0F CC A1 0C 24 6F 2C E9 2D   '.G.........$o,.-'
    004B0- AA 84 74 4A DC A9 B0 5C DA 88 F9 76 52 51 3E 98   '..tJ...\...vRQ>.'
    004C0- 6D C6 31 A8 C8 27 03 B0 C7 7F 59 BF F3 0B E0 C6   'm.1..'....Y.....'
    004D0- 47 91 A7 D5 51 63 CA 06 67 29 29 14 85 0A B7 27   'G...Qc..g))....''
    004E0- 38 21 1B 2E FC 6D 2C 4D 13 0D 38 53 54 73 0A 65   '8!...m,M..8STs.e'
    004F0- BB 0A 6A 76 2E C9 C2 81 85 2C 72 92 A1 E8 BF A2   '..jv.....,r.....'
    00500- 4B 66 1A A8 70 8B 4B C2 A3 51 6C C7 19 E8 92 D1   'Kf..p.K..Ql.....'
    00510- 24 06 99 D6 85 35 0E F4 70 A0 6A 10 16 C1 A4 19   '$....5..p.j.....'
    00520- 08 6C 37 1E 4C 77 48 27 B5 BC B0 34 B3 0C 1C 39   '.l7.LwH'...4...9'
    00530- 4A AA D8 4E 4F CA 9C 5B F3 6F 2E 68 EE 82 8F 74   'J..NO..[.o.h...t'
    00540- 6F 63 A5 78 14 78 C8 84 08 02 C7 8C FA FF BE 90   'oc.x.x..........'
    00550- EB 6C 50 A4 F7 A3 F9 BE F2 78 71 C6 12 00 2A 59   '.lP......xq...*Y'
    00560- 2B 57 2C 4E 32 2E 3B 2F 55 3A A1 4D AD 4C AE 48   '+W,N2.;/U:.M.L.H'
    00570- AF 54 B0 5A B1 52 9E 51 BD 3F 00 38 00 38 20 24   '.T.Z.R.Q.?.8.8 $'
    00580- 2E 3C 2F 53 3A 82 40 8F 2A 96 2B 9F 2D AD 4C AE   '.</S:.@.*.+.-.L.'
    00590- 48 AF 54 B0 5A B1 52 80 23 B6 7C BB 5C 00 39 00   'H.T.Z.R.#.|.\.9.'
    005A0- 39 20 3D 2F 51 3A 5F 3E 5F 3C 77 5E 00 0D 0D 3D   '9 =/Q:_>_<w^...='
    005B0- 3D 3D 20 50 72 6F 70 65 6C 6C 65 72 20 49 49 20   '== Propeller II '
    005C0- 4D 6F 6E 69 74 6F 72 20 3D 3D 3D 0D 0D 00 3F 20   'Monitor ===...? '
    005D0- 2D 20 48 65 6C 70 0D 07 00 48 69 74 20 53 50 41   '- Help...Hit SPA'
    005E0- 43 45 00 20 20 27 00 27 0D 00 20 2D 0D 80 7B 61   'CE.  '.'.. -..{a'
    005F0- 64 72 7B 2E 61 64 72 7D 7D 80 7B 64 61 74 7B 20   'dr{.adr}}.{dat{ '
    00600- 64 61 74 7D 7D 80 61 64 72 80 0D 7E 48 55 42 8E   'dat}}.adr..~HUB.'
    00610- 92 60 56 69 65 77 0D 92 2F 9E 60 53 65 61 72 63   '.`View../.`Searc'
    00620- 68 0D 92 3A 9E 60 45 6E 74 65 72 0D AA 2E AA 5B   'h..:.`Enter....['
    00630- 3C 2F 3E 5D AA 60 4D 6F 76 65 0D AA 2E AA 5E 60   '</>].`Move....^`'
    00640- 43 68 65 63 6B 73 75 6D 0D AA 40 60 57 61 74 63   'Checksum..@`Watc'
    00650- 68 0D 5B 59 2F 57 2F 4E 5D 60 42 79 74 65 2F 77   'h.[Y/W/N]`Byte/w'
    00660- 6F 72 64 2F 6C 6F 6E 67 0D 7E 43 4F 47 53 8E 63   'ord/long.~COGS.c'
    00670- 6F 67 2B AA 7B 2B AA 7D 60 53 74 61 72 74 0D 63   'og+.{+.}`Start.c'
    00680- 6F 67 2D 60 53 74 6F 70 0D 4D 60 4D 61 70 0D 7E   'og-`Stop.M`Map.~'
    00690- 50 49 4E 53 8E 7B 70 69 6E 7D 5B 48 2F 4C 2F 54   'PINS.{pin}[H/L/T'
    006A0- 2F 5A 2F 52 5D 60 48 69 67 68 2F 6C 6F 77 2F 74   '/Z/R]`High/low/t'
    006B0- 6F 67 67 6C 65 2F 6F 66 66 2F 72 65 61 64 0D 70   'oggle/off/read.p'
    006C0- 69 6E 23 60 57 61 74 63 68 0D 70 69 6E 7C 63 66   'in#`Watch.pin|cf'
    006D0- 67 60 43 6F 6E 66 69 67 75 72 65 0D 64 61 74 5C   'g`Configure.dat\'
    006E0- 60 53 65 74 20 44 41 43 73 0D 7E 4D 49 53 43 8E   '`Set DACs.~MISC.'
    006F0- 64 61 74 2A 60 53 65 74 20 63 6C 6F 63 6B 0D 27   'dat*`Set clock.''
    00700- 60 52 65 70 65 61 74 0D 51 60 51 75 69 74 0D 00   '`Repeat.Q`Quit..'
    00710- 00 00 00 00 40 3C C0 0D D7 01 04 E0 00 EC D3 A0   '....@<..........'
    00720- 12 CC FF 0C 12 CE FF 0C 09 CE FF 28 DB CE 7F 0C   '...........(....'
    00730- 92 74 FF 0C CB 22 FC 0C 0A E6 7F F8 94 56 FF 0C   '.t...".......V..'
    00740- CB 32 FC 0C 01 C6 FF A0 D2 BE FD 1C AA 00 FC 0C   '.2..............'
    00750- B2 A2 FC 0C 6F E3 FE 1C E9 1A FE 1C 2B 73 FE 1C   '....o.......+s..'
    00760- 2F B0 6B F8 19 00 7C 1C 0B 1B FE 1C A4 02 FC 0C   '/.k...|.........'
    00770- 2B 73 FE 1C 1F 00 54 1C DA 65 FD 54 B2 00 FC 0C   '+s....T..e.T....'
    00780- C0 84 FD 1C B2 E4 FC 0C 11 00 7C 1C DD B7 BF A0   '..........|.....'
    00790- E0 65 FD 54 B2 3E FC 0C C0 84 FD 1C 38 00 7C 1C   '.e.T.>......8.|.'
    007A0- 2A 73 FE 1C 35 00 68 1C DD B9 BF A0 B2 84 FC 0C   '*s..5.h.........'
    007B0- C0 84 FD 1C 39 00 7C 1C 01 C6 FF A2 02 C6 EB A2   '....9.|.........'
    007C0- 04 C6 EB A0 D2 BE FD 1C 17 00 7C 1C 0F B8 FF A0   '..........|.....'
    007D0- 49 DD FE 1C 12 00 7C 1C FF B8 FF A0 49 DD FE 1C   'I.....|.....I...'
    007E0- 17 00 7C 1C FF B8 FF A0 4A DD FE 1C 18 00 7C 1C   '..|.....J.....|.'
    007F0- DB B9 BF A0 4C DD FE 1C 18 00 7C 1C DE B7 BF A0   '....L.....|.....'
    00800- E5 B9 BF A0 C7 A2 FD 1C 0E 45 FE 1C B2 B6 7F 0C   '.........E......'
    00810- 00 00 04 E0 00 B0 FF A0 E5 CC FD 1C F6 BB 07 86   '................'
    00820- 4B 00 68 1C E3 B7 BF 80 DC B7 3F 87 3F 00 78 1C   'K.h.......?.?.x.'
    00830- DB BD BF A0 E5 BD BF 60 18 00 7C 1C E1 B1 BF E9   '.......`..|.....'
    00840- 42 00 4C 1C E1 B9 BF A0 E4 B9 BF 2C DB B9 BF 80   'B.L........,....'
    00850- 39 00 7C 1C C7 A2 FD 1C 01 B2 FF A0 DB BF BF A0   '9.|.............'
    00860- E5 BF BF 60 0E 45 FE 1C 59 B2 7F FA E1 B5 BF A0   '...`.E..Y.......'
    00870- 01 B4 FF 80 B3 BE 7F 0C F6 BB 87 A0 E7 D0 FD 1C   '................'
    00880- 5A B4 FF F6 13 BE FF 0C 18 00 7C 1C D8 B3 BF A0   'Z.........|.....'
    00890- C7 A2 FD 1C 27 53 FE 1C E5 BB BF 4C E5 BB BF 60   '....'S.....L...`'
    008A0- 3C B2 7F 86 DB B1 AB A0 DD B7 AB A0 D8 BB AB A0   '<...............'
    008B0- DD B7 3F 85 DA B1 B3 A0 E4 B1 B3 2C D8 B7 B3 80   '..?........,....'
    008C0- D8 BB B3 80 7E CA F1 6C 7E CE F1 6C B2 B6 7F 0C   '....~..l~..l....'
    008D0- B3 BA 7F 0C E5 CC FD 1C E7 D0 FD 1C 71 B4 FF F6   '............q...'
    008E0- 7E CA F1 6C 7E CE F1 6C 18 00 7C 1C C7 A2 FD 1C   '~..l~..l..|.....'
    008F0- B2 B6 7F 0C E5 CC FD 1C DD B3 BF 80 79 B4 FF F6   '............y...'
    00900- D9 BB BF A0 08 C4 FF A0 85 1B FF 1C 16 00 7C 1C   '..............|.'
    00910- E6 C6 FD 52 01 C4 FF A0 E4 C6 E9 50 E3 C5 AB A0   '...R.......P....'
    00920- 01 C4 EB 2C E0 CC FD 1C DD B5 BF A0 85 1B FF 1C   '...,............'
    00930- 90 3D FF 1C A2 55 FF 1C 16 00 54 1C E0 CC FD 1C   '.=...U....T.....'
    00940- DA BB 3F 86 89 00 68 1C 86 00 7C 1C B2 FA FC 0C   '..?...h...|.....'
    00950- 6F E3 FE 1C 00 B6 7F 0C 9F 43 FF 1C 20 B0 7F 86   'o........C.. ...'
    00960- 92 00 54 1C 16 00 7C 1C E0 B6 7F 0C 27 53 FE 1C   '..T...|.....'S..'
    00970- DD B3 BF A0 00 BA FF A0 2B B0 7F 86 27 53 EA 1C   '........+...'S..'
    00980- DD B3 3F 0C 18 00 7C 1C 01 B6 FF 0C 03 B6 7F 0C   '..?...|.........'
    00990- 17 00 7C 1C 07 B2 FF A0 90 3D FF 1C D9 B1 BF A0   '..|......=......'
    009A0- 01 B0 FF 0D D9 B1 3F 86 30 B0 CF A0 31 B0 F3 A0   '......?.0...1...'
    009B0- 4D B0 EB A0 96 3D FF 1C 01 B2 FF 85 A2 00 4C 1C   'M....=........L.'
    009C0- 16 00 7C 1C DA 66 FD 52 DB 66 E9 52 D9 66 E9 52   '..|..f.R.f.R.f.R'
    009D0- D8 66 E9 52 D6 66 E9 50 DB C1 BF A0 D6 C0 7F 0D   '.f.R.f.P........'
    009E0- A5 00 68 1C 17 00 7C 1C 27 53 FE 1C E3 B6 7F 0C   '..h...|.'S......'
    009F0- 23 B6 FF 0C DD B7 3F E8 18 00 7C 1C D5 B6 7F 0C   '#.....?...|.....'
    00A00- 17 00 7C 1C B2 5C FD 0C 6F E3 FE 1C 16 00 7C 1C   '..|..\..o.....|.'
    00A10- B4 A4 7F 0C C1 B4 FF 00 00 B4 7F F8 C1 B2 FF 00   '................'
    00A20- D8 B3 BF 6E C1 00 54 1C DA 01 3C 1C E5 B7 BF 4C   '...n..T...<....L'
    00A30- E5 B7 BF 60 E5 B9 BF 4C E5 B9 BF 60 DB B9 3F 85   '...`...L...`..?.'
    00A40- 1D 00 70 1C DC B5 BF A0 DB B5 BF 84 E4 B5 BF 28   '..p............('
    00A50- 01 B4 FF 80 00 00 7C 1C 02 C6 7F 61 9A CB FD 0C   '......|....a....'
    00A60- 9A CF FD 0C 04 C6 7F 61 9B CB FD 0C 9B CF FD 0C   '.......a........'
    00A70- E3 C9 BF A0 01 C8 FF 28 E3 CB BF A0 01 CA FF 84   '.......(........'
    00A80- D3 CB BF 6C E5 BD BF 60 E5 BF BF 60 00 00 7C 1C   '...l...`...`..|.'
    00A90- D6 B6 7F 0D 00 BA CF A0 01 BA F3 A0 E6 00 7C 1C   '..............|.'
    00AA0- B2 B6 7F 0C C1 BA FF 00 00 00 7C 1C C1 BB 7F 00   '..........|.....'
    00AB0- 00 00 7C 1C A2 00 FC 0C 3E B0 FF A0 96 3D FF 1C   '..|.....>....=..'
    00AC0- 9F 43 FF 1C 27 B0 7F 86 F4 00 54 1C 18 B0 FF 0E   '.C..'.....T.....'
    00AD0- 96 3D D7 1C EF 00 54 1C 0A 01 7C 1C 9F 43 FF 1C   '.=....T...|..C..'
    00AE0- 0D B0 7F 86 09 01 68 1C 08 B0 7F 86 7F B0 57 86   '......h.......W.'
    00AF0- 01 01 68 1C 20 B0 7F 85 7E B0 4F E1 F3 00 70 1C   '..h. ...~.O...p.'
    00B00- AA B0 7F 0C 16 00 7C 0D A6 02 F0 0C 96 3D CF 1C   '......|......=..'
    00B10- F3 00 7C 1C 16 00 7C 0E A8 B0 57 0C 96 3D D7 1C   '..|...|...W..=..'
    00B20- 90 3D D7 1C 18 B0 D7 0C 96 3D D7 1C A6 02 D4 0C   '.=.......=......'
    00B30- F3 00 7C 1C AA 00 FC 0C A2 00 FC 0C D4 B1 BF A0   '..|.............'
    00B40- 96 3D FF 1C 00 00 7C 1C 00 AE FF A0 00 00 04 E0   '.=....|.........'
    00B50- 2A 73 FE 1C 23 4D D6 1C 20 B0 7F 86 10 01 68 1C   '*s..#M.. .....h.'
    00B60- 27 B0 7F 86 1E 01 54 1C A4 04 FC 0C 1A B0 FF 0C   ''.....T.........'
    00B70- 27 B0 7F 86 10 01 68 1C 1E B1 7F F8 D8 BB BF A0   ''.....h.........'
    00B80- 23 4D FE 1C 16 01 7C 1C 01 AE FF 85 D7 C3 8F A0   '#M....|.........'
    00B90- E1 43 BE 54 00 00 04 E4 00 00 7C 1C 11 AE FF E9   '.C.T......|.....'
    00BA0- 1D 00 70 1C DD ED 93 A0 00 00 7C 1C 2A 73 FE 1C   '..p.......|.*s..'
    00BB0- 1D 00 68 1C 00 00 7C 1C A4 02 FC 0C 00 BA FF A2   '..h...|.........'
    00BC0- 3A 7D FE 1E 18 B0 FF 0C 3F 91 FE 1C 04 BA F3 2C   ':}......?......,'
    00BD0- D8 BB B3 68 2D 01 70 1E A6 02 FC 0C 3A 7D FE 1E   '...h-.p.....:}..'
    00BE0- 3F 91 FE 1C 1A B0 F3 0C 60 B0 7F E1 7B B0 73 85   '?.......`...{.s.'
    00BF0- 20 B0 F3 84 00 00 7C 1C 18 B0 FF 0C 20 B0 7F 86   ' .....|..... ...'
    00C00- 3A 01 68 1C A6 02 FC 0C 00 00 7C 1E 2F B0 7F E1   ':.h.......|./...'
    00C10- 3A B0 73 85 07 B0 F3 80 40 B0 4F E1 47 B0 73 85   ':.s.....@.O.G.s.'
    00C20- 20 B0 F3 80 60 B0 4F E1 67 B0 73 85 57 B0 F3 84   ' ...`.O.g.s.W...'
    00C30- 00 00 7C 1C DE B7 BF A0 E5 B9 BF 60 DB B9 BF 80   '..|........`....'
    00C40- C7 A2 FD 1C DB BD BF A0 DE BB BF A0 05 C4 FF A0   '................'
    00C50- 85 1B FF 1C 8E 3D FF 1C E3 B1 BF A0 1B B0 FF 3C   '.....=.........<'
    00C60- DA B7 BF A0 D8 B7 BF 4C DB B9 BF A0 E4 B9 BF 2C   '.......L.......,'
    00C70- DB B5 BF 84 B2 BC 7F 0C E5 CC FD 1C E3 C5 BF A0   '................'
    00C80- 01 C4 FF 2C 85 1B FF 1C 90 3D FF 1C 5A B7 FF F6   '...,.....=..Z...'
    00C90- B2 0E FD 0C 6F E3 FE 1C B2 BC 7F 0C C1 B0 FF 00   '....o...........'
    00CA0- 20 B0 7F 85 7E B0 4F E1 2E B0 F3 A0 96 3D FF 1C   ' ...~.O......=..'
    00CB0- 63 B9 FF F6 12 BC FF 0C B2 16 FD 0C 6F E3 FE 1C   'c...........o...'
    00CC0- A2 55 FF 1C 4E B5 6B FA 00 00 7C 1C B4 A4 7F 0C   '.U..N.k...|.....'
    00CD0- C1 B0 FF 00 00 B0 7F F8 80 B0 7F 62 28 E1 D6 0C   '...........b(...'
    00CE0- B3 B0 57 0C B5 A4 57 0C 70 01 54 1C 60 B0 7F 86   '..W...W.p.T.`...'
    00CF0- 10 B2 EB E0 7E B0 57 86 10 B2 EB 80 90 3D EB 1C   '....~.W......=..'
    00D00- 7B B3 EB F6 8E 3D EB 1C 70 01 68 1C 0D B0 7F 86   '{....=..p.h.....'
    00D10- 0B 1B EA 1C 00 B2 EB A0 96 3D D7 1C 01 B2 D7 80   '.........=......'
    00D20- 70 01 7C 1C E2 B3 BF A0 02 B2 FF 2C D9 BB BF 20   'p.|........,... '
    00D30- E2 B3 BF A0 04 BA FF 24 DD B1 BF A0 92 3D FF 1C   '.......$.....=..'
    00D40- 89 B3 FF F6 00 00 7C 1C D5 B1 BF A0 96 01 7C 1C   '......|.......|.'
    00D50- 20 B0 FF A0 96 01 7C 1C 0F B0 FF 60 0A B0 7F 85   ' .....|....`....'
    00D60- 30 B0 F3 80 37 B0 CF 80 01 B0 FF 2C 69 B1 FF 0C   '0...7......,i...'
    00D70- 0D AE FF 0C F3 AF BF 80 0D AE 7F 0C 01 B0 FF 29   '...............)'
    00D80- DC CE 7F 0C 99 B1 7F FA 00 00 7C 1C A2 55 FF 1C   '..........|..U..'
    00D90- 9F 01 68 1C 00 00 7C 1C 80 D0 FF 68 17 D2 FF 0E   '..h...|....h....'
    00DA0- E8 D3 17 86 16 D2 D7 0C A2 D0 57 0C 18 B0 D7 0C   '..........W.....'
    00DB0- 16 D0 D7 0C A2 D2 57 0C 00 00 7C 1C 17 00 7C 0E   '......W...|...|.'
    00DC0- A3 00 E9 0C 09 D8 FF A0 F3 D5 BF A4 01 D4 FF 38   '...............8'
    00DD0- B0 CD FF F8 0C D4 FF 0C 01 D6 FF 30 F3 D5 BF 80   '...........0....'
    00DE0- 0D D4 7F 0C D6 CC 7F 0D B2 D9 FF F6 18 D6 FF 28   '...............('
    00DF0- AB D6 7F 0C AB 01 7C 1C E6 AD BF 54 25 AD FF 0D   '......|....T%...'
    00E00- F0 AC 7F 0C ED E1 8F A0 04 E0 CF 28 F0 E3 8F A4   '...........(....'
    00E10- ED E1 8F 80 ED E3 8F 80 EE E5 8F A0 06 E4 CF 10   '................'
    00E20- F0 E5 0F E1 F1 E5 0F 85 EF E5 8F A0 03 E4 CF 10   '................'
    00E30- F0 E5 0F E1 F1 E5 0F 85 EF DB 8F 80 03 DA CF 28   '...............('
    00E40- ED E7 8F A0 EE DB BF A0 EF DD BF A0 3A DE FF 0C   '............:...'
    00E50- BB DF 7F FA CF 01 7C 1C 5C 05 00 00 FF FF 01 00   '......|.\.......'
    00E60- 0D 28 04 00 2D 80 04 00 89 00 00 00 78 CF 68 9D   '.(..-.......x.h.'
    00E70- 3D 3D 20 45 6E 64 20 6F 66 20 52 4F 4D 20 3D 3D   '== End of ROM =='
    

    It is now 128 bytes shorter than it used to be, since I've used this time during full-chip verification being done by Beau and Open Silicon to pack things more efficiently.

    Here is the binary/HMAC-signed loader (it's only $70 longs and starts at $000):
    '********************************************************
    '*                            *
    '*        Propeller II ROM Booter            *
    '*                            *
    '*        Version 0.1                *
    '*                            *
    '*        11/01/2012                *
    '*                            *
    '********************************************************
    
    CON
    
      rx_pin = 91
      tx_pin = 90
      spi_cs = 89
      spi_ck = 88
      spi_di = 87
      spi_do = 86
    
      base = $E80
    
    
    DAT
    '
    '
    ' Version (@$000)
    '
                byte    "Prop2.0 "
    '
    '
    ' Shut down (@$008)
    '
                org
    
                clkset    h001+offset        'set clock to rc slow
                cogstop    h200+offset        'stop cog0
    offset
    '
    '
    ' Entry, read fuses (@$010)
    '
                org
    
                reps    #256,@:fuse        'ready to read 256 fuses
                setport    #rx_pin            'set rx_pin port for booting
    
                cogid    fuse_read    nr    'read fuses (172 fuses + 84 zeros)
                cogid    fuse_read    nr,wc    '(last iteration initializes cnt to $00000000_00000001)
                add    fuse_read,#1
                test    fuse_read,#$1F    wz
    :fusex            rcr    fuses,#1
    :fuse    if_z        add    :fusex,h200
    
                cogid    spi_read    nr    'disable fuses and enable cnt (spi_read[10..0] = 0)
    '
    '
    ' Attempt to boot from serial
    '
                jnp    monitor_ptr,#boot_flash    'if rx_pin is low, skip serial and boot from flash
    
                call    #rx_bit            'measure low rx calibration pulses (host $F9 -> %1..010011111..)
                mov    threshold,delta        'and calculate threshold
                call    #rx_bit            '(any timeout results in flash boot)
                add    threshold,delta
    h001            shr    threshold,#1        '(9 lsb's are $001)
    
                mov    count,#250        'ready to receive/verify 250 lfsr bits
    :lfsrin            call    #rx_bit            'receive bit ($FE/$FF) into c
                test    lfsr,#$01    wz    'get lfsr bit into nz
        if_c_eq_z    jmp    #boot_flash        'if mismatch, boot from flash
                test    lfsr,#$B2    wc    'advance lfsr
                rcl    lfsr,#1
                djnz    count,#:lfsrin        'loop for next bit in
    
                mov    count,#250+8        'ready to transmit 250 lfsr bits + 8 version bits
    :lfsrout        cmp    count,#8    wz    'if last 8 bits, set lfsr so that version will be output
        if_z        mov    lfsr,#$52        '$52 results in version $20 being sent (%00000100)
                test    lfsr,#$01    wz    'get lfsr/version bit into nz, z=1 on last iteration
                call    #wait_rx        'wait for rx low (convey incoming $F9 on rx_pin to $FE/$FF on tx_pin)
                clrp    #tx_pin            'make tx low
                call    #wait_rx        'wait for rx high
                setpnz    #tx_pin            'make tx lfsr/version bit
                call    #wait_rx        'wait for rx low
                setp    #tx_pin            'make tx high
                call    #wait_rx        'wait for rx high
                test    lfsr,#$B2    wc    'advance lfsr
                rcl    lfsr,#1
                djnz    count,#:lfsrout        'loop for next bit out
    
                jmp    #load            'serial handshake done, attempt to load from serial (z=1)
    '
    '
    ' Wait for rx low/high - if timeout, attempt to boot from flash
    '
    wait_rx            getcnt    time            'ready timeout
                add    time,timeout
    
    :waitpxx        waitpne    rx_mask,rx_mask    wc    'wait for rx low/high with timeout
    
                notb    :waitpxx,#23        'toggle waitpeq/waitpne
    
    wait_rx_ret    if_nc    ret                'return if not timeout (boot_flash follows)
    '
    '
    ' Attempt to boot from flash
    '
    boot_flash        mov    count,#4        'ready for 3 resets and 1 read command
    
    :cmd            setp    #spi_cs            'spi_cs high
                clrp    #spi_ck            'spi_ck low
    
                reps    #32,@:bit        'ready for 32 command bits
                clrp    #spi_cs            'spi_cs low
    
                cmpr    count,#1    wc    'first 3 commands = $FF_FF_FF_FF (reset)
        if_nc        rol    spi_read,#1    wc,wz    'last command = $03_00_00_00 (read from 0), z=0
                setpc    #spi_di
                setp    #spi_ck            'cycle spi_ck
    :bit            clrp    #spi_ck
    
                djnz    count,#:cmd        'loop for next spi command
    '
    '
    ' Load from serial (z=1) or flash (z=0)
    '
    load            setptra    loader_pgm        'load loader into base+$000..$7DF, HMAC into base+$7E0..$7FF
    
                mov    count,h200        'ready to input $200 longs
    :long            mov    bits,#32        'ready to input 32 data bits
    
    :bit    if_z        call    #rx_bit            'input serial bit (serial mode)
        if_nz        getp    #spi_do        wc    'input spi_do (flash mode)
        if_nz        setp    #spi_ck            'high spi_ck (flash mode)
        if_nz        clrp    #spi_ck            'low spi_ck (flash_mode)
                rcl    data,#1            'shift bit into long
                djnz    bits,#:bit        'loop, adequate time for next flash bit
    
                wrlong    data,ptra++        'store long in hub ram (ptra=base+$800 after)
                djnz    count,#:long        'loop for next long (count=0 after)
    '
    '
    ' Compute loader HMAC signature for loader authentication
    '
    ' base+$000..$7DF = loader                ($1F8 longs)
    ' base+$7E0..$7FF = loader HMAC signature        (8 longs)
    ' base+$800..$81F = fuses, 1st half are HMAC key    (8 longs)
    ' base+$820..$83F = proper HMAC signature        (8 longs)
    ' base+$840..$843 = sha256 command interface        (1 long)
    '
                reps    #8,#1            'store 128-bit key + 44 extra fuses + 84 zero bits
                setinda    fuses            'into base+$800..$81F
                wrlong    inda++,ptra++        '(ptra = base+$820, afterwards)
    
                wrlong    count,sha256_ptr    'clear sha256 command
    
                setcog    #1            'launch sha256 in cog1
                coginit    sha256_pgm,sha256_ptr
    
                setinda    begin_hmac        'do sha256 commands to compute proper loader hmac
                mov    count,#3        'ready for 3 commands: begin_hmac, hash_bytes, read_hash
    :cmd            wrlong    inda++,sha256_ptr    'set command
    :wait            rdlong    data,sha256_ptr    wz    'wait for command done
                tjnz    data,#:wait
                djnz    count,#:cmd        'loop for next command (count=0, z=1 after)
    
                cogstop    h001            'done with sha256, stop cog1
    '
    '
    ' If loader authenticates, run it
    '
                reps    #8,@:cmp        'verify loader hmac signature (z=1 on entry)
                setcog    #0            'ready to relaunch cog0 with loader/monitor
    
                rdlong    bits,ptra[-$10]        'get loader hmac signature long
                rdlong    data,ptra++        'get proper hmac signature long
    :cmp    if_z        cmp    bits,data    wz    'compare, z=1 if authenticated
    
        if_z        coginit    loader_pgm,loader_ptr    'if loader authenticated, relaunch cog0 with loader
    '
    '
    ' Authentication failed, hide fuses and clear memory
    '
                reps    #$20000/8,@:clr        'clear all memory
                cogid    monitor_pgm    nr    'hide fuses (bit 10 set)
    
                wrlong    count,ptra++        '(count=0)
    :clr            wrlong    count,ptra++
    '
    '
    ' If key <> 0, shut down - else, monitor
    '
                or    fuses+0,fuses+1    wz    'check if 128-bit key = 0
        if_z        or    fuses+2,fuses+3    wz
    
        if_nz        mov    monitor_pgm,#$008    'if key <> 0, shut down
    
                coginit    monitor_pgm,monitor_ptr    'relaunch cog0 with shut down or monitor
    '
    '
    ' Receive bit (c) - compare incoming pulse to threshold
    '
    rx_bit            call    #wait_rx        'wait for rx low
                getcnt    delta            'get time
    
                call    #wait_rx        'wait for rx high
                subcnt    delta            'get time delta
    
                cmp    delta,threshold    wc    'compare time delta to threshold
    
    rx_bit_ret        ret
    '
    '
    ' Constants
    '
    fuse_read        long    $200            '(gets modified to $300)
    timeout            long    20_000_000 / 1000 * 150    '150ms @20MHz (rcfast)
    rx_mask            long    1 << (rx_pin & $1F)
    lfsr            long    "P"
    spi_read        long    $03_000000
    h200            long    $200
    
    begin_hmac        long    1<<30 + (($004<<2)-1)<<17 + base+$800    'begin_hmac, loads key at base+$800 (4 longs)
    hash_bytes        long    2<<30 + (($1F8<<2)-1)<<17 + base+$000    'hash_bytes, hashes message at base+$000 ($1F8 longs)
    read_hash        long    3<<30              + base+$820    'read_hash, writes hash at base+$820 (8 longs)
    
    sha256_pgm        long    $1D0            'sha256 program address
    sha256_ptr        long    base+$840        'sha256 parameter (points to command)
    
    loader_pgm        long    base+$000        'loader program address
    loader_ptr        long    base+$800        'loader parameter (points to fuses)
    
    monitor_pgm        long    $55C+$1B4        'monitor program address
    monitor_ptr        long    tx_pin<<9 + rx_pin    'monitor parameter (conveys pins)
    '
    '
    ' Variables
    '
    fuses            res    8
    count            res    1
    bits            res    1
    data            res    1
    time            res    1
    delta            res    1
    threshold        res    1
    

    Here is the SHA-256/HMAC program used to authenticate code (thanks to Pedward for making this happen):
    '********************************************************
    '*                            *
    '*        Propeller II ROM SHA-256/HMAC        *
    '*                            *
    '*        Version 0.1                *
    '*                            *
    '*        11/01/2012                *
    '*                            *
    '********************************************************
    
    '
    ' Usage:            commandlong := 0                'pre-clear command long
    '                cognew($1D0, @commandlong)            'start SHA-256/HMAC in new cog
    '
    ' Start here for HMAC:        commandlong := 1<<30 + (keysize-1)<<17 + @key    'start HMAC with key of keysize bytes (1..64)
    '                repeat while commandlong            '(wait for command done)
    '
    ' Start here for SHA-256:    commandlong := 2<<30 + (msgsize-1)<<17 + @msg    'hash msg of msgsize bytes (1..8192)
    '                repeat while commandlong            '(wait for command done)
    '
    '                {issue more 2<<30 commands if msg > 8192 bytes}
    '
    '                commandlong := 3<<30 + @hashbuffer        'read resulting hash into hashbuffer (32 bytes)
    '                repeat while commandlong            '(wait for command done)
    '
    '                {hasbuffer now contains result, ready for new 1<<30 or 2<<30 command}
    '
    
    DAT
    
            org
    
            setf    #%0_1111_0000    'configure movf for sbyte0 -> {dbyte3,dbyte2,dbyte1,dbyte0,dbyte3,...}
    
            call    #init_hash    'init hash, clear hmac mode, reset byte count
    '
    '
    ' Command Loop
    '
    command        rdlong    x,ptra        'wait for command (%cc_nnnnnnnnnnnnn_ppppppppppppppppp)
            tjz    x,#command
    
            setptrb    x        'get pointer (%ppppppppppppppppp)
    
            mov    count,x        'get count (%nnnnnnnnnnnnn)
            shl    count,#2
            shr    count,#2+17
            add    count,#1    '+1 for 1..8192 range
    
            shr    x,#32-2        'get command (%cc)
    
            cachex            'invalidate cache for fresh rdbytec's
    
            djz    x,#begin_hmac    '1 = begin hmac, pointer @key (count+1 bytes, 1..64)
            djz    x,#hash_bytes    '2 = hash bytes, pointer @message (count+1 bytes, 1..8192)
            djz    x,#read_hash    '3 = read hash, pointer @hashbuffer (32 bytes)
    
    done        wrlong    zero,ptra    'clear command to signal done
    
            jmp    #command    'get next command
    '
    '
    ' Begin HMAC
    '
    begin_hmac    call    #end_hash    'end any hash in progress
    
    :ipad        mov    x,#$00        'get and hash ipad key (full block)
            cmpr    count,bytes wc    'after key bytes, hash $00's to fill block
        if_c    rdbytec    x,ptrb++
            xor    x,#$36        'xor bytes with ipad ($36)
            call    #hash_byte    '(last iteration triggers hash_block, z=1)
        if_nz    jmp    #:ipad
    
            reps    #16,#2        'save opad key
            setinds    opad_key,w
            mov    indb,inda++
            xor    indb++,opad    'xor bytes with opad ($5C)
    
            mov    hmac,#1        'set hmac mode
    
            jmp    #done
    '
    '
    ' Hash Bytes
    '
    hash_bytes    rdbytec    x,ptrb++    'hash bytes
            call    #hash_byte
            djnz    count,#hash_bytes
    
            jmp    #done
    '
    '
    ' Read Hash
    '
    read_hash    tjz    hmac,#:not    'if not hmac, output hash
    
    
            call    #end_hash    'hmac, end current hash
    
            reps    #16,#1        'get opad key into w[0..15] (full block)
            setinds    w,opad_key
            mov    indb++,inda++
    
            call    #hash_block    'hash opad key
    
            reps    #8,#1        'get hashx[0..7] into w[0..7]
            setinds    w,hashx
            mov    indb++,inda++
    
            movd    hash_byte,#w+8    'account for opad key and hashx bytes
            mov    bytes,#64+32    '(1-1/2 blocks, 1/2 block needs end_hash)
    
    
    :not        call    #end_hash    'end current hash
    
            setinda    hashx        'store hashx[0..7] at pointer, big-endian
            mov    count,#8
    :out        reps    #4,#2
            mov    x,inda++
            rol    x,#8
            wrbyte    x,ptrb++
            djnz    count,#:out
    
            jmp    #done
    '
    '
    ' End Hash - hash $80, any $00's needed to get to offset $38, then 8-byte length
    '
    end_hash    mov    length,bytes    'get message length in bits
            shl    length,#3
    
            mov    x,#$80        'hash end-of-message byte ($80)
    :fill        call    #hash_byte    '(may trigger hash_block)
            mov    x,bytes        'hash any $00's needed to get to offset $38
            and    x,#$3F
            cmp    x,#$38    wz
            mov    x,#$00
        if_nz    jmp    #:fill
    
    :len        test    bytes,#$04  wc    'hash 8-byte length, big-endian
        if_c    rol    length,#8    '(hash four $00's, then four length bytes)
        if_c    mov    x,length
            call    #hash_byte    '(last iteration triggers hash_block)
        if_nz    jmp    #:len
    
            reps    #8,#1        'save hash[0..7] into hashx[0..7]
            setinds    hashx,hash
            mov    indb++,inda++
    
    init_hash    reps    #8,#1        'copy hash_init[0..7] into hash[0..7]
            setinds    hash,hash_init
            mov    indb++,inda++
    
            mov    hmac,#0        'clear hmac mode
            mov    bytes,#0    'reset byte count
    init_hash_ret
    end_hash_ret    ret
    '
    '
    ' Hash Byte - add byte to w[0..15] and hash block if full (z=1)
    '
    hash_byte    movf    w,x        'store byte into w[0..15], big-endian
    
            add    bytes,#1    'increment byte count
    
            test    bytes,#$03  wz    'every 4th byte, increment w pointer
        if_z    add    hash_byte,d0
    
            test    bytes,#$3F  wz    'every 64th byte, reset w pointer
        if_z    movd    hash_byte,#w
    
        if_z    call    #hash_block    'every 64th byte, hash block
    
    hash_byte_ret    ret
    '
    '
    ' Hash Block - first extend w[0..15] into w[16..63] to generate schedule
    '
    hash_block    reps    #48,@:sch    'i = 16..63
            setinds    w+16,w+16-15+7    'indb = @w[i], inda = @w[i-15+7]
    
            setinda    --7        's0 = (w[i-15] -> 7) ^ (w[i-15] -> 18) ^ (w[i-15] >> 3)
            mov    indb,inda--
            mov    x,indb
            rol    x,#18-7
            xor    x,indb
            ror    x,#18
            shr    indb,#3
            xor    indb,x
    
            add    indb,inda    'w[i] = s0 + w[i-16]
    
            setinda    ++14        's1 = (w[i-2] -> 17) ^ (w[i-2] -> 19) ^ (w[i-2] >> 10)
            mov    x,inda
            mov    y,x
            rol    y,#19-17
            xor    y,x
            ror    y,#19
            shr    x,#10
            xor    x,y
    
            add    indb,x        'w[i] = s0 + w[i-16] + s1
    
            setinda    --5        'w[i] = s0 + w[i-16] + s1 + w[i-7]
    :sch        add    indb++,inda
    
    
    ' Load variables from hash
    
            reps    #8,#1        'copy hash[0..7] into a..h
            setinds    a,hash
            mov    indb++,inda++
    
    
    ' Do 64 hash iterations on variables
    
            reps    #64,@:itr    'i = 0..63
            setinds    k+0,w+0        'indb = @k[i], inda = @w[i]
    
            mov    x,g        'ch = (e & f) ^ (!e & g)
            xor    x,f
            and    x,e
            xor    x,g
    
            mov    y,e        's1 = (e -> 6) ^ (e -> 11) ^ (e -> 25)
            rol    y,#11-6
            xor    y,e
            rol    y,#25-11
            xor    y,e
            ror    y,#25
    
            add    x,y        't1 = ch + s1
            add    x,indb++    't1 = ch + s1 + k[i]
            add    x,inda++    't1 = ch + s1 + k[i] + w[i]
            add    x,h        't1 = ch + s1 + k[i] + w[i] + h
    
            mov    y,c        'maj = (a & b) ^ (b & c) ^ (c & a)
            and    y,b
            or    y,a
            mov    h,c
            or    h,b
            and    y,h
    
            mov    h,a        's0 = (a -> 2) ^ (a -> 13) ^ (a -> 22)
            rol    h,#13-2
            xor    h,a
            rol    h,#22-13
            xor    h,a
            ror    h,#22
    
            add    y,h        't2 = maj + s0
    
            mov    h,g        'h = g
            mov    g,f        'g = f
            mov    f,e        'f = e
            mov    e,d        'e = d
            mov    d,c        'd = c
            mov    c,b        'c = b
            mov    b,a        'b = a
    
            add    e,x        'e = e + t1
    
            mov    a,x        'a = t1 + t2
    :itr        add    a,y
    
    
    ' Add variables back into hash
    
            reps    #8,#1        'add a..h into hash[0..7]
            setinds    hash,a
            add    indb++,inda++
    
    hash_block_ret    ret
    '
    '
    ' Defined data
    '
    zero        long    0
    d0        long     1 << 9
    
    opad        long    $36363636 ^ $5C5C5C5C
    
    hash_init    long    $6A09E667, $BB67AE85, $3C6EF372, $A54FF53A, $510E527F, $9B05688C, $1F83D9AB, $5BE0CD19    'fractionals of square roots of primes 2..19
    
    k        long    $428A2F98, $71374491, $B5C0FBCF, $E9B5DBA5, $3956C25B, $59F111F1, $923F82A4, $AB1C5ED5    'fractionals of cube roots of primes 2..311
            long    $D807AA98, $12835B01, $243185BE, $550C7DC3, $72BE5D74, $80DEB1FE, $9BDC06A7, $C19BF174
            long    $E49B69C1, $EFBE4786, $0FC19DC6, $240CA1CC, $2DE92C6F, $4A7484AA, $5CB0A9DC, $76F988DA
            long    $983E5152, $A831C66D, $B00327C8, $BF597FC7, $C6E00BF3, $D5A79147, $06CA6351, $14292967
            long    $27B70A85, $2E1B2138, $4D2C6DFC, $53380D13, $650A7354, $766A0ABB, $81C2C92E, $92722C85
            long    $A2BFE8A1, $A81A664B, $C24B8B70, $C76C51A3, $D192E819, $D6990624, $F40E3585, $106AA070
            long    $19A4C116, $1E376C08, $2748774C, $34B0BCB5, $391C0CB3, $4ED8AA4A, $5B9CCA4F, $682E6FF3
            long    $748F82EE, $78A5636F, $84C87814, $8CC70208, $90BEFFFA, $A4506CEB, $BEF9A3F7, $C67178F2
    '
    '
    ' Undefined data
    '
    hmac        res    1
    bytes        res    1
    count        res    1
    length        res    1
    
    opad_key    res    16
    
    hash        res    8
    hashx        res    8
    
    w        res    64
    
    a        res    1
    b        res    1
    c        res    1
    d        res    1
    e        res    1
    f        res    1
    g        res    1
    h        res    1
    
    x        res    1
    y        res    1
    

    And here's the monitor, shrunk and improved:

    [code]
    '********************************************************
    '* *
    '* Propeller II ROM Monitor *
    '* *
    '* Version 0.1 *
    '* *
    '* 11/01/2012 *
    '* *
    '********************************************************

    '
    ' Usage: cognew($738, tx_pin << 9 + rx_pin) 'start monitor in new cog
    '

    CON

    branch1_ = 0
    branch2_ = branch1_ + 31
    branch3_ = branch2_ + 35
    hello_ = branch3_ + 15
    error_ = hello_ + 33
    hitspace_ = error_ + 11
    spquote_ = hitspace_ + 10
    quotecr_ = spquote_ + 4
    sub0_ = quotecr_ + 3 'must be => $80
    sub1_ = sub0_ + 4
    sub2_ = sub1_ + 12
    sub3_ = sub2_ + 12
    help_ = sub3_ + 4


    DAT

    '********
    '* Data *
    '********

    branch1 byte cmd_new, 0
    byte cmd_byte, "Y"
    byte cmd_word, "W"
    byte cmd_long, "N"
    byte cmd_viewp, "."
    byte cmd_search, "/"
    byte cmd_enter, ":"
    byte cmd_map, "M"
    byte cmd_clrp, "L"
    byte cmd_setp, "H"
    byte cmd_notp, "T"
    byte cmd_offp, "Z"
    byte cmd_getp, "R"
    byte cmd_quit, "Q"
    byte cmd_help, "?"
    byte 0 '31 bytes

    branch2 byte cmd_view2, 0
    byte cmd_view2, " "
    byte cmd_range, "."
    byte cmd_search2, "/"
    byte cmd_enter2, ":"
    byte cmd_watch, "@"
    byte cmd_clkset, "*"
    byte cmd_coginit, "+"
    byte cmd_cogstop, "-"
    byte cmd_clrp, "L"
    byte cmd_setp, "H"
    byte cmd_notp, "T"
    byte cmd_offp, "Z"
    byte cmd_getp, "R"
    byte cmd_watchp, "#"
    byte cmd_cfgp, "|"
    byte cmd_setdacs, "\"
    byte 0 '35 bytes

    branch3 byte cmd_view3, 0
    byte cmd_view3, " "
    byte cmd_search3, "/"
    byte cmd_enter3, ":"
    byte cmd_move, ">"
    byte cmd_move, "<"
    byte cmd_checksum, "^"
    byte 0 '15 bytes

    hello byte 13,13,"=== Propeller II Monitor ===",13,13
    byte 0 '33 bytes

    error byte "? - Help"
    byte 13,7,0 '11 bytes

    hitspace byte "Hit SPACE",0 '10 bytes

    spquote byte " '",0 '4 bytes

    quotecr byte "'",13,0 '3 bytes

    sub0 byte " -",13,$80 '4 bytes
    sub1 byte "{adr{.adr}}",$80 '12 bytes
    sub2 byte "{dat{ dat}}",$80 '12 bytes
    sub3 byte "adr",$80 '4 bytes

    help byte 13, "~HUB",sub0_
    byte sub1_, "`View",13
    byte sub1_,"/",sub2_, "`Search",13
    byte sub1_,":",sub2_, "`Enter",13
    byte sub3_,".",sub3_,"[</>]",sub3_, "`Move",13
    byte sub3_,".",sub3_,"^", "`Checksum",13
    byte sub3_,"@", "`Watch",13
    byte "[Y/W/N]", "`Byte/word/long",13
    byte "~COGS",sub0_
    byte "cog+",sub3_,"{+",sub3_,"}", "`Start",13
    byte "cog-", "`Stop",13
    byte "M", "`Map",13
    byte "~PINS",sub0_
    byte "{pin}[H/L/T/Z/R]", "`High/low/toggle/off/read",13
    byte "pin#", "`Watch",13
    byte "pin|cfg", "`Configure",13
    byte "dat\", "`Set DACs",13
    byte "~MISC",sub0_
    byte "dat*", "`Set clock",13
    byte "'", "`Repeat",13
    byte "Q", "`Quit",13 '(0 long follows)

    longs long


    '*********
    '* Entry *
    '*********

    org

    long 0 'start of data string = 0/nop

    reps #$1F6-reserves,#1 'clear reserves
    setinda reserves
    mov inda++,#0

    getptra rx_pin 'get rx/tx pins
    getptra tx_pin
    shr tx_pin,#9
    setp tx_pin

    jmptask #baud_task,#%0010 'enable baud detector task
    settask #%%0101

    tjz period,#$ 'wait for <space> to set period

    jmptask #rx_task,#%0100 'enable serial receiver task
    settask #%%0121

    mov wsize,#1 'init word size to byte
    call #set_size

    pusha #0 'init input line to <enter>

    setptra #hello_ 'print hello message

    dmax 'end of data string


    '*************
    '* Main Task *
    '*************

    message call #tx_string 'print hello/error message

    cmd_new call #rx_line 'get input line

    call #parse 'parse first term
    if_z tjz x,#cmd_viewl 'if no hex and eol, view data
    jmp #cmd_go 'else, process command


    cmd_next_crlf call #tx_crlf 'print cr/lf
    cmd_next addspa #1 'skip chr

    cmd_loop call #parse 'parse next term
    cmd_go if_nz jmp #cmd_hex 'if hex, branch
    movd pinx,#z 'pin update redirected to z
    setptra #branch1_ 'not hex, vector by chr
    call #vector 'if returns, no match

    cmd_error setptra #error_ 'print error message
    jmp #message


    cmd_hex mov v1,value 'hex, save v1
    movd pinx,#pin 'pin update okay
    setptra #branch2_ 'vector by chr
    call #vector 'if returns, no match
    jmp #cmd_view2 'view data


    cmd_range call #parse_next 'hex., get hex
    if_z jmp #cmd_viewp2 'if no hex, view data

    mov v2,value 'hex.hex, save v2
    setptra #branch3_ 'vector by chr
    call #vector 'if returns, no match
    jmp #cmd_view3 'view data
    '
    '
    ' Byte/word/long data
    '
    cmd_byte mov wsize,#1 wz 'set byte mode, z=0
    cmd_word if_z mov wsize,#2 wz 'set word mode, z=0
    cmd_long if_z mov wsize,#4 'set long mode

    call #set_size

    jmp #cmd_next 'next command
    '
    '
    ' View data
    '
    cmd_viewl mov v2,#$F '<enter> (eol), show line of data
    call #tx_range1
    jmp #cmd_new

    cmd_viewp mov v2,#$FF '. (more), show page of data
    call #tx_range1
    jmp #cmd_next

    cmd_viewp2 mov v2,#$FF 'addr. (more), show page of data
    call #tx_range2
    jmp #cmd_loop

    cmd_view2 mov v2,v1 'addr, show unit of data
    cmd_view3 call #tx_range 'addr.addr, show range of data
    jmp #cmd_loop
    '
    '
    ' Search
    '
    cmd_search mov v1,view '/, search from view to end
    cmd_search2 mov v2,amask 'addr/, search from address to end
    cmd_search3 call #check_range 'addr.addr/, search range

    call #parse_data 'parse data string

    :start setptra v1 'start search, point to search address
    setinda 0 'point to search data
    mov x,#0 'reset word match counter

    :word call #rdxxxx 'get memory word
    cmp value,inda++ wz 'compare against search data word
    if_z jmp #:match 'if word match, check if string match

    add v1,wsize 'word mismatch, advance search address
    cmp v1,v2 wz,wc 'at end of range?
    if_be jmp #:start 'if not, start next search

    mov view,v1 'else, update view
    and view,amask
    jmp #cmd_loop 'next command

    :match incmod x,dsize wc 'word match, increment match counter
    if_nc jmp #:word 'if more words to match, compare next word

    mov v2,dsize 'got string match
    shl v2,shift 'v1 = start of found data
    add v2,v1 'v2 = end of found data
    jmp #cmd_view3 'show found data
    '
    '
    ' Enter data
    '
    cmd_enter3 call #check_range 'addr.addr:, check range, z=words to fill
    mov y,#1 'set fill flag

    cmd_enter2 mov enter,v1 'addr:, set enter address
    and enter,amask 'trim enter address (in case cmd_enter2)

    cmd_enter call #parse_data ':, parse data

    tjnz y,#:go 'if not fill, set z to data size
    mov z,dsize
    add z,#1

    :go setptrb enter 'get pointer

    :loop mov value,inda++ 'get word from string data
    call #wrxxxx 'store value in memory
    djnz z,#:loop 'loop until enter done

    getptrb enter 'update pointer

    jmp #cmd_loop 'next command
    '
    '
    ' Move data
    '
    cmd_move mov y,x 'save ">"/"<"

    call #check_range 'check 1st address range, get number of words

    call #parse_hex 'get 2nd address

    max value,amask 'v1=1st, value=2nd, z=words, y=">"/"<"
    and value,amask

    cmp y,#"<" wz 'if "<", swap v1 and value
    if_z mov x,v1
    if_z mov v1,value
    if_z mov value,x 'v1=from, value=to, z=words

    cmp v1,value wc 'if from < to, downward move
    if_c mov x,z
    if_c shl x,shift
    if_c add v1,x
    if_c add value,x
    if_c xor rdxxxx,#%001_111110 'modify 'rdxxxx value,--ptra'
    if_c xor wrxxxx,#%001_111110 'modify 'wrxxxx value,--ptrb'

    setptra v1 'set pointers
    setptrb value

    :loop call #rdxxxx 'move data
    call #wrxxxx
    djnz z,#:loop

    if_c xor rdxxxx,#%001_111110 'restore 'rdxxxx value,ptra++'
    if_c xor wrxxxx,#%001_111110 'restore 'wrxxxx value,ptrb++'

    jmp #cmd_loop 'next command
    '
    '
    ' Checksum
    '
    cmd_checksum call #check_range 'check range

    setptra v1 'sum bytes
    :loop call #rdxxxx
    add y,value
    djnz z,#:loop

    mov value,y 'print sum
    mov hsize,#8
    call #tx_hex

    jmp #cmd_next_crlf 'next command
    '
    '
    ' Watch
    '
    cmd_watchp movs rdxxxj,#rdxxxx_ret wz 'set pin mode, z=0
    mov hsize,#1

    cmd_watch if_z movs rdxxxj,#rdxxxm 'set mem mode
    if_z mov hsize,wsize 'set hex size by word size
    if_z shl hsize,#1

    call #rdxxxp 'get initial value

    :loop mov z,value 'preserve value

    call #tx_hex 'print value
    call #tx_space 'print space

    :wait call #rx_check 'if key hit, exit
    if_nz jmp #cmd_next_crlf

    call #rdxxxp 'get current value

    cmp value,z wz 'if same, check again
    if_z jmp #:wait

    jmp #:loop 'new value, loop
    '
    '
    ' Clkset
    '
    cmd_clkset setptra #hitspace_ 'print hit-space message
    call #tx_string

    clkset v1 'set clk

    :wait call #rx 'wait for space
    cmp x,#" " wz
    if_nz jmp #:wait

    jmp #cmd_next_crlf 'next command
    '
    '
    ' Coginit
    '
    cmd_coginit setcog v1 'set cog

    call #parse_hex 'get program address

    mov y,value 'save program address
    mov value,#0 'clear pointer address

    cmp x,#"+" wz 'if '+', get pointer address
    if_z call #parse_hex

    coginit y,value 'do 'coginit program,pointer'

    jmp #cmd_loop 'next command
    '
    '
    ' Cogstop
    ' Quit
    '
    cmd_quit cogid v1 'quit

    cmd_cogstop cogstop v1 'stop cog

    jmp #cmd_next 'next command
    '
    '
    ' Map
    '
    cmd_map mov y,#7 'ready for 7..0

    cmd_map_loop call #tx_space 'print space
    mov x,y 'get cog status
    cogid x wc
    cmd_map_c cmp x,y wz
    if_nc mov x,#"0" 'get 0/1/M chr
    if_c mov x,#"1"
    if_z mov x,#"M"
    call #tx 'print chr
    sub y,#1 wc
    if_nc jmp #cmd_map_loop 'loop until done

    jmp #cmd_next_crlf 'next command
    '
    '
    ' Pin writes clrp/setp/notp/offp
    ' Pin read
    '
    cmd_clrp movs pinop,#$DA wz 'clrp, z=0
    cmd_setp if_z movs pinop,#$DB wz 'setp, z=0
    cmd_notp if_z movs pinop,#$D9 wz 'notp, z=0
    cmd_offp if_z movs pinop,#$D8 wz 'offp, z=0
    cmd_getp if_z movs pinop,#$D6 'getp, z=1

    pinx mov pin,v1 'if hex, get pin (d = pin/z)

    pinop getp pin wc 'becomes clrp/setp/notp/offp/getp

    if_z jmp #cmd_map_c 'if getp, show pin value

    jmp #cmd_next 'next command
    '
    '
    ' Pin configuration
    '
    cmd_cfgp call #parse_hex 'get configuration

    setport v1 'set pin port
    decod5 v1 'get pin mask
    cfgpins v1,value 'configure pin

    jmp #cmd_loop 'next command
    '
    '
    ' Setdacs
    '
    cmd_setdacs setdacs v1 'set all four dacs with 8-bit values

    jmp #cmd_next 'next command
    '
    '
    ' Help
    '
    cmd_help setptra #help_ 'print help message
    call #tx_string

    jmp #cmd_next_crlf 'next command


    '*************************
    '* Main Task Subroutines *
    '*************************
    '
    '
    ' Vector branch
    '
    vector addptra base 'add data base pointer

    vector_loop rdbyte z,ptra++ 'get jump address
    vector_ret tjz z,#0 'if 0, no match found, return

    rdbyte y,ptra++ 'get target
    xor y,x wz 'compare to x
    if_nz jmp #vector_loop 'if no match, loop

    jmp z 'match found, jump, y=0, z=1
    '
    '
    ' Check address range (v1..v2)
    '
    check_range max v1,amask 'trim v1
    and v1,amask

    max v2,amask 'trim v2
    and v2,amask

    cmp v2,v1 wc 'make sure v2 => v1
    if_c jmp #cmd_error

    mov z,v2 'get number of words
    sub z,v1
    shr z,shift
    add z,#1

    check_range_ret ret
    '
    '
    ' Set rdxxxx/wrxxxx and others by word size
    '
    set_size test wsize,#%010 wc 'set rdxxxx/wrxxxx by word size
    setbc rdxxxx,#26
    setbc wrxxxx,#26

    test wsize,#%100 wc
    setbc rdxxxx,#27
    setbc wrxxxx,#27

    mov shift,wsize 'set shift by word size
    shr shift,#1

    mov amask,wsize 'set amask by word size
    sub amask,#1
    xor amask,h0001FFFF

    and view,amask 'trim view
    and enter,amask 'trim enter

    set_size_ret ret


    rdxxxp getp v1 wc 'read pin as "0" or "1"
    if_nc mov value,#0
    if_c mov value,#1
    rdxxxj jmp #rdxxxx_ret 'd = rdxxxx_ret/rdxxxm

    rdxxxm setptra v1 'read mem

    rdxxxx rdbyte value,ptra++ 'rdbyte/rdword/rdlong
    rdxxxp_ret
    rdxxxx_ret ret


    wrxxxx wrbyte value,ptrb++ 'wrbyte/wrword/wrlong

    wrxxxx_ret ret
    '
    '
    ' Input line
    '
    rx_line setspa #0 'point to start of line

    mov x,#">" 'show prompt
    call #tx

    call #rx 'get first chr
    cmp x,#"'" wz 'check for repeat
    if_nz jmp #:first 'if not repeat, first chr

    :show popar x wz 'repeat, show line
    if_nz call #tx
    if_nz jmp #:show
    jmp #:done


    :loop call #rx 'get next chr

    :first cmp x,#13 wz 'cr?
    if_z jmp #:cr

    cmp x,#8 wz 'backspace?
    if_nz cmp x,#127 wz
    if_z jmp #:bs

    cmp x,#" " wc 'visible chr?
    if_nc cmpr x,#"~" wc
    if_c jmp #:loop

    pusha x 'visible chr, append to line
    chkspa wc 'overflow?
    if_c subspa #1 'if overflow, back up
    if_nc call #tx 'if not overflow, print chr
    jmp #:loop

    :bs chkspa wz 'backspace, line empty?
    if_nz pushar x 'if not empty,
    if_nz call #tx '..print backspace
    if_nz call #tx_space '..print space
    if_nz popar x '..print backspace
    if_nz call #tx
    if_nz subspa #1 '..back up
    jmp #:loop

    :cr pusha #0 'cr, end line with 0

    :done setspa #0 'point to start of line

    tx_crlf mov x,crlf 'print cr/lf
    call #tx
    tx_crlf_ret
    rx_line_ret ret
    '
    '
    ' Parse hex/text data
    '
    parse_data mov w,#0 'reset data count
    setinda 0 'point to string data

    :hex call #parse_next 'hex loop, check hex
    if_nz call #enter_data 'if hex, enter value
    cmp x,#" " wz 'check for space (more hex)
    if_z jmp #:hex 'if more hex, loop

    cmp x,#"'" wz 'not hex, "'"?
    if_nz jmp #:done 'if not "'", done

    :text addspa #2 'text loop
    popa x 'get and point to next chr
    cmp x,#"'" wz 'check for "'"
    if_z jmp #:hex 'if "'", back to hex
    tjz x,#:done 'if eol, done
    mov value,x 'text chr
    call #enter_data 'enter chr
    jmp #:text 'loop

    :done sub w,#1 wc 'get data count
    if_nc mov dsize,w 'if 0, reuse old data

    movd :fix,dsize 'form circular buffer
    :fix fixinda 0,0 '(no instruction-modification problem with 1:4 threading)

    parse_data_ret ret


    enter_data incmod w,#dmax wc 'check if data limit exceeded
    if_c jmp #cmd_error 'if data limit exceeded, error
    mov inda++,value 'store value in data

    enter_data_ret ret
    '
    '
    ' Parse hex
    '
    parse_hex call #parse_next 'try to parse hex
    if_z jmp #cmd_error 'if no hex, error

    parse_hex_ret ret
    '
    '
    ' Parse line (@spa), z=0 if hex (value)
    '
    parse_next addspa #1 'advance to next chr

    parse mov value,#0 wz 'z=1

    call #skip_spaces wz 'skip any spaces (preserve z)

    :loop popar x 'get chr
    call #check_hex 'check hex
    if_c shl value,#4 'if hex, append nibble and loop
    if_c or value,x
    if_c jmp #:loop wz 'z=0

    subspa #1 'repoint to non-hex chr

    call #skip_spaces wz 'skip any post-hex spaces (preserve z)

    call #check_hex 'check hex
    if_c popa x 'if hex, back up to space chr

    cmpr x,#"a"-1 wc 'make non-hex chr uppercase
    if_c cmp x,#"z"+1 wc
    if_c sub x,#"a"-"A"
    parse_next_ret
    parse_ret ret
    '
    '
    ' Skip spaces (@spa)
    '
    skip_spaces popar x 'skip space chr(s)
    cmp x,#" " wz
    if_z jmp #skip_spaces

    subspa #1 'back up to non-space chr

    skip_spaces_ret ret wz 'restore z
    '
    '
    ' Check hex (x), c=1 if hex (x)
    '
    check_hex cmpr x,#"0"-1 wc '"0".."9" -> $0..$9
    if_c cmp x,#"9"+1 wc
    if_c add x,#"A"-"9"-1

    if_nc cmpr x,#"A"-1 wc '"A".."F" -> $A..$F
    if_c cmp x,#"F"+1 wc
    if_c add x,#"a"-"A"

    if_nc cmpr x,#"a"-1 wc '"a".."f" -> $A..$F
    if_c cmp x,#"f"+1 wc
    if_c sub x,#"a"-10

    check_hex_ret ret
    '
    '
    ' Print range (v1..v2)
    '
    tx_range1 mov v1,view 'view..view + v2
    tx_range2 and v2,amask 'v1..v1 + v2
    add v2,v1

    tx_range call #check_range 'check range

    mov view,v1 'set address

    :line mov value,view 'print 5-digit address
    mov hsize,#5
    call #tx_hex

    call #tx_dspace 'print "- "

    mov x,wsize 'get number of words on line
    rev x,#32-5
    mov v1,z
    max v1,x

    mov v2,v1 'get number of ascii bytes on line
    shl v2,shift

    sub z,v1 'update number of words left

    setptra view 'print hex words
    :hex call #rdxxxx
    mov hsize,wsize
    shl hsize,#1
    call #tx_hex
    call #tx_space
    djnz v1,#:hex

    setptra #spquote_ 'print " '"
    call #tx_string

    setptra view 'print ascii bytes
    :ascii rdbyte x,ptra++
    cmp x,#" " wc 'visible chr?
    if_nc cmpr x,#"~" wc
    if_c mov x,#"." 'substitute "." for non-visible chrs
    call #tx
    djnz v2,#:ascii

    getptra view 'update address

    setptra #quotecr_ 'print "'" + cr
    call #tx_string

    call #rx_check 'check key hit
    if_z tjnz z,#:line 'if no key hit and more words left, print another line
    tx_range1_ret
    tx_range2_ret
    tx_range_ret ret
    '
    '
    ' Print string (@ptra)
    '
    tx_string addptra base 'add data base pointer

    tx_string_loop rdbyte x,ptra++ 'get chr

    tx_string_ret tjz x,#0 'if 0, done

    test x,#$80 wz 'substring?
    if_nz notb tx_string_loop,#8 'toggle ptra/ptrb
    if_nz setptrb x 'ptrb points to substring
    if_nz addptrb base
    if_nz jmp #tx_string_loop 'start substring or resume string

    cmp x,#"`" wz 'long tab?
    if_z subr y,#32-16
    if_nz cmp x,#"~" wz 'short tab?
    if_z add y,#16
    :tab if_z call #tx_space
    if_z djnz y,#:tab
    if_z call #tx_dspace
    if_z jmp #tx_string_loop

    cmp x,#13 wz 'cr?
    if_z call #tx_crlf
    if_z mov y,#0

    if_nz call #tx 'other?
    if_nz add y,#1
    jmp #tx_string_loop
    '
    '
    ' Print hex (value)
    '
    tx_hex mov y,hsize 'pre-rotate to get 1st nibble in top
    shl y,#2
    ror value,y

    mov y,hsize 'print nibbles
    :loop rol value,#4
    mov x,value
    call #tx_nib
    djnz y,#:loop

    tx_hex_ret ret
    '
    '
    ' Print "- "
    '
    tx_dspace mov x,dspace
    jmp #tx
    '
    '
    ' Print space
    '
    tx_space mov x,#" "
    jmp #tx
    '
    '
    ' Print nibble (x)
    '
    tx_nib and x,#$F 'isolate nibble

    cmp x,#$A wc 'alpha or numeric?
    if_c add x,#"0" 'numeric
    if_nc add x,#"A"-$A 'alpha
    '
    '
    ' Transmit chr (x)
    '
    tx shl x,#1 'insert start bit
    setb x,#9 'set stop bit

    getcnt w 'get initial time

    :loop add w,period 'add bit period to time
    passcnt w 'loop until bit period elapsed
    shr x,#1 wc 'get next bit into c
    setpc tx_pin 'write c to tx pin
    tjnz x,#:loop 'loop until bits done
    tx_dspace_ret
    tx_space_ret
    tx_nib_ret
    tx_ret ret
    '
    '
    ' Receive chr (x)
    '
    rx call #rx_check 'wait for rx chr
    if_z jmp #rx

    rx_ret ret
    '
    '
    ' Check receiver, z=0 if chr (x)
    '
    rx_check or rx_tail,#$80 'if start or rollover, reset tail

    getspb rx_temp wz 'if head uninitialized, z=1
    if_nz cmp rx_temp,rx_tail wz 'if head-tail mismatch, byte ready, z=0

    if_nz getspa rx_temp 'preserve spa
    if_nz setspa rx_tail 'get tail
    if_nz popar x 'get byte at tail
    if_nz getspa rx_tail 'update tail
    if_nz setspa rx_temp 'restore spa

    rx_check_ret ret


    '************************
    '* Serial Receiver Task *
    '************************

    rx_task chkspb wz 'if start or rollover, reset head
    if_z setspb #$80

    mov rx_bits,#9 'ready for 8 data bits + 1 stop bit

    neg rx_time,period 'get -0.5 period
    sar rx_time,#1

    jp rx_pin,#$ 'wait for start bit

    subcnt rx_time 'get time + 0.5 period for initial 1.5 period delay

    :bit rcr rx_data,#1 'rotate c into byte
    add rx_time,period 'add 1 period
    passcnt rx_time 'wait for center of next bit
    getp rx_pin wc 'read rx pin into c
    djnz rx_bits,#:bit 'loop until 8 data bits + 1 stop bit received

    shr rx_data,#32-8 'align byte
    pushb rx_data 'store byte at head, inc head

    jmp #rx_task 'wait for next byte


    '**********************
    '* Baud Detector Task *
    '**********************

    baud_task movd ctr,rx_pin 'set ctra to time rx pin states

    :loop notb ctr,#5 wc 'if 1,0 sample set, c=0
    setctra ctr '($20 -> 10000001001 -> 1, 6x 0, 1x 1, 2x 0, 1)

    if_nc mov limh,buff0 'if 1,0 sample set,
    if_nc shr limh,#4 '..make window from 1st 0 (6x if $20)
    if_nc neg liml,limh
    if_nc add limh,buff0
    if_nc add liml,buff0

    if_nc mov comp,buff1 'if 1,0 sample set,
    if_nc mul comp,#6 '..normalize 2nd 1 (1x if $20) to 6x
    if
  • cgraceycgracey Posts: 14,155
    edited 2012-11-10 00:10
    Sapieha wrote: »
    Hi Chip.

    One thing I'm are curious Why You not implemented Intel HEX loader in monitor with checksum cheking.
    That have ben nice to use as Loader from any Terminal program.

    Ps. In 8080 assembly it is only some lines of code.

    Because it's burdensome to have to remember how to compose Intel Hex lines and compute those checksum bytes. That's work for a computer, not a person. The monitor has a checksum command that can sum data within an address range in whatever mode you are are in (bytes/word/long) and return a 32-bit sum. You could just do one of those after loading your code and make sure it comes back with what you expect.
  • SapiehaSapieha Posts: 2,964
    edited 2012-11-10 00:21
    Hi Chip.

    Yes and NO.

    With Intel HEX Loader it is possible to have automated Loader that can know what place in memory I will place my data. And automatically test after every line if transfer was correct.


    In steps You describe it is impossible.
    cgracey wrote: »
    Because it's burdensome to have to remember how to compose Intel Hex lines and compute those checksum bytes. That's work for a computer, not a person. The monitor has a checksum command that can sum data within an address range in whatever mode you are are in (bytes/word/long) and return a 32-bit sum. You could just do one of those after loading your code and make sure it comes back with what you expect.
  • cgraceycgracey Posts: 14,155
    edited 2012-11-10 00:51
    Sapieha wrote: »
    Hi Chip.

    Yes and NO.

    With Intel HEX Loader it is possible to have automated Loader that can know what place in memory I will place my data. And automatically test after every line if transfer was correct.


    In steps You describe it is impossible.

    Here is how you'd enter code with the monitor and get a checksum:
    === Propeller II Monitor ===
    
    >1000:50 72 6F 70 32 2E 30 20 00 20 7C 0C 03 D0 7C 0C
    >1010:45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D
    >1020:01 C2 FC 80 1F C2 7C 62 01 E0 FC 30 66 0C A8 80
    >1030:01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0
    >1000.103F^
    00001C98
    >
    

    Here is Intel Hex (as used by Altera's FPGA tool):
    :100100000C7CD0030C7C200020302E32706F72509C
    :100101000D7CC2010C7CC2010CFCB6E30DC1FE45A6
    :1001020080A80C6630FCE001627CC21F80FCC20149
    :10010300A0BCFA7C1CFCC05BFAFCDE2A0C7CCA0197
    

    Both give you checksum functions, but the first seems way more human to me.

    I agree with your signature line: "If your gonna construct something, make it as simple as possible yet as versatile as possible."
  • SapiehaSapieha Posts: 2,964
    edited 2012-11-10 01:05
    Hi Chip.

    Thanks for that word on my signature.

    BUT still Alteras HEX not give complete hex code. It is missing last line in it - That are not necessary in it BUT important in CPU's (computers).
    It is starting point of loaded code to automatically start that Loaded program.

    In time I worked with control systems only possibility to update systems I have build was 300 baud modem -- And with Intel hex it give me possibility to Update them from Malmoe even if them was placed in Stockholm.

    I see Yours monitors possibility to show me HEX but still show me how I can use it with automated LOADER that can use simple serial communication ---- That Load code from serial test it if it is correct -- And then start it without my intervention.


    cgracey wrote: »
    Here is how you'd enter code with the monitor and get a checksum:
    === Propeller II Monitor ===
    
    >01000:50 72 6F 70 32 2E 30 20 00 20 7C 0C 03 D0 7C 0C
    >01010:45 FE C1 0D E3 B6 FC 0C 01 C2 7C 0C 01 C2 7C 0D
    >01020:01 C2 FC 80 1F C2 7C 62 01 E0 FC 30 66 0C A8 80
    >01030:01 CA 7C 0C 2A DE FC FA 5B C0 FC 1C 7C FA BC A0
    >1000.103F^
    00001C98
    >
    

    Here is Intel Hex (as used by Altera's FPGA tool):
    :100100000C7CD0030C7C200020302E32706F72509C
    :100101000D7CC2010C7CC2010CFCB6E30DC1FE45A6
    :1001020080A80C6630FCE001627CC21F80FCC20149
    :10010300A0BCFA7C1CFCC05BFAFCDE2A0C7CCA0197
    

    Both give you checksum functions, but the first seems way more human to me.

    I agree with your signature line: "If your gonna construct something, make it as simple as possible yet as versatile as possible."
  • cgraceycgracey Posts: 14,155
    edited 2012-11-10 01:23
    Sapieha wrote: »
    Hi Chip.

    Thanks for that word on my signature.

    BUT still Alteras HEX not give complete hex code. It is missing last line in it - That are not necessary in it BUT important in CPU's (computers).
    It is starting point of loaded code to automatically start that Loaded program.

    In time I worked with control systems only possibility to update systems I have build was 300 baud modem -- And with Intel hex it give me possibility to Update them from Malmoe even if them was placed in Stockholm.

    I see Yours monitors possibility to show me HEX but still show me how I can use it with automated LOADER that can use simple serial communication ---- That Load code from serial test it if it is correct -- And then start it without my intervention.

    After you load the hub memory, you can start a cog from it. For example, if you wanted to restart cog0 (which is running the monitor) with a program at $1000, you'd just type "0+1000" that would start cog0 at $1000.

    Here is the help menu from the monitor:
                    - HUB -
    {adr{.adr}}                     - View
    {adr{.adr}}/{dat{ dat}}         - Search
    {adr{.adr}}:{dat{ dat}}         - Enter
    adr.adr[</>]adr                 - Move
    adr.adr^                        - Checksum
    adr@                            - Watch
    [Y/W/N]                         - Byte/word/long
                    - COGS -
    cog+adr{+adr}                   - Start
    cog-                            - Stop
    M                               - Map
                    - PINS -
    {pin}[H/L/T/Z/R]                - High/low/toggle/off/read
    pin#                            - Watch
    pin|cfg                         - Configure
    dat\                            - Set DACs
                    - MISC -
    dat*                            - Set clock
    '                               - Repeat
    Q                               - Quit
    
  • SapiehaSapieha Posts: 2,964
    edited 2012-11-10 01:49
    Hi Chip.

    I see we don't understand each other.

    So my question are -- Can I in time I Load that program in memory some 1000 Km by simple serial modem be sure as it loaded correctly so it can be Started.

    If I load in my systems that Intel HEX LOADER automatically check for errors and only start that code if error free.
    If not give me prompt with info on load error.

    Ps. It is not as I say You need implement that -- BUT only debate with You what are usable.
    Lets say I send system with Propeller II up in one balloon and then see I need update it by some serial interface as simply as possible -- BUT need have security that will work correctly.
    Steps You describe -- NOT give me automated update possibility's.

    Bytes Address ___ Code ___________________________ Checksum.

    :10 0100000C7CD0030C7C200020302E32706F7250 9C :10 0101000D7CC2010C7CC2010CFCB6E30DC1FE45 A6 :10 01020080A80C6630FCE001627CC21F80FCC201 49 :10 010300A0BCFA7C1CFCC05BFAFCDE2A0C7CCA01 97

    It is line that are missing in Altera HEX code that give automated Start of Loaded code.
    Line to start loaded code - xx checksum of this line
    :0000 1000 XX


    Ps 2. --- I see I need add to my signature line You wreit on --- And see it is usable


    cgracey wrote: »
    After you load the hub memory, you can start a cog from it. For example, if you wanted to restart cog0 (which is running the monitor) with a program at $1000, you'd just type "0+1000" that would start cog0 at $1000.

    Here is the help menu from the monitor:
  • MJBMJB Posts: 1,235
    edited 2012-11-10 02:12
    Hi Saphiea,

    what I understand from Chips messages is:

    1. you load memory by this command
    {adr{.adr}}:{dat{ dat}} - Enter
    2. then you compute the checksum with
    adr.adr^ - Checksum
    3. your remote loader program checks if this is correct and if not repeats the steps 1 and 2
    4. if all is fine you start your code where you want with
    cog+adr{+adr} - Start

    so the only difference I see to your approach is that the check if the checksum is correct is done on the loader program and not inside the loaded PROP2

    If you like you can even do this line by line
    load the line, calc checksum, if ok proceed, else resend the line.
  • SapiehaSapieha Posts: 2,964
    edited 2012-11-10 02:17
    Hi MJB.

    Yes I understand that.

    But for automated HEX loader it need have possibility to send from Terminal simple text file in Intel HEX that MONITOR automatically load in correct place and if al OK then START it without any extra commands from You !!



    MJB wrote: »
    Hi Saphiea,

    what I understand from Chips messages is:

    1. you load memory by this command

    2. then you compute the checksum with

    3. your remote loader program checks if this is correct and if not repeats the steps 1 and 2
    4. if all is fine you start your code where you want with


    so the only difference I see to your approach is that the check if the checksum is correct is done on the loader program and not inside the loaded PROP2

    If you like you can even do this line by line
    load the line, calc checksum, if ok proceed, else resend the line.
  • MJBMJB Posts: 1,235
    edited 2012-11-10 02:31
    Hi Sapieha

    so with
    automated HEX loader
    you mean the part running in the PROP2, not a program on the sender side.
    There you want to be able to only do with a simple terminal.

    Then this would require a kind of conditional start command in the monitor
    like FORTH
    adr.adr^ ( compute checksum - and leave on stack )
    mychecksum =
    iftrue start with cog+adr{+adr} - Start
  • SapiehaSapieha Posts: 2,964
    edited 2012-11-10 02:42
    Hi MJB

    Original Intel HEX loader on 8080 check every loaded line for CHECKSUM - if not correct enter Monitor command mode else load next line.

    Then if it enter last line with (Byte counter 0) Start address -- Simply transfer Start address to tthis address.

    Ps. That give possibility to use send FILE mode in terminal program to load and start code automaticaly

    Ps 2. --- That system give possibility to update Program code by any type of Radio / Serial -Link.


    MJB wrote: »
    Hi Sapieha
    so this would require a kind of conditional start command in the monitor
    like FORTH
  • YanomaniYanomani Posts: 1,524
    edited 2012-11-10 07:42
    Hi Chip
    cgracey wrote: »
    After you load the hub memory, you can start a cog from it. For example, if you wanted to restart cog0 (which is running the monitor) with a program at $1000, you'd just type "0+1000" that would start cog0 at $1000.

    Are there any (effortless) means of patching only part of the running monitor, perhaps a new command to control that behavior, to extend (or ablate) funcionality without having to serialy re-send and re-check the entire (new) monitor then stoping, loading and restarting Cog 0?
    Can that be done by the use of self modifying code that acts based on Hub memory contents detected by the running monitor and/or a specific triggering event (command, piece of code or anything else)?

    (crossing my fingers and praying here ;)

    Yanomani
  • Dave HeinDave Hein Posts: 6,347
    edited 2012-11-10 08:33
    "squirt a little program into memory and launch it into a cog" :)
  • Bill HenningBill Henning Posts: 6,445
    edited 2012-11-10 09:04
    Chip,

    I *REALLY* like the monitor - it will be extremely handy.

    BUT

    What did you end up doing with the direct mode of {RD|WR}{BYTE|WORD|LONG|QUAD} ?

    The reason I ask that with the rom in low memory, the direct mode for the instructions would now be useless; knowing you, I expect you would have found a new use for it... I am guessing one of:

    A) added the extra bit to the offset
    B) moved the direct addressing to the end of memory (by substituting all 1's instead of all 0's when it is used)
    C) using it to select from among four pointer registers (instead of two)

    Inquiring minds want to know...

    (I suspect it is either A or B, C would be a pretty big change)

    Regards,

    Bill
  • potatoheadpotatohead Posts: 10,261
    edited 2012-11-10 09:19
    I bet on A

    Great, I can get started on P2, with my Tandy Model 100 now! :) Just having a little fun. I second, "Squirt a program..." Love it!
  • cgraceycgracey Posts: 14,155
    edited 2012-11-10 09:40
    Chip,

    I *REALLY* like the monitor - it will be extremely handy.

    BUT

    What did you end up doing with the direct mode of {RD|WR}{BYTE|WORD|LONG|QUAD} ?

    The reason I ask that with the rom in low memory, the direct mode for the instructions would now be useless; knowing you, I expect you would have found a new use for it... I am guessing one of:

    A) added the extra bit to the offset
    B) moved the direct addressing to the end of memory (by substituting all 1's instead of all 0's when it is used)
    C) using it to select from among four pointer registers (instead of two)

    Inquiring minds want to know...

    (I suspect it is either A or B, C would be a pretty big change)

    Regards,

    Bill

    There is no more direct addressing for RDxxxx/WRxxxx instructions. Any immediate #S value is treated as a pointer. So, I think "A" is the answer, if I understand.
  • cgraceycgracey Posts: 14,155
    edited 2012-11-10 10:19
    Yanomani wrote: »
    Hi Chip



    Are there any (effortless) means of patching only part of the running monitor, perhaps a new command to control that behavior, to extend (or ablate) funcionality without having to serialy re-send and re-check the entire (new) monitor then stoping, loading and restarting Cog 0?
    Can that be done by the use of self modifying code that acts based on Hub memory contents detected by the running monitor and/or a specific triggering event (command, piece of code or anything else)?

    (crossing my fingers and praying here ;)

    Yanomani

    I don't understand exactly what you are asking, but it sounds like you would like the monitor to have a restricted mode where it only allows a subset of commands to enable a verifiable download-and-execute procedure?
  • User NameUser Name Posts: 1,451
    edited 2012-11-10 11:40
    David Betz wrote: »
    I don't understand. A monitor is not a development system. You'll still need a tool on the host to compile or assemble code and download it into the P2 chip. This is really no different from the way P1 works. I guess you could use the monitor as a "development environment" if you like entering your code in hex. Is that what you mean?

    I wasn't comparing P2 to P1, but P2 to most of the 32-bit embedded world.

    You are certainly right...a monitor is not a development system. That's why I referred to it as a giant leap toward that end. It's a needed hook, especially if you're taking an incremental approach like I intend to do.

    Of course the P2 has other resources that would also contribute to it hosting a development system: More screen memory, and more hooks to fast external memory.
  • msrobotsmsrobots Posts: 3,709
    edited 2012-11-10 12:10
    Hi @Chip,

    great work - I love the monitor.

    I think @Sapieha is confused about the Monitor replacing boot over serial. As far as I understand the monitor is the last in the line of duty.

    So after failing to boot from serial, and failing to boot from flash the monitor gets activated if NO fuses for encryption are destroyed/set.

    So there is still a normals serial boot-loader, right?

    Can you please confirm this?

    Enjoy!

    Mike
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-11-10 12:18
    potatohead wrote:
    Great, I can get started on P2, with my Tandy Model 100 now! :) Just having a little fun.
    That's really not so far-fetched an idea. I did a lot of in-field program loading, testing and debugging on my Z8671 systems with a Model 100. They were a great little machine for that and easy for field personnel to understand and use. In fact, they are still being used by loyal fans:

    -Phil
  • potatoheadpotatohead Posts: 10,261
    edited 2012-11-10 12:30
    I know it's not. I use mine on occasion for notes on a meeting and such. It's always hilarious! Many people recognize it, and the discussion is always a good one. Great little computer. Got mine mint for a song out of a thrift store last year. It was $10, and I could not resist. Great curio. Everybody comes in with laptops, cords and the usual stuff. I just turn it on, in my lap and go, near instantly. When the right people are in the building, I find the entertainment worth it. The rest of the time, it is on my desk, with somebody tinkering with it every week.

    The keyboard is awesome! Heck, maybe I can gut another one for other uses. The thing runs about 20 hours on a nice set of batteries. And that's 20 hours just ON. If one is careful about not leaving it on, it's not unusual to go a week, using it when needed.

    I'm now wondering whether or not somebody did an 80 or 64 column display ROM for it.

    Could use the Apple as well. And I will too, just for some fun.

    Honestly, a P2 with some external RAM can probably do reasonable development. Bet we see a prop only system within a year. Can't wait, because I may well gut something, get that all installed and run portable, all prop! I've been collecting displays and such for that purpose as I find them cheap.

    Not sure what such a system would look like yet, but I know it will have two SD card slots, display, keyboard, battery, I/O, RAM. Lots of time for that once P2 gets completed.
  • potatoheadpotatohead Posts: 10,261
    edited 2012-11-10 12:37
    Re: Patch

    I think he's asking for an easy extension scheme. Boot monitor, "squirt the extensions over" restart, and now it's a monitor, plus some stuff.

    Bet it's not hard to do once we get to play with it some.

    Re: Intel HEX

    Saphia just wants it to run the code sent over without further intervention. [deleted]
  • SapiehaSapieha Posts: 2,964
    edited 2012-11-10 13:16
    Hi msrobots.

    NO -- My thinking was have alternate Loader -- That can load Simple ASCI HEX file from any terminal program and execute it.

    If You read entire Forum You will find that many people have problems with Load Propeller from all type of wireless serial communication.
    With Intel HEX Loader I talk on - that problem can be resolved.

    msrobots wrote: »
    Hi @Chip,

    great work - I love the monitor.

    I think @Sapieha is confused about the Monitor replacing boot over serial. As far as I understand the monitor is the last in the line of duty.

    So after failing to boot from serial, and failing to boot from flash the monitor gets activated if NO fuses for encryption are destroyed/set.

    So there is still a normals serial boot-loader, right?

    Can you please confirm this?

    Enjoy!

    Mike
  • jmgjmg Posts: 15,173
    edited 2012-11-10 13:50
    Sapieha wrote: »
    Ps. That give possibility to use send FILE mode in terminal program to load and start code automaticaly

    Ps 2. --- That system give possibility to update Program code by any type of Radio / Serial -Link.

    I'd agree with this, part of the terminal access cut/paste/copy/send file facility, should include blocks of intel hex.

    Things like Help strings, really do not need to be consuming valuable RAM space - put them in the terminal.
    Also things like Move and Fill and even Search, those can easily be done from a configured terminal, and are so rare
    the speed difference is not going to matter.
    In contrast, the RAM space is precious, and needed by everyone.

    Instead, put stuff in the smallest possible Monitor that allows human and non-human systems to easily slave the Prop II.

    Intel hex is universal, and comes from many tools, and a tiny micro can either compose Intel Hex, or Block-copy it.
    Given all intel hex lines start with :, it should be a safe syntax to include.

    This also give you a simple way to transport library files, that turn this into a really useful I/O Expander.
    Intel hex also allows comments, and you can append any single 'Load and go' line you like.
    Any common comment tag can be used ; or // or -- ; is my first guess, but may be close to :

    An example of how this would work :
    ; Title Comment Library Version 0.124  ; PWM Generation  blah etc
    -- Pin lists, link info - comments simply stripped by both/either Terminal and Monitor
    :100100000C7CD0030C7C200020302E32706F72509C
    :100101000D7CC2010C7CC2010CFCB6E30DC1FE45A6
    :1001020080A80C6630FCE001627CC21F80FCC20149
    :10010300A0BCFA7C1CFCC05BFAFCDE2A0C7CCA0197
    :00000001FF
    // Load above bytes, into Cog2, and Run
    cog2+0100+103F   ; whatever Monitor uses
    ; Title Comment Library Version 0.124  ; Multi Channel Quadrature Counter : Pins : 
    ; Pin lists, link info - comments simply stripped by both/either Terminal and Monitor
    :100100000C7CD0030C7C200020302E32706F72509C
    :100101000D7CC2010C7CC2010CFCB6E30DC1FE45A6
    :00000001FF
    ; Load above bytes, into Cog3, and Run
    cog3+0100+102F   ; whatever Monitor uses
    

    Someone can Select the I/O Function Library(s) from the configured terminal (or just paste it in), and then connect and test with their Host,
    and when they have decided that works, they paste their HEX library into their Host-loader, and they are on-air.

    They do not need to know any PASM, and it is a safe-step from terminal to field, as they can compose a single text script like file as they work.
    This target user is a total Prop II novice, but they are system experts. Make integration easy for them.
  • SapiehaSapieha Posts: 2,964
    edited 2012-11-10 13:56
    Hi jmg.

    You are correct.

    One thing I can add to Yours comments are that many of Terminal programs have ---- Send TEXT file command inbuilt that simplify that Loading.
Sign In or Register to comment.