├── .gitattributes ├── 4intro.txt ├── ed.dow ├── ed.scr ├── extras ├── 3ins4th │ ├── 3ins4th.html │ ├── 3ins4th.html~ │ ├── demo.scr │ ├── mona1.scr │ ├── mond0.scr │ ├── mone1.scr │ ├── monitor.txt │ └── readme ├── 6811asm.dow ├── 6811asm.scr ├── 6811asm.txt ├── cfth │ ├── bgi.dow │ ├── bgi.scr │ ├── cpyg.txt │ └── lp.c ├── cmforth.dow ├── cmforth.scr ├── doubquad.scr ├── help.txt ├── kermit │ ├── kermit.dow │ ├── kermit.scr │ ├── listing.ker │ ├── pfaaaa.ann │ ├── pfaaaa.txt │ ├── pfkerm.doc │ ├── pfkerm.msg │ ├── pfkerm.src │ ├── pfkerm.txt │ └── readme.txt ├── metacomp.txt └── metacomp.txt.old ├── files.txt ├── license20040130.txt ├── pygmy.com ├── pygmy.dow ├── pygmy.scr ├── pygmy.txt ├── readme ├── serial.dow ├── serial.scr ├── tutorial.txt ├── yourfile.dow └── yourfile.scr /.gitattributes: -------------------------------------------------------------------------------- 1 | *.scr linguist-language=Forth 2 | -------------------------------------------------------------------------------- /ed.dow: -------------------------------------------------------------------------------- 1 | ED.DOW Pygmy Line Editor Frank Sergeant frank@pygmy.utoh.org http://pygmy.utoh.org copyright 2005-2007 Frank C. Sergeant - frank@pygmy.utoh.org BSD/MIT/X-style license, see file license20040130.txt. http://pygmy.utoh.org Similar to the one described on p. 63 ff. of _Starting Forth_ 2nd Ed. ( Load screen for line editor) ( PLACE utility extensions ) PLACE ( a # buf -) move the string to a buffer, preserving the length count. Buffer must be at least #+1 bytes long. INDEX ( start end -) show the top lines of this block range (this is the conventional Forth INDEX ) ( Editor buffers ) CURSOR holds the offset (0 through 63) of the logical cursor into the block being edited, where SCR holds the block number of the block being edited. Should we use a lower case x or a vertical bar | to indicate the cursor location? Should we only indicate it with the single line commands such as T ? FBUF ( - a) the find buffer, holds a counted string IBUF ( - a) the insert buffer, holds a counted string K ( -) swap contents of FBUF and IBUF LINE-TAIL ( - a #) return the part of the current line from the CURSOR to the end of the line. BLOCK-TAIL ( - a #) return the part of the current block from the CURSOR to the end of the block. ( LIST list screen with line numbers ) .BAR .LINE# (LINE .L show a single line with a cursor marker below ( Here is a more complicated .L that attempts to print the) ( cursor indicator in-line rather on the next line) : .L ( -) CURSOR @ 64 U/MOD ( offset line) DUP .LINE# ( off n) 64 * SCR @ BLOCK + DUP PUSH OVER TYPE '^ EMIT POP ( off a) OVER + 64 ROT - TYPE .BAR ; ( (LIST LIST L +LIST N B A T ) T ( u) make line u the current line and display it ( SRCH ) SRCH ( - found) Search forward in the current block starting at CURSOR, looking for the string in FBUF. If found, return true and also bump the CURSOR so it points just past the matching string. We shorten the block tail but 1 less than the length of the string we are searching for, then search up to that many chars forward for a match on the first char of the string. If it matches, then we do a full compare using COMP. For efficiency, we could search for a matching first char beforechecking for a full match, e.g. FBUF 1+ C@ PUSH ( -- 1stChar) BLOCK-TAIL ( a #) FBUF C@ 1- - ( a #) BEGIN DUP WHILE ( a #) OVER C@ R@ = IF ( 1stChar matched, so now do a full compare) ... but that's premature ( (F F ) ( SPREAD INSERT ) SPREAD ( a # size -) insert size spaces into the string, sliding the rest of the string forward, but maintaining its original length, thus dropping size chars from the end of the string. INSERT ( buf -) insert the counted string at buf into the current line, pushing the rest of the line to the right. This insertion is limited to the current line. I can be used inside a definition so we get the Editor's 'I' rather than the COMPILER's 'I'? That is, the Editor's 'I' can be used only *outside* of definitions so as not to conflict with the For ... Next index named 'I'. The solution is to define '(I' so it that can be used in other definitions and define 'I' to call '(I'. ( DELETE E ) DELETE ( u -) remove u characters from the current line, block, starting at the CURSOR, sliding chars up and filling the end of the line with spaces. E ( -) delete the just-found string ( ie delete the length of the string in FBUF before the CURSOR, so we back the cursor up by the length of the string before DELETEing) ( P ) BOL ( -) move cursor to beginning of current line EOL ( -) move cursor to end of current line, ie BOL of next line P replaces the entire current line either with the string that follows P, e.g. P NEW TEXT FOR THE LINE or with the previous contents of the insert buffer IBUF if an empty string follows follows P, eg. P The cursor remains positioned on the same line (but at start) U string U is like P except it inserts the line below the current line and moves the remaining lines down C ( -) copy current line into the insert buffer X ( -) delete the current line, copying into insert buffer ( S search across blocks) ( BRING bring a range of lines into the current block) BRING ( sourceBlock first last -) Insert the range of blocks at the current line, sliding the current line and following lines down. Limit the lines brought over to those that will fit. The source block is not altered. ( TILL ) TILL string Delete everything on current line up through string TILL putN the deleted text into the insert buffer ( Pushing and Popping individual lines) In the Pygmy full-screen editor, CUT (F7) pushed the current line and UNCUT (F8) popped a line into the current line. The bufferwas at or above PAD. This was convenient for copying some lines from one or blocks into another block or blocks. That may be easier than using BRING which would seem to require remembering block and line numbers. However, the stack could be used to remember those for us. E.g.when you are looking at block 8019 and decide you want lines 3 through 6, type 8019 3 6 and then move to the destination block with N or B or xxx LIST and then say .S to verify the source block and line range are still there. ( HOLES insert one or more blank blocks after current block) HOLES ( u -) spread open current block file to insert u new blank blocks following the current block, moving the remaining blocks down ( ie toward the end of the file). -------------------------------------------------------------------------------- /ed.scr: -------------------------------------------------------------------------------- 1 | ED.SCR Pygmy Line Editor Frank Sergeant frank@pygmy.utoh.org http://pygmy.utoh.org copyright 2005-2007 Frank C. Sergeant - frank@pygmy.utoh.org BSD/MIT/X-style license, see file license20040130.txt. http://pygmy.utoh.org Similar to the one described on p. 63 ff. of _Starting Forth_ 2nd Ed. ( Load screen for line editor) 8001 8016 THRU ( PLACE INDEX utility extensions ) : PLACE ( a # buf -) 2DUP C! 1+ SWAP CMOVE ; : INDEX ( start end -) OVER - 1+ FOR ( u) ?SCROLL CR DUP 4 .R SPACE DUP BLOCK 64 TYPE 1+ NEXT DROP ; ( Editor buffers FBUF IBUF K LINE-TAIL BLOCK-TAIL CURSOR! ) VARIABLE CURSOR CREATE FBUF 65 ALLOT ( find buffer -- bigger than needed? ) CREATE IBUF 65 ALLOT ( insert buffer, count by 64 chars) : K ( -) FBUF PAD 65 CMOVE IBUF FBUF 65 CMOVE PAD IBUF 65 CMOVE ; : LINE-TAIL ( - a #) CURSOR @ 64 OVER 64 UMOD - SCR @ BLOCK +UNDER ; : BLOCK-TAIL ( - a #) CURSOR @ 1024 OVER - SCR @ BLOCK +UNDER ; : CURSOR! ( u -) 0 1023 CLAMP CURSOR ! ; : CURSOR+! ( u -) CURSOR @ + CURSOR! ; ( .BAR .LINE# (LINE MK .L list screen with line numbers ) : .BAR ( -) '| EMIT ; : .LINE# ( n -) CR 2 .R .BAR ; : (LINE ( n -) DUP .LINE# ( n) 64 * SCR @ BLOCK + 64 ( a #) TYPE .BAR ; VARIABLE MK ( marker ) '| MK ! : .L ( -) ( show a single line with a cursor marker below) CURSOR @ 64 U/MOD ( offset line) (LINE ( offset) ( ie show the line) CR 3 + SPACES MK @ EMIT ( ie show the cursor position) ; ( (LIST LIST L +LIST N B A T ) : (LIST ( -) CR ." scr " SCR @ DUP U. SPACE >UNIT# .FILE 0 16 FOR DUP (LINE 1+ NEXT DROP ; : LIST ( n -) CURSOR OFF DUP DUP >UNIT# RANGE UBETWEEN IF ( n) SCR ! (LIST EXIT THEN ( n) ." no block " ( n) U. ; : L ( -) (LIST ; : +LIST ( n -) SCR @ DUP +UNDER ( new old) >UNIT# RANGE WRAP ( n') LIST ; : N ( -) 1 +LIST ; : B ( -) -1 +LIST ; : A ( -) SCR @ 1000 OVER >UNIT# ODD? IF NEGATE THEN + LIST ; : T ( line# -) 64 * CURSOR! .L ; ( SRCH ) : SRCH ( - found) FBUF C@ 0= IF -1 ( nothing to find but we found it) EXIT THEN BLOCK-TAIL ( a #) FBUF C@ 1- - ( a #) BEGIN DUP WHILE ( a #) OVER FBUF COUNT COMP 0= IF ( a #) ( yes, a match) DROP SCR @ BLOCK - FBUF C@ + CURSOR! ( new cursor position is just past the found string) -1 EXIT THEN 1 +UNDER 1- REPEAT ( a #) 2DROP 0 ( ie not found) ; ( GET-SEARCH-STRING (F F ) : GET-SEARCH-STRING ( -) ( string) 0 WORD COUNT ( a #) ?DUP IF ( a #) FBUF PLACE EXIT THEN DROP ; : (F ( -) ( string) GET-SEARCH-STRING ( ) SRCH 0= ABORT" not found" ; : F ( -) (F .L ; EXIT : (F ( -) SRCH 0= ABORT" not found" .L ; : F ( -) ( string) 0 WORD COUNT ( a #) ?DUP IF ( a #) FBUF PLACE (F EXIT THEN DROP (F ; ( SPREAD INSERT (I I ) : SPREAD ( a # size -) OVER MIN PUSH 2DUP ( a # a # -- size) OVER ( a # a # a) R@ + ( a # a # dest) SWAP R@ - ( a # a dest #') CMOVE> ( a #) DROP POP 32 FILL UPDATE ; : INSERT ( a # -) ( new new#) LINE-TAIL ROT ( new tail t# new#) OVER MIN PUSH ( new tail t# -- new#) R@ SPREAD ( new -- new#) SCR @ BLOCK CURSOR @ + R@ CMOVE POP ( new#) CURSOR+! ( ) UPDATE ; : (I ( -) ( string) 0 WORD COUNT ( a #) DUP IF ( a #) 2DUP IBUF PLACE THEN 2DROP ( ) IBUF COUNT INSERT .L ; : I ( -) (I ; ( DELETE E D R) : DELETE ( del# -) LINE-TAIL ( del# tail t#) ROT OVER MIN ( tail t# del#) ( move from=tail+del# to=tail len=t#-del# ) ( then fill tail+t#-del# for a len of del# with spaces) PUSH ( tail t# -- del#) OVER R@ + ( tail t# from) ROT ( t# from tail) ROT ( from tail t#) ( from to #) R@ - CMOVE ( -- del#) LINE-TAIL ( tail t#) + R@ - ( a) POP 32 FILL UPDATE ; : E ( -) FBUF C@ ( #) DUP NEGATE CURSOR+! ( ie backup) ( #) DELETE .L ; : D ( -) ( string) F E ; : R ( -) E (I ; ( BOL EOL P ) : BOL ( -) CURSOR @ 64 U/ 64 * CURSOR! ; : EOL ( -) BOL 64 CURSOR+! ; : P ( -) ( string) 0 WORD COUNT ( a #) DUP IF ( a #) 2DUP IBUF PLACE THEN 2DROP PAD 64 32 FILL ( prepare a blank line) IBUF COUNT PAD SWAP CMOVE ( now PAD holds our new line) BOL ( temporarily move cursor to start of line) ( CURSOR @ 64 U/ 64 * ) ( DUP CURSOR ! ) CURSOR @ ( temporarily move cursor to start of line) PAD 64 INSERT ( move the line to the block) ( start-of-same-line) CURSOR! .L ; ( U C X ) : U ( -) ( string) EOL BLOCK-TAIL DUP 64 U< ABORT" end of block" ( a #) 64 SPREAD P ; : C ( -) BOL LINE-TAIL IBUF PLACE ( ) ; : X ( -) C CURSOR @ LINE-TAIL DROP ( cur to) EOL BLOCK-TAIL ( cur to from #) PUSH SWAP POP CMOVE ( cur) 15 64 * CURSOR! LINE-TAIL 32 FILL ( cur) CURSOR! UPDATE .L ; ( S search across blocks) : S ( -) ( string) GET-SEARCH-STRING CURSOR @ ( save it in case string is not found) SCR @ DUP DUP >UNIT# RANGE NIP ( ie lastBlk#) PUSH BEGIN ( origCur origBlk blk#) SRCH IF 2DROP POP 2DROP L .L EXIT ( ) THEN DUP R@ U< WHILE ( origCur origBlk blk) 1+ DUP SCR ! CURSOR OFF REPEAT POP DROP ." not found" ( origCur origBlk blk#) DROP SCR ! CURSOR! ; ( BRING bring a range of lines into the current block) : BRING ( sourceBlock first last -) OVER - 1+ ( ie lines) 64 * ( ie size) PUSH ( srcBlk first) 64 * ( ie offset) SWAP BLOCK + ( from) BLOCK-TAIL POP OVER ( from tail t# size t#) 0 SWAP ( from tail t# size 0 t#) CLAMP ( from tail t# 'size) DUP PUSH ( from tail t# size -- size) SPREAD ( from -- size) BLOCK-TAIL DROP ( from to) POP CMOVE L .L ; ( TILL ) : TILL ( -) ( string) CURSOR @ ( origCur) (F CURSOR @ ( origCur newCur) OVER CURSOR! ( restore cursor regardless) SWAP - ( actualDistance) DUP LINE-TAIL NIP ( actual actual allowedDistance) U> NOT IF ( actual#) LINE-TAIL DROP OVER IBUF PLACE ( actual#) DELETE ELSE DROP ." not found" THEN .L ; ( Possible enhancements ) EXIT Pushing and Popping individual lines Easy way to insert blank blocks, see HOLES in old editor SPLIT would delete from the cursor to the end of line then trim that string and put it in the insert buffer then insert it at the beginning of the next line (or maybe do U). JOIN would delete from cursor to end of current line and then pull as much from following line into current line as will fit. Define the common 1-letter commands also as lower case. ( HOLES insert one or more blank blocks after current block) ( this uses MORE [ # handle] ) : HOLES ( u -) 0 50 CLAMP ( u) DUP PUSH ( u -- u) ( first, extend file by u blocks and reopen) SCR @ >UNIT# DUP PUSH HANDLE @ MORE R@ ?OPEN ( -- unit# u) 1 SCR +! ( we insert *following* current block) ( next, copy original remaining blocks forward) SCR @ DUP ( from to-u) POP RANGE NIP SCR @ - 1+ ( ie count+u) ( from to-u count+u -- u) R@ +UNDER R@ - ( from to count) COPIES ( -- u) ( then, blank out the new blocks ) SCR @ POP FOR ( blk) DUP CLEAR 1+ NEXT DROP ( ) ( finally, restore current block) -1 SCR +! ; -------------------------------------------------------------------------------- /extras/3ins4th/demo.scr: -------------------------------------------------------------------------------- 1 | This file is a good place to put the source code you write. To get you started, block 2002 shows a sequence of commands you could type from the keyboard to make the least significant bit of port C be an output bit and then set the bit high and then set it low. It also defines the word FLASH1 which will toggle an LED or logic probe attached to that output pin (ie. pin 9 on the PLCC version of either the 'A1 or 'E1). Since FLASH1 runs on the PC, you may interrupt it by pressing the Esc key. Then, block 2003, shows more or less equivalent 68HC11 assembly language. 2003 LOAD assembles the word FLASH2, then typing the word FLASH2 causes the machine code to be downloaded to the 'HC11 and executed. It runs in an endless loop, so you'll need to reset the 'HC11 and run DL8 once again to regain control. I can be reached by email at frank@pygmy.utoh.org. ( You may use this block as a load block for code you write) ( Make port C bit 0 an output and then turn it on and off) ( Note, you must have run DL8 first, to download the MONITOR to the 'HC11 chip.) ( You may type the following commands from the keyboard, or you may type 2002 LOAD to load this block.) 1 DDRC X! ( make lsbit of port C an output) 1 PORTC X! ( turn on the bit) 0 PORTC X! ( turn off the bit, repeat as long as you like) : FLASH1 ( ) 1 DDRC X! BEGIN ?SCROLL 1 PORTC X! 200 MS 0 PORTC X! 200 MS AGAIN ; ( Do the same as block 2002, but in assembly language) XCODE: FLASH2 1 #, LDA, ( put a 1 into register A) DDRC #) STA, ( then transfer it to port C's data direction register) CLRA, ( put all zeroes into register A) BEGIN, ( note the comma) 1 #, EORA, ( flip bit zero of register A) PORTC #) STA, ( and write it to port C) $F837 #, LDX, ( put a delay value into the X register) BEGIN, DEX, 0=, UNTIL, ( kill some time) AGAIN, ( this is an endless loop, so you'll need to reset) ( the 'HC11 to break out of the loop) XEND -------------------------------------------------------------------------------- /extras/3ins4th/mona1.scr: -------------------------------------------------------------------------------- 1 | Copyright 1994-1997, 2007 Frank C. Sergeant. See license20040130.txt or http://pygmy.utoh.org/license.html I can be reached by email at frank@pygmy.utoh.org. MOND0.SCR & D0.COM are designed to work with the MC68HC11D0. MONE1.SCR & E1.COM are designed to work with the MC68HC11E1. MONA1.SCR & A1.COM are designed to work with the MC68HC11A1. MODE COM1:9600,8,N,1 may be necessary in your AUTOEXEC.BAT file. Note, MONITOR is limited to downloading a routine 256 bytes long. Some adjustments will need to be made to download a longer program, for example, into external RAM. (Easily enough done with a short routine downloaded thru MONITOR, which then downloads the longer code to external RAM.) ( Load block for 'HC11 "3-instruction Forth" MONITOR for 'A1 ) ( This assumes MONA1.SCR has been opened at unit 10 ) xxxxx LOAD ( serial port support) xxxxx LOAD ( hc11 assembler) 10002 10005 THRU ( Note block 10005 must be loaded twice!) 10005 10012 THRU ( General MONITOR related words) ( MONITOR a small monitor for 'hc11) $1000 CONSTANT 'REG ( These values apply only) 0 CONSTANT 'RAM ( to the 'E0 & 'A1 versions) : REG: CREATE C, DOES> C@ 'REG + ; ( above word used on next block to define registers) ( Define various RAM-based registers) $28 REG: SPCR ( serial peripheral control register) $2B REG: BAUD ( serial communications baud-rate register) $2E REG: SCSR ( serial communications status register) $2F REG: SCDR ( serial communications data register) $39 REG: OPTION ( watchdog time-out period) $3A REG: COP ( watchdog timer reset register) $3C REG: HPRIO ( for selecting external RAM) $00 REG: PORTA $26 REG: PACTL $0E REG: TCNT $04 REG: PORTB $06 REG: DDRB $18 REG: TOC2 $03 REG: PORTC $07 REG: DDRC $23 REG: TFLG1 $08 REG: PORTD $09 REG: DDRD $24 REG: TMSK2 ( MONITOR 'HC11 addresses ) VARIABLE 'RX ( VARIABLE 'GET-ADDR ) VARIABLE 'TX ( VARIABLE 'C@ VARIABLE 'C! ) VARIABLE 'MONITOR VARIABLE OFFSET VARIABLE MONITOR-LENGTH VARIABLE 'CODE : >MON ( a - a') 'MONITOR @ - 'RAM + ; : SET-OFFSET ( -) HERE OFFSET ! ; : >ABS ( a - a') OFFSET @ - 'CODE @ + ; : RX, ( macro) 'RX @ DIR JSR, ; : TX, ( macro) 'TX @ DIR JSR, ; : ADDR-IN, ( macro) RX, TAB, RX, ; ( leaves addr in regD) : COP, ( reset watchdog timer) PSHB, $55 #, LDB, COP ,Y STB, $AA #, LDB, COP ,Y STB, PULB, ; ( MONITOR ** this block must be loaded twice ** ) CODE MONITOR HERE 'MONITOR ! 'REG #, LDY, CLRA, SPCR #) STA, ( un-wire-OR port D) BEGIN, RX, TAB, ( ie save count) 'CODE @ #, LDX, BEGIN, RX, 0 ,X STA, INX, DECB, 0=, UNTIL, 'CODE @ DIR JSR, AGAIN, ( rx) ( rx) HERE >MON 'RX ! BEGIN, ( COP,) $20 #, LDA, SCSR #) BITA, <>, UNTIL, SCDR ,Y LDA, ( read byte from PC) RTS, ( tx) HERE >MON 'TX ! HERE $80 SCSR ,Y BRCLR, ( wait for TDRE) SCDR ,Y STA, ( send byte to PC) RTS, END-CODE HERE ' MONITOR - DUP MONITOR-LENGTH ! ( len) 'RAM + 'CODE ! ( 58 bytes with COP, and 46 without ) ( download monitor to 'HC11 board ) : .OUT ( a # -) FOR C@+ SER-OUT NEXT DROP ; : ?EMIT ( c -) DUP $20 $7F BETWEEN IF EMIT ELSE . THEN ; : .OUTE ( a # -) FOR DUP C@ SER-OUT SER-IN ?EMIT 1+ NEXT DROP ; : ADDR-OUT ( a -) BYTES ( lsb msb) SWAP SER-OUT SER-OUT ; ( Compile 'HC11 code routines in PC's memory, which can be downloaded later to 'HC11 and executed ) : XCODE: CREATE ( - a) HERE 0 C, ( save space for routine's length) DOES> C@+ DUP SER-OUT .OUT ; ( send length byte & machine code to 'hc11 board) : XEND ( addr-of-length-byte -) HERE OVER - 1- SWAP C! ; ( this fills in the length byte, now that it is known) XCODE: (X@ ADDR-IN, XGDX, 0 ,X LDA, TX, RTS, XEND : 1/2-X@ ( a -) (X@ ADDR-OUT ; ( used to verify connection) : X@ ( a - c) 1/2-X@ SER-IN ; XCODE: (X! ADDR-IN, XGDX, RX, 0 ,X STA, RTS, XEND : X! ( c a -) (X! ADDR-OUT SER-OUT ; XCODE: (XCALL ADDR-IN, XGDX, 0 ,X JSR, RTS, XEND : XCALL ( a -) ADDR-OUT ; : XDUMP ( a - a') HEX CR DUP 4 U.R 2 SPACES DUP 2 FOR 8 FOR DUP X@ 3 U.R 1+ NEXT SPACE NEXT DROP 2 SPACES ( a) 2 FOR 8 FOR DUP X@ DUP $20 $7F WITHIN NOT IF DROP $2E THEN EMIT 1+ NEXT SPACE NEXT ; : XDU ( a # - a') FOR ?SCROLL XDUMP NEXT DROP ; : X2@ ( u - v) DUP X@ $100 * SWAP 1+ X@ + ; : X2! ( u a -) PUSH BYTES ( lsb msb) R@ X! ( lsb) POP 1+ X! ; ( Adjust baud rate on both PC and 'HC11, assumes 8 MHz crystal) : 1200X ( -) $33 BAUD X! 50 MS 1200 BPS ; : 9600X ( -) $30 BAUD X! 50 MS 9600 BPS ; ( For 8 MHz xtal ) : RS ( -) -DTR 100 MS +DTR 100 MS 1200 BPS ; ( reset) : DL8 ( -) RS $FF SER-OUT ['] MONITOR ( a) ( MONITOR-LENGTH @ ( a #) ( use this for 'D0 & 'E1) 256 ( a #) ( use this for 'A1 ) ( a #) .OUT 150 MS RESET-SER-IN 9600X ; ( Note, for 'A1, we must download exactly 256 bytes, regardless of actual length of program.) ( Some possibly useful macros) : PSHD, ( macro) PSHB, PSHA, ; : PULD, ( macro) PULA, PULB, ; : DSTACK, ( macro) TSY, TXS, ; : RSTACK, ( macro) TSX, TYS, ; : LIT, ( macro) ( u -) #, LDD, DEX, DEX, 0 ,X STD, ; -------------------------------------------------------------------------------- /extras/3ins4th/mond0.scr: -------------------------------------------------------------------------------- 1 | Copyright 1994-1997, 2007 Frank C. Sergeant. See license20040130.txt or http://pygmy.utoh.org/license.html I can be reached by email at frank@pygmy.utoh.org. MOND0.SCR & D0.COM are designed to work with the MC68HC11D0. MONE1.SCR & E1.COM are designed to work with the MC68HC11E1. MONA1.SCR & A1.COM are designed to work with the MC68HC11A1. MODE COM1:9600,8,N,1 may be necessary in your AUTOEXEC.BAT file. Note, MONITOR is limited to downloading a routine 256 bytes long. Some adjustments will need to be made to download a longer program, for example, into external RAM. (Easily enough done with a short routine downloaded thru MONITOR, which then downloads the longer code to external RAM.) ( Load block for 'HC11 "3-instruction Forth" MONITOR for 'D0 ) ( This assumes MOND0.SCR has been opened at unit 10 ) xxxxx LOAD ( serial port support) xxxxx LOAD ( hc11 assembler) 10002 10005 THRU ( Note block 10005 must be loaded twice!) 10005 10012 THRU ( General MONITOR related words) ( MONITOR a small monitor for 'hc11) ( $1000) 0 CONSTANT 'REG ( These values apply only) ( 0) $40 CONSTANT 'RAM ( to the 'D0 version) : REG: CREATE C, DOES> C@ 'REG + ; ( above word used on next block to define registers) ( Define various RAM-based registers) $28 REG: SPCR ( serial peripheral control register) $2B REG: BAUD ( serial communications baud-rate register) $2E REG: SCSR ( serial communications status register) $2F REG: SCDR ( serial communications data register) $39 REG: OPTION ( watchdog time-out period) $3A REG: COP ( watchdog timer reset register) $3C REG: HPRIO ( for selecting external RAM) $00 REG: PORTA $26 REG: PACTL $0E REG: TCNT $04 REG: PORTB $06 REG: DDRB $18 REG: TOC2 $03 REG: PORTC $07 REG: DDRC $23 REG: TFLG1 $08 REG: PORTD $09 REG: DDRD $24 REG: TMSK2 ( MONITOR 'HC11 addresses ) VARIABLE 'RX ( VARIABLE 'GET-ADDR ) VARIABLE 'TX ( VARIABLE 'C@ VARIABLE 'C! ) VARIABLE 'MONITOR VARIABLE OFFSET VARIABLE MONITOR-LENGTH VARIABLE 'CODE : >MON ( a - a') 'MONITOR @ - 'RAM + ; : SET-OFFSET ( -) HERE OFFSET ! ; : >ABS ( a - a') OFFSET @ - 'CODE @ + ; : RX, ( macro) 'RX @ DIR JSR, ; : TX, ( macro) 'TX @ DIR JSR, ; : ADDR-IN, ( macro) RX, TAB, RX, ; ( leaves addr in regD) : COP, ( reset watchdog timer) PSHB, $55 #, LDB, COP ,Y STB, $AA #, LDB, COP ,Y STB, PULB, ; ( MONITOR ** this block must be loaded twice ** ) CODE MONITOR HERE 'MONITOR ! 'REG #, LDY, CLRA, SPCR #) STA, ( un-wire-OR port D) BEGIN, RX, TAB, ( ie save count) 'CODE @ #, LDX, BEGIN, RX, 0 ,X STA, INX, DECB, 0=, UNTIL, 'CODE @ DIR JSR, AGAIN, ( rx) ( rx) HERE >MON 'RX ! BEGIN, ( COP,) $20 #, LDA, SCSR #) BITA, <>, UNTIL, SCDR ,Y LDA, ( read byte from PC) RTS, ( tx) HERE >MON 'TX ! HERE $80 SCSR ,Y BRCLR, ( wait for TDRE) SCDR ,Y STA, ( send byte to PC) RTS, END-CODE HERE ' MONITOR - DUP MONITOR-LENGTH ! ( len) 'RAM + 'CODE ! ( 58 bytes with COP, and 46 without ) ( download monitor to 'HC11 board ) : .OUT ( a # -) FOR C@+ SER-OUT NEXT DROP ; : ?EMIT ( c -) DUP $20 $7F BETWEEN IF EMIT ELSE . THEN ; : .OUTE ( a # -) FOR DUP C@ SER-OUT SER-IN ?EMIT 1+ NEXT DROP ; : ADDR-OUT ( a -) BYTES ( lsb msb) SWAP SER-OUT SER-OUT ; ( Compile 'HC11 code routines in PC's memory, which can be downloaded later to 'HC11 and executed ) : XCODE: CREATE ( - a) HERE 0 C, ( save space for routine's length) DOES> C@+ DUP SER-OUT .OUT ; ( send length byte & machine code to 'hc11 board) : XEND ( addr-of-length-byte -) HERE OVER - 1- SWAP C! ; ( this fills in the length byte, now that it is known) XCODE: (X@ ADDR-IN, XGDX, 0 ,X LDA, TX, RTS, XEND : 1/2-X@ ( a -) (X@ ADDR-OUT ; ( used to verify connection) : X@ ( a - c) 1/2-X@ SER-IN ; XCODE: (X! ADDR-IN, XGDX, RX, 0 ,X STA, RTS, XEND : X! ( c a -) (X! ADDR-OUT SER-OUT ; XCODE: (XCALL ADDR-IN, XGDX, 0 ,X JSR, RTS, XEND : XCALL ( a -) ADDR-OUT ; : XDUMP ( a - a') HEX CR DUP 4 U.R 2 SPACES DUP 2 FOR 8 FOR DUP X@ 3 U.R 1+ NEXT SPACE NEXT DROP 2 SPACES ( a) 2 FOR 8 FOR DUP X@ DUP $20 $7F WITHIN NOT IF DROP $2E THEN EMIT 1+ NEXT SPACE NEXT ; : XDU ( a # - a') FOR ?SCROLL XDUMP NEXT DROP ; : X2@ ( u - v) DUP X@ $100 * SWAP 1+ X@ + ; : X2! ( u a -) PUSH BYTES ( lsb msb) R@ X! ( lsb) POP 1+ X! ; ( Adjust baud rate on both PC and 'HC11, assumes 8 MHz crystal) : 1200X ( -) $33 BAUD X! 50 MS 1200 BPS ; : 9600X ( -) $30 BAUD X! 50 MS 9600 BPS ; ( For 8 MHz xtal ) : RS ( -) -DTR 100 MS +DTR 100 MS 1200 BPS ; ( reset) : DL8 ( -) RS $FF SER-OUT ['] MONITOR ( a) MONITOR-LENGTH @ ( a #) ( use this for 'D0 & 'E1) ( 256 ( a #) ( use this for 'A1 ) ( a #) .OUT 150 MS RESET-SER-IN 9600X ; ( Note, for 'A1, we must download exactly 256 bytes, regardless of actual length of program.) ( Some possibly useful macros) : PSHD, ( macro) PSHB, PSHA, ; : PULD, ( macro) PULA, PULB, ; : DSTACK, ( macro) TSY, TXS, ; : RSTACK, ( macro) TSX, TYS, ; : LIT, ( macro) ( u -) #, LDD, DEX, DEX, 0 ,X STD, ; -------------------------------------------------------------------------------- /extras/3ins4th/mone1.scr: -------------------------------------------------------------------------------- 1 | Copyright 1994-1997, 2007 Frank C. Sergeant. See license20040130.txt or http://pygmy.utoh.org/license.html I can be reached by email at frank@pygmy.utoh.org. MOND0.SCR & D0.COM are designed to work with the MC68HC11D0. MONE1.SCR & E1.COM are designed to work with the MC68HC11E1. MONA1.SCR & A1.COM are designed to work with the MC68HC11A1. MODE COM1:9600,8,N,1 may be necessary in your AUTOEXEC.BAT file. Note, MONITOR is limited to downloading a routine 256 bytes long. Some adjustments will need to be made to download a longer program, for example, into external RAM. (Easily enough done with a short routine downloaded thru MONITOR, which then downloads the longer code to external RAM.) ( Load block for 'HC11 "3-instruction Forth" MONITOR for 'E1 ) ( This assumes MONE1.SCR has been opened at unit 10 ) xxxxx LOAD ( serial port support) xxxxx LOAD ( hc11 assembler) 10002 10005 THRU ( Note block 10005 must be loaded twice!) 10005 10012 THRU ( General MONITOR related words) ( MONITOR a small monitor for 'hc11) $1000 CONSTANT 'REG ( These values apply only) 0 CONSTANT 'RAM ( to the 'E0 & 'A1 versions) : REG: CREATE C, DOES> C@ 'REG + ; ( above word used on next block to define registers) ( Define various RAM-based registers) $28 REG: SPCR ( serial peripheral control register) $2B REG: BAUD ( serial communications baud-rate register) $2E REG: SCSR ( serial communications status register) $2F REG: SCDR ( serial communications data register) $39 REG: OPTION ( watchdog time-out period) $3A REG: COP ( watchdog timer reset register) $3C REG: HPRIO ( for selecting external RAM) $00 REG: PORTA $26 REG: PACTL $0E REG: TCNT $04 REG: PORTB $06 REG: DDRB $18 REG: TOC2 $03 REG: PORTC $07 REG: DDRC $23 REG: TFLG1 $08 REG: PORTD $09 REG: DDRD $24 REG: TMSK2 ( MONITOR 'HC11 addresses ) VARIABLE 'RX ( VARIABLE 'GET-ADDR ) VARIABLE 'TX ( VARIABLE 'C@ VARIABLE 'C! ) VARIABLE 'MONITOR VARIABLE OFFSET VARIABLE MONITOR-LENGTH VARIABLE 'CODE : >MON ( a - a') 'MONITOR @ - 'RAM + ; : SET-OFFSET ( -) HERE OFFSET ! ; : >ABS ( a - a') OFFSET @ - 'CODE @ + ; : RX, ( macro) 'RX @ DIR JSR, ; : TX, ( macro) 'TX @ DIR JSR, ; : ADDR-IN, ( macro) RX, TAB, RX, ; ( leaves addr in regD) : COP, ( reset watchdog timer) PSHB, $55 #, LDB, COP ,Y STB, $AA #, LDB, COP ,Y STB, PULB, ; ( MONITOR ** this block must be loaded twice ** ) CODE MONITOR HERE 'MONITOR ! 'REG #, LDY, CLRA, SPCR #) STA, ( un-wire-OR port D) BEGIN, RX, TAB, ( ie save count) 'CODE @ #, LDX, BEGIN, RX, 0 ,X STA, INX, DECB, 0=, UNTIL, 'CODE @ DIR JSR, AGAIN, ( rx) ( rx) HERE >MON 'RX ! BEGIN, ( COP,) $20 #, LDA, SCSR #) BITA, <>, UNTIL, SCDR ,Y LDA, ( read byte from PC) RTS, ( tx) HERE >MON 'TX ! HERE $80 SCSR ,Y BRCLR, ( wait for TDRE) SCDR ,Y STA, ( send byte to PC) RTS, END-CODE HERE ' MONITOR - DUP MONITOR-LENGTH ! ( len) 'RAM + 'CODE ! ( 58 bytes with COP, and 46 without ) ( download monitor to 'HC11 board ) : .OUT ( a # -) FOR C@+ SER-OUT NEXT DROP ; : ?EMIT ( c -) DUP $20 $7F BETWEEN IF EMIT ELSE . THEN ; : .OUTE ( a # -) FOR DUP C@ SER-OUT SER-IN ?EMIT 1+ NEXT DROP ; : ADDR-OUT ( a -) BYTES ( lsb msb) SWAP SER-OUT SER-OUT ; ( Compile 'HC11 code routines in PC's memory, which can be downloaded later to 'HC11 and executed ) : XCODE: CREATE ( - a) HERE 0 C, ( save space for routine's length) DOES> C@+ DUP SER-OUT .OUT ; ( send length byte & machine code to 'hc11 board) : XEND ( addr-of-length-byte -) HERE OVER - 1- SWAP C! ; ( this fills in the length byte, now that it is known) XCODE: (X@ ADDR-IN, XGDX, 0 ,X LDA, TX, RTS, XEND : 1/2-X@ ( a -) (X@ ADDR-OUT ; ( used to verify connection) : X@ ( a - c) 1/2-X@ SER-IN ; XCODE: (X! ADDR-IN, XGDX, RX, 0 ,X STA, RTS, XEND : X! ( c a -) (X! ADDR-OUT SER-OUT ; XCODE: (XCALL ADDR-IN, XGDX, 0 ,X JSR, RTS, XEND : XCALL ( a -) ADDR-OUT ; : XDUMP ( a - a') HEX CR DUP 4 U.R 2 SPACES DUP 2 FOR 8 FOR DUP X@ 3 U.R 1+ NEXT SPACE NEXT DROP 2 SPACES ( a) 2 FOR 8 FOR DUP X@ DUP $20 $7F WITHIN NOT IF DROP $2E THEN EMIT 1+ NEXT SPACE NEXT ; : XDU ( a # - a') FOR ?SCROLL XDUMP NEXT DROP ; : X2@ ( u - v) DUP X@ $100 * SWAP 1+ X@ + ; : X2! ( u a -) PUSH BYTES ( lsb msb) R@ X! ( lsb) POP 1+ X! ; ( Adjust baud rate on both PC and 'HC11, assumes 8 MHz crystal) : 1200X ( -) $33 BAUD X! 50 MS 1200 BPS ; : 9600X ( -) $30 BAUD X! 50 MS 9600 BPS ; ( For 8 MHz xtal ) : RS ( -) -DTR 100 MS +DTR 100 MS 1200 BPS ; ( reset) : DL8 ( -) RS $FF SER-OUT ['] MONITOR ( a) MONITOR-LENGTH @ ( a #) ( use this for 'D0 & 'E1) ( 256 ( a #) ( use this for 'A1 ) ( a #) .OUT 150 MS RESET-SER-IN ( 9600X ) ; ( Note, for 'A1, we must download exactly 256 bytes, regardless of actual length of program.) ( Some possibly useful macros) : PSHD, ( macro) PSHB, PSHA, ; : PULD, ( macro) PULA, PULB, ; : DSTACK, ( macro) TSY, TXS, ; : RSTACK, ( macro) TSX, TYS, ; : LIT, ( macro) ( u -) #, LDD, DEX, DEX, 0 ,X STD, ; -------------------------------------------------------------------------------- /extras/3ins4th/readme: -------------------------------------------------------------------------------- 1 | 3-Instruction Forth for the 'HC11 2 | 3 | 4 | This package is copyright 1994-1997,2007 by Frank Sergeant. 5 | 6 | (minor updates to packaging, license, addresses, etc April, 2007) 7 | 8 | For license, see the license20040130.txt file included with the Pygmy 9 | Forth version 1.7 or http://pygmy.utoh.org/license.html. 10 | 11 | 12 | MONITOR.TXT 13 | 14 | is a copy of my 3-Instruction Forth article that appeared in 15 | the 1991 FORML Conference Proceedings (published by the 16 | Forth Interest Group). 17 | 18 | MOND0.SCR 19 | MONA1.SCR 20 | MONE1.SCR 21 | 22 | contain the source code for the 3-instruction Forth for 23 | 3 variants of the Motorola 68HC11 microprocessor. The minor 24 | differences relate to where the different versions of the 25 | microprocessor map their memory-mapped registers and to how 26 | they expect to receive their initial program load in the 27 | bootstrap mode. The monitors included here take 28 | up even less space in the 'HC11's memory than the original 29 | version in the article. (In specialized cases, I have 30 | reduced the size of the monitor even further -- down to 31 | only 32 bytes.) 32 | 33 | 34 | DEMO.SCR 35 | 36 | contains a small demonstration of how the 3-instruction 37 | Forth might be used to control i/o lines. 38 | 39 | 40 | Frank Sergeant 41 | frank@pygmy.utoh.org (permanent email address) 42 | http://pygmy.utoh.org 43 | -------------------------------------------------------------------------------- /extras/6811asm.dow: -------------------------------------------------------------------------------- 1 | *** Version 2 of Forth assembler for Motorola 68HC11 *** copyright 1989-2007 Frank C. Sergeant Warning: All addressing modes (except inherent) now require an explicitmode indicator. Even the extended mode requires the symbol #) now. In the previous version the extended mode was the default and did not need a mode indicator. The order of the parameters for the BRCLR, BRSET, BCLR, BSET, instructions has also changed. Now, the mask comes before the operand. ( load screen for 68HC11 assembler ) I've been opening these source and shadow files as unit #12, e.g. " 6811ASM.SCR" 12 OPEN " 6811ASM.DOW" 13 OPEN Then creating an executable named ASM11.COM, or some such, for my working version for 'HC11 code generation, e.g. SAVE ASM11.COM If you open 6811ASM.SCR at some other unit number, you will needto change the 12002 12011 THRU to something appropriate. variables and addressing modes INTEL set this to true if running on an Intel machine or to false if running on a Motorola machine. BYTES ( xxyy - yy xx) FLIP ( hhll - llhh) reverse byte order to convert from big-endian to little-endian or vice versa BYTES and FLIP are now loaded in pygmy.scr version 1.7 W, ( u -) same as , but optionally adjusts for byte order. Mode examples: immediate direct indexed extended 45 #, LDA, $C2 DIR LDX, 3 ,X LDA, $1234 #) LDA, $1234 #, LDD, 7 DIR JSR, 18 ,Y LDS, $1234 #) JSR, inherent op codes These instructions do not require any explicit operands. The TEST, instruction is commented out, as it puts the CPU into the 16-bit counter mode until it is reset, and so is useless formost programs. inherent op codes - continued The opcodes in the first group are each one byte long. The opcodes in the second group are each two bytes long. opcode, ( xxyy | 00yy -) commas in the opcode as either one byte or two, depending on whether the most signifcant byte is non-zero. operand, ( u mode -) If mode is extended, comma in two bytes, else just one byte. operand2, ( u mode -) If mode is either extended or immediate, comma in two bytes, else just one byte. e.g. $1234 #, LDD, 8 ,Y STS, $0017 #) STD, 17 DIR STD, Note, the last 2 store D instructions perform the same function, but the 1st takes 3 bytes and the 2nd takes 2 bytes. 8-bit operands e.g. $34 #, SUBA, 0 DIR LDA, $50 ,Y DEC, 1234 #) LDA, ?IN-RANGE ( distance - distance) aborts with an error message ifthe destination of the branch instruction is too far away. In general, you would not use these branch instructions, but would let the assembler generate them for you automatically by usings the structured conditionals, such as TSTA, 0=, IF, COUNTER #) INC, THEN, But, BEWARE! the structured conditional form does not test for the destination in-range. Keep your routines short! Bit instructions. BRCLR, & BRSET, are conditional branch instructions that branch based on an operand's (masked) bit pattern. They do not alter the bits of the operand byte. The parameters passed to this instruction are . The operand must be expressed as either a positive offset plus index register (e.g. 7 ,X) or as a page 0 direct address (e.g. 18 DIR). See examples on source block. BCLR, & BSET, have a similar form to the BRCLR, & BRSET, instructions, but no destination address is used. These instructions do affect the bits in the operand byte. Note, the mask comes before the operand. Here is a table showing the value of the prebyte needed for each addressing mode of the "weird" instructions. imm dir ext ,X ,Y CPD 1A 1A 1A 1A CD LDX 00 00 00 00 CD CPX 00 00 00 00 CD STX xx 00 00 00 CD CPY 18 18 18 1A 18 LDY 18 18 18 1A 18 STY xx 18 18 1A 18 cc stands for "condition code" NOT, ( cc - opposite-cc) inverts the condition to be tested. These conditions, in conjunction with the words on the followingblock, allow doing such things as this in assembly language: CS, IF, ELSE, THEN, or BEGIN, PORTC DIR LDA, $1B #, CMPA, 0=, UNTIL, Note: IF, ELSE, & THEN, are not the same as IF ELSE & THEN. This would be a good place to put examples of using the structured assembler words. Here is an example of how to create a simple routine. CODE .reg ( save the value of 4 registers at a buffer at $8500) $8500 DUP #) STD, 2 + DUP #) STX, 2 + DUP #) STY, 2 + #) STS, RTS, END-CODE Note, the machine code is for the 'HC11, so DO NOT try to execute .reg on the PC. Here are some examples of how to write an 'HC11 macro. Think ofthese as extensions to the 'HC11 assembler & the 'HC11 instr set: PSHD, ( macro) PSHB, PSHA, ; : PULD, ( macro) PULA, PULB, ; THE END -------------------------------------------------------------------------------- /extras/6811asm.scr: -------------------------------------------------------------------------------- 1 | *** Version 2 of Forth assembler for Motorola 68HC11 *** Copyright 1989-2007 Frank C. Sergeant. See license20040130.txt or http://pygmy.utoh.org/license.html I can be reached by email at frank@pygmy.utoh.org. See the file 6811ASM.DOC for more info and important DISCLAIMER.See the file 6811ASM.DOW for shadow block comments. In editor, Ctrl-A switches between source and shadow blocks. This version corrects some errors, especially the STX, & STY, (extended mode) instructions. This runs under Pygmy on IBM PC and creates 68HC11 machine code.To run on a 68HC11, change the value of INTEL to zero. This is not fully tested. Use at your own risk (naturally). ( load block for 68HC11 assembler ) ( see notes on previous screen ) 12002 12012 THRU HEX ( variables and addressing modes) -1 CONSTANT INTEL ( change to zero for Motorola ) : W, ( n -) INTEL IF FLIP THEN , ; ( Modes ) 0 CONSTANT #, ( immediate ) 10 CONSTANT DIR ( direct ) 20 CONSTANT ,X ( indexed by X) 1820 CONSTANT ,Y ( indexed by Y) 30 CONSTANT #) ( extended, i.e. "immediate indirect" ) HEX ( inherent op codes ) : INH ( opcode -) ( -) CREATE C, DOES> C@ C, ; ( one-byte inherent opcodes) 1B INH ABA, 3A INH ABX, 05 INH ASLD, 11 INH CBA, 0C INH CLC, 0E INH CLI, 0A INH CLV, 19 INH DAA, 34 INH DES, 09 INH DEX, 03 INH FDIV, 02 INH IDIV, 31 INH INS, 08 INH INX, 05 INH LSLD, 04 INH LSRD, 3D INH MUL, 01 INH NOP, 36 INH PSHA, 37 INH PSHB, 3C INH PSHX, 32 INH PULA, 33 INH PULB, 38 INH PULX, 3B INH RTI, 39 INH RTS, 10 INH SBA, 0D INH SEC, 0F INH SEI, 0B INH SEV, CF INH STOP, 3F INH SWI, 16 INH TAB, 06 INH TAP, 17 INH TBA, ( 00 INH TEST, ) 07 INH TPA, 30 INH TSX, 35 INH TXS, 3E INH WAI, 8F INH XGDX, 48 INH ASLA, 58 INH ASLB, 47 INH ASRA, 57 INH ASRB, 4F INH CLRA, 5F INH CLRB, 43 INH COMA, HEX ( inherent op codes - continued ) 53 INH COMB, 4A INH DECA, 5A INH DECB, 4C INH INCA, 5C INH INCB, 48 INH LSLA, 58 INH LSLB, 44 INH LSRA, 54 INH LSRB, 40 INH NEGA, 50 INH NEGB, 49 INH ROLA, 59 INH ROLB, 46 INH RORA, 56 INH RORB, 4D INH TSTA, 5D INH TSTB, : INH2 ( opcode -) ( -) CREATE , DOES> @ W, ; ( two byte inherent op codes ) 183A INH2 ABY, 1809 INH2 DEY, 1808 INH2 INY, 183C INH2 PSHY, 1838 INH2 PULY, 1830 INH2 TSY, 1835 INH2 TYS, 188F INH2 XGDY, HEX ( helper words plus simple 16-bit operand instructions ) : opcode, ( xxyy | 00yy -) BYTES ( ls ms) ?DUP IF C, THEN C, ; : operand, ( u mode -) #) = IF ( extended) W, ELSE C, THEN ; : operand2, ( u mode -) DUP #) = SWAP #, = OR IF ( ext | imm) W, ELSE C, THEN ; ( any registers or immediate operands are 16 bits) : OP2 ( c -) ( operand mode -) CREATE C, DOES> C@ OVER + opcode, operand2, ; C3 OP2 ADDD, CC OP2 LDD, 8E OP2 LDS, CD OP2 STD, 83 OP2 SUBD, 8F OP2 STS, HEX ( 8-bit operands) : OP3 ( c -) ( operand mode -) CREATE C, DOES> C@ OVER + opcode, operand, ; 89 OP3 ADCA, C9 OP3 ADCB, 8B OP3 ADDA, CB OP3 ADDB, 84 OP3 ANDA, C4 OP3 ANDB, 85 OP3 BITA, C5 OP3 BITB, 81 OP3 CMPA, C1 OP3 CMPB, 88 OP3 EORA, C8 OP3 EORB, 86 OP3 LDA, C6 OP3 LDB, 8A OP3 ORA, CA OP3 ORB, 82 OP3 SBCA, C2 OP3 SBCB, 87 OP3 STA, C7 OP3 STB, 80 OP3 SUBA, C0 OP3 SUBB, 48 OP3 ASL, 47 OP3 ASR, 4F OP3 CLR, 43 OP3 COM, 4A OP3 DEC, 4C OP3 INC, 4E OP3 JMP, 8D OP3 JSR, 48 OP3 LSL, 44 OP3 LSR, 40 OP3 NEG, 49 OP3 ROL, 46 OP3 ROR, 4D OP3 TST, ( relative branch & call instructions) : IN-RANGE? ( distance - distance flag) DUP -128 127 BETWEEN ( distance flag) ; : ?IN-RANGE ( distance - distance) IN-RANGE? NOT ( distance flag) ABORT" out of range " ; : REL ( c -) ( a -) CREATE C, DOES> C@ C, HERE 1+ - ?IN-RANGE C, ; HEX 24 REL BCC, 25 REL BCS, 27 REL BEQ, 2C REL BGE, 2E REL BGT, 22 REL BHI, 24 REL BHS, 2F REL BLE, 25 REL BLO, 23 REL BLS, 2D REL BLT, 2B REL BMI, 26 REL BNE, 2A REL BPL, 20 REL BRA, 21 REL BRN, 8D REL BSR, 28 REL BVC, 29 REL BVS, HEX ( Bit branch, set, and clear instructions) : BITREL, ( destination mask operand mode opcode -) + DUP ,X ( ie $20) AND 2/ 2/ 2/ - opcode, ( dest mask operand) C, C, ( dest) HERE 1+ - ?IN-RANGE C, ; : BRCLR, 03 BITREL, ; ( e.g. HERE $20 SCSR DIR BRSET, ) : BRSET, 02 BITREL, ; ( or HERE $80 SCSR ,Y BRSET, ) : BIT, ( mask operand mode opcode -) + DUP ,X ( ie $20) AND 2/ 2/ - opcode, ( mask operand) C, C, ; : BCLR, 05 BIT, ; ( e.g. $80 SCSR DIR BCLR, ) : BSET, 04 BIT, ; ( or $80 3 ,Y BCLR, ) HEX ( The weird ones) ( 16-bit operand instructions) : OP4 ( c -) ( operand mode -) CREATE , DOES> @ OVER + OVER ,Y = IF 00FF AND CD00 OR THEN opcode, operand2, ; 1A83 OP4 CPD, 00CE OP4 LDX, 008C OP4 CPX, 00CF OP4 STX, : OP5 ( c -) ( operand mode -) CREATE , DOES> @ OVER + OVER ,X = 200 AND + ( ?make prebyte = 1A) OVER ,Y = 1800 AND - ( ?make prebyte = 18) opcode, operand2, ; 188C OP5 CPY, 18CE OP5 LDY, 18CF OP5 STY, HEX ( "structured" assembler) : cc ( c -) ( - c) CONSTANT ; 24 cc CC, 25 cc CS, 26 cc <>, 27 cc 0=, 2C cc >=, 2D cc <, 2E cc >, 2F cc <=, 22 cc U>, 23 cc U<=, 2A cc PL, 2B cc 0<, 20 cc ALWAYS, 21 cc NEVER, 28 cc -OV, 29 cc OV, : NOT, ( cc - opposite-cc) 1 XOR ; ( "structured" assembler continued ) HEX : IF, ( cc - here ) NOT, C, HERE 0 C, ; : THEN, ( back-addr -) HERE OVER 1+ - SWAP C! ; : ELSE, ( back-addr - here) HERE OVER 1- - SWAP C! ALWAYS, C, HERE 0 C, ; : BEGIN, ( - here) HERE ; : AGAIN, ( here -) BRA, ; ( ** better be in range!! ** ) : WHILE, ( here1 cc - here1 here2) IF, SWAP ; : REPEAT, ( here1 here2 -) AGAIN, THEN, ; : UNTIL, ( here cc -) NOT, C, HERE 1+ - C, ; ( END-CODE << >> ) EXIT ( The regular Pygmy 80x86 assembler words << and >> still work for use with the 6811ASM, but the following equivalents may be needed if loading the 6811ASM in other environments ) : END-CODE ( -) ; : CODE ( -) HEAD ; : << ( - a depth) HERE DEPTH ; ( for dumping code to screen) : >> ( a depth -) ( ditto) DEPTH 1- - ABORT" bad stack" CR BASE @ PUSH HEX DUP 4 U.R SPACE HERE OVER - FOR C@+ 3 U.R NEXT DROP POP BASE ! SPACE ; To examine snippets of machine code, bracket your assembly code with << and >>, e.g. << $1B #, CMPA, >> -------------------------------------------------------------------------------- /extras/6811asm.txt: -------------------------------------------------------------------------------- 1 | 68HC11 Assembler, version 2 2 | 3 | Copyright 1989,1997,2007 Frank C. Sergeant. 4 | 5 | For license, see the license20040130.txt file included with the Pygmy 6 | Forth version 1.7 or http://pygmy.utoh.org/license.html. 7 | 8 | 9 | This is a Forth-style assembler designed to run under Pygmy 10 | Forth (v1.4 or above) on an IBM PC or clone. It generates 11 | machine code for the Motorola 68HC11 microprocessor. It is 12 | easily adapted to run under Pygmy on the 68HC11. 13 | 14 | 15 | ----------------------------------------------------- Files 16 | 17 | There are three associated files: 18 | 1. 6811ASM.DOC - the text file you are now reading 19 | 2. 6811ASM.SCR - the Forth block file that contains 20 | the source code. 21 | 3. 6811ASM.DOW - the Forth block file that contains 22 | the shadow (documentation) blocks. 23 | 24 | 25 | ------------------------------------ Changes from Version 1 26 | 27 | Version 1 did not generate correct machine code for some 28 | addressing modes of the "weird" instructions, such as the 29 | extended addressing mode of STX, and STY,. Hopefully, this 30 | has been fixed in version 2. 31 | 32 | Version 1 kept the mode information in a variable. Version 33 | 2 keeps the mode information on the stack. Related to this 34 | change, you must now indicate extended mode with #) 35 | discussed below. 36 | 37 | In Version 1, if no mode indicator was used, the extended 38 | mode was used by default. In this version, each of the 39 | modes (immediate, extended, direct, indexed by X, indexed by 40 | Y) must be explicitly indicated. The symbol #) is used to 41 | indicate extended mode. This comes to me from an article 42 | written by Charles Curly, I believe, where he describes this 43 | as meaning "immediate indirect," which conveys the essence 44 | of the mode very well, at least to me. See examples below 45 | under Modes. 46 | 47 | The ordering of the operands for BRCLR, BRSET, BCLR, & BSET, 48 | have changed. Now, the mask must precede the address of the 49 | operand to be tested or altered. 50 | 51 | 52 | ------------------------------------------------ Byte Order 53 | 54 | The 68HC11 and the 80x86 use different byte orders for 55 | 16-bit quantities. Thus, this assembler uses W, to comma in 56 | (comma down?) each byte of a double-byte in the correct 57 | order. W, looks to the constant INTEL to see what to do. 58 | INTEL should have the value -1 (true) when the assembler is 59 | running on a PC, but 0 (false) when the assembler is running 60 | on the 68HC11. 61 | 62 | This assembler should also work for the 6800, 6802, 6808, 63 | 6801, and 6803, providing you do not use extra features 64 | present only in the 68HC11. In other words, the 68HC11's 65 | instruction set is a superset of the instruction sets of the 66 | 6800, 6802, 6808, 6801, and 6803. 67 | 68 | 69 | ------------------------------------- Instruction Mnemonics 70 | 71 | The assembly mnemonics typically end with a comma. This 72 | serves three purposes. It distinguishes the assembly 73 | language versions of words such as BEGIN, AGAIN, IF, #, from 74 | the similarly named Forth words. Also, it suggests they 75 | "comma" something (namely machine code) into the dictionary. 76 | The comma also marks the end of a series of words related to 77 | a single instruction, although the immediate mode symbol is 78 | an exception to this: it ends in a comma, but does not 79 | indicate the end of a phrase belonging to a single 80 | instruction. Perhaps renaming #, to ## would be better. 81 | 82 | Motorola made an error in suggesting that the mnemonics for 83 | loading and storing accumulators A & B should be LDAA, LDAB, 84 | STAA, & STAB. (Of these, though, STAB -- it sounds so 85 | violent -- is my favorite.) Clearly the superfluous middle 86 | "A" (which stands for "accumulator") should be omitted. 87 | Thus, this and all other right-thinking assemblers use LDA, 88 | LDB, STA, STB, instead. Motorola implicitly admits this 89 | error by their choice of mnemonics for the load accumulator 90 | D and store accumulator D mnemonics, i.e. LDD and STD. (I 91 | should consider factoring out the registers and shortening 92 | the mnemonic to just L or S, as in $FF #, A L, but am not 93 | prepared to go that far at the moment.) 94 | 95 | 96 | ---------------------- Urges I Have Resisted for the Moment 97 | 98 | Using lower case for the mnemonics, and factoring the 99 | register names (e.g. $45 #, b ld, $1234 #) x st, instead 100 | of $45 #, LDB, $1234 #) STX,) were resisted. 101 | 102 | 103 | ----------------------------------------------------- Modes 104 | 105 | Each mode, other than inherent, must be indicated 106 | explicitly. Here are some examples: 107 | 108 | $FF #, LDA, ( load immediate into the A register) 109 | $1234 #, LDX, ( load immediate into the X register) 110 | $1234 #) LDX, ( extended mode, ie load X from the 111 | contents of address $1234 & $1235) 112 | $34 DIR LDX, ( direct mode, ie load X from the 113 | contents of address $0034 & $0035) 114 | 7 ,X LDA, ( indexed by register X, ie load 115 | register A from the byte whose 116 | address is 7 plus the contents 117 | of register X) 118 | 15 ,Y STB, ( indexed by register Y, ie store 119 | register B into the byte whose 120 | address is 15 plus the contents 121 | of register Y) 122 | 123 | The unusual convention here is how extended mode is 124 | specified. Watch out for this until you get used to it. 125 | Also, special attention must be paid to the instructions 126 | BRCLR, BRSET, BCLR, & BSET,. See the source and shadow 127 | blocks for info on this. After loading the assembler, type 128 | V BRCLR, to jump into the editor at the location of the 129 | source code for the BRCLR, instruction, then press Ctrl-A to 130 | move back and forth between the source block and the shadow 131 | block. You can do this with any any instruction you need 132 | more information about. 133 | 134 | 135 | ---------------- Bug Reports, Comments, & How to Contact Me 136 | 137 | If you find any case where this assembler fails to generate 138 | the correct 68HC11 machine code, please send the details to 139 | me by email at frank@pygmy.utoh.org. 140 | 141 | 142 | 143 | END 144 | -------------------------------------------------------------------------------- /extras/cfth/bgi.dow: -------------------------------------------------------------------------------- 1 | Experiments with co-ordinating C and Forth Copyright 1995 Frank Sergeant frank@pygmy.utoh.org http://pygmy.utoh.org See license file license20040130.txt or http://pygmy.utoh.org/license.html ( Load block) 2VARIABLE creates a 4-byte variable that can hold a C "far pointer" CTABLE holds a seg offset (far pointer) address of the table in the C wrapper. The table contains the far pointers to various C functions and variables ( Macros to make building a call to a C routine easy) PUSH-ARGS, is an assembler macro that lays down the code to move parameters from Forth's data stack to Forth's return stack. When the C routine is called, Forth's return stack will be used as C's parameter stack. GET-RESULT, is an assembler macro that lays down the code to move the result (if any) returned by the C function from register AX or registers DX:AX to Forth's data stack. CDECL: This is a defining word that builds a CODE word to call a C function. The index is used at run time to look up the address of the C function in a table in the C program (the address of the table is stored in CTABLE). The #in parameter tells CDECL: how many 16-bit words to move from the data stack to C's stack prior to calling the C function. The #out parameter tells CDECL: how many 16-bit words to move from AX or DX:AX to Forth's data stack after the C function returns. CVAR: This is similar to CDECL: but is used for variables instead of functions. It defines a word that returns the seg offset address of a C variable. For example, if the 0th item in the table is an integer j, 0 CVAR: J defines the Forth word J which will return the seg and offset of the C integer j. J L@ would return the current value of that integer. 17 J L! would change the value to 17. This block and the next define Forth words to access all of the variables and functions in the C program's pointers table. These two blocks and the C program's pointers table must be keptsynchronized! J accesses the C integer j just to illustrate the mechanism. The sample program displays the value of j upon termination. You could play with setting it to different values in Forth, then see what value C displays upon termination: 17 J L! 0 #BYE 32 J L! 5 #BYE etc. Perhaps the most important point to notice is that the Forth stack comment shows the parameters in the very same order as the C function prototypes. If in C you would say circle (200, 300, 75); then in Forth you would say 200 300 75 circle For more information about these particular graphic functions, see Borland's BGI documentation. These are various examples of accessing the graphics functions from Forth. Try typing TST1 to see them in action. Note! It is unlikely that your Borland graphic drivers are on drive G: as mine are. Be sure to change the path in the definition of INIT-GPH before running these examples! This block contains more examples of accessing the BGI graphics routines. -------------------------------------------------------------------------------- /extras/cfth/bgi.scr: -------------------------------------------------------------------------------- 1 | Experiments with co-ordinating C and Forth Copyright 1995 Frank Sergeant frank@pygmy.utoh.org http://pygmy.utoh.org See license file license20040130.txt or http://pygmy.utoh.org/license.html ( Load block) 4002 4009 THRU SAVE PYGMYC.COM ( CTABLE holds the address of the table of addresses in C) : 2VARIABLE ( -) ( - a) VARIABLE 0 , ; 2VARIABLE CTABLE ( Macros to make building a call to a C routine easy) : PUSH-ARGS, ( #in -) ( move parms to Forth's return stack, ie C's stack to be) FOR BX POP, SWITCH, BX PUSH, SWITCH, NEXT ( off seg) ; : GET-RESULT, ( #out -) DUP 0= IF DROP BX POP, ( will refill TOS) EXIT THEN 2 = IF DX PUSH, THEN AX BX MOV, ( result to TOS) ; ( Use this to define a word which calls a C routine) : CDECL: ( index #in #out -) CODE SWAP BP AX MOV, ( save Forth's rstk ptr) BX PUSH, ( put TOS on real stack) PUSH-ARGS, AX PUSH, SI PUSH, DS PUSH, ( save important registers) SWITCH, ( make return stack become C's stack) CTABLE #, DI MOV, 0 [DI] DI LDS, ( now DS:DI points to 1st table entry in the C program) SWAP ( #out index) 2* 2* [DI] LCALL, ( call via the table) SWITCH, ( give us back our real data stack pointer) DS POP, SI POP, BP POP, ( & original return stack pointer) ( #out) GET-RESULT, NXT, ; ( Interface to a C data structure) ( Defines a word which returns address of a C data structure) : CVAR: ( index -) ( - seg off) CREATE 4 * , DOES> @ CTABLE 2@ ROT + 2DUP 2 + L@ ROT ROT L@ ; ( Define the data structures and subroutines) ( index #in #out) 0 CVAR: J ( - seg off) 1 2 1 CDECL: TST ( a b - c) 2 6 0 CDECL: initgraph ( Ldrv Lmode Lstr -) 3 0 0 CDECL: closegraph ( -) 4 0 1 CDECL: getgraphmode ( - mode) 5 1 0 CDECL: setgraphmode ( mode -) 6 0 0 CDECL: restorecrtmode ( -) 7 0 0 CDECL: graphdefaults ( -) 8 0 1 CDECL: graphresult ( - result) 9 0 1 CDECL: getmaxcolor ( - u) 10 1 0 CDECL: setcolor ( color -) 11 4 0 CDECL: putpixel ( x y color -) 12 4 0 CDECL: line ( x1 y1 x2 y2 -) ( NOTE: "L" as in Ldrv, Lstr, etc means a 4byte address ) ( Define the data structures and subroutines) ( index #in #out) 13 2 0 CDECL: linerel ( dx dy -) 14 2 0 CDECL: lineto ( x y -) 15 2 0 CDECL: moverel ( dx dy -) 16 2 0 CDECL: moveto ( x y -) 17 3 0 CDECL: circle ( x y radius -) 18 3 0 CDECL: settextstyle ( font dir size -) 19 2 0 CDECL: outtext ( Lstr -) 20 4 0 CDECL: outtextxy ( x y Lstr -) 21 CVAR: gdriver ( - seg off) 22 CVAR: gmode ( - seg off) 23 CVAR: textfont ( - seg off) 24 CVAR: textdir ( - seg off) : .ERR ( -) graphresult . ; : Lnull ( - long-null-C-string) " " 2 + CS@ ; : MSG ( - off seg) " HELLO! " 1+ CS@ ; : INIT-GPH ( -) gdriver SWAP gmode SWAP " G:\BC45\BGI\" 1+ CS@ initgraph ( .ERR ) ; : TXT ( -) restorecrtmode ( .ERR ) ; : GPH ( -) getgraphmode ( u) setgraphmode ; : TXTSIZE ( # -) PUSH textfont L@ textdir L@ POP settextstyle ; : TST1 ( -) INIT-GPH 20 30 moveto " This is Pygmy! " 1+ CS@ outtext 2 TXTSIZE 20 40 moveto " This is Pygmy! " 1+ CS@ outtext 4 TXTSIZE 20 60 moveto " This is Pygmy! " 1+ CS@ outtext 8 TXTSIZE 20 80 moveto " This is Pygmy! " 1+ CS@ outtext 300 240 75 circle KEY DROP TXT closegraph ; ( draw various circles) : END-GPH ( -) KEY DROP TXT closegraph ; : CONCENTRIC ( -) INIT-GPH 300 240 ( center) 15 FOR ( x y) 2DUP I 5 * ( ie radius) circle NEXT 2DROP END-GPH ; : CIRCLES ( -) INIT-GPH 400 200 ( center) 10 FOR ( x y) 2DUP 75 circle ( x y) -2 I * +UNDER 3 I * + ( x y) NEXT 2DROP END-GPH ; -------------------------------------------------------------------------------- /extras/cfth/lp.c: -------------------------------------------------------------------------------- 1 | /* lp.c "Load Pygmy" by Frank Sergeant 2 | frank@pygmy.utoh.org 3 | 4 | This is an example of co-ordinating Pygmy with C, 5 | to allow Pygmy to call C subroutines and access 6 | C variables. 7 | 8 | To compile and link lp.c with Borland C/C++ version 4.5 9 | from the command line, use the following command 10 | 11 | bcc -v -1- -mh -p- -tDe lp.c graphics.lib 12 | 13 | The options say to turn on debugging, to restrict the 14 | instructions to that of an 8086, to compile for the 15 | "huge" model, and to create a DOS .EXE file that also 16 | links in the graphics library. 17 | 18 | This program is an example of how to make C library 19 | functions available to Forth. Simply put the names 20 | of the desired functions into the pointers table 21 | but without the ending "()". Similarly, the addresses 22 | of C structures may be placed in the table. 23 | 24 | This example shows how Borland's BGI (graphics) routines 25 | may be used by Forth. 26 | */ 27 | 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | 42 | // declare a function to be defined in this file 43 | int tst (int a, int b); 44 | 45 | // Declare several variables whose addresses will be 46 | // passed to Forth. All except j have some use 47 | // in connection with the graphics functions. 48 | int j; 49 | int gdriver, gmode, textfont, textdir; 50 | 51 | 52 | main (int argc, char * argv[]) { 53 | 54 | int handle, file_size, temp; 55 | char * filename = {"PYGMYC.COM"}; // default file name 56 | 57 | int exit_status; 58 | 59 | char *realbuffer; // Allot a 64K byte buffer to hold the Forth image. 60 | char *loadbuffer; // Adjust this pointer to a proper SEG:OFF where the 61 | // offset is zero. It will point to the first byte 62 | // in realbuffer that is paragraph aligned. 63 | char forthstr[80]; // Staging area for Forth command strings 64 | char *commandline; // will point to 0x80 into loadbuffer 65 | int (*forth)(void); // declare forth to be a pointer to a function 66 | // that returns an integer. 67 | 68 | // This is the Table that Forth's CTABLE variable will point to. 69 | // Note the index values in the rightmost column in the comments. 70 | void *pointers[] = 71 | { 72 | (void *) &j, // integer 0 73 | (void *) tst, // function 1 74 | (void *) initgraph, // function 2 75 | (void *) closegraph, // function 3 76 | (void *) getgraphmode, // function 4 77 | (void *) setgraphmode, // function 5 78 | (void *) restorecrtmode, // function 6 79 | (void *) graphdefaults, // function 7 80 | (void *) graphresult, // function 8 81 | (void *) getmaxcolor, // function 9 82 | (void *) setcolor, // function 10 83 | (void *) putpixel, // function 11 84 | (void *) line, // function 12 85 | (void *) linerel, // function 13 86 | (void *) lineto, // function 14 87 | (void *) moverel, // function 15 88 | (void *) moveto, // function 16 89 | (void *) circle, // function 17 90 | (void *) settextstyle, // function 18 91 | (void *) outtext, // function 19 92 | (void *) outtextxy, // function 20 93 | (void *) &gdriver, // integer 21 94 | (void *) &gmode, // integer 22 95 | (void *) &textfont, // integer 23 96 | (void *) &textdir // integer 24 97 | }; 98 | 99 | 100 | // allocate memory for the Forth segment 101 | realbuffer = malloc(65535); 102 | 103 | // Walk forward in that segment until a paragraph (16 byte) 104 | // boundary is reached. 105 | temp = FP_OFF(realbuffer); 106 | if ( temp % 16 ) // if not paragraph aligned, 107 | temp += 16 - (temp % 16); // then align it 108 | loadbuffer = MK_FP ( FP_SEG (realbuffer) + temp / 16, 0 ); 109 | 110 | forth = (void *) (loadbuffer + 0x100); // entry point is + 256 bytes 111 | commandline = loadbuffer + 0x80; // command line is + 128 bytes 112 | 113 | // collect alternate Forth image file name from the 114 | // command line, if present 115 | if (argc == 2) strcpy(filename, argv[1]); 116 | 117 | // load the Forth image into the segment allocated for it 118 | handle = open( filename, O_RDONLY | O_BINARY); 119 | if ( handle != -1) { 120 | file_size = filelength(handle); 121 | read ( handle, loadbuffer+0x100, file_size); 122 | close (handle); 123 | } 124 | else 125 | puts("File could not be opened\n"); 126 | 127 | 128 | // set up some variables Forth will use when calling graphics routines 129 | gdriver = DETECT; 130 | textfont = TRIPLEX_FONT; 131 | textdir = HORIZ_DIR; 132 | 133 | // Build a string at forthstr which will be INTERPRETed by Forth 134 | // to make Forth's CTABLE variable hold the address of the 135 | // pointer table. 136 | sprintf(forthstr, " %d %d CTABLE 2! \r", 137 | FP_SEG(pointers), FP_OFF(pointers) ); 138 | 139 | // Copy that string where Forth expects to find a "command line" 140 | strcpy(commandline+1, forthstr); 141 | 142 | // Plug in the length of the "command line" 143 | commandline[0] = (char) (strlen(forthstr)-1); 144 | 145 | // Call Forth as a C subroutine 146 | exit_status = forth(); 147 | 148 | printf("The returned exit status is %d\n", exit_status); 149 | printf("The value of j is %d\n", j); 150 | 151 | free (realbuffer); 152 | return; 153 | } 154 | 155 | // Following is a dummy function to allow us to inspect 156 | // the exact calling protocol used by C 157 | int tst (int a, int b) { 158 | 159 | static int k = 7; 160 | int c; 161 | 162 | c = a + b + k++; 163 | return c; 164 | } 165 | 166 | -------------------------------------------------------------------------------- /extras/kermit/pfaaaa.ann: -------------------------------------------------------------------------------- 1 | A Simple Implementation of the Kermit Protocol 2 | in Pygmy Forth 3 | 4 | by Frank Sergeant 5 | frank@pygmy.utoh.org 6 | http://pygmy.utoh.org 7 | 8 | [ note April, 2007 I have corrected my email 9 | and web addresses above. References below 10 | to www.eskimo.com are no longer valid. See 11 | pygmy.utoh.org instead (the Kermit files are 12 | bundled with Pygmy version 1.7). ] 13 | 14 | 15 | I have written a very simple implementation of the 16 | Kermit protocol in Forth. In particular, it runs under 17 | my Pygmy Forth for DOS (available from my web site), 18 | but probably could be adapted easily to other Forths. 19 | As the code is broken up into very small subroutines, 20 | it might even be of interest for comparison purposes 21 | for other languages, providing you read Forth. 22 | 23 | I have also written an article describing this code: 24 | "A Simple Implementation of the Kermit Protocol in 25 | Pygmy Forth" appeared in the May/June and July/Aug 26 | 1997 issues (Volume XIX, Numbers 1 and 2) of _Forth 27 | Dimensions_, published by the Forth Interest Group 28 | (http://www.forth.org/fig.html). 29 | 30 | The file pfkerm.zip contains a copy of the article, 31 | the source code (in both Forth block files and as a 32 | text file listing), and some email correspondence 33 | between Frank da Cruz and myself containing some 34 | corrections to the article. pfkerm.zip is available 35 | separately at my website and is also included in 36 | the file pygmy15.zip and also on the Kermit ftp site. 37 | 38 | http://www.eskimo.com/~pygmy/pfkerm.zip 39 | http://www.eskimo.com/~pygmy/pygmy15.zip 40 | ftp://kermit.columbia.edu/kermit/archives/pfkerm.zip 41 | 42 | The plain text files (i.e. not containing the Forth block 43 | files and not containing the 132-column side-by-side 44 | listing of the source and shadow blocks) are available on 45 | the Kermit ftp site. Get the files beginning with a "pf" 46 | prefix. 47 | 48 | ftp://kermit.columbia.edu/kermit/c/pf* 49 | 50 | The source code is not Public Domain or Shareware, but 51 | you may use it freely for any private or commercial 52 | purpose provided you do so at your own risk. 53 | 54 | This effort makes no attempt to tap the speed potential 55 | of Kermit. I wanted to build into my medical 56 | accounting application the ability for my customers to 57 | upload and download small files, to and from a 58 | mainframe, for medical billing/insurance claims 59 | purposes. It is working very well for this purpose. 60 | 61 | -- Frank Sergeant 62 | -------------------------------------------------------------------------------- /extras/kermit/pfaaaa.txt: -------------------------------------------------------------------------------- 1 | file pfaaaa.txt (this is the "readme" file) 2 | 3 | 4 | 5 | A Simple Implementation of the Kermit Protocol 6 | in Pygmy Forth 7 | 8 | by Frank Sergeant 9 | frank@pygmy.utoh.org 10 | http://pygmy.utoh.org 11 | 12 | [ note April, 2007 I have corrected my email 13 | and web addresses above. References below 14 | to www.eskimo.com are no longer valid. See 15 | pygmy.utoh.org instead (the Kermit files are 16 | bundled with Pygmy version 1.7). ] 17 | 18 | See the announcement file (pfaaaa.ann) or the source code 19 | files for terms of use and distribution (basically free). 20 | 21 | The file names for the plain text files correspond to the 22 | file naming convention recommended by the Columbia 23 | University Kermit Project. The files begin with the prefix 24 | "pf" which stands for Pygmy Forth. The files in plain 25 | text format should be available on the Kermit ftp site as 26 | 27 | ftp://kermit.columbia.edu/kermit/c/pf* 28 | 29 | Those files, plus the non-plain-text files (which do not 30 | necessarily begin with the prefix "pf", are available in 31 | the pfkerm.zip file on the Kermit ftp site as 32 | 33 | ftp://kermit.columbia.edu/kermit/archives/pfkerm.zip 34 | 35 | and also on my web site 36 | 37 | http://www.eskimo.com/~pygmy 38 | 39 | Here is a description of the file contents: 40 | 41 | pfaaaa.ann 42 | The announcement file. 43 | 44 | pfaaaa.txt 45 | This file (the "readme" file). 46 | 47 | pfkerm.doc 48 | a copy of the article "A Simple Implementation 49 | of the Kermit Protocol in Pygmy Forth" 50 | which appeared in the May/June and July/Aug 51 | 1997 issues (Volume XIX, Numbers 1 and 2) of 52 | _Forth Dimensions_, published by the Forth 53 | Interest Group. 54 | 55 | pfkerm.msg 56 | Email correspondence between Frank da Cruz and 57 | me correcting and commenting upon the article. 58 | 59 | pfkerm.src 60 | The source code in plain text format. 61 | 62 | pfkerm.txt 63 | The shadow comments in plain text format. 64 | 65 | kermit.scr 66 | The source code as a Forth block file. 67 | (This is not a plain text file.) 68 | 69 | kermit.dow 70 | The associated "shadow" documentation file as 71 | a Forth block file. 72 | (This is not a plain text file.) 73 | 74 | listing.txt 75 | A text file containing a side-by-side listing 76 | of the source and shadow files. This has more 77 | than 80 columns, so it is included in pfkerm.zip 78 | but not on the plain text ftp site, but is 79 | readable as plain text if your viewer supports 80 | 132 columns. 81 | 82 | 83 | In order to run the code, you would need a copy of 84 | Pygmy Forth version 1.5 for DOS (pygmy15.zip) or later, 85 | available on my web site. You would also need serial 86 | port routines. An article I wrote for _The Computer 87 | Journal_ might help you get started with the serial 88 | port routines. Serial port routines are included in 89 | Pygmy version 1.7. 90 | 91 | 92 | If you use a different Forth, the code would need some 93 | modifications, but still might get you off to a good 94 | start. 95 | 96 | 97 | -- Frank Sergeant 98 | 99 | (end of file pfaaa.txt) 100 | -------------------------------------------------------------------------------- /extras/kermit/pfkerm.doc: -------------------------------------------------------------------------------- 1 | 2 | Kermit in Pygmy 3 | 4 | A Simple Implementation of the Kermit Protocol in Pygmy Forth 5 | 6 | by Frank Sergeant 7 | 8 | Introduction 9 | 10 | Kermit is not only the name of Henson Associates Inc's 11 | famous frog but also the name of an extensive and complex 12 | file transfer/remote computer access application written by 13 | Columbia University and/or volunteers (as I understand it) 14 | and sold and distributed by Columbia University [1]. The 15 | name Kermit is also used to refer to the family of file 16 | transfer protocols used in Columbia University's Kermit and 17 | by many modem programs. As I use the term Kermit throughout 18 | the rest of this article, it refers to the Kermit protocols, 19 | particularly the simplest form implemented here in Pygmy 20 | Forth. 21 | 22 | My Forth applications sometime need to transfer files 23 | with other systems via modem. I felt I needed to implement 24 | one or more of the following protocols: XMODEM, YMODEM, 25 | Kermit, ZMODEM. The basic XMODEM protocol doesn't have much 26 | respect these days, as it does not transmit exact file 27 | lengths, but rounds up to the nearest block size (128 28 | bytes). Enhanced versions of XMODEM, such as YMODEM 29 | overcome this. Kermit is well thought of and widely 30 | available. ZMODEM is usually considered to be the best 31 | although there seem to be arguments between the kermit and 32 | ZMODEM camps as to which is the better, faster protocol 33 | under various circumstances. I, personally, found the 34 | ZMODEM arguments more persuasive, but I don't really care 35 | about minor differences. I wanted something that worked 36 | reasonably well and was fairly easy to implement. Looking 37 | over the Kermit and ZMODEM protocols, I decided that a 38 | simple form of Kermit would be slightly easier to program. 39 | Later, I hope to implement ZMODEM as well. 40 | 41 | Why Write My Own 42 | 43 | You may well ask why we insist on writing our own 44 | version instead of using an existing product. Indeed, we 45 | have experimented some with other products and have been 46 | severely disappointed. For example, we have had a lot of 47 | trouble with PCAnywhere trying to get it configured 48 | correctly under DOS. On some client systems, we were unable 49 | to configure it by changing the configuration file in the 50 | directory PCAnywhere would be run from. Instead, we had to 51 | resort to a Rube Goldberg (an extremely cumbersome) approach 52 | to get the configuration to "take." We had to modify the 53 | batch file temporarily so it would not call the PCAnywhere 54 | script, run the application and let it shell out to 55 | PCAnywere, change and save the settings, and again modify 56 | the batch file so it would run the script. We never found 57 | just why we could configure it in some offices without going 58 | through this tedious process but not in most, but it was 59 | enough to make us hate PCAnywhere. 60 | 61 | Further, while the modem scripts would run under DOS, 62 | PCAnywhere was too slow. Also, we could not make the DOS 63 | versions of the scripts run under the Windows 95 version of 64 | PCAnywhere. Also, it was not free and we needed to fool with 65 | getting each client to purchase PCAnywhere. Similarly, the 66 | use of Columbia University's Kermit product would have 67 | required each customer to purchase a license for it (yes, it 68 | is NOT free). Ditto for the Oman Technologies ZMODEM 69 | product. So, to hell with the third-party products. We 70 | will just write our own, have full control of it, simpler 71 | installation, and a faster user interface. Were this 72 | running under Unix/Linux, we would have used the built-in, 73 | freely distributable zmodem. 74 | 75 | The Kermit Protocol 76 | 77 | My main guide for the Kermit protocol was _C 78 | Programmer's Guide to Serial Communications_ by Joe Campbell 79 | [2]. Note, there are some errors in Campbell's examples. 80 | 81 | Files are transferred in Kermit by exchanging "frames" 82 | between the sender and the receiver. Every frame begins 83 | with an SOH (start of header) character and ends with a 84 | carriage return. Between them are the following five 85 | fields: length, sequence, type, data, checksum. Each 86 | field except for the data field is a single character in 87 | printable form. The process of converting a number, say 88 | for the length field, into a character, is called 89 | "character-ization" and is done by adding the value of 90 | the space character to the number. Thus, the number zero 91 | becomes $20 and prints as a space. The number thirty-seven 92 | (i.e. $25) becomes $45 and prints as the letter "E" and so 93 | forth. I use the words CHAR and UNCHAR to convert between 94 | the two formats. Note this requirement of fitting numbers 95 | into a single byte as a printable character limits the 96 | numbers to the range zero to 94 and limits the size of 97 | frames that can be transmitted. Various extensions to the 98 | basic Kermit protocol allow longer frames, but not the 99 | simple form described here. 100 | 101 | The frame types used are S to initiate a file transfer 102 | session, F to send a file name, D to send a data frame, 103 | Z to indicate end of file, B to indicate end of 104 | transmission, E to indicate a fatal error, A to send file 105 | attributes (we do not use this one), Y to ack a frame, and 106 | N to nak a frame. No single bytes are exchanged between the 107 | sender and receiver, only whole frames. The length field 108 | indicates the number of bytes to follow the length field up 109 | to and including the checksum field, but not the carriage 110 | return. 111 | 112 | To transfer a file, the sender waits for an N-frame (a 113 | negative acknowledgement), then sends an S-frame to tell the 114 | receiver what values it wants to use for various protocol 115 | parameters, such as maximum frame length, the repeat 116 | character, the escape character, etc. The receiver then 117 | sends a Y-frame (an acknowledgement) with its preferred 118 | values for these parameters. The word COMPROMISE takes the 119 | more conservative value for each of the parameters. This 120 | single exchange of frames sets the protocol parameters for 121 | the session. In the S-frame and its Y-frame, the values of 122 | the parameters are sent in a fixed-order in the frames' data 123 | fields. 124 | 125 | Kermit has two major ways of converting bytes before 126 | transmitting them. One is the "character-ization" already 127 | mentioned, for converting numbers. The other is 128 | "controlification" to flip a bit in a control character to 129 | turn it into a printable character. Numbers, as such, are 130 | expected in the length and sequence and checksum fields, but 131 | never in the data field (except during the initial S and Y 132 | frames that establish the protocol parameters). Kermit 133 | would allow for transmitting 7-bit data bytes by escaping, 134 | with an ampersand, each byte with a high bit set and then 135 | clearing that high bit, but we do not do this. We assume 136 | the availability of an 8-bit channel. Kermit does insist, 137 | though, on escaping control characters (with "#") and at 138 | least some implementations insist on compressing data by 139 | run-length encoding repeated bytes. "#" and "~" characters, 140 | when appearing in the data as themselves, must be escaped. 141 | Thus a single "#" would appear in the data field as "##". 142 | 143 | To keep things simple, we never compress the data when 144 | we are sending a file. Unfortunately, not all 145 | implementations of Kermit respect the request not to use 146 | repeat counts. Therefore, we must be prepared to handle 147 | compressed data when receiving a file. (Since our main 148 | purpose in using Kermit is to transmit zip files, it doesn't 149 | look like we would gain much speed by compressing the data 150 | we send.) 151 | 152 | Kermit allows various types of checksums, ranging from 153 | a single byte to three bytes. Our main use will be to 154 | transmit zip'd files, with the zip file itself providing an 155 | additional level of data integrity verification with its 156 | 32-bit CRC, therefore, I am content to use a 1-byte 157 | checksum, the simplest form Kermit allows. 158 | 159 | The V-frame 160 | 161 | We invent a special input frame and assign it type V. 162 | A V-frame is never actually sent. Instead, whenever a 163 | timeout occurs, KSER-IN terminates (_and_ terminates its 164 | caller GETFRAME) and returns a V-frame. This way, a timeout 165 | is not a special case, but just an ordinary "frame." 166 | 167 | What Else Can Go Wrong 168 | 169 | In addition to a timeout, a frame with a bad checksum 170 | might be received. In this case, we send an N-frame to 171 | alert the sender so it will try again. If we are receiving 172 | and a frame is lost, the V-frame alerts us to the missing 173 | frame and we again send an N-frame to request a repeat. 174 | When sending, if a frame is lost or its Y-frame is lost, 175 | either a timeout or receipt of an N-frame alerts us to the 176 | need to resend that frame. When we receive a duplicate 177 | frame (perhaps because our Y-frame never reached the 178 | sender), we basically ignore it. However, we do acknowledge 179 | it so the sender will be free to continue. The progress of 180 | a file transfer is indicated on-screen by the printing of a 181 | dot for each frame transferred. Our code will wait forever 182 | attempting a transfer unless it is cancelled by the user or 183 | unless it receives an E-frame indicating a fatal error. 184 | 185 | The Environment 186 | 187 | This implementation expects the SER-IN, SER-OUT and 188 | related words that allow transmitting and receiving to and 189 | from the serial port connected to a modem. "The PC Serial 190 | Port in Forth" [3] describes one approach to handling the 191 | serial port on a PC using interrupts. 192 | 193 | My current approach does not use interrupts. Instead, 194 | it uses the new multi-tasking ability of the upcoming Pygmy 195 | version 1.5. The serial input is serviced by a separate 196 | task, thus greatly simplifying the serial port code. 197 | 198 | The Kermit code presented here should work regardless 199 | of which form of serial handling is used. 200 | 201 | How to Transfer Files 202 | 203 | Assuming the modem connection has been made and the 204 | other end is expecting to send or receive the file using 205 | Kermit, type " filename.zip" SEND to send a file, or type 206 | RECEIVE to receive a file. The RECEIVE routine is capable 207 | of receiving multiple files. The SEND routine transmits a 208 | single file. Since Pygmy 1.5 accepts instructions from 209 | the command line, you could type 210 | 211 | PYGMY " filename.zip" SEND BYE 212 | 213 | on the DOS command line or in a batch file, etc. In our 214 | application, we have a menu and a terminal mode with PgUp 215 | and PgDn keys invoking the SEND and RECEIVE routines. You 216 | can see a clue as to how we use this in the definition of 217 | KSER-IN on block 12007 where a user abort of the file 218 | transfer executes the DEFER'd word MYMENU to put the user 219 | back at the application menu. 220 | 221 | Conclusion 222 | 223 | This code has been used successfully at a number of 224 | client sites, but, remember, it uses only a very basic 225 | version of the Kermit protocol. It very well could have 226 | problems transferring between certain sites. If you try it 227 | out, please let me know your results. The files are available 228 | in Pygmy version 1.7 from http://pygmy.utoh.org. 229 | 230 | References 231 | 232 | [1] "Kermit: A File-transfer Protocol for Universities," 233 | parts 1 and 2, Frank da Cruz and Bill Catchings, June and 234 | July, 1984, Byte magazine. 235 | 236 | [2] _C Programmer's Guide to Serial Communications_, Joe 237 | Campbell, Howard W. Sams & Company, 1987, ISBN 238 | 0-672-22584-0, pp 98-113. Note, there are some errors in 239 | Campbell's examples. 240 | 241 | [3] "XT Corner: The PC Serial Port in Forth," Frank 242 | Sergeant, _The Computer Journal_, issue 79, Fall 1996, 243 | pp 5-10. 244 | 245 | 246 | Author's Bio 247 | 248 | Frank Sergeant, on the "thirty year plan," received his 249 | Master of Science in Computer Science degree from Southwest 250 | Texas State University. The degree and his 4.0 GPA were 251 | hard won. His thesis was entitled "Calculating the Crust of 252 | a Set of Points in C++" and has nothing to do with Forth 253 | except to help illustrate that computational geometry is 254 | easier in Forth than in C++. He can be reached at 255 | frank@pygmy.utoh.org. 256 | 257 | 258 | END 259 | -------------------------------------------------------------------------------- /extras/kermit/pfkerm.msg: -------------------------------------------------------------------------------- 1 | file pfkerm.msg 2 | 3 | This contains some email correspondence between me 4 | (Frank Sergeant) and Frank da Cruz which augments and 5 | corrects my discussion of Kermit in my article "A Simple 6 | Implementation of the Kermit Protocol in Pygmy Forth". 7 | The email headers have been kept intact (except for 8 | wrapping to no more than 80 columns) to make it easier for 9 | you to follow who is saying what and when. The complete 10 | package of files related to this article should be 11 | available on my web site 12 | 13 | http://www.eskimo.com/~pygmy/pfkerm.doc) 14 | 15 | and on the Kermit ftp site 16 | 17 | ftp://kermit.columbia.edu/kermit/c/pf* (for text files) 18 | ftp://kermit.columbia.edu/kermit/archives/pfkerm.zip (for the zip file) 19 | 20 | -- Frank Sergeant 21 | 8 November 1997 22 | 23 | [ Note, April, 2007 -- my web site is now pygmy.utoh.org and the 24 | Kermit files are included in Pygmy version 1.7 ] 25 | 26 | 27 | From fdc@watsun.cc.columbia.edu Wed Aug 13 09:47:08 1997 28 | Received: from poboxer.pobox.com (poboxer.pobox.com [208.210.124.21]) 29 | by mx2.eskimo.com (8.8.5/8.6.12) with ESMTP id JAA26079 30 | for ; Wed, 13 Aug 1997 09:47:02 -0700 (PDT) 31 | Received: from watsun.cc.columbia.edu 32 | (cu41841@watsun.cc.columbia.edu [128.59.39.2]) 33 | by poboxer.pobox.com (8.8.5/8.8.5) with ESMTP id MAA13352 34 | for ; Wed, 13 Aug 1997 12:45:49 -0400 35 | Received: (from fdc@localhost) 36 | by watsun.cc.columbia.edu (8.8.5/8.8.5) id MAA03983; 37 | Wed, 13 Aug 1997 12:45:49 -0400 (EDT) 38 | Date: Wed, 13 Aug 97 12:45:48 EDT 39 | From: Frank da Cruz 40 | To: pygmy@pobox.com 41 | Subject: Re: Kermit in Forth 42 | In-Reply-To: Your message of Tue, 12 Aug 1997 13:31:35 -0500 43 | Message-ID: 44 | Status: R 45 | X-Status: A 46 | 47 | > The actual Kermit protocol code is in the files KERMIT.SCR 48 | > (source code) and KERMIT.DOW (shadow or documentation) files 49 | > plus the text of my article in KERMIT.TXT. 50 | > 51 | OK, I've got them now, thanks! 52 | 53 | > I suppose the article (KERMIT.TXT) would be the best file to start 54 | > reading. 55 | > 56 | OK, thanks. Btw, here are a few corrections for your article, although 57 | I suppose it's too late now. 58 | 59 | Kermit is not only the name of Henson Associates Inc's 60 | famous frog but also the name of an extensive and complex 61 | file transfer/remote computer access application written by 62 | Columbia University and/or volunteers (as I understand it) 63 | and sold and distributed by Columbia University [1]. 64 | 65 | The implication that Kermit is "sold" and/or "not free" is something of 66 | an oversimplification. There are hundreds of different Kermit programs, 67 | and each one might have a different copyright status. The most popular 68 | versions are "free" in the sense that you can get and use them for free, 69 | but we also ask you to purchase the corresponding manual (for the good 70 | reasons that sales of these manuals are what support our continuing 71 | support and development work, and that they show you how to use the 72 | software), but they are "not free" in the sense that you can't resell 73 | them, bundle them with a product, etc, without licensing them. The 74 | details are all on our website: 75 | 76 | http://www.columbia.edu/kermit/ 77 | 78 | and in particular: 79 | 80 | http://www.columbia.edu/kermit/licensing.html 81 | 82 | ... ZMODEM is usually considered to be the best 83 | although there seem to be arguments between the kermit and 84 | ZMODEM camps as to which is the better, faster protocol 85 | under various circumstances. I, personally, found the 86 | ZMODEM arguments more persuasive... 87 | 88 | Did you look at: 89 | 90 | http://www.columbia.edu/kermit/perf.html 91 | 92 | which is a set of benchmarks of Kermit and XYZMODEM. Also, did you 93 | know there is an entire book on the subject, "The Working Programmer's 94 | Guide to Serial Protocols", by Tim Kienzle? 95 | 96 | Similarly, the 97 | use of Columbia University's Kermit product would have 98 | required each customer to purchase a license for it (yes, it 99 | is NOT free). 100 | 101 | Again, it depends on which version. 102 | 103 | The Kermit Protocol 104 | 105 | My main guide for the Kermit protocol was _C 106 | Programmer's Guide to Serial Communications_ by Joe Campbell 107 | [2]. Note, there are some errors in Campbell's examples. 108 | 109 | The definitive protocol reference is: 110 | 111 | Frank da Cruz, "Kermit, A File Transfer Protocol", Digital Press / 112 | Butterworth Heinemann, Woburn, MA, 1987, 379 pages, ISBN 0-932376-88-6. 113 | 114 | Kermit 115 | would allow for transmitting 7-bit data bytes by escaping, 116 | with an ampersand, each byte with a high bit set and then 117 | clearing that high bit, but we do not do this. 118 | 119 | There is also a much more efficient (but more complicated) locking 120 | shift method. 121 | 122 | Unfortunately, not all 123 | implementations of Kermit respect the request not to use 124 | repeat counts. 125 | 126 | Which ones did you find that didn't do this? 127 | 128 | I'd be curious to know more about what's going on with Forth? I take it 129 | that Forth is an "enclosed environment" that runs on various platforms, 130 | and the same Kermit program runs on the platforms where the Forth 131 | environment runs? Can you list them? 132 | 133 | Finally, would you want to write an announcement for your Kermit version 134 | that can be posed on the Kermit newsgroup? 135 | 136 | Thanks again! 137 | 138 | - Frank 139 | 140 | 141 | 142 | From: pygmy@eskimo.com (Frank Sergeant) 143 | To: fdc@watsun.cc.columbia.edu 144 | Subject: Re: Kermit in Forth 145 | Date: Mon, 18 Aug 1997 14:32:43 -0500 146 | Reply-To: pygmy@pobox.com 147 | Message-ID: 148 | In-Reply-To: 149 | Lines: 126 150 | X-Status: U 151 | 152 | Dear Frank, 153 | 154 | > OK, thanks. Btw, here are a few corrections for your article, although 155 | > I suppose it's too late now. 156 | 157 | Thanks for the corrections and further 158 | information. It is too late for the article in 159 | _Forth Dimensions_, as the issue has already come 160 | out. However, if it is ok with you, what I might 161 | do is add your letter to the pygmy15.zip file and 162 | mention on my web site that the additional 163 | information is available. 164 | 165 | > The implication that Kermit is "sold" and/or "not free" is something of 166 | > an oversimplification. There are hundreds of different Kermit programs, 167 | > and each one might have a different copyright status. The most popular 168 | > versions are "free" in the sense that you can get and use them for free, 169 | > but we also ask you to purchase the corresponding manual (for the good 170 | ^^^ 171 | ... 172 | > software), but they are "not free" in the sense that you can't resell 173 | > them, bundle them with a product, etc, without licensing them. The 174 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 175 | 176 | Well, that is more or less my point. I don't 177 | see how we can ask our clients to each ftp a copy 178 | of the program, so we would seem to need to give 179 | them a copy (which I suppose comes under the 180 | category of "bundle"). As I read the licensing 181 | information, the simplest way would be for us to 182 | also buy each of them the _Using MS-DOS Kermit_ 183 | book. To me, that seems equivalent to saying that 184 | (your primary MS-DOS Kermit distribution) it is 185 | "sold" and/or "not free". Perhaps I'm overlooking 186 | some subtle distinction, but that seems to me to 187 | be the pratical effect. Still, I am not sure that 188 | that wouldn't have been best after all, but it was 189 | one more complexity I was trying to avoid. 190 | Obviously, the full Kermit is an impressive 191 | system. I hope to look into it more fully, 192 | eventually. 193 | 194 | > ... ZMODEM is usually considered to be the best 195 | ... 196 | > Did you look at: 197 | > 198 | > http://www.columbia.edu/kermit/perf.html 199 | > 200 | > which is a set of benchmarks of Kermit and XYZMODEM. 201 | 202 | I have now forgotten what I did look at. I 203 | believe I read something from the columbia site 204 | and then read a rebuttal of it from the Oman site. 205 | 206 | > Also, did you 207 | > know there is an entire book on the subject, 208 | > "The Working Programmer's 209 | > Guide to Serial Protocols", by Tim Kienzle? 210 | 211 | I have seen title mentioned, but I haven't 212 | seen the book. Do you recommend it? 213 | 214 | > The definitive protocol reference is: 215 | > 216 | > Frank da Cruz, "Kermit, A File Transfer Protocol", 217 | > Digital Press / 218 | > Butterworth Heinemann, Woburn, MA, 1987, 379 pages, 219 | > ISBN 0-932376-88-6. 220 | 221 | And I wish I'd had it to hand at the time. 222 | 223 | > Unfortunately, not all 224 | > implementations of Kermit respect the request not to use 225 | > repeat counts. 226 | > 227 | > Which ones did you find that didn't do this? 228 | 229 | It was a version of Kermit from some years 230 | ago running on a '486. I got it, basically 231 | already set up, from Southwest Texas State 232 | University for use in connecting to their VAX. 233 | I can't get version information from it now as I 234 | have since reformatted the hard disk. 235 | 236 | > I'd be curious to know more about what's going on 237 | > with Forth? I take it that Forth is an "enclosed 238 | > environment" that runs on various platforms, and 239 | > the same Kermit program runs on the platforms 240 | > where the Forth environment runs? Can you list 241 | > them? 242 | 243 | At first, Forth was its own operating system 244 | and could run with very minimal hardware 245 | resources. It is used extensively in embedded 246 | systems (controlling the Saudi Arabian airport, 247 | running the FedX handheld gizmos) as its own 248 | "enclosed environment". In other areas, it 249 | usually runs under a host OS these days. It is 250 | available for nearly every environment. It is in 251 | the low-level boot ROM on Sun workstations, used 252 | for initial device configuration (although this is 253 | running before Unix comes up). There are several 254 | versions running under Unix and Linux, Windows, 255 | DOS, the Mac, etc. One of its first major 256 | applications was controlling radio telescopes and 257 | manipulating their data. Pygmy Forth runs in DOS, 258 | using DOS or BIOS calls for its I/O. It seems to 259 | run in just about any DOS box (under Windows 3.1, 260 | Windows 95, OS/2, or Linux's dos emulator). So, 261 | the only environment Pygmy Forth runs in is DOS. 262 | The KERMIT.SCR code almost certainly could not be 263 | loaded unchanged into a different Forth, but I 264 | hope it captures the essence of the algorithm so 265 | that it would not be very hard to port to a 266 | different Forth or to different hardware. (Did 267 | this answer the question?) 268 | 269 | > Finally, would you want to write an announcement 270 | > for your Kermit version that can be posed on the 271 | > Kermit newsgroup? 272 | 273 | I'll be glad to. I'll search for 'kermit' 274 | next time I'm reading news and try to find the 275 | appropriate group and then post something. 276 | 277 | -- Frank 278 | 279 | 280 | 281 | From fdc@watsun.cc.columbia.edu Mon Aug 18 14:56:44 1997 282 | Received: from poboxer.pobox.com (poboxer.pobox.com [208.210.124.21]) 283 | by mx1.eskimo.com (8.8.5/8.6.12) with ESMTP id OAA21324 284 | for ; Mon, 18 Aug 1997 14:56:27 -0700 285 | Received: from watsun.cc.columbia.edu 286 | (cu41841@watsun.cc.columbia.edu [128.59.39.2]) 287 | by poboxer.pobox.com (8.8.5/8.8.5) with ESMTP id RAA20751 288 | for ; Mon, 18 Aug 1997 17:56:25 -0400 289 | Received: (from fdc@localhost) 290 | by watsun.cc.columbia.edu (8.8.5/8.8.5) id RAA20868; 291 | Mon, 18 Aug 1997 17:56:24 -0400 (EDT) 292 | Date: Mon, 18 Aug 97 17:56:24 EDT 293 | From: Frank da Cruz 294 | To: pygmy@pobox.com 295 | Subject: Re: Kermit in Forth 296 | In-Reply-To: Your message of Mon, 18 Aug 1997 14:32:43 -0500 297 | Message-ID: 298 | Status: R 299 | X-Status: R 300 | 301 | > Thanks for the corrections and further 302 | > information. It is too late for the article in 303 | > _Forth Dimensions_, as the issue has already come 304 | > out. However, if it is ok with you, what I might 305 | > do is add your letter to the pygmy15.zip file and 306 | > mention on my web site that the additional 307 | > information is available. 308 | > 309 | That's fine. 310 | 311 | > > The implication that Kermit is "sold" and/or "not free" is something of 312 | > > an oversimplification. There are hundreds of different Kermit programs, 313 | > > and each one might have a different copyright status. The most popular 314 | > > versions are "free" in the sense that you can get and use them for free, 315 | > > but we also ask you to purchase the corresponding manual (for the good 316 | > ^^^ 317 | > ... 318 | > > software), but they are "not free" in the sense that you can't resell 319 | > > them, bundle them with a product, etc, without licensing them. The 320 | > ^^^^^^^^^^^^^^^^^^^^^^^^^^ 321 | > 322 | > Well, that is more or less my point. I don't 323 | > see how we can ask our clients to each ftp a copy 324 | > of the program, so we would seem to need to give 325 | > them a copy (which I suppose comes under the 326 | > category of "bundle"). As I read the licensing 327 | > information, the simplest way would be for us to 328 | > also buy each of them the _Using MS-DOS Kermit_ 329 | > book. To me, that seems equivalent to saying that 330 | > (your primary MS-DOS Kermit distribution) it is 331 | > "sold" and/or "not free". 332 | > 333 | The distinction is between end users and "resellers". 334 | For end users, these programs are free. For resellers 335 | (even if they are not actually selling), they are not 336 | free. There is a long history behind this that takes 337 | a long time to explain, but briefly: we used to be 338 | funded to do this work, but we aren't any more, so we 339 | have to pay for the Kermit Project out of income. Our 340 | work includes tech support -- unlike FSF, etc, we 341 | provide end-user support, and in fact this takes up 342 | most of our time each day. If you (generic "you") can 343 | take our software and give it away to your customers 344 | or clients without documentation, this gives you 345 | commercial advantage at our expense, since many of 346 | your users will ask us for assistance. On the other 347 | hand, if you provide them with manuals, then (a) they 348 | are less likely to ask us for help, and (b) we get 349 | some income to keep our work going. 350 | 351 | > > ... ZMODEM is usually considered to be the best 352 | > ... 353 | > > Did you look at: 354 | > > 355 | > > http://www.columbia.edu/kermit/perf.html 356 | > > 357 | > > which is a set of benchmarks of Kermit and XYZMODEM. 358 | > 359 | > I have now forgotten what I did look at. I 360 | > believe I read something from the columbia site 361 | > and then read a rebuttal of it from the Oman site. 362 | > 363 | Right -- there is a rebuttal there, but it doesn't hold 364 | a lot of water. There was a prolonged debate on the 365 | newsgroups after this, that finally settled down after 366 | a couple years. The bare fact is, there is precious 367 | little difference between Zmodem and Kermit in terms of 368 | performance on a perfect connection (8-bit clean, no 369 | noise, transparent to all control characters), but there 370 | is a big difference on all other types of connections. 371 | 372 | > > Also, did you 373 | > > know there is an entire book on the subject, 374 | > > "The Working Programmer's 375 | > > Guide to Serial Protocols", by Tim Kienzle? 376 | > 377 | > I have seen title mentioned, but I haven't 378 | > seen the book. Do you recommend it? 379 | > 380 | It's pretty good technically, and fair and impartial 381 | in the protocol wars. Yes, I do recommend it. 382 | 383 | > ...different Forth or to different hardware. (Did 384 | > this answer the question?) 385 | > 386 | Yes -- I like stories like that. We have a lot of them 387 | with Kermit too -- odd gadgets where it is embedded, etc 388 | (fast-food cash registers, hand-held bar-code scanners, 389 | even pacemakers...) 390 | 391 | > > Finally, would you want to write an announcement 392 | > > for your Kermit version that can be posed on the 393 | > > Kermit newsgroup? 394 | > 395 | > I'll be glad to. I'll search for 'kermit' 396 | > next time I'm reading news and try to find the 397 | > appropriate group and then post something. 398 | > 399 | The newsgroups are comp.protocols.kermit.misc and 400 | comp.protocols.kermit.announce; the latter is moderated. 401 | 402 | Let's coordinate on this, since you'll need to tell 403 | them where to find it and what it's called, etc, in 404 | the Kermit archive. 405 | 406 | There's the ZIP file, but then we usually like to put 407 | up the source code and docs as plain text for various 408 | reasons; in this case maybe somebody wants to port it 409 | to another environment where there is no UNZIP, etc. 410 | Can a Forth program be saved as plain ASCII text? 411 | 412 | Thanks again! 413 | 414 | - Frank 415 | 416 | (end of file pfkerm.msg) 417 | -------------------------------------------------------------------------------- /extras/kermit/pfkerm.src: -------------------------------------------------------------------------------- 1 | file pfkerm.src 2 | 3 | This is a conversion of the Forth block file KERMIT.SCR 4 | so as to be readable as a plain text file. Do not try 5 | load it (compile it) without editing it to suit your 6 | version of Forth. Don't load it under Pygmy Forth; 7 | instead, get the actual block files from 8 | 9 | Pygmy version 1.7 at http://pygmy.utoh.org 10 | 11 | 12 | 13 | KERMIT.SCR 14 | Contains a simple implementation of the Kermit 15 | file transfer protocol. 16 | 17 | copyright 1997 Frank Sergeant frank@pygmy.utoh.org 18 | 19 | License: See license20040130.txt or 20 | http://pygmy.utoh.org/license.html 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | ( load screen Kermit file transfer protocol) 29 | 30 | 31 | 32 | 12002 12024 THRU 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | EXIT ( KERMIT - user interface) 44 | 45 | : GET-Y/N ( - f) 46 | BEGIN KEY DUP 'Y = OVER 'y = OR IF DROP -1 EXIT THEN 47 | DUP 'N = SWAP 'n = OR IF 0 EXIT THEN BEEP 48 | AGAIN ; 49 | 50 | : TRY-AGAIN? ( a - f) 51 | CR COUNT TYPE CR ." Try again? (Y/N) " 52 | GET-Y/N ( f) ; 53 | 54 | : .MSG ( a -) 0 0 AT 160 SPACES 0 0 AT COUNT TYPE ; 55 | 56 | 57 | 58 | 59 | 60 | ( KERMIT) 61 | 1 CONSTANT SOH 62 | VARIABLE SEQ SEQ OFF 63 | : BUMPSEQ ( -) SEQ @ 1+ 63 AND SEQ ! ; 64 | 94 ( 35) CONSTANT MYMAXL ( fields SEQ TYPE DATA & CKSUM) 65 | 66 | CREATE OUT-BUF MYMAXL ( 1+) 2 + ALLOT VARIABLE OUTLEN 67 | CREATE IN-BUF MYMAXL ( 1+) 2 + ALLOT VARIABLE INLEN 68 | 69 | : ?NUM-OK ( n -) $5E > ABORT" too big" ; 70 | : CHAR ( n - c) DUP ?NUM-OK ( n) $20 + ; 71 | : UNCHAR ( c - n) $20 - ( n) DUP ?NUM-OK ; 72 | 73 | 74 | 75 | 76 | 77 | ( KERMIT - protocol parameters) 78 | VARIABLE MAXL 79 | VARIABLE QCTL 80 | VARIABLE NPAD 81 | VARIABLE PADC 82 | VARIABLE EOLC 83 | VARIABLE TIMEOUT 84 | 85 | : INIT-LIMITS ( -) 86 | MYMAXL MAXL ! ( maximum "len" value) 87 | '# QCTL ! ( control code escape character) 88 | 0 NPAD ! ( number of pad characters) 89 | 0 PADC ! ( pad character) 90 | $0D EOLC ! ( end of line character) 91 | 4 TIMEOUT ! ( timeout in seconds) ; INIT-LIMITS 92 | 93 | 94 | ( KERMIT - address of fields in buffers) 95 | : FIELD: ( offset -) ( buff - a) CREATE C, DOES> C@ + ; 96 | 97 | 0 FIELD: >LEN 98 | 1 FIELD: >SEQ 99 | 2 FIELD: >TYPE 100 | 3 FIELD: >DATA 101 | : >CKSUM ( buff - a) >LEN DUP C@ UNCHAR + ; 102 | 103 | 3 FIELD: >MAXL 104 | 4 FIELD: >TIME 105 | 5 FIELD: >NPAD 106 | 6 FIELD: >PADC 107 | 7 FIELD: >EOLC 108 | 8 FIELD: >QCTL 109 | 110 | 111 | ( KERMIT - compromise on the parameters) 112 | 113 | : COMPROMISE ( -) 114 | OUT-BUF IN-BUF ( a a) 115 | OVER >MAXL C@ UNCHAR OVER >MAXL C@ UNCHAR 116 | MIN MAXL ! ( a a) 117 | OVER >TIME C@ UNCHAR OVER >TIME C@ UNCHAR 118 | MAX TIMEOUT ! ( a a) 2DROP ; 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | DEFER M ( the menu to return to) 129 | : KSER-IN ( - c f) 130 | TIMEOUT @ 1000 * ( ms) 131 | BEGIN KEY? IF KEY DROP CR 132 | ." Abort file transfer (Y/N)? " GET-Y/N CR 133 | IF ." Transfer aborted -- press " 134 | ." any key to return to menu" 135 | KEY DROP M 136 | ELSE ." Transfer continuing " 137 | THEN THEN 138 | SER-IN? IF ( ms) DROP SER-IN DUP SOH = ( c f) EXIT THEN 139 | ( ms) 1- DUP 0= IF POP 2DROP 'V -1 EXIT THEN 1 MS 140 | AGAIN ; 141 | 142 | : TEST-IN ( - c f) KSER-IN ; 143 | 144 | 145 | ( KERMIT ) 146 | : CTRL ( c - c') 147 | DUP QCTL @ = OVER '~ = OR IF EXIT THEN $40 XOR ; 148 | 149 | : CTRL? ( c - f) 150 | DUP $20 < OVER QCTL @ = OR OVER $7E = OR SWAP $7F = OR ; 151 | 152 | : (KEMIT ( c -) OUT-BUF OUTLEN @ + C! ( ) 1 OUTLEN +! ; 153 | 154 | : KEMIT ( c -) PAUSE ( just in case) 155 | ( c) DUP CTRL? IF QCTL @ (KEMIT CTRL ( c) THEN (KEMIT ; 156 | 157 | : ROOM? ( - u) MAXL @ 1- OUTLEN @ > ; 158 | 159 | 160 | 161 | 162 | ( KERMIT ) 163 | : CK%% ( u - c) 164 | DUP $C0 AND 2/ 2/ 2/ 2/ 2/ 2/ + $3F AND CHAR ; 165 | 166 | : CKSUM ( buffer - c) >LEN DUP C@ UNCHAR ( a #) 0 ROT ROT 167 | FOR ( sum a) C@+ +UNDER NEXT DROP CK%% ( c) ; 168 | 169 | : CKSUM? ( - f) 170 | IN-BUF CKSUM ( c) IN-BUF >CKSUM C@ ( c c) = ; 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | DEFER MODEM! 181 | ( ' EMIT) ' SER-OUT IS MODEM! 182 | 183 | : DATA! ( a # - a' #') SWAP ( # a) 184 | BEGIN ( # a) OVER 0= ROOM? 0= OR ( ie out of source or room) 185 | NOT WHILE ( # a) C@+ KEMIT -1 +UNDER REPEAT SWAP ( a #) ; 186 | 187 | : BUILD-FRAME ( a # type - a' #') OUTLEN OFF 188 | 0 ( ie dummy len) CHAR (KEMIT SEQ @ CHAR (KEMIT 189 | (KEMIT ( a #) DATA! ( a' #') 190 | OUTLEN @ CHAR OUT-BUF >LEN C! ( a #) 191 | OUT-BUF CKSUM OUT-BUF >CKSUM C! ( a #) ; 192 | 193 | 194 | 195 | 196 | ( KERMIT - debugging aids) 197 | 198 | : .FRAME ( buf -) ." len = " C@+ UNCHAR DUP PUSH 2 U.R 199 | ." seq = " C@+ UNCHAR 2 U.R SPACE SPACE 200 | ." myseq = " SEQ @ 2 U.R SPACE SPACE 201 | POP 1- TYPE CR ; 202 | 203 | : .INB ( type -) .S 3 SPACES 204 | 'V = IF ." V-frame " CR ELSE ." IN: " IN-BUF .FRAME THEN ; 205 | 206 | : .OUTB ( -) .S 3 SPACES ." OUT: " OUT-BUF .FRAME ; 207 | 208 | " WHAT DOES THE SYMBOL # STAND FOR?" CONSTANT TEST1 209 | 210 | " as much labor for the study of its" CONSTANT TEST2 211 | 212 | 213 | ( KERMIT) 214 | 215 | : SENDFRAME ( -) SOH MODEM! OUT-BUF >LEN DUP C@ UNCHAR 1+ 216 | FOR ( a) C@+ MODEM! NEXT DROP ( ) $0D MODEM! ; 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | ( KERMIT) 231 | : LIMITS ( type -) 232 | SEQ OFF PUSH 233 | '~ ( the repeat char) 234 | '1 ( 1-byte chksum, either '1 or 1 CHAR seems to work) 235 | 'N ( no hi-bit prefix) 236 | QCTL @ EOLC @ CHAR PADC @ CTRL 237 | NPAD @ CHAR TIMEOUT @ CHAR MAXL @ CHAR POP 238 | SEQ @ CHAR 12 ( len) CHAR 239 | OUT-BUF 12 FOR DUP PUSH C! POP 1+ NEXT DROP ( ) 240 | OUT-BUF CKSUM OUT-BUF >CKSUM C! ; 241 | 242 | 243 | 244 | 245 | 246 | 247 | ( KERMIT) 248 | : BUILD/SEND ( a # type -) BUILD-FRAME SENDFRAME 2DROP ; 249 | : KINIT ( -) 'S LIMITS SENDFRAME ; 250 | : KINITACK ( -) 'Y LIMITS COMPROMISE 'Y LIMITS SENDFRAME ; 251 | : FILEHEADER ( a # -) " sending file " .MSG 2DUP TYPE 252 | ( a #) 'F BUILD/SEND ; 253 | : EMPTY-FRAME ( type -) ( ) CREATE C, 254 | DOES> C@ 0 0 ROT BUILD/SEND ; 255 | 256 | 'Y EMPTY-FRAME (ACK 'N EMPTY-FRAME (NAK 257 | 'Z EMPTY-FRAME EOF 'B EMPTY-FRAME EOT 258 | 'A EMPTY-FRAME ATTRIB 'E EMPTY-FRAME ERROR 259 | 260 | : ACK ( seq# -) SEQ @ SWAP SEQ ! (ACK SEQ ! ; 261 | : NAK ( seq# -) SEQ @ SWAP SEQ ! (NAK SEQ ! ; 262 | 263 | 264 | ( KERMIT) 265 | 266 | VARIABLE EXPECTED 267 | 268 | : INBUF! ( c -) IN-BUF INLEN @ + C! 1 INLEN +! ; 269 | 270 | : SETLENGTH ( clength -) 271 | INLEN OFF DUP INBUF! ( c) UNCHAR EXPECTED ! ; 272 | 273 | : PUT-IN-BUFFER ( c - f) INBUF! INLEN @ EXPECTED @ > ; 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | ( KERMIT) 282 | 283 | : GETFRAME ( - type f) 284 | BEGIN KSER-IN NIP UNTIL ( ) ( ie await SOH) 285 | BEGIN 286 | BEGIN KSER-IN WHILE DROP REPEAT ( c) SETLENGTH ( ) 287 | BEGIN KSER-IN NOT WHILE ( c) PUT-IN-BUFFER ( f) 288 | IF IN-BUF >TYPE C@ CKSUM? 289 | OVER 'E = OVER AND ABORT" Fatal Error in Kermit" 290 | EXIT THEN ( ) 291 | REPEAT ( c) DROP 292 | AGAIN ( type f) ; 293 | 294 | 295 | 296 | 297 | 298 | ( KERMIT) 299 | 300 | : GET-GOOD-FRAME ( - type) 301 | BEGIN GETFRAME ( type cksumflag) NOT WHILE 302 | ." bad cksum " DROP REPEAT ; 303 | 304 | 305 | : IN-SEQ ( - u) IN-BUF >SEQ C@ UNCHAR ; 306 | 307 | : GOOD-SEQ? ( - f) IN-SEQ SEQ @ = ; 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | ( KERMIT) 316 | : (GETACK ( - type) 317 | BEGIN GETFRAME ( type f) NOT WHILE DROP REPEAT ( type) ; 318 | 319 | : GETACK ( -) 320 | BEGIN (GETACK ( type) 321 | 'Y OF GOOD-SEQ? ( f) DUP IF BUMPSEQ THEN ( f) ELSE 322 | 'N OF GOOD-SEQ? IF SENDFRAME THEN 0 ELSE 323 | 'V OF SENDFRAME 0 ELSE 324 | ( default) DROP 0 [ 3 ] THENS ( f) 325 | UNTIL ; 326 | 327 | : READ ( h - a #) PUSH 32767 BUFFER ( ie dummy buffer) 328 | DUP 1024 POP FILE-READ #BYTES-READ @ ; 329 | 330 | 331 | 332 | ( KERMIT) 333 | 334 | : GET-FIRST-NAK ( -) BEGIN (GETACK 'N = UNTIL ; 335 | 336 | : SEND ( name -) CLS " Waiting to send " .MSG INIT-LIMITS 337 | DUP FOPEN IF CR ." cannot open input file" CR EXIT THEN 338 | ( name h) 1000 MS ( name h) GET-FIRST-NAK 339 | ( n h) KINIT RESET-SER-IN GETACK 340 | COMPROMISE SWAP COUNT ( h a #) FILEHEADER ( h) GETACK 341 | BEGIN ( h) DUP READ DUP WHILE ( h a #) 342 | BEGIN 'D BUILD-FRAME SENDFRAME GETACK '. EMIT 343 | DUP 0= UNTIL 2DROP 344 | REPEAT 2DROP ( h) FCLOSE ( ) EMPTY-BUFFERS ( just in case) 345 | EOF GETACK EOT GETACK ; 346 | 347 | 348 | 349 | ( KERMIT) 350 | 351 | CREATE IN-DATA MYMAXL 3 / 94 * 2 + ALLOT 352 | 353 | : C!+ ( c a - a+) DUP PUSH C! POP 1+ ; 354 | 355 | : C@+- ( fr # - fr # c) 1- PUSH C@+ POP SWAP ; 356 | 357 | : UNCTRL'd ( from # c - from # c) 358 | DUP QCTL @ - IF EXIT THEN DROP C@+- CTRL ; 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | ( KERMIT) 367 | : REPEAT'd ( to from # - to from #) ROT PUSH ( fr #) 368 | C@+- UNCHAR PUSH C@+- ( fr # c) UNCTRL'd ( fr # c) 369 | POP POP ( ie rpt# to) 2DUP + PUSH ( fr # c rpt# to) 370 | SWAP ROT FILL ( fr #) POP ROT ROT ( to fr #) ; 371 | 372 | : UNCTRL ( from to # - a #) 373 | ROT PUSH PUSH DUP POP POP SWAP ( to to from #) 374 | BEGIN DUP WHILE ( to to fr #) 375 | C@+- DUP '~ = IF ( to to fr # c) DROP REPEAT'd 376 | ELSE UNCTRL'd PUSH ROT POP SWAP C!+ ROT ROT THEN 377 | REPEAT ( to to fr 0) 2DROP OVER - ( a #) ; 378 | 379 | : >IN-DATA ( - a #) IN-BUF >DATA IN-DATA ( from to) 380 | IN-BUF C@ UNCHAR 3 - ( from to #) UNCTRL ; 381 | 382 | 383 | ( KERMIT) 384 | VARIABLE KHANDLE 385 | CREATE KFNAME 50 ALLOT 386 | 387 | : BUILDFNAME ( -) 388 | >IN-DATA ( a #) DUP PUSH KFNAME 1+ SWAP CMOVE ( ) 389 | 0 KFNAME R@ + 1+ C! ( make name into an asciiz string) 390 | POP KFNAME C! ; 391 | 392 | : RCVNAME ( -) 393 | BUILDFNAME KFNAME FMAKE ( h f) 394 | ABORT" cannot open output file" ( h) KHANDLE ! 395 | " receiving file " .MSG KFNAME COUNT TYPE SPACE ; 396 | 397 | 398 | 399 | 400 | ( KERMIT) 401 | : GETNEXT ( - type) 402 | BEGIN GETFRAME ( type f) 403 | IF ( type) DUP 'V = 404 | IF ( type) SEQ @ NAK -1 ( type f) 405 | ELSE ( type) IN-SEQ DUP ACK ( type seq) SEQ @ - 406 | THEN 407 | ELSE 408 | ( ie bad cksum) 409 | SEQ @ NAK -1 ( type f) ( -1 ABORT" BAD CKSUM" ) 410 | THEN 411 | WHILE DROP 412 | REPEAT BUMPSEQ ; 413 | 414 | : WRITE ( -) >IN-DATA KHANDLE @ ( a # h) FILE-WRITE ; 415 | 416 | 417 | ( KERMIT) 418 | 419 | : RECEIVE ( -) CLS " Waiting to receive " .MSG 420 | RESET-SER-IN INIT-LIMITS 421 | BEGIN 0 NAK 1000 MS GET-GOOD-FRAME 'S = UNTIL 422 | ( ) KINITACK BUMPSEQ 423 | BEGIN GETNEXT ( type) ( DUP EMIT ) 424 | 'D OF WRITE '. EMIT 0 ELSE 425 | 'F OF RCVNAME 0 ELSE 426 | 'Z OF KHANDLE @ FCLOSE 0 ELSE 427 | 'B OF -1 ELSE 428 | ( otherwise) DROP 0 [ 4 ] THENS 429 | UNTIL ( ) ; 430 | 431 | 432 | (end file pfkerm.src) 433 | -------------------------------------------------------------------------------- /extras/kermit/pfkerm.txt: -------------------------------------------------------------------------------- 1 | file pfkerm.txt 2 | 3 | This is a conversion of the Forth block file KERMIT.DOW 4 | so as to be readable as a plain text file. The complete 5 | package, including the actual block files, is available 6 | from my web site in Pygmy version 1.7 at 7 | 8 | http://pygmy.utoh.org 9 | 10 | This pfkerm.txt and KERMIT.DOW provide the "shadow" 11 | comments to match the source code in the file pfkerm.src 12 | and KERMIT.SCR. 13 | 14 | 15 | KERMIT.SCR 16 | Contains a simple implementation of the Kermit 17 | file transfer protocol. 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | ( load screen Kermit file transfer protocol) 33 | 34 | For the algorithm, see pp 98-113 of 35 | 36 | _C Programmer's Guide to Serial Communications_ 37 | by Joe Campbell, Howard W. Sams & Company, 1987, 38 | ISBN 0-672-22584-0. 39 | 40 | Note, there are some errors in Campbell's examples. 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ( KERMIT) 50 | 51 | GET-Y/N Wait for the user to press a y, n, Y, or N key. 52 | Return true if y or Y. Return false if n or N. 53 | 54 | 55 | TRY-AGAIN? 56 | Display a message and ask whether the user wants 57 | to try again. E.g. 58 | " Drive not ready" TRY-AGAIN? IF ... THEN 59 | 60 | .MSG clears the top 2 lines of the screen and displays a 61 | message, leaving the cursor positioned just past the 62 | message. E.g. " Starting the transfer ..." .MSG 63 | 64 | 65 | 66 | ( KERMIT) 67 | MYMAXL maximum "len" we are willing to handle. 68 | The transmitted LEN field includes SEQ, TYPE, DATA, CKSUM 69 | fields. 94 maximum allowed under basic Kermit. Our 70 | buffers must be 1 byte longer to hold the LEN field also. 71 | OUT-BUF & IN-BUF buffers for building outgoing or receiving 72 | incoming frames. We store LEN, SEQ, TYPE, DATA, CKSUM 73 | fields, but not the SOH nor the ending CR. 74 | OUTLEN & INLEN count bytes currently in the buffers 75 | MAXL holds agreed-upon maximum "len" value, which is 76 | the MIN of receiver's and sender's preferences. 77 | 78 | a "character-ized" number is produced by adding a "space." The 79 | result must be <= $7E, thus the original number must be 80 | <= $5E (ie 94 decimal). 81 | 82 | 83 | ( KERMIT) 84 | 85 | MAXL, QCTL, etc are the agreed-upon protocol parameters for 86 | the session. INIT-LIMITS initializes these to the values 87 | we would prefer to use. The sender and receiver exchange 88 | an S-frame and an ACK-frame listing their preferences. We 89 | then compromise by taking the MIN between them. 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | ( KERMIT) 101 | 102 | We make >LEN, >TYPE, etc relative to the start of the buffer 103 | so we can use the same definitions for both the receiving and 104 | sending buffers. >CKSUM assumes the LEN byte has been 105 | initialized. 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | ( KERMIT - compromise on the parameters) 118 | 119 | COMPROMISE assumes we have an S frame in one buffer and its 120 | ACK frame in the other buffer. We don't care whether we are 121 | the sender or receiver. The compromise takes the more 122 | conservative setting from each buffer as the actual protocol 123 | parameter to use. 124 | 125 | For now, we will ignore all the settings except for MAXL and 126 | TIMEOUT, taking the MIN of MAXL and the MAX of TIMEOUT. 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | MYMENU cheap error handling in the case where the user 135 | chooses to abort the file transfer process. Set up 136 | your own menu ( ' MYREALMENU IS MYMENU ) or allow the 137 | default 'no vector' error to occur. 138 | 139 | KSER-IN gets a serial character and tests whether it is SOH, 140 | all the while checking for a time-out. Returns 141 | character and SOH-flag (true if character is SOH). 142 | In case of time out, return up an extra level, 143 | putting a 'V on the stack as the dummy frame type 144 | indicating a time out followed by a true flag 145 | indicating a 'good' check sum. 146 | Note, KSER-IN is only called by GETFRAME and so is 147 | always called with the correct stack depth. To test 148 | it standalone, nest it once in a test word, as shown 149 | in TEST-IN. 150 | 151 | ( KERMIT) 152 | We "controlify" a control code (0-$1F, $7F) by flipping bit 6 153 | and preceding it with the QCTL character (usually '#). The 154 | QCTL character itself is escaped. We count QCTL as a control 155 | character in CTRL? so we can escape it, but we only flip bit 156 | 6 for actual control characters. Also, consider $7E (~) to 157 | be a control character, as it is used for repeat counts 158 | 159 | (KEMIT puts a character into OUT-BUF and increments the count 160 | KEMIT writes a character into OUT-BUF, escaping it if necessary. 161 | ROOM? says whether there is room in the buffer for another 162 | character. We require 2 bytes available in case the 163 | next character needs to be escaped. If we allowed 164 | high-bit escpaping we would require 3 bytes instead. 165 | 166 | 167 | 168 | ( KERMIT) 169 | CK%% converts the raw checksum of all the bytes 170 | after SOH into a checksum character by wrapping 171 | and characterifying it according to the KERMIT algorithm. 172 | 173 | CKSUM calculates a checksum on a buffer by adding the bytes 174 | in the LEN SEQ TYPE & DATA fields and applying CK%%. 175 | The LEN field must include the cksum byte. 176 | 177 | CKSUM? Calculate the checksum character for the input frame 178 | and compare it to the transmitted checksum character. 179 | Return true if the checksum is good. 180 | 181 | 182 | 183 | 184 | 185 | 186 | MODEM! sends a character to the modem. We defer it to make 187 | testing easy. 188 | 189 | DATA! builds an entire data field, stopping either when out 190 | of source characters or out of room in OUT-BUF. 191 | 192 | BUILD-FRAME Given the address and length of data to be 193 | transferred and the type of the frame, put as much of 194 | the data as will fit into a frame and return the address 195 | and length of the remaining (i.e. unsent) data. 196 | 197 | 198 | 199 | 200 | 201 | 202 | ( KERMIT - debugging aids) 203 | 204 | .FRAME .INB .OUTB are used for testing to dump the contents 205 | of the buffers to the screen. 206 | 207 | TEST1 TEST2 provide some test data 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | ( KERMIT) 220 | 221 | SENDFRAME sends an entire header, from SOH through 1-byte 222 | checksum and ending carriage return, to the "modem." 223 | It sends SOH, sends LEN+1 characters in the OUT-BUF, 224 | and then sends a carriage return. 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | ( KERMIT) 237 | 238 | LIMITS provides data for use in building either an S-frame 239 | or its ACK frame for purposes of negotiating 240 | the protocol as to maximum frame length, etc. 241 | Note that PADC is controlified, but seems not to 242 | be "escaped" -- after all, we haven't agreed upon 243 | the escape character at the time of sending the 244 | S-frame. We build this frame directly into OUT-BUF 245 | to prevent DATA! from escaping any characters. 246 | We say we'll use (~) as the repeat character, but we 247 | will _not_ use repeat counts when we transmit, but we 248 | _will_ handle them when we receive. If the sender does 249 | not escape actual tildes, then we will have a problem. 250 | 251 | 252 | 253 | ( KERMIT) 254 | KINIT sends the 'send-init' frame. It must have sequence zero. 255 | This is the 'S' frame sent by sender in response to the 256 | receiver's initial NAKs. 257 | KINITACK sends a reply to a 'send-init' frame. Before sending 258 | KINITACK (if we are receiving) or after receiving 259 | KINITACK (if we are sending), we must adjust our settings 260 | to the minimum of the sender's and the receiver's requests 261 | Note complex handling of COMPROMISE. 262 | FILEHEADER sends the file name of the file to be transmitted. 263 | 264 | EOF is sent at the end of each file we send. EOT is sent after 265 | we finish sending all the files. Reciever sends ACK or NAK 266 | after each frame is received, depending on whether chksum is 267 | ok. ERROR is sent to abandon the session. I think we will 268 | ignore an ATTRIB frame. 269 | 270 | ( KERMIT) 271 | 272 | EXPECTED holds the count of bytes we expect to receive 273 | following the length byte. 274 | 275 | 276 | SETLENGTH handles the length count for an incoming frame, 277 | initializing EXPECTED and INLEN and putting the 278 | length byte into the input buffer. 279 | 280 | PUT-IN-BUFFER puts input bytes into the buffer and returns 281 | a flag that is true when all the expected bytes 282 | have arrived. 283 | 284 | 285 | 286 | 287 | 288 | GETFRAME is closely tied to KSER-IN and is the only word that 289 | should ever call KSER-IN, as KSER-IN returns upward an extra 290 | level in case of a timeout, supplying the type and cksum flag 291 | (ie 'V -1). So, GETFRAME always succeeds, returning a type 292 | and flag. It watches for an SOH in the middle of a frame and 293 | starts over. What makes GETFRAME tricky is it needs to handle 294 | the usual case as well as a timeout at any time as well as an 295 | unexpected SOH at any time. What makes it simpler is pushing 296 | some of the logic down to the word KSER-IN and letting KSER-IN 297 | terminate not only itself but also GETFRAME in the case of a 298 | timeout, thus producing a dummy V-frame. After that we no 299 | longer have a timeout as a special case, we simply have an 300 | additional "frame" type (i.e. a timeout frame). 301 | 302 | 303 | 304 | ( KERMIT) 305 | 306 | GET-GOOD-FRAME continues to try to get a frame until one 307 | arrives with a good checksum. It will try 308 | forever unless the user aborts the transfer. 309 | (See KSER-IN for test for user abort.) 310 | 311 | 312 | IN-SEQ sequence number of the frame in the input buffer 313 | 314 | GOOD-SEQ? true if the input frame's sequence number is the 315 | expected sequence number. 316 | 317 | 318 | 319 | 320 | 321 | ( KERMIT) 322 | 323 | (GETACK keeps getting frames until one comes in with a good 324 | checksum. V-frames are ok. 325 | 326 | GETACK keeps getting ack frames, handling or ignoring each, as 327 | appropriate. It re-sends the data frame in case of a 328 | V-frame (timeout) or a NAK with the correct sequence 329 | number. It is used only by the sender. Later, it 330 | could bail out if too many NAKs or timeouts occur in a 331 | row, etc. 332 | 333 | READ load up the buffer from the file in preparation for 334 | transmitting it via the serial port 335 | 336 | 337 | 338 | ( KERMIT) 339 | 340 | GET-FIRST-NAK ignores timeouts and sequence numbers and waits 341 | for a NAK from the receiver. 342 | 343 | SEND wait for the prompting NAK frame from receiver 344 | send S-frame ( ie KINIT) 345 | reset serial in to throw away any extra prompting NAKs 346 | get S-frame ACK for SEQ 0 347 | send the entire file, one D-frame at a time 348 | close the file 349 | send end of file and end of transmission 350 | 351 | 352 | 353 | 354 | 355 | ( KERMIT) 356 | 357 | IN-DATA is a buffer for holding the UNCTRL'd data field. Make 358 | it big in case lots of repeat counts are present. 359 | 360 | C!+ stores a character and bumps the address (similar to C@+) 361 | 362 | C@+- gets a character from the 'from' address, increments 363 | the 'from' address and decrements the count of remaining 364 | characters. 365 | 366 | UNCTRL'd if the current character is the QCTL escape character, 367 | get another character and unescape it. 368 | 369 | 370 | 371 | 372 | 373 | REPEAT'd The most recent character was the tilde (~), indicating 374 | the beginning of a 3 or 4 character repeat sequence. 375 | Get the next character as the count and then the next 1 376 | or 2 (if escaped) to find the value to be repeated, & 377 | expand that repeated character into destination buffer. 378 | 379 | UNCTRL copy the escaped and repeated source buffer, 380 | unescaping and expanding as appropriate, to the 381 | destination buffer. 382 | 383 | >IN-DATA copies IN-BUF's data field, which may contain 384 | escaped characters, to IN-DATA with escaped characters 385 | converted to their actual values (and repeated counts 386 | expanded). 387 | 388 | 389 | ( KERMIT) 390 | 391 | BUILDFNAME extracts name of file to be received from an 392 | input F frame and stores it in our KFNAME buffer 393 | as a counted string (and an asciiz string suitable 394 | for passing to DOS for creating the file). 395 | 396 | RCVNAME this is what we do in response to an F-frame: 397 | save the file name in the KFNAME buffer as 398 | a counted, asciiz string, then create the file and 399 | save the handle. 400 | 401 | 402 | 403 | 404 | 405 | 406 | ( KERMIT) 407 | 408 | GET-NEXT Get the next frame we are expecting, ACKing or NAKing 409 | as appropriate. 410 | Always ack with the seq number we received, even if 411 | it wasn't the seq number we expected, thus allowing 412 | sender to continue. But, throw away frames that 413 | do not have the expected seq number. Except, if 414 | V-frame (ie timeout) or if a bad checksum, then 415 | NAK with our expected sequence number. 416 | It is possible a D-frame should not be ACK'd until 417 | after we have written it to disk, in case disk writes 418 | interfere with servicing the serial port. 419 | 420 | WRITE Append input data to the file. 421 | 422 | 423 | ( KERMIT) 424 | 425 | RECEIVE send NAK every second until we see SOH, then get 426 | the rest of that first frame -- until we get the 427 | S-frame. Then compromise on settings and send 428 | an ack for the S-frame. Then, handle the frame 429 | types, getting file name and opening it for an 430 | F-frame, writing D-frames to the file, closing 431 | the file upon getting a Z-frame, and exiting upon 432 | getting a B-frame (EOT). 433 | 434 | 435 | 436 | 437 | 438 | 439 | -------------------------------------------------------------------------------- /extras/kermit/readme.txt: -------------------------------------------------------------------------------- 1 | These files related to Kermit are mostly unchanged from their original 2 | release around 1997 other than a few corrections or notes about my 3 | current email and web addresses and the software license. 4 | 5 | My current email and web site addresses are 6 | 7 | frank@pygmy.utoh.org 8 | 9 | http://pygmy.utoh.org 10 | 11 | 12 | -- 13 | Frank 14 | -------------------------------------------------------------------------------- /files.txt: -------------------------------------------------------------------------------- 1 | The Pygmy Forth version 1.7 package of May, 2007 consists of the 2 | following files: 3 | 4 | 4intro.txt short introduction to Forth 5 | 6 | ed.dow simple line editor shadow blocks 7 | ed.scr simple line editor source blocks 8 | 9 | files.txt this file 10 | 11 | license20040130.txt license 12 | 13 | pygmy.com the program itself. It includes the kernel, the 14 | editor, the assembler, and extensions to allow 15 | printing the source code. 16 | 17 | pygmy.dow shadow blocks for pygmy.scr 18 | pygmy.scr block file containing the source code for the 19 | kernel, editor, assembler, meta-compiler, and various 20 | extensions. 21 | 22 | pygmy.txt the Pygmy Forth manual 23 | 24 | readme brief start up information 25 | 26 | serial.dow shadow blocks for serial.scr 27 | serial.scr serial port source code 28 | 29 | tutorial.txt short Pygmy Forth tutorial 30 | 31 | yourfile.dow (blank) shadow blocks for yourfile.scr 32 | yourfile.scr an empty block file all ready for you to program 33 | in. It is provided so you can get started right 34 | away without having to worry about creating or 35 | opening files. 36 | 37 | ./extras: 38 | 6811asm.dow source, shadow, and documentation on 39 | 6811asm.scr the Pygmy 68HC11 assembler 40 | 6811asm.txt 41 | 42 | cmforth.dow source and shadow blocks for the base 43 | cmforth.scr and inspiration for Pygmy 44 | 45 | doubquad.scr higher precision math routines 46 | 47 | help.txt article on creating help screens 48 | 49 | metacomp.txt article on the metacompiler 50 | 51 | 52 | ./extras/3ins4th: article and code for "A 3-Instruction Forth" 53 | 3ins4th.html 54 | demo.scr 55 | mona1.scr 56 | mond0.scr 57 | mone1.scr 58 | monitor.txt 59 | readme 60 | 61 | ./extras/cfth: article on calling C routines from Forth 62 | bgi.dow and vice versa 63 | bgi.scr 64 | cpyg.txt 65 | lp.c 66 | 67 | ./extras/kermit: the Kermit file transfer protocol in Pygmy 68 | kermit.dow 69 | kermit.scr 70 | listing.ker 71 | pfaaaa.ann 72 | pfaaaa.txt 73 | pfkerm.doc 74 | pfkerm.msg 75 | pfkerm.src 76 | pfkerm.txt 77 | readme.txt 78 | -------------------------------------------------------------------------------- /license20040130.txt: -------------------------------------------------------------------------------- 1 | January 30, 2004 2 | 3 | This my "modified BSD/MIT/X license". It applies to all the 4 | software I create which contains a note such as the following 5 | in the source distribution: 6 | 7 | Copyright (c) 2004 Frank C. Sergeant 8 | Freely available under a modified BSD/MIT/X license. 9 | Details at http://pygmy.utoh.org/license20040130.txt. 10 | 11 | All rights reserved. 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining 14 | a copy of this software and associated documentation files (the 15 | "Software"), to deal in the Software without restriction, including 16 | without limitation the rights to use, copy, modify, merge, publish, 17 | distribute, and/or sell copies of the Software, and to permit persons 18 | to whom the Software is furnished to do so, provided that the above 19 | copyright notice(s) and this permission notice appear in all copies of 20 | the Software and that both the above copyright notice(s) and this 21 | permission notice appear in supporting documentation. (Providing a 22 | url to http://pygmy.utoh.org/license20040130.txt suffices.) 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 27 | OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 28 | HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY 29 | SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER 30 | RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 31 | CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 32 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 33 | 34 | -------------------------------------------------------------------------------- /pygmy.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/utoh/pygmy-forth/21d555e1592ed266f3156d2a62e75a553cdbf9bf/pygmy.com -------------------------------------------------------------------------------- /readme: -------------------------------------------------------------------------------- 1 | This is the Pygmy Forth version 1.7 which may be used and distributed 2 | freely. See the license in license20040130.txt or at 3 | http://pygmy.utoh.org/license.html. 4 | 5 | It runs on the IBM PC and clones and emulators such as DOS, Microsoft 6 | Windows, FreeDOS and the DOS emulator under Linux, etc. It includes a 7 | multi-tasker and the ability to call C library routines and vice 8 | versa. 9 | 10 | To use it, create a directory for it and unzip 11 | PYGMY17.ZIP into that directory, e.g. 12 | 13 | C: 14 | CD \ 15 | MD PYGMY 16 | CD PYGMY 17 | COPY A:\PYGMY.ZIP 18 | UNZIP PYGMY.ZIP 19 | 20 | You can use any unzip program. I use the InfoZIP unzip. 21 | 22 | Then, read the manual, PYGMY.TXT. 23 | 24 | -- Frank 25 | May, 2007 26 | 27 | Frank Sergeant 28 | frank@pygmy.utoh.org 29 | http://pygmy.utoh.org 30 | -------------------------------------------------------------------------------- /yourfile.dow: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /yourfile.scr: -------------------------------------------------------------------------------- 1 | --------------------------------------------------------------------------------