CON ' Ray, Peter, this little 'Load new ROM' routine rewrites the built-in ' ..16KB ROM with what is being assembled into $FC000..$FFFFF. After ' ..running it, you'll have a new ROM. To update the ROM image again, ' ..you'll need to power-cycle the FPGA board to get it to reload the ' ..original image which permits loading the whole 1024KB again. {{ *********************** CHANGELOG ************************** '' RR20180512 v134a Combine: ROM_Booter v33d, LSD_v133i, SD2_133jx, TAQOZ BOOTROM(7) '' CG20180513 c Update booter '' RR20180513 c_001 Use booter's ao baud value for Monitor '' 002 Disable interrupts and smart pins on P0 & P1, but don't stop uart '' v134d '' ef Cmd_G coginit if addr $FC000, clockmax=200MHz, add nops/waitx to sendrecv '' may want to change the SD fail destination??? PJ20180514 V134e Implement buffered serial interrupts ^D from TAQOZ switches to DEBUGGER Add LF to LMM DEBUGGER (CRLF is standard line ending) '' RR20180515 v135b Add LF in other places; SD cogstop on failure '' cd Add load SD file "R"UN; SDinit to check for pullup '' e use "." in R as 8.3; add hubset #1 before cogstop '' f if Sd fails, jmp to shut_down in booter, now does cogid/cogstop '' parse R '' g add Chip's latest booter '' h Chip's latest; rearrange; remove delay1ms in serialinit & taqoz PBJ180516 v136 Adding in high level SD support, not complete but has virtual SD memory layer. Can load in full version of Tachyon with SD support using Ray's SD loader TAQOZ will reboot if four ESCs are entered in sequence (usually I use break detect) BIG BUG NOTICE!!! SD fail should not stop cog as application may be on Flash - Check Flash before SD '' RR20180516 v136c fix in _HubRxString; push/pop around pa use in _SDcard_Init; reset at _start_sdcard ??? '' RR20180517 v136d move and fname+2 ##$00FFFFFF from _Run_SDfile to search_dir '' use _str_hdg in _HubList (and for TAQOZ) '' remove reset_pins call in _Start_SDcard '' e _str_hdg add _str_dash; delay before calling taqoz '' f _HubList extra space ea 4 bytes '' RR20180519 v136m combine ROM_Booter_base_v32g; if SD fails boot,jmp #try_serial; Peter to add latest TAQOZ '' _str_hdg has dump header '' + tweek for P2ASM compiler; alignl long alignment after _str_hdg; _parsehex skip "_" 138PBJ Combine 137PBJ a remove delay1ms before monitor calls taqoz; jmp to _Enter_TAQOZ; remove _str_hdg Need to: Cmd_G use hubset ##$1000_0000 for FC000 +delay1ms (done) Taqoz to monitor needs to shutdown cogs Monitor to taqoz calls entry_taqoz and no 1ms delay (done) reset_booter ??? ???? Command9 needs to respect lmm_bufad not ##_HUBBUF ??? _HUBBUF use ROM (FC000 ???) (done) Cmd_X hex mode monitor/list option (done) "X" remove heading (done) SD add write sector ??? no space! monitor to repeat list (done) on its own??? '' RR20180520 138b command8 reply1=05 missing wz '' LL command replaces X (done) '' c add write_sector, command24, writeblock not verified!! '' overflowed ROM so use $FC000 for _HUBBUF '' d try to repeat list for next addr '' make G a call instead of a jump '' e tweeks to SD '' comment out write sd '' cmd_r result "="/"!"for passed/failed '' f mod _start/load/run_SDcard '' ##hubdata use _hubdata '' RR20180524 139 include ROM_Booter_base_138f.spin2 & RR139a (X) '' 139C w Chip pasted code ''----------------------------------------------------------------------------- '' 140_a List uses xxxxx: was xxxxx- '' R & L, List L[L] --> M[L] '' _e List xxxxx- does not require L/M '' _f use decod for PTN_SECCLU (needs TAQOZ 140e !!!) '' _g add TAQOZ 140F '' _gx remove unused labels fail etc '' _hx reorg SD routines '' RR20180526 140i proposed final SD & Monitor '' k fix SD timeout for dead/missing SD card w pullup. CMD0=10ms@35MHz '' RR20180527 v141 proposed final SD & Monitor '' PBJ20180527 Added SD and FAT32 routines **************************************************************** }} ' ' ' Load new ROM and wait for next reset ' 00000 000 dat org 00000 000 fecfc000 loc ptra,#$FC000 'ready to enter new data into rom 00004 001 fac41361 .lp rdbyte byte_data,ptra++ 'get new rom byte 00008 002 f8d00e09 setbyte rom_write,byte_data,#2 'install into command 0000c 003 fd600e00 hubset rom_write 'do rom write command 00010 004 f1040e01 add rom_write,#1 'inc address in command 00014 005 fb6c11fb djnz byte_count,#.lp 'loop until 16KB loaded into rom 00018 006 fd9ffffc jmp #$ 'wait for reset 0001c 007 30000000 rom_write long $30000000 'rom write command 00020 008 00004000 byte_count long $4000 'number of rom bytes 00024 009 byte_data res 1 'byte buffer '**************************************** '* * '* Propeller 2 ROM Booter * '* * '* 5/28/2018 - v32i * '* * '**************************************** CON ver = "A" 'Prop123-A9 / BeMicro-A9, 8 cogs, 64 smart pins ' ver = "B" 'DE2-115 ' ver = "C" 'DE0-Nano / DE0-Nano Bare ' ver = "D" 'BeMicro-A2 ' ver = "E" 'Prop123-A7 ' ver = "F" 'Prop123-A9 / BeMicro-A9, 16 cogs, 12 smart pins rx_pin = 63 'pin serial receiver tx_pin = 62 'pin serial transmitter spi_cs = 61 'pin SPI memory select (also sd_ck) spi_ck = 60 'pin SPI memory clock (also sd_cs) spi_di = 59 'pin SPI memory data in (also sd_di) spi_do = 58 'pin SPI memory data out (also sd_do) rx_ths = 1 'pin autobaud time high states rx_tne = 0 'pin autobaud time negative edges cog_spi = $000 'cog SPI program start cog_start = $100 'cog code start cog_base64 = $180 'cog base64 start lut_buff = $000 'lut serial receive buffer lut_btop = $00F 'lut serial receive buffer top lut_start = $010 'lut code start spi_ok = 0 'bit flags cmd_on = 1 ser_no = 2 rc_max = 30_000_000 'max frequency of RC oscillator DAT ' ' '******************************************* '* Cog init - overwritten by SPI program * '******************************************* ' fc000 orgh $FC000 fc000 000 org ' ' ' Seed xoroshiro 128** using delta-sigma ADC bits from calibration mode ' fc000 000 ff800800 wrpin ##$00100000,#rx_pin 'put rx pin in adc gio calibration mode fc004 001 fc0c003f fc008 002 f606c832 mov x,#50 'ready to seed 50 times with 31 bits fc00c 003 fcdc041f .seed rep #2,#31 'get 31 bits (31*4 clocks = 124/20 = ~6us) fc010 004 fd747e40 testp #rx_pin wc fc014 005 f0a6ca01 rcl y,#1 fc018 006 f426ca1f bith y,#31 'seed via hubset fc01c 007 fd62ca00 hubset y fc020 008 fb6ec9fa djnz x,#.seed fc024 009 fc0c003f wrpin #0,#rx_pin 'return rx pin to normal mode ' ' ' Move code into position ' fc028 00a fd64c428 setq #cog_end-cog_code-1 'move cog code into position fc02c 00b ff0007e0 rdlong cog_start,##@cog_code fc030 00c fb06012c fc034 00d fd655229 setq2 #lut_end-lut_code-1 'move lut code into position fc038 00e ff0007e1 rdlong lut_start,##@lut_code fc03c 00f fb0420b8 ' ' ' Make 256-byte base64 lookup table ' fc040 010 fd647e28 setq #$FF>>2 'reset table in hub fc044 011 ffffffff wrlong ##$FFFFFFFF,#0 fc048 012 fc6ffe00 fc04c 013 fb4c8231 callpa #"A",#fill26 '"A".."Z" --> $00..$19 fc050 014 fb4cc230 callpa #"a",#fill26 '"a".."z" --> $1A..$33 fc054 015 f606c80a mov x,#10 '"0".."9" --> $34..$3D fc058 016 fb4c602f callpa #"0",#fill fc05c 017 fc4c7c2b wrbyte #$3E,#"+" '"+" --> $3E fc060 018 fc4c7e2f wrbyte #$3F,#"/" '"/" --> $3F fc064 019 fd647e28 setq #$FF>>2 'load table into cog fc068 01a fb070000 rdlong cog_base64,#0 ' ' ' If pull-up on spi_di then try serial ' fc06c 01b fb4c76ed callpa #spi_di,#check_pullup fc070 01c cd9007cc if_c jmp #reset_serial ' ' ' If pull-up on spi_cs then try to load from SPI memory ' fc074 01d fb4c7aeb callpa #spi_cs,#check_pullup fc078 01e cd90000c if_c jmp #try_spi ' ' ' If pull-up on spi_ck (also sd_cs) then try to load from SD card ' fc07c 01f fb4c78e9 callpa #spi_ck,#check_pullup fc080 020 cd8fc560 if_c jmp #@_start_sdcard ' ' ' If no pull-down on spi_di then try serial ' fc084 021 fd900378 jmp #try_serial ' ' ' Try to load from SPI memory ' fc088 022 fd647a59 try_spi drvh #spi_cs 'drive spi_cs high fc08c 023 fd647858 drvl #spi_ck 'drive spi_ck low fc090 024 f667ee01 neg pb,#1 'set command bits to all 1's fc094 025 fd647459 drvh #spi_do 'drive spi_do high in case quad/dual mode fc098 026 fb4c04e8 callpa #2,#spi_cmd 'send exit-quad command fc09c 027 fb4c10e7 callpa #8,#spi_cmd 'send exit-quad command fc0a0 028 fb4c20e6 callpa #16,#spi_cmd 'send exit-dual command fc0a4 029 fd647450 fltl #spi_do 'float spi_do fc0a8 02a fb5ccce3 callpb #$66,#spi_cmd8 'send reset-enable command fc0ac 02b fb5d32e2 callpb #$99,#spi_cmd8 'send reset command fc0b0 02c ff800002 waitx ##rc_max/20_000 'wait 50us fc0b4 02d fd67b81f fc0b8 02e fb5c08df callpb #$04,#spi_cmd8 'send write-disable command to clear WEL fc0bc 02f fb5c0ade .wait callpb #$05,#spi_cmd8 'send read-status command fc0c0 030 fdb00398 call #spi_in 'get status fc0c4 031 f42ec801 testbn x,#1 wz 'if WEL high, no SPI memory (z=0) fc0c8 032 5d90003c if_nz jmp #.fail fc0cc 033 f42ec800 testbn x,#0 wz 'if BUSY high, wait for erase/write to finish fc0d0 034 5d9fffe8 if_nz jmp #.wait fc0d4 035 f607ec20 mov pa,#32 'send read-from-start command fc0d8 036 fb5c06d8 callpb #$03,#spi_cmd fc0dc 037 f9c6ca0a decod y,#10 'ready to input $400 bytes from SPI fc0e0 038 fc8c0000 wrfast #0,#0 'ready to write bytes to hub fc0e4 039 fdb00374 .data call #spi_in 'get byte fc0e8 03a fd62c815 wfbyte x 'store byte into hub fc0ec 03b fb6ecbfd djnz y,#.data 'loop for next byte (y=0 after) fc0f0 03c fc7c0000 rdfast #0,#0 'ready to read longs from hub fc0f4 03d fcdc0500 rep @.sum,#$100 'ready to read and sum $100 longs fc0f8 03e fd62cc12 rflong z 'read long fc0fc 03f f102cb66 add y,z 'sum long fc100 040 .sum fc100 040 f20acb52 cmp y,csum wz 'verify checksum, z=1 if okay fc104 041 f4868e00 bitz flags,#spi_ok 'if program verified, set spi_ok flag fc108 042 .fail ' ' ' If SPI failed, check for pull-up on spi_ck (also sd_cs) ' fc108 042 5b4c78c6 if_nz callpa #spi_ck,#check_pullup 'if no SPI program, check for pull-up on spi_ck (also sd_cs) fc10c 043 4d8fc560 if_nz_and_c jmp #@_start_sdcard 'if no SPI program and pull-up on spi_ck, try to load from SD card fc110 044 fd9002ec jmp #try_serial 'try serial ' ' ' Fill table ' fc114 045 f606c81a fill26 mov x,#26 'ready to fill "A".."Z"/"a".."z" entries fc118 046 fc8801f6 fill wrfast #0,pa 'set table pointer fc11c 047 fcd80564 rep @.v,x 'fill entries with ascending values fc120 048 fd609415 wfbyte .v fc124 049 f1049401 add .v,#1 fc128 04a 02040000 .v _ret_ cmp 0,#0 'bottom byte used as a counter fc12c 04b fit cog_start 'make sure below cog code ' ' '************** '* Cog code * '************** ' fc12c 100 org cog_start fc12c 100 cog_code ' ' ' Try serial if no pull-down on spi_di ' else, run SPI program if valid or float SPI pins and shut down ' fc12c 100 f40e8e00 try_serial testb flags,#spi_ok wz 'SPI program? fc130 101 5d647a50 if_nz fltl #spi_cs 'if no SPI program, float SPI pins fc134 102 5d647850 if_nz fltl #spi_ck fc138 103 ad65fe28 if_z setq #$FF 'if SPI program, move it into cog $000..$0FF fc13c 104 ab040000 if_z rdlong 0,#0 fc140 105 fd647659 drvh #spi_di 'check pull-down on spi_di, leave floating fc144 106 fb4c7603 callpa #spi_di,#check_pulldn 'c=0 if pull-down fc148 107 3d900664 if_nc jmp #serial_done 'if pull-down on spi_di, boot if SPI okay (z=1) or shut down fc14c 108 fd90041c jmp #reset_serial 'else try serial ' ' ' Check pin pull-up ' fc150 109 fd63ec58 check_pullup drvl pa 'drive pin low fc154 10a fd643c1f check_pulldn waitx #30*1 'wait >1us fc158 10b fd63ec50 fltl pa 'float pin fc15c 10c fd652c1f waitx #30*5 'wait >5us fc160 10d 0d73ec40 _ret_ testp pa wc 'sample pin ' ' ' SPI long/byte out ' fc164 10e f607ec08 spi_cmd8 mov pa,#8 'ready to send 8 bits fc168 10f fd647a59 spi_cmd drvh #spi_cs 'cs pin high fc16c 110 f027ee18 rol pb,#24 'msb-justify byte fc170 111 fd647a58 drvl #spi_cs 'cs pin low fc174 112 f037ee01 .out rol pb,#1 wc 'get bit to send fc178 113 fd64765a drvc #spi_di 'drive data-in pin to bit fc17c 114 fd647859 drvh #spi_ck 'drive clock pin high fc180 115 fd647858 drvl #spi_ck 'drive clock pin low fc184 116 0b6fedfb _ret_ djnz pa,#.out 'loop to output bits, return when done ' ' ' SPI byte in ' fc188 117 fcdc0808 spi_in rep @.in,#8 'ready to input a byte fc18c 118 fd647859 drvh #spi_ck 'drive clock pin high fc190 119 fd647858 drvl #spi_ck 'drive clock pin low fc194 11a fd747440 testp #spi_do wc 'sample data-out pin ('testp' is from before 'drvh') fc198 11b f0a6c801 rcl x,#1 'save data bit fc19c 11c .in fc19c 11c fd64002d ret ' ' ' Autobaud ISR - detects initial "> " ' ' falls |--7---| ' $3E --> ..10011111001..10000001001.. ' highs |-5--| ' fc1a0 11d fa8ed200 autobaud_isr rdpin a0,#rx_tne '2 get fall-to-fall time (7x if $3E) fc1a4 11e fa8ed401 rdpin a1,#rx_ths '2 get high time (5x if $3E) fc1a8 11f f292d33d cmpr a0,limit wc '2 make sure both measurements are within limit fc1ac 120 3292d53d if_nc cmpr a1,limit wc '2 fc1b0 121 fa32d33e scas a0,norm0 '2 if they are within 1/35th of each other, $3E fc1b4 122 3292d400 if_nc cmpr a1,0 wc '2 fc1b8 123 fa32d53f scas a1,norm1 '2 fc1bc 124 3292d200 if_nc cmpr a0,0 wc '2 fc1c0 125 cb3bfff5 if_c reti1 '2/4 if not $3E, exit fc1c4 126 fb3be9f5 resi1 '4 got $3E, resume on next interrupt fc1c8 127 fc0c0200 akpin #rx_tne '2 acknowledge pin fc1cc 128 fa02d340 mul a0,baud0 '2 compute baud rate fc1d0 129 f8c6d207 setbyte a0,#7,#0 '2 set word size to 8 bits fc1d4 12a fc16d23f wxpin a0,#rx_pin '2 set receiver baud rate and word size fc1d8 12b fc16d23e wxpin a0,#tx_pin '2 set transmitter baud rate and word size fc1dc 12c fb3be9f5 resi1 '4 resume on next interrupt fc1e0 12d fd647e41 dirh #rx_pin '2 enable receiver before next start bit fc1e4 12e fc068c00 wrpin mtpe,#rx_tne '2 change rx_tne to measure positive edges fc1e8 12f fd677e20 setse1 #%110<<6+rx_pin '2 set se1 to trigger on rx_pin high fc1ec 130 fb3be9f5 resi1 '4 resume on next interrupt ' ' ' Receiver ISR - detects maintenance ">" chrs ' ' rises |--7---| ' $3E --> ..10011111001.. ' fc1f0 131 fa8ed400 rdpin a1,#rx_tne '2 get rise-to-rise time (7x if $3E) fc1f4 132 fa9ed63f rdpin a2,#rx_pin wc '2 get received chr fc1f8 133 f046d618 shr a2,#32-8 '2 shift to lsb justify fc1fc 134 f20ed63e cmp a2,#">" wz '2 autobaud chr? fc200 135 5c32d76c if_nz wrlut a2,head '2 if not, write byte to circular buffer in lut fc204 136 5706d80f if_nz incmod head,#lut_btop '2 ..increment buffer head fc208 137 5b3bfff5 if_nz reti1 '2/4 ..exit fc20c 138 fa02d540 mul a1,baud0 '2 autobaud chr, compute baud rate fc210 139 f8c6d407 setbyte a1,#7,#0 '2 set word size to 8 bits fc214 13a fc16d43f wxpin a1,#rx_pin '2 set receiver baud rate and word size fc218 13b fc16d43e wxpin a1,#tx_pin '2 set transmitter baud rate and word size fc21c 13c fb3bfff5 reti1 '4 exit fc220 13d 000058e4 limit long $58E4 'count limit ($58E4 = 1.3889, keeps SCAS within $7FFF w/norm1) fc224 13e 00002f05 norm0 long $41D4*5/7 'fall-to-fall normalization factor fc228 13f 00005c28 norm1 long $41D4*7/5 'high-time normalization factor ($41D4 = 1.0 + 1/(7*5)) fc22c 140 00002492 baud0 long $1_0000/7 '7x baud computation factor ' ' ' Constants / initialized variables ' fc230 141 002dc6c0 timeout_per long rc_max/10 '100ms timeout for serial receive fc234 142 00000258 timeout_cnt long 600 '60s timeout for serial completion fc238 143 0000387c mtxf long %111<<11+%01_11110_0 'asynchronous serial transmit, float on high fc23c 144 60000022 mths long %0_110_0_000<<24+%00_10001_0 'time high states on pin[-2] (pin 63 in case of pin 1) fc240 145 ff000026 mtne long %1_111_1_111<<24+%00_10011_0 'time neg edges on pin[-1] (pin 63 in case of pin 0) fc244 146 77000026 mtpe long %0_111_0_111<<24+%00_10011_0 'time pos edges on pin[-1] (pin 63 in case of pin 0) fc248 147 00000000 flags long 0 'bit flags fc24c 148 50726f70 text_prop byte "porP" 'text fc250 149 5f43686b text_chk byte "khC_" fc254 14a 5f436c6b text_clk byte "klC_" fc258 14b 5f486578 text_hex byte "xeH_" fc25c 14c 5f547874 text_txt byte "txT_" fc260 14d 72500a0d text_ver byte 13,10,"Prop_Ver ",ver,13,10,0,0 fc270 151 0000002e text_sta byte ".",0,0,0 fc274 152 706f7250 csum byte "Prop" 'checksum fc278 153 00000000 hexchrs long %00000000_00000000_00000000_00000000 fc27c 154 03ff0000 long %00000011_11111111_00000000_00000000 '"0".."9" fc280 155 0000007e long %00000000_00000000_00000000_01111110 '"A".."F" fc284 156 0000007e long %00000000_00000000_00000000_01111110 '"a".."f" fc288 157 00000000 long %00000000_00000000_00000000_00000000 fc28c 158 00000000 long %00000000_00000000_00000000_00000000 fc290 159 00000000 long %00000000_00000000_00000000_00000000 fc294 15a 00000000 long %00000000_00000000_00000000_00000000 fc298 15b 00002600 whitechrs long %00000000_00000000_00100110_00000000 'cr, lf, tab fc29c 15c 20000001 long %00100000_00000000_00000000_00000001 '"=", space fc2a0 15d 00000000 long %00000000_00000000_00000000_00000000 fc2a4 15e 00000000 long %00000000_00000000_00000000_00000000 fc2a8 15f 00000000 long %00000000_00000000_00000000_00000000 fc2ac 160 00000000 long %00000000_00000000_00000000_00000000 fc2b0 161 00000000 long %00000000_00000000_00000000_00000000 fc2b4 162 00000000 long %00000000_00000000_00000000_00000000 fc2b8 163 cog_end ' ' ' Uninitialized variables ' fc2b8 163 i res 1 'universal fc2b8 164 x res 1 fc2b8 165 y res 1 fc2b8 166 z res 1 fc2b8 167 checksum res 1 'checksum fc2b8 168 bytemask res 1 fc2b8 169 a0 res 1 'serial autobaud/receiver ISR fc2b8 16a a1 res 1 fc2b8 16b a2 res 1 fc2b8 16c head res 1 'serial receiver buffer fc2b8 16d tail res 1 fc2b8 16e fit cog_base64 'make sure below cog_base64 ' ' '************** '* Lut code * '************** ' fc2b8 210 org $200 + lut_start fc2b8 210 lut_code ' ' ' Reset serial autobaud/receiver interrupt ' fc2b8 210 f527f403 reset_serial andn dira,#%11 'disable timing measurements for autobaud fc2bc 211 fd640025 setint1 #0 'disable int1 fc2c0 212 f606d800 mov head,#0 'reset serial buffer pointers fc2c4 213 f606da00 mov tail,#0 fc2c8 214 fd647e40 dirl #rx_pin 'disable receiver fc2cc 215 fc0c7c3f wrpin #%00_11111_0,#rx_pin 'configure rx_pin for asynchronous receive, always input fc2d0 216 fc0cf83e wrpin #%01_11110_0,#tx_pin 'configure tx_pin for asynchronous transmit, always output fc2d4 217 fd647c41 dirh #tx_pin 'enable transmitter fc2d8 218 fc068801 wrpin mths,#rx_ths 'configure rx_ths for timing high states fc2dc 219 fc068a00 wrpin mtne,#rx_tne 'configure rx_tne for timing negative edges fc2e0 21a fc1c0200 wxpin #1,#rx_tne 'report each cycle fc2e4 21b fc2c0000 wypin #0,#rx_tne 'measure fall to fall fc2e8 21c fd670020 setse1 #%110<<6+rx_tne 'set se1 to trigger on rx_tne high fc2ec 21d f607e91d mov ijmp1,#autobaud_isr 'set int1 jump vector to autobaud ISR fc2f0 21e fd640825 setint1 #4 'set int1 to trigger on se1 (rx_tne high) fc2f4 21f f547f403 or dira,#%11 'enable timing measurements for autobaud ' ' ' Attempt to get serial command ' fc2f8 220 fd62c81a get_command getct x 'reset serial timeout in case SPI program ready fc2fc 221 fa62c941 addct1 x,timeout_per fc300 222 f606cc00 mov z,#0 'reset string buffer fc304 223 fdb001d4 .byte call #get_rx 'get byte fc308 224 f20ec81b cmp x,#$1B wz 'esc? fc30c 225 ad8fd028 if_z jmp #@_start_taqoz fc310 226 f20ec804 cmp x,#$04 wz 'ctrl-d? fc314 227 ad8fca88 if_z jmp #@_start_monitor fc318 228 f91acb66 rolbyte y,z,#3 'scroll byte into 2-long/8-byte string buffer fc31c 229 f902cd64 rolbyte z,x,#0 fc320 22a f20acb48 cmp y,text_prop wz '"Prop"? fc324 22b 5d9fffdc if_nz jmp #.byte fc328 22c f20acd4c cmp z,text_txt wz '"_Txt"? fc32c 22d ad90005c if_z jmp #command_txt fc330 22e f20acd4b cmp z,text_hex wz '"_Hex"? fc334 22f ad9000b0 if_z jmp #command_hex fc338 230 f20acd4a cmp z,text_clk wz '"_Clk"? fc33c 231 ad900018 if_z jmp #command_clk fc340 232 f20acd49 cmp z,text_chk wz '"_Chk"? fc344 233 5d9fffbc if_nz jmp #.byte ' ' ' Command - check device ' fc348 234 fdb000ec command_chk call #match_device 'receive and check INA/INB filter values fc34c 235 f606c74d mov i,#text_ver 'transmit version string fc350 236 fdb001c0 call #transmit fc354 237 fd9fffa0 jmp #get_command 'get next command ' ' ' Command - clock setup ' fc358 238 fdb000dc command_clk call #match_device 'receive and check INA/INB filter values fc35c 239 fdb0011c call #get_hex 'get clock setting fc360 23a 3d9fff94 if_nc jmp #get_command 'if not hex, error, wait for another command fc364 23b f606a22e mov text_sta,#"." 'transmit acknowledgement character fc368 23c fdb001a4 call #transmit_sta fc36c 23d f746c818 zerox x,#24 'clear non-clock bits fc370 23e f602cb64 mov y,x 'switch to partial setting, but in RC fast mode fc374 23f f526ca03 andn y,#%11 fc378 240 fd62ca00 hubset y fc37c 241 ff800124 waitx ##rc_max/200 'wait 5ms fc380 242 fd67e01f fc384 243 fd62c800 hubset x 'switch to full setting fc388 244 fd9fff2c jmp #reset_serial 'restart serial at new setting, get next command ' ' ' Command - text load ' fc38c 245 fdb000a8 command_txt call #match_device 'receive and check INA/INB filter values fc390 246 f606c600 mov i,#0 'reset bit counter fc394 247 fdb00144 .chr call #get_rx 'get byte fc398 248 f99ec95b altb x,#whitechrs 'whitespace? fc39c 249 f4280164 testbn 0,x wz fc3a0 24a 5d9ffff0 if_nz jmp #.chr 'if whitespace, get another byte fc3a4 24b f96ec980 altgb x,#cog_base64 'lookup base64 value in table fc3a8 24c f8e2ca00 getbyte y fc3ac 24d f42eca07 testbn y,#7 wz 'if msb set, not base64 chr fc3b0 24e a066cc06 if_z shl z,#6 'if base64 chr, shift data buffer up 6 bits fc3b4 24f a542cd65 if_z or z,y '..or in new value fc3b8 250 a106c606 if_z add i,#6 '..add 6 into bit counter fc3bc 251 a2f6c608 if_z cmpsub i,#8 wc '..if bit counter >= 8, subtract 8, byte ready fc3c0 252 8602c966 if_z_and_c mov x,z '....get data buffer value fc3c4 253 8042c963 if_z_and_c shr x,i '....shift down to justify byte fc3c8 254 8d62c815 if_z_and_c wfbyte x '....write byte to hub fc3cc 255 89fec800 if_z_and_c movbyts x,#%%0000 '....replicate byte within long fc3d0 256 8502c968 if_z_and_c and x,bytemask '....mask current byte position fc3d4 257 8102cf64 if_z_and_c add checksum,x '....add into checksum fc3d8 258 8026d008 if_z_and_c rol bytemask,#8 '....update byte position mask fc3dc 259 ad9fffb4 if_z jmp #.chr '..loop for next chr fc3e0 25a f726da0f decmod tail,#lut_btop 'not base64 chr, repoint to prior chr fc3e4 25b fd900020 jmp #end_of_data 'done ' ' ' Command - hex load ' fc3e8 25c fdb0004c command_hex call #match_device 'receive and check INA/INB filter values fc3ec 25d fdb0008c .byte call #get_hex 'get hex byte fc3f0 25e cd62c815 if_c wfbyte x 'if hex, write byte to hub fc3f4 25f c9fec800 if_c movbyts x,#%%0000 '..replicate byte within long fc3f8 260 c502c968 if_c and x,bytemask '..mask current byte position fc3fc 261 c102cf64 if_c add checksum,x '..add into checksum fc400 262 c026d008 if_c rol bytemask,#8 '..update byte position mask fc404 263 cd9fffe4 if_c jmp #.byte '..loop for next byte (followed by end_of_data) ' ' ' End of data for text/hex load - get "~" and launch code ' fc408 264 fdb000b4 end_of_data call #get_chr 'end of data, check terminus chr fc40c 265 f20ec87e cmp x,#"~" wz 'if "~", run program fc410 266 ad90001c if_z jmp #.run fc414 267 f20ec83f cmp x,#"?" wz 'if not "?", error, wait for another command fc418 268 5d9ffedc if_nz jmp #get_command fc41c 269 f56acf52 xor checksum,csum wz 'test checksum fc420 26a a606a22e if_z mov text_sta,#"." '(okay) fc424 26b 5606a221 if_nz mov text_sta,#"!" '(error) fc428 26c fdb000e4 call #transmit_sta 'transmit status character fc42c 26d fb9ecfb2 tjnz checksum,#get_command 'if error, wait for another command fc430 26e fdb00110 .run call #reset_pins 'reset smart pins fc434 26f fcec0000 coginit #0,#$00000 'relaunch cog from $00000 ' ' ' Get and check INA/INB mask and data values ' fc438 270 f4268e01 match_device bith flags,#cmd_on 'command on, enable serial timeout for SPI program fc43c 271 f606c7fe mov i,#ina 'check INA first fc440 272 fdb00038 .pair call #get_hex 'get hex mask fc444 273 3d9ffeb0 if_nc jmp #get_command 'if not hex, error, wait for another command fc448 274 f60acd64 mov z,x wz 'got mask fc44c 275 5c06863e if_nz wrpin mtxf,#tx_pin 'if mask non-0, make tx_pin float on high fc450 276 f996c600 alts i 'point to INA/INB fc454 277 f502cdfe and z,ina 'mask INA/INB fc458 278 fdb00020 call #get_hex 'get hex data fc45c 279 3d9ffe98 if_nc jmp #get_command 'if not hex, wait for another command fc460 27a f20acd64 cmp z,x wz 'test for match fc464 27b 5d9ffe90 if_nz jmp #get_command 'if mismatch, wait for another command fc468 27c f4fec600 bitnot i,#0 wcz 'toggle INA/INB pointer fc46c 27d 3d9fffd0 if_nc jmp #.pair 'if INA checked, loop to check INB fc470 27e f606ce00 mov checksum,#0 'reset checksum fc474 27f f606d0ff mov bytemask,#$FF 'reset bytemask fc478 280 0c8c0000 _ret_ wrfast #0,#0 'ready to load data bytes into hub ' ' ' Get hex value, c=1 if hex ' fc47c 281 fdb00040 get_hex call #get_chr 'get chr fc480 282 fdb00024 call #.check 'check for hex fc484 283 3d900018 if_nc jmp #.prior 'if not hex, repoint to chr, c=0 fc488 284 f602cb64 mov y,x 'got first hex digit fc48c 285 fdb00014 .digit call #.get 'get any additional hex digits fc490 286 c882cb64 if_c rolnib y,x,#0 fc494 287 cd9ffff4 if_c jmp #.digit fc498 288 f602c965 mov x,y 'done, set result fc49c 289 fd75e06f modcz _set,0 wc 'c=1 for hex fc4a0 28a 0726da0f .prior _ret_ decmod tail,#lut_btop 'repoint to chr, exit fc4a4 28b fdb00034 .get call #get_rx 'get byte fc4a8 28c f99ec953 .check altb x,#hexchrs 'check for hex fc4ac 28d f4100164 testb 0,x wc fc4b0 28e 3d64002d if_nc ret 'if not hex, c=0 fc4b4 28f f42ec806 testbn x,#6 wz 'hex, "0".."9"? fc4b8 290 5106c809 if_nz add x,#9 'if not, make $A..$F fc4bc 291 0506c80f _ret_ and x,#$F 'isolate nibble, c=1 ' ' ' Get chr after any whitespace ' fc4c0 292 fdb00018 get_chr call #get_rx 'get byte fc4c4 293 f99ec95b altb x,#whitechrs 'whitespace? fc4c8 294 f4280164 testbn 0,x wz fc4cc 295 5d9ffff0 if_nz jmp #get_chr 'if whitespace, get another byte fc4d0 296 fd64002d ret ' ' ' Get serial byte ' fc4d4 297 fd62c81a get_rx_res getct x 'reset timer fc4d8 298 fa62c941 addct1 x,timeout_per fc4dc 299 fbcc0204 get_rx jct1 #.timeout 'timeout? fc4e0 29a f20ad96d cmp head,tail wz 'byte received? fc4e4 29b ad9ffff4 if_z jmp #get_rx 'loop until timeout or byte received fc4e8 29c faa2c96d rdlut x,tail 'get byte from circular buffer in lut fc4ec 29d 0706da0f _ret_ incmod tail,#lut_btop 'increment buffer tail fc4f0 29e f40e8e00 .timeout testb flags,#spi_ok wz 'timeout, SPI program? fc4f4 29f f4168e01 testb flags,#cmd_on wc 'command on? fc4f8 2a0 db6e85f6 if_nz_or_c djnz timeout_cnt,#get_rx_res 'if no SPI program or command on, try until 60s (serial_done follows) ' ' ' Serial done ' on entry, z=1 if SPI program ' fc4fc 2a1 fdb00044 serial_done call #reset_pins 'reset pins fc500 2a2 ad9ff574 if_z jmp #0 'if SPI program, run it, else shut down fc504 2a3 fd62c801 shut_down cogid x 'get cogid (in case jumped to from outside) fc508 2a4 fd640200 hubset #1 'set 20KHz oscillator fc50c 2a5 fd62c803 cogstop x 'shut down cog (floats pins) ' ' ' Transmit message ' fc510 2a6 f606c751 transmit_sta mov i,#text_sta 'point to status character fc514 2a7 f9b6c601 transmit setd i,#1 'set auto-increment for altgb fc518 2a8 f602cb69 mov y,a0 'wait 16 bit periods to allow host turn-around time fc51c 2a9 f046ca0e shr y,#16-4+2 'shr 16 gets clocks/bit, -4 gets 16 bits, +2 gets 4 clocks/djnz fc520 2aa fb6ecbff djnz y,#$ 'y=0 after (djnz allows interrupts, unlike waitx) fc524 2ab f96acb63 .byte altgb y,i 'get next byte of string, increment y fc528 2ac f8e2cc00 getbyte z fc52c 2ad 0b9ecc00 _ret_ tjnz z,#.send 'if zero, done fc530 2ae fc26cc3e .send wypin z,#tx_pin 'send byte fc534 2af fd64021f waitx #1 'accommodate wypin -> rdpin latency fc538 2b0 fa9ecc3e .wait rdpin z,#tx_pin wc 'wait for transmit done fc53c 2b1 cd9ffff8 if_c jmp #.wait fc540 2b2 fd9fffe0 jmp #.byte 'loop for more bytes ' ' ' Reset smart pins ' fc544 2b3 fd640025 reset_pins setint1 #0 'disable int1 fc548 2b4 f527f403 andn dira,#%11 'reset smart pins (avoids output on mode clears) fc54c 2b5 f747f61d zerox dirb,#29 '..but leave spi pins in current state fc550 2b6 fc0c0001 wrpin #0,#rx_ths 'clear rx_ths mode fc554 2b7 fc0c0000 wrpin #0,#rx_tne 'clear rx_tne mode fc558 2b8 fc0c003f wrpin #0,#rx_pin 'clear rx_pin mode fc55c 2b9 0c0c003e _ret_ wrpin #0,#tx_pin 'clear tx_pin mode fc560 2ba lut_end CON '------------------------------------------------------------------------------------------------ _clockmax = 200_000_000 ' max clock freq _clockfreq = 80_000_000 _clockfpga = 20_000_000 _cpufreq = rc_max delay1s = _cpufreq ' 1s (xtal * pll) delay10ms = _cpufreq / 100 ' 10ms delay1ms = _cpufreq / 1_000 ' 1ms delay5us = _cpufreq / 200_000 ' 5us _baud = 115_200 _bitper = (_cpufreq / _baud) << 16 + 7 ' 115200 baud, 8 bits _txmode = %0000_0000_000_0000000000000_01_11110_0 'async tx mode, output enabled for smart output _rxmode = %0000_0000_000_0000000000000_00_11111_0 'async rx mode, input enabled for smart input '------------------------------------------------------------------------------------------------ sd_ck = spi_cs 'pin SD Card clock sd_cs = spi_ck 'pin SD Card select sd_di = spi_di 'pin SD Card MOSI sd_do = spi_do 'pin SD Card MISO '------------------------------------------------------------------------------------------------ ' ASCII equates '------------------------------------------------------------------------------------------------ _CLS_ = $0C '$00 ' clear screen _BS_ = $08 _LF_ = $0A _CR_ = $0D _TAQOZ_ = $1B ' goto TAQOZ '------------------------------------------------------------------------------------------------ '------------------------------------------------------------------------------------------------ ' HUB ADDRESSES '------------------------------------------------------------------------------------------------ _HUBROM = $FC000 ' ROM $FC000 _HUBBUF = $FC000 ' overwrite Booter _HUBBUFSIZE = 80 ' RxString default size for _HUBBUF '------------------------------------------------------------------------------------------------ DAT ''============[ COG VARIABLES - SD BOOT]======================================== fc560 1c0 org $1C0 ' place the variables in cog $1C0-$1DF fc560 1c0 cmdout res 1 ' The 8b CMDxx | $40 fc560 1c1 cmdpar res 1 ' The 32b parameters fc560 1c2 cmdcrc res 1 ' The 8b CRC (must be valid for CMD0 & CMD8) fc560 1c3 cmdpar2 res 1 ' SDV1=$0, SDV2=$40000000 fc560 1c4 cmdtype res 1 ' reply is R1=1, R3=3, R7=7, else 0 fc560 1c5 reply res 1 ' R1 reply (moved to replyR1 when R3/R7 32b reply here) fc560 1c6 replyR1 res 1 ' R1 reply (8b saved when R3/R7 32b reply follows) fc560 1c7 dataout res 1 ' 8/32 bit data being shifted out fc560 1c8 bytescnt res 1 ' #bytes to send/recv fc560 1c9 bitscnt res 1 ' #bits to be shifted in/out fc560 1ca ctr1 res 1 fc560 1cb timeout res 1 ' = starttime + delay fc560 1cc spare res 1 fc560 1cd skiprun res 1 ' 1= skip load/run mbr/vol & load/no-run fname '\ 1=SDV1, 2=SDV2(byte address), 3=SDHC/SDV2(block address) fc560 1ce blocksh res 1 '/ block shift 0/9 bits fc560 1cf clustersh res 1 ' sectors/cluster SHL 'n' bits fc560 1d0 vol_begin res 1 '$0000_2000 ' Ptn0: first sector of PTN fc560 1d1 fsi_begin res 1 '$0000_2001 ' Ptn0: sector of file system info fc560 1d2 fat_begin res 1 '$0000_3122 ' Ptn0: first sector of FAT table fc560 1d3 dir_begin res 1' $0000_4000 ' Ptn0: first sector of DATA is DIR table fc560 1d4 dat_begin res 1 '$0000_4580 $0000_54C0' Ptn0: first sector of file's DATA fc560 1d5 ptn_size res 1 '$0008_0000 ' file-size 32KB = 64<<9 sectors fc560 1d6 _bufad res 1 fc560 1d7 _blocknr res 1 fc560 1d8 _sectors res 1 fc560 1d9 _entries res 1 fc560 1da bufad res 1 ' ptr sector buffer fc560 1db blocknr res 1 ' sector# fc560 1dc fname res 3 ' 8+3+1 fc560 1df _hubdata res 1 fc560 1e0 fit $1E0 ''============[ COG VARIABLES - MONITOR]======================================== fc560 1e0 org $1E0 ' place the variables in cog $1E0-$1EF ''-------[ LMM parameters, etc ]------------------------------------------------ fc560 1e0 lmm_x res 1 ' parameter passed to/from LMM routine (typically a value) fc560 1e1 lmm_f res 1 ' parameter passed to LMM routine (function options; returns unchanged) fc560 1e2 lmm_p res 1 ' parameter passed to/from LMM routine (typically a hub/cog ptr/addr) fc560 1e3 lmm_p2 res 1 ' parameter passed to/from LMM routine (typically a 2nd hub/cog address) fc560 1e4 lmm_c res 1 ' parameter passed to/from LMM routine (typically a count) ''-------[ LMM additional workareas ]------------------------------------------- fc560 1e5 lmm_w res 1 ' workarea (never saved - short term use between calls, except _HubTx) fc560 1e6 lmm_tx res 1 ' _HubTx fc560 1e7 lmm_hx res 1 ' _HubHex/_HubString fc560 1e8 lmm_hx2 res 1 ' _HubHex fc560 1e9 lmm_hc res 1 ' " fc560 1ea lmm_lx res 1 ' _HubList fc560 1eb lmm_lf res 1 ' " fc560 1ec lmm_lp res 1 ' " fc560 1ed lmm_lp2 res 1 ' " fc560 1ee lmm_lc res 1 ' " fc560 1ef lmm_bufad res 1 ' _HubRxString fc560 1f0 fit $1F0 ''=======[ ^^^^^ End of COG Variables ^^^^^ ]=================================== '' +--------------------------------------------------------------------------+ '' | Cluso's Minimal SD Boot Test for P2 (c)2012-2018 "Cluso99" (Ray Rodrick)| '' +--------------------------------------------------------------------------+ '' RR20180505 v128a add into ROM_v131b ''============================[ CON ]============================================================ CON _csum = ("P" + "r"<<8 + "o"<<16 + "p"<<24) ' "Prop" checksum (reversed) _csum2 = ("P" + "r"<<8 + "o"<<16 + "P"<<24) ' "ProP" checksum (reversed) _fname1a = ("_" + "B"<<8 + "O"<<16 + "O"<<24) '\\ filename... _fname1b = ("T" + "_"<<8 + "P"<<16 + "2"<<24) '|| 8.3 +$00 _fname1c = ("B" + "I"<<8 + "X"<<16 + $00<<24) '// _fname2c = ("B" + "I"<<8 + "Y"<<16 + $00<<24) '// mbr_begin = 0 ' first sector of disk $0000_0000 '------------------------------------------------------------------------------------------------ ' COG & LUT & HUB ADDRESSES '------------------------------------------------------------------------------------------------ hubdata = $0_0000 ' expands up (512byte sectors) max_size = (512-16)*1024 ' max file_size(bytes) that can be loaded cog_start0 = $000 ' cog code start cog_len = 512-16 ' cog code length cog_len80 = 512/4 ' 512 bytes (sector) '------------------------------------------------------------------------------------------------ ' SD Commands & Responses... '------------------------------------------------------------------------------------------------ ' Command Argument Response/Data Description CMD0 = 0 +$40 ' 0 R1 - GO_IDLE_STATE *Reqs valid CRC ' CMD1 = 1 +$40 ' 0 R1 - SEND_OP_COND ACMD41 = 41 +$40 ' $4000_0000 R1 - APP_SEND_OP_COND *Reqs CMD55 first CMD8 = 8 +$40 ' 0 R1+R7 - SEND_IF_COND *Reqs valid CRC CMD9 = 9 +$40 ' 0 R1 Y SEND_CSD CMD10 = 10 +$40 ' 0 R1 Y SEND_CID ' CMD12 = 12 +$40 ' 0 R2 - STOP_TRANSMISSION CMD16 = 16 +$40 ' BlkLen[31:0] R1 - SET_BLOCKLEN CMD17 = 17 +$40 ' Addr[31:0] R1 Y READ_SINGLE_BLOCK ' CMD18 = 18 +$40 ' Addr[31:0] R1 Y READ_MULTIPLE_BLOCK ' CMD23 = 23 +$40 ' NoBlks[15:0] R1 - SET_BLOCK_COUNT ' ACMD23 = 23 +$40 ' NoBlks[22:0] R1 - SET_WR_BLOCK_ERASE_COUNT *Reqs CMD55 first ' CMD24 = 24 +$40 ' Addr[31:0] R1 Y* WRITE_BLOCK ' CMD25 = 25 +$40 ' Addr[31:0] R1 Y* WRITE_MULTIPLE_BLOCK CMD55 = 55 +$40 ' 0 R1 - APP_CMD *Prefix for ACMD41/ACMD23 CMD58 = 58 +$40 ' 0 R1+R3 - READ_OCR ' R1 response: $FF = busy/wait (0-8 bytes?) ' b7: 0 (msb first) ' b6: Parameter Error ' b5: Address Error ' b4: Erase Sequence Error ' b3: Command CRC Error ' b2: Illegal Command ' b1: Erase Reset ' b0: In Idle State ' R1b response: ??? ' R3 response: R1 + OCR(32b) ' R7 response: R1($01) + 32b(b11..b0 = $1AA = SDC V2 2V7-3V6, else reject) ' ' DataPacket: DataToken(1byte) + DataBlock(1-2048bytes) + CRC(2bytes) ' DataToken: $FE = CMD17/18/24 (read'1'block/read'n'blocks/write'1'block) ' $FC = CMD25 (write'n'blocks) ' $FD = CMD25 StopToken (Single byte packet without data or CRC) ' ErrorToken: Single Byte Reply ' b7-b5: 000 ' b4: Card Locked ' b3: Out of Range ' b2: Card ECC failed ' b1: CC Error ' b0: Error ' DataResponse: ' b7-b4: xxx0 ' $x5: Data Accepted ' $xB: Data Rejected - CRC Error ' $xD: Data Rejected - Write Error DAT ''################################################################################################ ''## SD Card - HUBEXEC code... ## ''################################################################################################ fc560 orgh '+-------[ SD: Initialise/Locate/Load/Run a file from SD ]---------------------+ <--- SD: init/locate/load/run a file ---> '+ On Entry: + '+ fname[3]: filename[11] 8+3 without "." (will be $0 terminated) + '+ Call Format: + '+ CALL #@_Run_SDfile ' + < call: init/locate/load/run a file > '+ On Return: + '+ "NZ" if error, else does not return + '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ fc560 fdb00040 _Start_SDcard call #@_SDcard_Init ' initialise & read CSD/CID fc564 f6079a00 mov skiprun, #0 ' load/run MBR/VOL code fc568 adb00174 if_e call #@_readMBR ' read MBR/VOL/FSI/FAT fc56c adb002a0 if_e call #@_readDIR ' read directory for filenames '' mov skiprun, #0 ' load/run (already 0) fc570 adb0038c if_e call #@_readFILE ' read/load/run the file fc574 fd800100 JMP #try_serial ' failed: so go back and try serial '+-----------------------------------------------------------------------------+ fc578 fdb00028 _Run_SDfile call #@_SDcard_Init ' initialise & read CSD/CID '' mov skiprun, #1 ' do not load/run MBR/VOL code fc57c adb0015c if_e call #@_readMBR1 ' read MBR/VOL/FSI/FAT (don't run) fc580 adb002bc if_e call #@_searchDIR ' search dir for fc584 f6079a00 mov skiprun, #0 ' load/run fc588 adb00374 if_e call #@_readFILE ' read/load/run the file fc58c fd64002d RET ' return "NZ" = failed, "Z" if loaded ok '+-----------------------------------------------------------------------------+ fc590 fdb00010 _Load_SDfile call #@_SDcard_Init ' initialise & read CSD/CID '' mov skiprun, #1 ' do not load/run MBR/VOL code fc594 adb00144 if_e call #@_readMBR1 ' read MBR/VOL/FSI/FAT (don't run) fc598 adb002a4 if_e call #@_searchDIR ' search dir for '' mov skiprun, #1 ' do not load/run (already 1) fc59c adb00360 if_e call #@_readFILE ' read/load the file fc5a0 fd64002d RET ' return "NZ" = failed, "Z" if loaded ok '+-----------------------------------------------------------------------------+ '+-------[ SD Card Initialisation ]--------------------------------------------+ <--- SD initialisation ---> '+ On Entry: + '+ Call Format: + '+ CALL #@_SDcard_Init ' + < call: sd initialise > '+ On Return: + '+ hub $0 = CSD[16] + CID[16] ' csd/cid data + '+ Returns "Z" if ok, "NZ" if error + '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ SD/SDHC/sdxc SPI Initialisation + '+-----------------------------------------------------------------------------+ '+ Send >74 clocks with /CS=1 & DI=1 starting & ending with CLK=0 + '+-----------------------------------------------------------------------------+ fc5a4 f607be00 _SDcard_Init mov _hubdata, #hubdata ' init hub data ptr=$0 fc5a8 fd63ec2a push pa '\ save pa fc5ac f607ec3c mov pa, #sd_cs '| ensure we have an SD card fc5b0 fdbffb9c call #@check_pullup '| (pullup on cs) fc5b4 fd63ec2b pop pa '| restore pa fc5b8 3d9004b8 if_nc jmp #@_fail '_pullup '/ fc5bc fd647859 drvh #sd_cs ' cs=1 & output fc5c0 fd647a58 drvl #sd_ck ' ck=0 & output fc5c4 fd647659 drvh #sd_di ' di=1 & output fc5c8 f60794c0 mov ctr1, #(96*2) fc5cc ff800000 .count waitx ##delay5us '\ 5us+5us (ie 100KHz) fc5d0 fd652c1f fc5d4 fd647a4f outnot #sd_ck '| CLK=0-->1-->0 fc5d8 fb6f95fc djnz ctr1, #.count '/ fc5dc ff800000 waitx ##delay5us ' CLK=0 (idle) & /CS=1 fc5e0 fd652c1f '+-----------------------------------------------------------------------------+ '+ Software Reset: + '+ CMD0, PAR=$0, CRC=$95, REPLY=R1($01) + '+-----------------------------------------------------------------------------+ fc5e4 fd63961a .Command0 getct timeout '\ set timeout up to CMD9 fc5e8 ff000249 add timeout, ##delay10ms '/ fc5ec f10797e0 fc5f0 f607940a mov ctr1, #10 ' try a few times fc5f4 f6078040 .again0 mov cmdout, #CMD0 fc5f8 f6078200 mov cmdpar, #0 fc5fc f6078495 mov cmdcrc, #$95 '+-----------------------------------------------------------------------------+ fc600 fdb003c0 call #@_cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ fc604 3f00e4e1 if_nc add timeout, ##delay1s ' increase timeout to 1s fc608 31079780 '\ $01(idle): SD/MMC, not fully validated fc60c 3d900010 if_nc jmp #.Command8 '/ $00(good): (dane card response) '+-----------------------------------------------------------------------------+ fc610 ff800000 waitx ##delay5us ' delay 5us fc614 fd652c1f fc618 fb6f95f6 djnz ctr1, #.again0 ' n: try again? fc61c fd900454 jmp #@_fail '00 ' '+=============================================================================+ ' we know we now have an SD/MMC card but its not fully validated yet... '+-----------------------------------------------------------------------------+ '+ Check Voltage: + '+ CMD8, PAR=$1AA, CRC=$87, REPLY=R1($01)+R7($xx1AA) ($05=try SDV1) + '+-----------------------------------------------------------------------------+ fc620 f6078048 .Command8 mov cmdout, #CMD8 fc624 f60783aa mov cmdpar, #$1AA fc628 f6078487 mov cmdcrc, #$87 '+-----------------------------------------------------------------------------+ fc62c fdb00394 call #@_cmdR1R7 ' /CS=0, send cmd, recv R1+R7, /CS=1 '+-----------------------------------------------------------------------------+ fc630 ed90001c if_c_or_z jmp #.illegal ' j if <> $01 (not idle) fc634 ff000007 .idle and reply, ##$FFF '\ fc638 f5078bff fc63c f20f8baa cmp reply, #$1AA wz '/ R7[11:0]=$1AA ? fc640 ff200000 mov cmdpar2, ##$40000000 ' preset for SDV2 fc644 f6078600 fc648 5d900428 if_ne jmp #@_fail '98 ' n: unknown R7 fc64c fd90000c jmp #.Command55 ' y: CMD55+ACMD41($4000_0000) fc650 f20f8c05 .illegal cmp replyR1, #$05 wz ' $05(illegal cmd) ? fc654 5d90041c if_ne jmp #@_fail '08 ' <>$01/$05 (not idle/illegal) fc658 f6078600 mov cmdpar2, #0 ' try SDV1 ' CMD55+ACMD41($0) fall thru '+-----------------------------------------------------------------------------+ '+ Prefix to ACMD41 & ACMD23: + '+ CMD55, PAR=$0, CRC=$xx, REPLY=R1($01) + '+-----------------------------------------------------------------------------+ fc65c f6078077 .Command55 mov cmdout, #CMD55 ' fc660 f6078200 mov cmdpar, #0 ' '+-----------------------------------------------------------------------------+ fc664 fdb00354 call #@_cmdRZA41 ' /CS=0, send cmd, recv R1, /CS=0(ena) '+-----------------------------------------------------------------------------+ fc668 ed900408 if_c_or_z jmp #@_fail '55 ' <>$01 (not idle) ' fall thru '+-----------------------------------------------------------------------------+ '+ Check SDV1/SDV2: (follows CMD55) + '+ ACMD41, PAR=$0, CRC=$xx, REPLY=R1($00) SD-V1 + '+ ACMD41, PAR=$40000000, CRC=$xx, REPLY=R1($00) SD-V2 + '+-----------------------------------------------------------------------------+ fc66c f6078069 .CommandA41 mov cmdout, #ACMD41 ' fc670 f60383c3 mov cmdpar, cmdpar2 ' SDV1=0 / SDV2=$40000000 '+-----------------------------------------------------------------------------+ fc674 fdb0034c call #@_cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ fc678 1d9fffe0 if_nc_and_nz jmp #.Command55 ' =$01(busy): CMD55+CMD41 again fc67c cd9003f4 if_c jmp #@_fail '41 ' <>$00/$01: error fc680 f20f8600 cmp cmdpar2, #0 wz ' SDV1 ? fc684 a6079c09 if_z mov blocksh, #9 ' y: #1 SDV1(byte address) fc688 ad90001c if_z jmp #.Command16 ' y: SDV1 does not use CMD58 ' SDV2 fall thru '+-----------------------------------------------------------------------------+ '+ Check OCR CCS bit: + '+ CMD58, PAR=$0, CRC=$xx, REPLY=R1($00)+R3(b30=1) + '+-----------------------------------------------------------------------------+ fc68c f607807a .Command58 mov cmdout, #CMD58 ' SDHC ? fc690 f6078200 mov cmdpar, #0 ' '+-----------------------------------------------------------------------------+ fc694 fdb0032c call #@_cmdR1R3 ' /CS=0, send cmd, recv R1+R3, /CS=1 '+-----------------------------------------------------------------------------+ fc698 dd9003d8 if_c_or_nz jmp #@_fail '58 ' <>$00(good): error fc69c f42f8a1e testbn reply, #30 wz ' bit30=CCS=1? $40000000? fc6a0 a6079c09 if_z mov blocksh, #9 ' n: #2 SDV2(byte address) fc6a4 56079c00 if_nz mov blocksh, #0 ' y: #3 SDHC/SDV2(block address) '' if_nz jmp #.Command9x ' y: does not req cmd16? ????????? ' SDV2(byte) fall thru '+-----------------------------------------------------------------------------+ '+ Force block size to 512 bytes: + '+ CMD16, PAR=$200, CRC=$xx, REPLY=R1($00) + '+-----------------------------------------------------------------------------+ fc6a8 f6078050 .Command16 mov cmdout, #CMD16 ' force blocksize=512bytes fc6ac ff000001 mov cmdpar, ##512 ' 512 bytes fc6b0 f6078200 '+-----------------------------------------------------------------------------+ fc6b4 fdb0030c call #@_cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ fc6b8 1d9fffec if_nc_and_nz jmp #.Command16 ' =$01(idle): again fc6bc dd9003b4 if_c_or_nz jmp #@_fail '16 ' <>$00(good): error '+-----------------------------------------------------------------------------+ fc6c0 f603addf .Command9x mov _bufad, _hubdata ' where to store data fc6c4 f603b5d6 mov bufad, _bufad ' where to store CSD/CID '+-----------------------------------------------------------------------------+ '+ Read CSD register (16 bytes): + '+ CMD9, PAR=$0, CRC=$xx, REPLY=R1($00) + '+-----------------------------------------------------------------------------+ fc6c8 f6078049 .Command9 mov cmdout, #CMD9 ' read CSD register fc6cc fdb002a4 call #@_readREG ' '+-----------------------------------------------------------------------------+ '+ Read CID register (16 bytes): + '+ CMD10, PAR=$0, CRC=$xx, REPLY=R1($00) + '+-----------------------------------------------------------------------------+ fc6d0 f607804a .Command10 mov cmdout, #CMD10 ' read CID register fc6d4 fdb0029c call #@_readREG ' '+-----------------------------------------------------------------------------+ fc6d8 0d6c1e6f _RET_ MODZ _set wz ' "Z" = success '+=============================================================================+ '+-------[ SD: Read MBR/VBR/FSI/FAT ]------------------------------------------+ <--- SD: read mbr/vol/fsi/fat ---> '+ On Entry: + '+ skiprun: #0 = load/run boot code if found on MBR/VOL + '+ #1 = do not load/run boot code on MBR/VOL + '+ Call Format: + '+ CALL #@_readMBR ' + < call: read mbr/vol/fsi/fat > '+ On Return: + '+ DOES NOT RETURN if skiprun = #0 and code found on MBR/VOL + '+ Returns: "Z" if ok, "NZ" if error + '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Read MBR/VBR (Sector 0): + '+-----------------------------------------------------------------------------+ fc6dc f6079a01 _readMBR1 mov skiprun, #1 ' do not load/run MBR/VOL code fc6e0 f607ae00 _readMBR mov _blocknr, #mbr_begin ' VBR/MBR = SECTOR 0 fc6e4 fdb00268 call #@_readSECTOR ' read sector fc6e8 fd639a31 skip skiprun ' skips next instr if #1 fc6ec fdb001e0 call #@_validateCSUM ' valid -> load & run '+-----------------------------------------------------------------------------+ '+ Validate MBR (PTN0 table & signature) + '+ +$1BE[16] = = Ptn0 Table... + '+ verify +$1BE+$0[1] = $00/$80 = Ptn0 State + '+ verify +$1BE+$4[1] = $0B/$0C = Ptn0 Type + '+ calc +$1BE+$8[4] = = Ptn0 StartSector# --> vol_begin + '+ calc +$1BE+$C[4] = = Ptn0 SectorSize --> ptn_size + '+ verify +$1FE[2] = $55AA = signature + '+-----------------------------------------------------------------------------+ fc6f0 f603b5d6 ._validateMBR mov bufad, _bufad ' MBR hub addr fc6f4 f107b5be add bufad, #$1BE ' offset to PTN0 table fc6f8 fac38bda rdbyte reply, bufad ' ptn_state fc6fc f5078a7f and reply, #$7F fc700 f20f8a00 cmp reply, #0 wz ' $00/80? inactive/active fc704 5d90036c if_ne jmp #@_fail '_mbr ' fc708 f107b404 add bufad, #$4 ' offset to ptn_type fc70c fac38bda rdbyte reply, bufad ' ptn_type fc710 f20f8a0c cmp reply, #$0C wz ' $0C=FAT32(LBA) fc714 520f8a0b if_ne cmp reply, #$0B wz ' $0B=FAT32(<=2TB) '''' if_ne cmp reply, #$07 wz ' $07=exFAT Do not allow!!! fc718 5d900358 if_ne jmp #@_fail '_mbr ' fc71c f107b43c add bufad, #($1FE-$1BE-$4) ' offset to $55AA signature fc720 fae38bda rdword reply, bufad ' read fc724 ff000055 cmp reply, ##$AA_55 wz ' we read it reversed! fc728 f20f8a55 fc72c 5d900344 if_ne jmp #@_fail '_mbr ' fc730 f603b5d6 mov bufad, _bufad ' MBR hub addr fc734 f107b5be add bufad, #$1BE ' offset to PTN0 table '+-----------------------------------------------------------------------------+ '+ Calculate the raw sector address (LBA) for the VOL sector (vol_begin)... + '+ vol_begin = LBA begin ptn0 $1BE+$08[4] (reversed & not long aligned!!!)+ '+-----------------------------------------------------------------------------+ fc738 f107b408 add bufad, #$08 ' offset to start sector LBA fc73c fb03a1da rdlong vol_begin, bufad ' read '+-----------------------------------------------------------------------------+ '+ Calculate the partition size in sectors + '+ ptn_size = #sectors in ptn0 $1BE+$0C[4] (reversed & not long aligned!!!)+ '+-----------------------------------------------------------------------------+ fc740 f107b404 add bufad, #($0C-$08) ' offset to PTN0 size fc744 fb03abda rdlong ptn_size, bufad ' read '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Read VOL (Sector x): + '+-----------------------------------------------------------------------------+ fc748 f603afd0 ._readVOL mov _blocknr, vol_begin ' VOL SECTOR# fc74c fdb00200 call #@_readSECTOR ' read sector fc750 fd639a31 skip skiprun ' skips next instr if #1 fc754 fdb00178 call #@_validateCSUM ' valid -> load & run '+-----------------------------------------------------------------------------+ ' Validate VOL... + ' verify +$00B[2] = 512 = #Bytes/Sector + ' calc +$00D[1] = = #Sectors/Cluster 64? --> clustersh + ' calc +$00E[2] = #ResvSectors --> PTN0RESV + ' verify +$010[1] = 2 = #NoOfFATs PTN0NFATS + ' ??? +$020[4] = #Sectors/PTN --> =ptn_size? + ' calc +$024[4] = #Sectors/FAT --> PTN0SECFAT + ' calc +$030[2] = #FileSystemInfo --> fsi_begin + ' verify +$1FE[2] = $55AA = signature + ' + ' calc fat_begin = vol_begin + PTN0RESV + ' calc dir_begin = fat_begin + (PTN0SECFAT * 2) + '+-----------------------------------------------------------------------------+ fc758 f603b5d6 ._validateVOL mov bufad, _bufad ' VOL hub locn fc75c f107b40b add bufad, #$0B '\ offset to bytes/sector fc760 fae38bda rdword reply, bufad '| read fc764 ff000001 cmp reply, ##512 wz '| fc768 f20f8a00 fc76c 5d900304 if_ne jmp #@_fail '_vol '/ fc770 f107b402 add bufad, #($0D-$0B) ' offset to #Sectors/Cluster fc774 fac39fda rdbyte clustersh, bufad '\ calc as shift left 'n' fc778 f7839fcf encod clustersh '/ fc77c f107b401 add bufad, #($0E-$0D) ' offset to #ResvSectors fc780 fae3a5da rdword fat_begin, bufad '\ start of FAT table fc784 f103a5d0 add fat_begin, vol_begin '/ fc788 f107b402 add bufad, #($10-$0E) '\ offset to #nooffats fc78c fac38bda rdbyte reply, bufad '| read fc790 f20f8a02 cmp reply, #2 wz '| $02 PTN0NFATS fc794 5d9002dc if_ne jmp #@_fail '_vol '/ fc798 f107b414 add bufad, #($24-$10) ' offset to #Sectors/FAT fc79c fb03a7da rdlong dir_begin, bufad '\ start of DATA (DIR table) fc7a0 f067a601 shl dir_begin, #1 '| *2 fc7a4 f103a7d2 add dir_begin, fat_begin '/ +base fc7a8 f107b40c add bufad, #($30-$24) ' offset to #FileSystemSector fc7ac fae3a3da rdword fsi_begin, bufad ' read fc7b0 f103a3d0 add fsi_begin, vol_begin ' add vol_begin fc7b4 f107b5ce add bufad, #($1FE-$30) ' offset to $55AA signature fc7b8 fae38bda rdword reply, bufad ' read fc7bc ff000055 cmp reply, ##$AA_55 wz ' we read it reversed! fc7c0 f20f8a55 fc7c4 5d9002ac if_ne jmp #@_fail '_vol ' '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Read FSI (Sector x): + '+-----------------------------------------------------------------------------+ fc7c8 f603afd1 ._readFSI mov _blocknr, fsi_begin ' FSI SECTOR# fc7cc fdb00180 call #@_readSECTOR ' read sector '+-----------------------------------------------------------------------------+ '+ Validate FSI... + '+ verify +$000[4] = "RRaR" = signature + '+ verify +$1E4[4] = "rrAa" = signature + '+ verify +$1FE[2] = $55AA = signature + '+-----------------------------------------------------------------------------+ fc7d0 f603b5d6 ._validateFSI mov bufad, _bufad ' FSI hub locn fc7d4 fb038bda rdlong reply, bufad ' read fc7d8 ff20b0a9 cmp reply, ##$41615252 wz ' "RRaA" signature (reversed) fc7dc f20f8a52 fc7e0 f107b5e4 add bufad, #$1E4 ' offset to signature fc7e4 fb038bda rdlong reply, bufad ' read fc7e8 af30a0b9 if_e cmp reply, ##$61417272 wz ' "rrAa" signature (reversed) fc7ec a20f8a72 fc7f0 f107b41a add bufad, #($1FE-$1E4) ' offset to signature fc7f4 fae38bda rdword reply, bufad ' read fc7f8 af000055 if_e cmp reply, ##$AA_55 wz ' $55AA signature (reversed) fc7fc a20f8a55 fc800 5d900270 if_ne jmp #@_fail '_fsi ' '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Read FAT (Sector x): + '+-----------------------------------------------------------------------------+ fc804 f603afd2 ._readFAT mov _blocknr, fat_begin ' FAT SECTOR# fc808 fdb00144 call #@_readSECTOR ' read sector '+-----------------------------------------------------------------------------+ '+ Validate FAT... + '+ nothing to validate + '+-----------------------------------------------------------------------------+ fc80c 0d6c1e6f _RET_ MODZ _set wz ' "Z" = success '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ Read DIR (n Sectors): Search for "<_fname/_fname2>" + '+-----------------------------------------------------------------------------+ fc810 ff27a7a1 _readDIR mov fname, ##_fname1a ' copy _fname1 -> fname fc814 f607b85f fc818 ff19282f mov fname+1, ##_fname1b ' fc81c f607bb54 fc820 ff002c24 mov fname+2, ##_fname1c ' fc824 f607bd42 fc828 fdb00014 call #@_searchDIR ' search dir for fc82c ad64002d if_e RET ' return "Z" = found fc830 ff002ca4 mov fname+2, ##_fname2c ' new fname ext fc834 f607bd42 fc838 fdb00004 call #@_searchDIR ' search dir for fc83c fd64002d RET ' return "Z" = found, else "NZ" '+=============================================================================+ '+-------[ SD: Search Root Directory for <_fname> entry ]----------------------+ <--- SD: search root directory ---> '+ On Entry: + '+ fname[3]: filename[11] 8+3 without "." + '+ Call Format: + '+ CALL #@_searchDIR ' + < call: search root directory > '+ On Return: + '+ "Z" if found, and sets + '+ dat_begin = first native sector of file's data + '+ _sectors = file size in bytes + '+ "NZ" if not found / error + '+-----------------------------------------------------------------------------+ fc840 ff007fff _searchDIR and fname+2, ##$00FFFFFF ' 12th char must be $00 fc844 f507bdff fc848 f603afd3 mov _blocknr, dir_begin ' DIR SECTOR# fc84c f9c3b1cf decod _sectors, clustersh ' max sectors to scan (1 cluster) fc850 fdb000fc .search_next call #@_readSECTOR ' read sector '+-----------------------------------------------------------------------------+ '+ Walk Directory: (read DIR sectors) + '+ 16 x 32byte DIR(fname) entries per DIR sector + '+ +$00[1] = $00 = empty + '+ => $80 = deleted file + '+ search +$00[11] = 8.3 filename + '+ verify +$0B[1] = FileAttrib AND $D8,check $00 + '+ $01=read,02=hidden,04=system,08=volume,0F=longfile,10=dir,20=archive+ '+ calc +$14[2] = FAT32: 1st cluster# HI -\-> cluster + '+ calc +$1A[2] = FAT32: 1st cluster# LO -/ + '+ calc +$1C[4] = FAT32: FileSize in bytes --> file_size + '+ calc dat_begin = dir_begin + ((cluster-2)<<6) + '+-----------------------------------------------------------------------------+ ' scan dir sector for files... fc854 f607b210 .walk_dir mov _entries, #16 ' 16*32byte file entries fc858 f603b5d6 mov bufad, _bufad ' dir hub locn ' scan this sector for filename entry... fc85c fb038bda .scan rdlong reply, bufad '\ check this entry fc860 f20f8a00 cmp reply, #0 wz '| $0 = empty? fc864 5d900004 if_ne jmp #.check '| n: fc868 0d6c006f _RET_ MODZ _clr wz '/ return "NZ" = not found fc86c f20b8bdc .check cmp reply, fname wz '| check fname... fc870 f107b404 add bufad, #4 '| fc874 fb038bda rdlong reply, bufad '| fc878 a20b8bdd if_e cmp reply, fname+1 wz '| fc87c f107b404 add bufad, #4 '| fc880 fb038bda rdlong reply, bufad '| fc884 ff6c7fff and reply, ##$D8FFFFFF '| check atts b7+6+4+3 fc888 f5078bff fc88c a20b8bde if_e cmp reply, fname+2 wz '| fc890 ad900010 if_e jmp #.found '/ found! fc894 f107b418 add bufad, #(32-8) ' next entry fc898 fb6fb3f0 djnz _entries, #.scan ' "NZ" not found this sector '+-----------------------------------------------------------------------------+ fc89c f107ae01 add _blocknr, #1 ' next sector# fc8a0 0b6fb1eb _RET_ djnz _sectors, #.search_next ' return "NZ" = not found '+-----------------------------------------------------------------------------+ '+ set: cluster = +$14[2] +$1A[2] + '+ filesize = +$1C[4] + '+ sector = ((cluster-2)< '+ On Entry: + '+ dat_begin = first native sector of file's data + '+ _sectors = file size in bytes + '+ Call Format: + '+ CALL #@_readFILE ' + < call: load/run file > '+ On Return: + '+ "NZ" if error, else does not return + '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Read FILE (n Sectors): File "<_fname/_fname2>" + '+-----------------------------------------------------------------------------+ fc900 f603afd4 _readFILE mov _blocknr, dat_begin ' DAT SECTOR# ' convert _sectors = file_size (bytes) into sectors to read fc904 ff0003e0 fle _sectors, ##max_size ' limit max size to load fc908 f327b000 fc90c f107b1ff add _sectors, #511 ' +sector if extra bytes fc910 f047b009 shr _sectors, #9 ' sectors=file_size/512 ' load file's data - multiple sector(s) fc914 fdb00038 call #@_readSECTOR ' read sector fc918 fb67b002 djz _sectors, #.done fc91c fdb00024 .nextsector call #@_readnxtSECTOR ' read sector(s) fc920 fb6fb1fe djnz _sectors, #.nextsector fc924 f20f9a01 .done cmp skiprun, #1 wz ' skip running? fc928 ad64002d if_e RET ' return "Z" = successful load ' else fall thru & run '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ' load Cog & jmp #$000 fc92c fd67de28 ._success setq #cog_len-1 ' length -1 fc930 fb0001df rdlong cog_start0, _hubdata ' copy loaded code into cog fc934 fd800000 jmp #$0 ' execute loaded cog code '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ' load cog & jmp #$020 fc938 fd64fe28 _success80 setq #cog_len80-1 ' length -1 fc93c fb0001df rdlong cog_start0, _hubdata ' copy loaded code into cog fc940 fd800020 jmp #$020 ' execute loaded cog code from $080+ '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ '+-----------------------------------------------------------------------------+ '+ Read Sector: + '+-----------------------------------------------------------------------------+ fc944 f107ae01 _readnxtSECTOR add _blocknr, #1 ' next sector# fc948 ff000001 _readnxtSLOT add _bufad, ##512 ' next data slot fc94c f107ac00 fc950 f603b7d7 _readSECTOR mov blocknr, _blocknr ' sector# fc954 f603b5d6 mov bufad, _bufad ' where to store data '+-----------------------------------------------------------------------------+ '+ Read Block/Sector: (512 bytes) + '+ CMD17, PAR=blocknr, CRC=$xx, REPLY=R1($??) +n*$FF +($FE+block+CRC16) + '+-----------------------------------------------------------------------------+ fc958 ff000001 .Command17 mov bytescnt, ##512 ' read block (no. bytes) fc95c f6079000 fc960 f6078051 mov cmdout, #CMD17 ' fc964 f60383db mov cmdpar, blocknr ' fc968 f06383ce shl cmdpar, blocksh ' <<0 or <<9 '+-----------------------------------------------------------------------------+ fc96c fdb0000c call #@_readBLOCK ' read 512 bytes '+-----------------------------------------------------------------------------+ fc970 fd64002d RET ' "Z" = success '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ Read Block/Sector: (512 bytes) + '+ CMD9, PAR=$0, CRC=$xx, REPLY=R1($00) + '+ CMD10, PAR=$0, CRC=$xx, REPLY=R1($00) + '+ CMD17, PAR=blocknr, CRC=$xx, REPLY=R1($??) +n*$FF +($FE+block+CRC16) + '+-----------------------------------------------------------------------------+ fc974 f6079010 _readREG mov bytescnt, #16 ' CMD9,10: CSD,CID register fc978 f6078200 mov cmdpar, #0 ' PAR=$0, 16 bytes fc97c _readBLOCK ' CMD17: PAR=sector, 512 bytes fc97c fd63961a getct timeout '\ set timeout for cmd9,10,17 fc980 ff00e4e1 add timeout, ##delay1s '/ fc984 f1079780 '+-----------------------------------------------------------------------------+ fc988 fdb00030 call #@_cmdRZtoken ' /CS=0, send cmd, recv R1, /CS=0(ena) fc98c 5d9000e4 if_nz jmp #@_fail '17 ' <>$00(good): error '+-----------------------------------------------------------------------------+ fc990 fdb00064 call #@_getreply ' n*$FF+$FE fc994 f20f8afe cmp reply, #$FE wz ' $FE=valid Data Token fc998 5d9000d8 if_nz jmp #@_fail '97 ' '+-----------------------------------------------------------------------------+ fc99c fdb0009c .readbyte call #@_recvbyte ' read data byte fc9a0 fc438bda wrbyte reply, bufad ' save byte fc9a4 f107b401 add bufad, #1 ' bufad++ fc9a8 fb6f91fc djnz bytescnt, #.readbyte ' byte-- fc9ac fdb0008c call #@_recvbyte ' read CRC16 1/2 fc9b0 fdb00088 call #@_recvbyte ' read CRC16 2/2 ' NOTE: CRC16 not checked - do we want to do this? ?????????? '' outl #sd_ck ' CLK=0 (idle) already=0 fc9b4 fd647849 outh #sd_cs ' /CS=1 (disable) fc9b8 0d6c1e6f _RET_ MODZ _set wz ' "Z" = success '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ SEND: CMDx, PARx, CRCx, GET REPLY + '+-----------------------------------------------------------------------------+ fc9bc _cmdRZA41 ' CMD55: R1 response fc9bc _cmdRZtoken ' CMD9,10,17,24: R1+$FE response fc9bc f6078801 mov cmdtype, #1 ' returns w /CS=0(ena) fc9c0 fd900004 jmp #@_cmdxx ' fc9c4 _cmdR1R3 ' CMD58: R1+R3 response fc9c4 _cmdR1R7 ' CMD8: R1+R7 response fc9c4 _cmdR1 ' CMD0,A41,16: R1 response fc9c4 f6078800 mov cmdtype, #0 ' returns w /CS=1(disabled) fc9c8 _cmdxx ' '+-----------------------------------------------------------------------------+ fc9c8 fd647848 outl #sd_cs ' /CS=0 (enable) '+-----------------------------------------------------------------------------+ fc9cc fdb0006c call #@_sendFF ' send $FF byte first fc9d0 f6038fc0 mov dataout, cmdout ' CMD fc9d4 fdb00068 call #@_sendbyte ' send cmd byte fc9d8 f6038fc1 mov dataout, cmdpar ' Parameter fc9dc fdb00054 call #@_sendlong ' send 4 bytes (MSB first) fc9e0 f6038fc2 mov dataout, cmdcrc ' CRC fc9e4 fdb00058 call #@_sendbyte ' send crc byte '+-----------------------------------------------------------------------------+ fc9e8 fdb0000c call #@_getreply ' recv R1/R1+R3/R1+R7/RZ..+Token '+-----------------------------------------------------------------------------+ '' outl #sd_ck ' CLK=0 (idle) already=0 fc9ec fd638831 skip cmdtype '\ skips next instr if #1 fc9f0 fd647849 outh #sd_cs '| /CS=1(disable) if reqd fc9f4 fd64002d RET '/ else /CS=0 cmdRZA41/cmdRZtoken '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ READ REPLY: R1/R1+R3/R1+R7/R1+token + '+-----------------------------------------------------------------------------+ fc9f8 fdb00040 _getreply call #@_recvbyte ' recv R1 byte fc9fc f20f8aff cmp reply, #$FF wz ' reply=$FF=busy ? fca00 5d900010 if_nz jmp #.doneR1 ' n: ' timeout set in CMD0(for CMD0,8,55,A41,58,16) and CMD9,10,17(readblock) fca04 fd638c1a getct replyR1 '\ timeout ? fca08 f2138dcb cmp replyR1, timeout wc '| c if < timeout fca0c cd9fffe8 if_c jmp #@_getreply '| n: try again fca10 fd900060 jmp #@_fail '90 '/ timeout: fca14 f6038dc5 .doneR1 mov replyR1, reply ' save R1/Token reply '+-----------------------------------------------------------------------------+ fca18 f20f8048 cmp cmdout, #CMD8 wz fca1c 520f807a if_nz cmp cmdout, #CMD58 wz fca20 5d900004 if_nz jmp #.end ' ret if not CMD8/CMD58 '+-----------------------------------------------------------------------------+ fca24 fdb00008 call #@_recvlong ' R7=CMD8=volts/R3=CMD58=OCR '+-----------------------------------------------------------------------------+ fca28 .end '\ returns with... '| nc+z replyR1=$00(success) fca28 f7cf8c01 test replyR1, #1 wz '| nc+nz replyR1=$01(idle) fca2c 02978c01 _RET_ cmpr replyR1, #$01 wc '/ c replyR1>$01(error) '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ SD SPI Send/Recv Routines... (write/read byte/long simultaneously) + '+ /CS=0 & CLK=0 on both entry and exit + '+-----------------------------------------------------------------------------+ fca30 f6678e01 _recvlong neg dataout, #1 ' call here to Recv a Long (+send 1's) fca34 f6079220 _sendlong mov bitscnt, #32 ' call here to Send a Long (long=32bits) fca38 fd90000c jmp #@_sendrecv ' fca3c _sendFF ' call here to Send $FF Byte fca3c f6678e01 _recvbyte neg dataout, #1 ' call here to Recv a Byte (+send 1's) fca40 f0278e18 _sendbyte rol dataout, #24 ' call here to Send a Byte (msbit first) fca44 f6079208 mov bitscnt, #8 ' (byte=8bits) fca48 f6078a00 _sendrecv mov reply, #0 ' clear reply ' 8+15 low/high clk cycles (8.7MHz@200MHz, 1.3MHz@30MHz) fca4c f0378e01 .nextbit rol dataout, #1 wc ' \ prepare output bit (DI=0/1).. fca50 fd647a48 outl #sd_ck ' | CLK=0 (already 0 first time) fca54 fd64764a outc #sd_di ' / write output bit: output on CLK falling edge fca58 fd64041f waitx #2 ' | setup time to be safe fca5c fd647a49 outh #sd_ck ' \ CLK=1 fca60 fd64061f waitx #3 ' | setup time to be safe fca64 fd747440 testp #sd_do wc ' | read input bit: sample on CLK rising edge fca68 f0a78a01 rcl reply, #1 ' / accum DO input bits fca6c fb6f93f7 djnz bitscnt, #.nextbit ' 8/32 bits? fca70 0d647a48 _RET_ outl #sd_ck ' CLK=0 on exit '+=============================================================================+ '+-----------------------------------------------------------------------------+ fca74 0d7de06f _fail _RET_ MODCZ _set,_clr wcz ' C & NZ = fail '+=============================================================================+ ''%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ''%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ''%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% '' +--------------------------------------------------------------------------+ '' | Cluso's LMM_SerialDebugger for P2 (c)2013-2018 "Cluso99" (Ray Rodrick)| '' +--------------------------------------------------------------------------+ '' RR20180512 v133i LSD_v131i ''============================[ CON ]============================================================ CON ''----------------------------------------------------------------------------------------------- '' LMM DEBUGGER - SUPPORTED COMMANDS ''----------------------------------------------------------------------------------------------- '' xxxxxx - xx xx xx xx ... DOWNLOAD: to cog/lut/hub {addr1} following {byte(s)} '' xxxxxx [.xxxxxx] L LIST: from cog/lut/hub {addr1} to < {addr2} '' xxxxxx G GOTO: to cog/lut/hub {addr1} '' Q QUIT: Quit Rom Monitor and return to the User Program '' Rffffffffxxx RUN: Run file from SD '' TAQOZ: goto TAQOZ ''----------------------------------------------------------------------------------------------- '' LMM DEBUGGER - CALL Modes...(not all modes supported) ''----------------------------------------------------------------------------------------------- _MODE = $F << 5 ' mode bits defining the call b8..b5 (b4..b0 are modifier options) _SHIFT = 5 ' shr # to extract mode bits _HEX_ = 2 << 5 ' hex... _REV_ = 1 << 4 ' - reverse byte order _SP = 1 << 3 ' - space between hex output pairs '_DIGITS = 7..0 where 8->0 ' - no. of digits to display _LIST = 3 << 5 ' LIST memory line (1/4 longs) from cog/hub _ADDR2 = 1 << 4 ' 1= use lmm_p2 as to-address _LONG_ = 1 << 1 ' 1=display longs xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx _TXSTRING = 4 << 5 ' tx string (nul terminated) from hub _RXSTRING = 5 << 5 ' rx string _ECHO_ = 1 << 4 ' - echo char _PROMPT = 1 << 3 ' - prompt (lmm_x) _ADDR = 1 << 2 ' - addr of string buffer supplied _NOLF = 1 << 1 ' - strip _MONITOR = 7 << 5 ' goto rom monitor '------------------------------------------------------------------------------------------------ DAT ''################################################################################################ ''## LMM Monitor - HUBEXEC code... ## ''################################################################################################ fca78 orgh ''----------------------------------------------------------------------------------------------- '' RESET BOOTER SERIAL INTERRUPTS & AUTOBAUD - KEEP SMART UART RUNNING ''----------------------------------------------------------------------------------------------- fca78 fd640025 _reset_booter setint1 #0 ' disable int1 fca7c f527f403 andn dira,#3 ' reset smart pins on P0 & P1 fca80 fc0c0001 wrpin #0,#rx_ths ' clear P1 rx_ths mode fca84 0c0c0000 _RET_ wrpin #0,#rx_tne ' clear P0 rx_tne mode ''=============================================================================================== ''-------[ Start Monitor ]----------------------------------------------------- <--- start monitor ---> fca88 fdbfffec _Start_Monitor call #@_reset_booter ' reset the booters interrupts and autobaud fca8c ff0007e0 _Enter_Monitor mov lmm_bufad, ##_HUBBUF ' addr of hub buffer (_HubRxString) fca90 f607de00 fca94 f607c00d mov lmm_x, #_CR_ ' we have to prime send buffer empty flag, fca98 fc27c03e wypin lmm_x, #tx_pin ' ... so send to tx pin ''--------------------------------------------------------------------------------------------------- ' this code displays a version string (it's not required) fca9c fdb000fc _Redo_Monitor call #@_HubTxStrVer ' send version string ''--------------------------------------------------------------------------------------------------- ' call the Monitor (because we need a return address set) fcaa0 fdb002d4 .monitor call #@_HubMonitor ' to the monitor/debugger fcaa4 fd9ffff8 jmp #.monitor ' loop back in case of "Q" ''=============================================================================================== ''-------[ Serial Routines (uses SmartPins) ]---------------------------------- <--- serial initialise ---> ''_SerialInit '' On Entry: '' lmm_x = _bitper ' tx & rx bit period + #(bits-1) '' lmm_bufad = 'bufad' ' hubbuf addr for use by _HubRxString '' Call Format: '' CALL #@_SerialAddr ' use default _HUBBUF < call: serial initilise> '' CALL #@_SerialBaud ' use default _bitper < call: serial initilise> '' CALL #@_SerialInit ' provide addr & baud < call: serial initilise> '' On Return: '' lmm_x = #CR ' (changed) ''-------------------------------------------------------------------------------------------------- fcaa8 ff0007e0 _SerialAddr mov lmm_bufad, ##_HUBBUF ' addr of hub buffer (_HubRxString) fcaac f607de00 fcab0 ff008200 _SerialBaud mov lmm_x, ##_bitper ' 115200 baud, 8 bits fcab4 f607c007 fcab8 ff800000 _SerialInit wrpin ##_txmode, #tx_pin ' set asynchronous tx mode in smart pin tx fcabc fc0cf83e fcac0 fc17c03e wxpin lmm_x, #tx_pin ' set tx bit period + #(bits-1) fcac4 fd647c41 dirh #tx_pin ' enable smart pin tx fcac8 ff800000 wrpin ##_rxmode, #rx_pin ' set asynchronous rx mode in smart pin rx fcacc fc0c7c3f fcad0 fc17c03f wxpin lmm_x, #rx_pin ' set rx bit period + #(bits-1) fcad4 fd647e41 dirh #rx_pin ' enable smart pin rx fcad8 f607c00d mov lmm_x, #_CR_ ' we have to prime send buffer empty flag, fcadc fc27c03e wypin lmm_x, #tx_pin ' ... so send to tx pin fcae0 fd7c002d RET wcz ' <--- return to calling routine ---> ''=============================================================================================== ''-------[ Display Char(s) ]--------------------------------------------------- <--- display char(s) ---> ''_HubTx ' '' On Entry: '' lmm_x = char(s) ' char(s): up to 4 chars; B0 first; terminates '' ' if =$0, tx one '' Call Format: '' CALL #@_HubTxCR ' preloads cr+lf < call: display char(s)> '' CALL #@_HubTxRev ' reverses lmm_x < call: display char(s)> '' CALL #@_HubTx ' < call: display char(s)> '' On Return: '' lmm_x = -same- ' char(s): (unchanged) ''-------------------------------------------------------------------------------------------------- fcae4 ff068500 _HubTxCR mov lmm_x, ##(_CR_<<24+_LF_<<16) ' (gets reversed) fcae8 f607c000 fcaec f9ffc01b _HubTxRev movbyts lmm_x, #%%0123 ' reversed fcaf0 f603cbe0 _HubTx MOV lmm_w, lmm_x ' < push: 'x' #0 > ' ---------------------------------------- fcaf4 fd747c40 .send testp #tx_pin wc ' wait for buffer empty on tx pin fcaf8 3d9ffff8 if_nc jmp #.send ' fcafc fc27c03e wypin lmm_x, #tx_pin ' send byte (bits7:0) to tx pin fcb00 f04fc008 shr lmm_x, #8 wz ' any more chars to send? fcb04 5d9fffec if_nz jmp #.send '> br back: (nz = another char in lmm_x) ' ---------------------------------------- fcb08 f603c1e5 MOV lmm_x, lmm_w ' < pop: 'x' #0 > fcb0c fd7c002d RET wcz ' <--- return to calling routine ---> ''=============================================================================================== ''-------[ Rx: Receive a char ]------------------------------------------------ <--- receive char ---> ''_HubRx '' On Entry: '' lmm_x = -anything- ' value: '' Call Format: '' CALL #@_HubRx ' < call: receive char> '' On Return: '' lmm_x = char ' char: input char ''-------------------------------------------------------------------------------------------------- fcb10 _HubRx ' <--- receive char ---> fcb10 fd747e40 .recv testp #rx_pin wc ' char ready? fcb14 3d9ffff8 if_nc jmp #.recv ' fcb18 fa8fc03f rdpin lmm_x, #rx_pin ' recv byte (bits31:24) from rx pin fcb1c f047c018 shr lmm_x, #24 ' shift rx bits fcb20 fd7c002d RET wcz ' <--- return to calling routine ---> ''=============================================================================================== ''-------[ Display Hex ]------------------------------------------------------- <--- display hex ---> ''_HubHex ' '' On Entry: '' lmm_f = _HEX_ [+options] ' mode: #_HEX_[+_REV_][+_SP][+_ndigits] '' ' 'n' digits = 7..0 where 0 = 8 digits '' lmm_x = char(s) ' char(s): '' Call Format: '' CALL #@_HubHexRev ' reverse lmm_x < call: display hex > '' CALL #@_HubHex8 ' hex 8 digits < call: display hex > '' CALL #@_HubHex ' < call: display hex > '' On Return: '' lmm_f = -same- ' mode: (unchanged) '' lmm_x = -same- ' char(s): (unchanged) ''-------------------------------------------------------------------------------------------------- fcb24 f9ffc01b _HubHexRev movbyts lmm_x, #%%0123 ' reversed fcb28 f607c240 _HubHex8 mov lmm_f, #_HEX_+0 ' 8 digits fcb2c f603cfe0 _HubHex MOV lmm_hx, lmm_x ' < push: 'x' #0 > fcb30 f603d3e4 MOV lmm_hc, lmm_c ' < push: 'c' #1 > ' ---------------------------------------- fcb34 f7cfc210 test lmm_f, #_REV_ wz ' reverse mode? fcb38 59ffc01b if_nz movbyts lmm_x, #%%0123 ' y: reverse bytes fcb3c f603c9e1 mov lmm_c, lmm_f '\ CTR = ... fcb40 f50fc807 and lmm_c, #7 wz '| ... 'n' digits ... fcb44 a607c808 if_z mov lmm_c, #8 '/ ... if 0, then 8 fcb48 f607ca08 mov lmm_w, #8 '\ nibbles to... fcb4c f18bcbe4 sub lmm_w, lmm_c wz '| ... ... fcb50 5067ca02 if_nz shl lmm_w, #2 '| ... *4 ... fcb54 5023c1e5 if_nz rol lmm_x, lmm_w '/ ... discard ' ---------------------------------------- fcb58 f027c004 .next rol lmm_x, #4 '\ next nibble ... fcb5c f603d1e0 MOV lmm_hx2, lmm_x '| ... save ... < push: 'x' #2 > fcb60 f507c00f and lmm_x, #$0F '| ... extract ... fcb64 f547c030 or lmm_x, #"0" '| ... convert ... fcb68 f217c03a cmp lmm_x, #":" wc '| ... ... fcb6c 3107c007 if_nc add lmm_x, #("A"-"9"-1) '/ ... now 0-9,A-F fcb70 fdbfff7c CALL #@_HubTx ' < call: display char(s)> ' ---------------------------------------- fcb74 f7cfc208 test lmm_f, #_SP wz ' hex space mode? fcb78 f7d7c801 test lmm_c, #1 wc ' c if odd count fcb7c bd900008 if_z_or_nc jmp #.nospace '> br: (no space reqd) fcb80 f607c020 mov lmm_x, #" " ' " " fcb84 fdbfff68 CALL #@_HubTx ' < call: transmit char(s)> ' ---------------------------------------- fcb88 .nospace fcb88 f603c1e8 MOV lmm_x, lmm_hx2 ' ... restore ... < pop: 'x' #2 > fcb8c fb6fc9f2 djnz lmm_c, #.next '> CTR-- ' ---------------------------------------- fcb90 f603c9e9 MOV lmm_c, lmm_hc ' < pop: 'c' #1 > fcb94 f603c1e7 MOV lmm_x, lmm_hx ' < pop: 'x' #0 > fcb98 fd7c002d RET wcz ' <--- return to calling routine ---> ''=============================================================================================== ''-------[ Display String, terminated ]---------------------------------- <--- display string ---> ''_HubTxString ' '' On Entry: '' lmm_p = 'addr' ' addr: string (hub ptr) '' Call Format: '' CALL #@_HubTxStrVer ' display version < call: display string> '' CALL #@_HubTxString ' < call: display string> '' On Return: '' lmm_p = 'addr' (next string) ' addr: (hub ptr to next string) ''-------------------------------------------------------------------------------------------------- fcb9c ff0007e8 _HubTxStrVer mov lmm_p, ##_str_vers ' send version string, $00 terminated fcba0 f607c414 fcba4 f603cfe0 _HubTxString MOV lmm_hx, lmm_x ' < push: 'x' #0 > ' ---------------------------------------- fcba8 facbc1e2 .loop rdbyte lmm_x, lmm_p wz ' get char from string: nul? fcbac f107c401 add lmm_p, #1 ' PTR++ fcbb0 ad900008 if_z jmp #.return '> br fwd: (returns to calling program) fcbb4 fdbfff38 CALL #@_HubTx ' < call: transmit char(s)> fcbb8 fd9fffec jmp #.loop ' br back ' ---------------------------------------- fcbbc .return fcbbc f603c1e7 MOV lmm_x, lmm_hx ' < pop: 'x' #0 > fcbc0 fd7c002d RET wcz ' <--- return to calling routine ---> ''=============================================================================================== ''-------[ LIST a line(s) ]---------------------------------------------------- <--- LIST a line(s) ---> ''_HubList '' On Entry: '' lmm_f = #_LIST [+options] ' mode: _LIST[+_ADDR2][+_LONG_] '' lmm_p = 'addr' (from) ' addr: from cog addr / hub ptr '' lmm_p2 = 'addr2' (to) (optional) ' addr2: to cog addr / hub ptr (if _ADDR2 specified) '' Call Format: '' CALL #@_HubListA2 ' _LIST+_ADDR2 < call: LIST a line > '' CALL #@_HubList ' < call: LIST a line > '' On Return: '' lmm_f = same except _HDG off ' mode: same except _HDG will be off '' lmm_p = addr++ (from) ' addr: next from cog addr / hub ptr '' lmm_p2 = addr2++/same (to) ' addr2: next to addr -OR- unchanged ''--------------------------------------------------------------------------------------------------- fcbc4 f607c270 _HubListA2H mov lmm_f, #_LIST+_ADDR2 ' list addr2 fcbc8 f603d5e0 _HubList MOV lmm_lx, lmm_x '\ save params fcbcc f603d7e1 MOV lmm_lf, lmm_f '| fcbd0 f603d9e2 MOV lmm_lp, lmm_p '| fcbd4 f603dbe2 MOV lmm_lp2,lmm_p '| orig {addr} fcbd8 f603dde4 MOV lmm_lc, lmm_c '/ fcbdc f7cfc210 test lmm_f, #_ADDR2 wz ' nz if {addr2} mode fcbe0 a603c7e2 if_z mov lmm_p2, lmm_p ' n: replace {addr2} <-- {addr} ' ---------------------------------------- ' ===LOOPS HERE FOR MULTIPLE LINES=== fcbe4 _HubListLoop ' ---------------------------------------- ' ===DISPLAY LINE: ADDR=== fcbe4 f603c5ec MOV lmm_p, lmm_lp ' restore 'addr' fcbe8 ff000001 cmp lmm_p, ##$3FF wcz ' z|c if =<$3FF = cog/lut mode? fcbec f21fc5ff ' hub: fcbf0 1607c245 if_a mov lmm_f, #_HEX_+5 ' set hex mode with 5 digits ' cog: fcbf4 e607c243 if_be mov lmm_f, #_HEX_+3 ' set hex mode with 3 digits fcbf8 ef000010 if_be mov lmm_x, ##(" "+" "<<8) ' " " fcbfc e607c020 fcc00 edbffeec if_be CALL #@_HubTx ' < call: transmit char(s) > ' display address fcc04 f603c1e2 mov lmm_x, lmm_p ' set cog/lut/hub address (for displaying) fcc08 fdbfff20 CALL #@_HubHex ' < call: display hex > fcc0c ff000010 mov lmm_x, ##(":"+" "<<8) ' ": " fcc10 f607c03a fcc14 fdbffed8 CALL #@_HubTx ' < call: transmit char(s) > ' ---------------------------------------- ' ===DISPLAY 4x HEX LONGS=== ' lmm_p = ptr to 1st long fcc18 f7cfd602 test lmm_lf, #_LONG_ wz ' long or byte mode fcc1c 5607c240 if_nz mov lmm_f, #_HEX_+0 ' set hex with 8(=0) digits fcc20 a607c258 if_z mov lmm_f, #_HEX_+_REV_+_SP+0 ' set hex reversed space mode with 8(=0) digits fcc24 f607c804 mov lmm_c, #4 ' set 4 longs ' read a long from cog/lut/hub into lmm_x pointed to by lmm_p and inc lmm_p fcc28 fdb00308 .long4 CALL #_RdLongCogHub ' < call: read cog/hub long > fcc2c fdbffefc CALL #@_HubHex ' < call: display hex> fcc30 f607c020 mov lmm_x, #" " ' extra space fcc34 fdbffeb8 CALL #@_HubTx ' < call: transmit char(s) > fcc38 fb6fc9fb djnz lmm_c, #.long4 ' (4 longs)-- ' ---------------------------------------- ' ===DISPLAY ASCII=== fcc3c f607c804 mov lmm_c, #4 ' set 4 longs fcc40 f603c5ec MOV lmm_p, lmm_lp ' restore {addr} fcc44 ff000013 mov lmm_x, ##(" "+"'"<<8) ' " '" fcc48 f607c120 fcc4c fdbffea0 CALL #@_HubTx ' < call: transmit char(s) > ' ------------------------ ' read a long from cog/lut/hub into lmm_x pointed to by lmm_p and inc lmm_p fcc50 fdb002e0 .asciiloop CALL #_RdLongCogHub ' < call: read cog/hub long > fcc54 f7cfd602 test lmm_lf, #_LONG_ wz ' long mode? fcc58 59ffc01b if_nz movbyts lmm_x, #%%0123 ' y: reverse bytes ' convert 4 bytes to visible fcc5c f607c204 mov lmm_f, #4 ' (lmm_f as temp byte counter) fcc60 f603cbe0 .convert mov lmm_w, lmm_x ' duplicate fcc64 f527c0ff andn lmm_x, #$FF ' clear lower byte fcc68 f507caff and lmm_w, #$FF ' extract lower byte fcc6c f217ca20 cmp lmm_w, #" " wc ' c if <$20: invisible? fcc70 c607ca2e if_c mov lmm_w, #"." ' y: replace fcc74 f217ca7f cmp lmm_w, #$7F wc ' c if <$7F: visible? fcc78 3607ca2e if_nc mov lmm_w, #"." ' n: replace fcc7c f543c1e5 or lmm_x, lmm_w ' replace lower byte fcc80 f007c008 ror lmm_x, #8 ' next byte fcc84 fb6fc3f6 djnz lmm_f, #.convert ' (lmm_f as temp byte counter) fcc88 fdbffe64 CALL #@_HubTx ' 4 ascii bytes < call: transmit char(s)> fcc8c fb6fc9f0 djnz lmm_c, #.asciiloop ' (longs count)-- fcc90 ff000506 mov lmm_x, ##("'"+_CR_<<8+_LF_<<16) ' "'" fcc94 f607c127 fcc98 fdbffe54 CALL #@_HubTx ' < call: transmit char(s)> fcc9c f603d9e2 MOV lmm_lp, lmm_p ' save new {addr} ' ---------------------------------------- ' ===MULTIPLE LINES ?=== fcca0 f213c5e3 cmp lmm_p, lmm_p2 wc ' c if addr < addr2 fcca4 cd9fff3c if_b jmp #_HubListLoop ' n: another line ' ---------------------------------------- ' calculate how far 'addr' advanced and advance 'addr2' by the same amount fcca8 f183c7ed sub lmm_p2,lmm_lp2 ' {addr2} - orig {addr} fccac f103c7e2 add lmm_p2,lmm_p ' + final {addr} fccb0 f603dbe3 mov lmm_lp2, lmm_p2 ' save new {addr2} ' ---------------------------------------- fccb4 f603c1ea MOV lmm_x, lmm_lx '\ restore params fccb8 f603c3eb MOV lmm_f, lmm_lf '| '' MOV lmm_p, lmm_lp '| \(already done) '' MOV lmm_p2,lmm_lp2 '| / fccbc f603c9ee MOV lmm_c, lmm_lc '/ ' ---------------------------------------- fccc0 fd7c002d RET wcz ' <--- return to calling routine ---> ''=============================================================================================== ''-------[ Receive String ]---------------------------------------------------- <--- receive string ---> ''_HubRxString '' On Entry: '' lmm_f = #_RXSTRING [+options] ' mode: #_RXSTRING[+_ECHO_][+_PROMPT][+_ADDR][+_NOLF] '' lmm_x = char(s) (optional) ' prompt: char(s) '' lmm_p = 'bufad' (optional) ' addr: input string (hub ptr) '' lmm_bufad = 'bufad' (default) ' addr: input string (hub ptr) '' Call Format: '' CALL #@_HubRxStrMon ' presets lmm_x & lmm_f < call: receive string > '' CALL #@_HubRxString ' < call: receive string > '' On Return: '' lmm_f = -same- ' mode: (unchanged) '' lmm_x = -same- ' '' lmm_p = 'addr' ' addr: input string (hub ptr) '' lmm_c = 'count' ' count: char(s) entered (incl , excl ) ''-------------------------------------------------------------------------------------------------- fccc4 f607c02a _HubRxStrMon mov lmm_x, #"*" ' prompt fccc8 f607c2b8 mov lmm_f, #_RXSTRING+_ECHO_+_PROMPT ' params fcccc f603cfe0 _HubRxString MOV lmm_hx, lmm_x ' < push: 'x' #0 > ' ---------------------------------------- fccd0 f7cfc208 test lmm_f, #_PROMPT wz ' prompt ? fccd4 ad900004 if_z jmp #.noprompt ' n: ' Display prompt char(s) in lmm_x fccd8 fdbffe14 CALL #@_HubTx ' < call: transmit char(s) > ' setup the hub string address ptr fccdc f7cfc204 .noprompt test lmm_f, #_ADDR wz ' {addr} supplied option ? fcce0 a603c5ef if_z mov lmm_p, lmm_bufad ' n: use default hub buffer ' receive char(s) terminated in fcce4 f607c800 mov lmm_c, #0 ' set char count=0 fcce8 fdbffe24 .loop CALL #@_HubRx ' < call: receive char > fccec f20fc00a cmp lmm_x, #_LF_ wz ' ? fccf0 5d900008 if_nz jmp #.notlf ' n: fccf4 f7cfc202 test lmm_f, #_NOLF wz ' strip ? fccf8 5d9fffec if_nz jmp #.loop ' y: fccfc f20fc008 .notlf cmp lmm_x, #_BS_ wz ' ? fcd00 a20fc800 if_z cmp lmm_c, #0 wz ' start of input ? fcd04 ad9fffe0 if_z jmp #.loop ' y: skip fcd08 f217c84e cmp lmm_c, #_HUBBUFSIZE-2 wc ' c if < end-of-buf ? fcd0c 320fc008 if_nc cmp lmm_x, #_BS_ wz ' ? fcd10 120fc00d if_nc_and_nz cmp lmm_x, #_CR_ wz ' ? fcd14 1d9fffd0 if_nc_and_nz jmp #.loop ' j if buf full + not not (ignore) fcd18 fc43c1e2 wrbyte lmm_x, lmm_p ' push input char to buf (don't inc ptr yet) fcd1c f7cfc210 test lmm_f, #_ECHO_ wz ' echo? fcd20 ad900020 if_z jmp #.noecho ' n: fcd24 f20fc008 cmp lmm_x, #_BS_ wz ' ? fcd28 af000410 if_z mov lmm_x, ##(_BS_+" "<<8+_BS_<<16) ' y: echo " " fcd2c a607c008 fcd30 fdbffdbc CALL #@_HubTx ' < call: transmit char(s) > fcd34 f20fc00d cmp lmm_x, #_CR_ wz ' ? fcd38 a607c00a if_z mov lmm_x, #_LF_ ' y: follow with fcd3c adbffdb0 if_z CALL #@_HubTx ' fcd40 fac3c1e2 rdbyte lmm_x, lmm_p ' restore input char fcd44 f20fc008 .noecho cmp lmm_x, #_BS_ wz ' ? fcd48 a187c401 if_z sub lmm_p, #1 ' y: PTR-- fcd4c a187c801 if_z sub lmm_c, #1 ' y: CTR-- fcd50 ad9fff94 if_z jmp #.loop ' y: fcd54 f107c401 .notbs add lmm_p, #1 ' PTR++ fcd58 f107c801 add lmm_c, #1 ' CTR++ fcd5c f20fc00d cmp lmm_x, #_CR_ wz ' ? fcd60 5d9fff84 if_nz jmp #.loop ' n: ' have a buffer with followed by terminated fcd64 f607c000 mov lmm_x, #0 '\ load $0 (nul) fcd68 fc43c1e2 wrbyte lmm_x, lmm_p '/ push to buf fcd6c f183c5e4 sub lmm_p, lmm_c ' reset PTR to start of string ' ---------------------------------------- fcd70 f603c1e7 MOV lmm_x, lmm_hx ' < pop: 'x' #0 > fcd74 fd7c002d RET wcz ' <--- return to calling routine ---> ''=============================================================================================== ''-------[ Monitor: DebugMonitor]---------------------------------------------- <--- monitor/debug ---> ''_HubMonitor '' lmm_bufad = 'bufad' ' hubbuf addr for use by _HubRxString '' Call Format: ' '' CALL #@_HubMonitor ' < call: monitor/debug> ''-------------------------------------------------------------------------------------------------- fcd78 fdbfff48 _HubMonitor CALL #@_HubRxStrMon ' < call: recv string > ' get optionl 1st param: [xxxxxx] hex/addr {addr} followed by 'cmd' fcd7c fdb001e8 .parse CALL #@_ParseHex ' < call: parse hex > '--------------------------------------------------------------- ' returns: lmm_x=addr(hex), lmm_c=digitcount, lmm_p=ptrnextchar ' lmm_w=next non-hex char with lcase converted to ucase '--------------------------------------------------------------- ' check commands w/o {addr} first fcd80 f20fca0d cmp lmm_w, #_CR_ wz ' ? repeat LIST fcd84 ad900044 if_e jmp #@_Cmd_CR ' fcd88 f20fca1b cmp lmm_w, #_TAQOZ_ wz ' ? TAQOZ fcd8c ad90029c if_e jmp #@_Enter_TAQOZ ' fcd90 f20fca4c cmp lmm_w, #"L" wz ' "L" ? Load a file, don't run fcd94 520fca52 if_ne cmp lmm_w, #"R" wz ' "R" ? Run a file (Load & Run) fcd98 ad9000b8 if_e jmp #@_Cmd_Run ' fcd9c f20fca51 cmp lmm_w, #"Q" wz ' "Q" ? QUIT fcda0 ad7c002d if_e RET wcz ' y: return to caller <--- return to calling routine ---> '--------------------------------------- ' check commands w optional {addr} before cmd char fcda4 f20fca2d cmp lmm_w, #"-" wz ' "-" ? LIST fcda8 ad900044 if_e jmp #@_Cmd_List ' fcdac f20fca3a cmp lmm_w, #":" wz ' ":" ? Download fcdb0 ad9000f0 if_e jmp #@_Download ' fcdb4 f20fca47 cmp lmm_w, #"G" wz ' "G" ? GOSUB fcdb8 ad900074 if_e jmp #@_Cmd_G ' '------------------------------------------------------- fcdbc ff000506 _Cmd_What mov lmm_x, ##("?"+_CR_<<8+_LF_<<16) ' unknown fcdc0 f607c13f fcdc4 fdbffd28 CALL #@_HubTx ' fcdc8 fd9fffac jmp #@_HubMonitor ' '------------------------------------------------------- fcdcc _Cmd_CR ' repeat previous LIST command fcdcc f603cbeb mov lmm_w, lmm_lf ' check valid list saved fcdd0 f507cbe0 and lmm_w, #_MODE ' fcdd4 f20fca60 cmp lmm_w, #_LIST wz ' fcdd8 5d9fffe0 if_ne jmp #@_Cmd_What ' invalid fcddc f603c3eb mov lmm_f, lmm_lf '\ restore last saved list params fcde0 f603c5ec mov lmm_p, lmm_lp '| fcde4 f603c7ed mov lmm_p2, lmm_lp2 '/ fcde8 fdbffddc CALL #@_HubList ' fcdec fd9fff88 jmp #@_HubMonitor ' '------------------------------------------------------- ' LIST: get optional 2nd param: [yyyyyy] {addr2} optionally followed by "L" (L=long) fcdf0 _Cmd_List fcdf0 f603d9e0 mov lmm_lp, lmm_x ' save {addr} fcdf4 f607da00 mov lmm_lp2, #0 ' set {addr2} =0 fcdf8 f217c804 cmp lmm_c, #4 wc ' c if digitcount <4 ? fcdfc 3427d814 if_nc bith lmm_lp, #20 ' $1_xxxxx trick forces hub :) fce00 3427da14 if_nc bith lmm_lp2, #20 ' $1_xxxxx trick forces hub :) '--------------------------------------- fce04 fdb00160 CALL #@_ParseHex ' < call: parse hex > '--------------------------------------------------------------- ' returns: lmm_x=addr(hex), lmm_c=digitcount, lmm_p=ptrnextchar ' lmm_w=next non-hex char with lcase converted to ucase '--------------------------------------------------------------- fce08 f20fc800 cmp lmm_c, #0 wz ' {addr2} ? fce0c ad900004 if_z jmp #.list ' fce10 f543dbe0 or lmm_lp2, lmm_x ' save {addr2} keep b20 '------------------------------------------------------- ' lmm_lp='addr', lmm_lp2='addr2', lmm_lc='digitcount of param1 '------------------------------------------------------- fce14 f603c5ec .list mov lmm_p, lmm_lp ' {addr} fce18 f603c7ed mov lmm_p2, lmm_lp2 ' {addr2} '--------------------------------------- fce1c f20fca4c cmp lmm_w, #"L" wz ' "L" ? LIST longs fce20 a607c272 if_e mov lmm_f, #_LIST+_ADDR2+_LONG_ ' list addr2 in longs fce24 5607c270 if_ne mov lmm_f, #_LIST+_ADDR2 ' list addr2 in bytes fce28 fdbffd9c CALL #@_HubList ' fce2c fd9fff48 jmp #@_HubMonitor ' '------------------------------------------------------- fce30 _Cmd_G ' xxxxxxG GOSUB cog/lut/hub address fce30 fd63ca2b POP lmm_w ' pop stack fce34 ff0007e0 cmp lmm_x, ##$FC000 wz ' is it a ROM reboot? fce38 f20fc000 fce3c af80003a if_z waitx ##delay1ms ' allow char to get out fce40 ad66601f fce44 af880000 if_z hubset ##$1000_0000 ' y: reboot h/w fce48 ad640000 fce4c fd63c02d CALL lmm_x ' call cog/lut/hub addr in lmm_x (not #lmm_x) fce50 fd9fff24 jmp #@_HubMonitor ' '------------------------------------------------------- fce54 _Cmd_Run ' R ' Run filename "ffffffff.xxx" from SD ' ' L ' Load filename "ffffffff.xxx" from SD fce54 f603c3e5 mov lmm_f, lmm_w ' save optional "L" fce58 fdb0018c call #@_ParseFname ' get filename.. fce5c f603b9e0 mov fname, lmm_x ' fce60 fdb00184 call #@_ParseFname ' fce64 f603bbe0 mov fname+1,lmm_x ' fce68 f20fca2e cmp lmm_w, #"." wz ' skipover "." ? fce6c a107c401 if_z add lmm_p, #1 ' fce70 fdb00174 call #@_ParseFname ' fce74 f603bde0 mov fname+2,lmm_x ' fce78 f20fc252 cmp lmm_f, #"R" wz ' run? fce7c 5d900008 if_ne jmp #.load ' fce80 fdbff6f4 .run CALL #@_Run_SDfile ' run from SD fce84 fd900004 jmp #.done ' fce88 fdbff704 .load CALL #@_LOAD_SDfile ' load from SD fce8c af000506 .done if_e mov lmm_x, ##("="+_CR_<<8+_LF_<<16) ' passed run fce90 a607c13d fce94 5f000506 if_ne mov lmm_x, ##("!"+_CR_<<8+_LF_<<16) ' failed run! fce98 5607c121 fce9c fdbffc50 CALL #@_HubTx ' fcea0 fd9ffed4 jmp #@_HubMonitor ''=============================================================================================== ''-------[ Download Command ]-------------------------------------------------- <--- download command ---> '' On Entry: '' '--------------------------------------------------------------- '' ' lmm_x=addr(hex), lmm_c=digitcount, lmm_p=ptrnextchar '' '--------------------------------------------------------------- '' lmm_x = 'addr(hex)' ' addr(hex): download addr in cog/hub '' lmm_c = 'count' ' count: count of chars in 'addr' for cog/hub '' lmm_p = 'addr' ' addr: ptr to string (hub) '' lmm_p2 = ???? ' addr2: '' Call Format: '' CALL #@_Download ' < call: download command > '' On Return: '' ???? ''-------------------------------------------------------------------------------------------------- '' [xx]xxx : xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ['xxxxxxxxxxxxxxxx'] ''-------------------------------------------------------------------------------------------------- fcea4 f603c7e0 _Download mov lmm_p2, lmm_x ' save download addr(hex) fcea8 f217c804 cmp lmm_c, #4 wc ' c if <4 digits (cog/lut?) fceac 3427c61f if_nc bith lmm_p2, #31 ' n: set 'hub' fceb0 fdb000b4 .loop CALL #@_ParseHex ' get next hex value '--------------------------------------------------------------- ' returns: lmm_x=value(hex), lmm_c=digitcount, lmm_p=ptrnextchar ' lmm_w=next non-hex char with lcase converted to ucase '--------------------------------------------------------------- fceb4 f20fc800 cmp lmm_c, #0 wz ' any input? fceb8 ad9ffebc if_z jmp #@_HubMonitor ' n: done so back to monitor fcebc f417c61f testb lmm_p2, #31 wc ' hub? fcec0 cd900044 if_c jmp #.hub ' y: ' cog/lut ' get a long or 4 bytes for cog/lut fcec4 f217c808 cmp lmm_c, #8 wc ' c if <8 chars? fcec8 3d900018 if_nc jmp #.gotlong ' n: fcecc fdb000a0 .getmore CALL #@_ParseHex2 ' get another hex byte fced0 f217c808 cmp lmm_c, #8 wc ' c if <8 chars? fced4 3d900008 if_nc jmp #.got4bytes ' n: fced8 f20fca0d cmp lmm_w, #_CR_ wz ' ? fcedc 5d9fffec if_ne jmp #.getmore ' n: fcee0 f9ffc01b .got4bytes movbyts lmm_x, #%%0123 ' reverse bytes fcee4 f21fc7ff .gotlong cmp lmm_p2, #$1FF wcz ' c|z if <$200 (cog?) fcee8 ed90000c if_c_or_z jmp #.cog ' y: fceec fc33c1e3 .lut wrlut lmm_x, lmm_p2 ' write a long to lut fcef0 f107c601 add lmm_p2, #1 ' PTR++ fcef4 fd9fffb8 jmp #.loop ' write 'long' from lmm_x into cog 'addr' in lmm_p2.. don't forget we are in hubexec! fcef8 f98fc600 .cog altd lmm_p2 '\ set PTR fcefc f60001e0 mov 0-0, lmm_x '/ write a long to cog fcf00 f107c601 add lmm_p2, #1 ' PTR++ fcf04 fd9fffa8 jmp #.loop fcf08 f217c803 .hub cmp lmm_c, #3 wc ' c if <3 chars (byte) fcf0c cc43c1e3 if_c wrbyte lmm_x, lmm_p2 ' write a byte to hub fcf10 c107c601 if_c add lmm_p2, #1 ' PTR++ (+1) fcf14 cd9fff98 if_c jmp #.loop fcf18 f217c805 cmp lmm_c, #5 wc ' c if <5 chars (word) fcf1c cc53c1e3 if_c wrword lmm_x, lmm_p2 ' write a word to hub fcf20 c107c602 if_c add lmm_p2, #2 ' PTR++ (+2) fcf24 cd9fff88 if_c jmp #.loop fcf28 fc63c1e3 wrlong lmm_x, lmm_p2 ' write a long to hub fcf2c f107c604 add lmm_p2, #4 ' PTR++ (+4) fcf30 fd9fff7c jmp #.loop ''=============================================================================================== ''-------[ Read Cog/Lut/Hub Long ]--------------------------------------------- <--- read: cog/lut/hub long ---> ''_RdLongCogHub '' On Entry: '' lmm_x = -anything- ' 'long': '' lmm_p = 'addr' ' 'addr': cog/lut addr / hub ptr '' Call Format: '' CALL #@_RdLongCogHub ' < call: read cog/lut/hub long > '' On Return: '' lmm_x = 'long' ' 'long': read from cog/hub '' lmm_p = 'addr++' ' 'addr++' cog/lut addr++ / hub ptr++ '--------------------------------------------------------------------------------------------------- fcf34 _RdLongCogHub ' <--- read: cog/lut/hub long ---> fcf34 ff000001 cmp lmm_p, ##$3FF wcz ' z|c if =<$3FF = cog/lut mode? fcf38 f21fc5ff ' read the 'long' into lmm_x from hub 'addr' in lmm_p fcf3c 1b03c1e2 if_a rdlong lmm_x, lmm_p '\ read a long (hub) fcf40 1107c404 if_a add lmm_p, #4 '| PTR++ fcf44 1d7c002d if_a RET WCZ '/ fcf48 f21fc5ff cmp lmm_p, #$1FF wcz ' z|c if =<$3FF = cog mode? ' read the 'long' into lmm_x from lut 'addr' in lmm_p fcf4c 1aa3c1e2 if_a rdlut lmm_x, lmm_p '\ read a long (lut) fcf50 1107c401 if_a add lmm_p, #1 '| PTR++ fcf54 1d7c002d if_a RET WCZ '/ ' read the 'long' into lmm_x from cog 'addr' in lmm_p.. ' don't forget we are executing from hub (hubexec) fcf58 e997c400 if_be alts lmm_p '\ set PTR fcf5c e603c000 if_be mov lmm_x, 0-0 '| read a long (cog) fcf60 e107c401 if_be add lmm_p, #1 '| PTR++ fcf64 fd7c002d RET WCZ '/ ''=============================================================================================== ''-------[ Parse hex input ]--------------------------------------------------- <--- parse hex input ---> ''_ParseHex '' On Entry: '' lmm_x = -anything-/'hex' ' 'hex': ---/prev hex value '' lmm_c = -anything-/'count' ' 'count': ---/prev count '' lmm_p = 'addr' ' 'addr': ptr to string (hub) '' lmm_w = -anything- ' '' Call Format: '' CALL #@_ParseHex ' < call: parse hex > '' On Return: '' lmm_x = 'hex' ' 'hex': hex value '' lmm_c = 'count' ' 'count': of hex digits '' lmm_p = 'addr++' ' 'addr': ptr past next non-hex char '' lmm_w = 'ucase' ' 'ucase': next non-hex char in ucase ''-------------------------------------------------------------------------------------------------- fcf68 _ParseHex ' <--- parse hex input ---> fcf68 f607c000 mov lmm_x, #0 ' preset hex=0 fcf6c f607c800 mov lmm_c, #0 ' preset count=0 fcf70 fac3cbe2 _ParseHex2 rdbyte lmm_w, lmm_p '\ read a char from string fcf74 f20fca20 cmp lmm_w, #" " wz '| " " ? fcf78 a107c401 if_e add lmm_p, #1 '| y: PTR++ fcf7c ad9ffff0 if_e jmp #@_ParseHex2 '/ skip fcf80 fac3cbe2 .loop rdbyte lmm_w, lmm_p ' read a char from string fcf84 f20fca5f cmp lmm_w, #"_" wz ' "_" ? fcf88 a107c401 if_e add lmm_p, #1 ' y: PTR++ fcf8c ad9ffff0 if_e jmp #.loop ' y: skip "_" fcf90 f217ca30 cmp lmm_w, #"0" wc ' c if <"0" fcf94 cd900044 if_b jmp #.done ' j if not hex fcf98 f217ca3a cmp lmm_w, #"9"+1 wc ' c if "0"-"9" fcf9c cd900018 if_b jmp #.num ' y: 0-9 fcfa0 f547ca20 or lmm_w, #$20 ' force lower case a-z fcfa4 f217ca61 cmp lmm_w, #"a" wc ' c if <"a" fcfa8 cd900024 if_b jmp #.nothex ' j if not hex fcfac f217ca67 cmp lmm_w, #"f"+1 wc ' c if <"g" fcfb0 3d90001c if_nc jmp #.nothex ' j if not hex fcfb4 f187ca07 sub lmm_w, #("A"-"9"-1) ' convert from A-F/a-f fcfb8 f507ca0f .num and lmm_w, #$0F ' extract valid nibble fcfbc f067c004 shl lmm_x, #4 ' shift nibbles fcfc0 f543c1e5 or lmm_x, lmm_w ' and add nibble fcfc4 f107c401 add lmm_p, #1 ' PTR++ fcfc8 f107c801 add lmm_c, #1 ' CTR++ fcfcc fd9fffb0 jmp #.loop ' ' ---------------------------------------- fcfd0 fac3cbe2 .nothex rdbyte lmm_w, lmm_p ' re-read the non-hex char fcfd4 f217ca60 cmp lmm_w, #$60 wc ' c if < lower case columns fcfd8 3527ca20 if_nc andn lmm_w, #$20 ' converts to uppercase columns fcfdc f217c00d .done cmp lmm_x, #_CR_ wc ' ? (don't skip over ) fcfe0 5107c401 if_ne add lmm_p, #1 ' n: PTR++ (skip over non-hex char) fcfe4 fd7c002d RET wcz ' <--- return to calling routine ---> ''=============================================================================================== ''-------[ Parse ]-------------------------------------------------- <--- parse filename ---> '' On Entry: '' lmm_x = -anything- ' -anything- '' lmm_c = -anything- ' -anything- '' lmm_p = 'addr' ' 'addr': ptr to string (hub) '' lmm_w = -anything- ' '' Call Format: '' CALL #@_ParseFname ' < call: parse filename > '' On Return: '' lmm_x = 'fname' ' 'fname': 4 chars of filename '' lmm_c = -undefined- ' '' lmm_p = 'addr++' ' 'addr': '' lmm_w = _undefined- ' ''-------------------------------------------------------------------------------------------------- fcfe8 f607c804 _ParseFname mov lmm_c, #4 ' 4 chars per call fcfec f607c000 mov lmm_x, #0 fcff0 fac3cbe2 .loop rdbyte lmm_w, lmm_p ' get a char fcff4 f20fca2e cmp lmm_w, #"." wz fcff8 520fca0d if_ne cmp lmm_w, #_CR_ wz fcffc 5543c1e5 if_ne or lmm_x, lmm_w ' insert char.. fd000 a547c020 if_e or lmm_x, #" " ' .. or space.. fd004 f007c008 ror lmm_x, #8 ' .. & rotate byte fd008 5107c401 if_ne add lmm_p, #1 ' PTR++ fd00c 5ac3cbe2 if_ne rdbyte lmm_w, lmm_p ' get a char fd010 0b6fc9f7 _RET_ djnz lmm_c, #.loop ' <4 chars ''=============================================================================================== fd014 4d2d3250 _str_vers byte "P2-MONITOR V1.0",$0D,$0A,0 ''=============================================================================================== fd026 alignl '******************************************************************************* '* * '* TAQOZ - Tachyon Forth for the Parallax P2 CPU ROM * '* * '******************************************************************************* CON '''''''''''''' SERIAL BUFFERS '''''''''' rxbuffers = $180 rxrd = $0C rxwr = $0E rxsize = $0E80 codeorg = $1000 ramdict = $B400 ' dictionary can be moved elsewhere at runtime' sys_clk = 80_000_000 nscnt = 100000/(sys_clk/1000000) '' baud_rate = 115200 '' baudval = (sys_clk/baud_rate)<<16 ' 180524 - implement 10-bit short literals and 9-bit task register addresses for compact fat32 variables' w = $F800 ' wordcode offset for 10-bit literals _IF = $FC00 ' IF relative forward branch 0 to 127 words _UNTIL = $FC80 ' UNTIL relative reverse branch 0 to 127 words opunused = $FD00 rg = $FE00 ' task/cog register 8-bit offset fat = $FF00 registers = rg 'Variables used by kernel + general-purpose tasks = rg+$D0 ' 2 longs/task * 8 cogs SKIPZ = _IF+01 ex = 1 ' EXITs (jump to hub wordcode instead of call) _FALSE = w+0 _0 = w+0 _1 = w+1 _2 = w+2 _3 = w+3 _4 = w+4 _5 = w+5 _6 = w+6 _7 = w+7 _8 = w+8 _9 = w+9 _13 = w+13 _16 = w+16 _32 = w+32 _BL = w+32 CON ' Offsets in LUT for stacks datstk = $000 brastk = $020 lpstk = $030 retstk = $040 ' The LUT is essentially free from $80 onwards CON lastkey = $00F0 ' written to directly from serialrx to hub ram ( reuse blank "R1" location ) numpadsz = 26 ' We really only need a large buffer for when long binary numbers with separators are used ' 26 digits for double number 18,446,744,073,709,551,615 wordsz = 39 ' any word up to 37 characters (1 count, 1 terminator) tasksz = 8 ' 8 bytes/task RUN[2] FLAG[1] ' fflags echo = 1 'linenums = 2 ' prepend line number to each new line ipmode = 4 ' interpret this number in IP format where a "." separates bytes prset = $10 ' private headers set as default sign = $20 comp = $40 ' force compilation of the current word - resets each time defining = $80 CON flashpins = spi_cs<<24+spi_do<<16+spi_di<<8+spi_ck sdpins = sd_cs<<24+sd_do<<16+sd_di<<8+sd_ck WW = $FFFF cntm = $1F ' mask for nfa count byte to mask off atrs' ' Dictionary header attribute flags pubatr = 0 priatr = 1 preatr = 2 modatr = 3 maxlen = 15 im = preatr<<6 'lexicon immediate bit pr = priatr<<6 'private (can be removed from the dictionary) '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' DAT fd028 orgh fd028 alignw ''-------[ Start TAQOZ ]----------------------------------------------------- <--- start TAQOZr ---> fd028 fdbffa4c _Start_TAQOZ call #@_reset_booter ' reset the booters interrupts and autobaud fd02c _Enter_TAQOZ ''--------------------------------------------------------------------------------------------------- fd02c fedfefd0 loc PTRA,#_hubrom ' copy all of ROM to low 64K' fd030 fef0efcc loc PTRB,#$C000 fd034 ff000008 rep #2,##$1000 fd038 fcdc0400 fd03c fb041761 rdlong fx,PTRA++ fd040 fc6417e1 wrlong fx,PTRB++ 'mov fx,##_ReEnter_TAQOZ & WW 'wrlong fx,#4 fd044 _ReEnter_TAQOZ { coginit #7,##@RESET coginit #6,##@RESET coginit #5,##@RESET coginit #4,##@RESET coginit #3,##@RESET coginit #2,##@RESET coginit #1,##@RESET } fd044 ff0007f6 coginit #0,##@RESET fd048 fcec0164 dat fd04c orgh fd04c 0000000a taqoz_version long 1_0 fd050 6b9ab1a7 taqoz_time long 180530_0135 fd054 20323431 taqoz_name byte "142 " ' use exactly 4 characters = 1 long' { to do READ & WRITE BLOCKS OF SPI FLASH add RUN (NEWCOG and TASK !) } fd058 orgh { *** OUTPUT OPERATIONS *** } fd058 f820 SPACE word _BL fd05a 00e0feae EMIT word rg+linenum,WFETCH fd05e 0073fc06 word _IF+06,DUP,w+$0A,_EQ,_IF+02,DROP,_13 fd06c ec64fe10 word rg+uemit,QJMP fd070 0063017c word CONEMIT,EXIT fd074 f803 SPACES3 word _3 fd076 007ef820 SPACES word _BL,SWAP ' ' EMITS ( ch cnt -- ) fd07a fc040072 EMITS word QDUP,_IF+04,FOR,DUP,EMIT,forNEXT,DROPEX+ex ' ?EMIT ,( ch -- ) suppress emitting the character if echo flag is off fd088 QEMIT fd088 d100f801 word w+echo,CHKFLG,SKIPZ,EMIT+ex fd090 00630069 DROPEX word DROP,EXIT ' mov txpin,#tx_pin fd094 ec44fe10 _CON word rg+uemit,CLRL,EXIT ' direct output to a smartpin (after init) fd09a 013feae4 _COM word _PIN,_WORD,WRACK fd0a0 fe10 SETEMIT word rg+uemit fd0a2 006300e8 WSTOREX word WSTORE,EXIT fd0a6 d0a1f869 NONE word w+DROP,SETEMIT+ex fd0aa d0a3fe12 SETKEY word rg+ukey,WSTOREX+ex fd0ae d05bf80c CLS word w+$0C,EMIT+ex fd0b2 d05bf807 BELL word w+7,EMIT+ex fd0b6 00ddfeb2 SPINNER word rg+spincnt,CFETCH,_3,_SHR,_3,_AND fd0c2 d59c word _STRING fd0c4 5c2d2f7c byte "|/-\ ",0 fd0ca 00dd0086 word PLUS,CFETCH fd0ce f808d05a word EMIT,_8,EMIT,rg+spincnt,CINC,_1,ms+ex ' ACCEPTED fd0dc d5b2 OK word PRTSTR fd0de 006b6f20 byte " ok",0 fd0e2 d0e8 CRLF word CR fd0e4 d05bf80a LF word w+$0A,EMIT+ex fd0e8 d05bf80d CR word _13,EMIT+ex ' emit printable ASCII or a dot otherwise fd0ec 00b7da06 AEMIT word QCHAR,_ZEQ fd0f0 0069fc02 word _IF+02,DROP fd0f4 d05bf82e DOT word w+".",EMIT+ex fd0f8 d05bf85f SCORE word w+"_",EMIT+ex fd0fc d05bf827 PRTTICK word w+"'",EMIT+ex fd100 ec30fe20 CHKFLG word rg+fflags,BITQ,EXIT fd106 ec20fe20 CLRFLG word rg+fflags,CLR,EXIT fd10c ec10fe20 SETFLG word rg+fflags,SET,EXIT ' U> SWAP U< ; fd112 eb30007e UGT word SWAP,_ULT,EXIT ' <= ( n1 n2 -- flg ) fd118 007e LTEQ word SWAP ' => ( n1 n2 -- flg ) 1- > ; fd11a eb200089 EQGT word DEC,GT,EXIT fd120 00c10077 DIVIDE word OVER,_ABS,OVER,_ABS,UDIVIDE,ROT2,_XOR,MNEGATE,EXIT ' */ ( u1 u2 div1 -- res ) ' CLKHZ 1.333333 1,000,000 LAP */ LAP .LAP 35.200us ok fd132 00c70081 MULDIV word ROT2,UMMUL,ROT,UMDIVMOD64,DROP,NIP,EXIT ' C-- fd140 d1470141 CDEC word MINUS1,CINC+2+ex ' C++ fd144 007ef801 CINC word _1,SWAP,CPLUSST,EXIT ' W-- fd14c d1530141 WDEC word MINUS1,WINC+2+ex ' W++ fd150 007ef801 WINC word _1,SWAP,WPLUSST,EXIT ' -- fd158 d15f0141 LDEC word MINUS1,LINC+2+ex ' ++ fd15c 007ef801 LINC word _1,SWAP,PLUSST,EXIT 'BOOTQ word rg+bootsig fd164 006300e1 FETCHX word FETCH,EXIT ''''''''''''''''''' SMARTPIN MODES ''''''''''''''''' { %AAAA_BBBB_FFF_PPPPPPPPPPPPP_TT_MMMMM_0 %AAAA: �� �A�� "! input selector %BBBB: �� �B�� "! input selector %FFF: �� �A�� "! and �� �B�� "! input logic/filtering (after �� �A�� "! and �� �B�� "! input selectors) %P..P: low-level pin control (needs final silicon to fully operate) %TT: pin DIR/OUT control (default = %00) %MMMMM: 00000 = smart pin off (default) ( * OUT signal overridden ) 00 100* = pulse/cycle output 00 101* = transition output 00 110* = NCO frequency 00 111* = NCO duty 01 000* = PWM triangle 01 001* = PWM sawtooth } fd168 0175eadc MUTE word _ATPIN,_FLOAT,_0,_WRPIN,EXIT fd172 00c5d224 MHZ word W1000,MUL16 fd176 00c5d224 KHZ word W1000,MUL16 fd17a d198 HZ word NCOCNT fd17c f826 NCO word w+%01_00110 ' ( Y X mode -- ) mode prescaler value ' SMART ( n mode -- ) fd17e eadc00ae SETNCO word _SHL1,_ATPIN,LOW,_WRPIN,_1,_WXPIN,_WYPIN,EXIT ' DUTY ( val -- ) $4E 100.1110 fd18e d17ff827 DUTY word w+%01_00111,SETNCO+ex ' -1/2 /CLKHZ/20000 == HZCON ' NCOCNT ( freq -- ncocnt ) HZCON #10000 */ ; fd192 014d HZCON word CONL fd194 00083126 long 536870 fd198 013fd192 NCOCNT word HZCON,_WORD,10000,MULDIV,EXIT ' BLINK ( pin -- ) fd1a2 f802eae4 BLINK word _PIN,_2,HZ+ex '--- TRIANGLE PWM MODE ' PWM ( duty frame div -- ) @PIN LOW $50 WRPIN SWAP 16 << + WXPIN WYPIN ; fd1a8 f850 PWM word w+$50 fd1aa 0153016b PWM1 word L,_WRPIN,SWAP,_SHL16,PLUS,_WXPIN,_WYPIN,EXIT fd1ba d1abf852 SAW word w+$52,PWM1+ex ' SAW ( duty frame div -- ) @PIN LOW $50 WRPIN SWAP 16 << + WXPIN WYPIN ; fd1be 04e2013f ns word _WORD,nscnt,UDIVIDE,EXIT ' transistion mode ' PW ( width -- ) fd1c6 f84a016b PW word L,w+%01_00101_0,_WRPIN,_WXPIN,EXIT fd1d0 f801 PULSE word _1 fd1d2 00630157 PULSES word _WYPIN,EXIT ' HILO ( high low -- ) fd1d6 f848016b HILO word L,w+%01_00100_0,_WRPIN,SWAP,OVERPLUS,SWAP,_SHL16,_OR,_WXPIN,EXIT ''''''''''''''' SERIAL MODES '''''''''''''''''' fd1ea ebc8f819 DL word w+tepin,COGFETCH,EXIT ' BIT ( n -- ) Set bit length of serial smartpin interface fd1f0 f8190089 BIT word DEC,w+tepin,COGSTORE,EXIT fd1f8 f87c016a TXD word H,w+$7C ' BAUD ( baud mode -- ) fd1fc d22a0153 BAUDST word _WRPIN,CLKHZ,SWAP,UDIVIDE,_SHL16,DL,_ZEQ,_IF+02,_8,BIT,DL,PLUS,_WXPIN,EXIT fd218 d1fdf83e RXD word w+$3E,BAUDST+ex { TRANSMITTING ASYNCH TAQOZ# 34 PIN 8 BIT 115200 TXD ok TAQOZ# $55 WYPIN ok TAQOZ# $41 WYPIN ok TAQOZ# @NAMES 4 TXDAT ok } ' 1098 7654 321 0987654321098 76 54321 0 ' 0 0001 000 0000000000000 01 11100 0 ' D/# = %AAAA_BBBB_FFF_PPPPPPPPPPPPP_TT_MMMMM_0 ' 11100* = sync serial transmit (A-data, B-clock) ' SYNTX ( bits -- ) L $100.0078 WRPIN 1- $20 OR WXPIN ; fd21c f878 SYNTX word w+$78 { pub TX WYPIN ; pub SERIAL ( pin -- ) PIN ' TX uemit W! ; } ''''''''''''''''''' CONSTANTS ''''''''''''''''''''' fd21e W1000000 fd21e 014d word CONL fd220 000f4240 long 1000000 fd224 014d W1000 word CONL fd226 000003e8 long 1000 fd22a 014d CLKHZ word CONL fd22c 04c4b400 long sys_clk fd230 014d CLKKHZ word CONL fd232 00013880 long sys_clk/1000 fd236 014d CLKMHZ word CONL fd238 00000050 long sys_clk/1000000 ' ADDRESS OF TAQOZ BACKUP/RESTORE IN FLASH' fd23c 014d BRORG word CONL fd23e 000f0000 long $F0000 fd242 014d BUFFERS word CONL fd244 0000f000 long $F000 fd248 014d ROM word CONL fd24a 000fc000 long $0F_C000 fd24e 014d IRQVEC word CONL fd250 000fffe0 long $0F_FFE0 { %0000_000E_DDDD_DDMM_MMMM_MMMM_PPPP_CCSS Set clock generator mode %0001_0000_0000_0000_0000_0000_0000_0000 Hard reset, reboots chip %001P_0000_0000_0000_0000_0000_0000_0000 Set write-protect of last 16KB RAM to P %01RR_0000_0000_0000_0000_0000_0LLT_TTTT Set filter R to length L and tap T %1DDD_DDDD_DDDD_DDDD_DDDD_DDDD_DDDD_DDDD Seed Xoroshiro128+ PRNG with D } fd254 d25ff801 REBOOT word w+1,HUBSW+ex fd258 d25ff802 WE word w+2,HUBSW+ex fd25c f803 WP word w+3 fd25e 00a6f81c HUBSW word w+28,_SHL fd262 0063ec8c HUBEX word _HUBSET,EXIT ' 1=80MZ 2=40MHZ 3=20MHZ 4=10MHZ 5=5MHZ fd266 00d8f801 CLKDIV word _1,_MAX,w+$1FF,SWAP,_SHR,HUBEX+ex fd272 d263f801 RCSLOW word _1,HUBEX+ex { pub 50MHZ $9F HUBSET ; pub 45.4MHZ $8F HUBSET ; pub 62.5MHZ $C7 HUBSET ; } { *** NUMBER BASE *** } ' change the default number bases fd276 f802 BIN word w+2 fd278 fe16 SETBASE word rg+base fd27a 006300e4 CSTOREX word CSTORE,EXIT fd27e d279f80a DECIMAL word w+10,SETBASE+ex fd282 d279f810 HEX word w+16,SETBASE+ex fd286 00ddfe16 GETBASE word rg+BASE,CFETCH,EXIT ' >UPPER ( str1 -- ) Convert lower-case letters to upper-case fd28c 008c TULP word INC fd28e 007200de TOUPPER word DUPCFT,QDUP,_IF+08 ' end of string? fd294 f87af861 word w+"a",w+"z",WITHIN fd29a fc88 word _UNTIL+08 fd29c 0077f8e0 word w+$E0,OVER,CPLUSST,TULP+ex ' convert case (subtract $20) fd2a4 d091 word DROPEX+ex { *** STRING TO NUMBER CONVERSION *** } fd2a6 f839f830 DECQ word w+"0",w+"9",WITHIN+ex fd2ac f846f841 HEXQ word w+"A",w+"F",WITHIN+ex ' functional test for now - optimize later ' Convert ASCII value as a digit to a numeric value - only interested in bases up to 16 at present ' fd2b2 TODIGIT ' ( char -- val true | false ) fd2b2 d2a60073 word DUP,DECQ,_IF+04 ',td8 ' only work with 0..9,A..F fd2b8 0085f830 word w+"0",MINUS fd2bc 00630141 TRUEX word _TRUE,EXIT ' pass decimal digits fd2c0 d2ac0073 td8 word DUP,HEXQ,_IF+03 ',td2 fd2c6 0085f837 word w+$37,MINUS,TRUEX+ex ' pass hex digits fd2cc 0069 td2 word DROP fd2ce 0063f800 FALX word _FALSE,EXIT { Try to convert a string to a number Allow all kinds of symbols but these are the rules for it to be treated as a number. 1. Leading character must be either a recognized prefix or a decimal digit 2. If trailing character is a recognized suffix then the first character must be a decimal digit Acceptable forms are: $1000 hex number 1000h #1000 decimal number 1000d %1000 binary number 1000b Also as long as the first character and last character are valid (0..9,prefix,suffix) then any symbols me be mixed in the number i.e. 11:59 11.59 #5_000_000 } fd2d2 00b50079 OVEQ word THIRD,_EQ,EXIT fd2d8 _NUMBER ' ( str -- value digits | false ) fd2d8 ec44fe04 word rg+4,CLRL ' REG0L = 0 fd2dc d106f820 word w+sign,CLRflg ' clear sign fd2e0 snlp fd2e0 00560073 word DUP,STRLEN,OVERPLUS,DEC,CFETCH,rg+suffix,CSTORE ' save suffix (assume string has count byte) fd2ee f82d00de word DUPCFT,w+"-",_EQ,_IF+03 ' save SIGN fd2f6 d10cf820 word w+sign,SETFLG,INC ' and use string without sign ' prefix may come after the sign fd2fc 007300de word DUPCFT,DUP,rg+prefix,CSTORE ' save prefix (it may or may not be) ' PREFIX HANDLER ' ( str ch ) fd304 f800 word _FALSE ' preset prefix flag = false ' $nnnn - set hex base - flag true fd306 d2d2f824 word w+"$",OVEQ,_IF+02,HEX,INC fd310 d2d2f823 word w+"#",OVEQ,_IF+02,DECIMAL,INC ' as does # - also set decimal base fd31a d2d2f825 word w+"%",OVEQ,_IF+02,BIN,INC ' as does % - also set binary base fd324 d2d2f826 word w+"&",OVEQ,_IF+05,DECIMAL,INC ' as does & - also set decimal base and IP notation fd32e fe87f880 word w+$80,rg+bnumber+3,CSTORE ' this forces "." symbols to work the same as ":" ' ( str ch flg ) fd334 fc030073 word DUP,_IF+03,ROT,INC,ROT2 ' adjust string pointer to skip prefix ' ( str ch flg ) fd33e d2a6007e word SWAP,DECQ,_OR ' 0..9 forces processing as a number '' ( str flg ) flg is true if a prefix is found OR the first character is 0..9 fd344 dd9feb14 word SKIPNZ,DROPFEX+ex ' ( -- false ) ' Give up now, it isn't a candiate '' ( str ) ' so far, so good, now check suffix ' SUFFIX HANDLER - must end in 0..9 or A..F or valid suffix fd348 00ddfe78 word rg+suffix,CFETCH fd34c d2a60073 word DUP,DECQ ' 0..9 fd350 d2ac0077 word OVER,HEXQ,_OR ' A..F ( str sfx flg ) true if still a digit fd356 d2d2f868 word w+"h",OVEQ,_IF+02,HEX,INC ' h = HEX fd360 d2d2f862 word w+"b",OVEQ,_IF+02,BIN,INC ' b = BINARY fd36a f864007e word SWAP,w+"d",_EQ,_IF+02,DECIMAL,INC ' d = DECIMAL fd376 dd9feb14 word SKIPNZ,DROPFEX+ex ' bad suffix, no good ' so far the prefix and suffx have been checked prior to attempt a number conversion ' From here on there must be at least one valid digit for a number to be accepted ' DIGIT EXTRACTION & ACCUMULATION fd37a nmlp fd37a 007300de word DUPCFT,DUP,_IF+(nmend-nm1)/2 ' while there is another character fd380 fc12d2b2 nm1 word TODIGIT,_IF+(nmsym-nm2)/2 ' convert to a digit? or else check symbol ' a digit has been found but is it valid for this base? ' ( str val ) fd384 d2860073 nm2 word DUP,GETBASE,DEC,GT,_IF+02 fd38e d2cf0068 FALX2 word DROP2,FALX+ex ' a digit but exceeded base fd392 00e1fe80 nmok word rg+anumber,FETCH,GETBASE,MULTIPLY ' shift anumber left one digit (base) fd39a fe800086 word PLUS,rg+anumber,STORE ' and merge in new digit fd3a0 d144fe88 word rg+digits,CINC ' update number of digits fd3a4 d37b008c nmnxt word INC,nmlp+ex ' update str and loop ' character was not a digit - check for valid symbols (keep it simple for now) ' SYMBOLS fd3a8 f83a00de nmsym word DUPCFT,w+":",_EQ ' : ENTER fd3ae 00dd0077 word OVER,CFETCH,w+".",_EQ ' . dot fd3b6 fc040073 word DUP,_IF+04,rg+digits,CFETCH,rg+dpl,CSTORE ' remember last decimal place fd3c2 00e1fe84 ns01 word rg+bnumber,FETCH,_ZNE,_AND,_OR fd3cc fc0a word _IF+10 ' Use : as special byte shift for IP notation etc fd3ce 00e1fe84 nmsym1 word rg+bnumber,FETCH fd3d2 00e1fe80 word rg+anumber,FETCH,PLUS,_SHL8 fd3da 00ecfe84 word rg+bnumber,STORE,rg+anumber,CLRL ' accumulate & number in bnumber fd3e2 d3a5 nmsym2 word nmnxt+ex ' just ignore other symbols for now ' fd3e4 nmend ' end of string - check fd3e4 fe880068 word DROP2,rg+digits,CFETCH,DUP,ZEXIT ' return with false if there are no digits fd3ee 00e1fe80 word rg+anumber,FETCH,rg+bnumber,FETCH,PLUS fd3f8 d100f820 word w+sign,CHKFLG,QNEGATE fd3fe 0063007e word SWAP,EXIT ' all good, return with number and true ' NUMBER processing -try to convert a string to a number fd402 NUMBER ' ( str -- value digits | false ) ' process control prefix i.e. ^A fd402 00560073 word DUP,STRLEN,_2,_EQ fd40a 00dd0077 word OVER,CFETCH,w+"^",_EQ,_AND,_IF+06 ' ^ch Accept caret char as char fd416 00dd008c word INC,CFETCH,w+$1F,_AND,_1,EXIT ' control character processed - single digit ' process character literal i.e. "A" fd422 00560073 ch01 word DUP,STRLEN,_3,_EQ fd42a 00dd0077 word OVER,CFETCH,DUP,w+$22,_EQ,SWAP,w+$27,_EQ fd43a 00930097 word _OR,_AND,_IF+04 ' "ch" or 'ch' Accept as an ASCII literal fd440 00dd008c ascch word INC,CFETCH,_1,EXIT ' It wasn't an ASCII literal, process as a number fd448 f80afe80 ch02 word rg+anumber,w+10,ERASE ' zero out assembled number (double), digits, dpl fd44e fe17d286 word GETBASE,rg+base+1,CSTORE ' backup current base as it may be overridden fd454 d2d8 word _NUMBER '( str -- digits num | false ) fd456 00ddfe17 nmb1 word rg+base+1,CFETCH,SETBASE+ex ' restore default base before returning ' QFNUM ( -- flg ) Test if word is a fast prefixed number fd45c QFNUM 'word _TRUE,rg+wordbuf,DUP,STRLEN,ADO,IX,CFETCH,DECQ,_AND,LOOP,QDUP,IFEXIT fd45c 00ddfe24 word rg+wordbuf,CFETCH,w+"#",w+"%",WITHIN ' Numeric prefixes? fd466 00ddfe23 word rg+wordbuf-1,CFETCH,_2,GT,_AND ' and more than 2 characters? (inc term) fd470 00defe23 word rg+wordbuf-1,DUPCFT,PLUS,CFETCH ' and last char is a digit or hex digit? fd478 d2a60073 word DUP,DECQ ' decimal digit? fd47c d2ac007e word SWAP,HEXQ,_OR,_AND ' hex digit? fd484 0063 word EXIT { *** COMPILER EXTENSIONS *** } ' Most of these words are acted upon immediately rather than compiled as they are ' part of the "compiler" in that they create the necessary structures ' ''' dumb compiler for literals - improve later - just needs to optimize the number of bytes needed fd486 LITCOMP ' ( n -- ) compile the literal according to size fd486 009d0073 word DUP,_SHR16,_IF+07 ' Compile long fd48c d5f8f93d word w+_LONG,COMPW ' compile the _LONG instruction fd490 009d0073 word DUP,_SHR16,SWAP,COMPW,COMPW+ex ' compile the long itself ' Compile 2 bytes - 16bits fd49a f80a0073 .L1 word DUP,W+10,_SHR,_IF+03 ' 10 BIT LITERAL?' fd4a2 d5f8f93f word w+_WORD,COMPW,COMPW+ex fd4a8 .L2 ' Compile short literal directly fd4a8 f800013f word _WORD,w,PLUS,COMPW+ex '''' BEGIN as in BEGIN...AGAIN or BEGIN...UNTIL generate branch for BEGIN fd4b0 f8bed68a _BEGIN_ word ATCODES,w+$BE ''' ''' MARK ( addr tag -- tag&addr ) Merge tag and addr by shifting tag into hi word fd4b4 00a6f818 MARK word w+24,_SHL fd4b8 00630097 ORX word _OR,EXIT ' UNMARK ( tag&addr -- addr tag ) fd4bc 01410073 UNMARK word DUP,MINUS1,_SHR8,_AND,SWAP,w+24,_SHR,EXIT ''' REPEAT if mark is $1F preceded by $BE mark fd4cc _REPEAT_ fd4cc d4d2007e word SWAP,_AGAIN_,_THEN_+ex ''' AGAIN if mark is $BE fd4d2 _AGAIN_ fd4d2 d4bc __AGAIN word UNMARK fd4d4 00b5f8be word w+$BE,_EQ,_IF+(badthen-ag1)/2 ' ( addr bc -- ) compile the wordcode and calculate the branch back fd4da d5f9008c ag1 word INC,COMPW+ex ''' UNTIL ( flg -- ) fd4de d4bc _UNTIL_ word UNMARK fd4e0 00b5f8be unt00 word w+$BE,_EQ,_IF+(badthen-unt1)/2 fd4e6 007ed68a unt1 word ATCODES,SWAP,MINUS,_SHR1,INC fd4f0 fc80013f word _WORD,_UNTIL,_OR,COMPW+ex ''' IF as in IF...THEN or IF...ELSE...THEN ''' WHILE fd4f8 _IF_ fd4f8 f81fd68a word ATCODES,w+$1F,MARK fd4fe fc00013f word _WORD,_IF,COMPW+ex ' compile an IF and a dummy branch (else/then will set) fd504 f81ed68a GOTO word ATCODES,w+$1E,MARK '' compile a dummy NOP to be replacd later with a goto (addr+ex) fd50a d5f9f871 word w+_NOP,COMPW+ex ' ELSE fd50e _ELSE_ fd50e d4bc word UNMARK ' ( addr tag ) '' does this match an IF? fd510 00b5f81f word w+$1F,_EQ,_IF+(badthen-.L0)/2 '' mark the else to be processed on a THEN fd516 d504 .L0 word GOTO ' '' get the IF addr and proceed as if it were a THEN fd518 f81f007e word SWAP,w+$1F,MARK ' THEN fd51e d4bc _THEN_ word UNMARK '( addr tag ) ' ' ( addr tag ) resolve structure branch '' ELSE THEN ? fd520 f81e0073 word DUP,w+$1E,_EQ,_IF+05 fd528 d68a0069 word DROP,ATCODES,INC,SWAP,WSTOREX+ex '' IF THEN ? fd532 00b5f81f word w+$1F,_EQ,_IF+8 '' update IF's branch fd538 0077d68a word ATCODES,OVER,MINUS,_SHR1,DEC,SWAP,CSTOREX+ex ' fd546 d5b2 badthen word PRTSTR fd548 72745320 byte " Structure mismatch! ",0 fd55e d091e002 word ERROR,DROPEX+ex ''''''''''''''''''''' STRINGS '''''''''''''''''''''''''' ' NULL$ fd562 00000150 NULLSTR word VARB,0 ' $! ( str1 str2 -- ) fd566 00560077 STRST word OVER,STRLEN,INC,CMOVE,EXIT ' $= ( str1 str2 -- flg ) fd570 00560077 STREQ word OVER,STRLEN,OVER,STRLEN,_EQ fd57a 0073fc0e word _IF+14,DUP,STRLEN,ADO fd582 010300da word CFETCHINC,IX,CFETCH,_NEQ,_IF+03,DROP,_0,LEAVE,LOOP,_ZNE,EXIT fd598 00010068 word DROP2,FALSE+ex ' STR ( -- n ) Leave address of inline string on stack and skip to next instruction fd59c 0073012d _STRING word RPOP,DUP,STRLEN,OVERPLUS,INC,WALIGN,AJMP ' " string" Compile a literal string - no length restriction - any codes can be included except the delimiter " fd5aa _STRING_ '' compile wordcodes for string fd5aa d59c013f word _WORD,_STRING,COMPW,COMPSTR+ex ' Print inline string fd5b2 012d PRTSTR word RPOP fd5b4 007200da .lp word CFETCHINC,QDUP,_IF+02,EMIT,.lp+ex fd5be 012ad66a word WALIGN,PUSHR,EXIT ' PRINT" HELLO WORLD" Compile a literal print string - no length restriction - any codes can be included except the delimiter " fd5c4 d5b2013f _PSTR_ word _WORD,PRTSTR,COMPW fd5ca 0073e104 COMPSTR word WKEY,DUP,QEMIT ' echo string fd5d0 f8220073 word DUP,w+$22,_NEQ,_IF+02,COMPC,COMPSTR+ex '' word align end of string with an extra null fd5dc f801d68a word ATCODES,_1,_AND,_ZEQ,_IF+02,_0,COMPC fd5ea f8000069 word DROP,_0 fd5ee 00e8d68a COMPC word ATCODES,WSTORE '' advance code write address by 1 fd5f2 d15cfea2 word rg+codes,LINC,COMPX+ex ' ( wordcode -- ) append this wordcode to next free code location + append EXIT (without counting) fd5f8 d66ad68a COMPW word ATCODES,WALIGN,WSTORE fd5fe fea2f802 word _2,rg+codes,WPLUSST '' word WALIGN '' advance code write address by 2 '' word rg+codes,STORE '' compile an EXIT after the latest codes fd604 d68af863 COMPX word w+EXIT,ATCODES,WSTOREX+ex ' C, or | ( n -- ) IMMEDIATE --- compile a byte into code and allocate fd60a d5eed636 CCOMP word GRAB,COMPC,rg+codes,WFETCH,_1,_AND,IFEXIT,ALLOCATED+ex ' W, or || ( n -- ) fd61a d627d636 WCOMP word GRAB,WCOMMA+ex ' , ( n -- ) Compile a long literal fd61e d636 LCOMP word GRAB fd620 d5f80073 COMPL word DUP,COMPW,_SHR16 fd626 d631d5f8 WCOMMA word COMPW,ALLOCATED+ex ' ALLOT ( bytes -- ) fd62a 00eafea2 ALLOT word rg+codes,PLUSST,ALLOCATED+ex ' lock in compiled code so far - do not release but set new "here" to the end of these codes fd630 ALLOCATED fd630 fe9ed68a word ATCODES,rg+here,STOREX+ex ' GRAB ( -- ) \ IMMEDIATE --- executes preceding code to make it available for any immediate words following fd636 d5f8f863 GRAB word w+EXIT,COMPW ' append an EXIT fd63a 0073d680 word ATHERE,DUP,rg+codes,STORE,ACALL ' execute and release preceding code in text line fd644 0063 word EXIT ' NFA' ( -- nfaptr ) ' COMPILE ( not used in this version ) fd646 NFATICK fd646 0089dd7c word _GETWORD,DEC,SEARCH+ex fd64c _NFATICK fd64c d487d646 word NFATICK,LITCOMP+ex ' The CPA is the address of the word code stored in the header that points to the code to execute ' 03,D,U,P,CPAL,CPAH' ' CPA ( nfa -- cpa ) fd650 f81f00da NFACPA word CFETCHINC,w+cntm,_AND,PLUS,EXIT ' ' ( -- pfa ) Find the address of the following word - zero if not found or its CFA/PFA fd65a d646 TICK word NFATICK ' CFA ( nfa -- cfa )' fd65c 00610073 NFACFA word DUP,ZEXIT,NFACPA,WFETCH,EXIT fd666 d487d65a ATICK word TICK,LITCOMP+ex fd66a f801008c WALIGN word INC,_1,_ANDN,EXIT fd672 f804 _ALIGNL word _4 ' ALIGN ( address align -- val00 ) 1- SWAP OVER + SWAP ANDN ; fd674 007e0089 _ALIGN word DEC,SWAP,OVERPLUS,SWAP,_ANDN,EXIT {HELP _HERE ( -- addr ) Address of next compilation location } fd680 00e0fe9e ATHERE word rg+here,WFETCH,EXIT ' ( -- atradr ) --- point to the attribute byte in the header of the latest name fd686 ATATR fd686 d165fe96 ATNAMES word rg+names,FETCHX+ex fd68a 00e0fea2 ATCODES word rg+codes,WFETCH,EXIT ' CREATEWORD - create a name in the dictionary using the next word encountered '' cnt,name,atr,cpa fd690 CREATEWORD fd690 dd7c word _GETWORD ' ( str ) read the next word ' CREATE$ ( str -- ) fd692 CREATESTR ' skip empty string ' fd692 eb1400de word DUPCFT,SKIPNZ,DROPEX+ex ' ' get attribute ' word rg+fflags,CFETCH,w+prset,_AND ' setup CPA field right now ' fd698 d686d68a word ATCODES,ATNAMES,DEC2,WSTORE ' build up a header in the word buffer then copy across ' get string count ( str ) fd6a0 00730089 word DEC,DUP,CFETCH,INC ' ( c+str size )' ' ( str size ) update names ptr by backwards count + cpa field fd6a8 008b0073 word DUP,INC2,NEGATE,rg+names,PLUSST '' copy it across fd6b2 007ed686 word ATNAMES,SWAP,CMOVE '' check for dictionary full ( less than 64 bytes ) fd6b8 d680d686 word ATNAMES,ATHERE fd6bc 0086f840 word w+64,PLUS,LT,ZEXIT,PRTSTR fd6c6 69442020 byte " Dictionary full! ",0 fd6da e003 word ERROR+ex ' CREATE - Create a name in the dictionary and also a VARIABLE code entry - or revectored through NOP fd6dc d6900071 CREATE word _NOP,CREATEWORD,w+VARB,COMPW,_0,ALLOT+ex ' Change the value of a constant ' pub ==! ( val 'con -- ) 2+ ! ; fd6e8 da7f008b CONST word INC2,STOREX+ex fd6ec f800d6dc _VAR word CREATE,_0,COMPL+ex ' := fd6f2 d690d636 _CON9 word GRAB,CREATEWORD,BITS9,_WORD,w,PLUS,ATNAMES,NFACPA,WSTOREX+ex ' == fd704 d690d636 _CONST word GRAB,CREATEWORD,w+CONL fd70a d620d5f8 DCOMP word COMPW,COMPL,_0,ALLOT+ex ' Identical to a constant except the call address is slightly different so a FORGET can release the data area fd712 d690d636 _DATCON word GRAB,CREATEWORD fd716 d70bf94c word w+DATCON,DCOMP+ex ' GETATR ( -- code ) fd71a f806d686 GETATR word ATNAMES,_6,_SHR,EXIT ' Create a new entry in the dictionary but also prevent any execution of code ' : fd722 PUBDEF fd722 d690 NEWDEF word CREATEWORD fd724 d10df880 REDEF word w+defining,SETFLG+ex ' flag that we have entered a definition 'MODDEF word w+modatr,SDEF+ex fd728 d72ff802 PREDEF word w+preatr,SDEF+ex fd72c f801 PRIDEF word w+priatr fd72e d722 SDEF word NEWDEF ' SETATR ( code -- ) fd730 00a6f806 SETATR word _6,_SHL,ATNAMES,CFETCH,w+cntm,_AND,_OR,ATNAMES,CSTORE,EXIT ' Update "here" pointer to point to current free position which "codes" pointer is now at ' Also unsmudge the headers tag ' fd744 ENDDEF fd744 d5f8f863 word w+EXIT,COMPW ' compile an EXIT fd748 d106f880 UNDEF word w+defining,CLRFLG,ALLOCATED+ex ' end definition and lock allocated bytes ' [C] force compilation of the next word fd74e COMPILES fd74e d10df840 word w+comp,SETFLG+ex ' ************** CASE STATEMENTS *********************8 ' SWITCH ( val -- ) fd752 da7ffe1c _SWITCH word rg+uswitch,STOREX+ex ' SWITCH@ ( -- val ) fd756 d165fe1c SWFETCH word rg+uswitch,FETCHX+ex ' SWITCH= ( val -- flg ) fd75a ISEQ fd75a 00b5d756 word SWFETCH,_EQ,EXIT ' CASE ( compare -- ) fd760 d75a013f _CASE word _WORD,ISEQ,COMPW,_IF_+ex ' BREAK fd768 d5f8f863 ISEND word w+EXIT,COMPW,_THEN_,ALLOCATED+ex ' SWITCH>< ( from to -- flg ).. fd770 ISWITHIN fd770 0081d756 word SWFETCH,ROT2,WITHIN+ex { Table vectoring - index a table of vectors and jump to that vector A table limit is supplied as well as a default vector Usage: VECTORS ...... ) Sample: 4 LOOKUP BELL \ an index of 4 or more will default to BELL INDEX0 INDEX1 INDEX2 INDEX3 \ 0 to 3 will execute corresponding vectors } { ' LOOKUP ' VECTORS ( index range -- ) VECTORS word OVER,GT,_ZEQ,_IF+02,DROP,MINUS1 ' limit index to range or -1 (.>0) .L0 word INC,_SHL1,RPOP,PLUS,WFETCH,ACALL,EXIT } ' ( n lo hi -- flg ) true if n is within range of low and high inclusive fd776 0077008c WITHIN word INC,OVER,MINUS,PUSHR fd77e 012d0085 word MINUS,RPOP,_ULT fd784 006300b9 WT1 word _ZNE,EXIT { *** MOVES & FILLS *** } ' D during text input fd948 e076 DEBUG word PRTSTKS fd94a d5b2 word PRTSTR fd94c 45520a0d byte $0D,$0A,"REGS ",0 fd954 f900fe00 word rg+temp,w+$100,DUMPW fd95a d5b2 word PRTSTR fd95c 4f430a0d byte $0D,$0A,"CODE ",0 fd964 f820d680 word ATHERE,_32,MINUS,w+64,DUMPW fd96e d5b2 word PRTSTR fd970 4f570a0d byte $0D,$0A,"WORDS",0 fd978 f840d686 word ATNAMES,w+$40,DUMPB fd97e d98ed0e2 word CRLF,lsio fd982 d0e3 word CRLF+ex fd984 d5b2d0e2 PRTP word CRLF,PRTSTR fd988 003a500d byte $0D,"P:",0 fd98c 0063 word EXIT fd98e lsio fd98e d984 word PRTP fd990 f800f83e word w+62,_0,DO,IX,w+10,DIVIDE,PRINT,LOOP fd9a0 d984 word PRTP fd9a2 f800f83e word w+62,_0,DO,IX,w+10,UMOD,PRINT,LOOP fd9b2 d5b2d0e2 word CRLF,PRTSTR fd9b6 003a3d0d byte $0D,"=:",0 fd9ba f800f83e word w+62,_0,DO fd9c0 01730103 word IX,LOW,w+200,WAIT,IX,_FLOAT,w+200,WAIT,IX,PINTEST,_1,_AND,_SHL1 fd9da 01710103 word IX,HIGH,w+200,WAIT,IX,_FLOAT,w+200,WAIT,IX,PINTEST,_1,_AND,_OR fd9f4 d59c word _STRING fd9f6 68637e64 byte "d~ch ",0 fd9fc 00dd0086 word PLUS,CFETCH,EMIT,LOOP fda04 0063 word EXIT fda06 f8200073 QCHAR word DUP,_BL,w+$7E,WITHIN+ex fda0e 00b7da06 TOCHAR word QCHAR,_ZEQ,_IF+02,DROP,w+$20,EXIT ' @PAD ( -- addr ) pointer to current position in number pad fda1a 00ddfe65 ATPAD word rg+padwr,CFETCH,rg+numpad,PLUS,EXIT ' >CHAR ( val -- ch ) convert binary value to an ASCII character fda24 0093f83f BINASC word w+$3F,_AND,w+"0",PLUS,DUP,w+"9" ' convert to "0".."9" fda30 f807eb20 word GT,_7,_AND,PLUS ' convert to "A".. fda38 f85d0073 word DUP,w+$5D,GT,ZEXIT,_3,PLUS,EXIT ' skip symbols to go to "a".. ' <# ' resets number pad write index to end of pad fda46 fe65f81a LHASH word w+numpadsz,rg+padwr,CSTORE,_0 ''' ' HOLD ( char -- ) fda4e d140fe65 HOLD word rg+padwr,CDEC,ATPAD,CSTOREX+ex ' # ( n1 -- n2 ) convert the next ls digit of a double to a char and prepend to number string fda56 00e1fe0c HASH word rg+double,FETCH,GETBASE,UMDIVMOD64,rg+double,STORE fda62 da24007e word SWAP,BINASC,HOLD+ex ' conversion digits exhausted, use zeros or spaces ' #S ( d1 -- 0 ) Convert all digits fda68 0073da56 HASHS word HASH,DUP,_ZEQ,_UNTIL+04,EXIT ' #> ( n1 -- caddr ) fda72 da1a0069 RHASH word DROP,ATPAD,rg+double,CLRL,EXIT ' ( d1 -- n1 ) ' Store high long of double for formating fda7c fe0c DNUM word rg+double fda7e 006300ec STOREX word STORE,EXIT ' . ( n -- ) Print the number off the stack fda82 PRINT fda82 00bf0073 PRT word DUP,_ZLT,_IF+03,w+"-",EMIT,NEGATE ''' ' U. ( n -- ) Print an unsigned number fda8e da68da46 UPRT word LHASH,HASHS,RHASH ''' ' PRINT$ ( adr -- ) Print the null or 8th bit terminated string - stops on any non-printable character fda94 PRINTSTR fda94 008c0073 word DUP,INC,SWAP,DCFETCH,QDUP,_IF+02,EMIT,PRINTSTR+ex fdaa4 d8830069 pstrxt word DROP,RAM+ex ' since printing a 32-bit binary number with formatting can be quite long, this one prints directly fdaa8 d05af825 PRTBIN word w+"%",EMIT,_BL,FOR,DUP,w+31,_SHR,w+"0",PLUS,EMIT,_SHL1,forNEXT,DROPEX+ex { .AS" Format string spec: # Convert one digit (default is decimal) ~ Toggle leading zero suppression \ pad leading zeros with spaces $| Hexadecimal *| Convert all remaining digits 4| Convert 4 digits } fdac2 00970076 DZEQ word DUP2,_OR,_ZEQ,EXIT fdaca f802dac2 AHASH word DZEQ,_2,rg+pflg,BITQ,_AND,_IF+02,w+$20,HOLD+ex,rg+pbase,CFETCH,UMDIVMOD64,ROT,BINASC,HOLD+ex fdae6 f804d752 ASHASH word _SWITCH,_4,rg+pflg,BITQ,_NOT,_4,rg+pflg,CLR,_IF+(ASCMD-.L3)/2 fdaf8 d75af87c .L3 word w+"|",ISEQ,_IF+04,_4,rg+pflg,SET,EXIT fdb06 d75af87e word w+"~",ISEQ,_IF+03,rg+pflg,CINC,EXIT fdb12 d75af85c word w+"\",ISEQ,_IF+04,_2,rg+pflg,SET,EXIT fdb20 f801dac2 word DZEQ,_1,rg+pflg,BITQ,_AND,IFEXIT fdb2c d75af823 word w+"#",ISEQ,_IF+(ASONE-.L0)/2 fdb32 dacb .L0 word AHASH+ex '' $| command - hexadecimal fdb34 d75af824 ASCMD word w+"$",ISEQ,_IF+03,_16,rg+pbase,CSTOREX+ex '' n| multiple # command 3 TO 9 fdb40 f833d756 word SWFETCH,w+"3",w+"9",WITHIN,_IF+07,SWFETCH,w+"0",MINUS,FOR,AHASH,forNEXT,EXIT '' *| Convert remaining digits fdb58 d75af82a .L2 word w+"*",ISEQ,_IF+05,DUP2,_OR,ZEXIT,AHASH,.L2+ex '' [| send an escape fdb68 d75af85b word w+"[",ISEQ,_IF+02,w+$1B,AHOLD+ex '' @| treat simply as ASCII fdb72 d75af840 word w+"@",ISEQ,_IF+03,OVER,BITS8,AHOLD+ex '' literal character fdb7e da4fd756 ASONE word SWFETCH,HOLD+ex fdb82 da4fda0e AHOLD word TOCHAR,HOLD+ex fdb86 0073012d PRTAST word RPOP,DUP,STRLEN,INC2,_1,_ANDN,OVERPLUS,PUSHR fdb96 ec5cfe66 PRTAS word rg+pflg,CLRC,w+10,rg+pbase,CSTORE fdba0 00e1fe0c word rg+double,FETCH,SWAP,LHASH,DUP,STRLEN fdbac 00750089 word DEC,OVERPLUS,rg+pfmt,STORE,STRLEN fdbb6 fe68010d word FOR,rg+pfmt,FETCH,CFETCH,ASHASH,rg+pfmt,LDEC,forNEXT fdbc6 da720069 word DROP,RHASH,PRINTSTR+ex fdbcc db86013f PRTASR word _WORD,PRTAST,COMPW,COMPSTR+ex fdbd4 db86 PRTDECL word PRTAST fdbd6 232c2323 byte "##,###,###,##~#",0 fdbe6 0063 word EXIT fdbe8 db86 PRTDEC4 word PRTAST fdbea 5c232323 byte "###\#",0 fdbf0 0063 word EXIT fdbf2 db86 PRTDEC2 word PRTAST fdbf4 0023232e byte ".##",0 fdbf8 0063 word EXIT { PRTDEC2D word PRTAST byte "##.",0 word EXIT } ' Print decimal with at least a single digit fdbfa db86 PRTDEC word PRTAST fdbfc 00237c2a byte "*|#",0 fdc00 0063 word EXIT '--------------------------------------------------- { *** CONSOLE INPUT HANDLERS *** } { Replaced traditional parse function with realtime stream parsing Each word is acted upon when a delimiter is encountered and this also allows for interactive error checking and even autocompletion. } ' SCRUB --- scrub out any temporary compiled code, restore the code pointers etc. fdc02 fea2d680 SCRUB word ATHERE,rg+codes,STORE fdc08 ec5cfe23 word rg+wordcnt,CLRC,rg+wordbuf,CLRC '' restore end-of-line delimiter to a CR fdc10 fe6df80d word _13,rg+delim+1,CSTORE '' print long line of dashes fdc16 f82dd0e8 PRTDASH word CR,w+"-",w+64,EMITS+ex ' ( ch -- ) write a character into the next free position in the word buffer fdc1e 00dafe23 PUTCHAR word rg+wordcnt,CFETCHINC,PLUS,CSTOREX+ex fdc26 PUTCHARPL fdc26 fe23dc1e word PUTCHAR,rg+wordcnt,DUPCFT,INC fdc2e 00cdf827 word w+wordsz,UMOD,SWAP,CSTOREX+ex ' As characters are accepted from the input stream, checks need to be made for delimiters, ' editing commands etc. 123us/CHAR, 184us/CTRL fdc36 doCHAR ' ( char -- flg ) Process char into wordbuf and flag true if all done ' ignore null fdc36 00610073 word DUP,ZEXIT ' delimiter is always last character fdc3a fe6d0073 word DUP,rg+delim+1,CSTORE ' Replace DEL with BS fdc40 0077f87f word w+$7F,OVER,_EQ,_IF+02,DROP,_8 ' only check for control characters fdc4c f8200073 dch1 word DUP,_BL,LT,_IF+(ischar-ctrls)/2 ' ' PROCESS CONTROL CHARACTERS ' fdc54 ctrls '' discard LF fdc54 0077f80a word w+$0A,OVER,_EQ,SKIPZ,DROPFEX+ex '' ^W WORDS fdc5e 0077f817 word w+$17,OVER,_EQ,_IF+04,DROP,WORDS,CRLF,FALX+ex '' ^R FIXDICT '' word w+$12,OVER,_EQ,_IF+03,DROP,FIXDICT,FALX+ex ' ^X reeXecute previous compiled line fdc6e 0077f818 word w+$18,OVER,_EQ,_IF+02,DROP,TRUEX+ex '' ^C RESET fdc7a 0077f803 word _3,OVER,_EQ,SKIPZ,RESET ' ^R RESTORE fdc84 0077f812 word w+$12,OVER,_EQ,_IF+03,DROP,RESTORE,TERMINAL '' ^V VERSION fdc92 0077f816 word w+$16,OVER,_EQ,_IF+02,PRTVER,CONSOLE+ex ' ^D DEBUGGER fdc9e 0077f804 word _4,OVER,_EQ,_IF+03,DROP,DEBUGGER,FALX+ex ' ^? DEBUG fdcac 0077f81f word w+$1F,OVER,_EQ,_IF+03,DROP,DEBUG,FALX+ex ' ^Q print top stack fdcba 0077f811 word w+$11,OVER,_EQ,_IF+04,DROP,PRTSTK,CRLF,FALX+ex ' ^S clear Stack fdcca 0077f813 word w+$13,OVER,_EQ,_IF+03,DROP,INITSP,FALX+ex ' ^B Block dump fdcd8 0077f802 word _2,OVER,_EQ,_IF+06,DROP fdce2 f900f800 word _0,w+$100,_SHL8 fdce8 d2cfd86c word DUMPB,FALX+ex ' ^Z^Z cold start fdcec 0077f81a word w+$1A,OVER,_EQ '''rg,prevch+1,CFETCH,w+$1A,_EQ,_AND fdcf2 0069fc03 word _IF+03,DROP,COLDST,RESET '''SCRUB,FALX+ex fdcfa ignore2 fdcfa 0077f81b word w+$1B,OVER,_EQ,_IF+03,DROP,SCRUB,TRUEX+ex ' ESC will cancel line fdd08 0077f809 ig01 word _9,OVER,_EQ,_IF+02,EMIT,_BL ' TAB - substitute with a space fdd14 0077f81c ig02 word w+$1C,OVER,_EQ,_IF+03,DROP,CRLF,_BL ' ^| - multi-line interactive fdd22 0077f80d ig03 word _13,OVER,_EQ,_IF+02,DROP,TRUEX+ex ' CR - Return & indicate completion fdd2e ig04 ' fdd2e 0077f808 word _8,OVER,_EQ,_IF+(ischar-bksp1)/2 ' BKSP - null out last char fdd36 00ddfe23 bksp1 word rg+wordcnt,CFETCH,_IF+09 ' don't backspace on empty word fdd3c d058d05a bksp2 word EMIT,SPACE,_8,EMIT ' backspace and clear fdd44 d140fe23 word rg+wordcnt,CDEC,_0,PUTCHAR ' null previous char fdd4c d2cf word FALX+ex '' ' fdd4e d05af807 bksp3 word _7,EMIT,DROPFEX+ex ' can't backspace anymore, bell ' fdd54 d100f801 ischar word w+echo,CHKFLG,_IF+02,DUP,EMIT ' don't echo if we don't want it fdd5e 00ddfe6c .L0 word rg+delim,CFETCH,OVER,_EQ ' delimiter? (always accept a blank) fdd66 f8200077 word OVER,_BL,_EQ,_OR,_IF+04,DROP,rg+wordcnt,CFETCH,EXIT ' true if trailing delimiter - all done (flg=cnt) ' ' otherwise build text in wordbuf - null terminated with a preceding count ..... fdd78 d2cfdc26 .L1 word PUTCHARPL,FALX+ex ' put a character into the word buffer ' Build a delimited word in wordbuf for wordcnt and return immediately upon a valid delimiter fdd7c _GETWORD ' ( -- str ) ' Erase the word buffer & preceding count fdd7c f827fe23 word rg+wordcnt,w+wordsz,ERASE 'word w+6,PEN ' get another character fdd82 dc36e104 word WKEY,doCHAR,_UNTIL+03 'word PLAIN fdd88 0063fe24 word rg+wordbuf,EXIT { ****************** DICTIONARY SEARCH ********************** } ' SEARCH ( cstr -- nfaptr ) ' cstr points to the count+strinw+null fdd8c SEARCH fdd8c ec64fe7e word rg+ufind,QJMP ' use alternative method if enabled (hash search) fdd90 d6860073 word DUP,ATNAMES,FINDSTR fdd96 fc020072 word QDUP,_IF+02,NIP,EXIT ' found it - return now with result fdd9e d2cf0069 DROPFEX word DROP,FALX+ex ' not found in dictionary ' Discard the current line fdda2 DISCARD fdda2 00b7e0b2 dslp word KEY,_ZEQ,_UNTIL+03 ' fast discard fdda8 d7a0f814 ds01 word w+20,ms,KEY,_ZEQ,_UNTIL+08,EXIT ' pause and check and repeat if necessarys fddb4 ebdc ATID word _COGID ' TASK ( cog -- addr ) Return with address of task control register in "tasks" fddb6 00a6f803 TASK word _3,_SHL,_WORD,tasks,PLUS,EXIT { TASK RECORD 0 ENTRY CODE ADDRESS 4 flags } fddc2 ea00 IDLE word INITSTKS fddc4 f808ddb4 word ATID,_8,ERASE fddca ddb4f801 idlp word _1,ATID,_3,PLUS,CPLUSST ' increment task+3 to indicate Tachyon running fddd4 d7a0f80a word w+10,ms ' do nothing for a bit - saves power fddd8 00e0ddb4 word ATID,WFETCH ' fetch cog's task variable fdddc fc8b0072 word QDUP,_UNTIL+11 ' until it is non-zero fdde0 002d word ACALL ' Execute fdde2 ec50ddb4 word ATID,CLRW ' clear run address only if it has returned back to idle fdde6 ddc3 word IDLE+ex fdde8 fea6d65a AUTORUN word TICK,rg+autovec,WSTOREX+ex fddee 33253130 radix byte "01%34567o9#BCDEF$ " '' List line number if enabled fde00 PROMPT '' execute user prompt code fde00 00e0fe70 word rg+uprompt,WFETCH,QDUP,_IF+02,ACALL,trl1+ex fde0c 00e0feae word rg+linenum,WFETCH,_IF+08 '' display line# fde12 feaed0e8 word CR,rg+linenum,WFETCH,PRTDEC4,SPACES3 '' increment line# fde1c d150feae word rg+linenum,WINC,EXIT '' Prompt with version and base fde22 d5b2 word PRTSTR fde24 4f514154 byte "TAQOZ",0 '' prompt char = base %#$ etc fde2a 013fd286 word GETBASE,_WORD,radix,PLUS,CFETCH,EMIT,SPACE+ex ' COLD Force factory defaults fde38 COLDST fde38 FIXDICT ' Copy dictionary from ROM to area just before copied ROM in bank 0' fde38 013d word _LONG fde3a 000ff478 long romdict fde3e 013d word _LONG fde40 0000b400 long ramdict fde44 0b52013f word _WORD,enddict-romdict,CMOVE '' initialize task registers fde4a f900fe00 word rg+0,w+$100,ERASE '' free memory backup fde50 1000013f word _WORD,codeorg fde54 fe9e0073 word DUP,rg+here,STORE,rg+here-4,STORE fde5e ed64013f word _word,endcode,DATORG fde64 013d word _LONG fde66 0000b400 long ramdict fde6a 00ecfe96 word rg+names,STORE '' word DUP,rg+names,STORE,rg+oldnames,STORE ' reset cold start fde6e d5b2d094 XCOLD word _CON,PRTSTR fde72 200a0d78 byte "x",$0D,$0A," Cold start",0 fde82 a55a013f word _WORD,$A55A,rg+cold,WSTOREX+ex { *** MAIN TERMINAL CONSOLE *** } fde8a TERMINAL fde8a e9b4ea0c word InitRP,INITSP ' Init the internal stack and setup external stack space fde8e f832d25c word WP,w+50,ms ' a little startup delay (also wait for serial cog) fde94 f960f810 word w+$10,w+$160,ERASE '' performing a check for a saved session fde9a 00e0feaa word rg+cold,WFETCH,_WORD,$A55A,_NEQ,SKIPZ,COLDST fdea8 d094 word _CON fdeaa ec50fe14 word rg+keypoll,CLRW,rg+accept,CLRW fdeb2 ec50feae word rg+linenum,CLRW fdeb6 fe20f801 word _1,rg+fflags,WSTORE '' Show VERSION with optional CLS (default CR) 'word w+3,PEN fdebc d0e2 word CRLF 'word REVERSE fdebe d0e2dc16 word PRTDASH,CRLF,PRTVER '' word _GETRND,rg+bootsig,STORE '' ^A abort autostart with ^A fdec4 00ddf8f0 word w+lastkey,CFETCH,_1,_NEQ,_IF+(CS1-.L0)/2 '' check for an AUTORUN fdece 00e0fea6 word rg+autovec,WFETCH,QDUP,SKIPZ,ACALL '' Set the rx buffer size fded8 d27e .L0 word DECIMAL '' echo on fdeda fe20f801 word w+echo,rg+fflags,CSTORE '' default delimiter is a space character fdee0 fe6cf820 word _BL,rg+delim,CSTORE '' word MOUNT '' word w+"!",w+rxbuffers,CSTORE ' fdee6 dc02ea0c CONSOLE word InitRP,SCRUB,CRLF '',PLAIN '' Stop compilation fdeec d106f880 CS1 word w+defining,CLRFLG ' ' *** Main console line loop - get a new line (word by word) *** ' '------------------------------------------------------------- fdef0 de00 LINELP word PROMPT '' reset temporary code compilation pointer fdef2 fea2d680 trl1 word ATHERE,rg+codes,STORE ' '' Main console loop - read a word and process fdef8 dd7c WORDLP word _GETWORD fdefa fe21f804 word _4,rg+fflags+1,CLR '' ignore empty string fdf00 00b700dd word CFETCH,_ZEQ,_IF+(EVAL-.L0)/2 '' ^X then repeat last line fdf06 00ddfe6d .L0 word rg+delim+1,CFETCH,w+$18,_NEQ,_IF+(execinp-.L2)/2 '' Otherwise process ENTER fdf10 00ddfe6d .L2 word rg+delim+1,CFETCH,_13,_NEQ,_IF+(chkeol-EVAL)/2 '' good, try to process this as a number first (for speed) fdf1a 00b7d45c EVAL word QFNUM,_ZEQ,_IF+(TRYNUM-trm4)/2 '' otherwise search the dicitonary for a match (as a counted string) fdf20 0089fe24 trm4 word rg+wordbuf,DEC,SEARCH '' found it fdf26 fc360072 word QDUP,_IF+(TRYNUM-foundword)/2 '' found the word in the dictionary - compile or execute? fdf2a foundword ' point to attribute word (CNT,,ATR,CPA) fdf2a d65c0073 word DUP,NFACFA ' ( cpa cfa ) '' is the immediate bit set? fdf2e 00dd007e word SWAP,CFETCH,_6,_SHR,w+preatr,_EQ '' and comp flag off (not forced to compile with [COMPILE]) fdf3a d100f840 word w+comp,CHKFLG,_ZEQ,_AND '' Fetch and EXECUTE code immediately fdf42 002dfc02 word _IF+02,ACALL,chkeol+ex fdf48 compword '' or else COMPILE the wordcode(s) for this word fdf48 d5f8 word COMPW '' reset any forced compile mode via [COMPILE] fdf4a d106f840 word w+comp,CLRFLG '' *** END OF LINE CHECK *** fdf4e 00ddfe6d chkeol word rg+delim+1,CFETCH,_13,_EQ fdf56 fc040073 word DUP,_IF+(eol01-.L0)/2 '' Yes, put a space between any user input and response fdf5a 00e0fe72 .L0 word rg+accept,WFETCH,SKIPNZ,SPACE '' word PROMPT '' and are we in a definition or interactive? fdf62 f8800073 eol01 word DUP,w+defining,CHKFLG,_AND '' If not interactive then CRLF (no other response) fdf6a d0e2fc01 word SKIPZ,CRLF '' do not execute if still defining fdf6e d100f880 eol02 word w+defining,CHKFLG,_ZEQ,_AND '' wait until CR to execute compiled codes fdf76 fcc0 word _UNTIL+(.L0-WORDLP)/2 fdf78 .L0 fdf78 execs '' EXECUTE CODE from user input (append an EXIT first) fdf78 d5f8f863 word w+EXIT,COMPW '' execute wordcodes from beginning fdf7c 002dd680 execinp word ATHERE,ACALL '' execute accept vector if 0<> fdf80 00e0fe72 word rg+accept,WFETCH,QDUP,_IF+02,ACALL,LINELP+ex fdf8c 00e0feae word rg+linenum,WFETCH,SKIPNZ,OK,LINELP+ex '------------------------------------------------------------- fdf96 TRYNUM '' Attempt to process this word as a number but check for special literals first (^ ' etc) fdf96 d402fe24 word rg+wordbuf,NUMBER,_IF+02 '' is it a number? ( value digits ) fdf9c df4fd486 compnum word LITCOMP,chkeol+ex '' Unknown word or number - try converting case first time fdfa0 00ddfe21 UNKNOWN word rg+fflags+1,CFETCH,_4,_AND,_ZEQ fdfaa f804fc06 word _IF+06,_4,rg+fflags+1,CPLUSST fdfb2 d28efe24 word rg+wordbuf,TOUPPER,trm4+ex '' UNKNOWN - try unum vector if set fdfb8 00e0fe7c word rg+unum,WFETCH,QDUP,_IF+02,ACALL,chkeol+ex ' ' Failed all searches and conversions!!!! ' '' interactive or in the middle of a definition? fdfc4 fe20f880 word w+defining,rg+fflags,CFETCH,_AND,_IF+(HUH-nfdef)/2 '' Display position in line of error fdfce d5b2 nfdef word PRTSTR fdfd0 20200909 byte 9,9," error in ",0 fdfde 008cd686 word ATNAMES,INC,PRINTSTR,PRTSTR fdfe6 74612020 byte " at ",0 '' Spit out offending word fdfec da94fe24 word rg+wordbuf,PRINTSTR,SPACE '' discard but echo remainder of line fdff2 0073e0b2 .L0 word KEY,DUP,_13,_NEQ,_IF+02,EMIT,.L0+ex fe000 0069 .L1 word DROP '' count errors and force a new line to display error fe002 d150feac ERROR word rg+errors,WINC,w+$10A,EMIT fe00a d5b2 ERRSTR word PRTSTR fe00c 72652a20 byte " *error* ",7,$0D,$0A,$0B,0 ' '' force a new line to prevent overwrite then return to console fe01a d05af90a word w+$10A,EMIT,DISCARD,INITSP,_END,CONSOLE+ex ' as-you-go error prompt in interactive mode fe026 d5b2 HUH word PRTSTR fe028 3f3f3f20 byte " ??? ",0 fe02e def9 word WORDLP+ex fe030 d5b2d0e2 PRTSTK word CRLF,PRTSTR fe034 54414420 byte " DATA STACK (",0 fe042 0073ed50 word _DEPTH,DUP,PRINT1 fe048 0061 word ZEXIT fe04a 0073ed50 word _DEPTH,DUP,_0 fe050 d0e2010b word DO,CRLF,IX,INC,PRINT,SPACES3,DEC,DUP,INC4,LUTFETCH,DUP,PRTL,SPACES3,PRINT,LOOP fe06e d091 word DROPEX+ex fe070 f829da82 PRINT1 word PRINT,w+")",EMIT+ex fe076 e030 PRTSTKS word PRTSTK fe078 d5b2d0e2 PRTRET word CRLF,PRTSTR fe07c 54455220 byte " RETURN (",0 fe086 f814f840 word w+retstk,w+retptr fe08a 0076ebc8 PRTSTKX word COGFETCH,DUP2,SWAP,MINUS,PRINT1 fe094 007ed074 DMPSTK word SPACES3,SWAP fe098 00bc0076 .L0 word DUP2,_NEQ,_IF+06,DUP,LUTFETCH,SPACE,PRTL,INC,.L0+ex,DROP2,EXIT ' KEY! ( ch -- ) Force a character as the next KEY read fe0ae PUTKEY fe0ae da7ffe74 word rg+keychar,STOREX+ex ' KEY ( -- ch ) if ch is zero then no key was read fe0b2 KEY fe0b2 00ddfe74 word rg+keychar,CFETCH,QDUP,_IF+06 ' read a "key" that was forced with KEY! fe0ba 00e1fe74 word rg+keychar,FETCH,_SHR8,rg+keychar,STORE,CHKKEY+ex fe0c6 00e0fe12 word rg+ukey,WFETCH,_IF+06,rg+ukey,WFETCH,ACALL fe0d2 005e0073 word DUP,IFEXIT,DOPOLL+ex fe0d8 ea4c CONKEY word READRX fe0da fc070073 DOKEY word DUP,_IF+07 fe0de 007300b3 word BITS8,DUP,_ZEQ,ZEXIT ' return as if non-zero fe0e6 0086f900 word w+$0100,PLUS,EXIT ' otherwise add $100 to a null ' fe0ec ec64fe14 DOPOLL word rg+keypoll,QJMP ' execute background polling while waiting for input fe0f0 0063 word EXIT ' keep a track of the position of the this key on the input line (useful for assembler etc) fe0f2 d144fe22 CHKKEY word rg+keycol,CINC,DUP,_13,_EQ,ZEXIT,rg+keycol,CLRC,EXIT ' background polling while waiting for a key ' WKEY ( -- ch ) wait for a key and return with character fe104 0072e0b2 WKEY word KEY,QDUP,_UNTIL+03,BITS8,EXIT { *** COMMENTING *** } '' \ ( -- ) '' Ignore following text till the end of line. '' IMMED fe10e COMMENT fe10e 00ddfe6d word rg+delim+1,CFETCH,_13,_NEQ,ZEXIT ' ignore is this is an empty line fe118 f80de0b2 .L0 word KEY,_13,_EQ,_UNTIL+04 ' terminate comment on a CR fe120 fe74f80d word _13,rg+keychar,STOREX+ex ' force a CR back into the key stream on exit fe126 0073e0b2 PAREN word KEY,DUP,QEMIT,w+")",_EQ,_UNTIL+06,EXIT fe134 00b7d646 IFDEF word NFATICK,_ZEQ,ZEXIT,BRACE+ex fe13c 0061d646 IFNDEF word NFATICK,ZEXIT '''' ' Block comments - allow nested operation '''' fe140 BRACE fe140 f801 word _1 ' allow nesting by counting braces fe142 e104 .LP word WKEY ' keep reading each char until we have a matching closing brace fe144 f87b0073 word DUP,w+"{",_EQ,_IF+03,DROP,INC,.LP+ex ' add up opening braces fe152 00b5f87d word w+"}",_EQ,SKIPZ,DEC ' count down closing braces fe15a 00b70073 word DUP,_ZEQ,_UNTIL+15,DROPEX+ex ' 06,F,O,R,G,E,T,CODEL,CODEH fe162 d636d646 FORGET word NFATICK,GRAB,QDUP,_IF+17 fe16a 00de0073 word DUP,DUPCFT,PLUS,_3,PLUS,rg+names,STORE fe178 008600de word DUPCFT,PLUS,INC,WFETCH,DUP,rg+here,STORE fe186 007ef863 word w+EXIT,SWAP,WSTOREX+ex fe18c NOTFOUND fe18c d5b2 word PRTSTR fe18e 746f6e20 byte " not found ",0 fe19a 0063 word EXIT ' >W fe19c 0091f810 TOW word w+16,BITS,EXIT ' L>W fe1a2 e19c0073 L2W word DUP,TOW,SWAP,_SHR16,EXIT ' W>B ( word bytel byteh ) fe1ac 00b30073 W2B word DUP,BITS8,SWAP,_SHR8,BITS8,EXIT fe1b8 0136e1c2 B2L word B2W,PUSHL,B2W,LPOP fe1c0 00ac W2L word _SHL8 fe1c2 d4b900ac B2W word _SHL8,ORX+ex ' CTYPE ( str cnt -- ) fe1c6 0103010a CTYPE word ADO,IX,CFETCH,TOCHAR,EMIT,LOOP,EXIT ' .VER fe1d4 PRTVER fe1d4 d5b2 word PRTSTR '12345678901234567890123456789012345678901234567890123456789011' fe1d6 61502020 byte " Parallax P2 .:.:--TAQOZ--:.:. V",0 fe1fa d04c013f word _WORD,@taqoz_version,FETCH,PRTAST fe202 2e237e23 byte "#~#.#--",0 fe20a d054013f word _WORD,@taqoz_name,_4,CTYPE fe212 d076f809 word w+9,SPACES,_WORD,@taqoz_time,FETCH,PRTAST fe21e 342d7c36 byte "6|-4|",0 fe224 d0e3 word CRLF+ex { 00.2488: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ DICTIONARY 00.D000: 03 44 55 50 6B 00 04 32 44 55 50 6D 00 04 4F 56 .DUPk..2DUPm..OV 00.D010: 45 52 6E 00 04 44 52 4F 50 61 00 05 32 44 52 4F ERn..DROPa..2DRO 00.D020: 50 60 00 04 53 57 41 50 75 00 05 32 53 57 41 50 P..SWAPu..2SWAP 00.D030: 50 0D 03 52 4F 54 7A 00 04 2D 52 4F 54 79 00 03 P..ROTz..-ROTy.. } fe226 d686d0e2 WORDS word CRLF,ATNAMES fe22a ec44feb2 word rg+spincnt,CLRL fe22e 00e0feb2 .l0 word rg+spincnt,WFETCH,w+70,GT,_IF+03,CRLF,rg+spincnt,CLRW fe23e fc1100de word DUPCFT,_IF+17 fe242 d150feb4 word rg+spincnt+2,WINC ' track width ' fe246 f81f00de word DUPCFT,w+cntm,_AND,INC,rg+spincnt,WPLUSST fe252 00da0073 word DUP,CFETCHINC,w+cntm,_AND,CTYPE,SPACE,NFACPA,INC2,.l0+ex fe264 feb40069 word DROP,rg+spincnt+2,WFETCH,SPACE,PRTDEC+ex { PRT3S word LHASH,HASH,HASH,HASH,w+".",HOLD,HASHS,RHASH,PSTR+ex PRTF word CLKHZ,_WORD,10000,UDIVIDE,DUP,w+100,UMOD,_IF+02 word PRT3S,.L0+ex word w+100,UDIVIDE,PRINT .L0 word PRTSTR byte "MHz",0 word EXIT } fe26e ELAPSED fe26e 01c3ea80 LAPCAL word LAPFETCH,LAP,LAP,LAPFETCH,MINUS,EXIT ' .LAP LAP@ LAP LAP LAP@ - DUP DEC . ." cycles = " fe27a e26e PRTLAP word LAPCAL fe27c d27e0073 PRTCYC word DUP,DECIMAL,PRINT,PRTSTR fe284 63796320 byte " cycles = ",0,0 '' DUP CLKHZ < IF 100 * 3 >> ELSE fe290 d22a0073 REPLAP word DUP,CLKHZ,LT,_IF+17,w+100,MULTIPLY,_3,_SHR,.L0+ex '' CLKHZ U// PRINT DOT #1000 CLKHZ */ PRINT ." sec" EXIT THEN fe2a2 00cad22a word CLKHZ,UDIVMOD,PRINT,DOT,W1000,CLKHZ,MULDIV,PRINT,PRTSTR fe2b4 00636573 byte "sec",0 fe2b8 0063 word EXIT '' DUP #999999 > IF #1,000,000 U// PRINT DOT #1000 U/ PRINT ." ms " EXIT THEN fe2ba d21e0073 .L0 word DUP,W1000000,EQGT,_IF+11,W1000000,UDIVMOD,PRINT,DOT,W1000,UDIVIDE,PRINT,PRTSTR fe2d2 0020736d byte "ms ",0 fe2d6 0063 word EXIT ' DUP #999 > IF #1,000 U// PRINT DOT PRINT ." us" EXIT THEN fe2d8 d2240073 .L1 word DUP,W1000,EQGT,_IF+09,W1000,UDIVMOD,PRINT,DOT,PRINT,PRTSTR fe2ec 00207375 byte "us ",0 fe2f0 0063 word EXIT ' PRINT ." ns " fe2f2 d5b2da82 .L2 word PRINT,PRTSTR fe2f6 0020736e byte "ns ",0 fe2fa 0063 word EXIT ' .ms LAP@ LAP LAP LAP@ - ~l ; fe2fc e291e26e PRTMS word LAPCAL,REPLAP+ex fe300 0000ed64 _datorg long endcode&$FFFF fe304 0000ed64 _datptr long endcode&$FFFF fe308 e304013f ATDAT word _WORD,_datptr,FETCHX+ex fe30e 013f0073 DATORG word DUP,_WORD,_datorg fe314 013f00ec word STORE,_WORD,_datptr,STOREX+ex ' pub res ( bytes -- ) _datptr +! ; fe31c e304013f dres word _WORD,_datptr,PLUSST,EXIT ' pre words [C] GRAB 2* [C] BYTES ; ' pre LONGS [C] GRAB 4* [C] BYTES ; ' pre BYTES ( bytes -- ) [C] GRAB DATPTR SWAP res [C] DATCON ; fe324 00aed636 dlongs word GRAB,_SHL1 fe328 00aed636 dwords word GRAB,_SHL1 fe32c e308d636 dbytes word GRAB,ATDAT,SWAP,dres,_DATCON+ex fe336 e32df801 dbyte word _1,dbytes+ex fe33a e32df802 dword word _2,dbytes+ex fe33e e32df804 dlong word _4,dbytes+ex fe342 fe20f801 _ECHO word w+echo,rg+fflags,ROT,BITST,EXIT ' TAQOZ marks the start of a block of source code to be compiled in block mode ' fe34c _TAQOZ fe34c e1d4 word PRTVER '' disable background keypoll during load & reset error count fe34e ec50fe14 word rg+keypoll,CLRW,rg+errors,CLRW '' remember code position for reporting fe356 fe9ad680 word ATHERE,rg+fromhere,STORE '' reset line# to 1 to active fe35c feaef801 word _1,rg+linenum,WSTORE,_0,_ECHO '' backup dictionary pointer '' word ATNAMES,rg+oldnames,STORE '' time the load fe366 feb2ead4 word _GETCNT,rg+spincnt,STOREX+ex ' end of block load mode TAQOZ END ' fe36c e3420141 _END word _TRUE,_ECHO '' read linenum and clear to exit line mode fe370 00e0feae word rg+linenum,WFETCH,rg+linenum,CLRW fe378 dbfad0e2 word CRLF,PRTDEC,PRTSTR fe37e 6e696c20 byte " lines and ",0 fe38a fe9ad680 word ATHERE,rg+fromhere,FETCH,MINUS,PRTDECL,PRTSTR fe396 74796220 byte " bytes compiled, with ",0 fe3ae 00e0feac word rg+errors,WFETCH,PRTDEC,PRTSTR fe3b6 72726520 byte " errors in ",0 '' report compile time fe3c2 feb2ead4 word _GETCNT,rg+spincnt,FETCH,MINUS,CLKKHZ,UDIVIDE,PRTDECL,PRTSTR fe3d2 0020736d byte "ms ",0 fe3d6 d107f802 word _2,CLRFLG+ex '''''''''''''''''''''''''''''''''''''''''''''''''''' ' SERIAL FLASH '''''''''''''''''''''''''''''''''''''''''''''''''''' ''( &cs.so.si.ck -- ) fe3da e3e8013f SFPINS word _WORD,_sfpins,STOREX+ex fe3e0 f806e42e SFWE word SFBSY,w+6,SFINS fe3e6 013d SFINS word _LONG fe3e8 3d3a3b3c _sfpins long flashpins fe3ec 01b5eb88 word SPIPINS,SPICE,SPIWR8,EXIT '' SFWE ( ins -- ) fe3f4 d0b7f804 SFWD word _4,SPINNER+ex fe3f8 f805 SFSTAT word _5 fe3fa f800e3e6 SFRD1 word SFINS,_0,SPIRD,SPIX+ex ''( Read serial Flash serial number ) fe402 e3e6f84b SFSID word w+$4B,SFINS fe406 018ff800 SFRDD word _0,SPIRDL,SPIRDL fe40c 018ff800 SFRDL word _0,SPIRDL,SPIX+ex ''( Read serial Flash Jedec ID ) fe412 e3e6f89f SFJID word w+$9F,SFINS,SFRDL+ex fe418 d7f8e412 PRTSF word SFJID,PRTL,SPACE,SFSID,PRTL,SCORE,PRTL+ex ''( addr -- ) fe426 f820 SFER4 word w+$20 fe428 01a4e3e0 SFER word SFWE,SPIWM,SPICE fe42e 00b7e3f8 SFBSY word SFSTAT,_ZEQ,_UNTIL+03,EXIT ''( addr -- ) fe436 e429f852 SFER32 word w+$52,SFER+ex '' SFER64K ( addr -- ) fe43a e429f8d8 SFER64 word w+$D8,SFER+ex fe43e e3e0f8c7 SFERALL word w+$C7,SFWE,SPIX+ex '' SFWRPAGE ( src dst -- ) fe444 e3e0f802 SFWRPAGE word w+$02,SFWE,SPIWM,w+256,SPITX,SPIX+ex '' BACKUP the first 64K of memory into flash fe450 0073e412 BACKUP word SFJID,DUP,INC,_AND,ZEXIT 'EXIT IF BLANK ID' '' Write block 0 to Flash block 0 fe45a e43ad23c word BRORG,SFER64 fe45e e49c013f word _WORD,brstr,FETCH,_4,STORE fe468 d23cf800 word _0,BRORG,w+64,KB ''SFWRS ( hubsrc sfdst cnt -- ) fe470 007e0082 SFWRS word ROT,SWAP,ADO,IX,OVER,SFWRPAGE,SPINNER,w+256,PLUS,w+256,PLOOP,DROPEX+ex fe488 0191f800 SFRDW word _0,SPIRD,_0,SPIRD,_SHL8,ORX+ex '' SFR ( addr -- ) fe494 e3e6f803 SFRD word _3,SFINS,SPIWM,EXIT fe49c 4f514154 brstr byte "TAQO" '' RESTORE TAQOZ from FLASH by copying to $1.0000 first' fe4a0 008ad23c RESTORE word BRORG,INC4,SFFETCH,_WORD,brstr,FETCH,_EQ,ZEXIT '' word BRORG,_WORD,$1000,PLUS,_WORD,$1000,_WORD,$F000,SFRDS,EXIT fe4b0 1000013f word _WORD,$1000,BRORG,OVERPLUS,SWAP,_WORD,$F000 '' ( sfadr dst cnt -- ) '' read block from SF to RAM fe4be e4940082 SFRDS word ROT,SFRD,SPIRX fe4c4 006301b5 SPIX word SPICE,EXIT { '' SFRDS ( sfsrc hubdst bytes -- ) SFRDS word ROT,SFRD,ADO,_0,SPIRD,IX,CSTORE,LOOP,SPIX+ex } '' SFC@ fe4c8 SFCFETCH fe4c8 f800e494 word SFRD,_0,SPIRD,SPIX+ex ''pub SFW@ fe4d0 SFWFETCH fe4d0 e488e494 word SFRD,SFRDW,SPIX+ex ''pub SF@ ( addr -- long ) fe4d6 e488e494 SFFETCH word SFRD,SFRDW,SFRDW,_SHL16,_OR,SPIX+ex '' SF Select Serial Flash as memory for DUMP words fe4e2 e4c8d832 SF word SETDMP,SFCFETCH,SFWFETCH,SFFETCH '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''' SD CARD SUPPORT ''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' CON SDCS = w|sd_cs SDCK = w|sd_ck SDBUFS = $10000 dtk = w|$FE BLKSIZ = w|512 DAT fe4ea 014d _sdpins word CONL fe4ec 3c3a3b3d long sdpins fe4f0 014d SDBUF word CONL fe4f2 00010000 long SDBUFS ' pub SD? ( -- flg ) *SDCS PIN L 200 WAIT F 200 WAIT R H ; fe4f6 eae4f83c SDQ word SDCS,_PIN,L,w+200,WAIT,F,w+200,WAIT,R,H,EXIT ' pri SDCLK fe50c 01ac0141 SDCLK word MINUS1,SPIWR8,EXIT fe512 e50c SDCLK3 word SDCLK fe514 e50de50c SDCLK2 word SDCLK,SDCLK+ex ' pri TOKEN ( marker -- flgX ) fe518 4e20013f TOKEN word _WORD,20000 fe51c f8000077 tklp word OVER,_0,SPIRD,_NEQ,_IF+07,DEC,DUP,_ZEQ,_IF+02,NIP,EXIT fe532 e51d word tklp+ex fe534 ffff0068 word DROP2,TRUE,EXIT ' pub ACMD ( data acmd -- res ) fe53a f837f800 ACMD word _0,w+55,CMD,DROP ' pub CMD ( data cmd -- res ) fe542 f8350073 CMD word DUP,w+sdcmd,CSTORE fe548 eb88e4ea word _sdpins,SPIPINS,SDCLK fe54e 01a201aa word SPIWRC,SPIWRL fe552 00ddf834 word w+sdcrc,CFETCH,SPIWR8,RSTCRC fe55a fbe8f800 SDRES word _0,w+1000,FOR,SPIRD,BITS8,DUP,w+$FF,_NEQ,QNEXT,DROP,EXIT 'SDRES word _0,SPIRD,BITS8,DUP,w+$FF,_NEQ,_UNTIL+06,EXIT ' pri STAT@ ( -- stat ) fe570 f80df800 SDSTAT word _0,w+13,CMD,SDRES,_SHL8,ORX+ex { '' pri SDERR? ( -- flg ; return SD bit flag errors) SDERRQ word _0,SDQ,_ZEQ,_1,_AND,_OR word w+_sdrd,FETCH,_ZEQ,_2,_AND,_OR word w+_sdwr,FETCH,_ZEQ,_4,_AND,_OR word w+ocr,FETCH,_ZEQ,_8,_AND,_OR word EXIT } '' pri SD4@ ( -- long ) fe57c 0191f800 SDRD4 word _0,SPIRD,SPIRD,SPIRD,SPIRD,EXIT '' pri SDDAT! ( adr -- ) read info into memory fe588 e518f8fe SDDATST word dtk,TOKEN,_IF+08,w+16,ADO,_0,SPIRD,IX,CSTORE,LOOP,SDCLK3+ex fe59e d091 word DROPEX+ex fe5a0 f895 RSTCRC word w+$95 fe5a2 00e4f834 SETCRC word w+sdcrc,CSTORE,EXIT fe5a8 ec58f835 INITSX word w+sdcmd,SETC fe5ac 010df805 word _5,FOR,RSTCRC,_0,_0,CMD,_1,_EQ,QNEXT,ZEXIT fe5c0 010df805 word _5,FOR,w+$87,SETCRC,w+$1AA,_8,CMD,_1,_EQ,QNEXT,ZEXIT fe5d6 f9aae57c word SDRD4,w+$1AA,_EQ,ZEXIT fe5de 013ff800 word _0,_WORD,1000,_0,DO fe5e8 00b0f81e word w+30,MASK,w+41,ACMD,_IF+09,SPICE,SDCK,_PIN,w+200,FOR,H,L,forNEXT,isd1+ex fe604 0128008c word INC,LEAVE fe608 00610116 isd1 word LOOP,ZEXIT fe60c f83af800 word _0,w+58,CMD,IFEXIT,SDRD4,DUP,w+ocr,STORE,ZEXIT fe61e f80af800 word _0,w+10,CMD,_ZEQ,_IF+02,w+cid,SDDATST fe62c f809f800 word _0,w+9,CMD,_ZEQ,ZEXIT,w+csd,SDDATST+ex '' Initialise the SD card in SPI mode and return with the OCR '' pub !SD ( -- ocr|false ) fe63a eb88e4ea INITSD word _sdpins,SPIPINS fe63e f8a1f810 word w+sdvars,w+(sdend-sdvars),ERASE fe644 f804e4f0 word SDBUF,_4,_SHL9,ERASE ' erase all n file buffers fe64c f810f856 word w+_sector,w+16,w+$FF,CFILL fe654 fc0ae4f6 word SDQ,_IF+10,SDCLK3,w+20,FOR,INITSX,w+sdcmd,CFETCH,w+9,_EQ,QNEXT,DROP fe66c d165f810 word w+ocr,FETCHX+ex '' Write from src to xdst in the SD '' pub SDWR ( src sect -- flg ) fe670 e512 SDWR word SDCLK3 fe672 e542f818 word w+24,CMD,_ZEQ,_IF+11 fe67a f8fee512 word SDCLK3,dtk,SPIWR8,BLKSIZ,SPITX fe684 e518f800 word _0,TOKEN,w+$FF,TOKEN,_AND,sdwr1+ex fe690 f800 word _FALSE fe692 f83a0073 sdwr1 word DUP,w+_sdwr,STORE,SPIX+ex '' pub FLUSH ( force -- ) wrflg C@ OR IF SDBUF @sector @ SDWR DROP wrflg C~ THEN ; fe69a 00ddf842 FLUSH word w+wrflg,CFETCH,_OR,ZEXIT fe6a2 f856e4f0 word SDBUF,w+_sector,FETCH,SDWR,DROP,w+wrflg,CLRC,EXIT '' pri SDRDBK ( dst -- ) BLKSIZ SPIRX sdsum ! 0 SPIRD SPIRD 1 OR ; fe6b2 0184fa00 SDRDBK word BLKSIZ,SPIRX,w+sdsum,STORE,_0,SPIRD,SPIRD,_1,ORX+ex { pri SDRDBLK ( dst -- crc|flg ) BLKSIZ SPI>BUF --- read crc and force as true flag 0 SPIRD SPIRD 1 OR ; } '' pub SECTOR ( sect -- sdbuf ) fe6c4 f8560073 SECTOR word DUP,w+_sector,FETCH,_EQ,_IF+02,DROP,SDBUF+ex fe6d2 e69af800 SECTORF word _0,FLUSH,DUP,w+_sector,STORE,SDBUF,SDRD,SDBUF,EXIT '' pub SDRD ( sector dst -- ) fe6e4 f811007e SDRD word SWAP,w+17,CMD,DUP,_ZEQ,_IF+11 fe6f0 e55a0069 word DROP,SDRES,dtk,_EQ,_IF+02,SDRDBK,sdrd1+ex fe6fe e570e514 word SDCLK2,SDSTAT,DROP2,_0 fe706 0073e50c sdrd1 word SDCLK,DUP,w+_sdrd,STORE,w+seccrc,STORE,SPIX+ex '' pub SDRDS ( sector dst cnt -- crc | false ) ' convert cnt to sectors ' fe714 d674fa00 SDRDS word BLKSIZ,_ALIGN,_SHR9 ' multiblock read -- command not accepted ' fe71a 007e0081 word ROT2,SWAP,w+18,CMD,_IF+03,DROP2,_FALSE,.sd1+ex ' process read token and read block if available ' fe72a f8fee55a word SDRES,dtk,_EQ,_IF+09,SWAP,FOR,DUP,SDRDBK,BLKSIZ,PLUS,forNEXT,.sd1+ex ' ELSE ' fe742 e5140068 word DROP2,SDCLK2,SDSTAT,DROP,SPICE,_FALSE fe74e 01b5e50c .sd1 word SDCLK,SPICE fe752 f8360073 word DUP,w+_sdrd,STORE fe758 f80cf800 word _0,w+12,CMD,_ZEQ,_UNTIL+05,SPIX+ex '' SDWRS ( hubsrc sdadr cnt -- ) fe764 d674fa00 SDWRS word BLKSIZ,_ALIGN,_SHR9 fe76a 0073010a word ADO,DUP,IX,SECTOR,BLKSIZ,CMOVE fe776 e69af801 word _1,FLUSH,BLKSIZ,PLUS,LOOP,DROPEX+ex fe782 ec58f842 SDADRW word w+wrflg,SETC '' pub SDADR ( xaddr -- addr ) L>S ( @SECTOR + ) SECTOR SDBUF + ; fe786 f8a7ebf8 SDADR word L2S,w+opensect,FETCH,PLUS,SECTOR,PLUS,EXIT '' pub SD@ ( xaddr -- long ) RDSDA @ ; fe794 00e1e786 SDFETCH word SDADR,FETCH,EXIT fe79a 00ece782 SDSTORE word SDADRW,STORE,EXIT fe7a0 00dde786 SDCFETCH word SDADR,CFETCH,EXIT fe7a6 00e4e782 SDCSTORE word SDADRW,CSTORE,EXIT fe7ac 00e0e786 SDWFETCH word SDADR,WFETCH,EXIT fe7b2 e7a0d832 SD word SETDMP,SDCFETCH,SDWFETCH,SDFETCH '' @FAT ( fat# -- sector ) fe7ba 00e1f8d5 ATFAT word w+sectfat,FETCH,MULTIPLY fe7c0 f8bfe7d0 word ATBOOT,w+rsvd,WFETCH,PLUS,PLUS,EXIT fe7cc d165f90b ATROOT word w+rootdir,FETCHX+ex fe7d0 d165f86f ATBOOT word w+partitions+8,FETCHX+ex '' cd! ( sect str -- ) ' CDST word w+cwdsect,STOREX+ex fe7d4 e6d2e7d0 RDFAT word ATBOOT,SECTORF,w+fat32,w+90,CMOVE 'word w+sectclust,CFETCH,ENCODE,w+clshift,CSTORE fe7de 00e0f8bf word w+rsvd,WFETCH,w+sectfat,FETCH,w+fats,CFETCH,MULTIPLY fe7ec 00e1f8dd word w+rootcl,FETCH,DEC2 fe7f2 0086e814 word CLSECT2,PLUS,PLUS fe7f8 00ecf90b word w+rootdir,STORE '' save time by precalculating FAT table addresses fe7fc e7baf800 word _0,ATFAT,w+fat1,STORE,_1,ATFAT,w+fat1+4,STORE fe80c 0063 word EXIT '' CLUST>SECT ( clust# -- sector ) fe80e 00e1f8dd CLSECT word w+rootcl,FETCH,MINUS fe814 00ddf8be CLSECT2 word w+sectclust,CFETCH,MULTIPLY,ATBOOT,PLUS,EXIT fe820 0061e4f6 AMOUNT word SDQ,ZEXIT,w+mounted,CFETCH,IFEXIT fe82a 00b7e63a MOUNT word INITSD,_ZEQ,_IF+01,ERRSTR+ex fe832 e6d2f800 word _0,SECTORF,w+$1FE,PLUS,WFETCH,_WORD,$AA55,_EQ fe842 0061 word ZEXIT fe844 f86af8b1 word w+fat32,w+(fatend-fat32),ERASE fe84a e4f0f9be word w+$1BE,SDBUF,PLUS,w+partitions,w+64,CMOVE fe856 e954e7d4 word RDFAT,ROOT,w+mounted,SETC fe85e f808f814 PRTFAT word w+cid,_8,ATYPE fe864 f8f4d058 word SPACE,w+serial,FETCH,PRTLONG,SPACE fe86e f80bf8f8 word w+volname,w+11,CTYPE fe874 00ddf8be word w+sectclust,CFETCH,_SHR1,PRINT,w+"k",EMIT fe880 f8d1d058 word SPACE,w+sdsize,FETCH,W+11,_SHR,PRTDECL,w+"M",EMIT+ex ' DIR ' fe890 e820 PRTDIR word AMOUNT fe892 e956f800 word _0,FOPEN,CRLF,PRTFAT fe89a 00abe7cc word ATROOT,_SHL9,w+sectclust,CFETCH,_SHL9,ADO fe8a6 e7940103 word IX,SDFETCH,_IF+(.L2-.L1)/2 fe8ac 0103d0e2 .L1 word CRLF,IX,SDADR,DUP,w+8,CTYPE fe8b8 f8080073 word DUP,_8,PLUS,DUP,CFETCH,w+$20,_NEQ,_IF+05 fe8c8 0073d0f4 word DOT,DUP,_3,CTYPE,.L0+ex fe8d2 d076f804 word _4,SPACES fe8d6 007ed058 .L0 word SPACE,SWAP,FSECT,PRTL fe8de 0103d074 word SPACES3,IX,SDADR,PRTDATE fe8e6 f814d074 word SPACES3,w+fsize-8,PLUS,FETCH,PRTDECL fe8f0 0113f820 .L2 word w+32,PLOOP,CRLF+ex '' .DATE ( diradr -- ) fe8f6 f8180073 PRTDATE word DUP,w+fdate,PLUS,WFETCH fe8fe 009e0073 word DUP,_SHR9,_WORD,1980,PLUS,PRTDEC4 fe90a f8050073 word DUP,_5,_SHR,BITS4,PRTDEC2,w+$1F,_AND,PRTDEC2 '' fe91a 0086f816 word w+ftime,PLUS,WFETCH,DUP,w+11,_SHR,PRTDEC2 fe928 009bf805 word _5,_SHR,w+$3F,_AND,PRTDEC2+ex ' FSECT ( diradr -- sector )' fe932 0075f81a FSECT word w+fclstl,OVERPLUS,WFETCH,SWAP,w+fclsth,PLUS,WFETCH,W2L fe942 00e1f8dd C2S word w+rootcl,FETCH,MINUS,w+sectclust,CFETCH,MULTIPLY,ATROOT,PLUS,EXIT fe954 e7cc ROOT word ATROOT ' FOPEN ( sect -- ) fe956 ec44f8ab FOPEN word w+_fread,CLRL,w+opensect,STOREX+ex fe95e fe12e956 FLOAD word FOPEN,rg+ukey,WFETCH,w+fkey,WSTORE fe968 e96e013f word _WORD,FGET,SETKEY+ex fe96e 00e1f8ab FGET word w+_fread,FETCH,SDCFETCH,QDUP,_ZEQ fe978 f8affc08 word _IF+08,w+fkey,WFETCH,QDUP fe980 d0aafc04 word _IF+04,SETKEY,w+fkey,CLRW,FALX+ex fe98a d15df8ab word w+_fread,LINC+ex ' FREAD ( sdsrc hubdst bytes -- )' fe98e 010ad672 FREAD word _ALIGNL,ADO,IX,OVERPLUS,SDFETCH,IX,STORE fe99c 0113f804 FLOOP word _4,PLOOP,DROP,EXIT ' FWRITE ( hubsrc sddst bytes -- )' fe9a4 010ad672 FWRITE word _ALIGNL,ADO,IX,OVERPLUS,FETCH,IX,SDSTORE,FLOOP+ex { ' RENAME THE CURRENTLY OPEN FILE' RENAME : FNAME GETWORD FNAME word GETWORD To print a file: $1B780 FOPEN 0 SD PRINT$ } '''''''''''''''''''''''''''''' ' SD CARD '''''''''''''''''''''''''''''' fe9b4 010 org $0010 '...$0110' fe9b4 010 sdvars fe9b4 010 ocr res 4 fe9b4 014 cid res 16 fe9b4 024 csd res 16 fe9b4 034 sdcrc res 1 fe9b4 035 sdcmd res 1 fe9b4 036 _sdrd res 4 fe9b4 03a _sdwr res 4 fe9b4 03e sdsum res 4 fe9b4 042 wrflg fe9b4 042 wrflgs res 4 fe9b4 046 seccrc res 16 fe9b4 056 _sector res 16 fe9b4 066 mounted res 1 fe9b4 067 partitions res 64 fe9b4 0a7 opensect res 4 ' starting sector of open file' fe9b4 0ab _fread res 4 fe9b4 0af fkey res 2 fe9b4 0b1 sdend '''''''''''''''''''''''''''''' ' FAT32 '''''''''''''''''''''''''''''' fe9b4 0b1 fat32 fe9b4 0b1 res 3 fe9b4 0b4 oemname res 8 '' res 8 fe9b4 0bc bytesect res 2 '' res 2 fe9b4 0be sectclust res 1 fe9b4 0bf rsvd res 2 fe9b4 0c1 fats res 1 fe9b4 0c2 res 15 fe9b4 0d1 sdsize res 4 ' Number of sectors * byte/sect (512) = capacity' '' res 4 fe9b4 0d5 sectfat res 4 ' Number of sectors per FAT table' fe9b4 0d9 res 2 ' fatflags' fe9b4 0db res 2 ' fatver' fe9b4 0dd rootcl res 4 ' Cluster Number of the Start of the Root Directory' fe9b4 0e1 res 2 ' info = Sector Number of the FileSystem Information Sector (from part start) fe9b4 0e3 res 2 ' boot = Sector Number of the Backup Boot Sector (from part start) fe9b4 0e5 res 12 ' offset 64 fe9b4 0f1 res 3 fe9b4 0f4 serial res 4 ' serial number of partition fe9b4 0f8 volname res 11 ' volume name fe9b4 103 fatname res 8 ' always FAT32 - (don't trust) ' 96 ' '''''''''''''''''''''''''''''' ' create room for some system variables in this table fe9b4 10b rootdir res 4 ' sector address of root directory fe9b4 10f fat1 res 4 fe9b4 113 fat2 res 4 fe9b4 117 cwdsect res 4 'cwdstr res 16 fe9b4 11b fatend '''''''''''''''''''''''''''''' ' DIRECTORY STRUCTURE' '''''''''''''''''''''''''''''' fe9b4 000 org 0 fe9b4 000 fnam res 8 fe9b4 008 fext res 3 fe9b4 00b fatr res 1 fe9b4 00c res 1 ' MUST BE 00' fe9b4 00d fcms res 1 fe9b4 00e fctime res 2 fe9b4 010 fcdate res 2 fe9b4 012 fadate res 2 fe9b4 014 fclsth res 2 fe9b4 016 ftime res 2 fe9b4 018 fdate res 2 fe9b4 01a fclstl res 2 fe9b4 01c fsize res 4 ' '***************************************** HUBEXEC CODE *************************** ' fe9b4 orgh fe9b4 alignw fe9b4 _hubexec ' !SP - init the data stack pointer fe9b4 f6042200 INITSP mov datptr,#datstk fe9b8 f6042a00 mov depth,#0 fe9bc ff6f56df _ret_ mov tos,##$DEADBEEF ' marker fe9c0 060442ef { dirl #rx_pin 'disable receiver wrpin #%00_11111_0,#rx_pin 'configure rx_pin for asynchronous receive, always input wrpin #%01_11110_0,#tx_pin 'configure tx_pin for asynchronous transmit, always output dirh #tx_pin 'enable transmitter } fe9c4 InitTaqoz fe9c4 fd601601 cogid fx fe9c8 fed0f3f6 loc PTRA,#@IDLE&$FFFF ' default startup into Instruction Pointer fe9cc fb9c160c tjnz fx,#INITSTKS ' COG 0 CONSOLE ' fe9d0 fd647c41 dirh #tx_pin 'set tx output high fe9d4 fc2c1a3e wypin #$0D,#tx_pin fe9d8 fed0f4ae loc PTRA,#@TERMINAL&$FFFF fe9dc fd647e41 dirh #rx_pin 'setse1 #%001_111111 fe9e0 fa9c3c3f rdpin fz,#rx_pin wc ' clear rx? fe9e4 fd640025 setint1 #0 fe9e8 f6044000 mov rxwrC,#0 fe9ec fc64400c wrlong rxwrC,#rxrd fe9f0 fd677e20 setse1 #%110<<6+rx_pin 'set se1 to trigger on rx char event????? fe9f4 ff0007f5 mov ijmp1,##@taqoz_rxisr 'set int1 jump vector to receive buffer fe9f8 f607e810 fe9fc fd640825 setint1 #4 fea00 fdbfffb0 INITSTKS call #INITSP fea04 f6042630 INITLP mov lpptr,#lpstk fea08 f6042420 mov braptr,#brastk fea0c 06042840 INITRP _ret_ mov retptr,#retstk fea10 f0643a08 taqoz_rxisr shl rxlong,#8 fea14 fa8c3c3f rdpin fz,#rx_pin ' recv byte (bits31:24) from rx pin fea18 f0443c18 shr fz,#24 fea1c f5483a1e or rxlong,fz wz fea20 ff0d8d8d cmp rxlong,##$1B1B1B1B wz ' esc esc esc esc break' fea24 f20c3b1b fea28 af0007f6 if_z coginit #0,##@RESET fea2c acec0164 fea30 f6003e20 mov rxwrP,rxwrC fea34 f1043f80 add rxwrP,#rxbuffers fea38 fc403c1f wrbyte fz,rxwrP fea3c ff000007 incmod rxwrC,##rxsize-1 fea40 f704407f fea44 fc54400e wrword rxwrC,#rxwr fea48 fb3bfff5 reti1 '_rxrd long rxrd '_rxwr long rxwr fea4c fae4180c READRX rdword r0,#rxrd fea50 f2081820 cmp r0,rxwrC wz fea54 ad900018 if_z jmp #@rr1 fea58 f6001a0c mov r1,r0 fea5c f1041b80 add r1,#rxbuffers fea60 fac0140d rdbyte acc,r1 fea64 ff000007 incmod r0,##rxsize-1 fea68 f704187f fea6c fc54180c wrword r0,#rxrd fea70 fd800142 rr1 jmp #PUSHACC fea74 fd640025 DEBUGGER setint1 #0 fea78 fd8fca88 jmp #\_Start_Monitor ' \ forces absolute address ' ' Registers can be used just like variables and the interpreted kernel uses some for itself ' 128+ bytes are reserved. Since the registers are pointed to by "regptr" they can relocated ' REG ( index -- addr ) Find the address of the register fea7c 01004209 ATREG _ret_ add tos,regptr fea80 f6001616 LAPFETCH mov fx,lap1 fea84 f1801617 sub fx,lap2 fea88 fd800143 jmp #pushx ' COGSTOP ( cog -- ) fea8c fd604203 _COGSTOP cogstop tos fea90 fd800069 jmp #DROP ' COGINIT ( addr cog -- ) fea94 fce04222 coginit tos,tos1 fea98 fd800068 jmp #DROP2 ' COGATN ( mask -- ) fea9c fd60423f _COGATN cogatn tos feaa0 fd800069 jmp #DROP ' POLLATN ( -- flg ) feaa4 fd701c24 _POLLATN pollatn wc feaa8 c1841401 if_c sub acc,#1 feaac fd800142 jmp #PUSHACC '' SETEDG ( edge pin -- ) add 4 to edge for lock feab0 f0644406 _SETEDG shl tos+1,#6 feab4 f1004222 add tos,tos+1 feab8 fd604220 setse1 tos feabc fd800068 jmp #DROP2 '' POLLEDG ( -- flg ) feac0 fd700824 _POLLEDG pollse1 wc feac4 c1841401 if_c sub acc,#1 feac8 fd800142 jmp #PUSHACC feacc WAIT ''( clks -- ) feacc fd60421f waitx tos fead0 fd800069 jmp #DROP fead4 fd60161a _GETCNT GETCT fx fead8 fd800143 jmp #PUSHX ' some smartpin support for high level ' @PIN ( -- pin ) feadc f6001618 _ATPIN mov fx,pinreg feae0 fd800143 jmp #PUSHX '' PIN ( pin -- ) feae4 f6003021 _PIN mov pinreg,tos feae8 fd800069 jmp #DROP feaec f6003221 _CLK mov tepin,tos feaf0 fd800069 jmp #DROP ' WRACK ( data -- ) Write smartpin data and wait for empty then ack feaf4 fc204218 WRACK wypin tos,pinreg feaf8 fd703040 .wait testp pinreg wc '..wait for buffer empty feafc 3d9ffff8 if_nc jmp #.wait feb00 fc080218 akpin pinreg '..acknowledge pin feb04 fd800069 jmp #DROP feb08 fd605468 _RND xoro32 seed feb0c f600162a mov fx,seed feb10 fd800143 jmp #PUSHX ' SKIPNZ ( flg -- ) Skip if flg is true ( replace 0= IF xxx THEN ) feb14 fb944201 SKIPNZ tjz tos,#.L0 feb18 f107f002 add PTRA,#2 feb1c fd800069 .L0 jmp #DROP ' > ( n1 n2 -- flg ) feb20 f2504222 GT cmps tos,tos1 wc feb24 fd90000c jmp #CFLG ' < ( n1 n2 -- flg ) feb28 f2504421 LT cmps tos1,tos wc feb2c fd900004 jmp #CFLG ' U< ( u1 u2 -- flg ) feb30 f2104421 _ULT cmp tos1,tos wc feb34 f1a04422 CFLG subx tos1,tos1 feb38 fd800069 jmp #DROP ' main division sub - called both by U/ and U// ' double div, single divisor ' By specifing bits and left justifying the routine can be adapted and run faster ' CLKHZ 1234 LAP U// LAP .LAP 27.400us ok --> 18.800us ' UM/MOD64 ( Dbl.dividend divisor -- remainder Dbl.quotient) feb3c f6041420 UMDIVMOD64 mov ACC,#32 feb40 f1041420 UMDIVMOD32 add ACC,#32 feb44 f6001821 mov R0, tos ' R0 = divisor feb48 f6001a23 mov R1, tos2 ' R1R2 = dividend feb4c f6001c22 mov R2, tos1 feb50 f6044600 mov tos2, #0 ' remainder feb54 f0741a01 udmlp shl R1, #1 wc ' dividend msb feb58 f0b41c01 rcl R2, #1 wc feb5c f0a44601 rcl tos2, #1 ' hi bit from dividend feb60 f2f0460c cmpsub tos2, R0 wc ' cmp divisor ( R0 - tos & c set if tos => R0 ) feb64 f0b44401 rcl tos1, #1 wc ' R1 = quotient l feb68 f0a44201 rcl tos, #1 ' R2 = quotient h feb6c 0b6c15f9 _ret_ djnz ACC,#udmlp ' DSWAP ( n1 n2 n3 n4 -- n3 n4 n1 n2 ) feb70 f6001821 DSWAP mov R0,tos feb74 f6001a22 mov R1,tos1 feb78 f6004223 mov tos,tos2 feb7c f6004424 mov tos1,tos3 feb80 f600460c mov tos2,R0 feb84 0600480d _ret_ mov tos3,R1 feb88 SPIPINS ' ( long --- ) sets bit numbers for SPI mode from bytes in long as cs.mi.mo.ck feb88 fdb00030 call #.SPSET feb8c fd601658 drvl fx ' clock low feb90 f600040b mov sck,fx ' setup SCK clock ' feb94 fdb00024 call #.SPSET feb98 fd601659 drvh fx ' leave high feb9c f600060b mov mosi,fx ' setup MOSI data to slave ' feba0 fdb00018 call #.SPSET feba4 fd601640 dirl fx ' input feba8 f600080b mov miso,fx ' MISO ' febac fdb0000c call #.SPSET febb0 fd601659 drvh fx ' chip select high febb4 f6000a0b mov ss,fx ' SS febb8 fd800069 jmp #DROP febbc f6001621 .SPSET mov fx,tos febc0 f50416ff and fx,#$FF febc4 00044208 _ret_ ror tos,#8 { PAFETCH mov fx,INA jmp #PUSHX PBFETCH mov fx,INB jmp #PUSHX PASTORE mov OUTA,tos jmp #DROP PBSTORE mov OUTA,tos jmp #DROP DACLR andn DIRA,tos jmp #DROP DBCLR andn DIRB,tos jmp #DROP ' ( mask -- ) PASET or OUTA,tos DASET or DIRA,tos jmp #DROP PBSET or OUTB,tos DBSET or DIRB,tos jmp #DROP PACLR andn OUTA,tos jmp #DASET PBCLR andn OUTB,tos jmp #DBSET } { *** COG ACCESS *** } febc8 f9944200 COGFETCH alts tos,#0 febcc 06004200 _ret_ mov tos,0_0 '' COG! ( long addr -- ) Store a long to cog memory febd0 COGSTORE febd0 f98c4200 altd tos,#0 febd4 f6000022 mov 0_0,tos+1 febd8 fd800068 jmp #DROP2 febdc fd601601 _COGID cogid fx febe0 fd800143 jmp #PUSHX '' _COGINIT ( dest cog -- ) febe4 fce04222 _COGINIT coginit tos,tos1 febe8 fd800068 jmp #DROP2 '' DELTA ( delta -- ) Calculate and set the cnt delta and waitcnt febec fda00069 DELTA call #POPX febf0 f600200b mov deltaR,fx '' WAITCNT ( -- ) febf4 0d60201f WAITCNTS _ret_ waitx deltaR '' continue from last count (must be called before target is reached) { ' OUTCLR ( iomask -- ) Clear multiple bits on the output OUTCLRA andn OUTA,tos or DIRA,tos jmp #DROP '' OUTSET ( iomask -- ) Set multiple bits on the output OUTSETA or OUTA,tos ' OUTPUTS ( iomask -- ) Set selected port pins to outputs or DIRA,tos jmp #DROP ' INPUTS ( iomask -- ) Set selected port pins to inputs INPUTSA andn DIRA,tos jmp #DROP } ' L2S ( n -- lsb9 h ) specialized operation for filesystem addresses febf8 f6001621 L2S mov fx,tos febfc f50443ff and tos,#$1FF fec00 f0441609 shr fx,#9 fec04 fd800143 jmp #PUSHX ' L2W word DUP,TOW,SWAP,_SHR16,EXIT { ' SHIFT from INPUT - Assembles with last bit received as msb - needs SHR to right justify if asynch data ' SHRINP ( pin dat -- pin dat/2 ) SHRINP testp tos1 wc rcr tos,#1 ret } { SHIFT to OUT - This is optimized for when you are sending out multiple bits as in asynchronous serial data or I2C Shift data one bit right into output via iomask - leave mask & shifted data on stack (looping) 400ns execution time including wordcode read and execute or 200ns/bit with REPS } { ' SHROUT ( pin dat -- iomask dat/2 ) SHROUT shr tos,#1 wc ' Shift right and get lsb drvc tos1 ret } fec08 fda00069 BITST call #POPX fec0c fb941604 tjz fx,#CLR ' SET ( mask addr -- ) Set bit(s) in hub long fec10 fb001621 SET rdlong fx,tos fec14 f5401622 or fx,tos1 fec18 fc601621 wrlong fx,tos fec1c fd800068 jmp #DROP2 ' CLR ( mask addr -- ) Clear bit(s) in hub long fec20 fb001621 CLR rdlong fx,tos fec24 f5201622 andn fx,tos1 fec28 fc601621 wrlong fx,tos fec2c fd800068 jmp #DROP2 ' SET? ( mask caddr -- flg ) Test single bit of a byte in memory fec30 fb004221 BITQ rdlong tos,tos fec34 f5084421 and tos1,tos wz fec38 56004579 if_nz mov tos1,M1 fec3c fd800069 jmp #DROP ' ~~ ( addr -- ) set long fec40 f1841401 SETL sub ACC,#1 ' ~ ( addr -- ) clear long fec44 fc601421 CLRL wrlong ACC,tos fec48 fd800069 jmp #DROP ' W~~ ( addr -- ) set word fec4c f1841401 SETW sub ACC,#1 ' W~ ( addr -- ) clear word fec50 fc501421 CLRW wrword ACC,tos fec54 fd800069 jmp #DROP ' C~~ ( addr -- ) set byte fec58 f1841401 SETC sub ACC,#1 ' C~ ( addr -- ) clear byte fec5c fc401421 CLRC wrbyte ACC,tos fec60 fd800069 jmp #DROP ' Inline vector check and exeute !!!! needs to be able to handle hubexec !!!! ' ?JMP ( adr -- ) fec64 fae81621 QJMP rdword fx,tos wz ' read contents of vector fec68 5603f00b if_nz mov PTRA,fx fec6c fd800069 jmp #DROP ' SQRT ( d. -- sqrt ) fec70 fd304421 _SQRT qsqrt tos+1,tos fec74 fd604418 getqx tos+1 fec78 fd800069 jmp #DROP { _INCMOD '( mod dst -- ) incmod tos,tos+1 jmp #DROP2 } fec7c fd60421c _SETDACS setdacs tos fec80 fd800069 jmp #DROP fec84 fd60161b _GETRND getrnd fx fec88 fd800143 jmp #PUSHX fec8c _HUBSET fec8c fd604200 hubset tos fec90 fd800069 jmp #DROP ' WS2812 ( array ledcnt -- ) pin is in cog "pinreg" - line RET is done at HL, not here ' Will transmit a whole array of 24-bit words each back to back in WS2812 timing format ' line idles low and resets/synchs with low =>50us ' A zero is transmitted as 400ns high by 850ns low (+/-150ns) ' A one is transmitted as 800ns high by 450ns low HHL ' The low period between each led is about 400ns longer but inconsequential ' <30us/LED fec94 00000020 wsdly long sys_clk/2500000 fec98 ff0007f6 WSLED rdbyte r2,##wsdly fec9c fac41c94 feca0 f1844401 sub tos1,#1 ' offset for 24-bit long alignment feca4 fb001622 .l2 rdlong fx,tos1 ' read next long feca8 f1044403 add tos1,#3 ' but leds are 3 bytes apart fecac f6041a18 mov r1,#24 ' write all 24 bits fecb0 .lp fecb0 f0741601 shl fx,#1 wc ' get next bit fecb4 fd603059 drvh pinreg ' always clock tx pin high for at least 400ns fecb8 fd601c1f waitx r2 ' 400ns fecbc fd60305a drvc pinreg ' output data bit fecc0 fd601c1f waitx r2 ' delay again, (data is either high or low) fecc4 fd603058 drvl pinreg ' always needs to go low in the last third of the cycle fecc8 fd601c1f waitx r2 '-20' feccc fb6c1bf8 djnz r1,#.lp fecd0 fb6c43f4 djnz tos,#.l2 ' read the next long as long as we can (tos = count) fecd4 fd800068 jmp #DROP2 ' tx line left low to synch - discard stack parameters, all done. { ' VER ( -- verptr ) GETVER loc PA,#@version mov fx,PA jmp #PUSHX } { DICTIONARY 00.D000: 03 44 55 50 6B 00 04 32 44 55 50 6D 00 04 4F 56 .DUPk..2DUPm..OV 00.D010: 45 52 6E 00 04 44 52 4F 50 61 00 05 32 44 52 4F ERn..DROPa..2DRO 00.D020: 50 60 00 04 53 57 41 50 75 00 05 32 53 57 41 50 P..SWAPu..2SWAP 00.D030: 50 0D 03 52 4F 54 7A 00 04 2D 52 4F 54 79 00 03 P..ROTz..-ROTy.. } { ATR(765):CNT(43210),,CFA ' ' Find string in dictionary is written in code and takes around 1us/word ' r3 = cnt+1st char of source ' ' r1 r2 ' } fecd8 FINDSTR ' ( cstr dict -- nfaptr | false ) fecd8 fae01e22 rdword r3,tos1 ' read in count and 1st char fecdc f6001c21 fstlp mov r2,tos ' R2 = dict word ptr ' fece0 f6001a22 mov r1,tos1 ' R1 = source fece4 fae8160e rdword fx,r2 wz ' read in count + 1st char' fece8 ad90005c if_z jmp #fstfail ' end of dictionary?' fecec f52416e0 andn fx,#$E0 ' mask out atrs from count fecf0 f208160f cmp fx,r3 wz ' compare count+1st char ' fecf4 5d90003c if_nz jmp #fstskip ' no match, go to next word fecf8 f600200f mov r4,r3 ' matched on cnt + 1st char' fecfc f504201f and r4,#cntm ' now match rest if needed' fed00 f18c2001 sub r4,#1 wz ' matched if single else setup' fed04 ad900024 if_z jmp #fstmatch fed08 f1041a02 add r1,#2 ' skip into 2nd char' fed0c f1041c02 add r2,#2 fed10 fac0180d fstrem rdbyte r0,r1 ' read in char from source ' fed14 f1041a01 add r1,#1 ' hub has to wait anyway so get ready for next source byte fed18 fac0160e rdbyte fx,r2 ' read in a character from the dictionary fed1c f1041c01 add r2,#1 fed20 f208160c cmp fx,r0 wz ' are they the same? fed24 5d90000c if_nz jmp #fstskip ' skip if not same' fed28 fb6c21f9 djnz r4,#fstrem ' continue for remainder' fed2c f6004421 fstmatch mov tos1,tos ' NIP fed30 fd800069 jmp #DROP ' found it fed34 fac01621 fstskip rdbyte fx,tos ' read cnt to skip to next header ' fed38 f504161f and fx,#cntm ' 03,D,U,P,CFAL,CFAH fed3c f100420b add tos,fx fed40 f1044203 add tos,#3 ' skip over CPA to next header' fed44 fd9fff94 jmp #fstlp fed48 f6044400 fstfail mov tos1,#0 fed4c fd800069 jmp #DROP fed50 f6001615 _DEPTH mov fx,depth fed54 fd800143 jmp #PUSHX { REGVAR POP fx rdbyte fx,fx add fx,regptr jmp #PUSHX } { " ABCDEFGHIKLMNOPQRSTUVWXYZ$@!+- _abcdefghijklmnopqrstuvwxyz{|}~ #J%&'()*,./0123456789:;<=>?[\]^" 0 -ROT BEGIN DUP C@ WHILE OVER OVER C@ = IF 2DROP EXIT THEN ROT 1+ -ROT 1+ REPEAT ; } { ' LOOKIN ( val array -- index ) LOOKIN mov R1,tos1 mov tos1,#0 ' init result index .L0 rdbyte fx,tos wz if_z mov tos1,#0 if_z jmp #DROP add tos1,#1 ' inc result index cmp fx,R1 wz if_z jmp #DROP add tos,#1 jmp #.L0 _LOOKUP '( index array -- value ) add tos1,tos rdbyte tos1,tos1 jmp #DROP } fed58 ff0007f6 NEWCOG coginit tos,##@RESET fed5c fce44364 fed60 fd800069 jmp #DROP { dPRTIP call #dCRLF '' mov P,PTRA '' shr P,#16 call #dPRTWORD mov P,PTRA jmp #dPRTWORD dPRTX mov R1,#$20 call #TX mov P,fx dPRTWORD mov R1,P shr R1,#12 call #HEXASC mov R1,P shr R1,#8 call #HEXASC mov R1,P shr R1,#4 call #HEXASC mov R1,P call #HEXASC mov R1,#$20 call #TX ret ' HEXASC and R1,#$0F add R1,#$30 cmp R1,#$3A wc if_nc add R1,#7 TX wypin R1,#tx_pin '..send byte .wait testp #tx_pin wc '..wait for buffer empty if_nc jmp #.wait akpin #tx_pin '..acknowledge pin waitx #200 ret dCRLF mov R1,#$0D call #TX mov R1,#$0A jmp #TX '} fed64 endcode '************************************* HUB REGISTERS ************************************** fed64 000 org 0 ' register offsets within "registers". Access as REG,delim ... REG,base ... etc ' ' Minimum registers required for a new task - other registers after the ' ---- are not needed other than by the console fed64 000 temp res 12 ' general purpose fed64 00c double res 4 ' hold high word of double ' @16 fed64 010 uemit res 2 ' emit vector 0 = default fed64 012 ukey res 2 ' key vector fed64 014 keypoll res 2 ' poll user routines - low priority background task fed64 016 base res 2 ' current number base + backup location during overrides fed64 018 baudcnt res 4 ' SERIN SEROUT baud cnt value where baud = clkfreq/baudcnt each cog can have it's own fed64 01c uswitch res 4 ' target parameter used in CASE structures ' @32 fed64 020 fflags res 2 ' echo,linenums,ipmode,leadspaces,prset,striplf,sign,comp,defining fed64 022 keycol res 1 ' maintains column position of key input fed64 023 wordcnt res 1 ' length of current word (which is still null terminated) fed64 024 wordbuf res wordsz ' words from the input stream are assembled here ' numpad may continue to build backwards into wordbuf for special cases such as long binary numnbers fed64 04b numpad res numpadsz ' Number print format routines assemble digit characters here builds from end - 18,446,744,073,709,551,615 fed64 065 padwr res 1 ' write index (builds characters down from lsb to msb in MODULO style) 'leader res 1 fed64 066 pflg res 1 fed64 067 pbase res 1 fed64 068 pfmt res 4 fed64 06c delim res 2 ' the delimiter used in text input and a save location fed64 06e dcnt res 1 fed64 06f prefix res 1 ' NUMBER input prefix fed64 070 uprompt res 2 ' pointer to code to execute when Forth prompts for a new line fed64 072 accept res 2 ' pointer to code to execute when Forth accepts a line to interpret (0=ok) fed64 074 keychar res 4 ' override for key character fed64 078 suffix res 1 ' NUMBER input suffix fed64 079 res 3 fed64 07c unum res 2 ' User number processing routine - executed if number failed and UNUM <> 0 fed64 07e ufind res 2 ' runs extended dictionary search if set after failing precompiled dictionary search ' ' ------ console only registers not required for other tasks --- can be accessed as globals ' ' these 4 variables are cleared as an array of 10 bytes fed64 080 anumber res 4 ' Assembled number from input fed64 084 bnumber res 4 fed64 088 digits res 1 ' number of digits in current number that has just been processed fed64 089 dpl res 1 ' Position of the decimal point if encountered (else zero) 'createvec res 2 ' If set will execute user create routines rather than the kernel's (CREATE revectored) fed64 08a dmm res 6 ' dump "fetch' vectors to allow dump to access special devices fed64 090 dmp res 2 ' DUMP vector ''''''''''''''''''''''' fixed '''''''''''''''''''''''''''' 'rxptr res 4 ' Pointer to the terminal receive buffer - read & write index precedes 'rxsz res 2 fed64 092 oldnames res 4 ' backup of names used at start of TAQOZ load fed64 096 names res 4 ' start of dictionary (builds down) fed64 09a fromhere res 4 ' Used by TAQOZ word to backup current here to determine code size at end of load fed64 09e here res 4 ' pointer to compilation area (overwrites VM image) fed64 0a2 codes res 4 ' current code compilation pointer (updates "here" or is reset by it) 'bootsig res 4 fed64 0a6 autovec res 4 ' user autostart address if non-zero - called from within terminal fed64 0aa cold res 2 ' pattern to detect if this is a cold or warm start ($A55A ) fed64 0ac errors res 2 fed64 0ae linenum res 2 'lines res 2 fed64 0b0 prevch res 2 ' used to detect LF only sequences vs CRLF to perform auto CR fed64 0b2 spincnt res 2 ' Used by spinner to rotate busy symbol fed64 0b4 res 2 ' word count fed64 0b6 endreg res 0 '********************************************************************************************************* '************************************** TACHYON COG KERNEL *********************************************** '********************************************************************************************************* fed64 000 org 0 fed64 000 fdafe9c4 RESET call #@InitTaqoz fed68 001 fd9000d0 jmp #doNEXT '********************************** data ************************************* ' Registers used by PASM modules to hold parameters such as I/O masks and bit counts etc ' COG 2 fed6c 002 sck fed6c 002 00000000 REG0 long 0 fed70 003 mosi fed70 003 00000000 REG1 long 0 fed74 004 miso fed74 004 00000000 REG2 long 0 fed78 005 ss fed78 005 00000000 REG3 long 0 fed7c 006 00000000 REG4 long 0 fed80 007 00000000 long 0 fed84 008 00000000 long 0 ' $00E0 ' COG 9 = TASK REGISTER POINTER fed88 009 0000fe00 regptr long registers ' used by REG fed8c 00a 00000000 ACC long 0 fed90 00b 00000000 fx long 0 fed94 00c 00000000 R0 long 0 fed98 00d 00000000 R1 long 0 fed9c 00e P fed9c 00e 00000000 R2 long 0 feda0 00f 00000000 R3 long 0 feda4 010 R4 feda4 010 00000000 deltaR long 0 ' COG 17 STACK POINTERS feda8 011 00000000 datptr long 0 ' data stack pointer to LUT fedac 012 00000000 braptr long 0 ' branch stack pointer to LUT fedb0 013 00000000 lpptr long 0 fedb4 014 00000000 retptr long 0 ' return stack pointer to LUT ' COG 21 fedb8 015 00000000 depth long 0 fedbc 016 00000000 lap1 long 0 fedc0 017 00000000 lap2 long 0 ' #0024 fedc4 018 00000000 pinreg long 0 fedc8 019 00000000 tepin long 0 fedcc 01a 00000050 pinticks long sys_clk / 1000000 ' set default 1Mbaud ' #0027 fedd0 01b 00000000 clockpins long 0 ' I/O mask for CLOCK instruction fedd4 01c 00000000 clkdly long 0 ' #0029 rx isr variables fedd8 01d 00000000 rxlong long 0 feddc 01e 00000000 fz long 0 fede0 01f 00000000 rxwrP long 0 fede4 020 00000000 rxwrC long 0 ' *** COG STACKS *** ' top of data stack registers fede8 021 deadbee1 tos long $DEADBEE1 fedec 022 deadbee2 tos1 long $DEADBEE2 fedf0 023 deadbee3 tos2 long $DEADBEE3 fedf4 024 deadbee4 tos3 long $DEADBEE4 ' top of loop stack registers fedf8 025 00000000 limit1 long 0 fedfc 026 00000000 index long 0 fee00 027 00000000 limit2 long 0 fee04 028 00000000 index2 long 0 fee08 029 00000000 branchadr long 0 fee0c 02a 00000001 seed long 1 fee10 02b f603f021 AJMP mov PTRA,tos ' jump to address on top of the data stack fee14 02c fd9000f0 jmp #DROP fee18 02d fdb000ec ACALL call #POPX ' get wordcode into X fee1c 02e fd601a2b pop R1 ' discard return address and jump back and use interpreter fee20 02f fd90001c jmp #doCODE ' main Forth wordcode interpreter - PTRA = Instruction Pointer ' wordcode order: ASM,THREADED,HUBEXEC,IF,UNTIL,REG,LIT9 '' { w = $F800 ' wordcode offset for 10-bit literals _IF = $FC00 ' IF relative forward branch 0 to 127 words _UNTIL = $FC80 ' UNTIL relative reverse branch 0 to 127 words opunused = $FD00 rg = $FE00 ' task/cog register 8-bit offset fat = $FF00 } ' constants used by doNEXT decode fee24 030 000001f0 cogadr long 496 fee28 031 0000e9b3 threaded long (_hubexec-1)&$FFFF fee2c 032 0000f7ff calls long $F800-1 fee30 033 0000fbff shorts long $FC00-1 fee34 034 0000fcff branches long $FD00-1 fee38 035 fd60162d doCALL call fx ' could call cog or hub code - use ret to return fee3c 036 fae41761 doNEXT rdword fx,PTRA++ ' read word code instruction fee40 037 f210600b doCODE cmp cogadr,fx wc ' wordcode below $1F0 are cog addresses - just call fee44 038 3d9ffff0 if_nc jmp #doCALL fee48 039 f210620b cmp threaded,fx wc ' just call if it is asm code - either cog or in hubexec range below wordcodes fee4c 03a 3d900030 if_nc jmp #THREAD ' if not then just execute as threaded code - needs to save IP fee50 03b f210640b cmp calls,fx wc ' special opcodes? (at high end for branches, short literals, registers etc) fee54 03c 3d9fffe0 if_nc jmp #doCALL ' hubexec - execute as cog code ' fee58 03d f210660b cmp shorts,fx wc ' fee5c 03e 3d900014 if_nc jmp #doSHORT ' LIT short 9-bit literal fee60 03f f210680b cmp branches,fx wc fee64 040 3d900030 if_nc jmp #doBRANCH ' IF UNTIL conditional relative branch code ' ' REG OP ( -- addr ) - the byte offset is relative to the regptr for that task fee68 041 doREG fee68 041 f7441608 zerox fx,#8 fee6c 042 f1001609 add fx,regptr fee70 043 fd900004 jmp #doPUSHX fee74 044 doSHORT fee74 044 f7441609 zerox fx,#9 ' push 10-bit literal fee78 045 fdb003f4 doPUSHX call #PUSHX fee7c 046 fd9fffbc jmp #doNEXT ' Call wordcode - Save IP and load with new IP from call ' fee80 047 THREAD fee80 047 f7cc1601 test fx,#1 wz ' bit0 is the jump/call bit fee84 048 f5241601 andn fx,#1 ' word align fee88 049 ac33f014 if_z wrlut PTRA,retptr ' save IP onto return stack fee8c 04a a1042801 if_z add retptr,#1 fee90 04b f603f00b mov PTRA,fx ' jump to new wordcode (PTRA = IP) fee94 04c fd9fffa4 jmp #doNEXT ' ' Conditional with 7-bit signed word displacement fee98 04d doBRANCH fee98 04d fb9c4204 tjnz tos,#dj1 ' discard flag and continue w/o jumping ' take the jump - X has instruction wordcode fee9c 04e f7cc1680 test fx,#$80 wz ' reverse jump? nz feea0 04f f504167f and fx,#$7F ' mask displacement feea4 050 f0641601 shl fx,#1 ' index as words feea8 051 f3e3f00b sumnz PTRA,fx ' +/- jump feeac 052 fdb00058 dj1 call #DROP ' discard condition flag feeb0 053 fd9fff88 jmp #doNEXT { dPRTPA mov R1,PA jmp #TXR1 } '###################################################################################' feeb4 054 fd63f02d _ASM call PTRA feeb8 055 fd900034 jmp #EXIT feebc 056 STRLEN ' ( str -- len ) feebc 056 fc780021 rdfast #0,tos feec0 057 f6044200 mov tos,#0 feec4 058 fd601810 .L0 rfbyte R0 ' read a byte feec8 059 f1841801 sub R0,#1 ' end is either a null or anything >$7F feecc 05a f214187e cmp R0,#$7E wc feed0 05b c1044201 if_c add tos,#1 feed4 05c cd9fffec if_c jmp #.L0 feed8 05d fd64002d ret ' ?EXIT ( flg -- ) Exit if flg is true feedc 05e fdb00028 IFEXIT call #POPX feee0 05f 5d90000c if_nz jmp #EXIT feee4 060 fd64002d ret ' 0EXIT ( flg -- ) Exit if flg is false (or zero) Used in place of IF......THEN EXIT as false would just end up exiting feee8 061 fdb0001c ZEXIT call #POPX feeec 062 5d64002d if_nz ret feef0 063 f1842801 EXIT sub retptr,#1 feef4 064 0aa3f014 _ret_ rdlut PTRA,retptr { *** STACK OPERATORS *** } ' NIP ( n1 n2 -- n2 ) : 600ns feef8 065 f6004421 NIP mov tos1,tos feefc 066 fd900008 jmp #DROP ' 3DROP ( n1 n2 n3 -- ) : 1.2us fef00 067 fdb00004 DROP3 call #POPX ' 2DROP ( n1 n2 -- ) : 800ns fef04 068 fdb00000 DROP2 call #POPX ' DROP ( n -- ) : 500ns : 400ns fef08 069 DROP ' Pop the data stack using fixed size register stack in COG memory (allows fast direct access for operations) ' overflow stack in hub ram and reduces the size of the cog stack to 4 fef08 069 POPX ' wz fef08 069 fb942a07 tjz depth,#_NOP ' don't pop beyond bottom of stack fef0c 06a f6081621 mov fx,tos wz ' pop old tos into X fef10 06b f6004222 mov tos,tos1 fef14 06c f6004423 mov tos1,tos2 fef18 06d f6004624 mov tos2,tos3 fef1c 06e f1842a01 sub depth,#1 ' maintain depth count fef20 06f f1842201 sub datptr,#1 ' stack pointer fef24 070 0aa04811 _ret_ rdlut tos3,datptr ' pop from lut stack into register stack fef28 071 fd64002d _NOP ret ' ?DUP ( n1 -- n1 n1 | 0 ) DUP n1 if non-zero fef2c 072 fb9443fe QDUP tjz tos,#_NOP ' DUP ( n1 - n1 n1 ) Duplicate the top item on the stack - 48 cycles fef30 073 f6001621 DUP mov fx,tos ' Read directly from the top of the data stack fef34 074 fd900338 jmp #PUSHX ' Push the internal X register onto the datastack fef38 075 01004222 OVERPLUS _ret_ add tos,tos1 fef3c 076 fdb00000 DUP2 call #OVER ' OVER ( n1 n2 -- n1 n2 n1 ) - 1us fef40 077 f6001622 OVER mov fx,tos1 'read second data item and push fef44 078 fd900328 jmp #PUSHX ' tos2 ( n1 n2 n3 -- n1 n2 n3 n1 ) Copy the tos2 item onto the stack fef48 079 f6001623 THIRD mov fx,tos2 ' read third data item fef4c 07a fd900320 jmp #PUSHX ' 4TH ( n1 n2 n3 n4 -- n1 n2 n3 n4 n1 ) Copy the 4th item onto the stack - 1.2us fef50 07b f6001624 FOURTH mov fx,tos3 fef54 07c fd900318 jmp #PUSHX ' BOUNDS ( n1 n2 -- n2+n1 n1 ) == OVER + SWAP fef58 07d f1004222 BOUNDS add tos,tos1 ' SWAP ( n1 n2 -- n2 n1 ) Swap the top two items fef5c 07e f6001622 SWAP mov fx,tos1 fef60 07f f6004421 SWAPX mov tos1,tos fef64 080 0600420b PUTX _ret_ mov tos,fx ' -ROT ( a b c -- c a b ) fef68 081 fdb00000 ROT2 call #ROT ' ROT ( a b c -- b c a ) fef6c 082 f6001623 ROT mov fx,tos2 fef70 083 f6004622 mov tos2,tos1 fef74 084 fd9fffe8 jmp #SWAPX { *** ARITHMETIC *** } ' - ( n1 n2 -- n3 ) Subtract n2 from n1 fef78 085 f6604221 MINUS neg tos ' (note: save one long by negating and adding) ' + ( n1 n2 -- n3 ) Add top two stack items together and replace with result fef7c 086 f1104421 PLUS add tos1,tos wc fef80 087 fd9fff84 jmp #DROP ' 2- fef84 088 01844202 DEC2 _ret_ sub tos,#2 ' 1- fef88 089 01844201 DEC _ret_ sub tos,#1 ' 4+ fef8c 08a 01044204 INC4 _ret_ add tos,#4 ' 2+ fef90 08b 01044202 INC2 _ret_ add tos,#2 ' 1+ fef94 08c 01044201 INC _ret_ add tos,#1 ' -NEGATE ( n1 sn -- n1 | -n1 ) negate n1 if the sign of sn is negative (used in signed divide op) fef98 08d f044421f MNEGATE shr tos,#31 ' ?NEGATE ( n1 flg -- n2 ) negate n1 if flg is true fef9c 08e fb9443da QNEGATE tjz tos,#DROP fefa0 08f fdbfff64 call #POPX ' NEGATE ( n1 -- n2 ) equivalent to n2 = 0-n1 fefa4 090 06604221 NEGATE _ret_ neg tos { *** BOOLEAN *** } { ' INVERT ( n1 -- n2 ) bitwise invert n1 and replace with result n2 INVERT add tos,#1 jmp #NEGATE } ' BITS ( n1 bits -- n2 ) fefa8 091 f9c04221 BITS decod tos fefac 092 f1844201 sub tos,#1 fefb0 093 f5004421 _AND and tos1,tos fefb4 094 fd9fff50 jmp #DROP fefb8 095 f5204421 _ANDN andn tos1,tos fefbc 096 fd9fff48 jmp #DROP fefc0 097 f5404421 _OR or tos1,tos fefc4 098 fd9fff40 jmp #DROP fefc8 099 f5604421 _XOR xor tos1,tos fefcc 09a fd9fff38 jmp #DROP { ' mainly for testing instructions' _ZEROX zerox tos1,tos jmp #DROP } ' *** shift operators *** ' *** RIGHT SHIFT *** ' SHR ( n1 cnt -- n2 ) Shift n1 right by count (5 lsbs ) fefd0 09b f0404421 _SHR shr tos1,tos fefd4 09c fd9fff30 jmp #DROP ' 16>> fefd8 09d 00444210 _SHR16 _ret_ shr tos,#16 ' 9>> fefdc 09e 00444209 _SHR9 _ret_ shr tos,#9 ' 8>> fefe0 09f 00444208 _SHR8 _ret_ shr tos,#8 ' 4/ fefe4 0a0 00444202 _SHR2 _ret_ shr tos,#2 ' 2/ ( n1 -- n1/2 ) fefe8 0a1 00444201 _SHR1 _ret_ shr tos,#1 fefec 0a2 f0004421 _ROR ror tos1,tos feff0 0a3 fd9fff14 jmp #DROP feff4 0a4 f0c04421 _SAR sar tos1,tos feff8 0a5 fd9fff0c jmp #DROP ' *** LEFT SHIFT *** ' << ( n1 bits -- n2 ) feffc 0a6 f0604421 _SHL shl tos1,tos ff000 0a7 fd9fff04 jmp #DROP ' ROL ( n1 bits -- n2 ) ff004 0a8 f0204421 _ROL rol tos1,tos ff008 0a9 fd9ffefc jmp #DROP ff00c 0aa 00644210 _SHL16 _ret_ shl tos,#16 ff010 0ab 00644209 _SHL9 _ret_ shl tos,#9 ' 8<< ff014 0ac 00644208 _SHL8 _ret_ shl tos,#8 ' 4* ff018 0ad 00644202 _SHL2 _ret_ shl tos,#2 ' 2* ( n1 -- n2 ) shift n1 left one bit (equiv to multiply by 2) ff01c 0ae 00644201 _SHL1 _ret_ shl tos,#1 ' REV ( n1 -- n2 ) Reverse bits 0..31 --> 31..0 ff020 0af 0d604269 _REV _ret_ rev tos '_BMASK bmask tos ' MASK ( bitpos -- bitmask \ only the lower 5 bits of bitpos are taken, regardless of the higher bits ) ff024 0b0 09c04221 MASK _ret_ decod tos ' ENCODE ( mask -- bitpos ) ff028 0b1 07804221 ENCODE _ret_ encod tos '' FAST MASKING ' 4BITS ( n -- nibble ) mask n to a nibble ff02c 0b2 0504420f BITS4 _ret_ and tos,#$0F ' 8BITS ( n -- nibble ) mask n to a byte ff030 0b3 050442ff BITS8 _ret_ and tos,#$FF ' 9BITS ff034 0b4 050443ff BITS9 _ret_ and tos,#$1FF { *** COMPARISON *** } ' Basic instructions from which other comparison instructions are built from ' = ( n1 n2 -- flg ) true if n1 is equal to n2 : 700ns @80 ff038 0b5 fdbffecc _EQ call #POPX ff03c 0b6 f180420b sub tos,fx ' n1 == 0 if equal ' 0= ( n -- flg ) true if n = 0 : 400ns @80 ff040 0b7 fb944202 _ZEQ tjz tos,#SETTRUE ff044 0b8 06044200 _ret_ mov tos,#0 ' 0<> ( n -- flg ) true if n <> 0 (promote n to boolean) : 400ns @80 ff048 0b9 fb944201 _ZNE tjz tos,#z1 ff04c 0ba 06004379 SETTRUE _ret_ mov tos,M1 ff050 0bb fd64002d z1 ret ' <> ( n1 n2 -- flg ) true if n1 <> n2 : 600ns @80 ff054 0bc f1884421 _NEQ sub tos1,tos wz ff058 0bd 56004579 if_nz mov tos1,M1 ff05c 0be fd9ffea8 jmp #DROP ' 0< ( n -- flg ) true if n < 0 (negative) : 400ns @80 ff060 0bf 00c4421f _ZLT _ret_ sar tos,#31 ' NOT ( n -- !n ) invert bits of n : 350ns @80 ff064 0c0 06204221 _NOT _ret_ not tos ' ABS ( n -- abs ) ff068 0c1 06404221 _ABS _ret_ abs tos,tos ff06c 0c2 fd004222 MULTIPLY qmul tos,tos1 ff070 0c3 fd604418 getqx tos1 ff074 0c4 fd9ffe90 jmp #DROP ff078 0c5 fa004421 MUL16 mul tos1,tos ff07c 0c6 fd9ffe88 jmp #DROP ' UM* ( u1 u2 -- u1*u2L u1*u2H ) ' DESC: unsigned 32bit * 32bit multiply -- 64bit result ff080 0c7 fd004222 UMMUL qmul tos,tos1 ff084 0c8 fd604418 getqx tos1 ff088 0c9 0d604219 _ret_ getqy tos ' U// ( dvdn dvsr -- rem quot ) ff08c 0ca fd104421 UDIVMOD qdiv tos1,tos ff090 0cb fd604218 getqx tos ff094 0cc 0d604419 _ret_ getqy tos1 ' MOD ( n1 mod -- rem ) ff098 0cd fdbffff0 UMOD call #UDIVMOD ff09c 0ce fd9ffe68 jmp #DROP ' U/ ( u1 u2 -- quot ) ff0a0 0cf fd104421 UDIVIDE qdiv tos1,tos ff0a4 0d0 fd604418 getqx tos1 ff0a8 0d1 fd9ffe5c jmp #DROP ' signed MIN returns the minimum of the two values ff0ac 0d2 f3604421 _MINS fles tos1,tos ff0b0 0d3 fd9ffe54 jmp #DROP ff0b4 0d4 f3404421 _MAXS fges tos1,tos ff0b8 0d5 fd9ffe4c jmp #DROP ' unsigned MIN returns the minimum of the two values ff0bc 0d6 f3204421 _MIN fle tos1,tos ff0c0 0d7 fd9ffe44 jmp #DROP ff0c4 0d8 f3004421 _MAX fge tos1,tos ff0c8 0d9 fd9ffe3c jmp #DROP { *** MEMORY *** } ' C@++ ( caddr -- caddr+1 byte ) fetch byte character and increment address ff0cc 0da f6001621 CFETCHINC mov fx,tos ' dup the address ff0d0 0db fdb0019c call #PUSHX ff0d4 0dc f1044401 add tos1,#1 ' inc the backup address ' C@ ( caddr -- byte ) Fetch a byte from hub memory : 500ns @80 ff0d8 0dd 0ac04221 CFETCH _ret_ rdbyte tos,tos ' DUPC@ ff0dc 0de fac01621 DUPCFT rdbyte fx,tos ff0e0 0df fd90018c jmp #PUSHX ' Push the internal fx register onto the datastack ' W@ ( waddr -- word ) Fetch a word from hub memory ff0e4 0e0 0ae04221 WFETCH _ret_ rdword tos,tos ' @ ( addr -- long ) Fetch a long from hub memory ff0e8 0e1 0b004221 FETCH _ret_ rdlong tos,tos ' C+! ( n caddr -- ) add n to byte at hub addr : 1.2us @80 ff0ec 0e2 fac01621 CPLUSST rdbyte fx,tos ' read in word from adress ff0f0 0e3 f100440b add tos1,fx ' add to contents of address - cascade ' C! ( n caddr -- ) store n to byte at addr : 1us @80 ff0f4 0e4 fc404421 CSTORE wrbyte tos1,tos ' write the byte using address on the tos ff0f8 0e5 fd9ffe08 jmp #DROP2 ' W+! ( n waddr -- ) add n to word at hub addr ff0fc 0e6 fae01621 WPLUSST rdword fx,tos ' read in word from address ff100 0e7 f100440b add tos1,fx ' W! ( n waddr -- ) store n to word at addr ff104 0e8 fc504421 WSTORE wrword tos1,tos ff108 0e9 fd9ffdf8 jmp #DROP2 ' +! ( n addr -- ) add n to long at hub addr ff10c 0ea fb001621 PLUSST rdlong fx,tos ' read in long from address ff110 0eb f100440b add tos1,fx ' ! ( n addr -- ) store n to long at addr ff114 0ec fc604421 STORE wrlong tos1,tos ff118 0ed fd9ffde8 jmp #DROP2 ' LUT@ ( addr -- data ) : 400ns ff11c 0ee 0aa04221 LUTFETCH _ret_ rdlut tos,tos ' LUT! ( data addr -- ) : 900ns ff120 0ef fc304421 LUTSTORE wrlut tos1,tos ff124 0f0 fd9ffddc jmp #DROP2 ' BLOCK MOVE ' ' 171219 64K in 19.866ms using rep vs 24.872ms using djnz ' RCMOVE bytes from source to destination primitive - $6.0000 $1.0000 LAP ERASE LAP DECIMAL .LAP 131208 cycles = 1.640ms/64K ' ( addr bytes -- ) ff144 0f8 fdb00124 ERASE call #PUSHACC ' ( addr cnt fillch -- ) ff148 0f9 fc804423 CFILL wrfast tos1,tos2 ff14c 0fa fcd80222 rep @.L0,tos1 ff150 0fb fd604215 wfbyte tos ff154 0fc fd9ffda8 .L0 jmp #DROP3 ' Test for non-zero data in memory block ' DATA? ( addr longs -- flg ) ff158 0fd fc780022 DATAQ rdfast #0,tos1 ff15c 0fe fcd80421 rep @.L0,tos ff160 0ff fd601612 rflong fx ff164 100 f540140b or ACC,fx ff168 101 f600440a .L0 mov tos1,ACC ff16c 102 fd9ffd98 jmp #DROP ' I ( -- index ) read the loop index ff170 103 f6001626 IX mov fx,index ff174 104 fd9000f8 jmp #PUSHX ' J ( -- index ) read the loop index ff178 105 f6001628 J mov fx,index2 ff17c 106 fd9000f0 jmp #PUSHX ' IC@ ( -- byte ) ff180 107 fac01626 ICFETCH rdbyte fx,index ff184 108 fd9000e8 jmp #PUSHX ' I+ ( n -- n+I ) fast index offset i.e. table I+ ff188 109 01004226 IPLUS _ret_ add tos,index { *** BRANCH & LOOP *** } ' ADO = BOUNDS DO - just a quick and direct way as BOUNDS is most often never used elsewhere ' ADO ( from cnt -- ) ff18c 10a fdbffdc8 ADO call #BOUNDS ' ' DO ( to from -- ) ff190 10b fdbffdc8 DO call #SWAP ff194 10c fdb000a4 call #PUSHL ' PUSH index onto loop stack ' ' FOR ( count -- ) Setup FOR...NEXT loop for count ' ff198 10d fc305212 FOR wrlut branchadr,braptr ff19c 10e f1042401 add braptr,#1 ff1a0 10f f60053f8 mov branchadr,PTRA ' >L ( n -- ) Push n onto the loop stack ff1a4 110 fd900094 jmp #PUSHL ' L> ( -- n ) Pop n from the loop stack ff1a8 111 fdb00078 LPOP call #LPOPX ' Pop loop stack into X ff1ac 112 fd9000c0 jmp #PUSHX ' Push X onto the data stack as tos ' +LOOP ( n1 -- ) ff1b0 113 fdbffd54 PLOOP call #POPX ' get loop increment ff1b4 114 f1004c0b add index,fx ' add to index ff1b8 115 f1844c01 sub index,#1 ' compensate so we can drop through to LOOP ' The comparison above is between the call insn (wr) at DELTA and the jump insn (nr) at POPX_ret, ' this will always be carry set. The call itself is indirect. ' ff1bc 116 f1044c01 LOOP add index,#1 ' increment index ff1c0 117 f2584a26 cmps limit1,index wcz ff1c4 118 1603f029 BRANCH if_a mov PTRA,branchadr ' Branch to the address that is saved in branch stack ff1c8 119 1d64002d if_a ret ff1cc 11a fdb00054 call #LPOPX ' discard the limit ff1d0 11b f1842401 POPBRANCH sub braptr,#1 ff1d4 11c f2142420 cmp braptr,#brastk wc ff1d8 11d c6042420 if_c mov braptr,#brastk ff1dc 11e faa05212 rdlut branchadr,braptr ff1e0 11f fd900040 jmp #LPOPX ' discard the index ' then next loop and its branch address ' ?NEXT ( flg -- index ) Same as NEXT except terminate early if flag is true and return with flag ff1e4 120 f6084221 QNEXT mov tos,tos wz ff1e8 121 5d9fffe4 if_nz jmp #POPBRANCH ff1ec 122 f19c4c01 sub index,#1 wcz ff1f0 123 5603f029 if_nz mov PTRA,branchadr ff1f4 124 5d9ffd10 if_nz jmp #DROP ' discard flag and continye looping ff1f8 125 fd9fffd4 jmp #POPBRANCH ' NEXT ( -- ) Decrement count (on loop stack) and loop until 0, then pop loop stack ff1fc 126 fb644df4 forNEXT djz index,#POPBRANCH ' exit loop ff200 127 0603f029 _ret_ mov PTRA,branchadr ' loop again ' LEAVE - make the loop index = to the limit so that it will leave on the next LOOP ff204 128 f6004c25 LEAVE mov index,limit1 ff208 129 01844c01 _ret_ sub index,#1 {HELP >R ( n -- ) Push n onto the return stack } ff20c 12a fc304214 PUSHR wrlut tos,retptr ff210 12b f1042801 add retptr,#1 ff214 12c fd9ffcf0 jmp #DROP {HELP R> ( -- n ) Pop n from the return stack } ff218 12d f1842801 RPOP sub retptr,#1 ff21c 12e faa01614 rdlut fx,retptr ff220 12f fd90004c jmp #PUSHX ' Push X onto the data stack as tos ff224 130 LPOPX ff224 130 f6001626 mov fx,index ff228 131 f6004c25 mov index,limit1 ff22c 132 f6004a28 mov limit1,index2 ff230 133 f6005027 mov index2,limit2 ff234 134 f1842601 sub lpptr,#1 ff238 135 0aa04e13 _ret_ rdlut limit2,lpptr ' 171231 - mod so that index is on top/last ' limit -> index ' index -> limit ' limit2 -> indexJ ' index2 -> limitJ ' stack ' >L ( tos -- ) Push tos onto the loop stack and drop tos ff23c 136 PUSHL ff23c 136 fc304e13 wrlut limit2,lpptr ' push bottom register to stack ff240 137 f1042601 add lpptr,#1 ff244 138 f6004e28 mov limit2,index2 ' ripple registers ff248 139 f6005025 mov index2,limit1 ff24c 13a f6004a26 mov limit1,index ff250 13b f6004c21 mov index,tos ff254 13c fd9ffcb0 jmp #POPX { *** LITERALS *** } ' LITERALS are stored unaligned in big endian format which faciliates cascading byte reads to accumulate the full number ' ( -- 32bits ) Push a 32-bit literal onto the datastack by reading in the next 4 bytes (non-aligned) ff258 13d fb041761 _LONG rdlong fx,PTRA++ ff25c 13e fd900010 jmp #PUSHX ' Read an inline word literal and push it onto the stack ' ff260 13f fae41761 _WORD rdword fx,PTRA++ ff264 140 fd900008 jmp #PUSHX ff268 141 _TRUE ff268 141 f1841401 MINUS1 sub ACC,#1 ff26c 142 f600160a PUSHACC mov fx,ACC ' Push the accumulator onto the stack then zero it ff270 143 f6041400 PUSHX mov ACC,#0 ' clear it for next operation ff274 144 fc304811 wrlut tos3,datptr ' save bottom of register stack into lut memory ff278 145 f1042201 add datptr,#1 ff27c 146 f6004823 mov tos3,tos2 ' push 4 top items held in registers ff280 147 f6004622 mov tos2,tos1 ff284 148 f6004421 mov tos1,tos ff288 149 f600420b mov tos,fx ' replace tos with X (DEFAULT) ff28c 14a f1042a01 add depth,#1 ' the depth variable indexes bytes in LUT ff290 14b 0d74006f _ret_ modcz 0,0 wc ' clear C for some operations that use this to determine behaviour { *** CONSTANTS & VARIABLES *** } { Constants and variables etc are standalone fragments preceded by an opcode then the parameters, either a long or the addess of the parameter field. They are called from the main program and only use the IP to get the result. } ff294 14c 00000000 DATCON nop ' This entry is used for constants that point to the DATA area - FORGETable by signature ff298 14d fb041700 CONL rdlong fx,PTRA ff29c 14e fdbfffd0 call #PUSHX ff2a0 14f fd9ffc4c jmp #EXIT { CONW rdword fx,PTRA call #PUSHX jmp #EXIT } ' INLINE: ff2a4 150 f60017f8 VARB mov fx,PTRA ff2a8 151 fdbfffc4 call #PUSHX ff2ac 152 fd9ffc40 jmp #EXIT { *** SMART PINS *** } { WRPIN D/#,S/# - Set smart pin S/# mode to D/# WXPIN D/#,S/# - Set smart pin S/# parameter X to D/# WYPIN D/#,S/# - Set smart pin S/# parameter Y to D/# RDPIN D,S/# - Get smart pin S/# result Z into D V30 WRPIN D/#,S/# - Set smart pin S/# mode to D/#, acknowledge pin WXPIN D/#,S/# - Set smart pin S/# parameter X to D/#, ack WYPIN D/#,S/# - Set smart pin S/# parameter Y to D/#, ack RDPIN D,S/# {WC} - Get smart pin S/# result Z into D, flag into C, ack RQPIN D,S/# {WC} - Get smart pin S/# result Z into D, flag into C, don't ack AKPIN S/# - Acknowledge pin S/# } ' 160620-2300 - MODIFIED SMARTPIN OPS TO USE "pinreg" for faster access ' WRPIN D/#,S/# - Set smart pin S/# mode to D/#, acknowledge pin ' WRPIN ( dst -- ) ff2b0 153 fc004218 _WRPIN wrpin tos,pinreg ff2b4 154 fd9ffc50 jmp #DROP ' WXPIN D/#,S/# - Set smart pin S/# parameter X to D/#, ack ' WXPIN ( dst -- ) ff2b8 155 fc104218 _WXPIN wxpin tos,pinreg ff2bc 156 fd9ffc48 jmp #DROP ' WYPIN D/#,S/# - Set smart pin S/# parameter Y to D/#, ack ' WYPIN ( dst -- ) ff2c0 157 fc204218 _WYPIN wypin tos,pinreg ff2c4 158 fd9ffc40 jmp #DROP ' RDPIN D,S/# {WC} - Get smart pin S/# result Z into D, flag into C, ack ' RDPIN ( -- res ) ff2c8 159 fa881618 _RDPIN rdpin fx,pinreg ff2cc 15a fd9fffa0 jmp #PUSHX ' RQPIN D,S/# {WC} - Get smart pin S/# result Z into D, flag into C, don't ack ' RQPIN ( -- res ) ff2d0 15b fa801618 _RQPIN rqpin fx,pinreg ff2d4 15c fd9fff98 jmp #PUSHX ' AKPIN S/# - Acknowledge pin S/# ' AKPIN ( -- ) ff2d8 15d 0c080218 _AKPIN _ret_ wrpin #1,pinreg ' BEGIN RDPIN $80 AND 0= UNTIL ff2dc 15e fa881618 WAITPIN rdpin fx,pinreg ff2e0 15f f40c1607 testb fx,#7 wz ff2e4 160 5d9ffff4 if_nz jmp #WAITPIN ff2e8 161 fd64002d ret ' TXDAT ( buf cnt -- ) write buffer direct to WYPIN ff2ec 162 fc780022 _TXDAT rdfast #0,tos+1 '' rep @.end,tos ff2f0 163 fd601610 .L1 rfbyte fx ff2f4 164 fc201618 wypin fx,pinreg ff2f8 165 fd703040 .wait testp pinreg wc '..wait for buffer empty ff2fc 166 3d9ffff8 if_nc jmp #.wait ff300 167 fc080218 akpin pinreg '..acknowledge pin ff304 168 fb6c43fa djnz tos,#.L1 ff308 169 fd9ffbf8 .end jmp #DROP2 { *** I/O ACCESS *** } ' Fast pin operations via PIN pinreg ' H - set the PIN high - fast as the parameter is in the pinreg ff30c 16a 0d603059 H _ret_ drvh pinreg ' L - set the PIN low - fast as the parameter is in the pinreg ff310 16b 0d603058 L _ret_ drvl pinreg ff314 16c 0d60305f _T _ret_ drvnot pinreg ' F - float pin ff318 16d 0d603040 F _ret_ dirl pinreg ' R - read pin ff31c 16e fd703040 R testp pinreg wc ff320 16f c1841401 if_c sub ACC,#1 ff324 170 fd9fff44 jmp #PUSHACC ' normal pin operations via stack ' HIGH ( pin -- ) ff328 171 fd604259 HIGH drvh tos ff32c 172 fd9ffbd8 jmp #DROP ' LOW ( pin -- ) ff330 173 fd604258 LOW drvl tos ff334 174 fd9ffbd0 jmp #DROP ' FLOAT ( pin -- ) ff338 175 fd604240 _FLOAT dirl tos ff33c 176 fd9ffbc8 jmp #DROP ' PIN@ ( bit -- state ) ff340 177 fd704240 PINTEST testp tos wc ff344 178 05804379 _ret_ muxc tos,M1 ff348 179 ffffffff M1 long -1 '************************************* SERIAL I/O ************************************** ff34c 17a f6030621 SEROUT mov txpin,tos ff350 17b fd9ffbb4 jmp #DROP ff354 17c f6001a21 CONEMIT mov R1,tos ff358 17d f607063e TXR1 mov txpin,#tx_pin ff35c 17e fc201b83 wypin r1,txpin '..send byte ff360 17f fd64001f waitx #0 ff364 180 fd730640 .wait testp txpin wc '..wait for buffer empty ff368 181 3d9ffff8 if_nc jmp #.wait ff36c 182 fd9ffb98 jmp #DROP ff370 183 0000003e txpin long tx_pin '********************** SPI READ/WRITE ********************* ' 461.7us/512 ' SPI>BUF ( dst cnt -- sum ) ff374 184 fc880022 SPIRX wrfast #0,tos1 ff378 185 f6044400 mov tos1,#0 ff37c 186 fcdc0808 .L0 rep @.end,#8 ' 8 bits ff380 187 fd60044f outnot sck ' clock (low high or low high) ff384 188 fd60044f outnot sck ff388 189 fd700840 testp miso wc ' read data from card ff38c 18a f0a41a01 rcl r1,#1 ' shift in msb first ff390 18b fd601a15 .end wfbyte r1 ff394 18c f100440d add tos1,r1 ff398 18d fb6c43f8 djnz tos,#.L0 ff39c 18e fd9ffb68 jmp #DROP ff3a0 18f SPIRDL ff3a0 18f fcdc0c20 rep @sre1,#32 ff3a4 190 fd640231 skip #1 ' SPIRD ( dat -- dat+rd ) ff3a8 191 fcdc0808 SPIRD rep @sre1,#8 ' 8 bits ff3ac 192 fd60044f outnot sck ' clock (low high) ff3b0 193 fd60044f outnot sck ff3b4 194 fd700840 testp miso wc ' read data from card ff3b8 195 f0a44201 rcl tos,#1 ' shift in msb first ff3bc 196 fd64002d sre1 ret ' 474.6us/512 ' SPITX ( src bytes -- ) ff3c0 197 fd600a58 SPITXE drvl ss ff3c4 198 fc780022 SPITX rdfast #0,tos1 ff3c8 199 fd601a10 .L0 rfbyte r1 ff3cc 19a f0641a18 shl r1,#24 ff3d0 19b fcdc0808 rep @.L1 , #8 ff3d4 19c f0341a01 rol r1,#1 wc ' output next msb ff3d8 19d fd60064a outc mosi ff3dc 19e fd60044f outnot sck ' clock ff3e0 19f fd60044f outnot sck ' clock ff3e4 1a0 fb6c43f8 .L1 djnz tos,#.L0 ff3e8 1a1 fd9ffb18 jmp #DROP2 ff3ec 1a2 f6041a20 SPIWRL mov r1,#32 ff3f0 1a3 fd900028 jmp #SPIWR ff3f4 1a4 f0644208 SPIWM shl tos,#8 ff3f8 1a5 f6041a18 mov r1,#24 ff3fc 1a6 fd90001c jmp #SPIWR ff400 1a7 f0644210 SPIWR16 shl tos,#16 ff404 1a8 f6041a10 mov r1,#16 ff408 1a9 fd900010 jmp #SPIWR ' Write SD Command ff40c 1aa f504423f SPIWRC and tos,#$3F ff410 1ab f5444240 or tos,#$40 ' SPIWR8 ( byte -- ) ' Shift 8 bits from data[0..7] out and leave data on stack (restored with other bytes zeroed) ' ff414 1ac f0644218 SPIWR8 shl tos , #24 ' left justify 8-bit data s ff418 1ad f6041a08 mov r1,#8 ff41c 1ae fd600a58 SPIWR drvl ss ' chip enable ff420 1af fcd8080d rep @.L1 , r1 ff424 1b0 f0344201 rol tos,#1 wc ' output next msb ff428 1b1 fd60064a outc mosi ff42c 1b2 fd60044f outnot sck ' clock ff430 1b3 fd60044f outnot sck ' clock ff434 1b4 fd9ffad0 .L1 jmp #DROP ff438 1b5 0d600a49 SPICE _ret_ outh ss ' I2C support ' CLKOUT ( iobit dat -- iobit dat2 ) REG6=iomask ) Shift msb bit out, clock high, clock low ff43c 1b6 fd604448 CLKOUT outl tos+1 ' ensure output will be active low ff440 1b7 fd603658 drvl clockpins ff444 1b8 f0744201 shl tos,#1 wc ff448 1b9 fd604443 dirnc tos+1 ' make it an output if it is a low else float ' CLOCK ( REG6=iomask ) Toggle multiple bits on the output) ff44c 1ba fd60364f CLOCK outnot clockpins ff450 1bb fb943802 tjz clkdly,#ckx ff454 1bc f600161c mov fx,clkdly ff458 1bd 0b6c17ff _ret_ djnz fx,#$ ff45c 1be fd64002d ckx ret ' $01CA ' CLKIN ( iomask dat -- iomask dat2 ) ff460 1bf fd604440 CLKIN dirl tos+1 ff464 1c0 fd704440 testp tos+1 wc ff468 1c1 f0a44201 rcl tos,#1 ff46c 1c2 fd9fffdc jmp #CLOCK ' timing utility word ff470 1c3 f6002e16 LAP mov lap2,lap1 ff474 1c4 0d602c1a _ret_ getct lap1 ff478 1c5 ENDCOG ff478 1c5 fit 496 '************************************************************************************ '************************************** DICTIONARY ********************************** '************************************************************************************ { *** DICTIONARY *** } ff478 orgh ff478 romdict ' The count field is left blank but filled in at cold boot so that these do not need to be calculated when defining ' '' CNT,NAME,ATR,addr16 ff478 50554403 byte 3, "DUP" ff47c 0073 word DUP ff47e 45564f04 byte 4, "OVER" ff483 0077 word OVER ff485 41575304 byte 4, "SWAP" ff48a 007e word SWAP ff48c 544f5203 byte 3, "ROT" ff490 0082 word ROT ff492 4f522d04 byte 4, "-ROT" ff497 0081 word ROT2 ff499 4f524404 byte 4, "DROP" ff49e 0069 word DROP ff4a0 44523303 byte 3, "3RD" ff4a4 0079 word THIRD ff4a6 48543403 byte 3, "4TH" ff4aa 007b word FOURTH ff4ac 52443205 byte 5, "2DROP" ff4b2 0068 word DROP2 ff4b4 52443305 byte 5, "3DROP" ff4ba 0067 word DROP3 ff4bc 50494e03 byte 3, "NIP" ff4c0 0065 word NIP ff4c2 57533205 byte 5, "2SWAP" ff4c8 eb70 word DSWAP ff4ca 55443204 byte 4, "2DUP" ff4cf 0076 word DUP2 ff4d1 55443f04 byte 4, "?DUP" ff4d6 0072 word QDUP ' BITWISE LOGIC ff4d8 444e4103 byte 3, "AND" ff4dc 0093 word _AND ff4de 444e4104 byte 4, "ANDN" ff4e3 0095 word _ANDN ff4e5 524f02 byte 2, "OR" ff4e8 0097 word _OR ff4ea 524f5803 byte 3, "XOR" ff4ee 0099 word _XOR '' byte 5, "ZEROX" '' word _ZEROX ' SHIFT' ff4f0 4c4f5203 byte 3, "ROL" ff4f4 00a8 word _ROL ff4f6 524f5203 byte 3, "ROR" ff4fa 00a2 word _ROR ff4fc 3e3e02 byte 2, ">>" ff4ff 009b word _SHR ff501 3c3c02 byte 2, "<<" ff504 00a6 word _SHL ff506 52415303 byte 3, "SAR" ff50a 00a4 word _SAR ff50c 2f3202 byte 2, "2/" ff50f 00a1 word _SHR1 ff511 2a3202 byte 2, "2*" ff514 00ae word _SHL1 ff516 2f3402 byte 2, "4/" ff519 00a0 word _SHR2 ff51b 2a3402 byte 2, "4*" ff51e 00ad word _SHL2 ff520 3c3c3803 byte 3, "8<<" ff524 00ac word _SHL8 ff526 3e363104 byte 4, "16>>" ff52b 009d word _SHR16 ff52d 3e3e3803 byte 3, "8>>" ff531 009f word _SHR8 ff533 3c3c3903 byte 3, "9<<" ff537 00ab word _SHL9 ff539 3e3e3903 byte 3, "9>>" ff53d 009e word _SHR9 ff53f 56455203 byte 3, "REV" ff543 00af word _REV ff545 3c7c02 byte 2, "|<" ff548 00b0 word MASK ff54a 7c3e02 byte 2, ">|" ff54d 00b1 word ENCODE ff54f 4e3e02 byte 2, ">N" ff552 00b2 word BITS4 ff554 423e02 byte 2, ">B" ff557 00b3 word BITS8 ff559 393e02 byte 2, ">9" ff55c 00b4 word BITS9 ff55e 54494204 byte 4, "BITS" ff563 0091 word BITS ff565 544f4e03 byte 3, "NOT" ff569 00c0 word _NOT ' COMPARISON ff56b 3d01 byte 1, "=" ff56d 00b5 word _EQ ff56f 3e3c02 byte 2, "<>" ff572 00bc word _NEQ ff574 3d3002 byte 2, "0=" ff577 00b7 word _ZEQ ff579 3e3c3003 byte 3, "0<>" ff57d 00b9 word _ZNE ff57f 3c3002 byte 2, "0<" ff582 00bf word _ZLT ff584 3c01 byte 1, "<" ff586 eb28 word LT ff588 3c5502 byte 2, "U<" ff58b eb30 word _ULT ff58d 3e01 byte 1, ">" ff58f eb20 word GT ff591 3e5502 byte 2, "U>" ff594 d112 word UGT ff596 3d3c02 byte 2, "<=" ff599 d118 word LTEQ ff59b 3e3d02 byte 2, "=>" ff59e d11a word EQGT ff5a0 54495706 byte 6, "WITHIN" ff5a7 d776 word WITHIN ff5a9 50554405 byte 5, "DUPC@" ff5af 00de word DUPCFT ff5b1 404302 byte 2, "C@" ff5b4 00dd word CFETCH ff5b6 405702 byte 2, "W@" ff5b9 00e0 word WFETCH ff5bb 4001 byte 1, "@" ff5bd 00e1 word FETCH ff5bf 212b4303 byte 3, "C+!" ff5c3 00e2 word CPLUSST ff5c5 214302 byte 2, "C!" ff5c8 00e4 word CSTORE ff5ca 2b404304 byte 4, "C@++" ff5cf 00da word CFETCHINC ff5d1 212b5703 byte 3, "W+!" ff5d5 00e6 word WPLUSST ff5d7 215702 byte 2, "W!" ff5da 00e8 word WSTORE ff5dc 212b02 byte 2, "+!" ff5df 00ea word PLUSST ff5e1 2101 byte 1, "!" ff5e3 00ec word STORE ff5e5 54494204 byte 4, "BIT!" ff5ea ec08 word BITST ff5ec 54455303 byte 3, "SET" ff5f0 ec10 word SET ff5f2 524c4303 byte 3, "CLR" ff5f6 ec20 word CLR ff5f8 54455304 byte 4, "SET?" ff5fd ec30 word BITQ ' MATHS ff5ff 2b3102 byte 2, "1+" ff602 008c word INC ff604 2d3102 byte 2, "1-" ff607 0089 word DEC ff609 2b3202 byte 2, "2+" ff60c 008b word INC2 ff60e 2d3202 byte 2, "2-" ff611 0088 word DEC2 ff613 2b3402 byte 2, "4+" ff616 008a word INC4 ff618 2b01 byte 1, "+" ff61a 0086 word PLUS ff61c 2d01 byte 1, "-" ff61e 0085 word MINUS ff620 2a4d5503 byte 3, "UM*" ff624 00c7 word UMMUL ff626 2a01 byte 1, "*" ff628 00c2 word MULTIPLY ff62a 2a5702 byte 2, "W*" ff62d 00c5 word MUL16 ff62f 2f01 byte 1, "/" ff631 d120 word DIVIDE ff633 2f5502 byte 2, "U/" ff636 00cf word UDIVIDE ff638 2f2f5503 byte 3, "U//" ff63c 00ca word UDIVMOD ff63e 2f2f02 byte 2, "//" ff641 00cd word UMOD ff643 2f2a02 byte 2, "*/" ff646 d132 word MULDIV ff648 2f4d5504 byte 4, "UM//" ff64d eb3c word UMDIVMOD64 ff64f 2b2b4303 byte 3, "C++" ff653 d144 word CINC ff655 2d2d4303 byte 3, "C--" ff659 d140 word CDEC ff65b 2b2b5703 byte 3, "W++" ff65f d150 word WINC ff661 2d2d5703 byte 3, "W--" ff665 d14c word WDEC ff667 2b2b02 byte 2, "++" ff66a d15c word LINC ff66c 2d2d02 byte 2, "--" ff66f d158 word LDEC ff671 444e5203 byte 3, "RND" ff675 eb08 word _RND ff677 54454706 byte 6, "GETRND" ff67e ec84 word _GETRND ff680 52515304 byte 4, "SQRT" ff685 ec70 word _SQRT ff687 54455307 byte 7, "SETDACS" ff68f ec7c word _SETDACS ff691 7e01 byte 1, "~" ff693 ec44 word CLRL ff695 7e7e02 byte 2, "~~" ff698 ec40 word SETL ff69a 7e5702 byte 2, "W~" ff69d ec50 word CLRW ff69f 7e7e5703 byte 3, "W~~" ff6a3 ec4c word SETW ff6a5 7e4302 byte 2, "C~" ff6a8 ec5c word CLRC ff6aa 7e7e4303 byte 3, "C~~" ff6ae ec58 word SETC ff6b0 533e4c03 byte 3, "L>S" ff6b4 ebf8 word L2S ff6b6 573e02 byte 2, ">W" ff6b9 e19c word TOW ff6bb 573e4c03 byte 3, "L>W" ff6bf e1a2 word L2W ff6c1 423e5703 byte 3, "W>B" ff6c5 e1ac word W2B ff6c7 4c3e5703 byte 3, "W>L" ff6cb e1c0 word W2L ff6cd 573e4203 byte 3, "B>W" ff6d1 e1c2 word B2W ff6d3 4c3e4203 byte 3, "B>L" ff6d7 e1b8 word B2L ff6d9 4e494d04 byte 4, "MINS" ff6de 00d2 word _MINS ff6e0 58414d04 byte 4, "MAXS" ff6e5 00d4 word _MAXS ff6e7 4e494d03 byte 3, "MIN" ff6eb 00d6 word _MIN ff6ed 58414d03 byte 3, "MAX" ff6f1 00d8 word _MAX ff6f3 53424103 byte 3, "ABS" ff6f7 00c1 word _ABS ff6f9 454e2d07 byte 7, "-NEGATE" ff701 008d word MNEGATE ff703 454e3f07 byte 7, "?NEGATE" ff70b 008e word QNEGATE ff70d 47454e06 byte 6, "NEGATE" ff714 0090 word NEGATE ' CONSTANTS ' ff716 4e4f02 byte 2, "ON" ff719 0141 word MINUS1 ff71b 55525404 byte 4, "TRUE" ff720 0141 word MINUS1 ff722 312d02 byte 2, "-1" ff725 0141 word MINUS1 ff727 4c414605 byte 5, "FALSE" ff72d f800 word _0 ff72f 46464f03 byte 3, "OFF" ff733 f800 word _0 ' STRUCTURES ff735 544f4784 byte 4+im, "GOTO" ff73a d504 word GOTO ff73c 464982 byte 2+im, "IF" ff73f d4f8 word _IF_ ff741 534c4584 byte 4+im, "ELSE" ff746 d50e word _ELSE_ ff748 45485484 byte 4+im, "THEN" ff74d d51e word _THEN_ 'byte 5, "ENDIF" +im 'word _THEN_ ff74f 47454285 byte 5+im, "BEGIN" ff755 d4b0 word _BEGIN_ ff757 544e5585 byte 5+im, "UNTIL" ff75d d4de word _UNTIL_ ff75f 41474185 byte 5+im, "AGAIN" ff765 d4d2 word _AGAIN_ ff767 49485785 byte 5+im, "WHILE" ff76d d4f8 word _IF_ ff76f 50455286 byte 6+im, "REPEAT" ff776 d4cc word _REPEAT_ ff778 49575306 byte 6, "SWITCH" ff77f d752 word _SWITCH ff781 53414305 byte 5, "CASE@" ff787 d756 word SWFETCH ff789 53414305 byte 5, "CASE=" ff78f d75a word ISEQ ff791 53414305 byte 5, "CASE>" ff797 d770 word ISWITHIN ff799 45524285 byte 5+im, "BREAK" ff79f d768 word ISEND ff7a1 53414384 byte 4+im, "CASE" ff7a6 d760 word _CASE ' LOOPS' ff7a8 4f444103 byte 3, "ADO" ff7ac 010a word ADO ff7ae 4f4402 byte 2, "DO" ff7b1 010b word DO ff7b3 4f4f4c04 byte 4, "LOOP" ff7b8 0116 word LOOP ff7ba 4f4c2b05 byte 5, "+LOOP" ff7c0 0113 word PLOOP ff7c2 524f4603 byte 3, "FOR" ff7c6 010d word FOR ff7c8 58454e04 byte 4, "NEXT" ff7cd 0126 word forNEXT ff7cf 454e3f05 byte 5, "?NEXT" ff7d5 0120 word QNEXT ff7d7 4901 byte 1, "I" ff7d9 0103 word IX ff7db 4a01 byte 1, "J" ff7dd 0105 word J ff7df 41454c05 byte 5, "LEAVE" ff7e5 0128 word LEAVE ff7e7 40434903 byte 3, "IC@" ff7eb 0107 word ICFETCH ff7ed 2b4902 byte 2, "I+" ff7f0 0109 word IPLUS ff7f2 554f4206 byte 6, "BOUNDS" ff7f9 007d word BOUNDS ' -------------I/O--------------- ff7fb 4801 byte 1, "H" ff7fd 016a word H ff7ff 4c01 byte 1, "L" ff801 016b word L ff803 5401 byte 1, "T" ff805 016c word _T ff807 4601 byte 1, "F" ff809 016d word F ff80b 5201 byte 1, "R" ff80d 016e word R ff80f 47494804 byte 4, "HIGH" ff814 0171 word HIGH ff816 574f4c03 byte 3, "LOW" ff81a 0173 word LOW ff81c 4f4c4605 byte 5, "FLOAT" ff822 0175 word _FLOAT ff824 4e495004 byte 4, "PIN@" ff829 0177 word PINTEST '' byte 6, "SHROUT" '' word SHROUT '' byte 6, "SHRINP" '' word SHRINP ' SMARTPIN INSTRUCTIONS ff82b 50525705 byte 5, "WRPIN" ff831 0153 word _WRPIN ff833 50585705 byte 5, "WXPIN" ff839 0155 word _WXPIN ff83b 50595705 byte 5, "WYPIN" ff841 0157 word _WYPIN ff843 50445205 byte 5, "RDPIN" ff849 0159 word _RDPIN ff84b 50515205 byte 5, "RQPIN" ff851 015b word _RQPIN ff853 504b4105 byte 5, "AKPIN" ff859 015d word _AKPIN ff85b 49415707 byte 7, "WAITPIN" ff863 015e word WAITPIN ff865 41525705 byte 5, "WRACK" ff86b eaf4 word WRACK ff86d 4e495003 byte 3, "PIN" ff871 eae4 word _PIN ff873 49504004 byte 4, "@PIN" ff878 eadc word _ATPIN ff87a 736e02 byte 2, "ns" ff87d d1be word ns ff87f 575002 byte 2, "PW" ff882 d1c6 word PW ff884 4c555005 byte 5, "PULSE" ff88a d1d0 word PULSE ff88c 4c555006 byte 6, "PULSES" ff893 d1d2 word PULSES ff895 4c494804 byte 4, "HILO" ff89a d1d6 word HILO ' SMARTPIN NCO/PWM ff89c 54554404 byte 4, "DUTY" ff8a1 d18e word DUTY ff8a3 4f434e03 byte 3, "NCO" ff8a7 d17c word NCO ff8a9 5a4802 byte 2, "HZ" ff8ac d17a word HZ ff8ae 5a484b03 byte 3, "KHZ" ff8b2 d176 word KHZ ff8b4 5a484d03 byte 3, "MHZ" ff8b8 d172 word MHZ ff8ba 54554d04 byte 4, "MUTE" ff8bf d168 word MUTE ff8c1 494c4205 byte 5, "BLINK" ff8c7 d1a2 word BLINK ff8c9 4d575003 byte 3, "PWM" ff8cd d1a8 word PWM ff8cf 57415303 byte 3, "SAW" ff8d3 d1ba word SAW ' SMARTPIN ASYNCH ff8d5 54494203 byte 3, "BIT" ff8d9 d1f0 word BIT ff8db 55414204 byte 4, "BAUD" ff8e0 d1fc word BAUDST ff8e2 44585403 byte 3, "TXD" ff8e6 d1f8 word TXD ff8e8 44585203 byte 3, "RXD" ff8ec d218 word RXD ff8ee 44585405 byte 5, "TXDAT" ff8f4 0162 word _TXDAT { byte c, "PA@" word PAFETCH byte c, "PB@" word PBFETCH byte c, "PA!" word PASTORE byte c, "PB!" word PBSTORE byte c, "DACLR" word DACLR byte c, "DBCLR" word DBCLR byte c, "PASET" word PASET byte c, "DASET" word DASET byte c, "PBSET" word PBSET byte c, "DBSET" word DBSET byte c, "PACLR" word PACLR byte c, "PBCLR" word PBCLR } ff8f6 49415705 byte 5, "WAITX" ff8fc ebec word DELTA ff8fe 49415707 byte 7, "WAITCNT" ff906 ebf4 word WAITCNTS ff908 42455206 byte 6, "REBOOT" ff90f d254 word REBOOT ff911 53455205 byte 5, "RESET" ff917 0000 word RESET ff919 58453005 byte 5, "0EXIT" ff91f 0061 word ZEXIT ff921 49584504 byte 4, "EXIT" ff926 0063 word EXIT '' byte 6, "SKIPNZ" '' word SKIPNZ ff928 504f4e03 byte 3, "NOP" ff92c 0071 word _NOP ff92e 4c414304 byte 4, "CALL" ff933 002d word ACALL ff935 4d554a04 byte 4, "JUMP" ff93a 002b word AJMP ff93c 523e02 byte 2, ">R" ff93f 012a word PUSHR ff941 3e5202 byte 2, "R>" ff944 012d word RPOP ff946 4c3e02 byte 2, ">L" ff949 0136 word PUSHL ff94b 3e4c02 byte 2, "L>" ff94e 0111 word LPOP ff950 50532103 byte 3, "!SP" ff954 e9b4 word INITSP ff956 50454405 byte 5, "DEPTH" ff95c ed50 word _DEPTH ff95e 474f4304 byte 4, "COG@" ff963 ebc8 word COGFETCH ff965 474f4304 byte 4, "COG!" ff96a ebd0 word COGSTORE ff96c 54554c04 byte 4, "LUT@" ff971 00ee word LUTFETCH ff973 54554c04 byte 4, "LUT!" ff978 00ef word LUTSTORE ff97a 474f4305 byte 5, "COGID" ff980 ebdc word _COGID ff982 474f4307 byte 7, "COGINIT" ff98a ebe4 word _COGINIT ff98c 474f4307 byte 7, "COGSTOP" ff994 ea8c word _COGSTOP ff996 57454e06 byte 6, "NEWCOG" ff99d ed58 word NEWCOG ff99f 474f4306 byte 6, "COGATN" ff9a6 ea9c word _COGATN ff9a8 4c4f5007 byte 7, "POLLATN" ff9b0 eaa4 word _POLLATN ff9b2 54455306 byte 6, "SETEDG" ff9b9 eab0 word _SETEDG ff9bb 4c4f5007 byte 7, "POLLEDG" ff9c3 eac0 word _POLLEDG ff9c5 59454b03 byte 3, "KEY" ff9c9 e0b2 word KEY ff9cb 454b5704 byte 4, "WKEY" ff9d0 e104 word WKEY ff9d2 59454b04 byte 4, "KEY!" ff9d7 e0ae word PUTKEY '' byte 7, "keypoll" '' word rg+keypoll ff9d9 4e4f4303 byte 3, "CON" ff9dd d094 word _CON ff9df 4e4f4e04 byte 4, "NONE" ff9e4 d0a6 word NONE ff9e6 4d4f4303 byte 3, "COM" ff9ea d09a word _COM '' byte 7, "DISCARD" '' word DISCARD ff9ec 4e4f4306 byte 6, "CONKEY" ff9f3 e0d8 word CONKEY ff9f5 4e4f4307 byte 7, "CONEMIT" ff9fd 017c word CONEMIT ff9ff 52455306 byte 6, "SEROUT" ffa06 017a word SEROUT ffa08 494d4504 byte 4, "EMIT" ffa0d d05a word EMIT ffa0f 494d4505 byte 5, "EMITS" ffa15 d07a word EMITS ffa17 4c524304 byte 4, "CRLF" ffa1c d0e2 word CRLF ffa1e 524302 byte 2, "CR" ffa21 d0e8 word CR ffa23 534c4303 byte 3, "CLS" ffa27 d0ae word CLS { byte 3, "DOT" word DOT } ffa29 41505305 byte 5, "SPACE" ffa2f d058 word SPACE ffa31 41505306 byte 6, "SPACES" ffa38 d076 word SPACES ' DUMP MEMORY ffa3a 4d415203 byte 3, "RAM" ffa3e d882 word RAM ffa40 4d554405 byte 5, "DUMP:" ffa46 d832 word SETDMP ffa48 4d554404 byte 4, "DUMP" ffa4d d83c word DUMP ffa4f 4d554405 byte 5, "DUMPW" ffa55 d88c word DUMPW ffa57 4d554405 byte 5, "DUMPL" ffa5d d8a0 word DUMPL ffa5f 4d554405 byte 5, "DUMPA" ffa65 d8b8 word DUMPA ffa67 4d554406 byte 6, "DUMPAW" ffa6e d8b4 word DUMPAW ffa70 445102 byte 2, "QD" ffa73 d86a word QD ffa75 575102 byte 2, "QW" ffa78 d88a word QW ffa7a 42454405 byte 5, "DEBUG" ffa80 d948 word DEBUG ffa82 69736c04 byte 4, "lsio" ffa87 d98e word lsio ffa89 474f4303 byte 3, "COG" ffa8d d90e word _COG ffa8f 54554c03 byte 3, "LUT" ffa93 d90a word _LUT ffa95 424b02 byte 2, "KB" ffa98 d7c4 word KB ffa9a 424d02 byte 2, "MB" ffa9d d7c2 word MB ffa9f 4d01 byte 1, "M" ffaa1 d7bc word M ' PRINTING ffaa3 2e01 byte 1, "." ffaa5 da82 word PRT ffaa7 49525005 byte 5, "PRINT" ffaad da82 word PRT ffaaf 53412e03 byte 3, ".AS" ffab3 db96 word PRTAS ffab5 53412e84 byte 4+im, ".AS",$22 ffaba dbcc word PRTASR ffabc 45442e05 byte 5, ".DECL" ffac2 dbd4 word PRTDECL ffac4 45442e05 byte 5, ".DEC4" ffaca dbe8 word PRTDEC4 '' byte 5, ".DEC2" '' word PRTDEC2 '' byte c, "@PAD" '' word ATPAD ffacc 4c4f4804 byte 4, "HOLD" ffad1 da4e word HOLD '' byte 5, ">CHAR" '' word BINASC ffad3 3e2302 byte 2, "#>" ffad6 da72 word RHASH ffad8 233c02 byte 2, "<#" ffadb da46 word LHASH ffadd 2301 byte 1, "#" ffadf da56 word HASH ffae1 532302 byte 2, "#S" ffae4 da68 word HASHS ffae6 3e443c03 byte 3, "" ffaea da7c word DNUM ffaec 2e5502 byte 2, "U." ffaef da8e word UPRT ffaf1 45442e04 byte 4, ".DEC" ffaf6 dbfa word PRTDEC ffaf8 49422e04 byte 4, ".BIN" ffafd daa8 word PRTBIN ffaff 482e02 byte 2, ".H" ffb02 d7ca word PRTHEX ffb04 422e02 byte 2, ".B" ffb07 d7e2 word PRTB ffb09 59422e05 byte 5, ".BYTE" ffb0f d7e4 word PRTBYTE ffb11 572e02 byte 2, ".W" ffb14 d7ee word PRTW ffb16 4f572e05 byte 5, ".WORD" ffb1c d7f0 word PRTWORD ffb1e 4c2e02 byte 2, ".L" ffb21 d7f8 word PRTL ffb23 4f4c2e05 byte 5, ".LONG" ffb29 d7fa word PRTLONG ffb2b 44412e05 byte 5, ".ADDR" ffb31 d8da word PRTADR ffb33 49525006 byte 6, "PRINT$" ffb3a da94 word PRINTSTR ffb3c 4e454c04 byte 4, "LEN$" ffb41 0056 word STRLEN ffb43 2281 byte 1+im, $22 ffb45 d5aa word _STRING_ ffb47 222e82 byte 2+im, $2E,$22 ffb4a d5c4 word _PSTR_ ' ." ffb4c 59544305 byte 5, "CTYPE" ffb52 e1c6 word CTYPE ffb54 58453f05 byte 5, "?EXIT" ffb5a 005e word IFEXIT '' byte c, "MOVBYTES" '' word _MOVBYTES ' MEMORY BLOCKS ffb5c 54414405 byte 5, "DATA?" ffb62 00fd word DATAQ ffb64 41524505 byte 5, "ERASE" ffb6a 00f8 word ERASE ffb6c 4c494604 byte 4, "FILL" ffb71 00f9 word CFILL ffb73 4f4d4305 byte 5, "CMOVE" ffb79 00f2 word CMOVE ffb7b 4d433c06 byte 6, "#" ffbef d402 word NUMBER ffbf1 41444005 byte 5, "@DATA" ffbf7 e308 word ATDAT ffbf9 52454804 byte 4, "HERE" ffbfe d680 word ATHERE ffc00 45484005 byte 5, "@HERE" ffc06 fe9e word rg+here ffc08 4f434006 byte 6, "@CODES" ffc0f fea2 word rg+codes ' TABLES '' byte 6, "LOOKIN" '' word LOOKIN '' byte 6, "LOOKUP" '' word _LOOKUP ' VARIABLES ffc11 6d657505 byte 5, "uemit" ffc17 fe10 word rg+uemit ffc19 656b7504 byte 4, "ukey" ffc1e fe12 word rg+ukey ffc20 61686304 byte 4, "char" ffc25 f8f0 word w+lastkey ffc27 6c656405 byte 5, "delim" ffc2d fe6c word rg+delim ffc2f 6d616e05 byte 5, "names" ffc35 fe96 word rg+names ffc37 53415404 byte 4, "TASK" ffc3c ddb6 word TASK ffc3e 47455203 byte 3, "REG" ffc42 ea7c word ATREG ffc44 4f574005 byte 5, "@WORD" ffc4a fe24 word rg+wordbuf ffc4c 49505304 byte 4, "SPIN" ffc51 d0b6 word SPINNER ' | compile byte || compile word , compile long ffc53 7c81 byte 1+im, "|" ffc55 d60a word CCOMP ffc57 7c7c82 byte 2+im, "||" ffc5a d61a word WCOMP ffc5c 2c81 byte 1+im, "," ffc5e d61e word LCOMP ffc60 5d575b83 byte 3+im, "[W]" ffc64 d5f8 word COMPW ffc66 5d225b83 byte 3+im, "[",$22,"]" ffc6a d5ca word COMPSTR ffc6c 4c554e05 byte 5, "NULL$" ffc72 d562 word NULLSTR ffc74 212402 byte 2, "$!" ffc77 d566 word STRST ffc79 3d2402 byte 2, "$=" ffc7c d570 word STREQ ' DEFINITIONS ' ffc7e 4d534103 byte 3, "ASM" ffc82 0054 word _ASM ffc84 524f4686 byte 6+im, "FORGET" ffc8b e162 word FORGET ffc8d 45524387 byte 7+im, "CREATE$" ffc95 d690 word CREATEWORD ffc97 45524386 byte 6+im, "CREATE" ffc9e d6dc word CREATE ffca0 52415683 byte 3+im, "VAR" ffca4 d6ec word _VAR ffca6 62757083 byte 3+im, "pub" ffcaa d722 word PUBDEF ffcac 69727083 byte 3+im, "pri" ffcb0 d72c word PRIDEF ffcb2 65727083 byte 3+im, "pre" ffcb6 d728 word PREDEF { byte 6+im, "module" word MODDEF } ffcb8 3a81 byte 1+im, ":" ffcba d722 word NEWDEF ffcbc 3b81 byte 1+im, ";" ffcbe d744 word ENDDEF ffcc0 5b81 byte 1+im, "[" ffcc2 d748 word UNDEF ffcc4 5d81 byte 1+im, "]" ffcc6 d724 word REDEF ffcc8 2781 byte 1+im, "'" ffcca d666 word ATICK '' byte 2+im, ":=" '' word _CON9 ffccc 3d3a82 byte 2+im, ":=" ffccf d704 word _CONST ffcd1 213d3d03 byte 3, "==!" ffcd5 d6e8 word CONST ffcd7 494c4105 byte 5, "ALIGN" ffcdd d674 word _ALIGN ffcdf 54414486 byte 6+im, "DATCON" ffce6 d712 word _DATCON ffce8 4c4c4105 byte 5, "ALLOT" ffcee d62a word ALLOT ffcf0 67726f03 byte 3, "org" ffcf4 e30e word DATORG ffcf6 74796285 byte 5+im, "bytes" ffcfc e32c word dbytes ffcfe 726f7785 byte 5+im, "words" ffd04 e328 word dwords ffd06 6e6f6c85 byte 5+im, "longs" ffd0c e324 word dlongs ffd0e 74796284 byte 4+im, "byte" ffd13 e336 word dbyte ffd15 726f7784 byte 4+im, "word" ffd1a e33a word dword ffd1c 6e6f6c84 byte 4+im, "long" ffd21 e33e word dlong ffd23 73657203 byte 3, "res" ffd27 e31c word dres ffd29 5d435b83 byte 3+im, "[C]" ffd2d d74e word COMPILES ffd2f 41524784 byte 4+im, "GRAB" ffd34 d636 word GRAB ' FIELDS ( NAME-FIELD CODE-POINTER CODE-FIELD ) ffd36 41464e84 byte 4+im, "NFA'" ffd3b d64c word _NFATICK ffd3d 41504303 byte 3, "CPA" ffd41 d650 word NFACPA ffd43 41464303 byte 3, "CFA" ffd47 d65c word NFACFA ' COMMENTS ffd49 5c81 byte 1+im, "\" ffd4b e10e word COMMENT ffd4d 2d2d2d83 byte 3+im, "---" ffd51 e10e word COMMENT ffd53 2881 byte 1+im, "(" ffd55 e126 word PAREN ffd57 7b81 byte 1+im, "{" ffd59 e140 word BRACE ffd5b 7d81 byte 1+im, "}" ffd5d 0071 word _NOP ' CONDITIONAL COMPILATION ( conditionally ignore as comment ) ffd5f 4e464986 byte 6+im, "IFNDEF" ffd66 e13c word IFNDEF ffd68 44464985 byte 5+im, "IFDEF" ffd6e e134 word IFDEF '' byte 4, "IDLE" '' word IDLE '' byte 4, ".VER" '' word PRTVER ffd70 51415405 byte 5, "TAQOZ" ffd76 e34c word _TAQOZ ffd78 52455404 byte 4, "TERM" ffd7d de8a word TERMINAL ffd7f 54554184 byte 4+im, "AUTO" ffd84 dde8 word AUTORUN ffd86 49505305 byte 5, "SPIRD" ffd8c 0191 word SPIRD ffd8e 49505306 byte 6, "SPIRDL" ffd95 018f word SPIRDL ffd97 49505305 byte 5, "SPIWB" ffd9d 01ac word SPIWR8 ffd9f 49505305 byte 5, "SPICE" ffda5 01b5 word SPICE ffda7 49505305 byte 5, "SPIWC" ffdad 01aa word SPIWRC ffdaf 49505305 byte 5, "SPIWW" ffdb5 01a7 word SPIWR16 ffdb7 49505305 byte 5, "SPIWM" ffdbd 01a4 word SPIWM ffdbf 49505305 byte 5, "SPIWL" ffdc5 01a2 word SPIWRL ffdc7 49505307 byte 7, "SPIPINS" ffdcf eb88 word SPIPINS ffdd1 49505305 byte 5, "SPIRX" ffdd7 0184 word SPIRX ffdd9 49505306 byte 6, "SPITXE" ffde0 0197 word SPITXE ffde2 49505305 byte 5, "SPITX" ffde8 0198 word SPITX { byte 5, "CLKIN" word CLKIN byte 6, "CLKOUT" word CLKOUT byte 5, "CLOCK" word CLOCK } ffdea 4c535705 byte 5, "WSLED" ffdf0 ec98 word WSLED ffdf2 49415704 byte 4, "WAIT" ffdf7 eacc word WAIT ffdf9 4b4c4306 byte 6, "CLKDIV" ffe00 d266 word CLKDIV ffe02 53435206 byte 6, "RCSLOW" ffe09 d272 word RCSLOW ffe0b 42554806 byte 6, "HUBSET" ffe12 ec8c word _HUBSET ffe14 505702 byte 2, "WP" ffe17 d25c word WP ffe19 455702 byte 2, "WE" ffe1c d258 word WE ffe1e 4b4c4305 byte 5, "CLKHZ" ffe24 d22a word CLKHZ '' byte 6, "CLKMHZ" '' word CLKMHZ { byte 7, "BUFFERS" word BUFFERS byte 3, "ROM" word ROM byte 6, "IRQVEC" word IRQVEC byte 4, "PTRA" word w+PTRA byte 4, "PTRB" word w+PTRB byte 4, "DIRA" word w+DIRA byte 4, "DIRB" word w+DIRB byte 4, "OUTA" word w+OUTA byte 4, "OUTB" word w+OUTB byte 3, "INA" word w+INA byte 3, "INB" word w+INB } ffe26 52524505 byte 5, "ERROR" ffe2c e002 word ERROR ffe2e 50465306 byte 6, "SFPINS" ffe35 e3da word SFPINS ffe37 3f465303 byte 3, "SF?" ffe3b e3f8 word SFSTAT ffe3d 57465304 byte 4, "SFWE" ffe42 e3e0 word SFWE ffe44 49465305 byte 5, "SFINS" ffe4a e3e6 word SFINS ffe4c 57465304 byte 4, "SFWD" ffe51 e3f4 word SFWD ffe53 53465305 byte 5, "SFSID" ffe59 e402 word SFSID ffe5b 4a465305 byte 5, "SFJID" ffe61 e412 word SFJID ffe63 45465305 byte 5, "SFER4" ffe69 e426 word SFER4 ffe6b 45465306 byte 6, "SFER32" ffe72 e436 word SFER32 ffe74 45465306 byte 6, "SFER64" ffe7b e43a word SFER64 ffe7d 45465307 byte 7, "SFERASE" ffe85 e43e word SFERALL ffe87 57465306 byte 6, "SFWRPG" ffe8e e444 word SFWRPAGE ffe90 43414206 byte 6, "BACKUP" ffe97 e450 word BACKUP ffe99 53455207 byte 7, "RESTORE" ffea1 e4a0 word RESTORE ffea3 52465305 byte 5, "SFRDS" ffea9 e4be word SFRDS ffeab 57465305 byte 5, "SFWRS" ffeb1 e470 word SFWRS ffeb3 43465304 byte 4, "SFC@" ffeb8 e4c8 word SFCFETCH ffeba 57465304 byte 4, "SFW@" ffebf e4d0 word SFWFETCH ffec1 40465303 byte 3, "SF@" ffec5 e4d6 word SFFETCH ffec7 465302 byte 2, "SF" ffeca e4e2 word SF ffecc 46532e03 byte 3, ".SF" ffed0 e418 word PRTSF ffed2 42445305 byte 5, "SDBUF" ffed8 e4f0 word SDBUF ffeda 70647306 byte 6, "sdpins" ffee1 e4ea word _sdpins ffee3 554f4d05 byte 5, "MOUNT" ffee9 e82a word MOUNT ffeeb 52494403 byte 3, "DIR" ffeef e890 word PRTDIR ffef1 44532103 byte 3, "!SD" ffef5 e63a word INITSD ffef7 58532103 byte 3, "!SX" ffefb e5a8 word INITSX ffefd 3f445303 byte 3, "SD?" fff01 e4f6 word SDQ fff03 444d4303 byte 3, "CMD" fff07 e542 word CMD fff09 4d434104 byte 4, "ACMD" fff0e e53a word ACMD '' byte 3, "csd" '' word csd fff10 64696303 byte 3, "cid" fff14 f814 word w+cid fff16 57445304 byte 4, "SDWR" fff1b e670 word SDWR fff1d 52445305 byte 5, "SDRDS" fff23 e714 word SDRDS fff25 57445305 byte 5, "SDWRS" fff2b e764 word SDWRS fff2d 554c4605 byte 5, "FLUSH" fff33 e69a word FLUSH fff35 504f4605 byte 5, "FOPEN" fff3b e956 word FOPEN fff3d 4f4c4605 byte 5, "FLOAD" fff43 e95e word FLOAD fff45 45474604 byte 4, "FGET" fff4a e96e word FGET fff4c 45524605 byte 5, "FREAD" fff52 e98e word FREAD fff54 52574606 byte 6, "FWRITE" fff5b e9a4 word FWRITE fff5d 43455306 byte 6, "SECTOR" fff64 e6c4 word SECTOR fff66 52445304 byte 4, "SDRD" fff6b e6e4 word SDRD fff6d 52445305 byte 5, "SDRDS" fff73 e714 word SDRDS fff75 41445305 byte 5, "SDADR" fff7b e786 word SDADR fff7d 40445303 byte 3, "SD@" fff81 e794 word SDFETCH fff83 21445303 byte 3, "SD!" fff87 e79a word SDSTORE fff89 43445304 byte 4, "SDC@" fff8e e7a0 word SDCFETCH fff90 43445304 byte 4, "SDC!" fff95 e7a6 word SDCSTORE fff97 57445304 byte 4, "SDW@" fff9c e7ac word SDWFETCH fff9e 445302 byte 2, "SD" fffa1 e7b2 word SD '' byte 5, "RDFAT" '' word RDFAT fffa3 41464004 byte 4, "@FAT" fffa8 e7ba word ATFAT fffaa 4f424005 byte 5, "@BOOT" fffb0 e7d0 word ATBOOT fffb2 4f524005 byte 5, "@ROOT" fffb8 e7cc word ATROOT '' byte 7, "CL>SECT" '' word CLSECT fffba 74616603 byte 3, "fat" fffbe f8b1 word w+fat32 fffc0 444e4503 byte 3, "END" fffc4 e36c word _END fffc6 00000000 long 0 fffca enddict fffca alignl {{ +------------------------------------------------------------------------------------------------------------------------------+ | TERMS OF USE: MIT License | +------------------------------------------------------------------------------------------------------------------------------+ |Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation | |files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, | |modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software| |is furnished to do so, subject to the following conditions: | | | |The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.| | | |THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | |WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | |COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | +------------------------------------------------------------------------------------------------------------------------------+ }}