跳转到内容

Forth/PSoC Forth

来自维基教科书,开放的书籍,开放的世界

如何安装 PSoC Forth

[编辑 | 编辑源代码]

成分

  • 一个 PSoC 微控制器
  • 一个 PSoC 闪存烧录器,例如 ICE-Cube(它允许您调试、设置断点、单步执行代码等)或 MiniProg(成本更低)。
  • 一台可以运行 PSoC Designer for Windows 或 M8Cutils for Linux 的 PC。
  • 创建 hex 文件 "psoc_forth.hex":以下两种方式任选
    • 如果您使用的是 Windows 系统,请使用 PSoC Designer(详细说明见下文),或者
    • 如果您使用的是 Linux 或 Macintosh 系统,请使用 M8Cutils。
    • (两种开发工具都可以免费下载。)
  • 使用 PSoC 编程器将 hex 文件烧录到微控制器中。

使用 M8Cutils 创建 hex 文件

[编辑 | 编辑源代码]

一次性安装


使用 PSoC Designer 创建 hex 文件

[编辑 | 编辑源代码]

未完成 - 需要改进

一次性安装

  • 安装 PSoC Designer for Windows http://www.cypress.com/psocdesigner.
  • 运行 PSoC Designer 创建新项目
    • 创建新项目。新项目名称:"interactive"(不带引号)。基本部件:27443。
    • 使用“汇编器”生成“Main”文件。完成。
  • http://www.psocdeveloper.com/uploads/media/OneWire_v1.3.3.zip 下载 Wes Randall 的“One Wire 用户模块”,并安装“OneWireSW”自定义用户模块。(FIXME: 如何?)
  • 在“用户模块选择视图”中,选择您可能需要的“用户模块”:(您可以一次选择并放置一个,或选择所有模块,然后放置所有模块)。
    • 数字通信:Uart(双击它以创建 UART_1)
    • 温度:FlashTemp
    • 三个“SAR6”模块 - 将它们重命名为“sar1”、“sar2”和“sar3”。
    • 一个“OneWireSW”模块
    • 一个 INSAMP - 将它重命名为“amp”。
  • 在“互连视图”中,放置所有用户模块(右键单击每个模块并选择“放置”。(“已放置”的模块周围有一个粗彩色矩形。您尚未放置的模块周围没有矩形或只有细黑色矩形。)
  • 在“应用程序编辑器”视图中,点击“构建”(F7)。
    • 您应该收到消息“0 error(s) 0 warning(s)”。
  • 将 psoc_forth.asm 源代码复制到一个名为 "psoc_forth.asm" 的文件中,与我们刚刚创建的 "main.asm" 文件位于同一目录中。
  • 下载 "Algorithm - Unsigned Multiplication - AN2032" 由 Dave Van Ess 编写,并将文件“unsignedmath.inc”解压缩并放入与 "psoc_forth.asm" 相同的目录中
    • (嗯...... “Algorithm - Signed Multi-Byte Multiplication - AN2038” 不会更好吗?)
  • 在“应用程序编辑器”视图中,选择项目 | 添加到项目 | 文件... 并选择 "psoc_forth.asm"。
  • 在“应用程序编辑器”视图中,点击“构建”(F7)。
    • 您应该收到消息“0 error(s) 0 warning(s)”。(FIXME: ... 我从来没有完成过这一步 ...)
  • 编辑源文件 "main.asm",在 ".terminate" 之前添加以下行
        jmp start ; start Forth interpreter
  • 在“应用程序编辑器”视图中,点击“构建”(F7)以创建 hex 文件。

交互式开发

[编辑 | 编辑源代码]
  • 将微控制器上的串行端口连接到终端。(也许是上面使用的同一台 PC,运行一个终端模拟器;或者一个 PDA 串行端口,或者一个哑终端。)
  • ...

源代码

[编辑 | 编辑源代码]
;    psoc_forth.asm -- kernel 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 safety 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, continuous 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 operations
;----------------------------------------------------------------------------------------------
;@		( 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 operations
;---------------------------------------------------------------------------------------------
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
		

;-------------------------------------------------------------------------------------------------
; Interrupt 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
;--------------------------------------------------------------------------------------------------

separate:
		rlc	[W]
		rlc	[W]
		mov a,1
separate0:
		or	[W+1],0
		jz	separate1
		rlc	a
		dec	[W+1]
		jmp	separate0
separate1:
		mov [W+1],a
		mov x,[W]
		ret				

Linput: head	5,'input',Lwend,0
input:	pops	W
		call	separate
		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	separate
		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	separate
		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 separate
		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 separate
		mov a,reg[x]
		or a,[W+1]
		mov reg[x], a
		next

Loff:	head	3,'off',Lon,0		
poff:	pops	W
		call    separate
		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    separate
		mov a, reg[x]
		xor a, [W+1]
		mov reg[x],a
		next		

Linp:	head	3,'inp',Ltoggle,0				
inp:	pops	W
		call    separate
		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	separate
		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	separate
		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

源代码:备用

[编辑 | 编辑源代码]

Gus Calabrese 和 Bill Goodrich 做了一些细微的更改和注释,希望为更新的 PSOC(如我们的 CY8C29466)创建一个可行的版本。

;    Kernel 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 safety 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, continuous 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  - pushes 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 operations
;----------------------------------------------------------------------------------------------
;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 operations
;---------------------------------------------------------------------------------------------
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
		

;-------------------------------------------------------------------------------------------------
; Interrupt 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 approximation 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 approximation 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 approximation 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 replacing 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
;--------------------------------------------------------------------------------------------------

separate:
		rlc	[W]
		rlc	[W]
		mov a,1
separate0:
		or	[W+1],0
		jz	separate1
		rlc	a
		dec	[W+1]
		jmp	separate0
separate1:
		mov [W+1],a
		mov x,[W]
		ret				

Linput: head	5,'input',Lwend,0
input:	pops	W
		call	separate
		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	separate
		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	separate
		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 separate
		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	separate
		mov a,reg[x]
		or a,[W+1]
		mov reg[x], a
		next

Loff:	head	3,'off',Lon,0		
poff:	pops	W
		call	separate
		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	separate
		mov a, reg[x]
		xor a, [W+1]
		mov reg[x],a
		next		

Linp:	head	3,'inp',Ltoggle,0				
inp:	pops	W
		call	separate
		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	separate
		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	separate
		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
safetey:	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,这种技术对维基来说好吗? - Bill

当然,很好。在我弄清楚你的更改意味着什么之后,我会编辑维基教科书:PSoC Forth,以便只显示一个版本 - 最新最好的版本。

这个最新版本是否仍然支持原始版本运行的所有芯片?(人们总是可以访问维基教科书:PSoC Forth 历史记录,查看原始版本或任何其他版本)。

"什么是 rp?返回指针?" 是的,它是指向“返回堆栈”顶部的指针。如果我们进行搜索和替换,将其重命名为“RSP”,使用与 Brad Rodríguez 和 FigUK 相同的术语:“The Heart of Forth” 文章,会不会更清晰?

现在对我来说最令人费解(的更改)是在一堆注释中添加“w” - 例如,我看到“;drop ( x -- ) drop TOS” 被更改为 “;w drop ( x -- ) drop TOS”。这个 “w” 对你来说意味着什么?

我发现试图将它适应更新的 466 芯片并不实际。我所能做的最好的就是让更新的芯片“模拟”Pforth,但这并没有什么用。最好从头开始。Chris Burns

  • 2003:最初由 Christopher W. Burns 编写。
  • 2006:维护工作由 David Cary 接手(从 版本 2.01 开始)。
  • 2008 - 还有人对 PSOC Forth 感兴趣吗?Chris Burns
  • 2008 - 我是唯一一个仍然对 PSoC Forth 感兴趣的人吗?-- DavidCary
             20090208 No, David I am interested in supporting PSOC Forth. [email protected]

进一步阅读

[编辑 | 编辑源代码]
华夏公益教科书