;;======================================================================;;
;;				MiniMaus		 		;;
;;======================================================================;;
;;									;;
;; Program:		MiniMaus -- Lokmaus throttle			;;
;; Code:		Paco Caņada ( http://www.fut.es/~fmco )		;;
;; Platform:		Microchip PIC16F628, 4 Mhz			;;
;; Date:		11.01.2007					;;
;; First release:	08.02.2007					;;
;; LastDate:		11.02.2008					;;
;;									;;
;;======================================================================;;

; This program is for a simple LokMaus throttle (Lenz XBus) with LCD and keyboard 4x4,without potentiometer.
;
; Processor PIC 16F628 running at 4MHz internal oscillator.
;
; Revisions:
;
; 11/01/2007	Start of writing code.
; 31/01/2007	First prototype
; 08/02/2007	Service mode routines
; 25/03/2007	Corrected bug on turnout
; 19/05/2007	Changes in initialization
; 27/06/2007	Removed potentiometer, control speed by keys
; 28/06/2007	Enter CV values with numbers.
; 05/12/2007	Read CV in PoM mode command. Requires Railcom and Lenz LRC120


; ----- Definitions

#define		__VERNUM	0x02
#define		__VERREV	"B"
#define		__VERDAY	0x27
#define		__VERMONTH	0x05
#define		__VERYEAR	0x11

					; Language selection
#define		__ENGLISH	1
;#define		__CASTELLANO	1
;#define		__DEUTSCH	1
;#define		__ITALIANO	1
;#define		__NEDERLANDS	1
;#define		__CATALA	1
;#define		__FRANCAIS	1
;#define		__CZECH		1
;#define		__HUNGARIAN	1
;#define		__SWEDISH	1
;
;		^Yes	^No		; Language selection, uncomment only one



                list    p=16F628,r=hex

		errorlevel -302
		errorlevel -306

	        INCLUDE "P16F628.INC"


                __FUSES _BODEN_ON & _CP_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF & _MCLRE_OFF  & _INTRC_OSC_NOCLKOUT


#define		RAMINI0		0x020		; 80 bytes
#define		RAMINI1		0x0A0		; 80 bytes
#define		RAMINI2		0x120		; 48 bytes
#define		RAMINT		0x070		; 16 bytes


; ----- Macros

SEL_BANK_0:	macro	
		bcf	STATUS,RP0		; macros for data access
		bcf	STATUS,RP1
		endm

SEL_BANK_1:	macro	
		bsf	STATUS,RP0
		bcf	STATUS,RP1
		endm

SEL_BANK_2:	macro	
		bcf	STATUS,RP0
		bsf	STATUS,RP1
		endm

SEL_BANK_3:	macro	
		bsf	STATUS,RP0
		bsf	STATUS,RP1
		endm

#define		SEL_IBANK_0	bcf	STATUS,IRP

#define		SEL_IBANK_1	bsf	STATUS,IRP

#define		DNOP		goto	$+1

; ----- Constant values

FXTAL		equ	D'4000000'		; Internal oscillator frequency
BaudRate	equ	D'62500'		; XBus serial speed

HIGH_BAUD	equ	(((D'10'*FXTAL/(D'16'*BaudRate))+5)/D'10')-1		; BRGH = 1
LOW_BAUD	equ	(((D'10'*FXTAL/(D'64'*BaudRate))+5)/D'10')-1		; BRGH = 0


RA_TRIS         equ     0x37			; RA1,RA2: comparator input,RA0,RA4,RA5: key input
RB_TRIS         equ     0x07			; all outputs, serial port,RB0=Key input
RA_INI          equ     0x00			; display off, TXRX=0 receive
RB_INI          equ     0x00			; all zero
INTC_INI	equ	0xC0			; GIE enable, PEIE enable
PIE1_INI	equ	0x20			; RX interrupt
OPTION_INI	equ	0x02			; Option reg: timer prescaler 1:4, pull-ups
						; Port B Pull-up:       	  0   enabled
						; External int edge:    	  0   falling
						; Timer trigger source: 	  0   clock
						; Timer trigger edge:   	  0   rising
						; Prescaler assignment: 	  0   Timer0
						; Prescaler value :		010   1:8



; --- Pin assignement

; --- Port A

; RA0	KEY2
; RA1	PWM_IN
; RA2	POT
; RA3	TXRX
; RA4	KEY0
; RA5	KEY1
; RA6	LCD_E
; RA7	LCD_RS

						; PORTA
KEY2		equ	0
KEY0		equ	4
KEY1		equ	5
TXRX		equ	3			; 1: enable, 0: disable RS485 transmision
LCD_E		equ	6			; LCD
LCD_RS		equ	7			; LCD

; --- Port B

; RB0	KEY3
; RB1	RXD
; RB2	TXD
; RB3	PWM_OUT
; RB4	LCD + KEYB
; RB5	LCD + KEYB
; RB6	LCD + KEYB
; RB7	LCD + KEYB

COMPORT		equ	PORTA			; PortA. TXRX
LCDPORT		equ	PORTB			; PortB. LCD data
KEYPORT		equ	PORTB			; PortB. Key output
INPORT		equ	PORTA			; PortA. Key input
KEY3		equ	0


; --- Xbus constants

BROADCAST	equ	0x60			; broadcast call byte


; --- Display constants

MENU_LOK	equ	0x00
MENU_RUN	equ	0x01
MENU_TURNOUT	equ	0x02
MENU_PROG	equ	0x03
MENU_SETUP	equ	0x04
MENU_MSG	equ	0x05

SUBM_STOP	equ	d'10'
SUBM_SERVICE	equ	d'11'

	ifdef	__CZECH
#define		__NO_CHR_FNC
#define		__NO_CHR_ARROW
	endif

	ifdef	__HUNGARIAN
#define		__NO_CHR_FNC
	endif

	ifdef	__SWEDISH
#define		__NO_CHR_ARROW
	endif

CHR_N		equ	0			; LCD Graphic characters
CHR_14		equ	1
CHR_12		equ	2
CHR_2		equ	3
CHR_8		equ	4
	ifdef	__NO_CHR_ARROW
	ifdef	__SWEDISH
CHR_EA		equ	5
CHR_OO		equ	6
	else
CHR_Y		equ	5
CHR_CC		equ	6
	endif
	else
CHR_FWD		equ	5
CHR_BKW		equ	6
	endif
	ifdef	__NO_CHR_FNC
CHR_A		equ	7
	else
CHR_FNC		equ	7
	endif
CHR_C		equ	7

CHR_DEF		equ	8			; number of chars defined
CHR_DEF_STP	equ	1			; additional chars defined for setup

FIRSTLINE	equ	0x80
SECONDLINE	equ	0xC0


; --- EEPROM Section

#define		EE_INI		0x00

ADR_MEM		equ	EE_INI+0x00		; Xbus address EEPROM location
LOKH_MEM	equ	EE_INI+0x01		; Last loco used
LOKL_MEM	equ	EE_INI+0x02		; Last loco used
CMD_MEM		equ	EE_INI+0x03		; ** Command station selected

; ----- Variables

; --- Internal RAM Section

; --- Top on all banks

INT_W		equ	RAMINT+0x00		; Interrupt variables.
INT_STAT	equ	RAMINT+0x01
INT_PCLATH	equ	RAMINT+0x02
INT_FSR		equ	RAMINT+0x03

EEDATA0		equ	RAMINT+0x06		; EEPROM shadow variables
EEADR0		equ	RAMINT+0x07


; --- Bank 0

BUFRXINI	equ	RAMINI0+0x00		; first input buffer location
HEADER		equ	RAMINI0+0x00		; Xbus packet
DATA1		equ	RAMINI0+0x01
DATA2		equ	RAMINI0+0x02
DATA3		equ	RAMINI0+0x03
DATA4		equ	RAMINI0+0x04
DATA5		equ	RAMINI0+0x05
;
BUFRXEND	equ	RAMINI0+0x11		; last reception buffer location
KEYFLAG		equ	RAMINI0+0x15		; Keyboard flags

R0		equ	RAMINI0+0x18		; General & Bin to BCD registers
R1		equ	RAMINI0+0x19
LSB		equ	RAMINI0+0x1A
MSB		equ	RAMINI0+0x1B

DUMMY		equ	RAMINI0+0x1C		; Temporary values
TEMP		equ	RAMINI0+0x1D
TEMP2		equ	RAMINI0+0x1E
COUNT		equ	RAMINI0+0x1F

CALLBYTE	equ	RAMINI0+0x20		; call byte byte from command station
MY_ADR		equ	RAMINI0+0x21		; XpressNet Address for normal inquiry messages
TXPOS		equ	RAMINI0+0x22		; Serial Buffer output pointers
TXCNT		equ	RAMINI0+0x23
RX_XOR		equ	RAMINI0+0x24		; Serial incoming checksum
RX_LEN		equ	RAMINI0+0x25		; Incomming message length
XFLAGS		equ	RAMINI0+0x26		; XpressNet flags
XBUS_VER	equ	RAMINI0+0x27		; XpressNet version
XBUS_STA	equ	RAMINI0+0x28		; Command Station type
FLAGS		equ	RAMINI0+0x29		; Flags
FLAGS2		equ	RAMINI0+0x2A
INFOPRE		equ	RAMINI0+0x2B		; get info prescaler
NUMBERH		equ	RAMINI0+0x2C		; screen input number
NUMBERL		equ	RAMINI0+0x2D
UNITS		equ	RAMINI0+0x2E
DCC_STATUS	equ	RAMINI0+0x2F		; Command Station Status

CURRMTR		equ	RAMINI0+0x32		; Current Loco Multi-Unit
CURRADRH	equ	RAMINI0+0x33		; Current Loco address
CURRADR		equ	RAMINI0+0x34		; Current Loco address
CURRSPD		equ	RAMINI0+0x35		; Current Loco speed
CURRFNC		equ	RAMINI0+0x36		; Current Loco functions FL,F1..F4
CURRFNC2	equ	RAMINI0+0x37		; Current Loco functions F5..F12

CVLOW		equ	RAMINI0+0x38		; 
CVHIGH		equ	RAMINI0+0x39		; 
CVDATA		equ	RAMINI0+0x3A		; 
CVTYPE		equ	RAMINI0+0x3B		; 

TURNOUTH	equ	RAMINI0+0x44		; Current Turnout 
TURNOUT		equ	RAMINI0+0x45		; 

KEY		equ	RAMINI0+0x48		; Key row scanned
NEWKEY		equ	RAMINI0+0x49		; Keys pressed
DEBOUNCE	equ	RAMINI0+0x4A		; debounce time
KEYPRE		equ	RAMINI0+0x4B		; key prescaler
MENU		equ	RAMINI0+0x4C		; current menu
SUBMENU		equ	RAMINI0+0x4D		; current submenu

LCD_DATA	equ	RAMINI0+0x4F		; current character


; --- Bank 1

; --- Buffers

BUFTXINI	equ	RAMINI1+0x00		; XpressNet Serial output buffer
;BUFTXEND	equ	RAMINI1+0x1F


;----- Flags

#define		NEW_TX		XFLAGS,0	; new message to command station
#define		TXMIT		XFLAGS,1	; transmiting a message
#define		RCVING		XFLAGS,2	; receiving a message
#define		NEW_MSG		XFLAGS,3	; received new message to us

#define		EmergStop	DCC_STATUS,0	; System in Emergency Stop
#define		EmergOff	DCC_STATUS,1	; System in Emergency Off
#define		AutoStart	DCC_STATUS,2	; System in auto start-up. Not used
#define		ServiceMode	DCC_STATUS,3	; System in Service Mode

#define		LOCO_OTHER	FLAGS,0		; current loco is controlled by other device
#define		GETINFO		FLAGS,1		; get loco info
#define		MULTIUNIT	FLAGS,2		; Current is multiunit address
#define		SEL_SETUP	FLAGS,3		; Setup selection
#define		SETUP_MODE	FLAGS,4		; Setup mode
#define		MENU_CHG	FLAGS,5		; Menu changed, print again
#define		SHW_F5F8	FLAGS,6		; displaying F5..F8
#define		SHW_F9F12	FLAGS,7		; displaying F9..F12

F5F8_BIT	equ	6
F9F12_BIT	equ	7
SELSETUP_MSK	equ	0x08

#define		T_COMMAND	FLAGS2,0	; Command station for turnouts
#define		SENDTURN	FLAGS2,1	; Sended accessory operation
#define		CVSEL		FLAGS2,2	; CV select address or data
#define		GETRESULTS	FLAGS2,3	; CV request results
#define		CVRESULTS	FLAGS2,4	; CV waiting results
#define		CVERROR		FLAGS2,5	; CV error
#define		TPOSITION	FLAGS2,6	; Turnout position

CVSEL_MSK	equ	0x04

#define		KeyHit		KEYFLAG,0	; Key hitted
#define		ServKey		KEYFLAG,1	; Key need service
#define		DbnceOn		KEYFLAG,2	; Key debounce time
#define		KeyRep		KEYFLAG,3	; Key repeated
#define		NUMTYPED	KEYFLAG,5	; Typed number

Loco128		equ	7			; CURRFNC bit definition
Loco28		equ	6
LocoDir		equ	5
LocoFL		equ	4
LocoF4		equ	3
LocoF3		equ	2
LocoF2		equ	1
LocoF1		equ	0

LocoF12		equ	7			; CURRFNC2 bit definition.
LocoF11		equ	6
LocoF10		equ	5
LocoF9		equ	4
LocoF8		equ	3
LocoF7		equ	2
LocoF6		equ	1
LocoF5		equ	0



; --------------- Program Section --------------------------------------


		org	0x000

PowerUp:
		clrf	INTCON			; Disable all interrupts
		clrf	PCLATH			; Tables on page 0
		clrf	STATUS			; reset flags
		goto	INIT


; ----- ISR (Interrupt Service Routines)

		org	0x004

Interrupt:
		movwf	INT_W			; 1 Save registers W, STATUS, PCLATH, FSR
		swapf	STATUS,w		; 2
		clrf	STATUS			; 3 Ensure port / timer access in bank 0
		movwf	INT_STAT		; 4
;		movf	PCLATH,w		; 
;		movwf	INT_PCLATH		; save PCLATH, interrupt uses page 0
;		clrf	PCLATH			; 
		movf	FSR,w			; Save FSR
		movwf	INT_FSR

IntRx:
		btfss	PIR1,RCIF		; serial receive interrupt?
		goto	IntTx

		btfss	RCSTA,OERR		; yes, handle RX errors
		btfsc	RCSTA,FERR
		goto	IntError

		btfss	RCSTA,RX9D		; is the call byte?
		goto	IntRxData		; no
IntRxCallByte:
		bcf	RCVING			; yes, abort message in progress
		clrf	RX_LEN
		movf	RCREG,w			; get call byte and save it
		movwf	CALLBYTE
		btfsc	NEW_MSG			; decoded last message?
		goto	IntRestore		; no, ignore this call byte
		xorlw	BROADCAST		; broadcast call byte? ('P1100000')
		btfsc	STATUS,Z
		goto	IntRxPacket		; yes, new message
		movf	CALLBYTE,w		; message to us?
		xorwf	MY_ADR,w		;     'P10AAAAA' anything to transmit?
		btfsc	STATUS,Z
		goto	IntRxSend		; yes, answer before 80us
		xorlw	b'10100000'		; no, 'P11AAAAA' message to us?
		btfsc	STATUS,Z
		goto	IntRxPacket		; yes, new message
		xorlw	b'01100000'		; no, 'P00AAAAA' acknowledge?
		btfsc	STATUS,Z
		goto	IntRxAck		; yes, send ack
		goto	IntRestore		; no, discard

IntRxPacket:
		clrf	RX_XOR			; set receiving a message
		bsf	RCVING
		goto	IntRestore
		
IntRxData:
		movlw	BUFRXINI		; save data
		addwf	RX_LEN,w
		movwf	FSR
		movf	RCREG,w			; get data byte to clear interrupt
		btfss	RCVING			; are we receiving a packet for us?
		goto	IntRestore		; no, discard data byte
		movwf	INDF			; yes, save data
		xorwf	RX_XOR,f		; checksum
		incf	RX_LEN,f		; next byte
		movlw	BUFRXINI		; check end of message
		movwf	FSR
		movf	INDF,w			; get header byte
		andlw	0x0F			; length to receive
		addlw	0x02			; plus header and xor-byte
		xorwf	RX_LEN,w		; equal to received length?
		btfss	STATUS,Z
		goto	IntRestore		; no, receive more bytes
IntRxEnd:
		bcf	RCVING			; yes, end of receiving data
		movf	RX_XOR,w
		btfsc	STATUS,Z		; xor-byte correct?
		bsf	NEW_MSG			; yes, received new packet
		goto	IntRestore
	
IntRxAck:					; Acknowledge transmision (send 0x20, 0x20)
		bsf	COMPORT,TXRX		; MAX485 TX enable
		movlw	0x20
		movwf	TXREG
		SEL_BANK_1
IntTxAck:
		btfss	TXSTA,TRMT		; wait until end of byte transmited
		goto	IntTxAck
		SEL_BANK_0
		movlw	0x20			; send second byte
		movwf	TXREG
		goto	IntTxEnd		; wait until transmited

IntRxSend:
		btfss	NEW_TX			; new message to command station?
		goto	IntRestore		; no
		bsf	COMPORT,TXRX		; MAX485 TX enable
		SEL_BANK_1
		bsf	PIE1,TXIE		; Enable TX interrupts
		SEL_BANK_0		
		clrf	TXPOS
		bsf	TXMIT			; now transmiting
		goto	IntTxByte

IntError:
		movf	RCREG,w			; on error re-init receiver
		bcf	RCSTA,CREN
		bsf	RCSTA,CREN

IntTx:
		btfss	PIR1,TXIF		; serial transmit interrupt?
		goto	IntRestore		; no, nothing to do
		btfss	TXMIT			; yes, still transmiting?
		goto	IntTxEnd		; no, disable TX interrupts

IntTxByte:
		movlw	BUFTXINI		; calc buffer position
		addwf	TXPOS,w
		movwf	FSR
		movf	INDF,w			; get byte from buffer
		movwf	TXREG			; and send it
		incf	TXPOS,f
		decfsz	TXCNT,f			; last byte?
		goto	IntRestore		; no
		bcf	NEW_TX			; yes, stop transmiting
		bcf	TXMIT
IntTxEnd:
		SEL_BANK_1
IntTxDone:
		btfss	TXSTA,TRMT		; wait until end of last byte transmited
		goto	IntTxDone
		bcf	PIE1,TXIE		; Disable TX interrupts
		DNOP
		DNOP
		DNOP
		DNOP
		SEL_BANK_0		
		bcf	COMPORT,TXRX		; MAX485 TX disable

IntRestore:
		movf	INT_FSR,w		;  Restore the Context Registers and Return
		movwf	FSR
;		movf	INT_PCLATH,w
;		movwf	PCLATH
		swapf	INT_STAT,w
		movwf	STATUS
		swapf	INT_W,f
		swapf	INT_W,w
		retfie



; ----- Tables on first 256 bytes


ShowMenu:
		bcf	MENU_CHG
		clrf	PCLATH
		movf	MENU,w
		andlw	0x07
		addwf	PCL,f			; Show current MENU
		goto	ShowSelect
		goto	ShowLoco
		goto	ShowTurnout
		goto	ShowProg
		goto	ShowSetup
		goto	ShowMessages


	if ($ > d'255') 
		ERROR "  Tables exceded page 0.   If it works, why do you change it?   "
	endif



; ----- Initialization

INIT:
		clrf	RCSTA			; disable UART

		movlw   RA_INI			; Set ports
		movwf   PORTA                         
		movlw   RB_INI
		movwf   PORTB
		SEL_BANK_1
		movlw	RB_TRIS			; Set port B I/O configuration
		movwf   TRISB
		movlw   RA_TRIS         	; Set port A I/O configuration
		movwf   TRISA
		movlw	PIE1_INI
		movwf	PIE1			; peripheral interrupts
		movlw   OPTION_INI      	; PORTB pull-ups enabled, Timer configuration
		movwf   OPTION_REG
		movlw	0x0B			; internal oscillator to 4MHz default
		movwf	PCON
		movlw	0x00			; VRR off
		movwf	VRCON
		SEL_BANK_0
		movlw	0x05			; RA1, RA2 analog inputs
		movwf	CMCON                          

		movlw	0x04			; Timer 2. Run with 1:1 Prescaler
		movwf	T2CON

		movlw	RAMINI0			; Clear variables bank0
		movwf	FSR
ClearRAM:
		clrf	INDF
		incf	FSR,f
		btfss	FSR,7
		goto	ClearRAM

		call	SetMyAddress		; get Xbus address
		call	UART_INI		; Init peripheals
		bcf	COMPORT,TXRX		; MAX485 TX disable just to be sure

		movlw	INTC_INI		; Set interrupts
		movwf	INTCON

		movlw	LOKH_MEM		; get last loco used
		call	EE_Read
		movwf	CURRADRH
		movlw	LOKL_MEM
		call	EE_Read
		movwf	CURRADR
		clrf	CURRSPD			; stop default
		movlw	b'01100000'		; default 28 steps, forward, FL,F1..F4 off
		movwf	CURRFNC

		movlw	CMD_MEM			; ** Read command station
		call	EE_Read			; **
		iorwf	FLAGS2,f		; ** T_COMMAND

		movlw	MENU_RUN
		movwf	MENU

		movlw	0xD0			; Enter setup mode if SEL pressed
		movwf	PORTB
		movlw	0x01			; default turnout: 1
		movwf	TURNOUT
		call	Delay10us
		btfss	PORTB,KEY3
		call	Setup

		btfss	SETUP_MODE
		call	GetVersion		; get command station version & type

		movlw	0x01			; Timer 1. Run, set 1:1 Prescaler
		movwf	INFOPRE			; **
		call	SetTimer1		; 32ms delay to reset LCD
		bsf	TMR1H,7

LCD_INI:					
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it
		btfss	PIR1,TMR1IF
		goto	LCD_INI
		movlw	0x33			; set 8 bit mode
		call	LCDCON
		movlw	0x33			; set 8 bit mode
		call	LCDCON
		movlw	0x33			; set 8 bit mode
		call	LCDCON
		movlw	0x20			; set 4 bit mode
		call	LCDCON

		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		movlw	0x06			; incr dir. no display shift
		call	LCDCON
		movlw	0x0C			; display on, cursor/flash off
		call	LCDCON
;		movlw	0x02			; home
;		call	LCDCON
		movlw	0x01			; Clear LCD
		call	LCDCON
		clrf	TMR1L			; 2ms to clear
		movlw	0xF8
		movwf	TMR1H
		bcf	PIR1,TMR1IF
ClearLCD:
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it
		btfss	PIR1,TMR1IF
		goto	ClearLCD

LCDDEF:
		movlw	0x40			; start of CG RAM
		call	LCDCON
		movlw	(CHR_DEF * 8)		; 8 chars, 8 bytes each (5x8 matrix)
		movwf	COUNT
LCDDEFN:
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it
		movlw	HIGH (NEWLCDCHR)
		movwf	PCLATH
		movf	COUNT,w
		sublw	(CHR_DEF * 8)
		btfsc	SETUP_MODE		; if setup, define others
		addlw	(CHR_DEF_STP) * 8	; **
		call	NEWLCDCHR
		call	LCDCHR
		decfsz	COUNT,f
		goto	LCDDEFN

		btfsc	SETUP_MODE
		goto	Loop

		movlw	FIRSTLINE		; Show Welcome
		call	LCDCON
		movlw	d'0'	
		call	LCDSTR			; ' MiniMaus  v.1C '
		movlw	SECONDLINE
		call	LCDCON
		movlw	d'1'			; ' by  F.M.Caņada '
		call	LCDSTR

		movlw	0x31			; Timer 1. Run, set 1:8 Prescaler
		call	SetTimer1		; time to transmit to command station
FindStation:
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it
		btfss	PIR1,TMR1IF		; timeout?
		goto	FindStationWait

		bcf	PIR1,TMR1IF		; yes, show not found
		movlw	FIRSTLINE
		call	LCDCON
		movlw	d'4'	
		call	LCDSTR			; 'Command  Station'
		movlw	SECONDLINE
		call	LCDCON
		movlw	d'5'			; '   not found!   '
		call	LCDSTR
FindStationWait:
		btfsc	NEW_TX			; packet sended, command station present
		goto	FindStation

;		bsf	T1CON,TMR1ON		; Timer1 on to be sure
		call	GetStatus		; get current status

		movlw	0x01			; Timer 1. Run, set 1:1 Prescaler
		call	SetTimer1		; time to transmit changes to command station
						; and read keys and pot value

; --- Main Loop


MainLoop:
		call	GetLocoInfo
		movlw	0x18
		movwf	MSB
		
MainStabilize:
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it
		btfss	PIR1,TMR1IF		; wait stabilize time 1,5 sec
		goto	MainStabilize
		bcf	PIR1,TMR1IF
		decfsz	MSB,f
		goto	MainStabilize
		movlw	0xD0			; clear keys status
		andwf	KEYFLAG,f

Loop:
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		btfsc	INTCON,T0IF		; update keyboard and pot
		call	TimerOut

		btfss	PIR1,TMR1IF		; read pot value if needed
		goto	LoopKey
		bcf	PIR1,TMR1IF

		decfsz	INFOPRE,f		;**
		goto	LoopKey
		bsf	INFOPRE,4
		btfsc	LOCO_OTHER
		bsf	GETINFO
		
LoopKey:
		btfsc	NEW_MSG			; ** new message received?
		call	HandleMsg		; ** yes, handle it

		btfsc	ServKey			; key need service?
		call	ServiceKey		; yes, do action

		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		btfsc	GETRESULTS
		call	SMResults
		btfsc	GETINFO
		call	GetLocoInfo

		btfsc	NEW_MSG			; ** new message received?
		call	HandleMsg		; ** yes, handle it

		btfsc	MENU_CHG		; Menu changed?
		goto	ShowMenu		; yes, show it

		goto	Loop


Setup:
		bsf	SETUP_MODE		; On setup disable Xbus
		movlw	MENU_SETUP
		movwf	MENU
		bsf	MENU_CHG
		return


; --- Show Menu

ShowLoco:
		movlw	FIRSTLINE		; Show loco control
		call	LCDCON
		movlw	d'3'	
		call	LCDSTR			; 'Loco        0003'
						; '<000  28  F*1234'
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		movf	CURRADRH,w
		andlw	0x3F
		movwf	MSB
		movf	CURRADR,w
		call	LCDLONG
		goto	LocoShow

ShowSelect:
		movlw	FIRSTLINE		; Show loco selection
		call	LCDCON
		movlw	d'2'	
		call	LCDSTR			; 'Select Loco:'
		movf	NUMBERH,w
		call	LCDBCD
		movf	NUMBERL,w
		call	LCDBCD

LocoShow:
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		movlw	SECONDLINE		; '<000  28  F*1234'
		call	LCDCON

		movf	CURRSPD,w		; emergency stop?
		xorlw	0x01
		btfss	STATUS,Z
		goto	LocoShwSpd
		movlw	'S'			; yes, 'STOP'
		call	LCDCHR
		movlw	'T'
		call	LCDCHR
		movlw	'O'
		call	LCDCHR
		movlw	'P'
		call	LCDCHR
		goto	LocoShwStep
LocoShwSpd:
	ifdef	__NO_CHR_ARROW
		movlw	0x7E			; loco direction
	else
		movlw	CHR_FWD			; loco direction
	endif
		btfss	CURRFNC,LocoDir
	ifdef	__NO_CHR_ARROW
		movlw	0x7F
	else
		movlw	CHR_BKW
	endif
		call	LCDCHR

		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		call	Normalize		; **
		call	LCDBYTE
LocoShwStep:
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		movlw	' '			;**
		btfsc	LOCO_OTHER		;**
		movlw	'#'			;**

		call	LCDCHR
		movlw	' '
		call	LCDCHR
		movlw	CHR_14			; Char 14 steps
		btfsc	CURRFNC,Loco28
		movlw	CHR_2			; Char 28 steps
		btfsc	CURRFNC,Loco128
		movlw	CHR_12			; char for 128 steps
		call	LCDCHR
		movlw	' '			; Char 14 steps
		btfsc	CURRFNC,Loco28
		movlw	CHR_8			; Char 28 steps
		btfsc	CURRFNC,Loco128
		movlw	CHR_8			; char for 128 steps
		call	LCDCHR
		movlw	' '
		call	LCDCHR
		movlw	' '
		call	LCDCHR

		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		movlw	'F'
		call	LCDCHR
		btfsc	SHW_F5F8
		goto	LocoShwF5F8
		btfsc	SHW_F9F12
		goto	LocoShwF9F12
LocoShwFLF4:
		movlw	'-'
		btfsc	CURRFNC,LocoFL		; show FL,F1,F2,F3,F4
		movlw	'*'
		call	LCDCHR
		movf	CURRFNC,w
		goto	LocoShwFx
LocoShwF5F8:
		movlw	CHR_8			; show F5,F6,F7,F8
		call	LCDCHR
		movf	CURRFNC2,w
		goto	LocoShwFx
LocoShwF9F12:
		movlw	CHR_12			; show F9,F10,F11,F12
		call	LCDCHR
		swapf	CURRFNC2,w
LocoShwFx:
		movwf	TEMP
		movlw	0x04
		movwf	COUNT
LocoShwFxNxt:
		movlw	'-'
		btfsc	TEMP,0
	ifdef	__NO_CHR_FNC
		movlw	":"
	else
		movlw	CHR_FNC
	endif
		call	LCDCHR
		rrf	TEMP,f
		decfsz	COUNT,f
		goto	LocoShwFxNxt
		goto	Loop


ShowTurnout:
		movlw	FIRSTLINE		; Show Turnout
		call	LCDCON
		movlw	d'6'	
		call	LCDSTR			; 'Turnout:    999/'
		movf	NUMBERH,w		; typed new number?
		iorwf	NUMBERL,w
		btfsc	STATUS,Z
		goto	ShowTurnOld
		movf	NUMBERH,w		; yes, show it
		call	LCDBCDL
		movf	NUMBERL,w
		call	LCDBCD
		goto	ShowTurnPos
ShowTurnOld:
		movf	TURNOUTH,w		; no, show last used
		movwf	MSB
		movf	TURNOUT,w
		call	LCDWORD
ShowTurnPos:
		movlw	0x7C			; 'I'
		btfss	TPOSITION
		movlw	'/'
		call	LCDCHR

		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		movlw	SECONDLINE		; 
		call	LCDCON
		movlw	d'7'	
		call	LCDSTR			; '                '
		goto	Loop


ShowProg:
		movlw	FIRSTLINE		; Show CV parameters
		call	LCDCON
		movf	CVTYPE,w
		addlw	d'12'			; 'CV Dir''CV Paged''CV Reg''CV PoM'
		movwf	TEMP
		call	LCDSTR
		movlw	d'16'			; 'Loco'
		call	LCDSTR
		movlw	SECONDLINE
		call	LCDCON

	ifdef	__NO_CHR_ARROW
		movlw	0x7E
	else
		movlw	CHR_FWD
	endif
		btfsc	CVSEL
		movlw	'C'
		call	LCDCHR

		btfss	CVSEL			;** typed CV?
		btfss	NUMTYPED		;**
		goto	ShowProgCVNum		;**

		movf	NUMBERH,w		;** yes, show it
		call	LCDBCDL			;**
		movf	NUMBERL,w		;**
		call	LCDBCD			;**
		goto	ShowProgData		;**
ShowProgCVNum:
		movf	CVHIGH,w		;**
		movwf	MSB			;** normalize CV number
		incf	CVLOW,w
		btfsc	STATUS,Z
		incf	MSB,f
		call	LCDWORD

ShowProgData:		
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it
		
		btfsc	CVERROR
		goto	ShowProgError

	ifdef	__NO_CHR_ARROW
		movlw	0x7E
	else
		movlw	CHR_FWD
	endif
		btfss	CVSEL
		movlw	'-'
		call	LCDCHR

		btfsc	CVSEL			;** typed CV?
		btfss	NUMTYPED		;**
		goto	ShowProgDataNum		;**

		movf	NUMBERH,w		;** yes, show it
		call	LCDBCDL			;**
		movf	NUMBERL,w		;**
		call	LCDBCD			;**
		goto	ShowProgLoco		;**

ShowProgDataNum:
		movf	CVDATA,w
		call	LCDBYTE
ShowProgLoco:
		movlw	d'17'			; '   '
		call	LCDSTR

		movf	CVTYPE,w		;** PoM mode?
		xorlw	0x03			;**
		btfss	STATUS,Z		;**
		goto	ShowProgNoPoM		;**

		movf	CURRADRH,w		; yes, show loco number
		andlw	0x3F
		movwf	MSB
		movf	CURRADR,w
		call	LCDLONG
		goto	Loop
ShowProgError:
		movlw	d'9'			;** '<-->'
		call	LCDSTR
		goto	ShowProgLoco
ShowProgNoPoM:
		movlw	0x00			;**
		goto	LocoShwFx		;** '----'


ShowSetup:
		movlw	FIRSTLINE		; Show Setup Xbus address
		call	LCDCON
		btfsc	SEL_SETUP
		goto	ShowPot
		movlw	d'8'	
		call	LCDSTR			; 'Xbus address: 01'
		movlw	ADR_MEM			; read from EEPROM
		call	EE_Read
		call	LCDBIN
		movlw	SECONDLINE		; **
		call	LCDCON			; **
		movlw	d'7'			; **
		call	LCDSTR			; ** '               '
		goto	Loop			; **

ShowPot:
		movlw	d'4'			; ** 
		call	LCDSTR			; ** 'Command  Station'
		movlw	SECONDLINE		; **
		call	LCDCON			; **
		movlw	CMD_MEM			; ** read from EEPROM
		call	EE_Read			; **
		addlw	d'20'			; ** 'Lenz'
		call	LCDSTR			; ** 'Roco'
		movlw	d'22'			; ** 
		call	LCDSTR			; ** '        '
		goto	Loop			; **

ShowMessages:
		movlw	FIRSTLINE		; Show Status messages
		call	LCDCON
		movlw	d'7'	
		call	LCDSTR			; '                '
		movlw	SECONDLINE		; 
		call	LCDCON
		movf	SUBMENU,w		; submenu
		call	LCDSTR
		goto	Loop

		
Normalize:					; ** normalize CURRSPD
		movf	CURRSPD,w
		btfss	CURRFNC,Loco28
		goto	LocoSpdNorm
		bcf	STATUS,C		; normalize 28 speed
		btfsc	CURRSPD,4
		bsf	STATUS,C
		rlf	CURRSPD,w
		andlw	0x1F
LocoSpdNorm:
		btfsc	STATUS,Z
		return
		addlw	0xFF			; normalize for 14 & 128 steps
		btfsc	CURRFNC,Loco28
		addlw	0xFE			; normalize for 28 steps
		return


; --- Xbus Incoming messages


HandleMsg:
		btfsc	SETUP_MODE		; Handle incoming messages	
		goto	HandleEnd		; not in setup mode
Handle6X:
		movf	HEADER,w
Handle61:
		xorlw	0x61
		btfss	STATUS,Z
		goto	Handle6X_2
Handle61_0:
		movf	DATA1,w
		btfss	STATUS,Z
		goto	Handle61_1

		btfsc	EmergOff		; second transmision
		goto	HandleEnd
		bcf	ServiceMode		; Track power off
		bsf	EmergOff
		bcf	EmergStop
HandleOff:
		movlw	SUBM_STOP
		movwf	SUBMENU

HandleSubMsg:
		movlw	MENU_MSG
		movwf	MENU
		goto	HandleEndShwMenu
				
Handle61_1:
		xorlw	0x01
		btfss	STATUS,Z
		goto	Handle61_2

		bcf	ServiceMode		; normal operations resume
		bcf	EmergOff
		bcf	EmergStop
HandleResume:
		bsf	GETINFO
		movlw	MENU_RUN
		movwf	MENU
		goto	HandleEndShwMenu

Handle61_2:
		xorlw	(0x01 ^ 0x02)
		btfss	STATUS,Z
		goto	Handle61_1X

		btfsc	ServiceMode		; second transmision
		goto	HandleEnd
		bsf	ServiceMode		; Service Mode entry
		bcf	EmergOff
		bcf	EmergStop
HandleServ:
		movlw	SUBM_SERVICE
		movwf	SUBMENU
		btfss	CVRESULTS		; waiting results?
		goto	HandleSubMsg		; no, other throttle programm
		goto	HandleEnd		; yes, we are programming

Handle61_1X:
		xorlw	(0x02 ^ 0x10)
		andlw	0xF0
		btfss	STATUS,Z
		goto	HandleEnd

		bsf	CVERROR			; Programming info: Data byte not found or Short circuit
		bcf	CVRESULTS		; don't wait results anymore.
		goto	HandleEndShwMenu

Handle6X_2:
		xorlw	(0x61 ^ 0x62)
		btfss	STATUS,Z
		goto	Handle6X_3
Handle62:
		movf	DATA1,w
		xorlw	0x22
		btfss	STATUS,Z
		goto	HandleEnd

		movf	DATA2,w			; Commnad station status response
		movwf	DCC_STATUS

		btfsc	ServiceMode		; set correct status
		goto	HandleServ
		btfss	EmergStop
		btfsc	EmergOff
		goto	HandleOff
;		btfsc	EmergStop
;		goto	HandleStop
		goto	HandleResume

Handle6X_3:
		xorlw	(0x62 ^ 0x63)
		btfss	STATUS,Z
		goto	Handle8X
Handle63:
		movf	DATA1,w
		xorlw	0x21
		btfss	STATUS,Z
		goto	Handle63_1

		movf	DATA2,w			; software version
		movwf	XBUS_VER
		movf	DATA3,w
		movwf	XBUS_STA
		goto	HandleEnd
		
Handle63_1:
		xorlw	(0x21 ^ 0x10)
		andlw	0xF0
		btfss	STATUS,Z
		goto	HandleEnd

		bcf	CVRESULTS
		decf	DATA2,w			; service mode results
		movwf	CVLOW
		clrf	CVHIGH			;**
		movf	DATA3,w
		movwf	CVDATA
		goto	HandleEndShwMenu

Handle8X:
		movf	HEADER,w
Handle81:
		xorlw	0x81
		btfss	STATUS,Z
		goto	HandleEX

		movf	DATA1,w
		btfss	STATUS,Z
		goto	HandleEnd

		btfsc	EmergStop		; second transmision
		goto	HandleEnd
		bcf	ServiceMode		; Emergency stop
		bcf	EmergOff
		bsf	EmergStop
HandleStop:
		goto	HandleOff
;		movlw	SUBM_STOP
;		movwf	SUBMENU
;		goto	HandleSubMsg

HandleEX:
		movf	HEADER,w		
HandleEX_1:
		xorlw	0xE1			; MU+DH errors
		btfss	STATUS,Z
		goto	HandleEX_2
HandleE1:
;		movf	DATA1,w
;		xorlw	0x88			; stack full
;		btfss	STATUS,Z
;		goto	HandleEnd
HandleFull:
;		movlw	MENU_FULL
;		movwf	MENU
		goto	HandleEndShwMenu


HandleEX_2:
		xorlw	(0xE1 ^ 0xE2)
		btfss	STATUS,Z
		goto	HandleEX_3
HandleE2:
		movf	DATA1,w			; Loco information
		andlw	0xF0
		xorlw	0x20
		btfss	STATUS,Z
		goto	HandleEnd

;		bsf	MULTIUNIT		; set Multi Unit
;		movf	CURRADR,w		; no functions
;		movwf	CURRMTR
		goto	HandleE4_Data

HandleEX_3:
		xorlw	(0xE2 ^ 0xE3)		; Loco is being operated by another device
		btfss	STATUS,Z
		goto	HandleEX_4
		movf	DATA1,w			; Loco information
		xorlw	0x40
		btfss	STATUS,Z
		goto	HandleEnd
		movf	DATA2,w			; check with CURRADR
		xorwf	CURRADRH,w
		btfss	STATUS,Z
		goto	HandleEnd
		movf	DATA3,w
		xorwf	CURRADR,w
		btfss	STATUS,Z
		goto	HandleEnd
		bsf	LOCO_OTHER		; operated by other
		goto	HandleEndShwMenu

		
HandleEX_4:
		xorlw	(0xE3 ^ 0xE4)
		btfss	STATUS,Z
		goto	HandleEX_5
HandleE4_0:
		movf	DATA1,w			; Loco information normal locomotive
		andlw	0xF0
		btfss	STATUS,Z
		goto	HandleEnd

;		bcf	MULTIUNIT
;		movf	CURRADR,w		; normal locomotive
;		movwf	CURRMTR
HandleE4_Loco:
		movf	DATA3,w			; function
		andlw	0x1F			; clear other bits to be sure
		movwf	CURRFNC
		movf	DATA4,w
		movwf	CURRFNC2
HandleE4_Data:
		btfsc	DATA2,7			; set dir
		bsf	CURRFNC,LocoDir
		btfss	DATA1,0			; set 27 -> steps
		btfsc	DATA1,1			; set 28 steps
		bsf	CURRFNC,Loco28
		btfsc	DATA1,2			; set 128 steps
		bsf	CURRFNC,Loco128
		movf	DATA2,w
		andlw	0x7F
		movwf	CURRSPD
		bcf	LOCO_OTHER		; loco controlled by other device?
		btfsc	DATA1,3
		bsf	LOCO_OTHER
		goto	HandleEndShwMenu

HandleEX_5:
		xorlw	(0xE4 ^ 0xE5)
		btfss	STATUS,Z
		goto	HandleEnd
HandleE5_1:
		movf	DATA1,w			; Loco information in multi-unit
		andlw	0xF0
		xorlw	0x10
		btfss	STATUS,Z
		goto	HandleEnd

;		bsf	MULTIUNIT
;		movf	DATA5,w			; Loco in a Multi Unit
;		movwf	CURRMTR
		goto	HandleE4_Loco

HandleEndShwMenu:
		bsf	MENU_CHG
HandleEnd:
		bcf	NEW_MSG			; message processed
		return


; --- Request messages


GetVersion:
		movlw	0x21			; get software version request
		call	SendHeader
		movlw	0x21
		call	SendData
		goto	SendMsg
		
GetStatus:
		movlw	0x21			; get status request
		call	SendHeader
		movlw	0x24
		call	SendData
		goto	SendMsg

;Estop:
;		movlw	0x80			; Emergency stop
;		call	SendHeader
;		goto	SendMsg

EOff:
		movlw	0x21			; Emergency Off
		call	SendHeader
		movlw	0x80
		call	SendData
		goto	SendMsg


Resume:
		movlw	0x21			; Resume operations request
		call	SendHeader
		movlw	0x81
		call	SendData
		goto	SendMsg
		
GetLocoInfo:
		bcf	GETINFO
		btfsc	SETUP_MODE
		return
		movlw	0xE3			; Locomotive information request
		call	SendHeader
		movlw	0x00
		call	SendData
		movf	CURRADRH,w		; AH
		call	SendData
		movf	CURRADR,w		; AL
		call	SendData		
		goto	SendMsg
		

LocoOperations:
		movlw	0xE4			; Locomotive operations request
		call	SendHeader
		movlw	0x10			; 14 steps
		btfsc	CURRFNC,Loco28
		movlw	0x12			; 28 steps
		btfsc	CURRFNC,Loco128
		movlw	0x13			; 128 steps
		call	SendData		
		movf	CURRADRH,w		; AH
		call	SendData
		movf	CURRADR,w		; AL
		call	SendData		
		movf	CURRSPD,w
		btfsc	CURRFNC,LocoDir
		iorlw	0x80
		call	SendData
SaveCurrentLoco:
		bcf	LOCO_OTHER
		movf	CURRADRH,w		; save current used loco
		movwf	EEDATA0
		movlw	LOKH_MEM
		call	SetParm
		movf	CURRADR,w		; save current used loco
		movwf	EEDATA0
		movlw	LOKL_MEM
		call	SetParm
		bsf	MENU_CHG
		goto	SendMsg


FuncOperations:
		movlw	0xE4			; Function operations request
		call	SendHeader
		movlw	0x20
		call	SendData
		movf	CURRADRH,w		; AH
		call	SendData
		movf	CURRADR,w		; AL
		call	SendData		
		movf	CURRFNC,w		; Function group 1
		andlw	0x1F
		call	SendData		
		goto	SaveCurrentLoco

FuncOperF5F12:
		movlw	0xE4			; Function operations request
		call	SendHeader
		movlw	0x21
		btfsc	SHW_F9F12
		movlw	0x22
		call	SendData
		movf	CURRADRH,w		; AH
		call	SendData
		movf	CURRADR,w		; AL
		call	SendData		
		movf	CURRFNC2,w		; Function group 2
		btfsc	SHW_F9F12
		swapf	CURRFNC2,w		; Function group 3
		andlw	0x0F
		call	SendData		
		goto	SaveCurrentLoco


SetAccessoryOff:
		bcf	SENDTURN
SetAccessory:
		movlw	0x52
		call	SendHeader
		movf	TURNOUTH,w		; turn out address starts at 1
		movwf	MSB
		movlw	0x03			; add 3 or -1 depending on command station
		btfss	T_COMMAND		; **
		movlw	0xFF			; **
		addwf	TURNOUT,w
		movwf	LSB
		btfsc	STATUS,C
		incf	MSB,f
		movlw	0xFF			;**
		btfss	T_COMMAND		;**
		addwf	MSB,f			;**
						; 'xxxxxxAA''AAAAAABB'
		rrf	MSB,f			; 'xxxxxxxA''AAAAAAAB'
		rrf	LSB,w
		rrf	MSB,f			; 'xxxxxxxx'A
		movwf	MSB			; 'AAAAAAAB'
		rrf	MSB,w			; 'AAAAAAAA'
		call	SendData

		rlf	LSB,w			; 'AAAAABBx'
		andlw	0x06
		iorlw	0x80			; deactivate default
		btfsc	SENDTURN
		iorlw	0x08			; activate
		btfsc	TPOSITION
		iorlw	0x01			; '1000DBBD'
		call	SendData
		goto	SendMsg		

CVReadRequest:
		movlw	0x22			; CV read request
		call	SendHeader
		movlw	0x15			; direct
		btfsc	CVTYPE,0
		movlw	0x14			; paged
		btfsc	CVTYPE,1		
		movlw	0x11			; register
		call	SendData
		incf	CVLOW,w			; CV 1..256
		call	SendData
		goto	SendMsg


CVWriteRequest:
		movlw	0x23			; CV write request
		call	SendHeader
		movlw	0x16			; direct
		btfsc	CVTYPE,0
		movlw	0x17			; paged
		btfsc	CVTYPE,1		
		movlw	0x12			; register
		call	SendData
		incf	CVLOW,w			; CV 1..256
		call	SendData
		movf	CVDATA,w		; data
		call	SendData
		goto	SendMsg


SMResults:
		bcf	GETRESULTS
		movlw	0x21			; Request for Service mode results
		call	SendHeader
		movlw	0x10
		call	SendData
		goto	SendMsg


CVWritePoM:
		movlw	0xE6			; PoM write request
		call	SendHeader
		movlw	0x30
		call	SendData
		movf	CURRADRH,w
;		andlw	b'10111111'		; *** Test SwitchPilot
		call	SendData
		movf	CURRADR,w
		call	SendData
		movf	CVHIGH,w		;**
		andlw	0x03			;**
		iorlw	0xEC			;**
		call	SendData
		movf	CVLOW,w
		call	SendData
		movf	CVDATA,w
		call	SendData
		goto	SendMsg

CVReadPoM:
		bsf	CVERROR			; *** 11/02/08 Show <?> to indicate read on LRC120
		movlw	0xE6			; *** PoM read request 05/12/07
		call	SendHeader
		movlw	0x30
		call	SendData
		movf	CURRADRH,w
;		andlw	b'10111111'		; *** Test SwitchPilot
		call	SendData
		movf	CURRADR,w
		call	SendData
		movf	CVHIGH,w
		andlw	0x03	
		iorlw	0xE4	
		call	SendData
		movf	CVLOW,w
		call	SendData
;		movf	CVDATA,w
		clrw
		call	SendData
		goto	SendMsg




; --- XpressNet messages routines


SendHeader:
		movwf	DUMMY
SendHeaderW:
		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it
		btfsc	NEW_TX			; last message sended?
		goto	SendHeaderW		; no, wait
		clrf	TXPOS			; xor byte
		clrf	TXCNT			; byte count
		movf	DUMMY,w
SendData:
		movwf	TEMP
		movlw	BUFTXINI
		addwf	TXCNT,w
		movwf	FSR
		movf	TEMP,w
		movwf	INDF
		xorwf	TXPOS,f
		incf	TXCNT,f
		return

SendMsg:
		movf	TXPOS,w			; Xor byte
		call	SendData
		bsf	NEW_TX			; transmit this
		return


SetMyAddress:
		movlw	ADR_MEM			; read from EEPROM
		call	EE_Read
		andlw	0x1F			; address beetwen 1 to 31
		iorlw	0x40			; anything to transmit default value
		movwf	MY_ADR
		movwf	TEMP			;	0000 0011
		swapf	TEMP,W			;	0011 0000
		xorwf	TEMP,F			;	0011 0011
		rrf	TEMP,W			;	X001 1001 1
		xorwf	TEMP,F			;	X010 1010
		btfsc	TEMP,2
		incf	TEMP, F
		rrf	TEMP,w			;	XX01 0101 0    ; C flag = parity (1=odd)
		btfsc	STATUS,C
		bsf	MY_ADR,7
		return

; --- LCD routines

LCDLONG:
		movwf	LSB			; Show bin byte 0..9999
		call	BIN2BCD
		movf	R1,w
		call	LCDBCD			; thousands & cents
		movf	R0,w
		goto	LCDBCD			; tens & units

LCDBYTE:
		clrf	MSB			; Show bin byte 0..255
LCDWORD:
		movwf	LSB			; Show bin byte 0..999
		call	BIN2BCD
		movf	R1,w
		call	LCDBCDL			; cents
		movf	R0,w
		goto	LCDBCD

LCDCON:
		bcf	PORTA,LCD_RS		; send command to LCD
		goto	LCDOUT

LCDBIN:
		movwf	LSB			; Show bin: 0..99 
		clrf	MSB
		call	BIN2BCD
		movf	R0,w
LCDBCD:
		movwf	TEMP			; out 2 BCD digits
		swapf	TEMP,w
		andlw	0x0F			; out BCD tens
		iorlw	0x30
		call	LCDCHR
		movf	TEMP,w
LCDBCDL:
		andlw	0x0F			; out BCD units
		iorlw	0x30
LCDCHR:
		bsf	PORTA,LCD_RS		; send char to LCD
LCDOUT:
		movwf	LCD_DATA
		movlw	0x04			; delay 40us
		call	Delay10us
		call	LCDSEND
		swapf	LCD_DATA,f
LCDSEND:
		movf	LCD_DATA,w		; send as 4 bit mode
		movwf	LCDPORT
		bsf	PORTA,LCD_E
		DNOP
		DNOP
		bcf	PORTA,LCD_E
		return

		
LCDSTR:
					; Print w string
		movwf	LSB		
		movlw	HIGH (String)
		movwf	PCLATH
		bcf	STATUS,C		; w * 2
		rlf	LSB,f
		movf	LSB,w
		call	String
		movwf	MSB			; PCLATH
		incf	LSB,w	
		call	String
		movwf	LSB			; PCL
LCDSTRCHR:
		call	GetChar
		movwf	TEMP
		btfsc	TEMP,7
		return
		call	LCDCHR
		incf	LSB,f			; next character
		btfsc	STATUS,Z
		incf	MSB,f

		btfsc	NEW_MSG			; new message received?
		call	HandleMsg		; yes, handle it

		goto	LCDSTRCHR

GetChar:
		movf	MSB,w			; goto MSB,LSB
		movwf	PCLATH
		movf	LSB,w
		movwf	PCL


; --- Bin and BCD conversions

BIN2BCD:                       
		bcf	STATUS,C		; 16 bit bin to 4 digit BCD
		movlw	0x10
		movwf	COUNT
		clrf	R0                          
		clrf	R1                          
LOOP8:                       
		rlf	LSB,f                          
		rlf	MSB,f                          
		rlf	R0,f                          
		rlf	R1,f                          
		decfsz	COUNT,f                          
		goto	ADJDEC
		return
ADJDEC:                         
		movlw	R0                          
		call	ADJBCD
		movlw	R1                          
		call	ADJBCD
		goto	LOOP8 
ADJBCD:                        
		movwf 	FSR                           
		movlw 	0x3                           
		addwf 	INDF,W                         
		movwf	TEMP
		btfsc	TEMP,3                      
		movwf	INDF                           
		movlw	0x30                          
		addwf	INDF,W                         
		movwf	TEMP
		btfsc	TEMP,7                      
		movwf	INDF                           
		return


BCD2BIN:					; 2 digit BCD to BIn
		movwf	TEMP			; units
		movwf	TEMP2			; dizain
		swapf	TEMP2,f
		movlw	0x0F
		andwf	TEMP,f			; units
		andwf	TEMP2,f			; dizain
		bcf	STATUS,C
		rlf	TEMP2,f			; DIZ*2
		movf	TEMP2,w	
		rlf	TEMP2,f			; DIZ*4
		rlf	TEMP2,f			; DIZ*8
		addwf	TEMP2,w			; DIZ*8 + DIZ*2 = DIZ*10
		addwf	TEMP,w			; DIZ*10 + UNIT
		return

MBCD2BIN:
		movlw	0x0F			; 3 digits BCD to Bin
		andwf	NUMBERH,f
LBCD2BIN:
		movf	NUMBERL,w		; 4 digits BCD to Bin
		call	BCD2BIN
		movwf	R0
		movf	NUMBERH,w
		call	BCD2BIN
		movwf	R1
		clrf	TEMP
		movlw	d'100'
		movwf	TEMP2
					; MSB,LSB = R1 * TEMP2 + R0
BINMUL:					
		clrf	MSB		; 
		clrf	LSB		; RES = 0
		movlw	0x08
		movwf	COUNT
LBCD2B1:
		rrf	TEMP2,f		; RR NUM1
		btfss	STATUS,C	; BTFSC CARRY
		goto	LBCD2B2
		movf	R1,w		; RES = NUM2 + RES
		addwf	LSB,f
		btfsc	STATUS,C
		incf	MSB,f
		movf	TEMP,w
		addwf	MSB,f
LBCD2B2:
		bcf	STATUS,C	; RL NUM2
		rlf	R1,f
		rlf	TEMP,f
		decfsz	COUNT,f
		goto	LBCD2B1

		movf	R0,w		; MSB,LSB + R0
		addwf	LSB,f
		btfsc	STATUS,C
		incf	MSB,f
		return


; --- Delays

;Delay4ms:
;		call	Delay2ms
;Delay2ms:
;		movlw	d'200'			; Delay 200 * 10us = 2ms
Delay10us:
		DNOP				; 1,2	Delay w * 10us
		DNOP				; 3,4
		DNOP				; 5,6

		addlw	0xFF			; 7
		btfss	STATUS,Z		; 8
		goto	Delay10us		; 9,10
		return

; ----- Analog Section

TimerOut:
		incf	KEYPRE,f		; scan keyboard 60Hz
		btfsc	KEYPRE,3
		call	ScanKeyb
;ReadPot:
		bcf	INTCON,T0IF
		return

; --- Keyboard Section

ScanKeyb:
		clrf	KEYPRE			; scan keyboard 60Hz
		btfss	DbnceOn			; debounce time?
		goto	Scan			; no, scan keyboard
		decfsz	DEBOUNCE,f		; yes, wait debouncing
		return
		bcf	DbnceOn			; end debounce
		movlw	d'40'			; first time auto repeat
		movwf	DEBOUNCE
		return
		
Scan:
		movlw	0xEF			; Init Column
		movwf	TEMP
		clrf	KEY
ScanNext:
		movf	TEMP,w
		movwf	KEYPORT			; out column
		DNOP
		DNOP
		swapf	INPORT,w
		movwf	TEMP2
		andlw	b'00000011'
		btfsc	PORTB,KEY3
		iorlw	b'00001000'
		btfsc	TEMP2,4
		iorlw	b'00000100'
		xorlw	b'00001111'		; a 1 indicates a key pressed
 		btfsc	STATUS,Z		; key pressed?
		goto	NoKey			; no

		btfsc	KeyHit			; yes, last key released?
		goto	KeyRepeat		; no
		bsf	KeyHit
		bcf	KeyRep
		movwf	TEMP
		rrf	TEMP,f
		btfsc	STATUS,C
		goto	KeyValue		; Row 0
		incf	KEY,f
		rrf	TEMP,f
		btfsc	STATUS,C
		goto	KeyValue		; Row 1
		incf	KEY,f
		rrf	TEMP,f
		btfsc	STATUS,C
		goto	KeyValue		; Row 2
		incf	KEY,f			; Row 3
KeyValue:
		movf	KEY,w
		movwf	NEWKEY
		bsf	DbnceOn
		movlw	0x02
		movwf	DEBOUNCE
KeyReturn:
		bsf	ServKey			; key need service
		return

NoKey:
		movlw	0x04			; next column 
		addwf	KEY,f
		rlf	TEMP,f			; next column bit
		btfsc	STATUS,C		; all columns readed?
		goto	ScanNext		; no, next
		bcf	KeyHit			; set no key pressed
		bcf	KeyRep

		btfsc	SENDTURN
		call	SetAccessoryOff

		return

KeyRepeat:
		decfsz	DEBOUNCE,f		; wait auto repeat time
		return
		bsf	KeyRep
		movf	MENU,w			;**
		andlw	0xFE			;**
		movlw	d'3'			;** next time auto repeat
		btfsc	CURRFNC,Loco128		;**
		btfss	STATUS,Z		;**
		movlw	d'5'			;**
		movwf	DEBOUNCE
		goto	KeyReturn		; set key pressed
	

; --- Keys routines


Number_9:
		incf	UNITS,f
Number_8:
		incf	UNITS,f
Number_7:
		incf	UNITS,f
Number_6:
		incf	UNITS,f
Number_5:
		incf	UNITS,f
Number_4:
		incf	UNITS,f
Number_3:
		incf	UNITS,f
Number_2:
		incf	UNITS,f
Number_1:
		incf	UNITS,f
Number_0:
		swapf	NUMBERH,w
		andlw	0xF0
		movwf	NUMBERH
		swapf	NUMBERL,w
		andlw	0x0F
		iorwf	NUMBERH,f
		swapf	NUMBERL,w
		andlw	0xF0
		iorwf	UNITS,w
		movwf	NUMBERL
		clrf	UNITS
		bsf	NUMTYPED		;**
		goto	K_ShwEnd

K_ChgDir:
		movlw	(1<<LocoDir)		; change direction
		xorwf	CURRFNC,f
		goto	LocoOperations

K_SpeedUp:					; **
		call	Normalize
		movwf	TEMP			; if max speed, nothing to do
		movlw	d'14'
		btfsc	CURRFNC,Loco28
		movlw	d'28'
		btfsc	CURRFNC,Loco128
		movlw	d'126'
		xorwf	TEMP,w
		btfsc	STATUS,Z
		return
		incf	TEMP,w			; accelerate
		goto	ConvertSpd

K_SpeedDown:					; **
		call	Normalize
		iorlw	0x00			; if stopped, nothing to do
		btfsc	STATUS,Z
		return
		addlw	0xFF			; brake
ConvertSpd:
		andlw	0x7F
		btfsc	CURRFNC,Loco28		; convert to current speed step
		goto	ConvSpd28
		btfsc	CURRFNC,Loco128	
		goto	ConvSpd128
ConvSpd14:					; 14 steps
		andlw	0x0F
ConvSpd128:
		btfss	STATUS,Z
		addlw	0x01			; skip E.stop
		movwf	CURRSPD			; update speed
		goto	LocoOperations
ConvSpd28:
		andlw	0x1F
		btfss	STATUS,Z
		addlw	0x03			; skip E.stop
		movwf	TEMP
		rrf	TEMP,w			; set bit 4 as LSB
		btfsc	STATUS,C
		iorlw	0x10
		andlw	0x1F
		movwf	CURRSPD			; update speed
		goto	LocoOperations

K_Brake:					;**
		clrf	CURRSPD			; Stop with current deceleration
		goto	LocoOperations

K_Stop:
		btfss	ServiceMode		; exit service mode
		btfsc	EmergStop		; in E_stop or E_Off?
K_StopOn:
		goto	Resume			; yes, Resume
K_StopOff:
		btfsc	EmergOff
		goto	K_StopOn
		goto	EOff			; no, do Emergency Off


K_SetShwF9F12:
		movlw	(1<<F9F12_BIT)		; Show F9..F12
		goto	K_SetShwFx
K_SetShwF5F8:
		movlw	(1<<F5F8_BIT)		; Show F5..F8
		goto	K_SetShwFx
K_SetShwFLF4:
		movlw	0x00			; Show FL..F4
K_SetShwFx:
		bcf	SHW_F5F8
		bcf	SHW_F9F12
		iorwf	FLAGS,f
		goto	K_ShwEnd

K_F4:
		movlw	0x08			; Change key 4
		goto	K_Fx
K_F3:
		movlw	0x04			; Change key 3
		goto	K_Fx
K_F2:
		movlw	0x02			; Change key 2
		goto	K_Fx
K_F1:
		movlw	0x01			; Change key 1
K_Fx:
		btfss	SHW_F5F8		; Change key 1..4
		btfsc	SHW_F9F12
		goto	K_SetFx2
		goto	K_SetFx
K_Light:
		movlw	0x10			; Change FL
K_SetFx:
		xorwf	CURRFNC,f		; Change F1..F4
		goto	FuncOperations	
K_SetFx2:
		movwf	TEMP			; Change F5..F12
		btfsc	SHW_F9F12
		swapf	TEMP,w
		xorwf	CURRFNC2,f	
		goto	FuncOperF5F12

K_ExitProg:
		bcf	CVSEL
		btfsc	ServiceMode
		call	Resume
		clrf	MENU			;**
		goto	K_NxtMenu		;**
K_EnterRun:
		clrf	MENU
		movf	NUMBERL,w
		iorwf	NUMBERH,w
		btfsc	STATUS,Z
		goto	K_NxtMenu
		call	LBCD2BIN		; NUMBERH.NUMBERL -> MSB,LSB
		movf	NUMBERH,w		; loco 1..99?
		btfss	STATUS,Z
		movlw	0xC0			; no, 100..9999
		iorwf	MSB,w
		movwf	CURRADRH
		movf	LSB,w
		movwf	CURRADR
		bsf	GETINFO
K_NxtMenu:
		clrf	NUMBERL
		clrf	NUMBERH
		incf	MENU,f
		bcf	NUMTYPED		;**
		goto	K_ShwEnd


K_EnterLok:
		clrf	NUMBERL
		clrf	NUMBERH
		clrf	MENU
		bsf	MENU_CHG
		return


K_ChangeStep:
		movf	CURRSPD,w		; only if speed 0
		btfss	STATUS,Z
		return
		movlw	b'10000000'		; change step 14,28,128
		btfss	CURRFNC,Loco128
		movlw	b'01000000'
		btfsc	CURRFNC,Loco28
		movlw	b'11000000'
		xorwf	CURRFNC,f
		goto	LocoOperations		; update new steps



K_SelSetup:
		movlw	SELSETUP_MSK		; change setup menu
		xorwf	FLAGS,f
		goto	K_ShwEnd


K_TrnThrow:
		bcf	TPOSITION		; Turnout thwow
		goto	K_ChgTrn
K_TrnNormal:
		bsf	TPOSITION		; Turnout normal
K_ChgTrn:
		btfsc	SENDTURN
		return
		movf	NUMBERH,w		; any typed number?
		iorwf	NUMBERL,w
		btfsc	STATUS,Z
		goto	K_TrnOld
		call	MBCD2BIN		; yes, calc number
		movf	MSB,w
		movwf	TURNOUTH
		movf	LSB,w
		movwf	TURNOUT
K_TrnOld:
		clrf	NUMBERH			; no, send old turnout	
		clrf	NUMBERL
		bsf	MENU_CHG
		bsf	SENDTURN
		goto	SetAccessory


K_SetupUp:
		btfsc	SEL_SETUP
		goto	K_CmdSetup
K_XbusUp:
		movlw	ADR_MEM			; Increment Xbus address
		call	EE_Read
		movwf	EEDATA0

		incf	EEDATA0,f
		movlw	d'32'
		xorwf	EEDATA0,w
		movlw	d'1'
		btfsc	STATUS,Z
		movwf	EEDATA0
K_XbusUpdate:
		bsf	MENU_CHG
		movlw	ADR_MEM
		goto	SetParm
K_SetupDwn:
		btfsc	SEL_SETUP
		goto	K_CmdSetup
K_XbusDwn:
		movlw	ADR_MEM			; Decrement Xbus address
		call	EE_Read
		movwf	EEDATA0

		decf	EEDATA0,f
		movlw	d'31'
		btfsc	STATUS,Z
		movwf	EEDATA0
		goto	K_XbusUpdate


K_CmdSetup:
		movlw	CMD_MEM			; ** Change command station used
		call	EE_Read
		xorlw	0x01
		movwf	EEDATA0
		bsf	MENU_CHG
		movlw	CMD_MEM
		goto	SetParm


K_CVSel:
		call	K_CVTyped		;**
		movlw	CVSEL_MSK		; change input selection
		xorwf	FLAGS2,f
		clrf	NUMBERL			;**
		clrf	NUMBERH			;**
		bcf	NUMTYPED		;**
K_CVShwEnd:
		bcf	CVERROR
K_ShwEnd:
		bsf	MENU_CHG
		return


K_IncCVType:
		incf	CVTYPE,w
		goto	K_CVType
K_DecCVType:
		decf	CVTYPE,w
K_CVType:
		andlw	0x03
		btfss	CVSEL			;** not permited if enter data
		movwf	CVTYPE
		goto	K_CVShwEnd


K_CVRequest:
		call	K_CVTyped		;**
		clrf	NUMBERL			;**
		clrf	NUMBERH			;**
		bcf	NUMTYPED		;****

		movf	MSB,w			;** data error?
		btfss	STATUS,Z		;**
		goto	K_ShwEnd		;**

		movlw	0x03			; PoM mode?
		xorwf	CVTYPE,w
		btfsc	STATUS,Z
		goto	K_CVRequestPoM
		bcf	CVERROR
		bsf	GETRESULTS		
		bsf	CVRESULTS		; waiting for results
		btfsc	CVSEL			; no, read or write?
		call	CVWriteRequest
		btfss	CVSEL
		call	CVReadRequest
		movlw	SECONDLINE
		call	LCDCON
		movlw	d'19'
		btfsc	CVSEL
		movlw	d'18'
		bcf	CVSEL
		goto	LCDSTR
K_CVRequestPoM:
		bcf	CVERROR
		btfsc	CVSEL
		call	CVWritePoM
		btfss	CVSEL			; *** 05/12/07
		call	CVReadPoM		; ***
		bcf	CVSEL
		goto	K_ShwEnd


K_CVTyped:
		clrf	MSB			;** save typed values
		btfsc	CVSEL
		goto	K_CVTypedData
		movlw	0x03			; PoM?
		xorwf	CVTYPE,w
		btfsc	STATUS,Z
		goto	K_CVTypedPoM
		movf	CVHIGH,w		; max. CV256
		movwf	MSB
		btfss	STATUS,Z
		clrf	CVLOW
		clrf	CVHIGH
		btfss	NUMTYPED
		return				; not typed
		call	MBCD2BIN		; yes, calc number
		movlw	0xFF			; normalize CV number 1->0; 256->255
		addwf	LSB,f
		btfsc	STATUS,C
		incf	MSB,f
		addwf	MSB,f
		movf	MSB,w			; greater than 255?
		btfss	STATUS,Z
		return				; yes, nothing to do
		movf	LSB,w			; save value
		movwf	CVLOW
		return
K_CVTypedPoM:
		btfss	NUMTYPED		;
		return				; not typed
		call	MBCD2BIN		; yes, calc number
		movlw	0xFF			; normalize CV number 1->0; 256->255
		addwf	LSB,f
		btfsc	STATUS,C
		incf	MSB,f
		addwf	MSB,f
		movf	MSB,w			; save CV address
		movwf	CVHIGH
		movf	LSB,w
		movwf	CVLOW
		clrf	MSB
		return
K_CVTypedData:
		btfss	NUMTYPED		;
		return				; not typed
		call	MBCD2BIN		; yes, calc number
		movf	MSB,w			; greater than 255?
		btfss	STATUS,Z
		return				; yes, nothing to do
		movf	LSB,w			; save value
		movwf	CVDATA
		return
	

; ----- Serial port routines (XBus)

UART_INI:
		bcf	COMPORT,TXRX		; Disable TX
		clrf	XFLAGS			; clear XpressNet flags
		clrf	RX_LEN			; clear input buffer
		SEL_BANK_1
		movlw	HIGH_BAUD
		movwf	SPBRG
		movlw	0x64			; 9 bit, Enable TX, BRGH=1, TXD9=0
		movwf	TXSTA
		SEL_BANK_0
		movlw	0xD0			; Enable RX, 9 bit
		movwf	RCSTA
		clrw				; Settling time
SETTLE:
		addlw	0xFF
		btfss	STATUS,Z
    		goto 	SETTLE
		movf 	RCREG,w         	; flush receive buffer
		movf 	RCREG,w
		movf 	RCREG,w
		return

;------------------------------------------------------------------------------------------------

; ----- Data Tables

		org	0x5D0
String:
		addwf	PCL,f
		retlw	HIGH (MSG_DCC)		; 0
		retlw	LOW  (MSG_DCC)
		retlw	HIGH (MSG_WELL)		; 1
		retlw	LOW  (MSG_WELL)
		retlw	HIGH (MSG_SEL)		; 2
		retlw	LOW  (MSG_SEL)
		retlw	HIGH (MSG_CTRL)		; 3
		retlw	LOW  (MSG_CTRL)
		retlw	HIGH (MSG_CMD)		; 4
		retlw	LOW  (MSG_CMD)
		retlw	HIGH (MSG_NFOUND)	; 5
		retlw	LOW  (MSG_NFOUND)
		retlw	HIGH (MSG_TURN)		; 6
		retlw	LOW  (MSG_TURN)
		retlw	HIGH (MSG_BLANK)	; 7
		retlw	LOW  (MSG_BLANK)
		retlw	HIGH (MSG_XBUS)		; 8
		retlw	LOW  (MSG_XBUS)
		retlw	HIGH (MSG_ARROW)	; 9 **
		retlw	LOW  (MSG_ARROW)
		retlw	HIGH (MSG_ESTOP)	; 10
		retlw	LOW  (MSG_ESTOP)
		retlw	HIGH (MSG_SERV)		; 11
		retlw	LOW  (MSG_SERV)
		retlw	HIGH (MSG_CVDIR)	; 12
		retlw	LOW  (MSG_CVDIR)
		retlw	HIGH (MSG_CVPAG)	; 13
		retlw	LOW  (MSG_CVPAG)
		retlw	HIGH (MSG_CVPHY)	; 14
		retlw	LOW  (MSG_CVPHY)
		retlw	HIGH (MSG_CVPOM)	; 15
		retlw	LOW  (MSG_CVPOM)
		retlw	HIGH (MSG_CVLOCO)	; 16
		retlw	LOW  (MSG_CVLOCO)
		retlw	HIGH (MSG_BLANK4)	; 17
		retlw	LOW  (MSG_BLANK4)
		retlw	HIGH (MSG_PROG)		; 18
		retlw	LOW  (MSG_PROG)
		retlw	HIGH (MSG_READ)		; 19
		retlw	LOW  (MSG_READ)
		retlw	HIGH (MSG_LENZ)		; 20 **
		retlw	LOW  (MSG_LENZ)
		retlw	HIGH (MSG_ROCO)		; 21 **
		retlw	LOW  (MSG_ROCO)
		retlw	HIGH (MSG_BLANK12)	; 22 **
		retlw	LOW  (MSG_BLANK12)


;----- Internal EEPROM routines


EE_Read:
		bsf	STATUS,RP0		; w=ADR
		movwf	EEADR
		bsf	EECON1,RD
		movf	EEDATA,w
		bcf	STATUS,RP0
		return


SetParm:
		call	EE_Read			; w=ADR, EEDATA0=data. Write only changes
		xorwf	EEDATA0,w
		btfsc	STATUS,Z
		return
EE_Write:		
		movf	EEDATA0,w
		bsf	STATUS,RP0
		movwf	EEDATA
		bsf	EECON1,WREN
		bcf	INTCON,GIE
		movlw	0x55
		movwf	EECON2
		movlw	0xAA
		movwf	EECON2
		bsf	EECON1,WR
		bsf	INTCON,GIE
		bcf	EECON1,WREN
EEWrite0:
		btfsc	EECON1,WR
		goto	EEWrite0
		bcf	STATUS,RP0
		return

SetTimer1:
		movwf	T1CON			; set timer1
		clrf	TMR1L			; 
		clrf	TMR1H
		bcf	PIR1,TMR1IF
		return


; ------------- Language messages -------------------------------------------------------------------


	ifdef	__ENGLISH

; ------------- English messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	" by  F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"Select Loco:"		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Loco        "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Command  Station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	"   not found!   "	,0x80
MSG_TURN:
		dt	"Turnout:    "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Xbus Address: "	,0x80
;MSG_POT:
;		dt	"Pot. Offset:  "	,0x80
;		dt	".......|........"
MSG_ESTOP: 
		dt	"Emergency  Stop!"	,0x80
MSG_SERV:
		dt	"  Service Mode  "	,0x80
MSG_CVDIR:
		dt	" CV Direct  "		,0x80
MSG_CVPAG:
		dt	" CV Paged   "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Loco"			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"Programming CV.."	,0x80
MSG_READ:
		dt	"Reading CV...   "	,0x80
MSG_ARROW:
		dt	"-",CHR_BKW,"?",CHR_FWD	,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif

	ifdef	__CASTELLANO

; ------------- Spanish messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	" por F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"Selecc.Loco:"		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Loco        "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Command  Station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	" no encontrada! "	,0x80
MSG_TURN:
		dt	"Desvio:     "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Direcc. Xbus: "	,0x80
;MSG_POT:
;		dt	"Desplaz.Pot:  "	,0x80
;		dt	".......|........"
MSG_ESTOP: 
		dt	"Stop Emergencia!"	,0x80
MSG_SERV:
		dt	"  Modo Servicio "	,0x80
MSG_CVDIR:
		dt	" CV Directo "		,0x80
MSG_CVPAG:
		dt	" CV Pagina  "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Loco"			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"Programando CV.."	,0x80
MSG_READ:
		dt	"Leyendo CV...   "	,0x80
MSG_ARROW:
		dt	"-",CHR_BKW,"?",CHR_FWD	,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif


	ifdef	__DEUTSCH

; ------------- German messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	" bei F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"Waehle Lok: "		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Lok         "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"    Zentrale    "	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	"nicht  gefunden!"	,0x80
MSG_TURN:
		dt	"Weichen:    "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Xbus Address: "	,0x80		; ***
;MSG_POT:
;		dt	"Pot. Offset:  "	,0x80		; ***
;		dt	".......|........"
MSG_ESTOP: 
		dt	" STOP! Nothalt! "	,0x80
MSG_SERV:
		dt	"  Service Modus "	,0x80
MSG_CVDIR:
		dt	" CV Direct  "		,0x80
MSG_CVPAG:
		dt	" CV Paged   "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Lok "			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"Programmieren CV"	,0x80
MSG_READ:
		dt	"Lesen CV...     "	,0x80
MSG_ARROW:
		dt	"-",CHR_BKW,"?",CHR_FWD	,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif


	ifdef	__ITALIANO

; ------------- Italian messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	" di  F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"Scegli Loco:"		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Loco        "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Command  Station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	"  non trovata!  "	,0x80
MSG_TURN:
		dt	"Scambi:     "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Xbus Address: "	,0x80		; ***
;MSG_POT:
;		dt	"Pot. Offset:  "	,0x80		; ***
;		dt	".......|........"
MSG_ESTOP: 
		dt	"STOP! Emergenza!"	,0x80
MSG_SERV:
		dt	" Modo  Servizio "	,0x80
MSG_CVDIR:
		dt	" CV Direct  "		,0x80
MSG_CVPAG:
		dt	" CV Paged   "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Loco"			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"Programmo CV... "	,0x80
MSG_READ:
		dt	"Leggo CV...     "	,0x80
MSG_ARROW:
		dt	"-",CHR_BKW,"?",CHR_FWD	,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif


	ifdef	__NEDERLANDS

; ------------- Dutch messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	" bei F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"Kies Lok:   "		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Lok         "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Command  Station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	" niet gevonden! "	,0x80
MSG_TURN:
		dt	"Wissel:     "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Xbus Address: "	,0x80		; ***
;MSG_POT:
;		dt	"Pot. Offset:  "	,0x80		; ***
;		dt	".......|........"
MSG_ESTOP: 
		dt	" STOP! Noodstop "	,0x80
MSG_SERV:
		dt	"  Service Mode  "	,0x80
MSG_CVDIR:
		dt	" CV Direct  "		,0x80
MSG_CVPAG:
		dt	" CV Paged   "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Lok "			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"Programmeren CV."	,0x80
MSG_READ:
		dt	"Lezen CV...     "	,0x80
MSG_ARROW:
		dt	"-",CHR_BKW,"?",CHR_FWD	,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif

	ifdef	__CATALA

; ------------- Catalan messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	" per F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"Selecc.Loco:"		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Loco        "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Command  Station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	"  no  trobada!  "	,0x80
MSG_TURN:
		dt	"Agulla:     "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Adre",CHR_C,"a Xbus:  ",0x80
;MSG_POT:
;		dt	"Despl.Pot  :  "	,0x80
;		dt	".......|........"
MSG_ESTOP: 
		dt	"Stop Emergencia!"	,0x80
MSG_SERV:
		dt	"  Modo  Servei  "	,0x80
MSG_CVDIR:
		dt	" CV Directe "		,0x80
MSG_CVPAG:
		dt	" CV Pagina  "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Loco"			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"Programant CV..."	,0x80
MSG_READ:
		dt	"Llegint CV...   "	,0x80
MSG_ARROW:
		dt	"-",CHR_BKW,"?",CHR_FWD	,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif

	ifdef	__FRANCAIS

; ------------- French messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	"pour F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"Tapez Loco: "		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Loco        "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Command  Station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	"  non  trouve!  "	,0x80
MSG_TURN:
		dt	"Aiguillage: "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Adresse Xbus: "	,0x80
;MSG_POT:
;		dt	"Despl.Pot  :  "	,0x80
;		dt	".......|........"
MSG_ESTOP: 
		dt	"Arret d'urgence!"	,0x80
MSG_SERV:
		dt	"  Mode Service  "	,0x80
MSG_CVDIR:
		dt	" CV Direct  "		,0x80
MSG_CVPAG:
		dt	" CV Pagine  "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Loco"			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001>000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"Programation CV."	,0x80
MSG_READ:
		dt	"Lecture CV...   "	,0x80
MSG_ARROW:
		dt	"-",CHR_BKW,"?",CHR_FWD	,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif


	ifdef	__CZECH

; ------------- Czech messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	" od  F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"Vyber Loko: "		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Lokomotiva  "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Command  Station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	"  Nenalezeno!   "	,0x80
MSG_TURN:
		dt	"V",CHR_Y,"hybka ",CHR_CC,".: "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Xbus Adresa:  "	,0x80
;MSG_POT:
;		dt	"Pot. Offset:  "	,0x80
;		dt	".......|........"
MSG_ESTOP: 
		dt	"Z",CHR_A,"chran",CHR_A,"  Brzda!"	,0x80
MSG_SERV:
		dt	"  Servisni Mod  "	,0x80
MSG_CVDIR:
		dt	" CV Direct  "		,0x80
MSG_CVPAG:
		dt	" CV Paged   "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Loko"			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"Programuji CV..."	,0x80
MSG_READ:
		dt	CHR_CC,"tu CV...       "	,0x80
MSG_ARROW:
		dt	"-<?>"			,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif


	ifdef	__HUNGARIAN

; ------------- Hungarian messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	CHR_A,"ltal F.M.CA",CHR_N,"ADA",0x80
MSG_SEL:
		dt	"Lok.valaszt:"		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Lokomotiv   "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Command  Station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	" Nem tal",CHR_A,"lh. !! "	,0x80
MSG_TURN:
		dt	"V",CHR_A,"lto:      "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Xbus Adresa:  "	,0x80
;MSG_POT:
;		dt	"Pot. Offset:  "	,0x80
;		dt	".......|........"
MSG_ESTOP: 
		dt	"  Vesz fek !!!  "	,0x80
MSG_SERV:
		dt	"  Szerviz  Mod  "	,0x80
MSG_CVDIR:
		dt	" CV Direct  "		,0x80
MSG_CVPAG:
		dt	" CV Paged   "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Loko"			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:
		dt	"CV Irasa...     "	,0x80
MSG_READ:
		dt	"CV Olvas...     "	,0x80
MSG_ARROW:
		dt	"-",CHR_BKW,"?",CHR_FWD	,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif


	ifdef	__SWEDISH

	
; ------------- Swedish messages 

		org	0x624

;		dt	"0123456789012345"
MSG_DCC:
		dt	" MiniMaus  v."
		dt	(__VERNUM  & 0x0F)+0x30
		dt	__VERREV
		dt	" " 			,0x80
MSG_WELL:
                dt	" av  F.M.CA",CHR_N,"ADA ",0x80
MSG_SEL:
		dt	"V",CHR_EA,"lj lok:   "		,0x80
;		dt	" <000  28  *----"	,0x80
MSG_CTRL:
		dt	"Lok         "		,0x80
;		dt	"Cocodrilo   0003"	,0x80
;		dt	" <000  28 F*1234"	,0x80
;		dt	"<<000  28 F81234"	,0x80
;		dt	"<<000  28 F21234"	,0x80
MSG_CMD:
		dt	"Kommand  station"	,0x80
;		dt	"Ver:3.0  Type:04"	
MSG_NFOUND:
		dt	"   ej funnen!   "	,0x80
MSG_TURN:
		dt	"V",CHR_EA,"xel:      "		,0x80
;		dt	"Turnout:    999/"	,0x80
MSG_BLANK:
		dt	"    "
MSG_BLANK12:
		dt	"        "
MSG_BLANK4:
		dt	"    "			,0x80
MSG_XBUS:
		dt	"Xbus adress:  "	,0x80
;MSG_POT:
;		dt	"Pot. Offset:  "	,0x80
;		dt	".......|........"
MSG_ESTOP: 
		dt	"   N",CHR_OO,"d stopp!   "	,0x80
MSG_SERV:
		dt	"  Service Mode  "	,0x80
MSG_CVDIR:
		dt	" CV Direkt  "		,0x80
MSG_CVPAG:
		dt	" CV Paged   "		,0x80
MSG_CVPHY:
		dt	" CV Reg.    "		,0x80
MSG_CVPOM:
		dt	" CV PoM     "		,0x80
MSG_CVLOCO:
		dt	"Lok "			,0x80
;		dt	" CV  PoM    Loco"
;		dt	" CV  Direct Loco"
;		dt	"C001-000    0003"
;		dt	">001-<?>    ----"
MSG_PROG:                
		dt	"Programmering CV"	,0x80
		     
MSG_READ:
		dt	"L",CHR_EA,"ser CV...     "	,0x80
MSG_ARROW:
		dt	"-<?>"			,0x80
MSG_LENZ:
		dt	"Lenz"			,0x80
MSG_ROCO:
		dt	"Roco"			,0x80

	endif


; ------------- Service to Keyboard Tables

		org	0x73C

;		1 2 3 STOP			; This is the keyboard we use
;		4 5 6 MENU
;		7 8 9 SEL
;		< 0 > NXT


ServiceKey:
		bcf	ServKey
		movlw	HIGH (ServRUN)
		movwf	PCLATH
		movlw	0x0F
		andwf	NEWKEY,f
		swapf	MENU,w
		andlw	0x70
		addwf	NEWKEY,w
		addwf	PCL,f

ServLOK:
		goto	Number_0	; 0
		goto	K_SpeedUp	; >
		goto	K_SpeedDown	; <
		goto	K_ChangeStep	; NXT
		goto	Number_8	; 8
		goto	Number_9	; 9
		goto	Number_7	; 7
		goto	K_EnterRun	; SEL
		goto	Number_5	; 5
		goto	Number_6	; 6
		goto	Number_4	; 4
		return			; MENU
		goto	Number_2	; 2
		goto	Number_3	; 3
		goto	Number_1	; 1
		goto	K_Stop		; STOP
ServRUN:
		goto	K_Brake		; 0		E C D F
		goto	K_SpeedUp	; >		A 8 9 B
		goto	K_SpeedDown	; <		6 4 5 7
		goto	K_ChgDir	; NXT		2 0 1 3
		goto	K_SetShwF5F8	; 8
		goto	K_SetShwF9F12	; 9
		goto	K_SetShwFLF4	; 7
		goto	K_EnterLok	; SEL
		goto	K_Light		; 5
		return			; 6
		goto	K_F4		; 4
		goto	K_NxtMenu	; MENU
		goto	K_F2		; 2
		goto	K_F3		; 3
		goto	K_F1		; 1
		goto	K_Stop		; STOP

ServTURNOUT:
		goto	Number_0	; 0
		goto	K_TrnThrow	; >
		goto	K_TrnNormal	; <
		return			; NXT
		goto	Number_8	; 8
		goto	Number_9	; 9
		goto	Number_7	; 7
		return			; SEL
		goto	Number_5	; 5
		goto	Number_6	; 6
		goto	Number_4	; 4
		goto	K_NxtMenu	; MENU
		goto	Number_2	; 2
		goto	Number_3	; 3
		goto	Number_1	; 1
		goto	K_Stop		; STOP
ServPROG:
		goto	Number_0	; 0
		goto	K_IncCVType	; >
		goto	K_DecCVType	; <
		goto	K_CVSel		; NXT
		goto	Number_8	; 8
		goto	Number_9	; 9
		goto	Number_7	; 7
		goto	K_CVRequest	; SEL
		goto	Number_5	; 5
		goto	Number_6	; 6
		goto	Number_4	; 4
		goto	K_ExitProg	; MENU
		goto	Number_2	; 2
		goto	Number_3	; 3
		goto	Number_1	; 1
		goto	K_Stop		; STOP
ServSETUP:
		return			; 0
		goto	K_SetupUp	; >
		goto	K_SetupDwn	; <
		return			; NXT
		return			; 8
		return			; 9
		return			; 7
		return			; SEL
		return			; 5
		return			; 6
		return			; 4
		goto	K_SelSetup	; MENU
		return			; 2
		return			; 3
		return			; 1
		goto	INIT		; STOP
ServMESSAGES:
		return			; 0
		return			; >
		return			; <
		return			; NXT
		return			; 8
		return			; 9
		return			; 7
		return			; SEL
		return			; 5
		return			; 6
		return			; 4
		return			; MENU
		return			; 2
		return			; 3
		return			; 1
		goto	K_Stop		; STOP


; ------------- LCD Grafic Characters 

		org	0x7A6

NEWLCDCHR:
		addwf	PCL,f

		dt	0x0E,0x00,0x11,0x19,0x15,0x13,0x11,0x00		; Ņ
		dt	0x00,0x00,0x15,0x15,0x17,0x11,0x11,0x00		; 14
		dt	0x00,0x00,0x17,0x11,0x17,0x14,0x17,0x00		; 12
		dt	0x00,0x00,0x07,0x01,0x07,0x04,0x07,0x00		; 2
		dt	0x00,0x00,0x1C,0x14,0x1C,0x14,0x1C,0x00		; 8
	ifdef	__NO_CHR_ARROW
	ifdef	__SWEDISH
		dt	0x11,0x00,0x0E,0x01,0x0E,0x11,0x0F,0x00		; ä
		dt	0x11,0x00,0x0E,0x11,0x11,0x11,0x0E,0x00		; ö
	else
		dt	0x02,0x04,0x11,0x11,0x0F,0x01,0x0E,0x00		; y
		dt	0x0A,0x04,0x00,0x0E,0x10,0x10,0x0E,0x00		; c
	endif
	else
		dt	0x10,0x18,0x1C,0x1E,0x1C,0x18,0x10,0x00		; ->
		dt	0x02,0x06,0x0E,0x1E,0x0E,0x06,0x02,0x00		; <-
	endif
	ifdef	__NO_CHR_FNC
		dt	0x02,0x04,0x0E,0x01,0x0F,0x11,0x0F,0x00		; a
	else
		dt	0x00,0x0E,0x0E,0x0E,0x0E,0x0E,0x00,0x00		; []
	endif
		dt	0x00,0x00,0x0E,0x11,0x10,0x12,0x0F,0x04		; į





; ----- EEPROM default values


		org	0x2100 + EE_INI
 	
		dw	0x01		; XpressNet device address
		dw	0x00		; Last Locomotive used
		dw	0x03
		dw	0x01		; Command station selected

		
		org	0x2110

		dt	"MiniMaus"
		dt	"v."
		dt	(__VERNUM   & 0x0F)+0x30
		dt	__VERREV

	ifdef	__ENGLISH
		dt	"-ENG"
	endif
	ifdef	__CASTELLANO
		dt	"-ESP"
	endif
	ifdef	__DEUTSCH
		dt	"-DEU"
	endif
	ifdef	__ITALIANO
		dt	"-ITA"
	endif
	ifdef	__NEDERLANDS
		dt	"-NED"
	endif
	ifdef	__CATALA
		dt	"-CAT"
	endif
	ifdef	__FRANCAIS
		dt	"-FRN"
	endif
	ifdef	__CZECH
		dt	"-CZH"
	endif
	ifdef	__HUNGARIAN
		dt	"-HUN"
	endif
	ifdef	__SWEDISH
		dt	"-SWE"
	endif

		dt	"F.Caņada"
		dt	(__VERDAY   >> 4)  +0x30
		dt	(__VERDAY   & 0x0F)+0x30,"/"
		dt	(__VERMONTH >> 4)  +0x30
		dt	(__VERMONTH & 0x0F)+0x30,"/"
		dt	(__VERYEAR  >> 4)  +0x30
		dt	(__VERYEAR  & 0x0F)+0x30


	end



