;;======================================================================;;
;;				TU_SHUUU				;;
;;======================================================================;;
;;									;;
;; Program:         TU-SHUU -- DCC Sound generator			;;
;; Code:            Paco Caņada	(http://www.fut.es/~fmco)		;;
;; Platform:        Microchip PIC16F628, 4 Mhz				;;
;; Date:            18.07.2004						;;
;; First release:   28.07.2004						;;
;; LastDate:        28.07.2004						;;
;;									;;
;;======================================================================;;

; Sound generator with DCC decoder based on chip AY-3-8910 (only one channel audio, noise generator and envelope function)
; DCC signal decoding based on Georg Ziegler routines.
;
; Minimal external components, uses internal oscilator at 4 MHz, 
; Uses TMR2 as PWM generator for sound, Vref module for volume control, TMR1 for Envelope timing,
; TMR0 for software noise generator, internal comparator for mixing sound and noise.
; RB0 is DCC input, RB3 (PWM) conected to RA1 (comparator), RA2 outputs to a buffer OPAMP
; RA4 to OPAMP output throught a resistor and to another OPAMP buffer for output to a buzzer
;
; This program is distributed as is but WITHOUT ANY WARRANTY
; I hope you enjoy!!
;
; Revisions:
; 18.07.2004	Start of writting code
; 22.07.2004	First prototype
; 25.07.2004	Added envelope generation
; 28.07.2004	Added Envelope duration based on speed

; ----- Definitions

#define		__VERNUM	D'1'
#define		__VERDAY	0x28
#define		__VERMONTH	0x07
#define		__VERYEAR	0x04


                list    p=16F628,r=hex

		errorlevel	-302		; suppress Bank warnings

	        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'

RA_TRIS         equ     0xE7			; RA0,RA1,RA2,RA5,RA6,RA7: inputs
RB_TRIS         equ     0xF1			; RB0,RB4,RB5,RB6,RB7: inputs
RA_INI          equ     0x00			; all zero
RB_INI          equ     0x00			; all zero
OPTION_INI	equ	0x85			; Option register: timer prescaler-64, no pull-up
INTC_INI	equ	0x00			; GIE, PEIE disable
PIE1_INI	equ	0x00			; no interrupts

#DEFINE		DCCIN	PORTB,0			; DCC input pin (GPIO,3 only input)
#define		FL_LED	PORTB,2			; Front light
#define		BL_LED	PORTB,1			; Back light

; --- EEPROM Section

#define		EE_INI		0x00

E_CV1		equ	EE_INI+0x00	; CV1	Primary Adress
E_CV7		equ	EE_INI+0x01	; CV7	Manufacturer version
E_CV8		equ	EE_INI+0x02	; CV8	Manufacturer ID
E_CV17		equ	EE_INI+0x03	; CV17
E_CV18		equ	EE_INI+0x04	; CV18
E_CV19		equ	EE_INI+0x05	; CV19
E_CV29		equ	EE_INI+0x06	; CV29
E_CV33		equ	EE_INI+0x07	; CV33
E_CV34		equ	EE_INI+0x08	; CV34
E_CV35		equ	EE_INI+0x09	; CV35
E_CV36		equ	EE_INI+0x0A	; CV36
E_CV37		equ	EE_INI+0x0B	; CV37
E_CV38		equ	EE_INI+0x0C	; CV38
E_CV49		equ	EE_INI+0x0D	; CV49
E_CV50		equ	EE_INI+0x0E	; CV50
E_CV51		equ	EE_INI+0x0F	; CV51
E_CV52		equ	EE_INI+0x10	; CV52
E_CV53		equ	EE_INI+0x11	; CV53
E_CV54		equ	EE_INI+0x12	; CV54
E_CV55		equ	EE_INI+0x13	; CV55
E_CV56		equ	EE_INI+0x14	; CV56
E_CV57		equ	EE_INI+0x15	; CV57


; ----- Variables

; --- Internal RAM Section

; --- Top on all banks

INT_W		equ	RAMINT+0x00	; Interrupt variables. not used
INT_STAT	equ	RAMINT+0x01

EEDATA0		equ	RAMINT+0x0B	; EEPROM shadow variables
EEADR0		equ	RAMINT+0x0C

; --- Bank 0

CV1		EQU	RAMINI0+0x00	; Primary Adress
CV7		equ	RAMINI0+0x01	; Manufacturer version
CV8		equ	RAMINI0+0x02	; Manufacturer ID
CV17		EQU	RAMINI0+0x03	; Extended Adress High Byte
CV18		EQU	RAMINI0+0x04	; Extended Adress Low Byte
CV19		EQU	RAMINI0+0x05	; Consist Adress
CV29		EQU	RAMINI0+0x06	; 0=DIR 1=14/28 2=PWRSRC 3=ADVACK 4=SPDTAB 5=LADRE 6= 7=ACCDEC
					; CV29 bit definition
#DEFINE		DIRINV		0	; direction inverted (+light)
#DEFINE		FS28		1	; 14/28 speed step
#DEFINE		LADRE		5	; long adress enable

CV33		EQU	RAMINI0+0x07	; front light -> xxxxSNBF: Sound, Noise, backlight, frontlight
CV34		EQU	RAMINI0+0x08	; back light  -> xxxxSNBF: Sound, Noise, backlight, frontlight
CV35		EQU	RAMINI0+0x09	; F1 -> xxxxSNBF: Sound, Noise, backlight, frontlight
CV36		EQU	RAMINI0+0x0A	; F2 -> xxxxSNBF: Sound, Noise, backlight, frontlight
CV37		EQU	RAMINI0+0x0B	; F3 -> xxxxSNBF: Sound, Noise, backlight, frontlight
CV38		EQU	RAMINI0+0x0C	; F4 -> xxxxSNBF: Sound, Noise, backlight, frontlight
					; CV33..CV38 bit definition
#define		FL_SEL		0
#define		BL_SEL		1
#define		NOISE_SEL	2	; 
#define		SOUND_SEL	3	; 
					; Manufacturer unique CV49-CV64. Sound parameters
CV49		equ	RAMINI0+0x0D	; Sound frequency (62500Hz / CV49)
CV50		equ	RAMINI0+0x0E	; Noise base freq (15625Hz / CV50)
CV51		equ	RAMINI0+0x0F	; Envelope for sound (0..31)
CV52		equ	RAMINI0+0x10	; Envelope for noise (0..31)
CV53		equ	RAMINI0+0x11	; Envelope duration sound (12.8ms...8.3s)
CV54		equ	RAMINI0+0x12	; Envelope duration noise (12.8ms...8.3s)
CV55		equ	RAMINI0+0x13	; Sound Speed delta
CV56		equ	RAMINI0+0x14	; Noise Speed delta
CV57		equ	RAMINI0+0x15	; Sound Config: (2:mix,3:Vol,4:Duty)
					; CV57 bit definition
#define		MIX		0	; Mix sound and noise
#define		VOL_LEVEL	1	; Volume Level
#define		SND_DUTY	2	; Sound duty cycle

F1F4SET		EQU	RAMINI0+0x21	; 
F1F4OLD		EQU	RAMINI0+0x22	; 
ENABLE		equ	RAMINI0+0x23	; enable sound flags
SPEED		equ	RAMINI0+0x24	; current speed
FLAGS		equ	RAMINI0+0x25	; flags

BT1		EQU	RAMINI0+0x2A	; DCC data received
BT2		EQU	RAMINI0+0x2B	;
BT3		EQU	RAMINI0+0x2C	;
BT4		EQU	RAMINI0+0x2D	;
BT5		EQU	RAMINI0+0x2E	;
BT6		EQU	RAMINI0+0x2F	; 

CONFIG		EQU	RAMINI0+0x30	; 0=DIR 1=CONSIST 2=STEPOK/NOCV 5=FS126 6=BITHI
NOADR		EQU	RAMINI0+0x31	; no adress since ...(for IB with M*)
PAGEREG		EQU	RAMINI0+0x32	; Page register

EnvVol		equ	RAMINI0+0x33	; Envelope current volume
EnvPage		equ	RAMINI0+0x34	; Envelope page table
EnvStep		equ	RAMINI0+0x35	; Envelope current step
EnvDur		equ	RAMINI0+0x36	; Envelope period
EnvSpeed	equ	RAMINI0+0x37	; Envelope speed divider
EnvDurStop	equ	RAMINI0+0x38	; Envelope period when stopped
EnvDelta	equ	RAMINI0+0x39	; Envelope delta select

NOISE0		equ	RAMINI0+0x3A	; noise generator
NOISE1		equ	RAMINI0+0x3B
NOISE2		equ	RAMINI0+0x3C
NOISE3		equ	RAMINI0+0x3D
TEMP		equ	RAMINI0+0x3E
COUNT		equ	RAMINI0+0x3F

PRE		EQU	RAMINI0+0x4D	; Preample 12 BIT
LO		EQU	RAMINI0+0x4E	; low bit counter
HI		EQU	RAMINI0+0x4F	; hi bit counter


;--------------------

#DEFINE 	DIR		CONFIG,0	;
#DEFINE		CONSIST		CONFIG,1	;
#DEFINE		STEPOK?		CONFIG,2	;
#DEFINE		LASTLT		CONFIG,3	;
#DEFINE		NOCV		CONFIG,2	; is mapped with STEPOK?
#DEFINE		ROMCV		CONFIG,3	; is mapped with LASTLT

#DEFINE		BITHI		CONFIG,6	;


#define 	FSET		FLAGS,0		; set function
#define		NOISE_ON	FLAGS,1		; noise on
#define		NXT_ENV		FLAGS,2		; load next envelope value

#DEFINE		ACKBIT		FLAGS,5		; 2x acknowledge
#DEFINE		PROGBIT		FLAGS,6		; 2x prog
#DEFINE		PROGBT1		FLAGS,7		; 3x prog

; --------------- Program Section --------------------------------------


		org	0x000

PowerUp:
		clrf	INTCON			; Disable all interrupts
		clrf	PCLATH			; Tables on page 0
		clrf	CONFIG			; reset flags
		goto	INIT


		org	0x004

Interrupt:
		goto	PowerUp			; not used so initialize

; ----- Tables on first 256 bytes

BITPOS:
		clrf	PCLATH
		addwf PCL,f
		retlw	b'00000001'	; 0	
		retlw	b'00000010'	; 1	
		retlw	b'00000100'	; 2	
		retlw	b'00001000'	; 3	
		retlw	b'00010000'	; 4	
		retlw	b'00100000'	; 5	
		retlw	b'01000000'	; 6	
		retlw	b'10000000'	; 7	

; ----- Low Level Hardware access routines

; --- Internal EEPROM routines

EERead:
		movwf	EEADR0		
		SEL_BANK_1
		movwf	EEADR			; Read EEPROM, w = ADR
		bsf	EECON1,RD
        	movf    EEDATA,w
		bcf	STATUS,RP0		; Bank 0
		movwf	EEDATA0
		return				; w = DATA

SetParm:                   
		movwf	EEADR0			; Write EEPROM, w = ADR, EEDATA0 = DATA
		SEL_BANK_1
		movwf	EEADR			; Read EEPROM, w = ADR
		bsf	EECON1,RD
        	movf    EEDATA,w
		bcf	STATUS,RP0		; Bank 0
		xorwf	EEDATA0,w
		btfsc	STATUS,Z                       
		return
EEWrite:
		SEL_BANK_1
		movf	EEADR0,w
		movwf	EEADR
		movf	EEDATA0,w
		movwf	EEDATA
		bsf	EECON1,WREN		; Enable writting EEPROM
;EEWr0:
;		bcf	INTCON,GIE		; Clear interrupts
;		btfsc	INTCON,GIE
;		goto	EEWr0
		movlw	0x55
		movwf	EECON2
		movlw	0xAA
		movwf	EECON2
		bsf	EECON1,WR
EEWr1:
		btfsc	EECON1,WR		; wait until write complete
		goto	EEWr1
		bcf	EECON1,WREN		; Disable writting EEPROM
;		bsf	INTCON,GIE		; Set interrupts
		bcf	STATUS,RP0		; bank 0
		return

; ----- Initialization

INIT:
		movlw   RA_INI			; Set ports
		movwf   PORTA                         
		movlw   RB_INI
		movwf   PORTB
		SEL_BANK_1
		clrf	PIE1			; no peripheral interrupts
		movlw	RB_TRIS
		movwf   TRISB
		movlw   RA_TRIS         	; Set port A I/O configuration
		movwf   TRISA
		movlw   OPTION_INI      	; PORTB pull-ups disabled, Timer configuration
		movwf   OPTION_REG
		movlw	0x0B			; internal oscillator to 4MHz
		movwf	PCON
		movlw	0xCF			; VRR on, Vref on RA2, high volume
		movwf	VRCON
		SEL_BANK_0
		movlw	0x06			; Two comparators, two outputs
		movwf	CMCON                          


		movlw	0x31			; Timer 1. Run, set 1:8 Prescaler
		movwf	T1CON
		movlw	0x06			; Timer 2. Run with 1:16 Prescaler
		movwf	T2CON
		bsf	NOISE0,0		; to be sure noise shift reg. isn't zero


		movlw	PIE1
		movwf	FSR
		movlw	PIE1_INI		; Set interrupt (none)
		movwf	INDF
		movlw	INTC_INI		; Set interrupts (none)
		movwf	INTCON

		clrf	PAGEREG

CLEAR:
		BCF	ACKBIT			; set all register to start condition
		CLRF	LO			;
		CLRF	HI
		CLRF	NOADR
		BCF	LASTLT

		clrf	F1F4SET			; outputs off
		clrf	F1F4OLD
		clrf	FLAGS			; noise off
		clrf	CCP1CON			; sound off
		bcf	FL_LED			; light off
		bcf	BL_LED
		movlw	HIGH(FixedVol0)		; volume off
		movwf	EnvPage
		movlw	LOW (FixedVol0)
		movwf	EnvStep
		movlw	0xE0
		movwf	EnvVol
		clrf	EnvSpeed
		clrf	EnvDur
		clrf	EnvDurStop
		clrf	SPEED
		bcf	NXT_ENV


BEGIN:
	
						; here when >10000us


LOADREG:
		movlw	CV1		; first CV to read
		movwf	FSR
		movlw	E_CV1
		movwf	EEADR0
LOADNEXT:
		movf	EEADR0,w
		call	EERead
		movwf	INDF
		movlw	CV57		; last CV to read
		xorwf	FSR,w
		btfsc	STATUS,Z
		goto	START
		incf	FSR,f
		incf	EEADR0,f
		goto	LOADNEXT


; ------ DCC Section

START:
	nop			;				12
	MOVLW	0xFF		;				13 clear receive regs
	MOVWF	BT4		;				14
	MOVWF	BT5		;				15
	MOVWF	BT6		;				16

	MOVLW	BT1 - d'1'	; Pointer for ind. Adressing	17
	MOVWF	FSR		; (BT1 - 1)			18
	MOVLW	d'11'		;				19
	MOVWF	PRE		; PRE to 10 Bit for Preample	20
;-------------
INTEST:
	CLRF	HI		; clear HI counter		20
INTST:
	BCF	STEPOK?		;				21
	NOP			;				22
	CALL	IN		;				23-24
	BTFSC	STEPOK?		;				4.
	GOTO	STEPOK		;				5.-6
	CALL	STEP		;				6.-7.
	BTFSC	DCCIN		; ########### input ##########	1  (25)
	BSF	BITHI		;				2

	GOTO	$+1		;				3-4
	GOTO	$+1		;				5-6

STEPOK:
	MOVLW	b'11111100'	; FF-03				7
	MOVF	HI,f		;				8
	BTFSC	STATUS,Z	; 0? 				9
	GOTO	LOWBIT		; low half of bit		10-11
	ADDWF	HI,w		; BIT im Carry			11
	DECFSZ	PRE,f		; Pre=0?			12
	GOTO	PRETEST		;				13-14
	BTFSC	STATUS,C	; waiting for 0			14
	GOTO	BYTE		; Preample ok!			15-16
	INCF	PRE,f		;				16
	NOP			;				17
	GOTO	INTEST		; next Bit			18-19

PRETEST:
	DECFSZ	HI,w		; HI=1?				15
	BTFSC	STATUS,C	;				16
	GOTO	START19		; no Preample!			17-18
	GOTO	INTEST		;				18-19

LOWBIT:
	NOP			;				12
	GOTO	$+1		;				13-14
	BTFSC	BITHI		;				15
	INCF	HI,f		;				16
	BCF	BITHI		;				17
	INCFSZ	LO,f		;				18
	GOTO	INTST		;				19-20
	GOTO	BEGIN		; >10000uS			20-21

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IN:
	BTFSS	DCCIN		; ########### input ##########	1  (25)
	RETLW	0		; 				2.-3.
	INCF	HI,f		;				3.
	CLRF	LO		;				4.
	BSF	STEPOK?		;				5.
	CALL	STEP		;				6.-7.
	BTFSS	DCCIN		; ########### input ##########	1  (25)
	RETLW	0		; FF-03				2-3
	INCF	HI,f		;				3


		btfsc	PIR1,TMR1IF			;4
		goto 	PutVol				;5,6
		btfss	NXT_ENV				;6
		goto	PutStep				;7,8
		incf	EnvStep,f			;8
		call	EnvValue			;9,10
		movwf	EnvStep				;18
		bcf	NXT_ENV				;19
		nop					;20
IN_ENV:

	BCF	STEPOK?		;				21
	INCFSZ	HI,w		;				22
	GOTO	IN		;				23-24
	GOTO	BEGIN		; >10000uS			24


PutVol:
		bcf	PIR1,TMR1IF			;7
		movf	EnvSpeed,w			;8 set timer
		movwf	TMR1L				;9
		movf	EnvDur,w				;10
		movwf	TMR1H				;11
		bsf	NXT_ENV				;12
		movf	EnvVol,w			;13 set volume
		btfsc	CV57,VOL_LEVEL			;14
		andlw	0xDF				;15
		bsf	STATUS,RP0			;16 bank 1
		movwf	VRCON				;17 
		bcf	STATUS,RP0			;18 bank 0
		goto	IN_ENV				;19,20

PutStep:
		call	EnvValue			;9,10
		movwf	EnvVol				;18
		goto	IN_ENV				;19,20

EnvValue:
		movf	EnvPage,w			;10
		movwf	PCLATH				;11
		movf	EnvStep,w			;12
		movwf	PCL				;13,14

;--------------------------------
NEXT:
	NOP			;				15
	RLF	INDF,f		; 1.Byte zusammenbauen		16
	DECFSZ	HI,w		; HI=1?				17
	GOTO	INTEST1		; next bit			18-19
	GOTO	START21		;				19-20
;.....................................................................

STEP:
		btfss	INTCON,T0IF	; noise generator		8
		goto	STEP2		;				9,10
		nop			;				10
		bcf	INTCON,T0IF	;				11
		movf	CV50,w		; CV noise freq			12
		sublw	0x00		; 256 - CV49			13
		movwf	TMR0		;				14
		swapf	NOISE0,w	;				15
		xorwf	NOISE1,w	;				16
		movwf	TEMP		;				17
		rrf	TEMP,w		;				18
		rlf	NOISE3,f	;				19
		rlf	NOISE2,f	;				20
		rlf	NOISE1,f	;				21
		rlf	NOISE0,f	;				22
		retlw	0		;				23,24
STEP2:
		nop			;				11
		btfss	NOISE_ON	;				12
		goto	STEP3		;				13,14
		btfss	NOISE0,7	;				14
		bcf	CMCON,C2INV	;				15
		btfsc	NOISE0,7	;				16
		bsf	CMCON,C2INV	;				17
		DNOP			;				18,19
		DNOP			;				20,21
		nop			;				22
		retlw	0		;				23,24.
STEP3:
		DNOP			;				15,16
		DNOP			;				17,18
		DNOP			;				19,20
		DNOP			;				21,22
		retlw	0		;				23,24.


	

;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

LOWBIT1:
	MOVLW	BT6 + d'1'	; -----------------------------	12
	SUBWF	FSR,w		;				13
	ANDLW	b'00000111'	; more than 6 BYTE read		14
	BTFSC	STATUS,Z	; begin new!			15
	GOTO	START18		; -----------------------------	16-17
	BTFSC	BITHI		;				17
	INCF	HI,f		;				18
	GOTO	INTST1		;				19-20

BYTE:
	MOVLW	d'9'		; PRE to 8 Bit for 1.Byte	17
	MOVWF	PRE		;				18
	INCF	FSR,f		; Pointer for ind. Adressing	19

INTEST1:
	CLRF	HI		;				20
INTST1:
	BCF	STEPOK?		;				21
	BCF	BITHI		;				22
	CALL	IN		;				23-24
	BTFSC	STEPOK?		;				4.
	GOTO	STEPOK1		;				5.-6
	CALL	STEP		;				6.-7.
	BTFSC	DCCIN		; ########### input ##########	1  (25)
	BSF	BITHI		;				2

	NOP			;				3
	NOP			;				4
	NOP			;				5
	NOP			;				6

STEPOK1:
	MOVLW	b'11111100'	; FF-03				7
	MOVF	HI,f		;				8
	BTFSC	STATUS,Z	; 0? 				9
	GOTO	LOWBIT1		; low half of bit		10-11
	ADDWF	HI,w		; BIT im Carry			11
	DECFSZ	PRE,f		; Pre=0?			12
	GOTO	NEXT		;				13-14
	BTFSC	STATUS,C	;				14
	GOTO	BYTE		; 9.Bit=0			15-16

;------------- last BIT=1 -------------
	
	CLRF	NOADR		; for IB with M*		16
	MOVF	BT1,w		;				17
	XORWF	BT2,w		;				18
	XORWF	BT3,w		;				19
	XORWF	BT4,w		;				20
	XORWF	BT5,w		;				21
	XORWF	BT6,w		;				22
	BTFSS	STATUS,Z	; all Bytes ok?			23
	GOTO	START2.		;				24-1.
	COMF	BT1,f		; 9.Bit=1  (inverting BYTE)	1.
	COMF	BT2,f		; 	   (inverting BYTE)	2.
	COMF	BT3,f		; 	   (inverting BYTE)	3.
	COMF	BT4,f		; 	   (inverting BYTE)	4.
	COMF	BT5,f		; 	   (inverting BYTE)	5.
	CALL	STEP		;				6.-7.

	DECF	FSR,f		; last Byte			1

	nop			;				2
	nop			; set port GPIO			3

;....................................................................


;....................................................................
CV:	nop			; rampage to 0x30..		4
	MOVF	BT1,w		;				5
	BTFSS	BT1,7		; >0<AAA AAAA			6
	GOTO	SHORTA		; short adress			7-8
	XORWF	CV17,w		; long address high		8
	BTFSS	STATUS,Z	;				9
	GOTO	CHKPROG		;				10-11
	MOVF	BT2,w		;				11
	XORWF	CV18,w		; long address low		12
	BTFSS	STATUS,Z	;				13
	GOTO	CHKPROG		;				14
	MOVLW	BT3		; BT3				15
	MOVWF	FSR		; to 3. byte			16
	BTFSS	CV29,LADRE	; long adress enabled?		17
	GOTO	CHKPROG		;				18
	BTFSC	CONSIST		;				19
	GOTO	CHKPROG		;				20
	NOP			;				21
	nop			;				22
	GOTO	DECOD		;				23-24
;--------------------------------
BCAST:
	GOTO	$+1		;				12-13
	GOTO	$+1		;				14-15
	GOTO	OVER1		;				16-17

OVER:
	BTFSC	CONSIST		;				16
	GOTO	START		;				17
OVER1:
	NOP			;				18
	GOTO	BCBCK		;				19-20
;--------------------------------
CHKPROG:
	MOVF	BT1,w		;
	ANDLW	b'11110000'	; untere 3bit ausblenden
	XORLW	b'01110000'	; >= 120 (120=CV1 121=CV2 ...)
	BTFSS	STATUS,Z	;
	GOTO	START		;
	GOTO	PROG		; register mode (CV1-CV8)
;--------------------------------
SHORTA:
	BTFSC	STATUS,Z	; address = 0?			9
	GOTO	BCAST		;				10-11
	BTFSS	CV29,LADRE	; long Adress enabled?		11
	XORWF	CV1,w		;				12
	BTFSC	STATUS,Z	;				13
	GOTO	OVER		;				14-15
	MOVF	CV19,w		; consist			15
	ANDLW	b'01111111'	;				16
	BCF	CONSIST		;				17
	BTFSS	STATUS,Z	;				18
	BSF	CONSIST		;				19
	XORWF	BT1,w		; consist?			20
BCBCK:
	BTFSS	STATUS,Z	;				21
	GOTO	CHKPROG		;				22-23
	MOVLW	BT2		; BT2				23
	MOVWF	FSR		; to 2. byte			24
	nop			;				25
	GOTO	DECOD		;				26-27

;--------------------------------------------------------------------
START1.	NOP			;				1.
START2.	NOP			;				2.
START3.	NOP			;				3.
START4.	NOP			;				4.
START5.	NOP			;				5.
START6.	CALL	STEP		;				6.-7.
START1	NOP			;				1
START2	NOP			;				2
START3	NOP			;				3
START4	NOP			;				4
START5	NOP			;				5
START6	NOP			;				6
START7	NOP			;				7
START8	NOP			;				8
START9	NOP			;				9
START10	GOTO	START		;				10-11
START11	NOP			;				11
START12	NOP			;				12
START13	NOP			;				13
START14	NOP			;				14
START15	NOP			;				15
START16	NOP			;				16
START17	NOP			;				17
START18	NOP			;				18
START19	INCF	NOADR,f		; for IB with M*		19
START20	BTFSS	NOADR,7		; counts if no			20
START21	GOTO	START23		; DCC signal is 		21
	GOTO	CLEAR		; readable			22   **** change
START23	GOTO	START1.		;				23-24


;.....................................................................
;.....................................................................
;.....................................................................


DECOD:
	movlw	HIGH(DECOD)	; FSR = BT2 short / BT3 long	1
	movwf	PCLATH		;				2
	SWAPF	INDF,w		;				3
	MOVWF	BT6		;				4
	RRF	BT6,w		;				5
	ANDLW	b'00000111'	;				6
	ADDWF	PCL,f		;				7,8

	GOTO	DECCON		; 000				9,10
	GOTO	ADVAN		; 001
	GOTO	REVERSE		; 010
	GOTO	FORWARD		; 011
	GOTO	FTION		; 100
	GOTO	FTION1		; 101
	GOTO	TELNEW		; 110
				; 111
	MOVF	BT2,w		;--------------------------------
	XORLW	b'11111001'	; old acknowledge mode
	BTFSC	STATUS,Z	;
	GOTO	OLDACK		;--------------------------------

	MOVF	INDF,w		; OTM mode -copy bytes
	MOVWF	BT1		; 
	INCF	FSR,f		; 
	MOVF	INDF,w		; CV to pogram
	MOVWF	BT2		;
	INCF	FSR,f		; DATA for cv
	MOVF	INDF,w		; INDF looks to data
	MOVWF	BT3		;
	GOTO	PROGOTM		;

FTION1:
TELNEW:
		goto	HOPP

;.....................................................................

DECCON:
	BTFSC	INDF,4		; 000>0<CCCD
	GOTO	CONCON		; 0001 consist control
	movf	BT1,w		; '000 0 000 0' Decoder reset?
	iorwf	BT2,w
	iorwf	BT3,w
	btfsc	STATUS,Z
	goto	CLEAR
	GOTO	HOPP		;

CONCON:
	clrf	EEDATA0		;
	MOVF	INDF,w		;000>1<CCCC
	XORLW	b'00010010'	; normal direction?
	BTFSC	STATUS,Z	;
	BCF	EEDATA0,7		;
	XORLW	(b'00010010')^(b'00010011'); reverse direction?
	BTFSC	STATUS,Z	;
	BSF	EEDATA0,7		;
	incf	FSR,f
	movf	INDF,w
	andlw	0x7F
	iorwf	EEDATA0,f
	movlw	E_CV19		;
	movwf	EEADR0
	GOTO	EEIN		;

;-------------------------------

ADVAN:
		MOVF	INDF,w		;
		XORLW	b'00111111'	; 128 steps
		BTFSS	STATUS,Z	;
		GOTO	HOPP		; reserved for future use

		INCF	FSR,f		; speed & dir
		movlw	0x80
		btfsc	CV29,DIRINV		; CV29,0
		xorwf	INDF,f
		bcf	DIR
		btfsc	INDF,7
		bsf	DIR
		clrf	EnvSpeed

		movf	INDF,w			; get speed 128
		andlw	0x7F
		xorlw	0x01
		btfss	STATUS,Z		; check emergency stop
		xorlw	0x01
		movwf	TEMP			; 0..64
		rrf	TEMP,w
		andlw	0x3F
CHG_PERIOD:
		movwf	TEMP
		xorwf	SPEED,w			; equal last speed?
		btfsc	STATUS,Z
		goto	HOPP			; yes, nothing to do

		movf	EnvDelta,w		;
		btfsc	STATUS,Z		; delta >0 ?
		goto	HOPP
		movwf	EnvDur			; 
		movf	TEMP,w			; yes, calc new envelope period
		movwf	SPEED
		movwf	EnvSpeed		; do SPEED * CV56
		call	MULTIP
		movf	EnvDurStop,w		; EnvDur = EnvDurStop + (SPEED * CV56)
		addwf	EnvDur,f
		goto	HOPP

;--------------------- multiply MULT1 * MULT2 = hi MULT1 low MULT2 --
;--------------------- multiply EnvDur * EnvSpeed = hi EnvDur low EnvSpeed --

MULTIP:
	MOVLW	d'9'		;			1			
	MOVWF	COUNT		;			2
	CLRW			;			3
	BCF	STATUS,C	;			4
MULTI:
	MOVWF	TEMP		;			1	
	RRF	TEMP,w		;			2	
	RRF	EnvSpeed,f	;			3	
	BTFSC	STATUS,C	;			4	
	ADDWF	EnvDur,w	;			5	
	DECFSZ	COUNT,f		;			6	
	GOTO	MULTI		;			7-8	
	MOVWF	EnvDur		;			9*8=72		76
	RETLW	0		;	END MULTIP	77-78

;-------------------------------
FORWARD:
		btfsc	CV29,DIRINV		; forward 14/28 steps
		goto	REVERSE1
FORWARD1:
		bsf	DIR
		goto	SET_SPEED


REVERSE:
		btfsc	CV29,DIRINV
		goto	FORWARD1
REVERSE1:
		bcf	DIR

SET_SPEED:
		btfss	CV29,FS28
		goto	SET_14STEP
SET28_STEP:
		bcf	STATUS,C		; 01DH SSSS
		rlf	INDF,w			; 1DHS SSS0
		btfsc	INDF,4			; 1DHS SSSH
		iorlw	0x01
		andlw	0x1F			
		movwf	TEMP			; check stops
		sublw	0x03
		btfsc	STATUS,C
		clrf	TEMP
		rlf	TEMP,w			; DHSSSSH0  (0..64)
		andlw	0x3E
		goto	CHG_PERIOD


SET_14STEP:
						; light control

		movf	INDF,w
		andlw	0x0F			; check emergency stop
		xorlw	0x01
		btfss	STATUS,Z
		xorlw	0x01
		movwf	TEMP
		rlf	TEMP,f			; 0..64
		rlf	TEMP,w
		andlw	0x3C
		goto	CHG_PERIOD


;-------------------------------

FTION:
		movf	INDF,w		; 100LFFFF
		movwf	BT5
		clrf	F1F4SET

F0_CHG:
;		btfss	CV29,FS28	; FL on function 1?
;		goto	F1_CHG
		movlw	CV33
		btfss	DIR
		movlw	CV34
		btfsc	BT5,4
		call	FTION_SET
F1_CHG:
		movlw	CV35		; set function acording CV33..CV38
		btfsc	BT5,0
		call	FTION_SET
F2_CHG:
		movlw	CV36
		btfsc	BT5,1
		call	FTION_SET
F3_CHG:
		movlw	CV37
		btfsc	BT5,2
		call	FTION_SET
F4_CHG:
		movlw	CV38
		btfsc	BT5,3
		call	FTION_SET


		movf	F1F4SET,w		; only changes
		xorwf	F1F4OLD,w
		btfsc	STATUS,Z
		goto	HOPP

		movwf	BT6
		clrf	TEMP			; FixedVol0 default
		clrf	EnvDur			; long dur default
		clrf	EnvDurStop
NOISE_CHG:
		btfss	BT6,NOISE_SEL		; change on noise
		goto	SOUND_CHG
		btfss	F1F4SET,NOISE_SEL
		goto	NOISE_OFF
		bsf	NOISE_ON
		movf	CV54,w
		sublw	0x00
		movwf	EnvDur
		movwf	EnvDurStop
		movf	CV52,w
		movwf	TEMP
		movf	CV56,w
		movwf	EnvDelta
		btfsc	CV57,MIX		; mix noise and sound?
		goto	SOUND_CHG		; yes
		clrf	CCP1CON			; no, sound off
		goto	ENVELOPE_CHG
NOISE_OFF:
		bcf	NOISE_ON
		btfss	CV57,MIX
		goto	SOUND_SET
		
SOUND_CHG:
		btfss	BT6,SOUND_SEL		; change on sound
		goto	ENVELOPE_CHG
SOUND_SET:
		btfss	F1F4SET,SOUND_SEL
		goto	SOUND_OFF
		movf	CV49,w			; sound frequency
		bsf	STATUS,RP0		; bank 1
		movwf	PR2
		bcf	STATUS,RP0		; bank 0
		rrf	CV49,w
		movwf	CCPR1L
		movlw	0x2C			; 75% duty cycle
		btfss	CV57,SND_DUTY
		movlw	0x0C			; 50% duty cycle
		movwf	CCP1CON			; start PWM
		movf	CV53,w
		sublw	0x00
		movwf	EnvDur
		movwf	EnvDurStop
		movf	CV51,w			; sound envelope
		movwf	TEMP
		MOVF	CV55,w
		movwf	EnvDelta
		btfss	CV57,MIX		; mix noise and sound?
		bcf	NOISE_ON		; no, noise off
		goto	ENVELOPE_CHG
SOUND_OFF:
		clrf	CCP1CON			; sound off
		btfsc	F1F4SET,NOISE_SEL	; noise active?
		bsf	NOISE_ON

ENVELOPE_CHG:
		movf	EnvDur,w		; any envelope active?
		btfss	STATUS,Z
		goto	ENVELOPE_SEL
		btfsc	F1F4SET,NOISE_SEL
		movf	CV54,w
		btfsc	F1F4SET,SOUND_SEL
		movf	CV53,w
		sublw	0x00
		movwf	EnvDur
		movwf	EnvDurStop
		movlw	0x00			; envelope selection default
		btfsc	F1F4SET,NOISE_SEL
		movf	CV52,w
		btfsc	F1F4SET,SOUND_SEL
		movf	CV51,w
		movwf	TEMP
		btfsc	F1F4SET,NOISE_SEL
		movf	CV56,w
		btfsc	F1F4SET,SOUND_SEL
		movf	CV55,w
		movwf	EnvDelta

ENVELOPE_SEL:
		movlw	HIGH (GetEnv)		; load envelope 
		movwf	PCLATH
		bcf	STATUS,C		; w * 2
		rlf	TEMP,f
		movf	TEMP,w
		call	GetEnv
		movwf	EnvPage			; PCLATH
		incf	TEMP,w	
		call	GetEnv
		movwf	EnvStep			; PCL

		call	EnvValue		; Set initial volume
		movwf	EnvVol
		btfsc	CV57,VOL_LEVEL
		andlw	0xDF
		bsf	STATUS,RP0
		movwf	VRCON
		bcf	STATUS,RP0

		clrf	EnvSpeed		; Calculate envelope period 
		movf	EnvDelta,w
		btfsc	STATUS,Z		; dependent of speed?
		goto	ENVELOPE_SET		; no
		movwf	EnvDur
		movf	SPEED,w			; yes
		movwf	EnvSpeed		; do SPEED * CV56
		call	MULTIP
		movf	EnvDurStop,w		; EnvDur.EnvSpeed = EnvDurStop + (SPEED * CV56)
		addwf	EnvDur,f

ENVELOPE_SET:
		movf	EnvSpeed,w
		movwf	TMR1L
		movf	EnvDur,w
		movwf	TMR1H
		bcf	PIR1,TMR1IF
		bcf	NXT_ENV

FL_CHG:
		btfss	F1F4SET,FL_SEL		; set lights
		bcf	FL_LED
		btfsc	F1F4SET,FL_SEL
		bsf	FL_LED
		btfss	F1F4SET,BL_SEL
		bcf	BL_LED
		btfsc	F1F4SET,BL_SEL
		bsf	BL_LED


FTION_END:
		movf	F1F4SET,w
		movwf	F1F4OLD
		goto	HOPP


FTION_SET:
		movwf	FSR
		movf	INDF,w		; get CV value to set
		iorwf	F1F4SET,f
		retlw	0



; ----------------------------------------------------

HOPP:
		BCF	PROGBIT		; equal instrucions flags for programming
		BCF	PROGBT1		;
		BCF	ACKBIT		;
PROGEX:
		clrf	PCLATH
		GOTO	START		;

;----------------------------------------

FINDCV:
		BCF	NOCV		;
		BCF	ROMCV		;

		XORLW	0x00		; CV1
		BTFSC	STATUS,Z	;
		RETLW	E_CV1		; Manufacturer version
		XORLW	0x00 ^0x10	; CV17
		BTFSC	STATUS,Z	;
		RETLW	E_CV17		; Extended Adress Low Byte
		XORLW	0x10^0x11	; CV18
		BTFSC	STATUS,Z	;
		RETLW	E_CV18		; Extended Adress High Byte
		XORLW	0x11^0x12	; CV19
		BTFSC	STATUS,Z	;
		RETLW	E_CV19		; Consist Adress
		XORLW	0x12^0x1C	; CV29
		BTFSC	STATUS,Z	;
		RETLW	E_CV29		; 0=DIR 1=14/28 2=PWSRC 3=ADVACK 4=SPEEDTAB 5=LADRE 6= 7=ACCDEC
;-----------------------------
		XORLW	0x1C^0x20	; CV33
		BTFSC	STATUS,Z	;
		RETLW	E_CV33		; front light
		XORLW	0x20^0x21	; CV34
		BTFSC	STATUS,Z	;
		RETLW	E_CV34		; back light
		XORLW	0x21^0x22	; CV35
		BTFSC	STATUS,Z	;
		RETLW	E_CV35		; F1 
		XORLW	0x22^0x23	; CV36
		BTFSC	STATUS,Z	;
		RETLW	E_CV36		; F2 
		XORLW	0x23^0x24	; CV37
		BTFSC	STATUS,Z	;
		RETLW	E_CV37		; F3 
		XORLW	0x24^0x25	; CV38
		BTFSC	STATUS,Z	;
		RETLW	E_CV38		; F4 
;-----------------------------
		XORLW	0x25^0x30	; CV49
		BTFSC	STATUS,Z	;
		RETLW	E_CV49		; Sound freq
		XORLW	0x30^0x31	; CV50
		BTFSC	STATUS,Z	;
		RETLW	E_CV50		; Noise freq
		XORLW	0x31^0x32	; CV51
		BTFSC	STATUS,Z	;
		RETLW	E_CV51		; Envelope selection sound
		XORLW	0x32^0x33	; CV52
		BTFSC	STATUS,Z	;
		RETLW	E_CV52		; Envelope selection noise
		XORLW	0x33^0x34	; CV53
		BTFSC	STATUS,Z	;
		RETLW	E_CV53		; Envelope duration sound
		XORLW	0x34^0x35	; CV54
		BTFSC	STATUS,Z	;
		RETLW	E_CV54		; Envelope duration noise
		XORLW	0x35^0x36	; CV55
		BTFSC	STATUS,Z	;
		RETLW	E_CV55		; Sound Speed delta
		XORLW	0x36^0x37	; CV56
		BTFSC	STATUS,Z	;
		RETLW	E_CV56		; Noise Speed delta
		XORLW	0x37^0x38	; CV57
		BTFSC	STATUS,Z	;
		RETLW	E_CV57		; Sound control

;-----------------------------
		BSF	ROMCV		;
		XORLW	0x37^0x06	; CV7
		BTFSC	STATUS,Z	;
		RETLW	E_CV7		; Version No
		XORLW	0x06^0x07	; CV8
		BTFSC	STATUS,Z	;
		RETLW	E_CV8		; Manufacturer

		BCF	ROMCV		;
		BSF	NOCV		;
		RETLW	0x7F		; no CV's to program

;-----------------------------

PROG:
	MOVF	FSR,w		; FSR points to last data byte
	XORLW	BT3		; points to BT3?
	BTFSS	STATUS,Z	;
	GOTO	PROGREG		; 3 byte command

PROGOTM:			; Direct mode
	MOVF	BT2,w		; CV address low
	CALL	FINDCV		; w = CV location
	BTFSC	NOCV		;
	GOTO	HOPP		;

	BTFSC	ROMCV		; read only?
	BTFSS	BT1,3		; yes, write/verify bit
	GOTO	ROMNEXT		; verify
	btfsc	BT1,2		; write /bit
	goto	HOPP		; write not permited

ROMNEXT:
	BTFSS	BT1,2		;
	GOTO	BITMAN		; bit manipulation

	BTFSS	BT1,3		; write/verify bit
	GOTO	EEVERI		;

EEPROG:
	MOVWF	EEADR0		; write CV
	MOVF	INDF,w		; 
	MOVWF	EEDATA0		;
	clrf	CONFIG

	BTFSC	PROGBIT		;
	GOTO	EEIN		;
	BSF	PROGBIT		; 2x prog
	GOTO	PROGEX		;

PROG3:
	BTFSC	PROGBT1		;
	GOTO	EEIN		;
	BSF	PROGBT1		; 3x prog
	GOTO	PROGEX		;

EEIN:
	movf	EEADR0,w
	CALL	SetParm		; program EEPROM
	call	AckPulse

	CLRF	CONFIG
	BCF	PROGBIT		;
	BCF	PROGBT1		;
	GOTO	CLEAR		; **** change

;-------------------------------

PROGREG:
	MOVF	BT1,w		; CV5=CV29
	ANDLW	b'11110111'
	XORLW	b'01110101'	; reg6
	BTFSC	STATUS,Z	;
	GOTO	REG6		;
	XORLW	(b'01110101')^(b'01110100')	; reg5
	BTFSC	STATUS,Z	;
	GOTO	REG5		;
	XORLW	(b'01110100')^(b'01110110')	; reg7
	BTFSC	STATUS,Z	;
	GOTO	REG7		;
	XORLW	(b'01110110')^(b'01110111')	; reg8
	BTFSC	STATUS,Z	;
	GOTO	REG8		;

	MOVF	BT1,w		;
	ANDLW	b'00000111'	; lower 3bit
	ADDWF	PAGEREG,w		;
	CALL	FINDCV		;
	BTFSC	NOCV		;
	GOTO	HOPP		;
PREG:
	BTFSS	BT1,3		;
	GOTO	EEVERI		;
	GOTO	EEPROG		;

REG5:
	movlw	E_CV29		; CV29
	GOTO	PREG		;

REG6:
	DECF	BT2,f		; Page register
	BCF	STATUS,C	;
	RLF	BT2,f		;
	RLF	BT2,w		;
	movwf	PAGEREG
	goto	CLEAR

REG7:
	movlw	E_CV7
	BTFSS	BT1,3		;
	GOTO	EEVERI		;
	GOTO	HOPP		;	

REG8:
	movlw	E_CV8
	BTFSS	BT1,3		;
	GOTO	EEVERI		;
	GOTO	HOPP		;	

BITMAN:
	call	EERead		; get value
	movlw	EEADR0
	MOVWF	FSR		;
	MOVLW	b'00000111'	;
	ANDWF	BT3,w		;
	CALL	BITPOS		;
	BTFSS	BT3,4		;
	GOTO	VBIT		; verify bit
	BTFSC	BT3,3		;
	IORWF	INDF,f		; set bit
	XORLW	0XFF		;
	BTFSS	BT3,3		;
	ANDWF	INDF,f		; clear bit
	MOVF	EEADR0,w		; EEADDR
	GOTO	EEPROG		; write complete byte
;--------------------------------
VBIT:
	ANDWF	INDF,w		;
	BTFSC	STATUS,Z	;
	GOTO	BITCLR		;

BITSET:
	BTFSC	BT3,3		;
	GOTO	ACKNOW		; =1 
	GOTO	HOPP		;

BITCLR:
	BTFSS	BT3,3		;
	GOTO	ACKNOW		; =0
	GOTO	HOPP		;

;-------------------------------

OLDACK:
		MOVF	BT1,w		;------ for old DCC-Programmer ------
		MOVWF	INDF		; save loco adress
		movlw	E_CV1		; CV1
		CLRF	PAGEREG		; for old acknowledge
		GOTO	OACK		;
;--------------------------------

EEVERI:

OACK:
		MOVWF	EEADR0		;
		CALL	EERead		;
		CLRF	CONFIG
		MOVF	INDF,w		;
		XORWF	EEDATA,w	;

VERIBK:
		BTFSS	STATUS,Z	;
		GOTO	START		;

ACKNOW:
		BTFSC	ACKBIT		;
		GOTO	ACKNOW1		;
		BSF	ACKBIT		; 2x verify 
		GOTO	PROGEX		;

ACKNOW1:
;		BTFSS	ACKON		; acknowledge on?
;		GOTO	HOPP		;

		call	AckPulse
		GOTO	START		;


AckPulse:
		movlw	0xCF			; max. volume
		bsf	STATUS,RP0		; bank 1
		movwf	VRCON
		bcf	STATUS,RP0		; bank 0
		movlw	0x0C			; 50% duty cycle
		movwf	CCP1CON			; start PWM
		bsf	FL_LED			; set FL/FR and motor on
		bsf	BL_LED
LOOP:
		MOVLW	d'25'		; 7x765uS (5355) 4,5,6,7 ok; 8 9 10 IB
		MOVWF	BT5		;
OLOOP:
		CLRF	BT6		; help register
ILOOP:
		INCFSZ	BT6,f		; 765uS ON	1
		GOTO	ILOOP		;		2-3
		DECFSZ	BT5,f		;		
		GOTO	OLOOP		;		

		CLRF	CCP1CON		; shut off
		bcf	FL_LED
		bcf	BL_LED
		BCF	ACKBIT		;
		retlw	0

;-------------------------------------------------------------------------------------------

;---- Sound Envelopes

		org	0x580

GetEnv:
		andlw	0x3F
		addwf	PCL,f
		retlw	HIGH (FixedVol0)		; 0
		retlw	LOW  (FixedVol0)
		retlw	HIGH (FixedVol1)		; 1
		retlw	LOW  (FixedVol1)
		retlw	HIGH (FixedVol2)		; 2
		retlw	LOW  (FixedVol2)
		retlw	HIGH (FixedVol3)		; 3
		retlw	LOW  (FixedVol3)
		retlw	HIGH (FixedVol4)		; 4
		retlw	LOW  (FixedVol4)
		retlw	HIGH (FixedVol5)		; 5
		retlw	LOW  (FixedVol5)
		retlw	HIGH (FixedVol6)		; 6
		retlw	LOW  (FixedVol6)
		retlw	HIGH (FixedVol7)		; 7
		retlw	LOW  (FixedVol7)
		retlw	HIGH (FixedVol8)		; 8
		retlw	LOW  (FixedVol8)
		retlw	HIGH (FixedVol9)		; 9
		retlw	LOW  (FixedVol9)
		retlw	HIGH (FixedVol10)		; 10
		retlw	LOW  (FixedVol10)
		retlw	HIGH (FixedVol11)		; 11
		retlw	LOW  (FixedVol11)
		retlw	HIGH (FixedVol12)		; 12
		retlw	LOW  (FixedVol12)
		retlw	HIGH (FixedVol13)		; 13
		retlw	LOW  (FixedVol13)
		retlw	HIGH (FixedVol14)		; 14
		retlw	LOW  (FixedVol14)
		retlw	HIGH (FixedVol15)		; 15
		retlw	LOW  (FixedVol15)
		retlw	HIGH (Envelope0)		; 16
		retlw	LOW  (Envelope0)
		retlw	HIGH (Envelope1)		; 17
		retlw	LOW  (Envelope1)
		retlw	HIGH (Envelope2)		; 18
		retlw	LOW  (Envelope2)
		retlw	HIGH (Envelope3)		; 19
		retlw	LOW  (Envelope3)
		retlw	HIGH (Envelope4)		; 20
		retlw	LOW  (Envelope4)
		retlw	HIGH (Envelope5)		; 21
		retlw	LOW  (Envelope5)
		retlw	HIGH (Envelope6)		; 22
		retlw	LOW  (Envelope6)
		retlw	HIGH (Envelope7)		; 23
		retlw	LOW  (Envelope7)
		retlw	HIGH (Envelope8)		; 24
		retlw	LOW  (Envelope8)
		retlw	HIGH (Envelope9)		; 25
		retlw	LOW  (Envelope9)
		retlw	HIGH (Envelope0)		; 26
		retlw	LOW  (Envelope0)
		retlw	HIGH (Envelope0)		; 27
		retlw	LOW  (Envelope0)
		retlw	HIGH (Envelope0)		; 28
		retlw	LOW  (Envelope0)
		retlw	HIGH (Envelope0)		; 29
		retlw	LOW  (Envelope0)
		retlw	HIGH (Envelope0)		; 30
		retlw	LOW  (Envelope0)
		retlw	HIGH (Envelope0)		; 31
		retlw	LOW  (Envelope0)




		org	0x600


FixedVol0:
		retlw	0xE0
		retlw	LOW ($-d'1')
FixedVol1:
		retlw	0xE1
		retlw	LOW ($-d'1')
FixedVol2:
		retlw	0xE2
		retlw	LOW ($-d'1')
FixedVol3:
		retlw	0xE3
		retlw	LOW ($-d'1')
FixedVol4:
		retlw	0xE4
		retlw	LOW ($-d'1')
FixedVol5:
		retlw	0xE5
		retlw	LOW ($-d'1')
FixedVol6:
		retlw	0xE6
		retlw	LOW ($-d'1')
FixedVol7:
		retlw	0xE7
		retlw	LOW ($-d'1')
FixedVol8:
		retlw	0xE8
		retlw	LOW ($-d'1')
FixedVol9:
		retlw	0xE9
		retlw	LOW ($-d'1')
FixedVol10:
		retlw	0xEA
		retlw	LOW ($-d'1')
FixedVol11:
		retlw	0xEB
		retlw	LOW ($-d'1')
FixedVol12:
		retlw	0xEC
		retlw	LOW ($-d'1')
FixedVol13:
		retlw	0xED
		retlw	LOW ($-d'1')
FixedVol14:
		retlw	0xEE
		retlw	LOW ($-d'1')
FixedVol15:
		retlw	0xEF
		retlw	LOW ($-d'1')

Envelope0:						; \|\|\|\|\|
		retlw	0xEF				; 0 volume (VRCON:VREN,VREF on RA2, low range,VREF)
		retlw	LOW ($+1)			; 1 next step
		retlw	0xEE				; 2 volume
		retlw	LOW ($+1)			; 3 next step
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE1
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($-d'31')

Envelope1:						; \____
		retlw	0xEF				; 0 volume
		retlw	LOW ($+1)			; 1 next step
		retlw	0xEE				; 2 volume
		retlw	LOW ($+1)			; 3 next step
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE1
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($-1)

Envelope2:						; \/\/\/\
		retlw	0xEF				; 0 volume
		retlw	LOW ($+1)			; 1 next step
		retlw	0xEE				; 2 volume
		retlw	LOW ($+1)			; 3 next step
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE1
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
Envelope6:						; /\/\/\
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE1
		retlw	LOW ($+1)
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEE
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($-d'63')

Envelope3:						; \|----
		retlw	0xEF				; 0 volume
		retlw	LOW ($+1)			; 1 next step
		retlw	0xEE				; 2 volume
		retlw	LOW ($+1)			; 3 next step
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE1
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($-d'1')

Envelope4:						; /|/|/|/|/|
		retlw	0xE0				; 0 volume
		retlw	LOW ($+1)			; 1 next step
		retlw	0xE1				; 2 volume
		retlw	LOW ($+1)			; 3 next step
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEE
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($-d'31')


		org	0x700

Envelope5:						; /-----
		retlw	0xE0				; 0 volume
		retlw	LOW ($+1)			; 1 next step
		retlw	0xE1				; 2 volume
		retlw	LOW ($+1)			; 3 next step
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEE
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($-d'1')

Envelope7:						; /|____
		retlw	0xE0				; 0 volume
		retlw	LOW ($+1)			; 1 next step
		retlw	0xE1				; 2 volume
		retlw	LOW ($+1)			; 3 next step
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEE
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($-d'1')

Envelope8:						; -|_|-|_
		retlw	0xEF				; 0 volume
		retlw	LOW ($+1)			; 1 next step
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($+1)
		retlw	0xE0
		retlw	LOW ($-d'63')

Envelope9:						; /~~~~
		retlw	0xE0				; 0 volume
		retlw	LOW ($+1)			; 1 next step
		retlw	0xE1				; 2 volume
		retlw	LOW ($+1)			; 3 next step
		retlw	0xE2
		retlw	LOW ($+1)
		retlw	0xE3
		retlw	LOW ($+1)
		retlw	0xE4
		retlw	LOW ($+1)
		retlw	0xE5
		retlw	LOW ($+1)
		retlw	0xE6
		retlw	LOW ($+1)
		retlw	0xE7
		retlw	LOW ($+1)
		retlw	0xE8
		retlw	LOW ($+1)
		retlw	0xE9
		retlw	LOW ($+1)
		retlw	0xEA
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEE
		retlw	LOW ($+1)

		retlw	0xEF
		retlw	LOW ($+1)
		retlw	0xEE
		retlw	LOW ($+1)
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEB
		retlw	LOW ($+1)
		retlw	0xEC
		retlw	LOW ($+1)
		retlw	0xED
		retlw	LOW ($+1)
		retlw	0xEE
		retlw	LOW ($+1)

		retlw	0xEF
		retlw	LOW ($-d'19')


;------------------------------------------------------------------------------------------------



; ----- EEPROM default values

; Steam locomotive

		org	0x2100

		dw	0x03		; CV1	Primary Adress
		dw	0x10		; CV7	Manufacturer version 1.0
		dw	0x0D		; CV8	Manufacturer ID. DIY decoder
		dw	0xC0		; CV17	Extended Adress High Byte
		dw	0x03		; CV18	Extended Adress Low Byte
		dw	0x00		; CV19	Consist Adress
		dw	0x02		; CV29	0=DIR 1=14/28 2=PWRSRC 3=ADVACK 4=SPDTAB 5=LADRE 6= 7=ACCDEC
		dw	0x01		; CV33	front light -> xxxxSNBF: Sound, Noise, backlight, frontlight
		dw	0x02		; CV34	back light -> xxxxSNBF: Sound, Noise, backlight, frontlight
		dw	0x04		; CV35	F1 -> xxxxSNBF: Sound, Noise, backlight, frontlight
		dw	0x08		; CV36	F2 -> xxxxSNBF: Sound, Noise, backlight, frontlight
		dw	0x00		; CV37	F3 -> xxxxSNBF: Sound, Noise, backlight, frontlight
		dw	0x00		; CV38	F4 -> xxxxSNBF: Sound, Noise, backlight, frontlight
		dw	0x5A		; CV49	Sound frequency (62500Hz / CV49) ; 
		dw	0x01		; CV50	Noise base freq (15625Hz / CV50) ; 
		dw	0x19		; CV51	Envelope sound (0..31) ; 
		dw	0x10		; CV52	Envelope noise (0..31) ; 
		dw	0x01		; CV53	Envelope duration sound (12.8ms...8.3s) ; 
		dw	0x12		; CV54	Envelope duration noise (12.8ms...8.3s) ; 
		dw	0x00		; CV55	Speed delta sound ; 
		dw	0x3A		; CV56	Speed delta noise ; 
		dw	0x02		; CV57	Sound Config: (0:mix,1:Vol,2:Duty) ; 

		org	0x2120

		dt	"Tu-Shuuu"
		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


Steam (F1):
Whistle (F2):

CV35:	4
CV36:	8
CV49:	90
CV50:	1
CV51:	25
CV52:	16
CV53:	1
CV54:	18
CV55:	0
CV56:	58
CV57:	2



Diesel (F1):
Diesel turbo (F3):

CV35:	4
CV36:	8
CV37:	12
CV49:	100
CV50:	6
CV51:	20
CV52:	20
CV53:	4
CV54:	4
CV55:	4
CV56:	4
CV57:	3


Diesel (F1):
Horn (F2):

CV35:	4
CV36:	8
CV49:	100
CV50:	6
CV51:	15
CV52:	20
CV53:	4
CV54:	4
CV55:	4
CV56:	4
CV57:	2
