Imported Upstream version 2.3.1
[debian/as31] / examples / paulmon2.asm
1 ; PAULMON2, a user-friendly 8051 monitor, by Paul Stoffregen\r
2 ; Please email comments, suggestions, bugs to paul@pjrc.com\r
3 \r
4 ; It's free.  PAULMON2 is in the public domain.  You may copy\r
5 ; sections of code from PAULMON2 into your own programs, even\r
6 ; for commercial purposes.  PAULMON2 should only be distributed\r
7 ; free of charge, but may be bundled as 'value-added' with other\r
8 ; products, such as development boards, CDROMs, etc.  Please\r
9 ; distribute the PAULMON2.DOC file and other files, not just\r
10 ; the object code!\r
11 \r
12 ; The PAULMON2.EQU and PAULMON2.HDR files contain valuable\r
13 ; information that could help you to write programs for use\r
14 ; with PAULMON2.\r
15 \r
16 ; PAULMON2 is in the public domain. PAULMON2 is distributed in\r
17 ; the hope that it will be useful, but without any warranty;\r
18 ; without even the implied warranty of merchantability or fitness\r
19 ; for a particular purpose. \r
20 \r
21 \r
22 ; You are probably reading this code to see what it looks like\r
23 ; and possibly learn something, or to modify it for some reason.\r
24 ; Either is ok, but please remember that this code uses a number\r
25 ; of tricks to cram all the functionality into just 4k.  As a\r
26 ; result, the code can be difficult to read, and adding new\r
27 ; features can be very difficult without growing beyond 4k.  To\r
28 ; add or modify commands in PAULMON2, please consider using the\r
29 ; "external command" functionality.  It is easier to develop\r
30 ; new commands this way, and you can distribute them to other\r
31 ; users.  Email paul@pjrc.com if you have new PAULMON2\r
32 ; commands to contribute to others.  Details about adding new\r
33 ; commands to PAULMON2 (with examples) can be found at:\r
34 \r
35 ; http://www.pjrc.com/tech/8051/pm2_docs/addons.html\r
36 \r
37 \r
38 ;---------------------------------------------------------;\r
39 ;                                                         ;\r
40 ;           PAULMON2's default configuration              ;\r
41 ;                                                         ;\r
42 ;---------------------------------------------------------;\r
43 \r
44 ; PAULMON2 should be assembled using the modified AS31 assembler,\r
45 ; originally written by Ken Stauffer, many small changes by Paul\r
46 ; Stoffregen.  This free assembler is available on the web at\r
47 ; http://www.pjrc.com/tech/8051/index.html\r
48 ; As well, these web pages have a fill-out form which makes it\r
49 ; very easy to custom configure PAULMON2.  Using this form will\r
50 ; edit the code for you, run the AS31 assmebler, and send you the\r
51 ; object code to program into your chip.\r
52 \r
53 \r
54 ; These two parameters control where PAULMON2 will be assembled,\r
55 ; and where it will attempt to LJMP at the interrupt vector locations.\r
56 \r
57 .equ    base, 0x0000            ;location for PAULMON2\r
58 .equ    vector, 0x2000          ;location to LJMP interrupt vectors\r
59 \r
60 ; These three parameters tell PAULMON2 where the user's memory is\r
61 ; installed.  "bmem" and "emem" define the space that will be searched\r
62 ; for program headers, user installed commands, start-up programs, etc.\r
63 ; "bmem" and "emem" should be use so they exclude memory areas where\r
64 ; perphreal devices may be mapped, as reading memory from an io chip\r
65 ; may reconfigure it unexpectedly.  If flash rom is used, "bmem" and "emem"\r
66 ; should also include the space where the flash rom is mapped.\r
67 \r
68 .equ    pgm, 0x2000             ;default location for the user program\r
69 .equ    bmem, 0x1000            ;where is the beginning of memory\r
70 .equ    emem, 0xFFFF            ;end of the memory\r
71 \r
72 ; Flash ROM parameters.  If "has_flash" is set to zero, all flash rom\r
73 ; features are turned off, otherwise "bflash" and "eflash" should specify\r
74 ; the memory range which is flash rom.  Though AMD doesn't suggest it,\r
75 ; you may be able to map only a part of the flash rom with your address\r
76 ; decoder logic (and not use the rest), but you should be careful that\r
77 ; "bflash" and "eflash" don't include and memory which is NOT flash rom\r
78 ; so that the erase algorithm won't keep applying erase pulses until it\r
79 ; finally gives up (which will stress the thin oxide and degrade the\r
80 ; flash rom's life and reliability).  "erase_pin" allows you to specify\r
81 ; the bit address for a pin which (if held low) will tell PAULMON2 to\r
82 ; erase the flash rom chip when it starts up.  This is useful if you\r
83 ; download programs with the "start-up" headers on them and the code you've\r
84 ; put in the flash rom crashes!\r
85 \r
86 .equ    has_flash, 0            ;set to non-zero value if flash installed\r
87 .equ    bflash, 0x8000          ;first memory location of Flash ROM\r
88 .equ    eflash, 0xFFFF          ;last memory location of Flash ROM\r
89 .equ    erase_pin, 0            ;00 = disable erase pin feature\r
90 ;.equ   erase_pin, 0xB5         ;B5 = pin 15, P3.5 (T1)\r
91 \r
92 ; Please note... much of the memory management code only looks at the\r
93 ; upper 8 bits of an address, so it's not a good idea to somehow map\r
94 ; your memory chips (with complex address decoding logic) into chunks\r
95 ; less than 256 bytes.  In other words, only using a piece of a flash\r
96 ; rom chip and mapping it between C43A to F91B would confuse PAULMON2\r
97 ; (as well as require quit a bit of address decoding logic circuitry)\r
98 \r
99 \r
100 ; To set the baud rate, use this formula or set to 0 for auto detection\r
101 ; baud_const = 256 - (crystal / (12 * 16 * baud))\r
102 \r
103 .equ    baud_const, 0           ;automatic baud rate detection\r
104 ;.equ   baud_const, 255         ;57600 baud w/ 11.0592 MHz\r
105 ;.equ   baud_const, 253         ;19200 baud w/ 11.0592 MHz\r
106 ;.equ   baud_const, 252         ;19200 baud w/ 14.7456 MHz\r
107 ;.equ   baud_const, 243         ;4808 baud w/ 12 MHz\r
108 \r
109 .equ    line_delay, 6           ;num of char times to pause during uploads\r
110 \r
111 ; About download speed: when writing to ram, PAULMON2 can accept data\r
112 ; at the maximum baud rate (baud_const=255 or 57600 baud w/ 11.0592 MHz).\r
113 ; Most terminal emulation programs introduce intentional delays when\r
114 ; sending ascii data, which you would want to turn off for downloading\r
115 ; larger programs into ram.  For Flash ROM, the maximum speed is set by\r
116 ; the time it takes to program each location... 9600 baud seems to work\r
117 ; nicely for the AMD 28F256 chip.  The "character pacing" delay in a\r
118 ; terminal emulation program should be sufficient to download to flash\r
119 ; rom and any baud rate.  Some flash rom chips can write very quickly,\r
120 ; allowing high speed baud rates, but other chips can not.  You milage\r
121 ; will vary...\r
122 \r
123 \r
124 ; Several people didn't like the key definations in PAULMON1.\r
125 ; Actually, I didn't like 'em either, but I never took the time\r
126 ; to change it.  Eventually I got used to them, but now it's\r
127 ; really easy to change which keys do what in PAULMON2.  You\r
128 ; can guess what to do below, but don't use lowercase.\r
129 \r
130 .equ    help_key, '?'           ;help screen\r
131 .equ    dir_key,  'M'           ;directory\r
132 .equ    run_key,  'R'           ;run program\r
133 .equ    dnld_key, 'D'           ;download\r
134 .equ    upld_key, 'U'           ;upload\r
135 .equ    nloc_key, 'N'           ;new memory location\r
136 .equ    jump_key, 'J'           ;jump to memory location\r
137 .equ    dump_key, 'H'           ;hex dump memory\r
138 .equ    intm_key, 'I'           ;hex dump internal memory\r
139 .equ    edit_key, 'E'           ;edit memory\r
140 .equ    clrm_key, 'C'           ;clear memory\r
141 .equ    erfr_key, 'Z'           ;erase flash rom\r
142 \r
143 ; timing parameters for AMD Flash ROM 28F256.  These parameters\r
144 ; and pretty conservative and they seem to work with crystals\r
145 ; between 6 MHz to 24 MHz... (tested with AMD 28F256 chips only)\r
146 ; unless you know this is a problem, it is probably not a good\r
147 ; idea to fiddle with these.\r
148 \r
149 ;.equ   pgmwait, 10             ;22.1184 MHz crystal assumed\r
150 .equ    pgmwait, 19             ;11.0592 MHz\r
151 .equ    verwait, 5\r
152 ;.equ   erwait1, 40             ;fourty delays @22.1184\r
153 .equ    erwait1, 20             ;twenty delays for 11.0592 MHz\r
154 .equ    erwait2, 229            ;each delay .5 ms @22.1184MHz\r
155 \r
156 \r
157 \r
158 ; These symbols configure paulmon2's internal memory usage.\r
159 ; It is usually not a good idea to change these unless you\r
160 ; know that you really have to.\r
161 \r
162 .equ    psw_init, 0             ;value for psw (which reg bank to use)\r
163 .equ    dnld_parm, 0x10         ;block of 16 bytes for download\r
164 .equ    stack, 0x30             ;location of the stack\r
165 .equ    baud_save, 0x78         ;save baud for warm boot, 4 bytes\r
166 \r
167 ;---------------------------------------------------------;\r
168 ;                                                         ;\r
169 ;                    Interrupt Vectors                    ;\r
170 ;  (and little bits of code crammed in the empty spaces)  ;\r
171 ;                                                         ;\r
172 ;---------------------------------------------------------;\r
173 \r
174         .org    base\r
175         ljmp    poweron         ;reset vector\r
176 \r
177         .org    base+3\r
178         ljmp    vector+3        ;ext int0 vector\r
179 \r
180 r6r7todptr:\r
181         mov     dpl, r6\r
182         mov     dph, r7\r
183         ret\r
184 \r
185         .org    base+11\r
186         ljmp    vector+11       ;timer0 vector\r
187 \r
188 dptrtor6r7:\r
189         mov     r6, dpl\r
190         mov     r7, dph\r
191         ret\r
192 \r
193         .org    base+19\r
194         ljmp    vector+19       ;ext int1 vector\r
195 \r
196 dash:   mov     a, #'-'         ;seems kinda trivial, but each time\r
197         ajmp    cout            ;this appears in code, it takes 4\r
198         nop                     ;bytes, but an acall takes only 2\r
199 \r
200         .org    base+27\r
201         ljmp    vector+27       ;timer1 vector\r
202 \r
203 cout_sp:acall   cout\r
204         ajmp    space\r
205         nop\r
206 \r
207         .org    base+35\r
208         ljmp    vector+35       ;uart vector\r
209 \r
210 dash_sp:acall   dash\r
211         ajmp    space\r
212         nop\r
213 \r
214         .org    base+43\r
215         ljmp    vector+43       ;timer2 vector (8052)\r
216 \r
217 \r
218 ;---------------------------------------------------------;\r
219 ;                                                         ;\r
220 ;       The jump table for user programs to call          ;\r
221 ;             subroutines within PAULMON                  ;\r
222 ;                                                         ;\r
223 ;---------------------------------------------------------;\r
224 \r
225 .org    base+46         ;never change this line!!  Other\r
226                         ;programs depend on these locations\r
227                         ;to access paulmon2 functions\r
228 \r
229         ajmp    phex1           ;2E\r
230         ajmp    cout            ;30\r
231         ajmp    cin             ;32\r
232         ajmp    phex            ;34\r
233         ajmp    phex16          ;36\r
234         ajmp    pstr            ;38\r
235         ajmp    ghex            ;3A\r
236         ajmp    ghex16          ;3C\r
237         ajmp    esc             ;4E\r
238         ajmp    upper           ;40\r
239         ljmp    autobaud        ;42\r
240 pcstr_h:ljmp    pcstr           ;45\r
241         ajmp    newline         ;48\r
242         ljmp    lenstr          ;4A\r
243         ljmp    pint8u          ;4D\r
244         ljmp    pint8           ;50\r
245         ljmp    pint16u         ;53\r
246         ljmp    smart_wr        ;56\r
247         ljmp    prgm            ;59\r
248         ljmp    erall           ;5C\r
249         ljmp    find            ;5F\r
250 cin_filter_h:\r
251         ljmp    cin_filter      ;62\r
252         ajmp    asc2hex         ;64\r
253 \r
254 \r
255 ;---------------------------------------------------------;\r
256 ;                                                         ;\r
257 ;              Subroutines for serial I/O                 ;\r
258 ;                                                         ;\r
259 ;---------------------------------------------------------;\r
260 \r
261 \r
262 cin:    jnb     ri, cin\r
263         clr     ri\r
264         mov     a, sbuf\r
265         ret\r
266 \r
267 dspace: acall   space\r
268 space:  mov     a, #' '\r
269 cout:   jnb     ti, cout\r
270         clr     ti              ;clr ti before the mov to sbuf!\r
271         mov     sbuf, a\r
272         ret\r
273 \r
274 ;clearing ti before reading sbuf takes care of the case where\r
275 ;interrupts may be enabled... if an interrupt were to happen\r
276 ;between those two instructions, the serial port will just\r
277 ;wait a while, but in the other order and the character could\r
278 ;finish transmitting (during the interrupt routine) and then\r
279 ;ti would be cleared and never set again by the hardware, causing\r
280 ;the next call to cout to hang forever!\r
281 \r
282 newline2:                       ;print two newlines\r
283         acall   newline\r
284 newline:push    acc             ;print one newline\r
285         mov     a, #13\r
286         acall   cout\r
287         mov     a, #10\r
288         acall   cout\r
289         pop     acc\r
290         ret\r
291 \r
292         ;get 2 digit hex number from serial port\r
293         ; c = set if ESC pressed, clear otherwise\r
294         ; psw.5 = set if return w/ no input, clear otherwise\r
295 ghex:\r
296 ghex8:  clr     psw.5\r
297 ghex8c:\r
298         acall   cin_filter_h    ;get first digit\r
299         acall   upper\r
300         cjne    a, #27, ghex8f\r
301 ghex8d: setb    c\r
302         clr     a\r
303         ret\r
304 ghex8f: cjne    a, #13, ghex8h\r
305         setb    psw.5\r
306         clr     c\r
307         clr     a\r
308         ret\r
309 ghex8h: mov     r2, a\r
310         acall   asc2hex\r
311         jc      ghex8c\r
312         xch     a, r2           ;r2 will hold hex value of 1st digit\r
313         acall   cout\r
314 ghex8j:\r
315         acall   cin_filter_h    ;get second digit\r
316         acall   upper\r
317         cjne    a, #27, ghex8k\r
318         sjmp    ghex8d\r
319 ghex8k: cjne    a, #13, ghex8m\r
320         mov     a, r2\r
321         clr     c\r
322         ret\r
323 ghex8m: cjne    a, #8, ghex8p\r
324 ghex8n: acall   cout\r
325         sjmp    ghex8c\r
326 ghex8p: cjne    a, #21, ghex8q\r
327         sjmp    ghex8n\r
328 ghex8q: mov     r3, a\r
329         acall   asc2hex\r
330         jc      ghex8j\r
331         xch     a, r3\r
332         acall   cout\r
333         mov     a, r2\r
334         swap    a\r
335         orl     a, r3\r
336         clr     c\r
337         ret\r
338 \r
339 \r
340 \r
341 \r
342         ;carry set if esc pressed\r
343         ;psw.5 set if return pressed w/ no input\r
344 ghex16:\r
345         mov     r2, #0          ;start out with 0\r
346         mov     r3, #0\r
347         mov     r4, #4          ;number of digits left\r
348         clr     psw.5\r
349 \r
350 ghex16c:\r
351         acall   cin_filter_h\r
352         acall   upper\r
353         cjne    a, #27, ghex16d\r
354         setb    c               ;handle esc key\r
355         clr     a\r
356         mov     dph, a\r
357         mov     dpl, a\r
358         ret\r
359 ghex16d:cjne    a, #8, ghex16f\r
360         sjmp    ghex16k\r
361 ghex16f:cjne    a, #127, ghex16g  ;handle backspace\r
362 ghex16k:cjne    r4, #4, ghex16e   ;have they entered anything yet?\r
363         sjmp    ghex16c\r
364 ghex16e:acall   cout\r
365         acall   ghex16y\r
366         inc     r4\r
367         sjmp    ghex16c\r
368 ghex16g:cjne    a, #13, ghex16i   ;return key\r
369         mov     dph, r3\r
370         mov     dpl, r2\r
371         cjne    r4, #4, ghex16h\r
372         clr     a\r
373         mov     dph, a\r
374         mov     dpl, a\r
375         setb    psw.5\r
376 ghex16h:clr     c\r
377         ret\r
378 ghex16i:mov     r5, a             ;keep copy of original keystroke\r
379         acall   asc2hex\r
380         jc      ghex16c\r
381         xch     a, r5\r
382         lcall   cout\r
383         mov     a, r5\r
384         push    acc\r
385         acall   ghex16x\r
386         pop     acc\r
387         add     a, r2\r
388         mov     r2, a\r
389         clr     a\r
390         addc    a, r3\r
391         mov     r3, a\r
392         djnz    r4, ghex16c\r
393         clr     c\r
394         mov     dpl, r2\r
395         mov     dph, r3\r
396         ret\r
397 \r
398 ghex16x:  ;multiply r3-r2 by 16 (shift left by 4)\r
399         mov     a, r3\r
400         swap    a\r
401         anl     a, #11110000b\r
402         mov     r3, a\r
403         mov     a, r2\r
404         swap    a\r
405         anl     a, #00001111b\r
406         orl     a, r3\r
407         mov     r3, a\r
408         mov     a, r2\r
409         swap    a\r
410         anl     a, #11110000b\r
411         mov     r2, a\r
412         ret\r
413 \r
414 ghex16y:  ;divide r3-r2 by 16 (shift right by 4)\r
415         mov     a, r2\r
416         swap    a\r
417         anl     a, #00001111b\r
418         mov     r2, a\r
419         mov     a, r3\r
420         swap    a\r
421         anl     a, #11110000b\r
422         orl     a, r2\r
423         mov     r2, a\r
424         mov     a, r3\r
425         swap    a\r
426         anl     a, #00001111b\r
427         mov     r3, a\r
428         ret\r
429 \r
430 \r
431         ;carry set if invalid input\r
432 asc2hex:\r
433         clr     c\r
434         add     a, #208\r
435         jnc     hex_not\r
436         add     a, #246\r
437         jc      hex_maybe\r
438         add     a, #10\r
439         clr     c\r
440         ret\r
441 hex_maybe:\r
442         add     a, #249\r
443         jnc     hex_not\r
444         add     a, #250\r
445         jc      hex_not\r
446         add     a, #16\r
447         clr     c\r
448         ret\r
449 hex_not:setb    c\r
450         ret\r
451 \r
452 \r
453 \r
454 phex:\r
455 phex8:\r
456         push    acc\r
457         swap    a\r
458         anl     a, #15\r
459         add     a, #246\r
460         jnc     phex_b\r
461         add     a, #7\r
462 phex_b: add     a, #58\r
463         acall   cout\r
464         pop     acc\r
465 phex1:  push    acc\r
466         anl     a, #15\r
467         add     a, #246\r
468         jnc     phex_c\r
469         add     a, #7\r
470 phex_c: add     a, #58\r
471         acall   cout\r
472         pop     acc\r
473         ret\r
474 \r
475 \r
476 phex16:\r
477         push    acc\r
478         mov     a, dph\r
479         acall   phex\r
480         mov     a, dpl\r
481         acall   phex\r
482         pop     acc\r
483         ret\r
484 \r
485 \r
486 ;a not so well documented feature of pstr is that you can print\r
487 ;multiple consecutive strings without needing to reload dptr\r
488 ;(which takes 3 bytes of code!)... this is useful for inserting\r
489 ;numbers or spaces between strings.\r
490 \r
491 pstr:   push    acc\r
492 pstr1:  clr     a\r
493         movc    a, @a+dptr\r
494         inc     dptr\r
495         jz      pstr2\r
496         mov     c, acc.7\r
497         anl     a, #0x7F\r
498         acall   cout\r
499         jc      pstr2\r
500         sjmp    pstr1\r
501 pstr2:  pop     acc\r
502         ret\r
503 \r
504 \r
505 upper:  ;converts the ascii code in Acc to uppercase, if it is lowercase\r
506         push    acc\r
507         clr     c\r
508         subb    a, #97\r
509         jc      upper2          ;is it a lowercase character\r
510         subb    a, #26\r
511         jnc     upper2\r
512         pop     acc\r
513         add     a, #224         ;convert to uppercase\r
514         ret\r
515 upper2: pop     acc             ;don't change anything\r
516         ret\r
517 \r
518 \r
519 lenstr: mov     r0, #0    ;returns length of a string in r0\r
520         push    acc\r
521 lenstr1:clr     a\r
522         movc    a,@a+dptr\r
523         jz      lenstr2\r
524         mov     c,acc.7\r
525         inc     r0\r
526         Jc      lenstr2\r
527         inc     dptr\r
528         sjmp    lenstr1\r
529 lenstr2:pop     acc\r
530         ret\r
531 \r
532 \r
533 esc:  ;checks to see if <ESC> is waiting on serial port\r
534       ;C=clear if no <ESC>, C=set if <ESC> pressed\r
535       ;buffer is flushed\r
536         push    acc\r
537         clr     c\r
538         jnb     ri,esc2\r
539         mov     a,sbuf\r
540         cjne    a,#27,esc1\r
541         setb    c\r
542 esc1:   clr     ri\r
543 esc2:   pop     acc\r
544         ret\r
545 \r
546 \r
547 ;---------------------------------------------------------;\r
548 ;                                                         ;\r
549 ;    The 'high-level' stuff to interact with the user     ;\r
550 ;                                                         ;\r
551 ;---------------------------------------------------------;\r
552 \r
553 \r
554 menu: ;first we print out the prompt, which isn't as simple\r
555       ;as it may seem, since external code can add to the\r
556       ;prompt, so we've got to find and execute all of 'em.\r
557         mov     dptr, #prompt1    ;give 'em the first part of prompt\r
558         acall   pcstr_h\r
559         mov     a, r7\r
560         acall   phex\r
561         mov     a, r6\r
562         acall   phex\r
563         ;mov     dptr, #prompt2\r
564         acall   pstr\r
565 \r
566 ;now we're finally past the prompt, so let's get some input\r
567         acall   cin_filter_h    ;get the input, finally\r
568         acall   upper\r
569 \r
570 ;push return address onto stack so we can just jump to the program\r
571         mov     b, #(menu & 255)  ;we push the return address now,\r
572         push    b                 ;to save code later...\r
573         mov     b, #(menu >> 8)   ;if bogus input, just ret for\r
574         push    b                 ;another prompt.\r
575 \r
576 \r
577 \r
578 ;first we'll look through memory for a program header that says\r
579 ;it's a user installed command which matches what the user pressed\r
580 \r
581 ;user installed commands need to avoid changing R6/R7, which holds\r
582 ;the memory pointer.  The stack pointer can't be changed obviously.\r
583 ;all the other general purpose registers should be available for\r
584 ;user commands to alter as they wish.\r
585 \r
586 menux:  mov     b, a            ;now search for external commands...\r
587         mov     dptr, #bmem\r
588 menux1: acall   find\r
589         jnc     menuxend           ;searched all the commands?\r
590         mov     dpl, #4\r
591         clr     a\r
592         movc    a,@a+dptr\r
593         cjne    a, #254, menux2  ;only FE is an ext command\r
594         inc     dpl\r
595         clr     a\r
596         movc    a,@a+dptr\r
597         cjne    a, b, menux2      ;only run if they want it\r
598         acall   space\r
599         mov     dpl, #32\r
600         acall   pstr               ;print command name\r
601         acall   newline\r
602         mov     dpl, #64\r
603         clr     a\r
604         jmp     @a+dptr         ;take a leap of faith and jump to it!\r
605 menux2: inc     dph\r
606         mov     a, dph\r
607         cjne    a, #((emem+1) >> 8) & 255, menux1\r
608 menuxend:\r
609         mov     a, b\r
610 \r
611 \r
612 ;since we didn't find a user installed command, use the builtin ones\r
613 \r
614 menu1a: cjne    a, #help_key, menu1b\r
615         mov     dptr, #help_cmd2\r
616         acall   pcstr_h\r
617         ajmp    help\r
618 menu1b: cjne    a, #dir_key, menu1c\r
619         mov     dptr, #dir_cmd\r
620         acall   pcstr_h\r
621         ajmp    dir\r
622 menu1c: cjne    a, #run_key, menu1d\r
623         mov     dptr, #run_cmd\r
624         acall   pcstr_h\r
625         ajmp    run\r
626 menu1d: cjne    a, #dnld_key, menu1e\r
627         mov     dptr, #dnld_cmd\r
628         acall   pcstr_h\r
629         ajmp    dnld\r
630 menu1e: cjne    a, #upld_key, menu1f\r
631         mov     dptr, #upld_cmd\r
632         acall   pcstr_h\r
633         ajmp    upld\r
634 menu1f: cjne    a, #nloc_key, menu1g\r
635         mov     dptr, #nloc_cmd\r
636         acall   pcstr_h\r
637         ajmp    nloc\r
638 menu1g: cjne    a, #jump_key, menu1h\r
639         mov     dptr, #jump_cmd\r
640         acall   pcstr_h\r
641         ajmp    jump\r
642 menu1h: cjne    a, #dump_key, menu1i\r
643         mov     dptr, #dump_cmd\r
644         acall   pcstr_h\r
645         ajmp    dump\r
646 menu1i: cjne    a, #edit_key, menu1j\r
647         mov     dptr, #edit_cmd\r
648         acall   pcstr_h\r
649         ajmp    edit\r
650 menu1j: cjne    a, #clrm_key, menu1k\r
651         mov     dptr, #clrm_cmd\r
652         acall   pcstr_h\r
653         ajmp    clrm\r
654 menu1k: cjne    a, #erfr_key, menu1l\r
655         mov     a, #has_flash\r
656         jz      menu_end\r
657         mov     dptr, #erfr_cmd\r
658         acall   pcstr_h\r
659         ajmp    erfr\r
660 menu1l: cjne    a, #intm_key, menu1m\r
661         mov     dptr, #intm_cmd\r
662         acall   pcstr_h\r
663         ljmp    intm\r
664 menu1m:\r
665 \r
666     ;invalid input, no commands to run...\r
667 menu_end:                       ;at this point, we have not found\r
668         ajmp    newline         ;anything to run, so we give up.\r
669                                 ;remember, we pushed menu, so newline\r
670                                 ;will just return to menu.\r
671 \r
672 ;..........................................................\r
673 \r
674 ;---------------------------------------------------------;\r
675 \r
676 ;dnlds1 = "Begin sending Intel HEX format file <ESC> to abort"\r
677 ;dnlds2 = "Download aborted"\r
678 ;dnlds3 = "Download completed"\r
679 \r
680 \r
681 ;16 byte parameter table: (eight 16 bit values)\r
682 ;  *   0 = lines received\r
683 ;  *   1 = bytes received\r
684 ;  *   2 = bytes written\r
685 ;  *   3 = bytes unable to write\r
686 ;  *   4 = incorrect checksums\r
687 ;  *   5 = unexpected begin of line\r
688 ;  *   6 = unexpected hex digits (while waiting for bol)\r
689 ;  *   7 = unexpected non-hex digits (in middle of a line)\r
690 \r
691 dnld:\r
692         mov     dptr, #dnlds1            \r
693         acall   pcstr_h            ;"begin sending file <ESC> to abort"\r
694         mov     r0, #dnld_parm\r
695         mov     r2, #16\r
696 dnld0:  mov     @r0, #0         ;initialize all parameters to 0\r
697         inc     r0\r
698         djnz    r2, dnld0\r
699 \r
700           ;look for begining of line marker ':'\r
701 dnld1:  acall   cin\r
702         cjne    a, #27, dnld2   ;Test for escape\r
703         sjmp    dnld_esc\r
704 dnld2:  cjne    a, #':', dnld2b\r
705         mov     r1, #0\r
706         acall   dnld_inc\r
707         sjmp    dnld3\r
708 dnld2b:   ;check to see if it's a hex digit, error if it is\r
709         acall   asc2hex\r
710         jc      dnld1\r
711         mov     r1, #6\r
712         acall   dnld_inc\r
713         sjmp    dnld1\r
714           ;begin taking in the line of data\r
715 dnld3:  mov     a, #'.'\r
716         acall   cout\r
717         mov     r4, #0          ;r4 will count up checksum\r
718         acall   dnld_ghex\r
719         mov     r0, a           ;R0 = # of data bytes\r
720         acall   dnld_ghex\r
721         mov     dph, a          ;High byte of load address\r
722         acall   dnld_ghex\r
723         mov     dpl, a          ;Low byte of load address\r
724         acall   dnld_ghex       ;Record type\r
725         cjne    a, #1, dnld4    ;End record?\r
726         sjmp    dnld_end\r
727 dnld4:  jnz     dnld_unknown    ;is it a unknown record type???\r
728 dnld5:  mov     a, r0\r
729         jz      dnld_get_cksum\r
730         acall   dnld_ghex       ;Get data byte\r
731         mov     r2, a\r
732         mov     r1, #1\r
733         acall   dnld_inc        ;count total data bytes received\r
734         mov     a, r2\r
735         lcall   smart_wr        ;c=1 if an error writing\r
736         clr     a\r
737         addc    a, #2\r
738         mov     r1, a\r
739 ;     2 = bytes written\r
740 ;     3 = bytes unable to write\r
741         acall   dnld_inc\r
742         inc     dptr\r
743         djnz    r0, dnld5\r
744 dnld_get_cksum:\r
745         acall   dnld_ghex       ;get checksum\r
746         mov     a, r4\r
747         jz      dnld1           ;should always add to zero\r
748 dnld_sumerr:\r
749         mov     r1, #4\r
750         acall   dnld_inc        ;all we can do it count # of cksum errors\r
751         sjmp    dnld1\r
752 \r
753 dnld_unknown:   ;handle unknown line type\r
754         mov     a, r0\r
755         jz      dnld_get_cksum  ;skip data if size is zero\r
756 dnld_ukn2:\r
757         acall   dnld_ghex       ;consume all of unknown data\r
758         djnz    r0, dnld_ukn2\r
759         sjmp    dnld_get_cksum\r
760 \r
761 dnld_end:   ;handles the proper end-of-download marker\r
762         mov     a, r0\r
763         jz      dnld_end_3      ;should usually be zero\r
764 dnld_end_2:\r
765         acall   dnld_ghex       ;consume all of useless data\r
766         djnz    r0, dnld_ukn2\r
767 dnld_end_3:\r
768         acall   dnld_ghex       ;get the last checksum\r
769         mov     a, r4\r
770         jnz     dnld_sumerr\r
771         acall   dnld_dly\r
772         mov     dptr, #dnlds3\r
773         acall   pcstr_h            ;"download went ok..."\r
774         ;consume any cr or lf character that may have been\r
775         ;on the end of the last line\r
776         jnb     ri, dnld_sum\r
777         acall   cin\r
778         sjmp    dnld_sum\r
779 \r
780 \r
781 \r
782 dnld_esc:   ;handle esc received in the download stream\r
783         acall   dnld_dly\r
784         mov     dptr, #dnlds2    \r
785         acall   pcstr_h            ;"download aborted."\r
786         sjmp    dnld_sum\r
787 \r
788 dnld_dly:   ;a short delay since most terminal emulation programs\r
789             ;won't be ready to receive anything immediately after\r
790             ;they've transmitted a file... even on a fast Pentium(tm)\r
791             ;machine with 16550 uarts!\r
792         mov     r0, #0\r
793 dnlddly2:mov    r1, #0\r
794         djnz    r1, *           ;roughly 128k cycles, appox 0.1 sec\r
795         djnz    r0, dnlddly2\r
796         ret\r
797 \r
798 dnld_inc:     ;increment parameter specified by R1\r
799               ;note, values in Acc and R1 are destroyed\r
800         mov     a, r1\r
801         anl     a, #00000111b   ;just in case\r
802         rl      a\r
803         add     a, #dnld_parm\r
804         mov     r1, a           ;now r1 points to lsb\r
805         inc     @r1\r
806         mov     a, @r1\r
807         jnz     dnldin2\r
808         inc     r1\r
809         inc     @r1\r
810 dnldin2:ret\r
811 \r
812 dnld_gp:     ;get parameter, and inc to next one (@r1)\r
813              ;carry clear if parameter is zero.\r
814              ;16 bit value returned in dptr\r
815         setb    c\r
816         mov     dpl, @r1\r
817         inc     r1\r
818         mov     dph, @r1\r
819         inc     r1\r
820         mov     a, dpl\r
821         jnz     dnldgp2\r
822         mov     a, dph\r
823         jnz     dnldgp2\r
824         clr     c\r
825 dnldgp2:ret\r
826 \r
827 \r
828 \r
829 ;a spacial version of ghex just for the download.  Does not\r
830 ;look for carriage return or backspace.  Handles ESC key by\r
831 ;poping the return address (I know, nasty, but it saves many\r
832 ;bytes of code in this 4k ROM) and then jumps to the esc\r
833 ;key handling.  This ghex doesn't echo characters, and if it\r
834 ;sees ':', it pops the return and jumps to an error handler\r
835 ;for ':' in the middle of a line.  Non-hex digits also jump\r
836 ;to error handlers, depending on which digit.\r
837           \r
838 dnld_ghex:\r
839 dnldgh1:acall   cin\r
840         acall   upper\r
841         cjne    a, #27, dnldgh3\r
842 dnldgh2:pop     acc\r
843         pop     acc\r
844         sjmp    dnld_esc\r
845 dnldgh3:cjne    a, #':', dnldgh5\r
846 dnldgh4:mov     r1, #5          ;handle unexpected beginning of line\r
847         acall   dnld_inc\r
848         pop     acc\r
849         pop     acc\r
850         ajmp    dnld3           ;and now we're on a new line!\r
851 dnldgh5:acall   asc2hex\r
852         jnc     dnldgh6\r
853         mov     r1, #7\r
854         acall   dnld_inc\r
855         sjmp    dnldgh1\r
856 dnldgh6:mov     r2, a           ;keep first digit in r2\r
857 dnldgh7:acall   cin\r
858         acall   upper\r
859         cjne    a, #27, dnldgh8\r
860         sjmp    dnldgh2\r
861 dnldgh8:cjne    a, #':', dnldgh9\r
862         sjmp    dnldgh4\r
863 dnldgh9:acall   asc2hex\r
864         jnc     dnldghA\r
865         mov     r1, #7\r
866         acall   dnld_inc\r
867         sjmp    dnldgh7\r
868 dnldghA:xch     a, r2\r
869         swap    a\r
870         orl     a, r2\r
871         mov     r2, a\r
872         add     a, r4           ;add into checksum\r
873         mov     r4, a\r
874         mov     a, r2           ;return value in acc\r
875         ret\r
876 \r
877 ;dnlds4 =  "Summary:"\r
878 ;dnlds5 =  " lines received"\r
879 ;dnlds6a = " bytes received"\r
880 ;dnlds6b = " bytes written"\r
881 \r
882 dnld_sum:    ;print out download summary\r
883         mov     a, r6\r
884         push    acc\r
885         mov     a, r7\r
886         push    acc\r
887         mov     dptr, #dnlds4\r
888         acall   pcstr_h\r
889         mov     r1, #dnld_parm\r
890         mov     r6, #dnlds5 & 255\r
891         mov     r7, #dnlds5 >> 8\r
892         acall   dnld_i0\r
893         mov     r6, #dnlds6a & 255\r
894         mov     r7, #dnlds6a >> 8\r
895         acall   dnld_i0\r
896         mov     r6, #dnlds6b & 255\r
897         mov     r7, #dnlds6b >> 8\r
898         acall   dnld_i0\r
899 \r
900 dnld_err:    ;now print out error summary\r
901         mov     r2, #5\r
902 dnlder2:acall   dnld_gp\r
903         jc      dnlder3         ;any errors?\r
904         djnz    r2, dnlder2\r
905          ;no errors, so we print the nice message\r
906         mov     dptr, #dnlds13\r
907         acall   pcstr_h\r
908         sjmp    dlnd_sum_done\r
909 \r
910 dnlder3:  ;there were errors, so now we print 'em\r
911         mov     dptr, #dnlds7\r
912         acall   pcstr_h\r
913           ;but let's not be nasty... only print if necessary\r
914         mov     r1, #(dnld_parm+6)\r
915         mov     r6, #dnlds8 & 255\r
916         mov     r7, #dnlds8 >> 8\r
917         acall   dnld_item\r
918         mov     r6, #dnlds9 & 255\r
919         mov     r7, #dnlds9 >> 8\r
920         acall   dnld_item\r
921         mov     r6, #dnlds10 & 255\r
922         mov     r7, #dnlds10 >> 8\r
923         acall   dnld_item\r
924         mov     r6, #dnlds11 & 255\r
925         mov     r7, #dnlds11 >> 8\r
926         acall   dnld_item\r
927         mov     r6, #dnlds12 & 255\r
928         mov     r7, #dnlds12 >> 8\r
929         acall   dnld_item\r
930 dlnd_sum_done:\r
931         pop     acc\r
932         mov     r7, a\r
933         pop     acc\r
934         mov     r6, a\r
935         ajmp    newline\r
936 \r
937 dnld_item:\r
938         acall   dnld_gp         ;error conditions\r
939         jnc     dnld_i3\r
940 dnld_i2:acall   space\r
941         lcall   pint16u\r
942         acall   r6r7todptr\r
943         acall   pcstr_h\r
944 dnld_i3:ret\r
945 \r
946 dnld_i0:acall   dnld_gp         ;non-error conditions\r
947         sjmp    dnld_i2\r
948 \r
949 \r
950 ;dnlds7:  = "Errors:"\r
951 ;dnlds8:  = " bytes unable to write"\r
952 ;dnlds9:  = " incorrect checksums"\r
953 ;dnlds10: = " unexpected begin of line"\r
954 ;dnlds11: = " unexpected hex digits"\r
955 ;dnlds12: = " unexpected non-hex digits"\r
956 ;dnlds13: = "No errors detected"\r
957 \r
958 \r
959 \r
960 ;---------------------------------------------------------;\r
961 \r
962 \r
963 jump:\r
964         mov     dptr, #prompt8\r
965         acall   pcstr_h\r
966         acall   r6r7todptr\r
967         acall   phex16\r
968         mov     dptr, #prompt4\r
969         acall   pcstr_h\r
970         acall   ghex16\r
971         jb      psw.5, jump3\r
972         jnc     jump2\r
973         ajmp    abort2\r
974 jump2:\r
975         acall   dptrtor6r7\r
976 jump3:  acall   newline\r
977         mov     dptr, #runs1\r
978         acall   pcstr_h\r
979         acall   r6r7todptr\r
980 \r
981 jump_doit:  ;jump to user code @dptr (this used by run command also)\r
982         clr     a\r
983         mov     psw, a\r
984         mov     b, a\r
985         mov     r0, a\r
986         mov     r1, a\r
987         mov     r2, a\r
988         mov     r3, a\r
989         mov     r4, a\r
990         mov     r5, a\r
991         mov     r6, a\r
992         mov     r7, a\r
993         mov     sp, #8          ;start w/ sp=7, like a real reset\r
994         push    acc             ;unlike a real reset, push 0000\r
995         push    acc             ;in case they end with a RET\r
996         jmp     @a+dptr\r
997 \r
998 \r
999 ;---------------------------------------------------------;\r
1000 \r
1001 dump:   \r
1002         mov     r2, #16         ;number of lines to print\r
1003         acall   newline2\r
1004 dump1:  acall   r6r7todptr\r
1005         acall   phex16          ;tell 'em the memory location\r
1006         mov     a,#':'\r
1007         acall   cout_sp\r
1008         mov     r3, #16         ;r3 counts # of bytes to print\r
1009         acall   r6r7todptr\r
1010 dump2:  clr     a\r
1011         movc    a, @a+dptr\r
1012         inc     dptr\r
1013         acall   phex            ;print each byte in hex\r
1014         acall   space\r
1015         djnz    r3, dump2\r
1016         acall   dspace          ;print a couple extra space\r
1017         mov     r3, #16\r
1018         acall   r6r7todptr\r
1019 dump3:  clr     a\r
1020         movc    a, @a+dptr\r
1021         inc     dptr\r
1022         anl     a, #01111111b   ;avoid unprintable characters\r
1023         cjne    a, #127, dump3b\r
1024         clr     a               ;avoid 127/255 (delete/rubout) char\r
1025 dump3b: add     a, #224\r
1026         jc      dump4\r
1027         clr     a               ;avoid control characters\r
1028 dump4:  add     a, #32\r
1029         acall   cout\r
1030         djnz    r3, dump3\r
1031         acall   newline\r
1032         acall   line_dly\r
1033         acall   dptrtor6r7\r
1034         acall   esc\r
1035         jc      dump5\r
1036         djnz    r2, dump1       ;loop back up to print next line\r
1037 dump5:  ajmp    newline\r
1038 \r
1039 ;---------------------------------------------------------;\r
1040 \r
1041 edit:      ;edit external ram...\r
1042         mov     dptr, #edits1\r
1043         acall   pcstr_h\r
1044         acall   r6r7todptr\r
1045 edit1:  acall   phex16\r
1046         mov     a,#':'\r
1047         acall   cout_sp\r
1048         mov     a,#'('\r
1049         acall   cout\r
1050         acall   dptrtor6r7\r
1051         clr     a\r
1052         movc    a, @a+dptr\r
1053         acall   phex\r
1054         mov     dptr,#prompt10\r
1055         acall   pcstr_h\r
1056         acall   ghex\r
1057         jb      psw.5,edit2\r
1058         jc      edit2\r
1059         acall   r6r7todptr\r
1060         lcall   smart_wr\r
1061         acall   newline\r
1062         acall   r6r7todptr\r
1063         inc     dptr\r
1064         acall   dptrtor6r7\r
1065         ajmp    edit1\r
1066 edit2:  mov     dptr,#edits2\r
1067         ajmp    pcstr_h\r
1068 \r
1069 ;---------------------------------------------------------;\r
1070 \r
1071 dir:\r
1072         mov     dptr, #prompt9\r
1073         acall   pcstr_h\r
1074         mov     r0, #21\r
1075 dir0a:  acall   space\r
1076         djnz    r0, dir0a\r
1077         ;mov    dptr, #prompt9b\r
1078         acall   pcstr_h\r
1079 \r
1080         mov     dph, #(bmem >> 8)\r
1081 dir1:   acall   find            ;find the next program in memory\r
1082         jc      dir2\r
1083 dir_end:ajmp    newline         ;we're done if no more found\r
1084 dir2:\r
1085         acall   dspace\r
1086         mov     dpl, #32        ;print its name\r
1087         acall   pstr\r
1088         mov     dpl, #32        ;how long is the name\r
1089         acall   lenstr\r
1090         mov     a, #33\r
1091         clr     c\r
1092         subb    a, r0\r
1093         mov     r0, a\r
1094         mov     a, #' '         ;print the right # of spaces\r
1095 dir3:   acall   cout\r
1096         djnz    r0, dir3\r
1097         mov     dpl, #0\r
1098         acall   phex16          ;print the memory location\r
1099         mov     r0, #6\r
1100         mov     a, #' '\r
1101 dir4:   acall   cout\r
1102         djnz    r0, dir4\r
1103         mov     dpl, #4         ;now figure out what type it is\r
1104         clr     a\r
1105         movc    a, @a+dptr\r
1106         mov     r2, dph         ;save this, we're inside a search\r
1107 \r
1108 dir5:   cjne    a, #254, dir5b\r
1109         mov     dptr, #type1    ;it's an external command\r
1110         sjmp    dir7\r
1111 dir5b:  cjne    a, #253, dir5c\r
1112 dir5bb: mov     dptr, #type4    ;it's a startup routine\r
1113         sjmp    dir7\r
1114 dir5c:  cjne    a, #35, dir5d\r
1115         mov     dptr, #type2    ;it's an ordinary program\r
1116         sjmp    dir7\r
1117 dir5d:  cjne    a, #249, dir5e\r
1118         sjmp    dir5bb\r
1119 dir5e:\r
1120 dir6:   mov     dptr, #type5    ;who knows what the hell it is\r
1121 \r
1122 dir7:   acall   pcstr_h            ;print out the type\r
1123         mov     dph, r2         ;go back and find the next one\r
1124         acall   newline\r
1125         mov     a, #(emem >> 8)\r
1126         cjne    a, dph, dir8    ;did we just print the last one?\r
1127         ajmp    dir_end\r
1128 dir8:   inc     dph\r
1129         mov     a, dph\r
1130         cjne    a, #((emem+1) >> 8) & 255, dir1\r
1131         ajmp    dir_end\r
1132 \r
1133 \r
1134 ;type1=Ext Command\r
1135 ;type4=Startup\r
1136 ;type2=Program\r
1137 ;type5=???\r
1138 \r
1139 ;---------------------------------------------------------;\r
1140 \r
1141 \r
1142 run:   \r
1143         acall   newline2\r
1144         mov     r2, #255        ;first print the menu, count items\r
1145         mov     dptr, #bmem\r
1146         dec     dph\r
1147 run2:   inc     dph\r
1148         mov     a, dph\r
1149         cjne    a, #((emem+1) >> 8) & 255, run2b\r
1150         sjmp    run3\r
1151 run2b:  acall   find\r
1152         jnc     run3            ;have we found 'em all??\r
1153         mov     dpl, #4\r
1154         clr     a\r
1155         movc    a, @a+dptr\r
1156         orl     a, #00000011b\r
1157         cpl     a\r
1158         jz      run2            ;this one doesn't run... find next\r
1159         acall   dspace\r
1160         inc     r2\r
1161         mov     a, #'A'         ;print the key to press\r
1162         add     a, r2\r
1163         acall   cout_sp\r
1164         acall   dash_sp\r
1165         mov     dpl, #32\r
1166         acall   pstr            ;and the command name\r
1167         acall   newline\r
1168         ajmp    run2            ;and continue doing this\r
1169 run3:   cjne    r2, #255, run4  ;are there any to run??\r
1170         mov     dptr, #prompt5\r
1171         ajmp    pcstr_h\r
1172 run4:   mov     dptr, #prompt3  ;ask the big question!\r
1173         acall   pcstr_h\r
1174         mov     a, #'A'\r
1175         acall   cout\r
1176         acall   dash\r
1177         mov     a, #'A'         ;such user friendliness...\r
1178         add     a, r2           ;even tell 'em the choices\r
1179         acall   cout\r
1180         mov     dptr, #prompt4\r
1181         acall   pcstr_h\r
1182         acall   cin_filter_h\r
1183         cjne    a, #27, run4aa  ;they they hit <ESC>\r
1184         ajmp    newline\r
1185 run4aa: mov     r3, a\r
1186         mov     a, #31\r
1187         clr     c\r
1188         subb    a, r2\r
1189         mov     a, r3\r
1190         jc      run4a\r
1191         acall   upper\r
1192 run4a:  acall   cout\r
1193         mov     r3, a\r
1194         acall   newline\r
1195         ;check to see if it's under 32, if so convert to uppercase\r
1196         mov     a, r3\r
1197         clr     c\r
1198         subb    a, #'A'\r
1199         jc      run4            ;if they typed less than 'A'\r
1200         mov     r3, a           ;R3 has the number they typed\r
1201         mov     a, r2           ;A=R2 has the maximum number\r
1202         clr     c\r
1203         subb    a, r3\r
1204         jc      run4            ;if they typed over the max\r
1205         inc     r3\r
1206         mov     dptr, #bmem\r
1207         dec     dph\r
1208 run5:   inc     dph\r
1209         mov     a, dph\r
1210         cjne    a, #((emem+1) >> 8) & 255, run5b\r
1211         sjmp    run8\r
1212 run5b:  acall   find\r
1213         jnc     run8            ;Shouldn't ever do this jump!\r
1214         mov     dpl, #4\r
1215         clr     a\r
1216         movc    a, @a+dptr\r
1217         orl     a, #00000011b\r
1218         cpl     a\r
1219         jz      run5            ;this one doesn't run... find next\r
1220         djnz    r3, run5        ;count til we find the one they want\r
1221         acall   newline\r
1222         mov     dpl, #64\r
1223         ajmp    jump_doit\r
1224 run8:   ret\r
1225 \r
1226 ;---------------------------------------------------------;\r
1227 \r
1228 help:\r
1229         mov     dptr, #help1txt\r
1230         acall   pcstr_h\r
1231         mov     r4, #help_key\r
1232         mov     dptr, #help_cmd\r
1233         acall   help2\r
1234         mov     r4, #dir_key\r
1235         ;mov     dptr, #dir_cmd\r
1236         acall   help2\r
1237         mov     r4, #run_key\r
1238         ;mov     dptr, #run_cmd\r
1239         acall   help2\r
1240         mov     r4, #dnld_key\r
1241         ;mov     dptr, #dnld_cmd\r
1242         acall   help2\r
1243         mov     r4, #upld_key\r
1244         ;mov     dptr, #upld_cmd\r
1245         acall   help2\r
1246         mov     r4, #nloc_key\r
1247         ;mov     dptr, #nloc_cmd\r
1248         acall   help2\r
1249         mov     r4, #jump_key\r
1250         ;mov     dptr, #jump_cmd\r
1251         acall   help2\r
1252         mov     r4, #dump_key\r
1253         ;mov     dptr, #dump_cmd\r
1254         acall   help2\r
1255         mov     r4, #intm_key\r
1256         ;mov    dptr, #intm_cmd\r
1257         acall   help2\r
1258         mov     r4, #edit_key\r
1259         ;mov     dptr, #edit_cmd\r
1260         acall   help2\r
1261         mov     r4, #clrm_key\r
1262         ;mov     dptr, #clrm_cmd\r
1263         acall   help2\r
1264         mov     a, #has_flash\r
1265         jz      help_skerfm\r
1266         mov     r4, #erfr_key\r
1267         ;mov     dptr, #erfr_cmd\r
1268         acall   help2\r
1269 help_skerfm:\r
1270         mov     dptr, #help2txt\r
1271         acall   pcstr_h\r
1272         mov     dptr, #bmem\r
1273 help3:  acall   find\r
1274         jnc     help4\r
1275         mov     dpl, #4\r
1276         clr     a\r
1277         movc    a,@a+dptr\r
1278         cjne    a, #254, help3a    ;only FE is an ext command\r
1279         acall   dspace\r
1280         inc     dpl\r
1281         clr     a\r
1282         movc    a,@a+dptr\r
1283         acall   cout\r
1284         acall   dash_sp\r
1285         mov     dpl, #32\r
1286         acall   pstr\r
1287         acall   newline\r
1288 help3a: inc     dph\r
1289         mov     a, dph\r
1290         cjne    a, #((emem+1) >> 8) & 255, help3\r
1291 help4:  \r
1292         ajmp    newline\r
1293 \r
1294 help2:                          ;print 11 standard lines\r
1295         acall   dspace          ;given key in R4 and name in dptr\r
1296         mov     a, r4\r
1297         acall   cout\r
1298         acall   dash_sp\r
1299         acall   pcstr_h\r
1300         ajmp    newline\r
1301 \r
1302 ;---------------------------------------------------------;\r
1303 \r
1304 upld:\r
1305 \r
1306         acall   get_mem\r
1307         ;assume we've got the beginning address in r3/r2\r
1308         ;and the final address in r5/r4 (r4=lsb)...\r
1309 \r
1310         ;print out what we'll be doing\r
1311         mov     dptr, #uplds3\r
1312         acall   pcstr_h\r
1313         mov     a, r3\r
1314         acall   phex\r
1315         mov     a, r2\r
1316         acall   phex\r
1317         ;mov     dptr, #uplds4\r
1318         acall   pcstr_h\r
1319         mov     a, r5\r
1320         acall   phex\r
1321         mov     a, r4\r
1322         acall   phex\r
1323         acall   newline\r
1324 \r
1325         ;need to adjust end location by 1...\r
1326         mov     dph, r5\r
1327         mov     dpl, r4\r
1328         inc     dptr\r
1329         mov     r4, dpl\r
1330         mov     r5, dph\r
1331 \r
1332         mov     dptr, #prompt7\r
1333         acall   pcstr_h\r
1334         acall   cin\r
1335         cjne    a, #27, upld2e\r
1336         ajmp    abort_it\r
1337 upld2e: acall   newline\r
1338         mov     dpl, r2\r
1339         mov     dph, r3\r
1340 \r
1341 upld3:  mov     a, r4           ;how many more bytes to output??\r
1342         clr     c\r
1343         subb    a, dpl\r
1344         mov     r2, a\r
1345         mov     a, r5\r
1346         subb    a, dph\r
1347         jnz     upld4           ;if >256 left, then do next 16\r
1348         mov     a, r2\r
1349         jz      upld7           ;if we're all done\r
1350         anl     a, #11110000b\r
1351         jnz     upld4           ;if >= 16 left, then do next 16\r
1352         sjmp    upld5           ;otherwise just finish it off\r
1353 upld4:  mov     r2, #16\r
1354 upld5:  mov     a, #':'         ;begin the line\r
1355         acall   cout\r
1356         mov     a, r2\r
1357         acall   phex            ;output # of data bytes\r
1358         acall   phex16          ;output memory location\r
1359         mov     a, dph\r
1360         add     a, dpl\r
1361         add     a, r2\r
1362         mov     r3, a           ;r3 will become checksum\r
1363         clr     a\r
1364         acall   phex            ;output 00 code for data\r
1365 upld6:  clr     a\r
1366         movc    a, @a+dptr\r
1367         acall   phex            ;output each byte\r
1368         add     a, r3\r
1369         mov     r3, a\r
1370         inc     dptr\r
1371         djnz    r2, upld6       ;do however many bytes we need\r
1372         mov     a, r3\r
1373         cpl     a\r
1374         inc     a\r
1375         acall   phex            ;and finally the checksum\r
1376         acall   newline\r
1377         acall   line_dly\r
1378         acall   esc\r
1379         jnc     upld3           ;keep working if no esc pressed\r
1380         sjmp    abort_it\r
1381 upld7:  mov     a, #':'\r
1382         acall   cout\r
1383         clr     a\r
1384         acall   phex\r
1385         acall   phex\r
1386         acall   phex\r
1387         inc     a\r
1388         acall   phex\r
1389         mov     a, #255\r
1390         acall   phex\r
1391 upld8:  ajmp    newline2\r
1392 \r
1393 \r
1394 line_dly: ;a brief delay between line while uploading, so the\r
1395         ;receiving host can be slow (i.e. most windows software)\r
1396         mov     a, r0\r
1397         push    acc\r
1398         mov     r0, #line_delay*2\r
1399 line_d2:mov     a, th0          ;get baud rate const\r
1400 line_d3:inc     a\r
1401         nop\r
1402         nop\r
1403         jnz     line_d3\r
1404         djnz    r0, line_d2\r
1405         pop     acc\r
1406         mov     r0, a\r
1407         ret\r
1408 \r
1409 ;---------------------------------------------------------;\r
1410 \r
1411 get_mem:     ;this thing gets the begin and end locations for\r
1412              ;a few commands.  If an esc or enter w/ no input,\r
1413              ;it pops it's own return and returns to the menu\r
1414              ;(nasty programming, but we need tight code for 4k rom)\r
1415         acall   newline2\r
1416         mov     dptr, #beg_str\r
1417         acall   pcstr_h\r
1418         acall   ghex16\r
1419         jc      pop_it\r
1420         jb      psw.5, pop_it\r
1421         push    dph\r
1422         push    dpl\r
1423         acall   newline\r
1424         mov     dptr, #end_str\r
1425         acall   pcstr_h\r
1426         acall   ghex16\r
1427         mov     r5, dph\r
1428         mov     r4, dpl\r
1429         pop     acc\r
1430         mov     r2, a\r
1431         pop     acc\r
1432         mov     r3, a\r
1433         jc      pop_it\r
1434         jb      psw.5, pop_it\r
1435         ajmp    newline\r
1436 \r
1437 pop_it: pop     acc\r
1438         pop     acc\r
1439 abort_it:\r
1440         acall   newline\r
1441 abort2: mov     dptr, #abort\r
1442         ajmp    pcstr_h\r
1443 \r
1444 \r
1445 clrm:\r
1446         acall   get_mem\r
1447         mov     dptr, #sure\r
1448         acall   pcstr_h\r
1449         acall   cin_filter_h\r
1450         acall   upper\r
1451         cjne    a, #'Y', abort_it\r
1452         acall   newline2\r
1453      ;now we actually do it\r
1454 \r
1455 clrm2:  mov     dph, r3\r
1456         mov     dpl, r2\r
1457 clrm3:  clr     a\r
1458         lcall   smart_wr\r
1459         mov     a, r5\r
1460         cjne    a, dph, clrm4\r
1461         mov     a, r4\r
1462         cjne    a, dpl, clrm4\r
1463         ret\r
1464 clrm4:  inc     dptr\r
1465         sjmp    clrm3\r
1466 \r
1467 ;---------------------------------------------------------;\r
1468 \r
1469 nloc:\r
1470         mov     dptr, #prompt6\r
1471         acall   pcstr_h\r
1472         acall   ghex16\r
1473         jc      abort2\r
1474         jb      psw.5, abort2\r
1475         acall   dptrtor6r7\r
1476         ajmp    newline2\r
1477 \r
1478 ;---------------------------------------------------------;\r
1479 \r
1480 erfr:\r
1481         acall   newline2\r
1482         mov     dptr, #erfr_cmd\r
1483         acall   pcstr_h\r
1484         mov     a, #','\r
1485         acall   cout_sp\r
1486         mov     dptr, #sure\r
1487         acall   pcstr_h\r
1488         acall   cin_filter_h\r
1489         acall   upper\r
1490         cjne    a, #'Y', abort_it\r
1491         acall   newline2\r
1492         lcall   erall\r
1493         mov     dptr, #erfr_ok\r
1494         jnc     erfr_end\r
1495         mov     dptr, #erfr_err\r
1496 erfr_end:\r
1497         ajmp    pcstr_h\r
1498 \r
1499 \r
1500 \r
1501 ;---------------------------------------------------------;\r
1502 \r
1503 intm:   acall   newline\r
1504         mov     r0, #0\r
1505 intm2:  acall   newline\r
1506         cjne    r0, #0x80, intm3 \r
1507         ajmp    newline\r
1508 intm3:  mov     a, r0\r
1509         acall   phex\r
1510         mov     a, #':'\r
1511         acall   cout\r
1512 intm4:  acall   space\r
1513         mov     a, @r0\r
1514         acall   phex\r
1515         inc     r0\r
1516         mov     a, r0\r
1517         anl     a, #00001111b\r
1518         jnz     intm4\r
1519         sjmp    intm2\r
1520 \r
1521 \r
1522 \r
1523 \r
1524 \r
1525 ;**************************************************************\r
1526 ;**************************************************************\r
1527 ;*****                                                    *****\r
1528 ;*****       2k page boundry is somewhere near here       *****\r
1529 ;*****         (no ajmp or acall past this point)         *****\r
1530 ;*****                                                    *****\r
1531 ;**************************************************************\r
1532 ;**************************************************************\r
1533 \r
1534 \r
1535 \r
1536 ;---------------------------------------------------------;\r
1537 ;                                                         ;\r
1538 ;   Subroutines for memory managment and non-serial I/O   ;\r
1539 ;                                                         ;\r
1540 ;---------------------------------------------------------;\r
1541 \r
1542 \r
1543 ;finds the next header in the external memory.\r
1544 ;  Input DPTR=point to start search (only MSB used)\r
1545 ;  Output DPTR=location of next module\r
1546 ;    C=set if a header found, C=clear if no more headers\r
1547 find:   mov     dpl, #0\r
1548         clr     a\r
1549         movc    a, @a+dptr\r
1550         cjne    a, #0xA5, find3\r
1551         inc     dptr\r
1552         clr     a\r
1553         movc    a, @a+dptr\r
1554         cjne    a, #0xE5, find3\r
1555         inc     dptr\r
1556         clr     a\r
1557         movc    a, @a+dptr\r
1558         cjne    a, #0xE0, find3\r
1559         inc     dptr\r
1560         clr     a\r
1561         movc    a, @a+dptr\r
1562         cjne    a, #0xA5, find3\r
1563         mov     dpl, #0                 ;found one here!\r
1564         setb    c\r
1565         ret\r
1566 find3:  mov     a, #(emem >> 8)\r
1567         cjne    a, dph, find4           ;did we just check the end\r
1568         clr     c\r
1569         ret\r
1570 find4:  inc     dph                     ;keep on searching\r
1571         sjmp    find\r
1572 \r
1573 \r
1574 \r
1575 ;routine that erases the whole flash rom!  C=1 if failure, C=0 if ok\r
1576 \r
1577 erall:  mov     a, #has_flash\r
1578         jz      erallno\r
1579         mov     dptr, #bflash           ;is it already erased ??\r
1580 erall0: clr     a\r
1581         movc    a, @a+dptr\r
1582         cpl     a\r
1583         jnz     erall_b                 ;do actual erase if any byte not 255\r
1584         inc     dptr\r
1585         mov     a, #((eflash+1) & 255)\r
1586         cjne    a, dpl, erall0\r
1587         mov     a, #(((eflash+1) >> 8) & 255)\r
1588         cjne    a, dph, erall0\r
1589         ;if we get here, the entire chip was already erased,\r
1590         ;so there is no need to do anything\r
1591         clr     c\r
1592         ret\r
1593 erall_b:\r
1594         mov     dptr, #bflash           ;first program to all 00's\r
1595 erall1: clr     a\r
1596         movc    a, @a+dptr\r
1597         jz      erall2                  ;don't waste time!\r
1598         clr     a\r
1599         lcall   prgm                    ;ok, program this byte\r
1600         ;if the program operation failed... we should abort because\r
1601         ;they are all likely to fail and it will take a long time...\r
1602         ;which give the appearance that the program has crashed,\r
1603         ;when it's really following the flash rom algorithm\r
1604         ;correctly and getting timeouts.\r
1605         jc      erallno\r
1606         ;mov    a, #'.'\r
1607         ;lcall  cout\r
1608 erall2: inc     dptr\r
1609         mov     a, #((eflash+1) & 255)\r
1610         cjne    a, dpl, erall1\r
1611         mov     a, #(((eflash+1) >> 8) & 255)\r
1612         cjne    a, dph, erall1          ;after this it's all 00's\r
1613         mov     dptr, #bflash           ;beginning address\r
1614         mov     r4, #232                ;max # of trials, lsb\r
1615         mov     r5, #4                  ;max # of trials, msb-1\r
1616 erall3: \r
1617         ;mov    a, #'#'\r
1618         ;lcall  cout\r
1619         djnz    r4, erall3a\r
1620         djnz    r5, erall3a\r
1621 erallno:setb    c\r
1622         ret                             ;if it didn't work!\r
1623 erall3a:mov     a, #0x20\r
1624         mov     c, ea            ;-     ;turn off all interrupts!!\r
1625         mov     psw.1, c\r
1626         clr     ea\r
1627         movx    @dptr, a                ;send the erase setup\r
1628         movx    @dptr, a                ;and begin the erase\r
1629         mov     r3, #erwait1\r
1630 erwt:   mov     r2, #erwait2            ;now wait 10ms...\r
1631         djnz    r2, *\r
1632         djnz    r3, erwt\r
1633 erall4: mov     a, #0xA0\r
1634         movx    @dptr, a                ;send erase verify\r
1635         mov     r2, #verwait            ;wait for 6us\r
1636         djnz    r2, *\r
1637         clr     a\r
1638         movc    a, @a+dptr\r
1639         mov     c, psw.1\r
1640         mov     ea, c           ;-     ;turn interrupts back on\r
1641         cpl     a\r
1642         jnz     erall3                  ;erase again if not FF\r
1643         inc     dptr\r
1644         mov     a, #(((eflash+1) >> 8) & 255)  ;verify whole array\r
1645         cjne    a, dph, erall4\r
1646         mov     a, #((eflash+1) & 255)\r
1647         cjne    a, dpl, erall4\r
1648         mov     a, #255\r
1649         mov     dptr, #bflash\r
1650         movx    @dptr, a                ;reset the flash rom\r
1651         clr     a\r
1652         movx    @dptr, a                ;and go back to read mode\r
1653         clr     c\r
1654         ret\r
1655 \r
1656 \r
1657 \r
1658 \r
1659 ;a routine that writes ACC to into flash memory at DPTR\r
1660 ; assumes that Vpp is active and stable already.\r
1661 ; C is set if error occurs, C is clear if it worked\r
1662 \r
1663 prgm:   mov     b, a\r
1664         mov     a, r2\r
1665         push    acc\r
1666         mov     a, r3\r
1667         push    acc\r
1668         mov     r2, #25        ;try to program 25 times if needed\r
1669 prgm2:  mov     a, #40h\r
1670         mov     c, ea            ;-     ;turn off all interrupts!!\r
1671         mov     psw.1, c\r
1672         clr     ea\r
1673         movx    @dptr, a        ;send setup programming command\r
1674         mov     a, b\r
1675         movx    @dptr, a        ;write to the cell\r
1676         mov     r3, #pgmwait    ;now wait for 10us\r
1677         djnz    r3, *\r
1678         mov     a, #0xC0\r
1679         movx    @dptr, a        ;send program verify command\r
1680         mov     r3, #verwait    ;wait 6us while it adds margin\r
1681         djnz    r3, *\r
1682         clr     a\r
1683         movc    a, @a+dptr\r
1684         mov     c, psw.1\r
1685         mov     ea, c           ;-     ;turn interrupts back on\r
1686         clr     c\r
1687         subb    a, b\r
1688         jz      prgmok          ;note, C is still clear is ACC=0\r
1689         djnz    r2, prgm2\r
1690 prgmbad:setb    c               ;it gets here if programming failure\r
1691 prgmok: clr     a\r
1692         movx    @dptr, a        ;and go back into read mode\r
1693         pop     acc\r
1694         mov     r3, a\r
1695         pop     acc\r
1696         mov     r2, a\r
1697         mov     a, b            ;restore ACC to original value\r
1698         ret\r
1699 \r
1700 \r
1701 \r
1702 ;************************************\r
1703 ;To make PAULMON2 able to write to other\r
1704 ;types of memory than RAM and flash rom,\r
1705 ;modify this "smart_wr" routine.  This\r
1706 ;code doesn't accept any inputs other\r
1707 ;that the address (dptr) and value (acc),\r
1708 ;so this routine must know which types\r
1709 ;of memory are in what address ranges\r
1710 ;************************************\r
1711 \r
1712 \r
1713 ;Write to Flash ROM or ordinary RAM.  Carry bit will indicate\r
1714 ;if the value was successfully written, C=1 if not written.\r
1715 \r
1716 \r
1717 smart_wr:\r
1718         push    acc\r
1719         push    b\r
1720         mov     b, a\r
1721         ;do we even have a flash rom?\r
1722         mov     a, #has_flash\r
1723         jz      wr_ram\r
1724         ;there is a flash rom, but is this address in it?\r
1725         mov     a, dph\r
1726         cjne    a, #(eflash >> 8), isfl3\r
1727         sjmp    wr_flash\r
1728 isfl3:  jnc     wr_ram\r
1729         cjne    a, #(bflash >> 8), isfl4\r
1730         sjmp    wr_flash\r
1731 isfl4:  jnc     wr_flash\r
1732         sjmp    wr_ram\r
1733 \r
1734 wr_flash:\r
1735         mov     a, b\r
1736         acall   prgm\r
1737         pop     b\r
1738         pop     acc\r
1739         ret\r
1740 \r
1741 wr_ram: mov     a, b\r
1742         movx    @dptr, a        ;write the value to memory\r
1743         clr     a\r
1744         movc    a, @a+dptr      ;read it back from code memory\r
1745         clr     c\r
1746         subb    a, b\r
1747         jz      smwrok\r
1748         movx    a, @dptr        ;read it back from data memory\r
1749         clr     c\r
1750         subb    a, b\r
1751         jz      smwrok\r
1752 smwrbad:setb    c\r
1753         sjmp    smwrxit\r
1754 smwrok: clr     c\r
1755 smwrxit:pop     b\r
1756         pop     acc\r
1757         ret\r
1758 \r
1759 \r
1760 \r
1761 \r
1762 ;---------------------------------------------------------;\r
1763 ;                                                         ;\r
1764 ;       Power-On initialization code and such...          ;\r
1765 ;                                                         ;\r
1766 ;---------------------------------------------------------;\r
1767 \r
1768 ;first the hardware has to get initialized.\r
1769 \r
1770 intr_return:\r
1771         reti\r
1772 \r
1773 poweron:\r
1774         clr     a\r
1775         mov     ie, a           ;all interrupts off\r
1776         mov     ip, a\r
1777         mov     psw, #psw_init\r
1778         ;clear any interrupt status, just in case the user put\r
1779         ;"ljmp 0" inside their interrupt service code.\r
1780         acall   intr_return\r
1781         acall   intr_return\r
1782         cpl     a\r
1783         mov     p0, a\r
1784         mov     p1, a\r
1785         mov     p2, a\r
1786         mov     p3, a\r
1787         mov     sp, #stack\r
1788 \r
1789 ;Before we start doing any I/O, a short delay is required so\r
1790 ;that any external hardware which may be in "reset mode" can\r
1791 ;initialize.  This is typically a problem when a 82C55 chip\r
1792 ;is used and its reset line is driven from the R-C reset\r
1793 ;circuit used for the 8051.  Because the 82C55 reset pin\r
1794 ;switches from zero to one at a higher voltage than the 8051,\r
1795 ;any 82C55 chips would still be in reset mode right now...\r
1796 \r
1797 rst_dly:\r
1798         mov     r1, #200        ;approx 100000 cycles\r
1799 rdly2:  mov     r2, #249        ;500 cycles\r
1800         djnz    r2, *\r
1801         djnz    r1, rdly2\r
1802 \r
1803 ;Check for the Erase-on-startup signal and erase Flash ROM \r
1804 ;if it's there.\r
1805 \r
1806         mov     a, #has_flash\r
1807         jz      skip_erase\r
1808         mov     a, #erase_pin\r
1809         jz      skip_erase\r
1810         mov     r0, #250        ;check it 250 times, just to be sure\r
1811 chk_erase:\r
1812         mov     c, erase_pin\r
1813         mov     r1, #200\r
1814         djnz    r1, *           ;short delay\r
1815         jc      skip_erase      ;skip erase if this bit is not low\r
1816         djnz    r0, chk_erase\r
1817         lcall   erall           ;and this'll delete the flash rom\r
1818 skip_erase:\r
1819 \r
1820 ;run any user initialization programs in external memory\r
1821         mov     b, #249\r
1822         acall   stcode\r
1823 \r
1824 ;initialize the serial port, auto baud detect if necessary\r
1825         acall   autobaud        ;set up the serial port\r
1826         ;mov    a, th1\r
1827         ;lcall  phex\r
1828 \r
1829 ;run the start-up programs in external memory.\r
1830         mov     b, #253\r
1831         acall   stcode\r
1832 \r
1833 ;now print out the nice welcome message\r
1834 \r
1835 welcome:\r
1836         mov     r0, #24\r
1837 welcm2: lcall   newline\r
1838         djnz    r0, welcm2\r
1839         mov     r0, #15\r
1840         mov     a, #' '\r
1841 welcm4: lcall   cout\r
1842         djnz    r0, welcm4\r
1843         mov     dptr, #logon1\r
1844         lcall   pcstr\r
1845         mov     dptr, #logon2\r
1846         lcall   pcstr\r
1847         lcall   dir\r
1848         mov     r6, #(pgm & 255)\r
1849         mov     r7, #(pgm >> 8)\r
1850         ljmp    menu\r
1851 \r
1852 \r
1853 stcode: mov     dptr, #bmem      ;search for startup routines\r
1854 stcode2:lcall   find\r
1855         jnc     stcode5\r
1856         mov     dpl, #4\r
1857         clr     a\r
1858         movc    a, @a+dptr\r
1859         cjne    a, b, stcode4   ;only startup code if matches B\r
1860         push    b\r
1861         push    dph\r
1862         mov     a, #(stcode3 & 255)\r
1863         push    acc\r
1864         mov     a, #(stcode3 >> 8)\r
1865         push    acc\r
1866         mov     dpl, #64\r
1867         clr     a\r
1868         jmp     @a+dptr         ;jump to the startup code\r
1869 stcode3:pop     dph             ;hopefully it'll return to here\r
1870         pop     b\r
1871 stcode4:inc     dph\r
1872         mov     a, dph\r
1873         cjne    a, #((emem+1) >> 8) & 255, stcode2\r
1874 stcode5:ret                     ;now we've executed all of 'em\r
1875 \r
1876 \r
1877 ;to do automatic baud rate detection, we assume the user will\r
1878 ;press the carriage return, which will cause this bit pattern\r
1879 ;to appear on port 3 pin 0 (CR = ascii code 13, assume 8N1 format)\r
1880 ;\r
1881 ;              0 1 0 1 1 0 0 0 0 1\r
1882 ;              | |             | |\r
1883 ; start bit----+ +--lsb   msb--+ +----stop bit\r
1884 ;\r
1885 ;we'll start timer #1 in 16 bit mode at the transition between the\r
1886 ;start bit and the LSB and stop it between the MBS and stop bit.\r
1887 ;That will give approx the number of cpu cycles for 8 bits.  Divide\r
1888 ;by 8 for one bit and by 16 since the built-in UART takes 16 timer\r
1889 ;overflows for each bit.  We need to be careful about roundoff during\r
1890 ;division and the result has to be inverted since timer #1 counts up.  Of\r
1891 ;course, timer #1 gets used in 8-bit auto reload mode for generating the\r
1892 ;built-in UART's baud rate once we know what the reload value should be.\r
1893 \r
1894 \r
1895 autobaud:\r
1896         mov     a, #baud_const  ;skip if user supplied baud rate constant\r
1897         jnz     autoend_jmp\r
1898         mov     a, baud_save+3  ;is there a value from a previous boot?\r
1899         xrl     baud_save+2, #01010101b\r
1900         xrl     baud_save+1, #11001100b\r
1901         xrl     baud_save+0, #00011101b\r
1902         cjne    a, baud_save+2, autob1\r
1903         cjne    a, baud_save+1, autob1\r
1904         cjne    a, baud_save+0, autob1\r
1905 autoend_jmp:\r
1906         ajmp    autoend\r
1907 \r
1908 autob1: ;wait for inactivity\r
1909 \r
1910         mov     pcon, #0x80     ;configure uart, fast baud\r
1911         mov     scon, #0x42     ;configure uart, but receive disabled\r
1912         mov     tmod, #0x11     ;get timers ready for action (16 bit mode)\r
1913         clr     a\r
1914         mov     tcon, a\r
1915         mov     tl0, a\r
1916         mov     th0, a\r
1917         mov     tl1, a\r
1918         mov     th1, a\r
1919 \r
1920         ;make sure there is no activity on the line\r
1921         ;before we actually begin looking for the carriage return\r
1922         mov     r0, #200\r
1923 autob1b:mov     r1, #30\r
1924 autob1c:jnb     p3.0, autob1\r
1925         djnz    r1, autob1c\r
1926         djnz    r0, autob1b\r
1927 \r
1928 autob2: ;look for the bits of the carriage return\r
1929         jb      p3.0, autob2    ;wait for start bit\r
1930         jb      p3.0, autob2\r
1931         jb      p3.0, autob2    ;  check it a few more times to make\r
1932         jb      p3.0, autob2    ;  sure we don't trigger on some noise\r
1933         jb      p3.0, autob2\r
1934 autob2b:jnb     p3.0, autob2b   ;wait for bit #0 to begin\r
1935         setb    tr1             ;and now we're timing it\r
1936 autob2c:jb      tf1, autob1     ;check for timeout while waiting\r
1937         jb      p3.0, autob2c   ;wait for bit #1 to begin\r
1938 autob2d:jb      tf1, autob1     ;check for timeout while waiting\r
1939         jnb     p3.0, autob2d   ;wait for bit #2 to begin\r
1940 autob2e:jb      tf1, autob1     ;check for timeout while waiting\r
1941         jb      p3.0, autob2e   ;wait for bit #4 to begin\r
1942         setb    tr0             ;start timing last 4 bits\r
1943 autob2f:jb      tf1, autob1     ;check for timeout while waiting\r
1944         jnb     p3.0, autob2f   ;wait for stop bit to begin\r
1945         clr     tr1             ;stop timing (both timers)\r
1946         clr     tr0\r
1947 \r
1948         jb      tf1, autob1     ;check for timeout one last time\r
1949 \r
1950         ;compute the baud rate based on timer1\r
1951         mov     a, tl1\r
1952         rlc     a\r
1953         mov     b, a\r
1954         mov     a, th1\r
1955         rlc     a\r
1956         jc      autob1          ;error if timer0 > 32767\r
1957         mov     c, b.7\r
1958         addc    a, #0\r
1959         cpl     a\r
1960         inc     a               ;now a has the value to load into th1\r
1961         jz      autob1          ;error if baud rate too fast\r
1962 \r
1963         ;after we get the carriage return, we need to make sure there\r
1964         ;isn't any "crap" on the serial line, as there is in the case\r
1965         ;were we get the letter E (and conclude the wrong baud rate).\r
1966         ;unfortunately the simple approach of just looking at the line\r
1967         ;for silence doesn't work, because we have to accept the case\r
1968         ;where the user's terminal emulation is configured to send a\r
1969         ;line feed after the carriage return.  The best thing to do is\r
1970         ;use the uart and look see if it receives anything\r
1971 \r
1972 autob3: mov     th1, a          ;config timer1\r
1973         mov     tl1, #255       ;start asap!\r
1974         mov     tmod, #0x21     ;autoreload mode\r
1975         setb    ren             ;turn on the uart\r
1976         setb    tr1             ;turn on timer1 for its clock\r
1977 \r
1978         mov     a, th1\r
1979         cpl     a\r
1980         inc     a\r
1981         mov     r1, a\r
1982 autob3b:mov     r0, #255\r
1983 autob3c:djnz    r0, autob3c\r
1984         djnz    r1, autob3b\r
1985 \r
1986         jnb     ri, autob4\r
1987         ;if we got here, there was some stuff after the carriage\r
1988         ;return, so we'll read it and see if it was the line feed\r
1989         clr     ri\r
1990         mov     a, sbuf\r
1991         anl     a, #01111111b\r
1992         add     a, #246\r
1993         jz      autob4          ;ok if 0A, the line feed character\r
1994         add     a, #5\r
1995         jz      autob4          ;of if 05, since we may have missed start bit\r
1996 autob1_jmp:\r
1997         ljmp    autob1\r
1998 autob4:\r
1999         ;compute the baud rate based on timer0, check against timer1 value\r
2000         mov     a, tl0\r
2001         rlc     a\r
2002         mov     r0, a\r
2003         mov     a, th0\r
2004         rlc     a\r
2005         mov     r1, a\r
2006         jc      autob1_jmp      ;error if timer0 > 32767\r
2007         mov     a, r0\r
2008         rlc     a\r
2009         mov     b, a\r
2010         mov     a, r1\r
2011         rlc     a\r
2012         mov     c, b.7\r
2013         addc    a, #0\r
2014         jz      autob1_jmp      ;error if baud too fast!\r
2015         cpl     a\r
2016         inc     a\r
2017         cjne    a, th1, autob1_jmp\r
2018         ;acc has th1 value at this point\r
2019 \r
2020 autoend:mov     baud_save+3, a\r
2021         mov     baud_save+2, a  ;store the baud rate for next warm boot.\r
2022         mov     baud_save+1, a\r
2023         mov     baud_save+0, a\r
2024         xrl     baud_save+2, #01010101b\r
2025         xrl     baud_save+1, #11001100b \r
2026         xrl     baud_save+0, #00011101b \r
2027         mov     th1, a\r
2028         mov     tl1, a\r
2029         mov     tmod, #0x21     ;set timer #1 for 8 bit auto-reload\r
2030         mov     pcon, #0x80     ;configure built-in uart\r
2031         mov     scon, #0x52\r
2032         setb    tr1             ;start the baud rate timer\r
2033         ret\r
2034 \r
2035 \r
2036 \r
2037 ;---------------------------------------------------------;\r
2038 ;                                                         ;\r
2039 ;     More subroutines, but less frequent used, so        ;\r
2040 ;     they're down here in the second 2k page.            ;\r
2041 ;                                                         ;\r
2042 ;---------------------------------------------------------;\r
2043 \r
2044 \r
2045 \r
2046 ;this twisted bit of code looks for escape sequences for\r
2047 ;up, down, left, right, pageup, and pagedown, as well\r
2048 ;as ordinary escape and ordinary characters.  Escape\r
2049 ;sequences are required to arrive with each character\r
2050 ;nearly back-to-back to the others, otherwise the characters\r
2051 ;are treated as ordinary user keystroaks.  cin_filter\r
2052 ;returns a single byte when it sees the multi-byte escape\r
2053 ;sequence, as shown here.\r
2054 \r
2055 ; return value   key          escape sequence\r
2056 ;   11 (^K)      up           1B 5B 41\r
2057 ;   10 (^J)      down         1B 5B 42\r
2058 ;   21 (^U)      right        1B 5B 43\r
2059 ;    8 (^H)      left         1B 5B 44\r
2060 ;   25 (^Y)      page up      1B 5B 35 7E\r
2061 ;   26 (^Z)      page down    1B 5B 36 7E\r
2062 \r
2063 .equ    esc_char, 27\r
2064 \r
2065 cin_filter:\r
2066         jnb     ri, cinf1\r
2067         lcall   cin\r
2068         cjne    a, #esc_char, cinf_end\r
2069         ;if esc was already in sbuf, just ignore it\r
2070 cinf1:  lcall   cin\r
2071         cjne    a, #esc_char, cinf_end\r
2072 cinf2:  acall   cinf_wait\r
2073         jb      ri, cinf4\r
2074         mov     a, #esc_char\r
2075         ret                     ;an ordinary ESC\r
2076 \r
2077 cinf4:  ;if we get here, it's a control code, since a character\r
2078         ;was received shortly after receiving an ESC character\r
2079         lcall   cin\r
2080         cjne    a, #'[', cinf_consume\r
2081         acall   cinf_wait\r
2082         jnb     ri, cin_filter\r
2083         lcall   cin\r
2084 cinf5a: cjne    a, #'A', cinf5b\r
2085         mov     a, #11\r
2086         ret\r
2087 cinf5b: cjne    a, #'B', cinf5c\r
2088         mov     a, #10\r
2089         ret\r
2090 cinf5c: cjne    a, #'C', cinf5d\r
2091         mov     a, #21\r
2092         ret\r
2093 cinf5d: cjne    a, #'D', cinf5e\r
2094         mov     a, #8\r
2095         ret\r
2096 cinf5e: cjne    a, #0x35, cinf5f\r
2097         sjmp    cinf8\r
2098 cinf5f: cjne    a, #0x36, cinf5g\r
2099         sjmp    cinf8\r
2100 cinf5g: sjmp    cinf_consume            ;unknown escape sequence\r
2101 \r
2102 cinf8:  ;when we get here, we've got the sequence for pageup/pagedown\r
2103         ;but there's one more incoming byte to check...\r
2104         push    acc\r
2105         acall   cinf_wait\r
2106         jnb     ri, cinf_restart\r
2107         lcall   cin\r
2108         cjne    a, #0x7E, cinf_notpg\r
2109         pop     acc\r
2110         add     a, #228\r
2111 cinf_end: ret\r
2112 cinf_restart:\r
2113         pop     acc\r
2114         sjmp    cin_filter\r
2115 cinf_notpg:\r
2116         pop     acc\r
2117 ;unrecognized escape... eat up everything that's left coming in\r
2118 ;quickly, then begin looking again\r
2119 cinf_consume:\r
2120         acall   cinf_wait\r
2121         jnb     ri, cin_filter\r
2122         lcall   cin\r
2123         cjne    a, #esc_char, cinf_consume\r
2124         sjmp    cinf2\r
2125 \r
2126 ;this thing waits for a character to be received for approx\r
2127 ;4 character transmit time periods.  It returns immedately\r
2128 ;or after the entire wait time.  It does not remove the character\r
2129 ;from the buffer, so ri should be checked to see if something\r
2130 ;actually did show up while it was waiting\r
2131         .equ    char_delay, 4           ;number of char xmit times to wait\r
2132 cinf_wait:\r
2133         mov     a, r2\r
2134         push    acc\r
2135         mov     r2, #char_delay*5\r
2136 cinfw2: mov     a, th0\r
2137 cinfw3: jb      ri, cinfw4\r
2138         inc     a\r
2139         jnz     cinfw3\r
2140         djnz    r2, cinfw2\r
2141 cinfw4: pop     acc\r
2142         mov     r2, a\r
2143         ret\r
2144 \r
2145 \r
2146 \r
2147 \r
2148 pint8u: ;prints the unsigned 8 bit value in Acc in base 10\r
2149         push    b\r
2150         push    acc\r
2151         sjmp    pint8b\r
2152 \r
2153 pint8:  ;prints the signed 8 bit value in Acc in base 10\r
2154         push    b\r
2155         push    acc\r
2156         jnb     acc.7, pint8b\r
2157         mov     a, #'-'\r
2158         lcall   cout\r
2159         pop     acc\r
2160         push    acc\r
2161         cpl     a\r
2162         add     a, #1\r
2163 pint8b: mov     b, #100\r
2164         div     ab\r
2165         setb    f0\r
2166         jz      pint8c\r
2167         clr     f0\r
2168         add     a, #'0'\r
2169         lcall   cout\r
2170 pint8c: mov     a, b\r
2171         mov     b, #10\r
2172         div     ab\r
2173         jnb     f0, pint8d\r
2174         jz      pint8e\r
2175 pint8d: add     a, #'0'\r
2176         lcall   cout\r
2177 pint8e: mov     a, b\r
2178         add     a, #'0'\r
2179         lcall   cout\r
2180         pop     acc\r
2181         pop     b\r
2182         ret\r
2183 \r
2184 \r
2185 \r
2186         ;print 16 bit unsigned integer in DPTR, using base 10.\r
2187 pint16u:        ;warning, destroys r2, r3, r4, r5, psw.5\r
2188         push    acc\r
2189         mov     a, r0\r
2190         push    acc\r
2191         clr     psw.5\r
2192         mov     r2, dpl\r
2193         mov     r3, dph\r
2194 \r
2195 pint16a:mov     r4, #16         ;ten-thousands digit\r
2196         mov     r5, #39\r
2197         acall   pint16x\r
2198         jz      pint16b\r
2199         add     a, #'0'\r
2200         lcall   cout\r
2201         setb    psw.5\r
2202 \r
2203 pint16b:mov     r4, #232        ;thousands digit\r
2204         mov     r5, #3\r
2205         acall   pint16x\r
2206         jnz     pint16c\r
2207         jnb     psw.5, pint16d\r
2208 pint16c:add     a, #'0'\r
2209         lcall   cout\r
2210         setb    psw.5\r
2211 \r
2212 pint16d:mov     r4, #100        ;hundreds digit\r
2213         mov     r5, #0\r
2214         acall   pint16x\r
2215         jnz     pint16e\r
2216         jnb     psw.5, pint16f\r
2217 pint16e:add     a, #'0'\r
2218         lcall   cout\r
2219         setb    psw.5\r
2220 \r
2221 pint16f:mov     a, r2           ;tens digit\r
2222         mov     r3, b\r
2223         mov     b, #10\r
2224         div     ab\r
2225         jnz     pint16g\r
2226         jnb     psw.5, pint16h\r
2227 pint16g:add     a, #'0'\r
2228         lcall   cout\r
2229 \r
2230 pint16h:mov     a, b            ;and finally the ones digit\r
2231         mov     b, r3\r
2232         add     a, #'0'\r
2233         lcall   cout\r
2234 \r
2235         pop     acc\r
2236         mov     r0, a\r
2237         pop     acc\r
2238         ret\r
2239 \r
2240 ;ok, it's a cpu hog and a nasty way to divide, but this code\r
2241 ;requires only 21 bytes!  Divides r2-r3 by r4-r5 and leaves\r
2242 ;quotient in r2-r3 and returns remainder in acc.  If Intel\r
2243 ;had made a proper divide, then this would be much easier.\r
2244 \r
2245 pint16x:mov     r0, #0\r
2246 pint16y:inc     r0\r
2247         clr     c\r
2248         mov     a, r2\r
2249         subb    a, r4\r
2250         mov     r2, a\r
2251         mov     a, r3\r
2252         subb    a, r5\r
2253         mov     r3, a\r
2254         jnc     pint16y\r
2255         dec     r0\r
2256         mov     a, r2\r
2257         add     a, r4\r
2258         mov     r2, a\r
2259         mov     a, r3\r
2260         addc    a, r5\r
2261         mov     r3, a\r
2262         mov     a, r0\r
2263         ret\r
2264 \r
2265 \r
2266 \r
2267 ;pcstr prints the compressed strings.  A dictionary of 128 words is\r
2268 ;stored in 4 bit packed binary format.  When pcstr finds a byte in\r
2269 ;a string with the high bit set, it prints the word from the dictionary.\r
2270 ;A few bytes have special functions and everything else prints as if\r
2271 ;it were an ordinary string.\r
2272 \r
2273 ; special codes for pcstr:\r
2274 ;    0 = end of string\r
2275 ;   13 = CR/LF\r
2276 ;   14 = CR/LF and end of string\r
2277 ;   31 = next word code should be capitalized\r
2278 \r
2279 pcstr:  push    acc\r
2280         mov     a, r0\r
2281         push    acc\r
2282         mov     a, r1\r
2283         push    acc\r
2284         mov     a, r4\r
2285         push    acc\r
2286         setb    psw.1\r
2287         setb    psw.5\r
2288 pcstr1: clr     a\r
2289         movc    a, @a+dptr\r
2290         inc     dptr\r
2291         jz      pcstr2\r
2292         jb      acc.7, decomp\r
2293         anl     a, #0x7F\r
2294 pcstrs1:cjne    a, #13, pcstrs2\r
2295         lcall   newline\r
2296         setb    psw.1\r
2297         sjmp    pcstr1\r
2298 pcstrs2:cjne    a, #31, pcstrs3\r
2299         clr     psw.5\r
2300         sjmp    pcstr1\r
2301 pcstrs3:cjne    a, #14, pcstrs4\r
2302         lcall   newline\r
2303         sjmp    pcstr2\r
2304 pcstrs4:\r
2305         clr     psw.1\r
2306         lcall   cout\r
2307         sjmp    pcstr1\r
2308 pcstr2: pop     acc\r
2309         mov     r4, a\r
2310         pop     acc\r
2311         mov     r1, a\r
2312         pop     acc\r
2313         mov     r0, a\r
2314         pop     acc\r
2315         ret\r
2316 \r
2317 ;dcomp actually takes care of printing a word from the dictionary\r
2318 \r
2319 ; dptr = position in packed words table\r
2320 ; r4=0 if next nibble is low, r4=255 if next nibble is high\r
2321 \r
2322 decomp: anl     a, #0x7F\r
2323         mov     r0, a           ;r0 counts which word\r
2324         jb      psw.1, decomp1  ;avoid leading space if first word\r
2325         lcall   space\r
2326 decomp1:clr     psw.1\r
2327         push    dpl\r
2328         push    dph\r
2329         mov     dptr, #words\r
2330         mov     r4, #0\r
2331         mov     a, r0\r
2332         jz      dcomp3\r
2333         ;here we must seek past all the words in the table\r
2334         ;that come before the one we're supposed to print\r
2335         mov     r1, a\r
2336 dcomp2: acall   get_next_nibble\r
2337         jnz     dcomp2\r
2338         ;when we get here, a word has been skipped... keep doing\r
2339         ;this until we're pointing to the correct one\r
2340         djnz    r1, dcomp2\r
2341 dcomp3: ;now we're pointing to the correct word, so all we have\r
2342         ;to do is print it out\r
2343         acall   get_next_nibble\r
2344         jz      dcomp_end\r
2345         cjne    a, #15, dcomp4\r
2346         ;the character is one of the 12 least commonly used\r
2347         acall   get_next_nibble\r
2348         inc     a\r
2349         movc    a, @a+pc\r
2350         sjmp    dcomp5\r
2351         .db     "hfwgybxvkqjz"\r
2352 dcomp4: ;the character is one of the 14 most commonly used\r
2353         inc     a\r
2354         movc    a, @a+pc\r
2355         sjmp    dcomp5\r
2356         .db     "etarnisolumpdc"\r
2357 dcomp5: ;decide if it should be uppercase or lowercase\r
2358         mov     c, psw.5\r
2359         mov     acc.5, c\r
2360         setb    psw.5\r
2361         cjne    r0, #20, dcomp6\r
2362         clr     acc.5\r
2363 dcomp6: cjne    r0, #12, dcomp7\r
2364         clr     acc.5\r
2365 dcomp7: lcall   cout\r
2366         sjmp    dcomp3\r
2367 dcomp_end:\r
2368         pop     dph\r
2369         pop     dpl\r
2370         ajmp    pcstr1\r
2371 \r
2372 get_next_nibble:        ;...and update dptr and r4, of course\r
2373         clr     a\r
2374         movc    a, @a+dptr\r
2375         cjne    r4, #0, gnn2\r
2376         mov     r4, #255\r
2377         anl     a, #00001111b\r
2378         ret\r
2379 gnn2:   mov     r4, #0\r
2380         inc     dptr\r
2381         swap    a\r
2382         anl     a, #00001111b\r
2383         ret\r
2384 \r
2385 \r
2386 ;---------------------------------------------------------;\r
2387 ;                                                         ;\r
2388 ;        Here begins the data tables and strings          ;\r
2389 ;                                                         ;\r
2390 ;---------------------------------------------------------;\r
2391 \r
2392 ;this is the dictionary of 128 words used by pcstr.\r
2393 \r
2394 words:\r
2395         .db     0x82, 0x90, 0xE8, 0x23, 0x86, 0x05, 0x4C, 0xF8\r
2396         .db     0x44, 0xB3, 0xB0, 0xB1, 0x48, 0x5F, 0xF0, 0x11\r
2397         .db     0x7F, 0xA0, 0x15, 0x7F, 0x1C, 0x2E, 0xD1, 0x40\r
2398         .db     0x5A, 0x50, 0xF1, 0x03, 0xBF, 0xBA, 0x0C, 0x2F\r
2399         .db     0x96, 0x01, 0x8D, 0x3F, 0x95, 0x38, 0x0D, 0x6F\r
2400         .db     0x5F, 0x12, 0x07, 0x71, 0x0E, 0x56, 0x2F, 0x48\r
2401         .db     0x3B, 0x62, 0x58, 0x20, 0x1F, 0x76, 0x70, 0x32\r
2402         .db     0x24, 0x40, 0xB8, 0x40, 0xE1, 0x61, 0x8F, 0x01\r
2403         .db     0x34, 0x0B, 0xCA, 0x89, 0xD3, 0xC0, 0xA3, 0xB9\r
2404         .db     0x58, 0x80, 0x04, 0xF8, 0x02, 0x85, 0x60, 0x25\r
2405         .db     0x91, 0xF0, 0x92, 0x73, 0x1F, 0x10, 0x7F, 0x12\r
2406         .db     0x54, 0x93, 0x10, 0x44, 0x48, 0x07, 0xD1, 0x26\r
2407         .db     0x56, 0x4F, 0xD0, 0xF6, 0x64, 0x72, 0xE0, 0xB8\r
2408         .db     0x3B, 0xD5, 0xF0, 0x16, 0x4F, 0x56, 0x30, 0x6F\r
2409         .db     0x48, 0x02, 0x5F, 0xA8, 0x20, 0x1F, 0x01, 0x76\r
2410         .db     0x30, 0xD5, 0x60, 0x25, 0x41, 0xA4, 0x2C, 0x60\r
2411         .db     0x05, 0x6F, 0x01, 0x3F, 0x26, 0x1F, 0x30, 0x07\r
2412         .db     0x8E, 0x1D, 0xF0, 0x63, 0x99, 0xF0, 0x42, 0xB8\r
2413         .db     0x20, 0x1F, 0x23, 0x30, 0x02, 0x7A, 0xD1, 0x60\r
2414         .db     0x2F, 0xF0, 0xF6, 0x05, 0x8F, 0x93, 0x1A, 0x50\r
2415         .db     0x28, 0xF0, 0x82, 0x04, 0x6F, 0xA3, 0x0D, 0x3F\r
2416         .db     0x1F, 0x51, 0x40, 0x23, 0x01, 0x3E, 0x05, 0x43\r
2417         .db     0x01, 0x7A, 0x01, 0x17, 0x64, 0x93, 0x30, 0x2A\r
2418         .db     0x08, 0x8C, 0x24, 0x30, 0x99, 0xB0, 0xF3, 0x19\r
2419         .db     0x60, 0x25, 0x41, 0x35, 0x09, 0x8E, 0xCB, 0x19\r
2420         .db     0x12, 0x30, 0x05, 0x1F, 0x31, 0x1D, 0x04, 0x14\r
2421         .db     0x4F, 0x76, 0x12, 0x04, 0xAB, 0x27, 0x90, 0x56\r
2422         .db     0x01, 0x2F, 0xA8, 0xD5, 0xF0, 0xAA, 0x26, 0x20\r
2423         .db     0x5F, 0x1C, 0xF0, 0xF3, 0x61, 0xFE, 0x01, 0x41\r
2424         .db     0x73, 0x01, 0x27, 0xC1, 0xC0, 0x84, 0x8F, 0xD6\r
2425         .db     0x01, 0x87, 0x70, 0x56, 0x4F, 0x19, 0x70, 0x1F\r
2426         .db     0xA8, 0xD9, 0x90, 0x76, 0x02, 0x17, 0x43, 0xFE\r
2427         .db     0x01, 0xC1, 0x84, 0x0B, 0x15, 0x7F, 0x02, 0x8B\r
2428         .db     0x14, 0x30, 0x8F, 0x63, 0x39, 0x6F, 0x19, 0xF0\r
2429         .db     0x11, 0xC9, 0x10, 0x6D, 0x02, 0x3F, 0x91, 0x09\r
2430         .db     0x7A, 0x41, 0xD0, 0xBA, 0x0C, 0x1D, 0x39, 0x5F\r
2431         .db     0x07, 0xF2, 0x11, 0x17, 0x20, 0x41, 0x6B, 0x35\r
2432         .db     0x09, 0xF7, 0x75, 0x12, 0x0B, 0xA7, 0xCC, 0x48\r
2433         .db     0x02, 0x3F, 0x64, 0x12, 0xA0, 0x0C, 0x27, 0xE3\r
2434         .db     0x9F, 0xC0, 0x14, 0x77, 0x70, 0x11, 0x40, 0x71\r
2435         .db     0x21, 0xC0, 0x68, 0x25, 0x41, 0xF0, 0x62, 0x7F\r
2436         .db     0xD1, 0xD0, 0x21, 0xE1, 0x62, 0x58, 0xB0, 0xF3\r
2437         .db     0x05, 0x1F, 0x73, 0x30, 0x77, 0xB1, 0x6F, 0x19\r
2438         .db     0xE0, 0x19, 0x43, 0xE0, 0x58, 0x2F, 0xF6, 0xA4\r
2439         .db     0x14, 0xD0, 0x23, 0x03, 0xFE, 0x31, 0xF5, 0x14\r
2440         .db     0x30, 0x99, 0xF8, 0x03, 0x3F, 0x64, 0x22, 0x51\r
2441         .db     0x60, 0x25, 0x41, 0x2F, 0xE3, 0x01, 0x56, 0x27\r
2442         .db     0x93, 0x09, 0xFE, 0x11, 0xFE, 0x79, 0xBA, 0x60\r
2443         .db     0x75, 0x42, 0xEA, 0x62, 0x58, 0xA0, 0xE5, 0x1F\r
2444         .db     0x53, 0x4F, 0xD1, 0xC0, 0xA3, 0x09, 0x42, 0x53\r
2445         .db     0xF7, 0x12, 0x04, 0x62, 0x1B, 0x30, 0xF5, 0x05\r
2446         .db     0xF7, 0x69, 0x0C, 0x35, 0x1B, 0x70, 0x82, 0x2F\r
2447         .db     0x2F, 0x14, 0x4F, 0x51, 0xC0, 0x64, 0x25, 0x00\r
2448 \r
2449 ;STR\r
2450 \r
2451 logon1: .db     "Welcome",128,148,"2, by",31,248,31,254,13,14\r
2452 logon2: .db     32,32,"See",148,"2.DOC,",148,"2.EQU",164\r
2453         .db     148,"2.HDR",180,213,141,".",14\r
2454 abort:  .db     " ",31,158,31,160,"!",13,14\r
2455 prompt1:.db     148,"2 Loc:",0\r
2456 prompt2:.db     " >", 160       ;must follow after prompt1\r
2457 prompt3:.db     134,202,130,'(',0\r
2458 prompt4:.db     "),",149,140,128,200,": ",0\r
2459 prompt5:.db     31,151,130,195,"s",199,166,131,","\r
2460         .db     186," JUMP",128,134,161,"r",130,13,14\r
2461 prompt6:.db     13,13,31,135,131,129,": ",0\r
2462 prompt7:.db     31,228,251," key: ",0\r
2463 prompt8:.db     13,13,31,136,128,131,129," (",0\r
2464 prompt9:.db     13,13,31,130,31,253,0\r
2465 prompt9b:.db     31,129,32,32,32,32,32,31,201,14        ;must follow prompt9\r
2466 prompt10:.db    ") ",31,135,31,178,": ",0\r
2467 beg_str:.db     "First",31,129,": ",0\r
2468 end_str:.db     "Last",31,129,":",32,32,0\r
2469 sure:   .db     31,185,161," sure?",0\r
2470 edits1: .db     13,13,31,156,154,146,",",140,128,200,14\r
2471 edits2: .db     "  ",31,156,193,",",142,129,247,13,14\r
2472 dnlds1: .db     13,13,31,159," ascii",249,150,31,152,132,137\r
2473         .db     ",",149,140,128,160,13,14\r
2474 dnlds2: .db     13,31,138,160,"ed",13,14\r
2475 dnlds3: .db     13,31,138,193,"d",13,14\r
2476 dnlds4: .db     "Summary:",14\r
2477 dnlds5: .db     " ",198,"s",145,"d",14\r
2478 dnlds6a:.db     " ",139,145,"d",14\r
2479 dnlds6b:.db     " ",139," written",14\r
2480 dnlds7: .db     31,155,":",14\r
2481 dnlds8: .db     " ",139," unable",128," write",14\r
2482 dnlds9: .db     32,32,"bad",245,"s",14\r
2483 dnlds10:.db     " ",133,159,150,198,14\r
2484 dnlds11:.db     " ",133,132,157,14\r
2485 dnlds12:.db     " ",133," non",132,157,14\r
2486 dnlds13:.db     31,151,155," detected",13,14\r
2487 runs1:  .db     13,134,"ning",130,":",13,14\r
2488 uplds3: .db     13,13,"Sending",31,152,132,137,172,32,32,0\r
2489 uplds4: .db     " ",128,32,32,0         ;must follow uplds3\r
2490 help1txt:.db    13,13,"Standard",31,158,"s",14\r
2491 help2txt:.db    31,218,31,244,"ed",31,158,"s",14\r
2492 type1:  .db     31,154,158,0\r
2493 type2:  .db     31,130,0\r
2494 type4:  .db     31,143,31,226,31,170,0\r
2495 type5:  .db     "???",0\r
2496 help_cmd2:.db   31,215,0\r
2497 help_cmd: .db   31,142,215,209,0        ;these 11 _cmd string must be in order\r
2498 dir_cmd:  .db   31,209,130,"s",0\r
2499 run_cmd:  .db   31,134,130,0\r
2500 dnld_cmd: .db   31,138,0\r
2501 upld_cmd: .db   31,147,0\r
2502 nloc_cmd: .db   31,135,129,0\r
2503 jump_cmd: .db   31,136,128,131,129,0\r
2504 dump_cmd: .db   31,132,219,154,131,0\r
2505 intm_cmd: .db   31,132,219,192,131,0\r
2506 edit_cmd: .db   31,156,154,146,0\r
2507 clrm_cmd: .db   31,237,131,0\r
2508 erfr_cmd: .db   31,203,153,144,0\r
2509 erfr_ok:  .db   31,153,144,203,'d',13,14\r
2510 erfr_err: .db   31,133,155,13,14\r
2511 \r
2512 \r