;
;	psg01
;
;	PSG SYNTESIZER
;
;	Copyright 2007 アルゴ算法堂
;
;	CPU 16F648A
;
;		RAM 256 BYTES
;		PROG 4096 WORD
;
; RA0 PORTOUT D0
; RA1 PORTOUT D1
; RA2 PORTOUT D2
; RA3 PORTOUT D3
; RA4 PORTOUT A0
; RA5 PORTIN  SW?
;
; RB0 PORTOUT YMZ00_CS-N/WR-N
; RB1 RX
; RB2 TX
; RB3 PORTOUT YMZ01_CS-N/WR-N (OPTION)
; RB4 PORTOUT D4
; RB5 PORTOUT D5
; RB6 PORTOUT D6
; RB7 PORTOUT D7
;
; 機能レジスタはbank0,bank1だけで十分
; 汎用レジスタ（個別）は　bank0,bank1,bank2 0x20-0x6f
; 汎用レジスタ（共用）は　0x70-0x7f
;
; 直接call/gotoできるのは　2kbの範囲(0-7ff,800-fff)
;
;	============================
;	後着優先、ポリフォニック単チャンネル処理
;	============================
;
	list	 p=16f648a
	#include p16f648a.inc
	
; CONFIGRATIONS
	__config	_HS_OSC & _PWRTE_ON & _WDT_OFF & _BOREN_ON & _LVP_OFF & _MCLRE_OFF & _DATA_CP_OFF & _CP_OFF

	
;   Set User ID Memory
	__idlocs	0x0002

;
; constant
;
;option_val	equ	b'10010101'
option_val	equ	b'10010111'
	;b7		RPBU	1:no pullup
	;b6		INTEDE	nouse	rb0/int
	;b5		T0CS	timer0 clock source 0:FOSC/4
	;b4		T0SE	nouse	timer0 clock edge
	;b3		PSA		0: prescaler to timer0
	;b2-b0	PSn		divider
	;				0:	1:2
	;				1:	1:4
	;				2:	1:8
	;				3:	1:16
	;				4:	1:32
	;				5:	1:64
	;				6:	1:128
	;				7:	1:255
;
;	define PSG registors
;
	cblock	0
	ymz_A_frqL,ymz_A_frqH
	ymz_B_frqL,ymz_B_frqH
	ymz_C_frqL,ymz_C_frqH
	ymz_N_freq
	ymz_Mixer
	ymz_A_vol,ymz_B_vol,ymz_C_vol
	ymz_Env_frqL,ymz_Env_frqH
	ymz_Env_form
	endc
;
; COMMON REGISTERS (NON BANKED REGISTERS)
;
	cblock	0x70
	irq_wback	; wk backup
	irq_sback	; swap backup
	irq_fsrback
	irq_pclathback
;
	endc
;
; 発音管理構造体
	cblock	0
	SLOT_NEXT
	SLOT_PRE
	SLOT_CH
	SLOT_NOTE
	SLOT_SIZE
	endc
;
#define SLOT_MAX	3
; bank0
	cblock	0x20
;
	ymz_adr
	ymz_data
	tmr0_count
;
;
	ToneHi			; high tonetable
;
	MidiIn_Channel	;;
	MidiIn_flag
	MidiIn_temp
	MidiIn_a
	MidiIn_b
	MidiIn_c
;
	PSGchannel
	PSGvol
	PSGnote
;
	SlotCur				; current
	SlotEmpty			; (adr) 0:empty
	SlotWork00,SlotWork01
	SlotRoot:2			; _NEXT,_PRE
	Slottbl:SLOT_MAX*SLOT_SIZE
	Slottbl_e
	endc
#if Slottbl_e>.127
	error	"table over flow"
#endif
;
; MIDIIN_FLAG BIT ASSIGN
;
	cblock	0
	MIDIIN_FLAG_3RD
	MIDIIN_FLAG_FERR
	endc
;
;	EEPROM Assign
;
	cblock	0
	EE_Channel
	endc
;
; NAME FOR DEBUG
	cblock	Slottbl
	SLOT0_NEXT
	SLOT0_PRE
	SLOT0_CH
	SLOT0_NOTE
;
	SLOT1_NEXT
	SLOT1_PRE
	SLOT1_CH
	SLOT1_NOTE
;
	SLOT2_NEXT
	SLOT2_PRE
	SLOT2_CH
	SLOT2_NOTE
	endc

	org	0x0
;***************
;	startup
;***************
startup:
	call	initialize
	goto	main
	org	0x4
;***************
;	intrupt
;***************
irq:
	; prologue
	movwf	irq_wback	;save wk
	swapf	STATUS,w	;save status
	movwf	irq_sback
;
	bcf		STATUS,RP0
	bcf		STATUS,RP1
	bcf		STATUS,IRP
	;
	; prologue 2
	movf	FSR,w
	movwf	irq_fsrback
	movf	PCLATH,w
	movwf	irq_pclathback
	;
	;----------------
	btfsc	PIR1,RCIF
	call	rsirq
	btfsc	INTCON,T0IF
	call	tmr0irq
	;----------------
	; epilogue 2
	;
	movf	irq_pclathback,w
	movwf	PCLATH
	movf	irq_fsrback,w
	movwf	FSR
	;
	; epilogue
	swapf	irq_sback,w	;load status
	movwf	STATUS
	swapf	irq_wback,f	;load wk
	swapf	irq_wback,w
	retfie

;***********************************
;	initialize for standard hardware
;***********************************
initialize:
	clrf	STATUS
; initialize portA & portB
	clrf	PORTA
	movlw	b'00001001'		; ymf cs & write hi
	movwf	PORTB
;
	bsf		STATUS,RP0
	movlw	b'11100000'
	movwf	TRISA
	movlw	b'00000110'
	movwf	TRISB
	bcf		STATUS,RP0
;
; ccp(not used)		default
;
; comparator(not used)
;
	movlw	0x07		; com off
	movwf	CMCON
;
; vref(not used) default
;
; timer1(not used) default
;
; timer2(not used) default
;
; usart
	movlw	b'00100100'		;txen,brgh
	bsf		STATUS,RP0
	movwf	TXSTA
	movlw	b'10010000'		;spen,cren
	bcf		STATUS,RP0
	movwf	RCSTA
	movlw	d'39'
	bsf		STATUS,RP0
	movwf	SPBRG
	bsf		PIE1,RCIE	;enable interupt
	bcf		STATUS,RP0
;	movf	RCREG,w			; boodoo

; option_reg
	bsf		STATUS,RP0
	movlw	option_val
	movwf	OPTION_REG
	bcf		STATUS,RP0
; timer0
	clrf	TMR0
; interupt
	clrf	INTCON
	return
;
;****************
;	main routine
;****************

main:
;
	clrf	tmr0_count
	call	initwait
;;
	call	PsgDrvInit
	call	MidiInit
;
	bsf		INTCON,PEIE		; all peri irq
	bsf		INTCON,GIE		; global irq
;
;
main_loop:
#if 0
;;;; test input ;;;;;;
	movlw	0xc0
	call	MidiIn
	movlw	0x01
	call	MidiIn
;
	movlw	0x90
	call	MidiIn
	movlw	0x40
	call	MidiIn
	movlw	0x7f
	call	MidiIn
#endif
;
	nop
	goto	main_loop
;
;-------------------
; timer0 irq routine
;-------------------
tmr0irq:
	bcf		INTCON,T0IF
	incf	tmr0_count,f
	return

;----------------
; rs irq routine
;----------------
rsirq:
	btfsc	RCSTA,FERR
	bsf		MidiIn_flag,MIDIIN_FLAG_FERR
	movf	RCREG,w		;read & clear ferr
	btfsc	MidiIn_flag,MIDIIN_FLAG_FERR
	return				;return if error
	btfss	RCSTA,OERR
	goto	MidiIn
	bcf		RCSTA,CREN	;framing_error
	bsf		RCSTA,CREN
	return
;
;===============
;	ymz access
;===============
;
;--------/ YmzWrite /-------
;
;		in:	ymz_adr: 	use low nible
;			ymz_data:	use 
;
YmzWrite:
;	address out
		movf	ymz_adr,w
		andlw	0x0f			;sure
		movwf	PORTA			;a0->0 & low nible
;
		clrf	PORTB			;write/cs -> 0
;
		movlw	b'00001001'
		movwf	PORTB			;write/cs -> 1
;	data out
		movf	ymz_data,w
		andlw	0x0f
		iorlw	b'00010000'
		movwf	PORTA			;a0-> & low nible
;
		movf	ymz_data,w
		andlw	0xf0
		movwf	PORTB			;write/cs ->0 & hi nible
;
		iorlw	b'00001001'
		movwf	PORTB			;write/cs ->1
;
		return
;
;----------/ initwait /---------
;
;
initwait:
		clrf	TMR0
initwait_loop1:
		movf	TMR0,w
		btfsc	STATUS,Z
		goto	initwait_loop1
initwait_loop2:
		movf	TMR0,w
		btfss	STATUS,Z
		goto	initwait_loop2
		return

;======================
;	MIDIin
;======================
;
;--------/ MidiInit /--------
;
;
MidiInit:
		clrf	MidiIn_a
		bcf		MidiIn_flag,MIDIIN_FLAG_3RD
		bcf		MidiIn_flag,MIDIIN_FLAG_FERR
;
		bsf		STATUS,RP0
		movlw	EE_Channel
		movwf	EEADR
		bsf		EECON1,RD
		movf	EEDATA,w
		bcf		STATUS,RP0
		andlw	0x0f
		movwf	MidiIn_Channel		;ch 1に固定
;
		; 平均率に固定
		movlw	high tonetable
		movwf	ToneHi			; high tonetable

		return
;
;--------/ MidiIn /----------
;
;	byte 2 msg conversion
;
;	in:	w:	data byte
;	out:	MidiIn_a: 1st bytes
;			MidiIn_b: 2nd bytes
;			MidiIn_c: 3rd bytes
;
MidiIn:
		movwf	MidiIn_temp
		btfss	MidiIn_temp,7
		goto	MidiIn_data
MidiIn_status:
		movlw	0xf8
		subwf	MidiIn_temp,w
		btfsc	STATUS,C
		return					; SystemRealMsg
		bcf		MidiIn_flag,MIDIIN_FLAG_3RD		; clear 3rd byte flag
		movf	MidiIn_temp,w
		movwf	MidiIn_a
;
		movlw	0xf0
		subwf	MidiIn_temp,w
		btfsc	STATUS,C
		clrf	MidiIn_a		; ignore system message
		return
;		
MidiIn_data:					; data value
		btfss	MidiIn_flag,MIDIIN_FLAG_3RD	; 3rd byte flag test
		goto	MidiIn_cont
;;;		movf	MidiIn_temp,w
		movwf	MidiIn_c
		bcf		MidiIn_flag,MIDIIN_FLAG_3RD	; 3rd byte flag clear
		goto	MidiInRender	; msg set (call & return)
;
MidiIn_cont:
		movf	MidiIn_a,f
		btfsc	STATUS,Z
		return					; status = 0: ignore failure data
;;;		movf	MidiIn_temp,w
		movwf	MidiIn_b
		movlw	0xc0
		subwf	MidiIn_a,w
		btfss	STATUS,C
		goto	MidiIn_Ch3		; 0x8n,0x9n,0xAn,0xBn
		movlw	0xe0
		subwf	MidiIn_a,w
		btfss	STATUS,C
		goto	MidiInRender	; 2byte msg: 0xCn,0xDn ( call & return )
MidiIn_Ch3:
		bsf		MidiIn_flag,MIDIIN_FLAG_3RD
		return
;
;--------/ MidiInRender /--------
;
;	action routine
;
;	直接発音させるか、バッファ胃に詰めるかのなどの処理。
;
;	現在は直接アクセス、即時処理とする
;
;	in:		MidiIn_a:
;			MidiIn_b:
;			MidiIn_c:
;
MidiInRender:
;
; CHANNEL FILTER
;
		movlw	0x0f
		andwf	MidiIn_a,w
		subwf	MidiIn_Channel,w
		btfss	STATUS,Z
		return
;
		movlw	high MidiInRender_Vec
		movwf	PCLATH
		swapf	MidiIn_a,w
		andlw	0x7
		addlw	low MidiInRender_Vec
		movwf	PCL
		
;
;0xbn cc
MidiInRender_CC:			;control changes
		movlw	.120
		subwf	MidiIn_b,w
		btfss	STATUS,C
		return				; 0-119 :ignore
		movlw	.121
		subwf	MidiIn_b,w
		btfsc	STATUS,Z
		return				; 121: reset all controler
		goto	AllNoteOff	; call & return
;
MidiInRender_NoteOnP:
		movf	MidiIn_c,f
		btfss	STATUS,Z
		goto	NoteOn		; call & return
		goto	NoteOff		; 9x nn 00 call & return
;
MidiInRecnder_PC:
		movlw	high tonetable
		movf	MidiIn_b,f
		btfss	STATUS,Z
		movlw	high pure_tonetable
		movwf	ToneHi
		return

		org		($-1)/.8*.8+.8
MidiInRender_Vec:
		goto	NoteOff					;0x8n	NoteOff
		goto	MidiInRender_NoteOnP	;0x9n	NoteOn
		return							;0xan	Poly After Touch
		goto	MidiInRender_CC			;0xbn	ControlChange
		goto	MidiInRecnder_PC		;0xcn	ProgramChange
		return							;0xdn	Channel After Touch
		return							;x0en	Pitch Bend
		return							;0xfn	Sys
;=========
; PSGDRIVE
;=========

;--------/ PsgdrvInit /-------
;
;	PSGdrv initializer
;
PsgDrvInit:
;
; initialize mixer setting
;
		movlw	ymz_Mixer
		movwf	ymz_adr
		movlw	b'00111000'
		movwf	ymz_data
		call	YmzWrite
; All note off
		clrf	PSGvol
		clrf	PSGchannel
		call	volset
		incf	PSGchannel,f
		call	volset
		incf	PSGchannel,f
		call	volset
;
; SlotInitialize
;
		movlw	Slottbl
		movwf	SlotEmpty
;
		movlw	SLOT_MAX
		movwf	SlotWork00	;use as counter
		clrf	PSGchannel
		movlw	Slottbl
		movwf	FSR
PsgDrvInit_loop:
;	SLOT_NEXT: set emptylink to next slot
		movf	FSR,w
		addlw	SLOT_SIZE
		movwf	INDF
		sublw	Slottbl+SLOT_MAX*SLOT_SIZE
		btfsc	STATUS,Z
		clrf	INDF	;last member
		incf	FSR,f
;	SLOT_PRE
		clrf	INDF
		incf	FSR,f
;	SLOT_CH
		movf	PSGchannel,w
		movwf	INDF
		incf	FSR,f
;	SLOT_NOTE
		clrf	INDF
		incf	FSR,f
;	update channel
		incf	PSGchannel,f
;
		decfsz	SlotWork00,f
		goto	PsgDrvInit_loop
;
; init Links
;
		movlw	SlotRoot
		movwf	SlotRoot	;root.next
		movwf	SlotRoot+1	;root.pre
		return
;
;--------/ getEmptySlot /---------
;
;	get empty slot from emtry_link
;
;	out:	SlotCur	: adr, 0 is no space
;
getEmptySlot:
		movf	SlotEmpty,w
		movwf	SlotCur
		btfsc	STATUS,Z
		return			; no empty
;
; rel from empty link
;	cur.SLOT_NEXT → SlotEmpty
;
		movwf	FSR
		movf	INDF,w
		movwf	SlotEmpty
		return
;
;-------/ appendSlot /----------
;
;	append to last
;
;	in:	SlotCur:	current
;
appendSlot:
; cur->next := &root
		movf	SlotCur,w
		movwf	FSR
		movlw	SlotRoot
		movwf	INDF
; cur->pre := root.pre
		incf	FSR,f
		movf	SlotRoot+SLOT_PRE,w	; root.pre
		movwf	INDF
; (root->pre)->next := cur
		movwf	FSR			; root->pre -> FSR
		movf	SlotCur,w
		movwf	INDF		; cur -> (root->pre)->next
; root.pre := cur
		movwf	SlotRoot+SLOT_PRE	; root.pre
		return
;   
;--------/ delSlot /--------
;
;	delete from link
;	and insert to empty link top
;
;	in:		SlotCur: adr
;
delSlot:
		movf	SlotCur,w
		movwf	FSR
		movf	INDF,w
		movwf	SlotWork00		; work00 := SlotCur->next
		incf	FSR,f
		movf	INDF,w
		movwf	SlotWork01		; work01 := SlotCur->pre
; (cur->pre)->next := cur->next
		movwf	FSR				; cur->pre
		movf	SlotWork00,w	; cur->next
		movwf	INDF			; (cur->pre)->next := cur.next
; (cur.next).pre <- cur.pre
		movwf	FSR
		incf	FSR,f
		movf	SlotWork01,w	;cur->pre
		movwf	INDF			;(cur.next).pre := cur.pre
; cur->next := empty
		movf	SlotCur,w
		movwf	FSR
		movf	SlotEmpty,w
		movwf	INDF
; emtpy := cur
		movf	SlotCur,w
		movwf	SlotEmpty
		return
;
;--------/ note2valH /---------
;
;	in:		PSGnote
;	out:	w	value
;
note2valH:
		movf	ToneHi,w
		movwf	PCLATH
		bsf		STATUS,C
		rlf		PSGnote,w		;; no overflow
		movwf	PCL				;; call & return
;
;--------/ note2valL /---------
;
;	in:		PSGnote
;	out:	w	value
;
note2valL:
		bcf		STATUS,C
		rlf		PSGnote,w		;; no overflow
		movwf	PCL				; call & return
;
;--------/ toneset /---------
;
;	tone value setup
;
;	in:		PSGchannel:
;			PSGnote
;
toneset:
		bcf		STATUS,C
		rlf		PSGchannel,w
		addlw	ymz_A_frqH
		movwf	ymz_adr
		call	note2valH
		movwf	ymz_data
		call	YmzWrite
;
		decf	ymz_adr,f
		call	note2valL
		movwf	ymz_data
		goto	YmzWrite	; call & return
;
;---------/ volset /-----------
;
;	volume value setup
;
;	in:	PSGchannel
;		PSGvol
volset:
		movlw	ymz_A_vol
		addwf	PSGchannel,w
		movwf	ymz_adr
		movf	PSGvol,w
		movwf	ymz_data
		goto	YmzWrite	; call & return
;
;-------/ SlotOn /-------
;
;	Phisical NoteOn
;
;	in:	SlotCur: current slot
;		MidiIn_a - c:	!!! use direct!!
;
SlotOn:
	; channel set
		movlw	SLOT_CH
		addwf	SlotCur,w
		movwf	FSR
		movf	INDF,w
		movwf	PSGchannel
	; noteset SLOT_NOTE
		incf	FSR,f
		movf	MidiIn_b,w
		movwf	INDF
		movwf	PSGnote
	; volume set
		movf	MidiIn_c,w
		movwf	PSGvol
		rrf		PSGvol,f
		rrf		PSGvol,f
		rrf		PSGvol,f
		movlw	0x0f
		andwf	PSGvol,f
		btfsc	STATUS,Z
		incf	PSGvol,f
	; set to LSI
		call	toneset
		goto	volset			; call & return
;
;-------/ SlotOff /-------
;
;	Phisical NoteOff
;
;	in:	SlotCur: current slot
;
SlotOff:
		movlw	SLOT_CH
		addwf	SlotCur,w
		movwf	FSR
		movf	INDF,w
		movwf	PSGchannel
		clrf	PSGvol
		goto	volset			; call & return
;
;-------/ NoteOn /--------
;
;	Logical NoteOn
;
;	in:	MidiIn_a - c
;
NoteOn:
;
; 空いてるチャンネルを捜す
;
		call	getEmptySlot
		movf	SlotCur,f
		btfss	STATUS,Z
		goto	NoteOn_new
;
		movf	SlotRoot+0,w	; first note
		movwf	SlotCur
		call	delSlot
;
; 発音を消す処理
;
		call	SlotOff
		call	getEmptySlot
		movf	SlotCur,f	;sure
		btfsc	STATUS,Z
		return			 	; irregal case
;
NoteOn_new:
; 末尾に登録
		call	SlotOn
		goto	appendSlot		; call & return
;
;------/ NoteOff /-------
;
;	Logical NoteOff
;
;	in:	MidiIn_a - c
;
NoteOff:
;
; 古いものから順に合致する音程を捜す
;
		movf	SlotRoot+0,w	;top
		movwf	SlotCur
NoteOff_loop:
		movlw	SlotRoot
		subwf	SlotCur,w
		btfsc	STATUS,Z
		return					; unfound
		movlw	SLOT_NOTE
		addwf	SlotCur,w
		movwf	FSR
		movf	MidiIn_b,w
		subwf	INDF,w
		btfsc	STATUS,Z
		goto	NoteOff_Found
		movf	SlotCur,w		;cur->next
		movwf	FSR
		movf	INDF,w
		movwf	SlotCur
		goto	NoteOff_loop
;
NoteOff_Found:
		call	SlotOff
		goto	delSlot		; call & return
;
;------/ AllNoteOff /------
;
; 発音中の音はすべて停止
;
AllNoteOff:
;
AllNoteOff_loop:
		movlw	SlotRoot
		subwf	SlotRoot,w
		btfsc	STATUS,Z
		return
		movf	SlotRoot,w
		movwf	SlotCur
		call	SlotOff
		call	delSlot
		goto	AllNoteOff_loop
;
;========================
; TONETABLE
;========================
; dt frq low , frq hi
		org		(($-1)/.256)*.256+.256
tonetable:
	dt	.238,.14
	dt	.24,.14
	dt	.77,.13
	dt	.142,.12
	dt	.218,.11
	dt	.47,.11
	dt	.143,.10
	dt	.247,.9
	dt	.104,.9
	dt	.225,.8
	dt	.97,.8
	dt	.210,.15
	dt	.238,.14
	dt	.24,.14
	dt	.77,.13
	dt	.142,.12
	dt	.218,.11
	dt	.47,.11
	dt	.143,.10
	dt	.247,.9
	dt	.104,.9
	dt	.225,.8
	dt	.97,.8
	dt	.210,.15
	dt	.238,.14
	dt	.24,.14
	dt	.77,.13
	dt	.142,.12
	dt	.218,.11
	dt	.47,.11
	dt	.143,.10
	dt	.247,.9
	dt	.104,.9
	dt	.225,.8
	dt	.97,.8
	dt	.233,.7
	dt	.119,.7
	dt	.12,.7
	dt	.167,.6
	dt	.71,.6
	dt	.237,.5
	dt	.152,.5
	dt	.71,.5
	dt	.252,.4
	dt	.180,.4
	dt	.112,.4
	dt	.49,.4
	dt	.244,.3
	dt	.188,.3
	dt	.134,.3
	dt	.83,.3
	dt	.36,.3
	dt	.246,.2
	dt	.204,.2
	dt	.164,.2
	dt	.126,.2
	dt	.90,.2
	dt	.56,.2
	dt	.24,.2
	dt	.250,.1
	dt	.222,.1
	dt	.195,.1
	dt	.170,.1
	dt	.146,.1
	dt	.123,.1
	dt	.102,.1
	dt	.82,.1
	dt	.63,.1
	dt	.45,.1
	dt	.28,.1
	dt	.12,.1
	dt	.253,.0
	dt	.239,.0
	dt	.225,.0
	dt	.213,.0
	dt	.201,.0
	dt	.190,.0
	dt	.179,.0
	dt	.169,.0
	dt	.159,.0
	dt	.150,.0
	dt	.142,.0
	dt	.134,.0
	dt	.127,.0
	dt	.119,.0
	dt	.113,.0
	dt	.106,.0
	dt	.100,.0
	dt	.95,.0
	dt	.89,.0
	dt	.84,.0
	dt	.80,.0
	dt	.75,.0
	dt	.71,.0
	dt	.67,.0
	dt	.63,.0
	dt	.60,.0
	dt	.56,.0
	dt	.53,.0
	dt	.50,.0
	dt	.47,.0
	dt	.45,.0
	dt	.42,.0
	dt	.40,.0
	dt	.38,.0
	dt	.36,.0
	dt	.34,.0
	dt	.32,.0
	dt	.30,.0
	dt	.28,.0
	dt	.27,.0
	dt	.25,.0
	dt	.24,.0
	dt	.22,.0
	dt	.21,.0
	dt	.20,.0
	dt	.19,.0
	dt	.18,.0
	dt	.17,.0
	dt	.16,.0
	dt	.15,.0
	dt	.14,.0
	dt	.13,.0
	dt	.13,.0
	dt	.12,.0
	dt	.11,.0
	dt	.11,.0
	dt	.10,.0

;======[ 純正律PSG周波数設定値 ]========
;
		org		(($-1)/.256)*.256+.256
pure_tonetable:
	dt	.0,.15
	dt	.102,.14
	dt	.128,.13
	dt	.168,.12
	dt	.0,.12
	dt	.64,.11
	dt	.32,.10
	dt	.0,.10
	dt	.96,.9
	dt	.0,.9
	dt	.112,.8
	dt	.0,.8
	dt	.0,.15
	dt	.102,.14
	dt	.128,.13
	dt	.168,.12
	dt	.0,.12
	dt	.64,.11
	dt	.32,.10
	dt	.0,.10
	dt	.96,.9
	dt	.0,.9
	dt	.112,.8
	dt	.0,.8
	dt	.0,.15
	dt	.102,.14
	dt	.128,.13
	dt	.168,.12
	dt	.0,.12
	dt	.64,.11
	dt	.32,.10
	dt	.0,.10
	dt	.96,.9
	dt	.0,.9
	dt	.112,.8
	dt	.0,.8
	dt	.128,.7
	dt	.51,.7
	dt	.192,.6
	dt	.84,.6
	dt	.0,.6
	dt	.160,.5
	dt	.16,.5
	dt	.0,.5
	dt	.176,.4
	dt	.128,.4
	dt	.56,.4
	dt	.0,.4
	dt	.192,.3
	dt	.154,.3
	dt	.96,.3
	dt	.42,.3
	dt	.0,.3
	dt	.208,.2
	dt	.136,.2
	dt	.128,.2
	dt	.88,.2
	dt	.64,.2
	dt	.28,.2
	dt	.0,.2
	dt	.224,.1
	dt	.205,.1
	dt	.176,.1
	dt	.149,.1
	dt	.128,.1
	dt	.104,.1
	dt	.68,.1
	dt	.64,.1
	dt	.44,.1
	dt	.32,.1
	dt	.14,.1
	dt	.0,.1
	dt	.240,.0
	dt	.230,.0
	dt	.216,.0
	dt	.203,.0
	dt	.192,.0
	dt	.180,.0
	dt	.162,.0
	dt	.160,.0
	dt	.150,.0
	dt	.144,.0
	dt	.135,.0
	dt	.128,.0
	dt	.120,.0
	dt	.115,.0
	dt	.108,.0
	dt	.101,.0
	dt	.96,.0
	dt	.90,.0
	dt	.81,.0
	dt	.80,.0
	dt	.75,.0
	dt	.72,.0
	dt	.68,.0
	dt	.64,.0
	dt	.60,.0
	dt	.58,.0
	dt	.54,.0
	dt	.51,.0
	dt	.48,.0
	dt	.45,.0
	dt	.41,.0
	dt	.40,.0
	dt	.38,.0
	dt	.36,.0
	dt	.34,.0
	dt	.32,.0
	dt	.30,.0
	dt	.29,.0
	dt	.27,.0
	dt	.25,.0
	dt	.24,.0
	dt	.23,.0
	dt	.20,.0
	dt	.20,.0
	dt	.19,.0
	dt	.18,.0
	dt	.17,.0
	dt	.16,.0
	dt	.15,.0
	dt	.14,.0
	dt	.14,.0
	dt	.13,.0
	dt	.12,.0
	dt	.11,.0
	dt	.10,.0
	dt	.10,.0


;=========================
;	EEPROM SECTION
;=========================
;
;	256 bytes
;	action data
;
;
	org		0x2100
	de		0		; midiIn Channel Number(0 : ch 1 ...)

;
;
;
;
	end
