Forth/PSoC Forth

From Wikibooks, open books for an open world
< Forth
Jump to: navigation, search

Contents

how to install PSoC Forth [edit]

Ingredients:

  • a PSoC microcontroller
  • a PSoC flash-burner such as the ICE-Cube (lets you debug, set breakpoints, single-step through your code, etc.) or the MiniProg (costs less).
  • a PC that can run PSoC Designer for Windows or the M8Cutils for Linux.
  • Create the hex file "psoc_forth.hex": either
    • If you have a Windows box, use PSoC Designer (details below), or
    • If you have a Linux box or a Macintosh, use M8Cutils.
    • ( Both development tools are free downloads. )
  • Use the PSoC programmer to burn the hex file into the microcontroller.

creating the hex file with M8Cutils [edit]

Unfinished -- needs work

one-time install:

... Need more details here ...

creating the hex file with PSoC designer [edit]

Unfinished -- needs work

one-time install:

  • Run PSoC Designer to create a new project
    • create new project. New project name: "interactive" (without quotes). base part: 27443.
    • Generate 'Main' file using: Assembler. Finish.
  • Download "One Wire User Module" by Wes Randall from http://www.psocdeveloper.com/uploads/media/OneWire_v1.3.3.zip , and install the "OneWireSW" custom user module. (FIXME: how?)
  • In the "user module selection view", choose the "user modules" you might need: (You can select and place one at a time, or select all of them, then place all of them).
    • Digital Comm: Uart (double-click on it to create UART_1)
    • Temperature: FlashTemp
    • 3 "SAR6" modules -- rename them "sar1", "sar2", and "sar3".
    • one "OneWireSW" module
    • one INSAMP -- rename it "amp".
  • In "interconnect view", place all the user modules. (right-click on each one and choose "place"). (The "placed" modules have a thick colored rectangle around them. The ones you haven't placed yet have no rectangle or only a thin black rectangle around them)
  • In the "ApplicationEditor" view, hit "Build" (F7).
    • You should get the message "0 error(s) 0 warning(s)".
  • Copy the psoc_forth.asm source code into a file "psoc_forth.asm", in the same directory as the "main.asm" we just created.
  • Download "Algorithm - Unsigned Multiplication - AN2032" by Dave Van Ess, and extract the file "unsignedmath.inc" and put it in the same directory as "psoc_forth.asm":
    • (Um... wouldn't "Algorithm - Signed Multi-Byte Multiplication - AN2038" be better?)
  • In the "ApplicationEditor" view, select Project | Add to project | Files... and select "psoc_forth.asm".
  • In the "ApplicationEditor" view, hit "Build" (F7).
    • You should get the message "0 error(s) 0 warning(s)". (FIXME: ... I never got this far ...)
  • edit the source file "main.asm" and just before the ".terminate", add the line
        jmp start ; start Forth interpreter
  • In the "ApplicationEditor" view, hit "Build" (F7) to create the hex file.


interactive development [edit]

  • connect serial port on the microcontroller to a terminal. (Perhaps the same PC used above, running a terminal emulator; or a PDA serial port, or a dumb terminal). need more details
  • ...


the source [edit]

;    psoc_forth.asm -- kernal 16 bit forth for PSoC 27443 - 28 pin device
;    copyright 2003, Christopher W. Burns
;    This program is free software; you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation; either version 2 of the License, or
;    (at your option) any later version.
 
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
 
;    You should have received a copy of the GNU General Public License
;    along with this program; if not, write to the Free Software
;    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
; Modified 20070821   WFT Electronics   wftElectronics.com
; b001   DHD ( Bill Goodrich ) and AGSC   Denver, CO
; same licensing as above
; some slight changes and notes by Gus Calabrese and Bill Goodrich,
; in hopes of creating a workable version for newer PSOCs, like
; our CY8C29466.
 
 
;memory map
        include "m8c.inc"
        include "unsignedmath.inc"
        include "uart_1.inc"     ; install UART   can we install another UART ? b001
;       include "counter8_1.inc"
        include "sar1.asm"
        include "sar2.asm"
        include "sar3.asm"
        include "amp.asm"
        include "flashtemp_1.asm"
        include "flashtemp_1int.asm"
        include "onewiresw_1.asm"
;__________________________________________________________________________________
;00|                                                                               |
;10|                                                                               |
;20|            FLASH WRITE BUFFER                                                     |
;30|_______________________________________________________________________________|
;40|            PARAMETER STACK                                                        |
;50|                                                                               |
;60|                                                                               |
;70|                                                                               |
;80|_________RETURN STACK__________________________________________________________|
;90|                                                                               |
;A0|                                                                               |
;B0|_______________________________________________________________________________|
;C0|_cnt|TEXT INPUT BUFFER                                                         |
;D0|_______________________________________________________________________________|
;E0|___IP____|____W____|___HERE__|___LAST__|_CURRENT_|bloc|loc_|_rp_|base|_IN_|____|
;F0|_________|_________|_________|_________|___T0____|____T1___|___T2____|___T3____|
IP:             equ             e0h
W:              equ             e2h
HERE:   equ             e4h
LAST:   equ             e6h
CURRENT:equ             e8h
bloc:   equ             eah
loc:    equ             ebh
rp:             equ             ech
base:   equ             edh
IN:             equ             eeh
 
T0:             equ             f8H
T1:             equ             fah
T2:             equ             fch
T3:             equ             feh
 
sp0:    equ             40h
rp0:    equ             90h
 
cnt:    equ             c0h
TIB:    equ             c1h
EOT:    equ             e0h
 
;boot block structure mirrored in RAM
vcurr:          equ     0
vlast:          equ     2
vhere:          equ     4
vbase:          equ     6
 
;--------------------------------------------------------------------------------------
;macros
;--------------------------------------------------------------------------------------
macro   next
                ljmp    _next
endm
 
macro   pushW
                ljmp    _pushW
endm
 
macro   incr
                inc     [@0+1]
                adc     [@0],0
endm            
 
macro   colon
                lcall   _colon
endm
 
macro   doCon
                lcall   _doCON
endm            
 
macro   fetch
                mov     a, [IP]
                mov     x, [IP+1]
                romx
                mov     [@0], a
                incr    IP
endm            
 
macro   pushs
                mov a,[@0]
                push a
                mov a, [@0+1]
                push a
endm
;********************************************************************************       
;pop the stack into a word register
;********************************************************************************       
macro   pops            
                pop     a                               ;1
                mov [@0+1], a           ;2
                pop     a                               ;1
                mov     [@0], a                 ;2
endm
;********************************************************************************       
 
macro   pushr
                mov x, [rp]
                dec x
                mov a, [@0]
                mov [x], a
                dec x
                mov a, [@0+1]
                mov [x], a
                mov [rp], x
endm
 
macro   popr
                mvi     a,[rp]
                mov     [@0+1], a
                mvi     a,[rp]
                mov [@0], a
endm
 
;       header structure
;       <len><"name"><LINK address><flags>|CODE FIELD|
macro   head
                db      @0
                ds      @1
                dw      @2
                db      @3
endm            
;-------------------------------------------------------------------------------------------------              
        area    kernal16(rom,abs)
 
        org             540h
send:   M8C_DisableGInt
                push a
send0:  mov A,  REG[UART_1_TX_CONTROL_REG]
                and     a,  16
                jz      send0
                pop     a
                mov REG[UART_1_TX_INPUT_REG], a
                ret     
read_blk:       
                mov [0f8h],3ah  ;should be 3ah
                mov X,sp
                mov a,X
                add a,3         
                mov [0f9h],a    ;sp+3
                mov [0fah],[W+1]   ;block id
                mov [0fbh], 0  ;buffer pointer
                mov [0fch],15   ;clock
                mov [fdh], 0
                mov [feh], 0
                mov [ffh], 0
                mov a,01
                SSC                             ;erase block
                nop
                nop
                nop
                ret     
blk_write:      
                mov [0f8h],3ah  ;should be 3ah
                mov X,sp
                mov a,X
                add a,3         
                mov [0f9h],a    ;sp+3
                mov [0fah],[W+1]   ;block id
                mov [0fbh], 0  ;buffer pointer
                mov [0fch],15   ;clock
                mov [fdh], 0
                mov [feh], 0
                mov [ffh], 0
                mov a,03
                SSC                             ;erase block
                nop
                nop
                nop
 
                mov [0f8h],3ah       ;should be 3ah
                mov X,sp
                mov a,X
                add a,3         
                mov [0f9h],a             ;sp+3
                mov [0fah],[W+1]                 ;block id
                mov [0fbh],0             ;buffer pointer
                mov [0fch],15            ;clock
                mov [fdh], 0
                mov [feh], 0
                mov [ffh], 0    
                mov a,02
                SSC                             ;write block
                nop     
                nop
                nop
                ret             
 
start:: mov             a,sp0
                swap    a,sp                                            ;initialize the stack
                mov         [rp],rp0                                    ;initialize the return stack
                lcall   OneWireSW_1_Start                       ;initialize one wire protocall
;********************************************************************************               
;initialize the UART
;********************************************************************************
;               or   reg[Counter8_1_CONTROL_REG],1
        or   REG[UART_1_TX_CONTROL_REG], 1
        or   REG[UART_1_RX_CONTROL_REG], 1
;********************************************************************************       
                mov     [IP],>FORTH
                mov [IP+1],<FORTH                                       ;point to the main FORTH loop
                mov     a, reg[8]                                               ;check saftey is set 
;               mov a, reg[12]                                          ;use pin 1.1 for 27143
                and a, 2
                jz      user
;********************************************************************************
;this is the default start
;********************************************************************************               
                mov [CURRENT],>cold                                     
                mov [CURRENT+1],<cold                           ;set current to "cold"
                next                                                            ;start FORTH
;********************************************************************************
; this is the user's start up
;********************************************************************************
user:   mov a, >Vcurrent                                        
                mov x, <Vcurrent                                        ;User's startup
                romx
                mov     [CURRENT],a                                             ;
                mov a, >Vcurrent
                inc     x
                romx
                mov     [CURRENT+1],a
                next
;********************************************************************************
;MAIN FORTH LOOP
;fetch the vector from "current" and execute.  When done, continous loop.
;********************************************************************************               
FORTH:  dw      current,at,execute,br,FORTH             
;-------------------------------------------------------------------------------------------
;headerless words
;-------------------------------------------------------------------------------------------
;colon  IP->rstack
;               pstack->IP
;               next
;get to colon by LCALL _colon the return address pushed by LCALL is the new IP
_colon: pushr   IP
                pops    IP
                next
;********************************************************************************               
;exit  rstack->IP
;********************************************************************************
exit:   popr    IP                                      ;pop the return address into the instruction pointer
                next
;********************************************************************************
;br     Branch to an inline address
;********************************************************************************               
br:             fetch   W
                fetch   W+1
                mov     [IP],[W]
                mov     [IP+1],[W+1]
                next
;********************************************************************************
;zbr    Branch to an inline address if TOS is 0, otherwise skip         
;********************************************************************************
zbr:    pops    W
                mov a, [W]
                or a,[W+1]
                jz      br
pass:   add     [IP+1],2
                adc     [IP],0
                next
;********************************************************************************
;nzbr   Branch to an inline address if TOS <> 0, other wise skip
;********************************************************************************               
nzbr:   pops    W
                mov     a,[W]
                or a,[W+1]
                jnz     br
                jmp     pass
;********************************************************************************
;lit    Pushes an inline word onto the parameter stack
;********************************************************************************               
lit:    fetch W
                fetch W+1
                pushW
;********************************************************************************               
;doCON get here by LCALL _doCON  - pushs address of constant on the stack
; and then fetches constant to the stack
;********************************************************************************
_doCON: pop     x
                pop a
                push    a
                romx
                mov [W], a
                pop     a
                inc     x
                adc     a,0
                romx
                mov [W+1],a
                pushW
;********************************************************************************               
;xquote send an counted string to the UART
;********************************************************************************
xquote: fetch   W                       ;length in W
xquote_loop:
                fetch   W+1                     ;char->W+1
                mov a, [W+1]
                call    send            ;send it out
                dec     [W]                             ;decrease count
                jnz xquote_loop         ;if it's not zero do it again
                next                            ;IP points to next token
;********************************************************************************
;doTable - push the address of the next word on the stack
;********************************************************************************
macro   doTABLE
        lcall   _next
endm            
 
 
 
;-----------------------------------------------------------------------------------------------
;inner interpreter - 
;                                               -check for an interrupt
;                                               ROM[IP]->W
;                                               IP+2->IP
;                                               W->stack
;                                               jmp(TOS)
;       
;********************************************************************************       
_pushW: pushs   W                                               ;push W register
_next:  fetch   W
                fetch   W+1                                             ;ROM[IP]->W IP+2
                pushs   W                                               ;W-> stack
                ret                                                             ;jmp[TOS]       
 
;               
;--------------------------------------------------------------------------------------------
;the DICTIONARY
;--------------------------------------------------------------------------------------------
;********************************************************************************       
;emit ( char -- ) send a character to UART
;********************************************************************************       
;done in FORTH  24 bytes
;********************************************************************************                               
Lemit:  head    4,'emit',0,0
;emit:  colon
;emit0: dw      lit,UART_1_TX_CONTROL_REG,regat
;               dw      lit,16,pand
;               dw      zbr,emit0
;               dw      lit,UART_1_TX_INPUT_REG,regsto,exit
;********************************************************************************       
;emit done as machine code - 20 bytes
;********************************************************************************                       
emit:   pops    W                                                               ;get the character
emit0:  mov a,reg[UART_1_TX_CONTROL_REG]                ;see if the UART is ready
                and a, 16
                jz      emit0
                mov a, [W+1]            
                mov reg[UART_1_TX_INPUT_REG], a                 ;send it out
                next
;********************************************************************************                                       
;drop   ( x -- ) drop TOS
;********************************************************************************       
Ldrop:  head    4,'drop',Lemit,0
drop:   add     sp,-2
                next
;********************************************************************************       
;dup    ( x -- x x ) copy TOS
;********************************************************************************       
Ldup:   head    3,'dup',Ldrop,0
dup:    pops    W
                pushs   W
                pushW
;********************************************************************************                       
;swap   ( a b -- b a )
;********************************************************************************       
Lswop:  head    4,'swap',Ldup,0
swop:   pops    T0
                pops    W
                pushs   T0
                pushW
;********************************************************************************                       
;over   ( a b -- b a b )
;********************************************************************************       
Lover:  head    4,'over',Lswop,0
over:   pops    T0
                pops    W
                pushs   W
                pushs   T0
                pushW           
;********************************************************************************                       
;1+             (a -- a+1 ) increment TOS
;********************************************************************************       
Lplone: head    2,'1+',Lover,0
plone:  pops    W
                incr    W
                pushW
;********************************************************************************                       
;1-             (a -- a-1) decrement TOS
;********************************************************************************       
Lmione: head    2,'1-',Lplone,0
mione:  pops    W
                dec     [W+1]
                sbb [W],0
                pushW
;********************************************************************************                       
;sp@    ( -- sp) where is sp pointing
;********************************************************************************       
Lspat:  head    3,'sp@',Lmione,0
spat:   mov [W],0
                mov x,sp
                mov [W+1],x
                pushW
;********************************************************************************                       
;rp@    ( -- rp) where is rp pointing 
;********************************************************************************       
Lrpat:  head    3,'rp@',Lspat,0
rpat:   mov [W],0
                mov [W+1],[rp]
                pushW                           
;********************************************************************************                       
;sp!    ( x -- ) point sp to x
;********************************************************************************       
Lspsto: head    3,'sp!',Lrpat,0
spsto:  pops    W
                mov a, [W+1]
                swap    a, sp
                next
;********************************************************************************                       
;rp!    ( x -- ) point rp to x
;********************************************************************************       
Lrpsto: head    3,'rp!',Lspsto,0
rpsto:  pops    W
                mov [W],0
                mov [rp],[W+1]
                next
;--------------------------------------------------------------------------------------------
;math
;-------------------------------------------------------------------------------------------
;+              ( a b -- a+b) add top
Lplus:  head    1,'+',Lrpsto,0
plus:   pops    T0
                pops    W
                mov a, [T0+1]
                add     [W+1],a
                mov a,[T0]
                adc     [W],a
                pushW
;********************************************************************************                       
;-              ( a b -- b-a ) subtract top
;********************************************************************************       
Lminus: head    1,'-',Lplus,0
minus:  pops    T0
                pops    W
                mov a, [T0+1]
                sub     [W+1],a
                mov a, [T0]
                sbb     [W],a
                pushW
;********************************************************************************                       
; *     ( a b -- a*b ) 16 multiplication
;********************************************************************************       
Lmul:   head    1,'*',Lminus,0
mul:    pops    T0                      ;X
                pops    T1                      ;Y
                Multiply16_16_16        W,T0,T1
                pushW
;********************************************************************************       
;/mod   ( a b -- b/a  b%a)
;********************************************************************************       
Ldivmod: head 4,'/mod',Lmul,0
 
divmod: pops    T0
                pops    T1      
                call    div16
                pushs   W
                pushs   T1
                next
div16:          
                mov [W+0],00h                   ;clear Remainder
                mov [W+1],00h
                and F,fbh                               ;clear carry flag
                mov [T3],16             ;load loop count to 16 for 16 bit division
d16u_1:         
                rlc [T1+1]                              ;rotate left through dividend and remainder
                rlc [T1+0]                              
                rlc [W+1]                               
                rlc [W+0]                               
                mov [T2+0],[W+0]                ;make backup of remainder
                mov [T2+1],[W+1]
                mov a,[W+1]                     ;subtract divisor from remainder
                sub a,[T0+1]
                mov [W+1],a
                mov a,[W+0]
                sbb a,[T0+0]
                mov [W+0],a
                jnc d16u_2                                      
                mov [W+1],[T2+1]                ;if result is negative
                mov [W+0],[T2+0]                ;restore remainder from backup
                and [T1+1],feh                  ;clear LSB of dividend
                jmp chkLcount16 
d16u_2:         
                or [T1+1],01h                   ;if result is positive set LSB of dividend
chkLcount16:
                dec [T3]                        
                jnz d16u_1                              ;repeat till 16 bits are done
                ret             
;----------------------------------------------------------------------------------------------         
;memory ops
;----------------------------------------------------------------------------------------------
;@              ( x -- ram[x]) get word at RAM[x]
Lat:    head    1,'@',Ldivmod,0
at:             pops    T0
                mov     x,[T0+1]
                mov     a,[x+0]
                mov [W], a
                mov a, [x+1]
                mov [W+1], a
                pushW
 
;c@             ( x -- ram[x] ) get byte at RAM[x]
Lcat:   head    2,'c@',Lat,0
cat:    pops    T0
                mov x,[T0+1]
                mov [W],0
                mov a, [x]
                mov [W+1],a
                pushW
 
;rom@   ( x -- rom[x]) get a word in rom
Lromat: head    4,'rom@',Lcat,0
romat:  pops    T0
                mov a, [T0]
                mov x,[T0+1]
                romx
                mov [W],a
                mov a,[T0]
                inc x
                adc a,0
                romx
                mov [W+1],a
                pushW
 
;romc@  ( x -- rom[x]) get a byte from rom
Lromcat:        head 5,'romc@',Lromat,0
romcat: pops    T0
                mov a, [T0]
                mov x, [T0+1]
                romx
                mov [W+1],a
                mov [W],0
                pushW           
 
;!      ( a b -- ) store word b in ram[a]                               
Lsto:   head    1,'!',Lromcat,0
sto:    pops    T0
                pops    T1
                mov x, [T0+1]
                mov a, [T1]
                mov [x], a
                mov a, [T1+1]
                mov [x+1], a
                next
 
;c!     ( a b -- ) store byte a in ram[b]
Lcsto:  head    2,'c!',Lsto,0
csto:   pops    T0
                pops    T1
                mov x, [T0+1]
                mov a, [T1+1]
                mov [x], a
                next            
 
;+!     ( a b -- ) add a to ram[b]      (word)
Lpsto:  head    2,'+!',Lcsto,0
psto:   pops    T0
                pops    T1
                mov x, [T0+1]   ;x points to lsb of destination
                mov a, [T1+1]   ;a=lsb of number
                add [x+1], a
                mov a, [T1]             ;a=msb of number
                adc [x], a
                next
 
;+c! ( a b -- ) add b to ram[a] (byte)          
Lpcsto: head    3,'+c!',Lpsto,0
pcsto:  pops    T0
                pops    T1
                mov x,[T0+1]
                mov a, [T1+1]
                add [x+0], a
                next
 
;----------------------------------------------------------------------------------------------
;system constants
;----------------------------------------------------------------------------------------------
 
LBASE:  head    4,'BASE',Lpcsto,0
BASE:   doCON
                dw      base
 
LHERE:  head    4,'HERE',LBASE,0
here:   doCON
                dw      HERE
 
LLAST:  head    4,'LAST',LHERE,0                
last:   doCON
                dw      LAST
Lcurrent: head 7,'CURRENT',LLAST,0
current: doCON
                dw      CURRENT
 
Lin:    head    2,'IN',Lcurrent,0
in:             doCON           
                dw      IN
 
LBLOC:  head    4,'BLOC',Lin,0
BLOC:   doCON
                dw      bloc
 
LLOC:   head    3,'LOC',LBLOC,0
LOC:    doCON
                dw      loc
;---------------------------------------------------------------------------------------------
;return stack ops
;---------------------------------------------------------------------------------------------
Ltor:   head    2,'>R',LLOC,0
tor:    pops    W
                pushr   W
                next
 
Lfromr: head    2,'R>',Ltor,0                           
fromr:  popr    W
                pushW
 
Lrat:   head    2,'R@',Lfromr,0
rat:    popr    W
                pushr   W
                pushW
 
;---------------------------------------------------------------------------------------------
;comparison
;---------------------------------------------------------------------------------------------
Leq:    head    1,'=',Lrat,0
eq:             pops    T0
                pops    W
                mov a, [W]
                cmp     a, [T0]
                jnz     false
                mov a, [W+1]
                cmp     a,[T0+1]
                jnz     false
negone:         
true:   mov a, -1
                push a
                push a
                next
zero:           
false:  mov a, 0
                push a
                push a
                next
;<      ( a b -- t|f ) true if a<b false otherwise
Llt:    head    1,'<',Leq,0
lt:             pops    W
                pops    T0
                mov a, [T0]
                cmp     a, [W]
                jc      true
                jz      lt0
                jmp     false
lt0:    mov a,[T0+1]
                cmp     a,[W+1]
                jc      true
                jmp     false
 
Lexecute: head  7,'execute',Llt,0
execute:        ret             
;******************************************************************************************
;?key   ( -- T char | F ) If there is a character, return true and char
;******************************************************************************************     
Lqkey:  head    4,'?key',Lexecute,0
qkey:   mov A,  REG[UART_1_RX_CONTROL_REG]
                and     a, 8
                jnz get_char
                ljmp false
get_char:
                mov A, REG[UART_1_RX_BUFFER_REG]
                mov [W], 0
                mov [W+1],a
                pushs W
                ljmp true               
;******************************************************************************************     
;key    ( -- char )  get a character from the UART
;******************************************************************************************     
Lkey:   head    3,'key',Lqkey,0
key:    colon
key0:   dw      qkey,zbr,key0
                dw      exit
 
Lregsto:        head 4,'reg!',Lkey,0
regsto: pops    W
                pops    T0
                cmp     [W],1
                jnz     regsto0
                m8c_SetBank1
regsto0:                
                mov x, [W+1]
                mov a, [T0+1]
                mov reg[x],a
                m8c_SetBank0
                next
 
Lregat: head 4,'reg@',Lregsto,0
regat:  pops    W
                cmp     [W],1
                jnz     regat0
                m8c_SetBank1
regat0: mov x,[W+1]
                mov a,reg[x]            
                m8c_SetBank0
                mov [W+1],a
                mov [W],0
                pushW
 
 
Lregor: head    5,'regor',Lregat,0
regor:  pops    W
                pops    T0
                cmp     [W],1
                jnz     regor0
                m8c_SetBank1
regor0: mov x, [W+1]
                mov a,reg[x]
                or a,[T0+1]
                mov reg[x],a
                m8c_SetBank0
                next
 
Lregand: head 6,'regand',Lregor,0
regand: pops    W
                pops    T0
                cmp     [W],1
                jnz     regand0
                m8c_SetBank1
regand0:mov x, [W+1]
                mov a, reg[x]
                and a, [T0+1]
                mov reg[x],a
                m8c_SetBank0
                next
 
Lregxor: head 6,'regxor',Lregand,0
regxor: pops    W
                pops    T0
                cmp     [W],1
                jnz     regxor0
                m8c_SetBank1
regxor0:mov x, [W+1]
                mov a,reg[x]
                xor a, [T0+1]
                mov reg[x],a
                m8c_SetBank0
                next
 
Land:   head    3,'and',Lregxor,0       ; b000 and word
pand:   pops    T0
                pops    T1
                mov a, [T0+1]
                and a, [T1+1]
                mov [W+1],a
                mov a, [T0]
                and a, [T1]
                mov [W],a
                pushW
 
Lor:    head    2,'or',Land,0            ; b000  or word
por:    pops    T0
                pops    T1
                mov a, [T0+1]
                or a, [T1+1]
                mov [W+1],a
                mov a, [T0]
                or a, [T1]
                mov [W],a
                pushW           
 
Lxor:   head    3,'xor',Lor,0       ; b000  xor word
pxor:   pops    T0
                pops    T1
                mov a, [T0+1]
                xor a, [T1+1]
                mov [W+1],a
                mov a, [T0]
                xor a, [T1]
                mov [W],a
                pushW                           
 
Lnot:   head    3,'not',Lxor,0         ; b000  not word
not:    pops    W
                mov a, [W+1]
                cpl a
                mov [W+1], a
                mov a,[W]
                cpl     a
                mov [W],a
                pushW
 
Lnegate:head    6,'negate',Lnot,0
negate: colon
                dw      not,plone,exit
 
Ltwostar:head   2,'2*',Lnegate,0
twostar:pops    W
                asl     [W+1]                                   ;shift left ignoring carry (low byte)
                rlc     [W]                                             ;shift left including carry     (high byte)
                pushW
 
Ltwodiv:head    2,'2/',Ltwostar,0
twodiv: pops    W
                asr     [W]                                             ;shift right ignoring carry (high byte)
                rrc     [W+1]                                   ;shift right including carry (low byte)1]
                pushW                                           
 
 
Lshout:head     5,'shout',Ltwodiv,0      ; b001   shift out ?
shout:  pops    T0
                mov [W],0
                mov [W+1],0
                asr [T0]                                        ;shift right ignoring carry (high byte)
                rrc [T0+1]                                      ;shift right including carry (low byte)
                rlc [W+1]                                       ;put the carry value into lsb
                pushs T0                                        ;push the shifted source
                pushW                                           ;push the lsb
 
 
 
Lzeq:   head    2,'0=',Lshout,0
zeq:    pops    W
                mov     a,[W]
                or      [W+1],a
                jz      true
                jmp     false
 
Lgt:    head    1,'>',Lzeq,0
gt:             colon
                dw      swop,lt,exit
 
Lneq:   head    2,'<>',Lgt,0
neq:    colon
                dw      eq,zeq,exit
 
Ldotq:  db      2,46,34      ; 2 chars '." '   dot-quote dot quote   b001
                dw      Lneq
                db      1
dotq:   colon
                dw      lit,xquote,tickw
dotq0:  dw      word,zbr,dotq1  
                dw      lit,TIB
                dw      lit,cnt,cat,dup,tick
dotq2:  dw      swop,dup,cat,tick
                dw      plone,swop,mione,dup
                dw      nzbr,dotq2
                dw      drop,drop,exit          
dotq1:  dw      accept,br,dotq0         
 
Lcount: head    5,'count',Ldotq,0
count:  colon
                dw      dup,romcat,swop,plone,swop,exit
 
Ltype:  head    4,'type',Lcount,0
type:   colon
type_loop:
                dw      swop,dup,romcat,emit,plone
                dw      swop,mione,dup
                dw      zbr,type_done
                dw      br,type_loop
type_done:
                dw      drop,drop,exit          
 
Laccept:head    6,'accept',Ltype,0
accept: colon
                dw      reset_in                                        ;reset IN
                dw      lit,'>',emit                            ;prompt
accept0:dw      key                                                     ;get a char
                dw      dup, lit,28h, pxor
                dw      zbr,comment
accept1:dw      dup,emit                                                ;print it
                dw      dup,lit,13,pxor                         ;is it a CR
                dw      zbr, EOL                                        ;then handle it
                dw      dup,lit,8,pxor                          ;is it a BKSP
                dw      zbr,BKSP                                        ;then handle it
                dw      in, cat, csto                           ;store in TIB
                dw      in, cat, plone,dup
                dw      lit, EOT,lt                                     ;end of TIB?
                dw      zbr,TIB_FULL
                dw      in,csto
                dw      br,accept0                                      ;do it again
comment:dw      drop
comment0:
                dw      key,lit,29h,pxor
                dw      nzbr, comment0
                dw      br,accept0              
TIB_FULL:
                dw      xquote
                db      11
                ds      'TIB FULL!'
                db      13,10
                dw      br,EOL0
EOL:    dw      lit,10,emit                                     ;send a LF
                dw      drop
EOL0:   dw      zero                                            ;replace CR with 0
                dw      in,cat,csto                                     ;to mark end
                dw      reset_in,exit                           ;reset and exit                                         
BKSP:   dw      in,cat,lit,TIB,pxor
                dw      zbr,BKSP0
                dw      lit,20h,emit                            ;wipe out character
                dw      emit                                            ;back up again
                dw      in,cat,mione                            ;back up IN
                dw      in,csto
                dw      br,accept0                                      ;get another 
BKSP0:  dw      drop,lit,'>',emit
                dw      br,accept0              
reset_in: colon
                dw      lit,TIB,in,csto,exit
 
 
Llfa:   head    3,'lfa',Laccept,0
lfa:    colon
                dw      count,plus,exit
 
Lcfa:   head    3,'cfa',Llfa,0
cfa:    colon
                dw      lfa,lit,3,plus,exit
 
Llex:   head    3,'lex',Lcfa,0
lex:    colon
                dw      lfa,lit,2,plus,exit             
 
;word ( -- T|F )        moves next token to TIB.  Returns T if a word if a word is assembled, 
;                                       returns false if not.
word:   mov x, TIB
                mov [cnt], 0
skip:   mvi     a,[IN]
                jz      false
                cmp     a, 33
                jc      skip            ;ignore white space             
scan:   mov     [x+0], a
                inc     [cnt]
                inc     x
                mvi     a,[IN]
                jz      word_done1
                cmp     a, 33
                jc      true
                jmp     scan
word_done1:
                dec     [IN]            ;so that next time word fails
                jmp     true
 
swab:   pops    T0
                mov [W+1], [T0]
                mov [W],[T0+1]
                pushW
 
 
d2a:    colon
                dw      dup,lit,9,gt
                dw      zbr,d2a0
                dw      lit,7,plus
d2a0:   dw      lit,30h,plus,emit,exit          
 
Ldot:   head    1,'.',Llex,0            
dot:    colon
                dw      zero,swop
dot0:   dw      BASE,cat,divmod,swop,tor
                dw      swop,plone,swop,dup,nzbr,dot0
                dw      drop
dot1:   dw      fromr,d2a,mione,dup,nzbr,dot1
                dw      drop,exit               
 
Lspc:   head 3,'spc',Ldot,0
spc:    colon
                dw      lit, 20h, emit, exit
 
Lcrlf:  head    4,'crlf',Lspc,0
crlf:   colon
                dw      lit,13,emit
                dw      lit,10,emit,exit
 
Lwords: head    5,'words',Lcrlf,0
words:  colon
                dw      last, at        
words_loop:
                dw      dup,count,type,lit,20h,emit
                dw      lfa,romat,dup
                dw      zbr,words_done
                dw      br,words_loop
words_done:
                dw      drop,crlf,exit                  
 
;match  ( nfa -- t|f ) see if TOS and word match
match:  mov     [T0], cnt
                mov     [W],[cnt]
                inc     [W]
                pop     x
                pop     a
match_loop:
                push    a
                romx
                mov [W+1], a
                mvi     a, [T0]
                cmp     a,[W+1]
                jnz     no_match
                pop     a
                inc     x
                adc     a, 0
                dec     [W]
                jz      true
                jmp     match_loop
no_match:
                pop     a
                jmp     false
 
; find ( -- [nfa t]|f ) see if WORD is in the dictionary. If it is,
;                                               return true and nfa, else, return false.
find:   colon
                dw      last, at
find_loop:
                dw      dup, match
                dw      zbr, find_next
                dw      true,exit                               ;leaves nfa and true                                    
find_next:
                dw      lfa,romat,dup
                dw      zbr,not_found
                dw      br,find_loop
not_found:
                dw      drop,false,exit
 
;>dig try to convert WORD to a number returns true and value or false
todig:  colon
                dw      lit,cnt,cat,lit,TIB
                dw      zero,tor
todig_loop:
                dw      dup,cat,qdig
                dw      zbr,not_dig
                dw      fromr,BASE,     cat,mul,plus,tor
                dw      plone,swop,mione,dup
                dw      zbr,todig_done
                dw      swop,br,todig_loop
todig_done:
                dw      drop,drop,fromr,true,exit
not_dig:
                dw      drop,drop,drop,fromr,drop,false,exit                            
 
 
;( char -- [t n]|[f char] )
qdig:   pops    W
                mov [W],0
                sub     [W+1],48
                jc      not_dig0
                cmp [W+1],10
                jc      is_dig
                sub     [W+1],7
                jc      is_dig
                cmp     [W+1],16
                jc is_dig
                sub     [W+1],32
                jc      not_dig0
                cmp     [W+1],16
                jc      is_dig
not_dig0:
                pushs   W       
                jmp     false           
is_dig: mov a, [W+1]
                cmp     a, [base]
                jc      digit
                jmp     not_dig0
digit:  pushs   W
                jmp     true
;----------------------------------------------------------------------------------------------------
;compiler
;----------------------------------------------------------------------------------------------------
 
Lblkat: head    4,'blk@',Lwords,0
blkat:  pops    W       
                lcall   read_blk
                next
 
 
 
Lblksto: head   4,'blk!',Lblkat,0
blksto: pops    W
                lcall   blk_write
                next
 
 
; >bloc ( addr -- loc bloc )    convert an address to a block and location for
;                                               FLASH ROM access
Ltobloc: head 5,'>bloc',Lblksto,0
tobloc: colon
                dw      lit,40h,divmod,exit
 
; >addr ( bloc loc -- addr )    convert a bloc/loc to an address                
Ltoaddr: head 5,'>addr',Ltobloc,0
toaddr: colon
                dw      lit,40h,mul,plus,exit
 
;' ( char -- )  tick - write a byte to FLASH.  Writes to FLASH BUFFER (RAM 0-3f).  When
;                                       buffer is full, writes to FLASH and resets the buffer to bloc+1.
Ltick:  db      1,96
                dw      Ltoaddr
                db      0
tick:   colon
                dw      LOC,cat,csto    
                dw      LOC,cat,plone           
                dw      dup,lit,40h,pxor,zbr,reload             
                dw      LOC,csto
                dw      exit
reload: dw      drop,BLOC,cat,blksto
                dw      BLOC,cat,plone,BLOC,csto
                dw      zero,LOC,csto           
                dw      exit
 
tickw:  colon
                dw      dup,swab,tick,tick,exit
 
new_here: colon
                dw      LOC,cat,BLOC,cat,toaddr,here,sto
                dw      exit
 
; create 
Lcreate:head    6,'create',Ltick,0
create: colon
                dw      here,at,tobloc,BLOC,csto,LOC,csto
                dw      BLOC,cat,blkat
create1:dw      word,zbr,create2
                dw      lit,cnt,cat,plone
                dw      lit,cnt
create_loop:                                                            ;compile name
                dw      dup,cat,tick
                dw      plone,swop,mione,dup
                dw      zbr,created
                dw      swop,br,create_loop
created:dw      drop,drop,last,at,tickw                 ;compile lex
                dw      zero,tick
                dw      BLOC,cat,blksto                                                                 ;write it
                dw      here,at,last,sto                                                                ;here->last 
                dw      new_here                                                                                ;bloc/loc->here
                dw      exit
create2:dw      accept,br,create1
 
; constant
Lconstant: head 8,'constant',Lcreate,0
constant:
                colon
                dw      create
                dw      lit,7ch,tick            ;compile lcall
                dw      lit,_doCON,tickw        ;compile _doCON
                dw      tickw                           ;compile TOS
                dw      BLOC,cat,blksto         ;write it
                dw      new_here
                dw      exit
 
; table 
Ltable: head    5,'table',Lconstant,0
tabl:   colon
                dw      create
                dw      lit,7ch,tick
                dw      lit,_next,tickw                 ;compile doTABLE
table0: dw      word,zbr,table1         
                dw      todig,zbr,table_err
                dw      tick,br,table0
table_err:
                dw      lit,TIB,cat,lit,22h,pxor,zbr,table_done
                dw      br, compile_err
table_done:
                dw      BLOC,cat,blksto         ;write it
                dw      new_here
                dw      exit
table1: dw      accept,br,table0
 
 
 
; colon :    head of compile
Lcompile:       head    1,':',Ltable,0
compile:
                colon
                dw      create
                dw      lit,7ch,tick
                dw      lit,_colon,tickw                ;compile LCALL _colon
compile_loop:
                dw      word,zbr,compile0
                dw      find,zbr,compile_num
                dw      dup,lex,romcat,zbr,compile_word
                dw      cfa,execute,br,compile_loop
compile_word:
                dw      cfa,tickw,br,compile_loop
compile_num:
                dw      todig,zbr,compile_err
                dw      lit,lit,tickw,tickw
                dw      br,compile_loop
compile_err:
                dw      print
                dw      xquote
                db      13
                ds      ' not found.'
                db      13,10
                dw      last,at,here,sto
                dw      last, at,lfa,romat
                dw      last,sto,save
                dw      abort                                           
compile0:
                dw      accept,br,compile_loop          
 
immed:  equ     1
Lsemi:  db      1,59
                dw      Lcompile
                db      immed
semi:   colon
                dw      lit,exit,tickw
                dw      BLOC,cat,blksto
                dw      new_here
                dw      quit
 
Lforget:        head    6,'forget',Lsemi,0
forget:         colon
forget1:dw      word,zbr,forget0
                dw      find,zbr,forget2
                dw      dup, here,sto
                dw      lfa,romat,last,sto,save,exit
forget2:dw      xquote
                db      24
                ds      'not in the dictionary.'
                db      13,10
                dw      quit            
forget0:dw      accept,br,forget1
 
;startup   <my_word><startup> will make FORTH start at <my_word> rather than <cold>
Lstartup:       head    7,'startup',Lforget,0
startup:        colon
startup1:
                dw      word,zbr,startup0
                dw      find,zbr,forget2
                dw      cfa,current,sto
                dw      save,exit               
startup0:
                dw      accept,br,startup1              
 
Lbootat:        head    5,'boot@',Lstartup,0
bootat: colon
                dw      lit,ffh,blkat,exit              
 
Lbootsto:       head    5,'boot!',Lbootat,0             
bootsto: colon
                dw      lit,ffh,blksto,exit             
 
Lsave:  head    4,'save',Lbootsto,0
save:   colon
                dw      bootat
                dw      last,at,lit,vlast,sto
                dw      here,at,lit,vhere,sto
                dw      current,at,lit,vcurr,sto
                dw      bootsto
                dw      exit
 
 
;-------------------------------------------------------------------------------------------------
;interrrupt words
;-------------------------------------------------------------------------------------------------
 
; GIE       enable general interrupt    
Lgie:   head    3,'GIE',Lsave,0
gie:    M8C_EnableGInt
                next            
; GID    disable general interrupt              
Lgid:   head    3,'GID',Lgie,0
gid:    M8C_DisableGInt
                next
 
; sar1  ( -- n )  get analog value connected to SAR1 ADC input pin
Lsar1:  head    4,'sar1',Lgid,0
sar1:   mov     a, 3
                lcall   sar1_SetPower
                lcall   sar1_GetSample
                mov             x,0
                push    x
                add             a, 20h
                push    a
                lcall   sar1_Stop
                next    
 
; sar2  ( -- n )  get analog value connected to SAR2 ADC input pin
Lsar2:  head    4,'sar2',Lsar1,0
sar2:   mov     a,3
                Lcall   sar2_SetPower
                lcall   sar2_GetSample
                mov             x,0
                push    x
                add             a, 20h
                push    a
                lcall   sar2_Stop
                next
 
; sar3  ( -- n )  get analog value connected to SAR3 ADC input pin
Lsar3:  head    4,'sar3',Lsar2,0
sar3:   mov             a,3
                Lcall   amp_Start
                mov     a,3
                lcall   sar3_SetPower
                lcall   sar3_GetSample
                mov             x,0
                push    x
                add             a, 20h
                push    a
                lcall   sar3_Stop
                Lcall   amp_Stop                
                next
 
; temp  
Ltemp:  head    4,'temp',Lsar3,0        
temp:   mov     reg[INT_VC],0
                M8C_EnableGInt
                lcall   FlashTemp_1_Start
temp_loop:
                lcall   FlashTemp_1_fIsData
                cmp             a,0
                jz              temp_loop
                lcall   FlashTemp_1_cGetData
                lcall   FlashTemp_1_Stop
                mov     [W+1], a
                mov     [W], 0
                M8C_DisableGInt
                pushW                   
;--------------------------------------------------------------------------------------------------             
;control structures
;--------------------------------------------------------------------------------------------------
mark:   colon
                dw      LOC,cat,BLOC,cat,toaddr,exit
 
unmark: colon
                dw      tickw,exit              
 
; begin
Lbegin: head    5,'begin',Ltemp,immed
begin:  colon
                dw      mark,exit               
; again
Lagain: head    5,'again',Lbegin,immed
again:  colon
                dw      lit,br,tickw,unmark,exit
; until         
Luntil: head    5,'until',Lagain,immed
until:  colon
                dw      lit,nzbr,tickw
                dw      unmark
                dw      exit                                            
 
; if
Lif:    head    2,'if',Luntil,immed
pif:    colon
                dw      lit,zbr,tickw
                dw      mark,zero,tickw,exit
; (addr addr -- ) 
resolve:        colon
                dw      BLOC,cat,blksto                         ;save current blk
                dw      BLOC,cat,tor,LOC,cat,tor        ;save current BLOC ptr
                dw      tobloc                                          ;convert mark to BLOC
                dw      BLOC,csto,LOC,csto                      ;put in BLOC ptr
                dw      BLOC,cat,blkat                          ;get code to be resolved
                dw      fromr,fromr,toaddr                      ;convert jmp address
                dw      dup,tickw                                       ;compile it
                dw      BLOC,cat,blksto                         ;save code
                dw      tobloc                                          ;convert to BLOC
                dw      BLOC,csto,LOC,csto                      ;restore BLOC ptr
                dw      BLOC,cat,blkat                          ;restore blk
                dw      exit
 
; endif
Lthen:  head    5,'endif',Lif,immed
then:   colon
                dw      resolve,exit                    
 
; else          
Lelse:  head    4,'else',Lthen,immed
pelse:  colon
                dw      lit,br,tickw
                dw      mark
                dw      zero,tickw
                dw      tor,resolve,fromr,exit                  
 
Ldo:    head    2,'do',Lelse,immed
do:             colon
                dw      mark,lit,tor,tickw,exit
 
;break forces premature end of do by replaceing the return stack with 1         
Lbreak: head    5,'break',Ldo,0
break:  colon
                dw      fromr, fromr, drop, lit, 1, tor,tor
                dw      exit    
 
Lloop:  head    4,'loop',Lbreak,immed
loop:   colon
                dw      lit,fromr,tickw
                dw      lit,mione,tickw
                dw      lit,dup,tickw
                dw      lit,nzbr,tickw
                dw      unmark                  
                dw      lit,drop,tickw
                dw      exit
 
Lwhile: head    5,'while',Lloop,immed
while:  colon
                dw      pif,exit
 
Lwend:  head    4,'wend',Lwhile,immed
wend:   colon
                dw      swop,again,then,exit                            
;--------------------------------------------------------------------------------------------------
;i/o words
;--------------------------------------------------------------------------------------------------
 
seperate:
                rlc     [W]
                rlc     [W]
                mov a,1
seperate0:
                or      [W+1],0
                jz      seperate1
                rlc     a
                dec     [W+1]
                jmp     seperate0
seperate1:
                mov [W+1],a
                mov x,[W]
                ret                             
 
 
Linput: head    5,'input',Lwend,0
input:  pops    W
                call    seperate
                mov a, [W+1]
                cpl a
                mov [W], a
                M8C_SetBank1
                mov a, reg[x]
                and a, [W]
                mov reg[x], a
                mov a, reg[x+1]
                or a, [W+1]
                mov reg[x+1], a
                M8C_SetBank0
                next
 
Lstrong: head   6, 'strong',Linput,0
strong: pops    W
                call    seperate
                mov a, [W+1]
                cpl     a
                mov [W], a
                M8C_SetBank1
                mov a, reg[x]
                or a, [W+1]
                mov reg[x], a
                mov a, reg[x+1]
                and a, [W]
                mov reg[x+1], a
                M8C_SetBank0
                next
 
Lpullup:        head 6,'pullup',Lstrong,0
pullup: pops    W
                call    seperate
                M8C_SetBank1
                mov a, reg[x]
                or a, [W+1]
                mov reg[x], a
                mov a, reg[x+1]
                or a, [W+1]
                mov reg[x+1], a
                M8C_SetBank0
                next
 
Lpulldown: head 8,'pulldown',Lpullup,0
pulldown: pops  W
                call seperate
                mov a, [W+1]
                cpl a
                mov [W],a
                M8C_SetBank1            
                mov a, reg[x]
                and a, [W]
                mov reg[x], a
                mov a, reg[x+1]
                and a, [W]
                mov reg[x+1],a
                M8C_SetBank0
                next
 
Lon:    head    2,'on',Lpulldown,0
pon:    pops    W
                call    seperate
                mov a,reg[x]
                or a,[W+1]
                mov reg[x], a
                next
 
 
Loff:   head    3,'off',Lon,0           
poff:   pops    W
                call    seperate
                mov a,[W+1]
                cpl     a
                mov [W+1],a
                mov a,reg[x]
                and a, [W+1]
                mov reg[x],a
                next
 
Ltoggle: head   6,'toggle',Loff,0               
toggle: pops    W
                call    seperate
                mov a, reg[x]
                xor a, [W+1]
                mov reg[x],a
                next            
 
Linp:   head    3,'inp',Ltoggle,0                               
inp:    pops    W
                call    seperate
                mov [W],0
                mov a,reg[x]
                and a, [W+1]
                jz      inp0
                mov [W+1],1
                pushW
inp0:   mov [W+1],0
                pushW   
 
save_mode:      
                mov a, reg[x]
                mov [T0], a
                mov a, reg[x+1]
                mov [T0+1], a                                           
                ret
 
restore_mode:
                M8C_SetBank1
                mov a, [T0]
                mov reg[x],a
                mov a, [T0+1]
                mov reg[x+1],a                  ;port mode restored
                M8C_SetBank0
                ret
 
 
;pulsout ( length pin -- )              
Lpulsout: head  7,'pulsout',Linp,0
pulsout:pops    W
                call    seperate
                cpl a
                mov [W],a                               ;W+1=pin, W=~pin,
                M8C_SetBank1
                call save_mode
                and a, [W]                              
                mov reg[X+1], a                 ;DM1=0
                mov a, reg[x]
                or a, [W+1]
                mov reg[x], a                   ;DM0=1 pin is strong
                M8C_SetBank0
                pops    T1                              ;get pulse length
                mov a, reg[x]                   ;
                xor a, [W+1]                    ;
                mov reg[x], a                   ;pin is opposite
pulsout_loop:
                lcall   OneWireSW_1_Delay50u
                dec             [T1+1]
                sbb             [T1], 0
                jnc             pulsout_loop
                mov a, reg[x]                   
                xor a, [W+1]
                mov reg[x], a                   ;pin is opposite
                call restore_mode
                next
 
;pulsin                         
Lpulsin: head   6,'pulsin',Lpulsout,0
pulsin: pops    W
                call    seperate
                cpl     a
                mov [W], a                      ;x=port, W=~pin, W+1=pin
                mov [T1],0
                mov [T1+1],0            ;initialize counter
                M8C_SetBank1
                call save_mode
                and     a, [W]
                mov reg[x+1],a          ;DM1=0
                mov a, reg[x]
                and a, [W]                      
                mov reg[x],a            ;dm0=0
                M8C_SetBank0
                pops    T2                      
                mov a, [T2+1]
                and a, [W+1]
                mov [T2],a                      ;T2=state
pulsin_hold:            
                mov a, reg[x]           ;sample pin
                and a, [W+1]
                cmp a, [T2]
                jnz     pulsin0                 ;if state <> start measuring
                inc     [T1+1]
                adc     [T1],0
                jnc     pulsin_hold             ;continue sampling until timeout
                jmp     pulsin_fail             ;timeout, return 0
pulsin0:mov [T1],0
                mov [T1+1],0
pulsin_edge:
                mov a,reg[x]
                and a, [W+1]            ;sample pin
                cmp     a, [W+1]
                jnz     get_pulse               ;if state changes, start measuring
                inc     [T1+1]
                adc     [T1],0
                jnc     pulsin_edge             ;if no time out, sample again
                jmp     pulsin_fail             ;timeout, return 0
get_pulse:
;               lcall   OneWireSW_1_Delay50u
                mov     a,reg[x]
                and             a, [W+1]                ;sample pin
                cmp             a, [W+1]                ;
                jnz             pulsin_done             ;when state changes, you're done
                inc             [T1+1]
                adc             [T1],0
                jnc             get_pulse               ;continue until pulsedone or timeout
pulsin_fail:
                call    restore_mode
                ljmp    false           
pulsin_done:
                call    restore_mode
                pushs   T1              
                next
 
;delay  (x -- ) delay for length x * 50 usec
Ldelay: head    5,'delay',Lpulsin,0
delay:  pops    W
delay_loop:
                lcall   OneWireSW_1_Delay50u
                dec             [W+1]
                sbb             [W],0
                jnc             delay_loop
                next            
 
;ow_rst         one wire reset
Lowrst: head    6, 'OW_rst',Ldelay,0
owrst:  lcall   OneWireSW_1_Reset
                mov             [W+1],a
                mov             [W],0
                pushW
 
;OWwr:    one wire write
Lowwr:  head 5, 'OW_wr',Lowrst,0
owwr:   pops    W
                mov             a, [W+1]
                lcall   OneWireSW_1_WriteByte
                next
 
;OWwrs: one wire write strong
Lowwrs: head 6, 'OW_wrs',Lowwr, 0
owwrs:  pops    W
                mov             a, [W+1]
                lcall   OneWireSW_1_WriteByteStrong
                next
 
;OWrd:          one wire read byte
Lowrd:  head 5, 'OW_rd', Lowwrs, 0
owrd:   lcall   OneWireSW_1_ReadByte
                mov             [W+1], a
                mov             [W], 0
                pushW           
;--------------------------------------------------------------------------------------------------
print:  colon
                dw      lit,cnt,cat
                dw      lit,TIB
print_loop:
                dw      dup,cat,emit,plone
                dw      swop,mione,dup
                dw      zbr,printq
                dw      swop,br,print_loop
printq: dw      drop,drop
                dw      exit
 
interpret:
                colon
interpret_loop:         
                dw      word, zbr, interpret0
                dw      find,zbr,qnum
                dw      cfa,execute,br,interpret_loop
qnum:   dw      todig
                dw      zbr,qtok
                dw      br,interpret_loop
qtok:   dw      print
                dw      lit,'?',emit,crlf       
interpret0:
                dw      exit            
 
;hex    change base to 16D
Lhex:   head    3,'hex',Lowrd,0
hex:    colon
                dw      lit,10h,BASE,csto,exit
 
;hex    change base to 10D              
Ldec:   head    7,'decimal',Lhex,0
decimal: colon
                dw      lit,0ah,BASE,csto,exit
 
;hex    change base to 2D
Lbinary: head   6,'binary',Ldec,0
binary: colon
                dw      lit,2,BASE,csto,exit
 
 
; quit
Lquit:  head    4,'quit',Lbinary,0
quit:   colon
                dw      lit,rp0,rpsto   
quit_loop:
                dw      spat,dot,rpat,dot
                dw      accept,interpret
                dw      xquote
                db      4
                ds      'ok'
                db      13,10
                dw      br,quit_loop
 
; abort
Labort: head    5,'abort',Lquit,0                               
abort:  colon
                dw      lit,sp0,spsto
                dw      quit
 
; default
Ldefault:       head 7,'default',Labort,0               
default:        colon
                dw      lit,d_top,last,sto
                dw      lit,new_code,here,sto
                dw      hex
                dw      lit,cold,current,sto
                dw      exit
 
; init
Linit:  head    4,'init',Ldefault,0             
init:   colon
                dw      lit,Vlast,romat,last,sto
                dw      lit,Vhere,romat,here,sto
                dw      lit,Vcurrent,romat,current,sto
                dw      hex
                dw      exit                    
d_top:                                          
 
; cold
Lcold:  head    4,'cold',Linit,0                                
cold:   colon
                dw      lit,12,emit
                dw      lit,201h,inp
;               dw      lit,101h,inp            ;use pin 1.1 for 27143    b001   look for different pins for 29466
                dw      nzbr,saftey
                dw      init,br,cold0
saftey: dw      default 
                dw      lit,40h,emit    
cold0:  dw      xquote
                db      endend - $   ;  end minus here  b001   this is length of string
                ds      'PSoC FORTH v2.01 beta001 b001  updated 20070821' ; b001
endend:         db      13,10    ; b001
                dw      abort
 
                org     2000h
new_code:
 
 
 
        org     3fc0h
Vcurrent:       dw      cold            ;3fc0
Vlast:          dw      d_top           ;3fc2
Vhere:          dw      new_code        ;3fc4
Vbase:          db      10h,0,0,0       ;3fc6

the source: alternate [edit]

some slight changes and notes by Gus Calabrese and Bill Goodrich, in hopes of creating a workable version for newer PSOCs, like our CY8C29466.

;    kernal 16 bit forth for PSoC 27443 - 28 pin device
;    copyright 2003, Christopher W. Burns
;    This program is free software; you can redistribute it and/or modify
;    it under the terms of the GNU General Public License as published by
;    the Free Software Foundation; either version 2 of the License, or
;    (at your option) any later version.
 
;    This program is distributed in the hope that it will be useful,
;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;    GNU General Public License for more details.
 
;    You should have received a copy of the GNU General Public License
;    along with this program; if not, write to the Free Software
;    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
; Modified 20070821   WFT Electronics   wftElectronics.com
; b001   DHD ( Bill Goodrich ) and AGSC   Denver, CO
; same licensing as above
; questions  ?????
;  what is rp ?   return pointer ?
 
;memory map
        include "m8c.inc"
        include "unsignedmath.inc"
        include "uart_1.inc"     ; install UART   can we install another UART ? b001
;       include "counter8_1.inc"
        include "sar1.asm"
        include "sar2.asm"
        include "sar3.asm"
        include "amp.asm"
        include "flashtemp_1.asm"
        include "flashtemp_1int.asm"
        include "onewiresw_1.asm"
;__________________________________________________________________________________
;00|                                                                               |
;10|                                                                               |
;20|            FLASH WRITE BUFFER                                                     |
;30|_______________________________________________________________________________|
;40|            PARAMETER STACK                                                        |
;50|                                                                               |
;60|                                                                               |
;70|                                                                               |
;80|_________RETURN STACK__________________________________________________________|
;90|                                                                               |
;A0|                                                                               |
;B0|_______________________________________________________________________________|
;C0|_cnt|TEXT INPUT BUFFER                                                         |
;D0|_______________________________________________________________________________|
;E0|___IP____|____W____|___HERE__|___LAST__|_CURRENT_|bloc|loc_|_rp_|base|_IN_|____|
;F0|_________|_________|_________|_________|___T0____|____T1___|___T2____|___T3____|
IP:             equ             e0h
W:              equ             e2h
HERE:   equ             e4h
LAST:   equ             e6h
CURRENT:equ             e8h
bloc:   equ             eah
loc:    equ             ebh
rp:             equ             ech
base:   equ             edh
IN:             equ             eeh
 
T0:             equ             f8H
T1:             equ             fah
T2:             equ             fch
T3:             equ             feh
 
sp0:    equ             40h
rp0:    equ             90h
 
cnt:    equ             c0h
TIB:    equ             c1h
EOT:    equ             e0h
 
;boot block structure mirrored in RAM
vcurr:          equ     0
vlast:          equ     2
vhere:          equ     4
vbase:          equ     6
 
;--------------------------------------------------------------------------------------
;macros
;--------------------------------------------------------------------------------------
macro   next
                ljmp    _next
endm
 
macro   pushW
                ljmp    _pushW
endm
 
macro   incr
                inc     [@0+1]
                adc     [@0],0
endm            
 
macro   colon
                lcall   _colon
endm
 
macro   doCon
                lcall   _doCON
endm            
 
macro   fetch
                mov     a, [IP]
                mov     x, [IP+1]
                romx
                mov     [@0], a
                incr    IP
endm            
 
macro   pushs
                mov a,[@0]
                push a
                mov a, [@0+1]
                push a
endm
;********************************************************************************       
;pop the stack into a word register
;********************************************************************************       
macro   pops            
                pop     a                               ;1
                mov [@0+1], a           ;2
                pop     a                               ;1
                mov     [@0], a                 ;2
endm
;********************************************************************************       
 
macro   pushr
                mov x, [rp]
                dec x
                mov a, [@0]
                mov [x], a
                dec x
                mov a, [@0+1]
                mov [x], a
                mov [rp], x
endm
 
macro   popr
                mvi     a,[rp]
                mov     [@0+1], a
                mvi     a,[rp]
                mov [@0], a
endm
 
;       header structure
;       <len><"name"><LINK address><flags>|CODE FIELD|
macro   head
                db      @0
                ds      @1
                dw      @2
                db      @3
endm            
;-------------------------------------------------------------------------------------------------              
        area    kernal16(rom,abs)
 
        org             540h
send:   M8C_DisableGInt
                push a
send0:  mov A,  REG[UART_1_TX_CONTROL_REG]
                and     a,  16
                jz      send0
                pop     a
                mov REG[UART_1_TX_INPUT_REG], a
                ret     
read_blk:       
                mov [0f8h],3ah  ;should be 3ah
                mov X,sp
                mov a,X
                add a,3         
                mov [0f9h],a    ;sp+3
                mov [0fah],[W+1]   ;block id
                mov [0fbh], 0  ;buffer pointer
                mov [0fch],15   ;clock
                mov [fdh], 0
                mov [feh], 0
                mov [ffh], 0
                mov a,01
                SSC                             ;erase block
                nop
                nop
                nop
                ret     
blk_write:      
                mov [0f8h],3ah  ;should be 3ah
                mov X,sp
                mov a,X
                add a,3         
                mov [0f9h],a    ;sp+3
                mov [0fah],[W+1]   ;block id
                mov [0fbh], 0  ;buffer pointer
                mov [0fch],15   ;clock
                mov [fdh], 0
                mov [feh], 0
                mov [ffh], 0
                mov a,03
                SSC                             ;erase block
                nop
                nop
                nop
 
                mov [0f8h],3ah       ;should be 3ah
                mov X,sp
                mov a,X
                add a,3         
                mov [0f9h],a             ;sp+3
                mov [0fah],[W+1]                 ;block id
                mov [0fbh],0             ;buffer pointer
                mov [0fch],15            ;clock
                mov [fdh], 0
                mov [feh], 0
                mov [ffh], 0    
                mov a,02
                SSC                             ;write block
                nop     
                nop
                nop
                ret             
 
start:: mov             a,sp0
                swap    a,sp                                            ;initialize the stack
                mov         [rp],rp0                                    ;initialize the return stack
                lcall   OneWireSW_1_Start                       ;initialize one wire protocall
;********************************************************************************               
;initialize the UART
;********************************************************************************
;               or   reg[Counter8_1_CONTROL_REG],1
        or   REG[UART_1_TX_CONTROL_REG], 1
        or   REG[UART_1_RX_CONTROL_REG], 1
;********************************************************************************       
                mov     [IP],>FORTH
                mov [IP+1],<FORTH                                       ;point to the main FORTH loop
                mov     a, reg[8]                                               ;check saftey is set 
;               mov a, reg[12]                                          ;use pin 1.1 for 27143
                and a, 2
                jz      user
;********************************************************************************
;this is the default start
;********************************************************************************               
                mov [CURRENT],>cold                                     
                mov [CURRENT+1],<cold                           ;set current to "cold"
                next                                                            ;start FORTH
;********************************************************************************
; this is the user's start up
;********************************************************************************
user:   mov a, >Vcurrent                                        
                mov x, <Vcurrent                                        ;User's startup
                romx
                mov     [CURRENT],a                                             ;
                mov a, >Vcurrent
                inc     x
                romx
                mov     [CURRENT+1],a
                next
;********************************************************************************
;MAIN FORTH LOOP
;fetch the vector from "current" and execute.  When done, continous loop.
;********************************************************************************               
FORTH:  dw      current,at,execute,br,FORTH             
;-------------------------------------------------------------------------------------------
;headerless words
;-------------------------------------------------------------------------------------------
;colon  IP->rstack
;               pstack->IP
;               next
;get to colon by LCALL _colon the return address pushed by LCALL is the new IP
_colon: pushr   IP
                pops    IP
                next
;********************************************************************************               
;exit  rstack->IP
;********************************************************************************
exit:   popr    IP                                      ;pop the return address into the instruction pointer
                next
;********************************************************************************
;br     Branch to an inline address
;********************************************************************************               
br:             fetch   W
                fetch   W+1
                mov     [IP],[W]
                mov     [IP+1],[W+1]
                next
;********************************************************************************
;zbr    Branch to an inline address if TOS is 0, otherwise skip         
;********************************************************************************
zbr:    pops    W
                mov a, [W]
                or a,[W+1]
                jz      br
pass:   add     [IP+1],2
                adc     [IP],0
                next
;********************************************************************************
;nzbr   Branch to an inline address if TOS <> 0, other wise skip
;********************************************************************************               
nzbr:   pops    W
                mov     a,[W]
                or a,[W+1]
                jnz     br
                jmp     pass
;********************************************************************************
;lit    Pushes an inline word onto the parameter stack
;********************************************************************************               
lit:    fetch W
                fetch W+1
                pushW
;********************************************************************************               
;doCON get here by LCALL _doCON  - pushs address of constant on the stack
; and then fetches constant to the stack
;********************************************************************************
_doCON: pop     x
                pop a
                push    a
                romx
                mov [W], a
                pop     a
                inc     x
                adc     a,0
                romx
                mov [W+1],a
                pushW
;********************************************************************************               
;xquote send an counted string to the UART
;********************************************************************************
xquote: fetch   W                       ;length in W
xquote_loop:
                fetch   W+1                     ;char->W+1
                mov a, [W+1]
                call    send            ;send it out
                dec     [W]                             ;decrease count
                jnz xquote_loop         ;if it's not zero do it again
                next                            ;IP points to next token
;********************************************************************************
;doTable - push the address of the next word on the stack
;********************************************************************************
macro   doTABLE
        lcall   _next
endm            
 
 
 
;-----------------------------------------------------------------------------------------------
;inner interpreter - 
;                                               -check for an interrupt
;                                               ROM[IP]->W
;                                               IP+2->IP
;                                               W->stack
;                                               jmp(TOS)
;       
;********************************************************************************       
_pushW: pushs   W                                               ;push W register
_next:  fetch   W
                fetch   W+1                                             ;ROM[IP]->W IP+2
                pushs   W                                               ;W-> stack
                ret                                                             ;jmp[TOS]       
 
;               
;--------------------------------------------------------------------------------------------
;the DICTIONARY
;--------------------------------------------------------------------------------------------
;********************************************************************************       
;emit ( char -- ) send a character to UART
;********************************************************************************       
;done in FORTH  24 bytes
;********************************************************************************                               
Lemit:  head    4,'emit',0,0
;emit:  colon
;emit0: dw      lit,UART_1_TX_CONTROL_REG,regat
;               dw      lit,16,pand
;               dw      zbr,emit0
;               dw      lit,UART_1_TX_INPUT_REG,regsto,exit
;********************************************************************************       
;emit done as machine code - 20 bytes
;********************************************************************************                       
emit:   pops    W                                                               ;get the character
emit0:  mov a,reg[UART_1_TX_CONTROL_REG]                ;see if the UART is ready
                and a, 16
                jz      emit0
                mov a, [W+1]            
                mov reg[UART_1_TX_INPUT_REG], a                 ;send it out
                next
;********************************************************************************                                       
;w drop ( x -- ) drop TOS
;********************************************************************************       
Ldrop:  head    4,'drop',Lemit,0
drop:   add     sp,-2
                next
;********************************************************************************       
;w dup  ( x -- x x ) copy TOS
;********************************************************************************       
Ldup:   head    3,'dup',Ldrop,0
dup:    pops    W
                pushs   W
                pushW
;********************************************************************************                       
;w swap ( a b -- b a )
;********************************************************************************       
Lswop:  head    4,'swap',Ldup,0
swop:   pops    T0
                pops    W
                pushs   T0
                pushW
;********************************************************************************                       
;w over ( a b -- b a b )
;********************************************************************************       
Lover:  head    4,'over',Lswop,0
over:   pops    T0
                pops    W
                pushs   W
                pushs   T0
                pushW           
;********************************************************************************                       
;w 1+           (a -- a+1 ) increment TOS
;********************************************************************************       
Lplone: head    2,'1+',Lover,0
plone:  pops    W
                incr    W
                pushW
;********************************************************************************                       
;w 1-           (a -- a-1) decrement TOS
;********************************************************************************       
Lmione: head    2,'1-',Lplone,0
mione:  pops    W
                dec     [W+1]
                sbb [W],0
                pushW
;********************************************************************************                       
;sp@    ( -- sp) where is sp pointing
;********************************************************************************       
Lspat:  head    3,'sp@',Lmione,0
spat:   mov [W],0
                mov x,sp
                mov [W+1],x
                pushW
;********************************************************************************                       
;rp@    ( -- rp) where is rp pointing 
;********************************************************************************       
Lrpat:  head    3,'rp@',Lspat,0
rpat:   mov [W],0
                mov [W+1],[rp]
                pushW                           
;********************************************************************************                       
;sp!    ( x -- ) point sp to x
;********************************************************************************       
Lspsto: head    3,'sp!',Lrpat,0
spsto:  pops    W
                mov a, [W+1]
                swap    a, sp
                next
;********************************************************************************                       
;rp!    ( x -- ) point rp to x
;********************************************************************************       
Lrpsto: head    3,'rp!',Lspsto,0
rpsto:  pops    W
                mov [W],0
                mov [rp],[W+1]
                next
;--------------------------------------------------------------------------------------------
;math
;-------------------------------------------------------------------------------------------
;+              ( a b -- a+b) add top
Lplus:  head    1,'+',Lrpsto,0
plus:   pops    T0
                pops    W
                mov a, [T0+1]
                add     [W+1],a
                mov a,[T0]
                adc     [W],a
                pushW
;********************************************************************************                       
;-              ( a b -- b-a ) subtract top
;********************************************************************************       
Lminus: head    1,'-',Lplus,0
minus:  pops    T0
                pops    W
                mov a, [T0+1]
                sub     [W+1],a
                mov a, [T0]
                sbb     [W],a
                pushW
;********************************************************************************                       
; *     ( a b -- a*b ) 16 multiplication
;********************************************************************************       
Lmul:   head    1,'*',Lminus,0
mul:    pops    T0                      ;X
                pops    T1                      ;Y
                Multiply16_16_16        W,T0,T1
                pushW
;********************************************************************************       
;/mod   ( a b -- b/a  b%a)
;********************************************************************************       
Ldivmod: head 4,'/mod',Lmul,0
 
divmod: pops    T0
                pops    T1      
                call    div16
                pushs   W
                pushs   T1
                next
div16:          
                mov [W+0],00h                   ;clear Remainder
                mov [W+1],00h
                and F,fbh                               ;clear carry flag
                mov [T3],16             ;load loop count to 16 for 16 bit division
d16u_1:         
                rlc [T1+1]                              ;rotate left through dividend and remainder
                rlc [T1+0]                              
                rlc [W+1]                               
                rlc [W+0]                               
                mov [T2+0],[W+0]                ;make backup of remainder
                mov [T2+1],[W+1]
                mov a,[W+1]                     ;subtract divisor from remainder
                sub a,[T0+1]
                mov [W+1],a
                mov a,[W+0]
                sbb a,[T0+0]
                mov [W+0],a
                jnc d16u_2                                      
                mov [W+1],[T2+1]                ;if result is negative
                mov [W+0],[T2+0]                ;restore remainder from backup
                and [T1+1],feh                  ;clear LSB of dividend
                jmp chkLcount16 
d16u_2:         
                or [T1+1],01h                   ;if result is positive set LSB of dividend
chkLcount16:
                dec [T3]                        
                jnz d16u_1                              ;repeat till 16 bits are done
                ret             
;----------------------------------------------------------------------------------------------         
;memory ops
;----------------------------------------------------------------------------------------------
;w @            ( x -- ram[x]) get word at RAM[x]
Lat:    head    1,'@',Ldivmod,0
at:             pops    T0
                mov     x,[T0+1]
                mov     a,[x+0]
                mov [W], a
                mov a, [x+1]
                mov [W+1], a
                pushW
 
;w c@           ( x -- ram[x] ) get byte at RAM[x]
Lcat:   head    2,'c@',Lat,0
cat:    pops    T0
                mov x,[T0+1]
                mov [W],0
                mov a, [x]
                mov [W+1],a
                pushW
 
;w rom@ ( x -- rom[x]) get a word in rom
Lromat: head    4,'rom@',Lcat,0
romat:  pops    T0
                mov a, [T0]
                mov x,[T0+1]
                romx
                mov [W],a
                mov a,[T0]
                inc x
                adc a,0
                romx
                mov [W+1],a
                pushW
 
;w romc@        ( x -- rom[x]) get a byte from rom
Lromcat:        head 5,'romc@',Lromat,0
romcat: pops    T0
                mov a, [T0]
                mov x, [T0+1]
                romx
                mov [W+1],a
                mov [W],0
                pushW           
 
;w !    ( a b -- ) store word b in ram[a]                               
Lsto:   head    1,'!',Lromcat,0
sto:    pops    T0
                pops    T1
                mov x, [T0+1]
                mov a, [T1]
                mov [x], a
                mov a, [T1+1]
                mov [x+1], a
                next
 
;w c!   ( a b -- ) store byte a in ram[b]
Lcsto:  head    2,'c!',Lsto,0
csto:   pops    T0
                pops    T1
                mov x, [T0+1]
                mov a, [T1+1]
                mov [x], a
                next            
 
;w +!   ( a b -- ) add a to ram[b]      (word)
Lpsto:  head    2,'+!',Lcsto,0
psto:   pops    T0
                pops    T1
                mov x, [T0+1]   ;x points to lsb of destination
                mov a, [T1+1]   ;a=lsb of number
                add [x+1], a
                mov a, [T1]             ;a=msb of number
                adc [x], a
                next
 
;w +c! ( a b -- ) add b to ram[a] (byte)                
Lpcsto: head    3,'+c!',Lpsto,0
pcsto:  pops    T0
                pops    T1
                mov x,[T0+1]
                mov a, [T1+1]
                add [x+0], a
                next
 
;----------------------------------------------------------------------------------------------
;system constants
;----------------------------------------------------------------------------------------------
 
LBASE:  head    4,'BASE',Lpcsto,0
BASE:   doCON
                dw      base
 
LHERE:  head    4,'HERE',LBASE,0
here:   doCON
                dw      HERE
 
LLAST:  head    4,'LAST',LHERE,0                
last:   doCON
                dw      LAST
Lcurrent: head 7,'CURRENT',LLAST,0
current: doCON
                dw      CURRENT
 
Lin:    head    2,'IN',Lcurrent,0
in:             doCON           
                dw      IN
 
LBLOC:  head    4,'BLOC',Lin,0
BLOC:   doCON
                dw      bloc
 
LLOC:   head    3,'LOC',LBLOC,0
LOC:    doCON
                dw      loc
;---------------------------------------------------------------------------------------------
;return stack ops
;---------------------------------------------------------------------------------------------
Ltor:   head    2,'>R',LLOC,0
tor:    pops    W
                pushr   W
                next
 
Lfromr: head    2,'R>',Ltor,0                           
fromr:  popr    W
                pushW
 
Lrat:   head    2,'R@',Lfromr,0
rat:    popr    W
                pushr   W
                pushW
 
;---------------------------------------------------------------------------------------------
;comparison
;---------------------------------------------------------------------------------------------
Leq:    head    1,'=',Lrat,0
eq:             pops    T0
                pops    W
                mov a, [W]
                cmp     a, [T0]
                jnz     false
                mov a, [W+1]
                cmp     a,[T0+1]
                jnz     false
negone:         
true:   mov a, -1
                push a
                push a
                next
zero:           
false:  mov a, 0
                push a
                push a
                next
;<      ( a b -- t|f ) true if a<b false otherwise
Llt:    head    1,'<',Leq,0
lt:             pops    W
                pops    T0
                mov a, [T0]
                cmp     a, [W]
                jc      true
                jz      lt0
                jmp     false
lt0:    mov a,[T0+1]
                cmp     a,[W+1]
                jc      true
                jmp     false
 
Lexecute: head  7,'execute',Llt,0
execute:        ret             
;******************************************************************************************
;w ?key   ( -- T char | F ) If there is a character, return true and char
;******************************************************************************************     
Lqkey:  head    4,'?key',Lexecute,0
qkey:   mov A,  REG[UART_1_RX_CONTROL_REG]
                and     a, 8
                jnz get_char
                ljmp false
get_char:
                mov A, REG[UART_1_RX_BUFFER_REG]
                mov [W], 0
                mov [W+1],a
                pushs W
                ljmp true               
;******************************************************************************************     
;w key    ( -- char )  get a character from the UART
;******************************************************************************************     
Lkey:   head    3,'key',Lqkey,0
key:    colon
key0:   dw      qkey,zbr,key0
                dw      exit
 
Lregsto:        head 4,'reg!',Lkey,0
regsto: pops    W
                pops    T0
                cmp     [W],1
                jnz     regsto0
                m8c_SetBank1
regsto0:                
                mov x, [W+1]
                mov a, [T0+1]
                mov reg[x],a
                m8c_SetBank0
                next
 
Lregat: head 4,'reg@',Lregsto,0
regat:  pops    W
                cmp     [W],1
                jnz     regat0
                m8c_SetBank1
regat0: mov x,[W+1]
                mov a,reg[x]            
                m8c_SetBank0
                mov [W+1],a
                mov [W],0
                pushW
 
 
Lregor: head    5,'regor',Lregat,0
regor:  pops    W
                pops    T0
                cmp     [W],1
                jnz     regor0
                m8c_SetBank1
regor0: mov x, [W+1]
                mov a,reg[x]
                or a,[T0+1]
                mov reg[x],a
                m8c_SetBank0
                next
 
Lregand: head 6,'regand',Lregor,0
regand: pops    W
                pops    T0
                cmp     [W],1
                jnz     regand0
                m8c_SetBank1
regand0:mov x, [W+1]
                mov a, reg[x]
                and a, [T0+1]
                mov reg[x],a
                m8c_SetBank0
                next
 
Lregxor: head 6,'regxor',Lregand,0
regxor: pops    W
                pops    T0
                cmp     [W],1
                jnz     regxor0
                m8c_SetBank1
regxor0:mov x, [W+1]
                mov a,reg[x]
                xor a, [T0+1]
                mov reg[x],a
                m8c_SetBank0
                next
 
Land:   head    3,'and',Lregxor,0       ; b000 and word
pand:   pops    T0
                pops    T1
                mov a, [T0+1]
                and a, [T1+1]
                mov [W+1],a
                mov a, [T0]
                and a, [T1]
                mov [W],a
                pushW
 
Lor:    head    2,'or',Land,0            ; b000  or word
por:    pops    T0
                pops    T1
                mov a, [T0+1]
                or a, [T1+1]
                mov [W+1],a
                mov a, [T0]
                or a, [T1]
                mov [W],a
                pushW           
 
Lxor:   head    3,'xor',Lor,0       ; b000  xor word
pxor:   pops    T0
                pops    T1
                mov a, [T0+1]
                xor a, [T1+1]
                mov [W+1],a
                mov a, [T0]
                xor a, [T1]
                mov [W],a
                pushW                           
 
Lnot:   head    3,'not',Lxor,0         ; b000  not word
not:    pops    W
                mov a, [W+1]
                cpl a
                mov [W+1], a
                mov a,[W]
                cpl     a
                mov [W],a
                pushW
 
Lnegate:head    6,'negate',Lnot,0
negate: colon
                dw      not,plone,exit
 
Ltwostar:head   2,'2*',Lnegate,0
twostar:pops    W
                asl     [W+1]                                   ;shift left ignoring carry (low byte)
                rlc     [W]                                             ;shift left including carry     (high byte)
                pushW
 
Ltwodiv:head    2,'2/',Ltwostar,0
twodiv: pops    W
                asr     [W]                                             ;shift right ignoring carry (high byte)
                rrc     [W+1]                                   ;shift right including carry (low byte)1]
                pushW                                           
 
 
Lshout:head     5,'shout',Ltwodiv,0      ; b001   shift out ?
shout:  pops    T0
                mov [W],0
                mov [W+1],0
                asr [T0]                                        ;shift right ignoring carry (high byte)
                rrc [T0+1]                                      ;shift right including carry (low byte)
                rlc [W+1]                                       ;put the carry value into lsb
                pushs T0                                        ;push the shifted source
                pushW                                           ;push the lsb
 
 
 
Lzeq:   head    2,'0=',Lshout,0
zeq:    pops    W
                mov     a,[W]
                or      [W+1],a
                jz      true
                jmp     false
 
Lgt:    head    1,'>',Lzeq,0
gt:             colon
                dw      swop,lt,exit
 
Lneq:   head    2,'<>',Lgt,0
neq:    colon
                dw      eq,zeq,exit
 
Ldotq:  db      2,46,34      ; 2 chars '." '   dot-quote dot quote   b001
                dw      Lneq
                db      1
dotq:   colon
                dw      lit,xquote,tickw
dotq0:  dw      word,zbr,dotq1  
                dw      lit,TIB
                dw      lit,cnt,cat,dup,tick
dotq2:  dw      swop,dup,cat,tick
                dw      plone,swop,mione,dup
                dw      nzbr,dotq2
                dw      drop,drop,exit          
dotq1:  dw      accept,br,dotq0         
 
Lcount: head    5,'count',Ldotq,0
count:  colon
                dw      dup,romcat,swop,plone,swop,exit
 
Ltype:  head    4,'type',Lcount,0
type:   colon
type_loop:
                dw      swop,dup,romcat,emit,plone
                dw      swop,mione,dup
                dw      zbr,type_done
                dw      br,type_loop
type_done:
                dw      drop,drop,exit          
 
Laccept:head    6,'accept',Ltype,0
accept: colon
                dw      reset_in                                        ;reset IN
                dw      lit,'>',emit                            ;prompt
accept0:dw      key                                                     ;get a char
                dw      dup, lit,28h, pxor
                dw      zbr,comment
accept1:dw      dup,emit                                                ;print it
                dw      dup,lit,13,pxor                         ;is it a CR
                dw      zbr, EOL                                        ;then handle it
                dw      dup,lit,8,pxor                          ;is it a BKSP
                dw      zbr,BKSP                                        ;then handle it
                dw      in, cat, csto                           ;store in TIB
                dw      in, cat, plone,dup
                dw      lit, EOT,lt                                     ;end of TIB?
                dw      zbr,TIB_FULL
                dw      in,csto
                dw      br,accept0                                      ;do it again
comment:dw      drop
comment0:
                dw      key,lit,29h,pxor
                dw      nzbr, comment0
                dw      br,accept0              
TIB_FULL:
                dw      xquote
                db      11
                ds      'TIB FULL!'
                db      13,10
                dw      br,EOL0
EOL:    dw      lit,10,emit                                     ;send a LF
                dw      drop
EOL0:   dw      zero                                            ;replace CR with 0
                dw      in,cat,csto                                     ;to mark end
                dw      reset_in,exit                           ;reset and exit                                         
BKSP:   dw      in,cat,lit,TIB,pxor
                dw      zbr,BKSP0
                dw      lit,20h,emit                            ;wipe out character
                dw      emit                                            ;back up again
                dw      in,cat,mione                            ;back up IN
                dw      in,csto
                dw      br,accept0                                      ;get another 
BKSP0:  dw      drop,lit,'>',emit
                dw      br,accept0              
reset_in: colon
                dw      lit,TIB,in,csto,exit
 
 
Llfa:   head    3,'lfa',Laccept,0
lfa:    colon
                dw      count,plus,exit
 
Lcfa:   head    3,'cfa',Llfa,0
cfa:    colon
                dw      lfa,lit,3,plus,exit
 
Llex:   head    3,'lex',Lcfa,0
lex:    colon
                dw      lfa,lit,2,plus,exit             
 
;word ( -- T|F )        moves next token to TIB.  Returns T if a word if a word is assembled, 
;                                       returns false if not.
word:   mov x, TIB
                mov [cnt], 0
skip:   mvi     a,[IN]
                jz      false
                cmp     a, 33
                jc      skip            ;ignore white space             
scan:   mov     [x+0], a
                inc     [cnt]
                inc     x
                mvi     a,[IN]
                jz      word_done1
                cmp     a, 33
                jc      true
                jmp     scan
word_done1:
                dec     [IN]            ;so that next time word fails
                jmp     true
 
swab:   pops    T0
                mov [W+1], [T0]
                mov [W],[T0+1]
                pushW
 
 
d2a:    colon
                dw      dup,lit,9,gt
                dw      zbr,d2a0
                dw      lit,7,plus
d2a0:   dw      lit,30h,plus,emit,exit          
 
Ldot:   head    1,'.',Llex,0            
dot:    colon
                dw      zero,swop
dot0:   dw      BASE,cat,divmod,swop,tor
                dw      swop,plone,swop,dup,nzbr,dot0
                dw      drop
dot1:   dw      fromr,d2a,mione,dup,nzbr,dot1
                dw      drop,exit               
 
Lspc:   head 3,'spc',Ldot,0
spc:    colon
                dw      lit, 20h, emit, exit
 
Lcrlf:  head    4,'crlf',Lspc,0
crlf:   colon
                dw      lit,13,emit
                dw      lit,10,emit,exit
 
Lwords: head    5,'words',Lcrlf,0
words:  colon
                dw      last, at        
words_loop:
                dw      dup,count,type,lit,20h,emit
                dw      lfa,romat,dup
                dw      zbr,words_done
                dw      br,words_loop
words_done:
                dw      drop,crlf,exit                  
 
;match  ( nfa -- t|f ) see if TOS and word match
match:  mov     [T0], cnt
                mov     [W],[cnt]
                inc     [W]
                pop     x
                pop     a
match_loop:
                push    a
                romx
                mov [W+1], a
                mvi     a, [T0]
                cmp     a,[W+1]
                jnz     no_match
                pop     a
                inc     x
                adc     a, 0
                dec     [W]
                jz      true
                jmp     match_loop
no_match:
                pop     a
                jmp     false
 
; find ( -- [nfa t]|f ) see if WORD is in the dictionary. If it is,
;                                               return true and nfa, else, return false.
find:   colon
                dw      last, at
find_loop:
                dw      dup, match
                dw      zbr, find_next
                dw      true,exit                               ;leaves nfa and true                                    
find_next:
                dw      lfa,romat,dup
                dw      zbr,not_found
                dw      br,find_loop
not_found:
                dw      drop,false,exit
 
;>dig try to convert WORD to a number returns true and value or false
todig:  colon
                dw      lit,cnt,cat,lit,TIB
                dw      zero,tor
todig_loop:
                dw      dup,cat,qdig
                dw      zbr,not_dig
                dw      fromr,BASE,     cat,mul,plus,tor
                dw      plone,swop,mione,dup
                dw      zbr,todig_done
                dw      swop,br,todig_loop
todig_done:
                dw      drop,drop,fromr,true,exit
not_dig:
                dw      drop,drop,drop,fromr,drop,false,exit                            
 
 
;( char -- [t n]|[f char] )
qdig:   pops    W
                mov [W],0
                sub     [W+1],48
                jc      not_dig0
                cmp [W+1],10
                jc      is_dig
                sub     [W+1],7
                jc      is_dig
                cmp     [W+1],16
                jc is_dig
                sub     [W+1],32
                jc      not_dig0
                cmp     [W+1],16
                jc      is_dig
not_dig0:
                pushs   W       
                jmp     false           
is_dig: mov a, [W+1]
                cmp     a, [base]
                jc      digit
                jmp     not_dig0
digit:  pushs   W
                jmp     true
;----------------------------------------------------------------------------------------------------
;compiler
;----------------------------------------------------------------------------------------------------
 
Lblkat: head    4,'blk@',Lwords,0
blkat:  pops    W       
                lcall   read_blk
                next
 
 
 
Lblksto: head   4,'blk!',Lblkat,0
blksto: pops    W
                lcall   blk_write
                next
 
 
;w >bloc ( addr -- loc bloc )   convert an address to a block and location for
;                                               FLASH ROM access
Ltobloc: head 5,'>bloc',Lblksto,0
tobloc: colon
                dw      lit,40h,divmod,exit
 
;w >addr ( bloc loc -- addr )   convert a bloc/loc to an address                
Ltoaddr: head 5,'>addr',Ltobloc,0
toaddr: colon
                dw      lit,40h,mul,plus,exit
 
;w ' ( char -- )        tick - write a byte to FLASH.  Writes to FLASH BUFFER (RAM 0-3f).  When
;                                       buffer is full, writes to FLASH and resets the buffer to bloc+1.
Ltick:  db      1,96
                dw      Ltoaddr
                db      0
tick:   colon
                dw      LOC,cat,csto    
                dw      LOC,cat,plone           
                dw      dup,lit,40h,pxor,zbr,reload             
                dw      LOC,csto
                dw      exit
reload: dw      drop,BLOC,cat,blksto
                dw      BLOC,cat,plone,BLOC,csto
                dw      zero,LOC,csto           
                dw      exit
 
tickw:  colon
                dw      dup,swab,tick,tick,exit
 
new_here: colon
                dw      LOC,cat,BLOC,cat,toaddr,here,sto
                dw      exit
 
;w create 
Lcreate:head    6,'create',Ltick,0
create: colon
                dw      here,at,tobloc,BLOC,csto,LOC,csto
                dw      BLOC,cat,blkat
create1:dw      word,zbr,create2
                dw      lit,cnt,cat,plone
                dw      lit,cnt
create_loop:                                                            ;compile name
                dw      dup,cat,tick
                dw      plone,swop,mione,dup
                dw      zbr,created
                dw      swop,br,create_loop
created:dw      drop,drop,last,at,tickw                 ;compile lex
                dw      zero,tick
                dw      BLOC,cat,blksto                                                                 ;write it
                dw      here,at,last,sto                                                                ;here->last 
                dw      new_here                                                                                ;bloc/loc->here
                dw      exit
create2:dw      accept,br,create1
 
;w constant
Lconstant: head 8,'constant',Lcreate,0
constant:
                colon
                dw      create
                dw      lit,7ch,tick            ;compile lcall
                dw      lit,_doCON,tickw        ;compile _doCON
                dw      tickw                           ;compile TOS
                dw      BLOC,cat,blksto         ;write it
                dw      new_here
                dw      exit
 
;w table 
Ltable: head    5,'table',Lconstant,0
tabl:   colon
                dw      create
                dw      lit,7ch,tick
                dw      lit,_next,tickw                 ;compile doTABLE
table0: dw      word,zbr,table1         
                dw      todig,zbr,table_err
                dw      tick,br,table0
table_err:
                dw      lit,TIB,cat,lit,22h,pxor,zbr,table_done
                dw      br, compile_err
table_done:
                dw      BLOC,cat,blksto         ;write it
                dw      new_here
                dw      exit
table1: dw      accept,br,table0
 
 
 
;w :    head of compile
Lcompile:       head    1,':',Ltable,0
compile:
                colon
                dw      create
                dw      lit,7ch,tick
                dw      lit,_colon,tickw                ;compile LCALL _colon
compile_loop:
                dw      word,zbr,compile0
                dw      find,zbr,compile_num
                dw      dup,lex,romcat,zbr,compile_word
                dw      cfa,execute,br,compile_loop
compile_word:
                dw      cfa,tickw,br,compile_loop
compile_num:
                dw      todig,zbr,compile_err
                dw      lit,lit,tickw,tickw
                dw      br,compile_loop
compile_err:
                dw      print
                dw      xquote
                db      13
                ds      ' not found.'
                db      13,10
                dw      last,at,here,sto
                dw      last, at,lfa,romat
                dw      last,sto,save
                dw      abort                                           
compile0:
                dw      accept,br,compile_loop          
 
immed:  equ     1
Lsemi:  db      1,59
                dw      Lcompile
                db      immed
semi:   colon
                dw      lit,exit,tickw
                dw      BLOC,cat,blksto
                dw      new_here
                dw      quit
 
Lforget:        head    6,'forget',Lsemi,0
forget:         colon
forget1:dw      word,zbr,forget0
                dw      find,zbr,forget2
                dw      dup, here,sto
                dw      lfa,romat,last,sto,save,exit
forget2:dw      xquote
                db      24
                ds      'not in the dictionary.'
                db      13,10
                dw      quit            
forget0:dw      accept,br,forget1
 
;w startup   <my_word><startup> will make FORTH start at <my_word> rather than <cold>
Lstartup:       head    7,'startup',Lforget,0
startup:        colon
startup1:
                dw      word,zbr,startup0
                dw      find,zbr,forget2
                dw      cfa,current,sto
                dw      save,exit               
startup0:
                dw      accept,br,startup1              
 
Lbootat:        head    5,'boot@',Lstartup,0
bootat: colon
                dw      lit,ffh,blkat,exit              
 
Lbootsto:       head    5,'boot!',Lbootat,0             
bootsto: colon
                dw      lit,ffh,blksto,exit             
 
Lsave:  head    4,'save',Lbootsto,0
save:   colon
                dw      bootat
                dw      last,at,lit,vlast,sto
                dw      here,at,lit,vhere,sto
                dw      current,at,lit,vcurr,sto
                dw      bootsto
                dw      exit
 
 
;-------------------------------------------------------------------------------------------------
;interrrupt words
;-------------------------------------------------------------------------------------------------
 
;w GIE       enable general interrupt   
Lgie:   head    3,'GIE',Lsave,0
gie:    M8C_EnableGInt
                next            
;w GID    disable general interrupt             
Lgid:   head    3,'GID',Lgie,0
gid:    M8C_DisableGInt
                next
 
;w sar1     successive apoximation register ??
Lsar1:  head    4,'sar1',Lgid,0
sar1:   mov     a, 3
                lcall   sar1_SetPower
                lcall   sar1_GetSample
                mov             x,0
                push    x
                add             a, 20h
                push    a
                lcall   sar1_Stop
                next    
 
;w sar2    successive aproximation register ??
Lsar2:  head    4,'sar2',Lsar1,0
sar2:   mov     a,3
                Lcall   sar2_SetPower
                lcall   sar2_GetSample
                mov             x,0
                push    x
                add             a, 20h
                push    a
                lcall   sar2_Stop
                next
 
;w sar3    successive aproximation register ??
Lsar3:  head    4,'sar3',Lsar2,0
sar3:   mov             a,3
                Lcall   amp_Start
                mov     a,3
                lcall   sar3_SetPower
                lcall   sar3_GetSample
                mov             x,0
                push    x
                add             a, 20h
                push    a
                lcall   sar3_Stop
                Lcall   amp_Stop                
                next
 
;w temp  
Ltemp:  head    4,'temp',Lsar3,0        
temp:   mov     reg[INT_VC],0
                M8C_EnableGInt
                lcall   FlashTemp_1_Start
temp_loop:
                lcall   FlashTemp_1_fIsData
                cmp             a,0
                jz              temp_loop
                lcall   FlashTemp_1_cGetData
                lcall   FlashTemp_1_Stop
                mov     [W+1], a
                mov     [W], 0
                M8C_DisableGInt
                pushW                   
;--------------------------------------------------------------------------------------------------             
;control structures
;--------------------------------------------------------------------------------------------------
mark:   colon
                dw      LOC,cat,BLOC,cat,toaddr,exit
 
unmark: colon
                dw      tickw,exit              
 
;w begin
Lbegin: head    5,'begin',Ltemp,immed
begin:  colon
                dw      mark,exit               
;w again
Lagain: head    5,'again',Lbegin,immed
again:  colon
                dw      lit,br,tickw,unmark,exit
;w until                
Luntil: head    5,'until',Lagain,immed
until:  colon
                dw      lit,nzbr,tickw
                dw      unmark
                dw      exit                                            
 
;w if
Lif:    head    2,'if',Luntil,immed
pif:    colon
                dw      lit,zbr,tickw
                dw      mark,zero,tickw,exit
; (addr addr -- ) 
resolve:        colon
                dw      BLOC,cat,blksto                         ;save current blk
                dw      BLOC,cat,tor,LOC,cat,tor        ;save current BLOC ptr
                dw      tobloc                                          ;convert mark to BLOC
                dw      BLOC,csto,LOC,csto                      ;put in BLOC ptr
                dw      BLOC,cat,blkat                          ;get code to be resolved
                dw      fromr,fromr,toaddr                      ;convert jmp address
                dw      dup,tickw                                       ;compile it
                dw      BLOC,cat,blksto                         ;save code
                dw      tobloc                                          ;convert to BLOC
                dw      BLOC,csto,LOC,csto                      ;restore BLOC ptr
                dw      BLOC,cat,blkat                          ;restore blk
                dw      exit
 
;w endif
Lthen:  head    5,'endif',Lif,immed
then:   colon
                dw      resolve,exit                    
 
;w else         
Lelse:  head    4,'else',Lthen,immed
pelse:  colon
                dw      lit,br,tickw
                dw      mark
                dw      zero,tickw
                dw      tor,resolve,fromr,exit                  
 
Ldo:    head    2,'do',Lelse,immed
do:             colon
                dw      mark,lit,tor,tickw,exit
 
;break forces premature end of do by replaceing the return stack with 1         
Lbreak: head    5,'break',Ldo,0
break:  colon
                dw      fromr, fromr, drop, lit, 1, tor,tor
                dw      exit    
 
Lloop:  head    4,'loop',Lbreak,immed
loop:   colon
                dw      lit,fromr,tickw
                dw      lit,mione,tickw
                dw      lit,dup,tickw
                dw      lit,nzbr,tickw
                dw      unmark                  
                dw      lit,drop,tickw
                dw      exit
 
Lwhile: head    5,'while',Lloop,immed
while:  colon
                dw      pif,exit
 
Lwend:  head    4,'wend',Lwhile,immed
wend:   colon
                dw      swop,again,then,exit                            
;--------------------------------------------------------------------------------------------------
;i/o words
;--------------------------------------------------------------------------------------------------
 
seperate:
                rlc     [W]
                rlc     [W]
                mov a,1
seperate0:
                or      [W+1],0
                jz      seperate1
                rlc     a
                dec     [W+1]
                jmp     seperate0
seperate1:
                mov [W+1],a
                mov x,[W]
                ret                             
 
 
Linput: head    5,'input',Lwend,0
input:  pops    W
                call    seperate
                mov a, [W+1]
                cpl a
                mov [W], a
                M8C_SetBank1
                mov a, reg[x]
                and a, [W]
                mov reg[x], a
                mov a, reg[x+1]
                or a, [W+1]
                mov reg[x+1], a
                M8C_SetBank0
                next
 
Lstrong: head   6, 'strong',Linput,0
strong: pops    W
                call    seperate
                mov a, [W+1]
                cpl     a
                mov [W], a
                M8C_SetBank1
                mov a, reg[x]
                or a, [W+1]
                mov reg[x], a
                mov a, reg[x+1]
                and a, [W]
                mov reg[x+1], a
                M8C_SetBank0
                next
 
Lpullup:        head 6,'pullup',Lstrong,0
pullup: pops    W
                call    seperate
                M8C_SetBank1
                mov a, reg[x]
                or a, [W+1]
                mov reg[x], a
                mov a, reg[x+1]
                or a, [W+1]
                mov reg[x+1], a
                M8C_SetBank0
                next
 
Lpulldown: head 8,'pulldown',Lpullup,0
pulldown: pops  W
                call seperate
                mov a, [W+1]
                cpl a
                mov [W],a
                M8C_SetBank1            
                mov a, reg[x]
                and a, [W]
                mov reg[x], a
                mov a, reg[x+1]
                and a, [W]
                mov reg[x+1],a
                M8C_SetBank0
                next
 
Lon:    head    2,'on',Lpulldown,0
pon:    pops    W
                call    seperate
                mov a,reg[x]
                or a,[W+1]
                mov reg[x], a
                next
 
 
Loff:   head    3,'off',Lon,0           
poff:   pops    W
                call    seperate
                mov a,[W+1]
                cpl     a
                mov [W+1],a
                mov a,reg[x]
                and a, [W+1]
                mov reg[x],a
                next
 
Ltoggle: head   6,'toggle',Loff,0               
toggle: pops    W
                call    seperate
                mov a, reg[x]
                xor a, [W+1]
                mov reg[x],a
                next            
 
Linp:   head    3,'inp',Ltoggle,0                               
inp:    pops    W
                call    seperate
                mov [W],0
                mov a,reg[x]
                and a, [W+1]
                jz      inp0
                mov [W+1],1
                pushW
inp0:   mov [W+1],0
                pushW   
 
save_mode:      
                mov a, reg[x]
                mov [T0], a
                mov a, reg[x+1]
                mov [T0+1], a                                           
                ret
 
restore_mode:
                M8C_SetBank1
                mov a, [T0]
                mov reg[x],a
                mov a, [T0+1]
                mov reg[x+1],a                  ;port mode restored
                M8C_SetBank0
                ret
 
 
;pulsout ( length pin -- )              
Lpulsout: head  7,'pulsout',Linp,0
pulsout:pops    W
                call    seperate
                cpl a
                mov [W],a                               ;W+1=pin, W=~pin,
                M8C_SetBank1
                call save_mode
                and a, [W]                              
                mov reg[X+1], a                 ;DM1=0
                mov a, reg[x]
                or a, [W+1]
                mov reg[x], a                   ;DM0=1 pin is strong
                M8C_SetBank0
                pops    T1                              ;get pulse length
                mov a, reg[x]                   ;
                xor a, [W+1]                    ;
                mov reg[x], a                   ;pin is opposite
pulsout_loop:
                lcall   OneWireSW_1_Delay50u
                dec             [T1+1]
                sbb             [T1], 0
                jnc             pulsout_loop
                mov a, reg[x]                   
                xor a, [W+1]
                mov reg[x], a                   ;pin is opposite
                call restore_mode
                next
 
;pulsin                         
Lpulsin: head   6,'pulsin',Lpulsout,0
pulsin: pops    W
                call    seperate
                cpl     a
                mov [W], a                      ;x=port, W=~pin, W+1=pin
                mov [T1],0
                mov [T1+1],0            ;initialize counter
                M8C_SetBank1
                call save_mode
                and     a, [W]
                mov reg[x+1],a          ;DM1=0
                mov a, reg[x]
                and a, [W]                      
                mov reg[x],a            ;dm0=0
                M8C_SetBank0
                pops    T2                      
                mov a, [T2+1]
                and a, [W+1]
                mov [T2],a                      ;T2=state
pulsin_hold:            
                mov a, reg[x]           ;sample pin
                and a, [W+1]
                cmp a, [T2]
                jnz     pulsin0                 ;if state <> start measuring
                inc     [T1+1]
                adc     [T1],0
                jnc     pulsin_hold             ;continue sampling until timeout
                jmp     pulsin_fail             ;timeout, return 0
pulsin0:mov [T1],0
                mov [T1+1],0
pulsin_edge:
                mov a,reg[x]
                and a, [W+1]            ;sample pin
                cmp     a, [W+1]
                jnz     get_pulse               ;if state changes, start measuring
                inc     [T1+1]
                adc     [T1],0
                jnc     pulsin_edge             ;if no time out, sample again
                jmp     pulsin_fail             ;timeout, return 0
get_pulse:
;               lcall   OneWireSW_1_Delay50u
                mov     a,reg[x]
                and             a, [W+1]                ;sample pin
                cmp             a, [W+1]                ;
                jnz             pulsin_done             ;when state changes, you're done
                inc             [T1+1]
                adc             [T1],0
                jnc             get_pulse               ;continue until pulsedone or timeout
pulsin_fail:
                call    restore_mode
                ljmp    false           
pulsin_done:
                call    restore_mode
                pushs   T1              
                next
 
;w delay        (x -- ) delay for length x * 50 usec
Ldelay: head    5,'delay',Lpulsin,0
delay:  pops    W
delay_loop:
                lcall   OneWireSW_1_Delay50u
                dec             [W+1]
                sbb             [W],0
                jnc             delay_loop
                next            
 
;w ow_rst               one wire reset
Lowrst: head    6, 'OW_rst',Ldelay,0
owrst:  lcall   OneWireSW_1_Reset
                mov             [W+1],a
                mov             [W],0
                pushW
 
;w OWwr:    one wire write
Lowwr:  head 5, 'OW_wr',Lowrst,0
owwr:   pops    W
                mov             a, [W+1]
                lcall   OneWireSW_1_WriteByte
                next
 
;w OWwrs:       one wire write strong
Lowwrs: head 6, 'OW_wrs',Lowwr, 0
owwrs:  pops    W
                mov             a, [W+1]
                lcall   OneWireSW_1_WriteByteStrong
                next
 
;w OWrd:          one wire read byte
Lowrd:  head 5, 'OW_rd', Lowwrs, 0
owrd:   lcall   OneWireSW_1_ReadByte
                mov             [W+1], a
                mov             [W], 0
                pushW           
;--------------------------------------------------------------------------------------------------
print:  colon
                dw      lit,cnt,cat
                dw      lit,TIB
print_loop:
                dw      dup,cat,emit,plone
                dw      swop,mione,dup
                dw      zbr,printq
                dw      swop,br,print_loop
printq: dw      drop,drop
                dw      exit
 
interpret:
                colon
interpret_loop:         
                dw      word, zbr, interpret0
                dw      find,zbr,qnum
                dw      cfa,execute,br,interpret_loop
qnum:   dw      todig
                dw      zbr,qtok
                dw      br,interpret_loop
qtok:   dw      print
                dw      lit,'?',emit,crlf       
interpret0:
                dw      exit            
 
;w hex    change base to 16D
Lhex:   head    3,'hex',Lowrd,0
hex:    colon
                dw      lit,10h,BASE,csto,exit
 
;w hex    change base to 10D            
Ldec:   head    7,'decimal',Lhex,0
decimal: colon
                dw      lit,0ah,BASE,csto,exit
 
;w hex    change base to 2D
Lbinary: head   6,'binary',Ldec,0
binary: colon
                dw      lit,2,BASE,csto,exit
 
 
;w quit
Lquit:  head    4,'quit',Lbinary,0
quit:   colon
                dw      lit,rp0,rpsto   
quit_loop:
                dw      spat,dot,rpat,dot
                dw      accept,interpret
                dw      xquote
                db      4
                ds      'ok'
                db      13,10
                dw      br,quit_loop
 
;w abort
Labort: head    5,'abort',Lquit,0                               
abort:  colon
                dw      lit,sp0,spsto
                dw      quit
 
;w default
Ldefault:       head 7,'default',Labort,0               
default:        colon
                dw      lit,d_top,last,sto
                dw      lit,new_code,here,sto
                dw      hex
                dw      lit,cold,current,sto
                dw      exit
 
;w init
Linit:  head    4,'init',Ldefault,0             
init:   colon
                dw      lit,Vlast,romat,last,sto
                dw      lit,Vhere,romat,here,sto
                dw      lit,Vcurrent,romat,current,sto
                dw      hex
                dw      exit                    
d_top:                                          
 
;w cold
Lcold:  head    4,'cold',Linit,0                                
cold:   colon
                dw      lit,12,emit
                dw      lit,201h,inp
;               dw      lit,101h,inp            ;use pin 1.1 for 27143    b001   look for different pins for 29466
                dw      nzbr,saftey
                dw      init,br,cold0
saftey: dw      default 
                dw      lit,40h,emit    
cold0:  dw      xquote
                db      endend - $   ;  end minus here  b001   this is length of string
                ds      'PSoC FORTH v2.01 beta001 b001  updated 20070821' ; b001
endend:         db      13,10    ; b001
                dw      abort
 
                org     2000h
new_code:
 
 
 
        org     3fc0h
Vcurrent:       dw      cold            ;3fc0
Vlast:          dw      d_top           ;3fc2
Vhere:          dw      new_code        ;3fc4
Vbase:          db      10h,0,0,0       ;3fc6

David, is this a good technique, wiki-wise, to include changes we've made? - Bill

Sure, that's great. After I figure out what your changes mean, I'll edit Wikibooks:PSoC Forth so it shows only one version -- the latest and greatest.

This latest version still supports all the chips that the original one ran on, right? (People can always go to Wikibooks:PSoC Forth history to see the original version or any other version).

"what is rp ? return pointer ?" Yes, it's the pointer to the top of the "return stack". Would it be less confusing if we did a search-and-replace to rename it "RSP", so we're using the same terminology as Brad Rodriguez and the FigUK: "The Heart of Forth" articles?

Right now the most mystifying (to me) change is adding "w" to a bunch of comments -- for example, I see ";drop ( x -- ) drop TOS" changed to ";w drop ( x -- ) drop TOS" . Does that "w" mean anything to you?

I found that it is not very practical to try to fit theis to the newer 466 chips. The best I could do was to get the newer chips to "emulate" Pforth, which was not very useful. It would be better to start from scratch. Chris Burns

history [edit]

  • 2003: originally written by Christopher W. Burns.
  • 2006: maintenance taken over by David Cary (starting from version 2.01 ).
  • 2008 - Is anyone still interested in PSOC Forth? Chris Burns
  • 2008 - Am I the only one still interested in a PSoC Forth? -- DavidCary
             20090208  No, David  I am interested in supporting PSOC Forth.  psocforth@nope9.com

further reading [edit]