$MOD167					; Define 80C167 mode
;
;------------------------------------------------------------------------------
;  This file is part of the C166 Compiler package
;  Copyright KEIL ELEKTRONIK GmbH 1994
;------------------------------------------------------------------------------
;  START167.A66:  This code is executed after processor reset and provides
;                 the startup sequence for the 80C167 processor.
;
;  To translate this file use A166 with the following invocation:
;
;     A166 START167.A66 SET (TINY | SMALL | COMPACT | MEDIUM | LARGE)
;
;  Example:  A166 START167.A66 SET (SMALL)
;
;  To link the modified START167.OBJ file to your application use the following
;  L166 invocation:
;
;     L166 <your object file list>, START167.OBJ <controls>
;
;  The STARTUP module must be the last object file in the L166 invocation line
;------------------------------------------------------------------------------
; Setup model-dependend Assembler controls
$CASE
$IF NOT TINY
$SEGMENTED
$ENDIF
;------------------------------------------------------------------------------
;
; Definitions for SYSCON and BUSCON0 Register:
; --------------------------------------------
;
; MCTC0: Memory Cycle Time (BUSCON0.0 .. BUSCON0.3):
; Note: if RDYEN0 == 1 a maximum number of 7 waitstates can be selected
_MCTC0	 EQU	2	; Memory wait states is 1 (MCTC0 = 0EH).
;			; (Reset Value = 15 additional state times)
;
; RWDC0: Read/Write Signal Delay (BUSCON0.4):
_RWDC0	 EQU	0	; 0 = Delay Time     0.5 States (Reset Value)  
;			; 1 = No Delay Time  0   States
;
; MTTC0: Memory Tri-state Time (BUSCON0.5):
_MTTC0	 EQU	1	; 0 = Delay Time     0.5 States (Reset Value)
;			; 1 = No Delay Time  0   States
;
$SET (BTYP_ENABLE = 0)  ; 0 = BTYP0 and BUSACT0 is set according to the level
                        ;     at pins P0L.6 and P0L.7 during reset.
			; 1 = the following _BTYP0 and _BUSACT0 values are
			;     written to BTYP0 and BUSACT0
;
; BTYP0: External Bus Configuration Control (BUSCON.6 .. BUSCON.7):
_BTYP0	 EQU	3	; 0 = 8 Bit Non Multiplexed
;			; 1 = 8 Bit Multiplexed
;			; 2 = 16 Bit Non Multiplexed
;			; 3 = 16 Bit Multiplexed
;
; ALECTL0: ALE Lengthening Control Bit (BUSCON0.9):
_ALECTL0 EQU	0	; see data sheet for description
;
; BUSACT0: Bus Active Control Bit (BUSCON0.10):
_BUSACT0 EQU	0	; = 0 external bus disabled
			; = 1 external bus enabled
;
; RDYEN0: READY# Input Enable control bit (BUSCON0.12):
_RDYEN0  EQU	0	; 0 = READY# function disabled  (Reset Value)
;			; 1 = READY# function enabled
;
; RDY_AS: Synchronous / Asynchronous READY# Input (BUSCON.3):
; Note: This bit is only valid if _RDYEN == 1.
_RDY_AS EQU	0	; 0 = synchronous READY# input
;			; 1 = asynchronous READY# input
;
; WRCFG: Write Configuration Control Bit (SYSCON.7):
_WRCFG	 EQU	0	; 0 = Normal configuration of WR# and BHE#
;			; 1 = WR# pin acts as WRL#, BHE# pin acts as WRH#
;
; CLKEN: System Clock Output Enable bit (SYSCON.8):
_CLKEN	EQU	0	; 0 = disabled    (Reset Value)
;			; 1 = enabled
;
; BYTDIS: Byte High Enable pin control bit (SYSCON.9):
_BYTDIS	EQU	0	; 0 = enabled     (Reset Value)
;			; 1 = disabled
;
; ROMEN: Internal ROM Access Enable is read only (SYSCON.10):
_ROMEN	EQU	0	; 0 = Internal ROM disabled
			; 1 = Internal ROM enabled
;
; SGTDIS: Segmentation Disable control bit (SYSCON.11):
$IF TINY
_SGTDIS	EQU	1	; disable segmented mode for TINY model
$ELSE
_SGTDIS	EQU	0	; enable segmented mode (Reset Value)
$ENDIF
;
; ROMS1: ROM Segment Mapping Control Bit (SYSCON.12):
_ROMS1  EQU	0	; _ROMS1 = 0 Internal ROM mapped to segment 0
;			; _ROMS1 = 1 Internal ROM mapped to segment 1
;
; STKSZ: Maximum System Stack Size selection  (SYSCON.13 .. SYSCON.15)
$SET (STK_SIZE = 0)
;                       ; System stack sizes
; 			; 0 = 256 words (Reset Value)
;			; 1 = 128 words
;			; 2 =  64 words
;			; 3 =  32 words
;                       ; 4 = 512 words
;                       ; 5 = not implemented
;                       ; 6 = not implemented
;                       ; 7 = no wrapping (entire internal RAM use as STACK)
;
; WATCHDOG: Disable 80C166 Watchdog
; --- Set WATCHDOG = 1 to enable the 80C166 watchdog
$SET (WATCHDOG = 0)
;
;
; CLR_MEMORY: Disable Memory Zero Initialization of RAM area
; --- Set CLR_MEMORY = 0 to disable memory zero initilization
$SET (CLR_MEMORY = 1)
;
; INIT_VARS: Disable Variable Initilization
; --- Set INIT_VARS = 0 to disable variable initilization
$SET (INIT_VARS = 1)
;
;------------------------------------------------------------------------------

_STKSZ		SET	0
_STKSZ1		SET	0		; size is 512 Words
$IF (STK_SIZE = 0)
_STKSZ1		SET	1		; size is 256 Words
$ENDIF
$IF (STK_SIZE = 1)
_STKSZ		SET	1
_STKSZ1		SET	2		; size is 128 Words
$ENDIF
$IF (STK_SIZE = 2)
_STKSZ		SET	2
_STKSZ1		SET	3		; size is  64 Words
$ENDIF
$IF (STK_SIZE = 3)
_STKSZ		SET	3
_STKSZ1		SET	4		; size is  32 Words
$ENDIF
$IF (STK_SIZE = 4)
_STKSZ		SET	4
$ENDIF
$IF (STK_SIZE = 5)
_STKSZ		SET	5
$ENDIF
$IF (STK_SIZE = 6)
_STKSZ		SET	6
$ENDIF
$IF (STK_SIZE = 7)
_STKSZ		SET	7
$ENDIF


$IF NOT TINY
ASSUME	DPP3:SYSTEM
ASSUME  DPP2:NDATA
$ENDIF

NAME	?C_STARTUP
PUBLIC	?C_STARTUP

$IF TINY
EXTRN	main:NEAR
$ELSE
EXTRN	main:FAR
$ENDIF

PUBLIC		?C_USRSTKBOT

?C_USERSTACK	SECTION	DATA PUBLIC 'NDATA'
$IF NOT TINY
NDATA		DGROUP	?C_USERSTACK
$ENDIF
?C_USRSTKBOT:
		DS	100H		; Size of User Stack
?C_USERSTKTOP:
?C_USERSTACK	ENDS

?C_MAINREGISTERS	REGDEF	R0 - R15

?C_STARTUP_CODE	SECTION	CODE	'ICODE'

		SSKDEF	_STKSZ		; System stack size

;------------------------------------------------------------------------------

SYSCON   DEFR   0FF12H
BUSCON0  DEFR   0FF0CH
STKOV    DEFR   0FE14H
P3       DEFR	0FFC4H
DP3      DEFR	0FFC6H

?C_RESET  	PROC TASK C_STARTUP INTNO RESET = 0
?C_STARTUP:
;// start-of-code
$IF (WATCHDOG = 0)
		DISWDT			; Disable watchdog timer
$ENDIF

BCON0L		SET     (_MTTC0 << 5) OR (_RWDC0 << 4)
BCON0L		SET	BCON0L OR ((NOT _MCTC0) AND 0FH)
BCON0L		SET	BCON0L AND (NOT (_RDYEN0 << 3))
BCON0L		SET	BCON0L OR (_RDY_AS << 3)
BCON0H		SET	(_ALECTL0 << 1) OR (_RDYEN0 << 4)
$IF (BTYP_ENABLE == 1)
BCON0L		SET	BCON0L OR (_BTYP0 << 6)
BCON0H		SET	BCON0H OR (_BUSACT0 << 2)
$ENDIF

$IF (BTYP_ENABLE == 0)
		BFLDL	BUSCON0,#03FH,#BCON0L
		BFLDH	BUSCON0,#012H,#BCON0H
$ELSE
		BFLDL	BUSCON0,#0FFH,#BCON0L
		BFLDH	BUSCON0,#016H,#BCON0H
$ENDIF

SYS_H		SET	(_STKSZ << 5) OR (_ROMS1 << 4) OR (_SGTDIS << 3)
SYS_H		SET	SYS_H OR (_ROMEN << 2) OR (_BYTDIS << 1) OR _CLKEN
SYS_L		SET	(_WRCFG << 7)
; Setup SYSCON Register

 		BFLDH	SYSCON,#0FFH,#SYS_H
		BFLDL	SYSCON,#080H,#SYS_L

; Setup Stack Overflow
_TOS	EQU	0FC00H			        ;top of system stack
_BOS	EQU	_TOS - (1024 >> _STKSZ1)	;bottom of system stack

PUBLIC		?C_SYSSTKBOT
?C_SYSSTKBOT	EQU	_BOS

		MOV	STKOV,#(_BOS+6*2)	;INITIALIZE STACK OVFL REGISTER

$IF NOT TINY

		EXTRN	?C_PAGEDPP1 : DATA16
		EXTRN	?C_PAGEDPP2 : DATA16

		MOV	DPP1,#?C_PAGEDPP1		; NEAR CONST PAGE
		MOV	DPP2,#?C_PAGEDPP2		; NEAR DATA  PAGE

$ENDIF

		MOV	CP,#?C_MAINREGISTERS
		EINIT

$IF NOT TINY
        	MOV	R0,#DPP2:?C_USERSTKTOP
$ELSE
	       	MOV	R0,#?C_USERSTKTOP
$ENDIF


;------------------------------------------------------------------------------
;
; The following code is necessary to set RAM variables to 0 at start-up
; (RESET) of the C application program.
;

$IF (CLR_MEMORY = 1)

		EXTRN	?C_CLRMEMSECSTART : WORD
Clr_Memory:
$IF NOT TINY
		MOV	R2,#PAG (?C_CLRMEMSECSTART)
		MOV	R1,#POF (?C_CLRMEMSECSTART)
		MOV	DPP0,R2
		OR	R2,R1
		JMPR	cc_Z,EndClear
$ELSE
		MOV	R1,#?C_CLRMEMSECSTART
		JMPR	cc_Z,EndClear
$ENDIF

RepeatClear:
$IF (WATCHDOG = 1)
		SRVWDT				; SERVICE WATCHDOG
$ENDIF
		MOV	R5,#0
		MOV	DPP3,#3			; SYSTEM PAGE
		MOV	R2,[R1+]
		JMPR	cc_Z,EndClear
		MOV	R3,R2
		MOV	R4,[R1+]
		JBC	R2.14,ClearNear
$IF NOT TINY
		JBC	R2.15,ClearFar
$ENDIF

ClearBit:	MOV	R3,R4
		SHR	R3,#3
		BCLR	R3.0
		ADD	R3,#0FD00H		; START OF BIT SPACE
		MOV	R5,#1
		SHL	R5,R4
		CPL	R5
		AND	R5,[R3]
		MOV	[R3],R5
		ADD	R4,#1
		SUB	R2,#1
		JMPR	cc_NZ,ClearBit
		JMPR	cc_UC,RepeatClear

$IF NOT TINY
ClearFar:
		MOV	DPP3,R4
		MOV	R4,[R1+]
$ENDIF
ClearNear:
$IF (WATCHDOG = 1)
		SRVWDT				; SERVICE WATCHDOG
$ENDIF
		MOVB	[R4],RL5
		ADD	R4,#1
$IF NOT TINY
		JNB	R3.15,NoDPP3Corr
		JB	R4.14,NoDPP3Corr
		ADD	DPP3,#1
		OR	R4,#0C000H		; SET DPP3 Bits 
NoDPP3Corr:	
$ENDIF
		SUB	R2,#1
		JMPR	cc_NN,ClearNear
		JMPR	cc_UC,RepeatClear
EndClear:

$ENDIF

;------------------------------------------------------------------------------
;
;  The following code is necessary, if the application program contains
;  initialized variables at file level.
;

$IF (INIT_VARS = 1)

		EXTRN	?C_INITSECSTART : WORD
Init_Vars:
$IF NOT TINY
		MOV	DPP0,#PAG (?C_INITSECSTART)
		MOV	R1,#POF (?C_INITSECSTART)
$ELSE
		MOV	R1,#?C_INITSECSTART
$ENDIF
RepeatInit:	
$IF (WATCHDOG = 1)
		SRVWDT				; SERVICE WATCHDOG
$ENDIF
		MOV	DPP3,#3			; SYSTEM PAGE
		MOV	R2,[R1+]
		JMPR	cc_Z,EndInit
$IF NOT TINY
		JNB	R1.14,NoDPP0Adj1
		ADD	DPP0,#1
		BCLR	R1.14
NoDPP0Adj1:
$ENDIF
		JBC	R2.15,InitBit
		MOV	R4,R2
		AND	R2,#3FFFH
		JMPR	cc_NZ,LenLoad
		MOV	R4,#0
		MOV	R2,[R1+]
$IF NOT TINY
		JNB	R1.14,NoDPP0Adj2
		ADD	DPP0,#1
		BCLR	R1.14
NoDPP0Adj2:
$ENDIF
LenLoad:			
		MOV	R3,[R1+]
$IF NOT TINY
		JNB	R1.14,NoDPP0Adj3
		ADD	DPP0,#1
		BCLR	R1.14
NoDPP0Adj3:
$ENDIF
$IF NOT TINY
		JB	R4.14,CopyInitVal
		MOV	DPP3,R3
		MOV	R3,[R1+]
		JNB	R1.14,NoDPP0Adj4
		ADD	DPP0,#1
		BCLR	R1.14
NoDPP0Adj4:
$ELSE
$ENDIF
CopyInitVal:	MOVB	[R3],[R1+]
$IF (WATCHDOG = 1)
		SRVWDT				; SERVICE WATCHDOG
$ENDIF
$IF NOT TINY
		JNB	R1.14,NoDPP0Adj5
		ADD	DPP0,#1
		BCLR	R1.14
NoDPP0Adj5:
$ENDIF
		ADD	R3,#1
$IF NOT TINY
		JB	R4.14,NoDPP3Adj
		JB	R3.14,NoDPP3Adj
		ADD	DPP3,#1
		OR	R3,#0C000H		; SET DPP3 Bits 
NoDPP3Adj:	
$ENDIF
		SUB	R2,#1
		JMPR	cc_NZ,CopyInitVal
		JNB	R1.0,RepeatInit
		ADD	R1,#1
$IF NOT TINY
		JNB	R1.14,NoDPP0Adj6
		ADD	DPP0,#1
		BCLR	R1.14
NoDPP0Adj6:
$ENDIF
		JMPR	cc_UC,RepeatInit

InitBit:	MOVBZ	R3,RL2
		SHL	R3,#1
		OR 	R3,#0FD00H		; START OF BIT SPACE
		MOV	R4,#1
		MOVB	RL5,RH2
		SHL	R4,R5			; CALCULATE BIT MASK
		JB	R2.7,SetBit
		CPL	R4			; CLEAR BIT
		AND	R4,[R3]
		JMPR	cc_UC,StoreBit
SetBit:		OR	R4,[R3]			; SET BIT
StoreBit:	MOV	[R3],R4
		JMPR	cc_UC,RepeatInit

EndInit:

$ENDIF

;------------------------------------------------------------------------------

		JMP	main
?C_RESET	ENDP
?C_STARTUP_CODE	ENDS
;// end-of-code
$IF (INIT_VARS = 1)

?C_INITSEC	SECTION	HDATA GLOBAL
		DW	0			; End of Init Table
?C_INITSEC	ENDS

$ENDIF

		END
