;	Disassembled by:
;		DASMx object code disassembler
;		(c) Copyright 1996-2003   Conquest Consultants
;		Version 1.40 (Oct 18 2003)
;	File:		klm8049.bin
;	Size:		2048 bytes
;	Checksum:	6C38
;	CRC-32:		246D7767
;	Date:		Fri Mar 28 15:18:44 2014
;	CPU:		Intel 8048 (MCS-48 family)
;
; tasm -48 -g3 klm8049.asm myklm8049.bin
; g0 is Intel Hex
; g3 selects binary

; Assembly source code for Korg PolySix D8049C Key Assigner MCU
; This file is valid input for TASM32 and will produce a binary that 
; matches the original code.

: Seems like this code was also used for the Mono/Poly.

; Note: Comments are mine, based on how I think the code works.
; 	There could easily be mistakes.

;8049 has RAM from 0-7F

rb0r0		.equ	00h	;first set of registers
rb0r1		.equ	01h	;occupy RAM addresses 0-7
rb0r2		.equ	02h
rb0r3		.equ	03h
rb0r4		.equ	04h
rb0r5		.equ	05h
rb0r6		.equ	06h
rb0r7		.equ	07h

				;second set of regs occupy RAM addr 24-31:
rb1r0		.equ	18h	
rb1r1		.equ	19h
rb1r2		.equ	1Ah
rb1r3		.equ	1Bh
rb1r4		.equ	1Ch
rb1r5		.equ	1Dh
rb1r6		.equ	1Eh
rb1r7		.equ	1Fh	;counts 0-8 then wraps to 0 for time slots

row0stat	.equ	020h	;hw keydown status for row 0, 1=pressed
row1stat	.equ	021h	;hw keydown status for row 1
row2stat	.equ	022h	;hw keydown status for row 2
row3stat	.equ	023h	;hw keydown status for row 3
row4stat	.equ	024h	;hw keydown status for row 4
row5stat	.equ	025h	;hw keydown status for row 5
row6stat	.equ	026h	;hw keydown status for row 6
row7stat	.equ	027h	;hw keydown status for row 7

P20swstate	.equ	028h	;P20 sw bits, 1=closed
				;  7    6   5   4   3    2       1    0
				;{ARP,  0,  0, Poly,0, Unison,Chord,Hold}

P21swstate	.equ	029h	;P21 sw bits, 1=closed
				;  7    6   5   4   3    2       1    0
				;{Full,Two,One,Up,Up/Dn,Dn,    Latch, 0}

row0played	.equ	030h	;bits are set as keys in each row are
row1played	.equ	031h	;played in arpeggiator mode
row2played	.equ	032h	
row3played	.equ	033h	
row4played	.equ	034h	
row5played	.equ	035h	
row6played	.equ	036h
row7played	.equ	037h

arpoct		.equ	03Ch	;indicates current octave when
				;playing arpeggio in full mode (0-4)
arpdir		.equ	03Dh	;arpeggiator direction, 00=up, FF=down
lstkeybit	.equ	03Eh	;mask of keystate bit corresponding to 
				;last arp note we sent out
lstkeyrow	.equ	03Fh	;low bits point to keyrow of last arp
				;note we sent out

chordx0		.equ	040h	;used in chord mem mode
chordx1		.equ	048h	;used in chord mem mode

				;chord intervals stored in order they were in 
				;in voices 0-5 at the time chord sw was pressed,
				;and in the order they will be assigned when played
chordint0	.equ	051h	;one of the intervals will be 0
chordint1	.equ	051h	;interval from lowest note to note in chord
chordint2	.equ	052h	
chordint3	.equ	053h
chordint4	.equ	054h
chordint5	.equ	055h

lstarpnote	.equ	059h	;seems to hold the last arp note sent out
				;in chord mem mode, seems to hold chord low key number

nxtvce		.equ	05Bh	;points to next vce to be used in rotation
lstvce		.equ	05Eh	;seems like the index 0-5 of the highest voice present
				;(5 for Poly6, 3 for Mono/Poly)
inttemp		.equ	05Fh	;used to save acc value during int handler

				;not sure, but:
vcegatex	.equ	060h	;D7: 
				;D6: No new keys need to be assigned
				;D5: Voice 5 has note assigned and gate is on
				;D4: Voice 4 has note assigned and gate is on
				;D3: Voice 3 has note assigned and gate is on
				;D2: Voice 2 has note assigned and gate is on
				;D1: Voice 1 has note assigned and gate is on
				;D0: Voice 0 has note assigned and gate is on


FPLEDsx		.equ	061h	;seems to be same as 0x71 value

vce0note	.equ	062h	;current key # assigned to voice 0 (not incl octave sel)
vce1note	.equ	063h	;current key # assigned to voice 1
vce2note	.equ	064h	;current key # assigned to voice 2
vce3note	.equ	065h	;current key # assigned to voice 3
vce4note	.equ	066h	;current key # assigned to voice 4
vce5note	.equ	067h	;current key # assigned to voice 5

highnote	.equ	06Ah	;constant, seems to be highest note we would 
				;send out (0x54) seems like any note numbers higher 
				;than this in arp full mode are discarded
lstnote		.equ	06Bh	;last note assigned?

vcegates	.equ	070h	;storage for six voice gate bits used by hw
FPLEDs		.equ	071h	;storage for LED control bits used by hw

vce0adjnote	.equ	072h	;current note # assigned to voice 0, adjusted for octave
vce1adjnote	.equ	073h	;current note # assigned to voice 1
vce2adjnote	.equ	074h	;current note # assigned to voice 2
vce3adjnote	.equ	075h	;current note # assigned to voice 3
vce4adjnote	.equ	076h	;current note # assigned to voice 4
vce5adjnote	.equ	077h	;current note # assigned to voice 5
hghnote		.equ	07Ah	;copy of 6A, high note value, used for ALog servo
lstadjnote	.equ	07Bh	;last adjusted note # assigned?



	.org	00000H

L0000:
	dis	i
	dis	tcnti
	sel	rb0
	clr	a
	cpl	a		;acc = 0xFF
L0005:	jmp	L009		;jump over vector

L0007:	jmp	L0080		;counter/timer interrupt jumps here		

L009:
	outl	bus,a		;send out 0xFF on data bus
	outl	p1,a		;on p1 as well
	mov	a,#0E3H		;inhibit 4051's
	outl	p2,a

	clr	a		;clear RAM from address 8 to 0x7F
	mov	r0,#008H	;that's everything except reg bank 0
	mov	r7,#078H
L013:	mov	@r0,a
	inc	r0
	djnz	r7,L013

	anl	p2,#0FEH	;drive P20 low
	mov	r0,#028H
	in	a,p1		;read five switch inputs from front panel
				; D7   D4     D2      D1     D0
	cpl	a		;ARP  Poly  Unison ChordMem Hold
	mov	@r0,a		;make sw status bits active high and save at addr 0x28

	mov	r0,#05EH
	mov	r1,#07EH
	jb6	L002E		;Mono/Poly has a diode from P16 to P20
				;but we complemented Port 1 input
	mov	@r0,#005H	;so this code would be executed if on the PolySix	 	
	mov	@r1,#0FFH	;set 0x5E to 5 (highest voice index)	
	mov	r0,#061H	
	mov	@r0,#010H	;set bit to turn on Poly LED
	jmp	L036

L002E:
	mov	@r0,#003H	;this code is for the MonoPoly, maybe 0x5E is index of highest voice?
	mov	@r1,#0CFH
	mov	r0,#061H
	mov	@r0,#004H
L036:
	mov	r0,#058H	;write FF to addr 0x58
	mov	@r0,#0FFH
	mov	r0,#06AH	;and 54 to 0x6A
	mov	@r0,#054H	;0x54 is the highest value we send to the DAC, (key 60+24 for 4')

	mov	a,#0FAH
	mov	t,a		;set timeout interval		
	strt	t		;and start timer

	clr	f1
	cpl	f1		;set f1
	en	tcnti		;enable timer interrupt

				;at startup, the following get set up:
				;addr 58: FF
				;addr 5E: 05 (index of highest voice)
				;addr 61: 10 (turn on Poly LED)
				;addr 6A: 54 (used for alog servo loop)
				;addr 7E: FF


				;wait loop:
L0045:				;code jumps back to this label in one place near the end
				;and intr will come back, assuming we were here when it came in
	jni	L004B		;jump if arpeggiator trigger is low
L0047:
	jf1	L0045		;if f1 set, we wait in this loop for a timer interrupt
	jmp	L0167		;otherwise we process any sw/key changes



L004B:
	mov	r0,#07DH
	mov	@r0,#0FFH
	jmp	L0047

L0051:
	mov	r0,#061H	;check LED/mode
	mov	a,@r0
	jb6	L006B		;jump if Arp mode
	jb1	L0078		;jump if Chord Mem mode
	jb2	L007A		;jump if Unison mode
	jb3	L007C
	jb4	L007E		;jump if Poly mode
	jmp	L04C0

L0060:
	mov	r0,#061H
	mov	a,@r0
	jb3	L0069
	jb4	L0069		;jump if Poly mode
	jmp	L02A1
L0069:
	jmp	L0489

L006B:
	mov	r0,#07DH
	mov	a,@r0
	jnz	L0060
	dec	r0
	mov	a,@r0
	jz	L0076
	jmp	L05CA
L0076:
	jmp	L06FC
L0078:
	jmp	L02B6
L007A:
	jmp	L027B
L007C:
	jmp	L0362
L007E:
	jmp	L0409


; ************   Start of timer interrupt code ********************


L0080:				;counter/timer interrupt handler
	sel	rb1

	mov	r0,#05FH
	mov	@r0,a		;save acc value at address 0x5F

	mov	a,#0F8H		;each tick is 80 uSec
	mov	t,a		;so 8 counts (to 0) would take 640 uSec
	strt	t

	orl	p2,#060H	;set P26,P25, inhibit 4051's

	mov	a,r7		;timeslot counter (=MUXSEL+1)
	xrl	a,#008H		;is it 8?
	jnz	L0095		;no, jump
	mov	r7,a		;yes, set it to 0
	mov	a,#0F7H		;make interval a little longer for this one
	mov	t,a		;set timout interval
	jmp	L00E3		;update voice gates and LED's

L0095:				;timeslots 0-7
	mov	a,r7
	xrl	a,#006H		;is it timeslot 6?
	jz	L00AE
	mov	a,r7		;no
	xrl	a,#007H		;is it timeslot 7?
	jz	L00C3
	mov	a,r7		;no, get timeslot (0-5) into acc
L00A0:
	add	a,#072H		;add it to address 0x72
	mov	r0,a
	mov	a,@r0		;read data at result address (DAC value for voice)
	outl	bus,a		;and send it out
	in	a,p2
	anl	a,#0F8H		;clear the lower 3 bits of p2
	orl	a,r7		;OR in r7 value
	outl	p2,a		;and send it out
	anl	p2,#0DFH	;drop P25, to enable the 4051's
				;(write voltage out to a voice between 0 and 5)
	jmp	L00BE		;jump to end of intr handler		

L00AE:				;timeslot 6
	mov	r0,#07AH
	mov	r1,#028H	;Mono/Poly has a diode from P20 to P16
	mov	a,@r1		;so it will jump to A0
	jb6	L00A0		;P6 has no sw on this bit
L00B5:
	mov	a,@r0
	outl	bus,a		;Poly6 would read value at 0x7A and send it out
	in	a,p2		;that's the high C note value, for alog servo 
	anl	a,#0F8H
	orl	a,r7		;put out lower 3 bits of r7
	outl	p2,a
	anl	p2,#09FH	;drop P26 and P25
L00BE:
	inc	r7		;bump ctr, r7 is always ahead of muxsel,
				;since we bump it here
				;this value will be sent out on next interrupt
L00BF:
	mov	r0,#05FH	;restore saved acc value from addr 0x5F
	mov	a,@r0
	retr			;return with psw restore, used for ints



L00C3:				;timeslot 7
	mov	r0,#07BH
	mov	r1,#028H	;Mono/Poly has a diode from P20 to P16
	mov	a,@r1		;so it will jump to B5
	jb6	L00B5
	jmp	L00A0		;P6 has no sw on this bit, so it will jump to A0
				;probably the value it puts out here is not important



				;called with a mask in r6, and r1 pointing to addr 38
L00CC:				;if addr 38 bit for r6 mask=0, enable LED using mask			
	clr	f0		;clear f0 flag
	mov	a,@r1
	anl	a,r6		;using r6 as mask, test bit at addr 38
	jnz	L00DD		;if it's 1, return
	mov	r0,#061H	;if not
	mov	a,@r0
	anl	a,r6		;test same bit in LED control location
	jnz	L00DD		;if it's set, return
	mov	a,@r0
	anl	a,#0C0H		;otherwise, turn off all LEDs except ARP
	orl	a,r6		;OR r6 into LED value
	mov	@r0,a		;and write it out
	cpl	f0		;set f0 flag
L00DD:
	ret



L00DE:				;add 0x10 to addr in r0, copy to r1
	mov	a,r0
	add	a,#010H
	mov	r1,a
	ret


L00E3:				;this is last time slot, with muxes inhibited
	mov	r0,#070H	;we update gates and LED's here
	mov	a,@r0		;using values in 0x70 and 0x71
	outl	bus,a
	inc	r0
	orl	p2,#008H	;activate stb for gates
	anl	p2,#0F7H	;this is where gates turned on
	mov	a,@r0
	outl	bus,a
	nop			;delay
	orl	p2,#010H	;activate stb for FP LED's
	anl	p2,#0EFH	;this turned on the Poly LED initially
	jf1	L00F7
	jmp	L00BF		;jump to end of int handler


; ************   End of timer interrupt code ********************



L00F7:
	clr	f1		;f1 gets cleared here, which allows code to exit loop at 45
	clr	f0		;(f1 goes low at the end of MUXSEL=7 time)
	cpl	f0		;set f0 (assume latch sw not on)
	clr	c
	mov	r1,#05DH
	mov	r0,#061H
L00FF:
	mov	a,@r0		
	cpl	a
	jb6	L010A
	mov	r0,#029H	;P21 sw states
	mov	a,@r0
	cpl	a
	jb1	L010A
	clr	f0		;clear f0 if latch is on
L010A:
	mov	r0,#020H	;keyboard scan code:
	orl	p2,#003H	;Set p20 and p21
	mov	r2,#0FEH	;initial row value (scan row 0)
	mov	r6,#008H	;scan 8 rows
L0112:
	mov	a,r2
	outl	bus,a		;drive one key row low
	rl	a
	mov	r2,a		;shift zero bit to the left
	in	a,p1		;read keyboard columns
	cpl	a		;make them active high
	jnz	L0158		;if any key is down in this group, jump
	jf0	L011D		;if not latch, skip OR
L011C:
	orl	a,@r0		;either add any new keys to what's already stored (latch)
L011D:
	mov	@r0,a		;or just use new value
	inc	r0		;bump ptr
	djnz	r6,L0112	;scan all 8 rows

	jc	L014B
	mov	@r1,#000H
	mov	r1,#029H	;check latch switch
	mov	a,@r1
	jb1	L0137		;if latch mode, jump
	mov	r1,#07FH
	jmp	L0135

L012E:
	in	a,p2
	nop
	nop
	orl	p2,#080H
	mov	r1,#07DH
L0135:
	mov	@r1,#0FFH
L0137:
	mov	a,#0FFH
	outl	bus,a
	anl	p2,#0FEH	;drive P20 low
	nop			;delay
	in	a,p1		;read switches
	cpl	a		;invert the bits
	mov	@r0,a		;save at addr 0x28		
	inc	r0
	orl	p2,#001H	;raise P20
	anl	p2,#0FDH	;drop P21
	nop
	in	a,p1		;read switches
	cpl	a		;invert the bits
	mov	@r0,a		;save at addr 0x29
	jmp	L00BF

L014B:
	mov	a,@r1
	jnz	L0135
	mov	r1,#07FH
	mov	@r1,#0FFH
	mov	r1,#05DH
	mov	@r1,#0FFH
	jmp	L012E

L0158:
	clr	c
	cpl	c		;set cy flag
	jf0	L011D		;if not latch, jump
	xch	a,@r1		;check contents of 0x5D
	jnz	L0164		;if it's non-zero, just go back to loop
	xch	a,@r1		;(but we have already set the cy flag)
	clr	f0		;if 0x5D is 0,
	cpl	f0		;set f0 flag
	jmp	L010A		;and restart loop

L0164:
	xch	a,@r1
	jmp	L011C


				;we jump here from wait loop
				;so presumably this is where we start processing
				;any key or switch changes, which are logged in		
L0167:				;the interrupt code, so basically, all scanning
	mov	r0,#028H	;of hw and updating hw values happens in the interrupt
	mov	r1,#038H	;code				
	clr	f0
	mov	a,@r0
	cpl	a
	jb0	L0189		;jump if hold sw not pressed
	mov	r2,a		;save inverted switches value
	mov	a,@r1
	jb0	L0188		;jump if we have already logged switch as down?
	mov	r0,#061H	;point to LED states	
	mov	a,@r0
	jb6	L0188		;jump if ARP LED is on (hold is ignored)
	jb0	L017F		;jump if Hold LED is on
	orl	a,#001H
	jmp	L0187		;turn on Hold LED

L017F:				;Hold LED is already on
	anl	a,#0FEH
	mov	@r0,a		;turn it off
	dec	r0		;point to 0x60
	clr	a		
	mov	@r0,a		;clear it
	mov	r0,#05BH	;addr 5B points to next vce to be used in rotation
L0187:
	mov	@r0,a	
L0188:
	mov	a,r2
L0189:				;acc holds inverted sw states
	jb5	L018F
	mov	r6,#020H
	jmp	L019F

L018F:
	jb4	L0195		;jump if Poly sw not pressed	
	mov	r6,#010H
	jmp	L019F

L0195:
	jb3	L019B
	mov	r6,#008H
	jmp	L019F

L019B:
	jb2	L01A3		;jump if Unison sw not pressed
	mov	r6,#004H
L019F:
	call	L00CC		;if addr 38 bit for r6 mask=0, enable LED using mask
	jmp	L01EB

L01A3:
	jb1	L01EB		;jump if Chord sw not pressed

	mov	r6,#002H	
	mov	r0,#061H
	mov	a,@r0		;get LED states
	jb2	L019F		;jump if Uni LED is on
	jb1	L019F		;jump if Chord LED is on
	jb6	L019F		;jump if ARP LED is on

	call	L00CC		;if addr 38 bit for r6 mask=0, enable LED using mask

	mov	r0,#060H	;if no voices assigned
	mov	a,@r0
	jz	L01EB		;jump

	mov	r0,#062H
	mov	r6,#006H	;loop ctr
	mov	r5,#0FFH
	mov	r1,#060H
	mov	a,@r1
	mov	r2,a		;move value at 0x60 into r2
	mov	r4,#001H	;init mask
L01C3:
	mov	a,r2
	anl	a,r4		;is this voice assigned?
	jz	L01CF		;if not, skip it
	clr	c
	mov	a,@r0		;this loop finds lowest key number in 62-67
	cpl	a		;ones complement
	add	a,r5		;and leaves it in r5 (the lowest key pressed)
	jnc	L01CF
	mov	a,@r0
	mov	r5,a
L01CF:				;label only used two places right above
	clr	c
	mov	a,r4
	rl	a		;rotate mask to left one place
	mov	r4,a
	inc	r0
	djnz	r6,L01C3

	mov	r0,#062H	;OK, now we have lowest key in r5, so 
	mov	r6,#006H	;calculate offsets to other keys
	mov	r1,#050H
L01DC:				;label only used for looping
	mov	a,r5
	cpl	a		;ones complement
	add	a,@r0
	inc	a		;so this forms @r0-r5 value
	mov	@r1,a		;write it out to addr 50-55
	inc	r0
	inc	r1
	djnz	r6,L01DC	;do all 6 voices

	mov	r0,#060H
	mov	a,@r0
	mov	r0,#058H
	mov	@r0,a
L01EB:
	jf0	L01EF
	jmp	L0205

L01EF:				;only executed if f0 is set:
	mov	r0,#05BH	;addr 5B points to next vce to be used in rotation
	mov	@r0,#000H	;clear it

	mov	r0,#061H
	mov	a,@r0
	anl	a,#0FEH		;clear bit 0 of addr 0x61 to shut off Hold LED
	mov	@r0,a		;and write it out		

	dec	r0
	mov	@r0,#000H	;clear address 0x60
	mov	r1,#048H
	mov	r6,#008H
	clr	a
L0201:	mov	@r1,a		;clear addr 48-4F
	inc	r1
	djnz	r6,L0201

L0205:
	mov	r0,#028H
	mov	r1,#038H
	mov	a,@r0
	cpl	a
	jb6	L0227		;jump if PolySix

	inc	r0
	mov	a,@r0
	mov	r0,#061H
	jb0	L0222	
	jb1	L0222	
L0215:
	mov	a,@r0
	cpl	a
	jb6	L023A	
	cpl	a
	anl	a,#0BFH	
	mov	@r0,a
	dec	r0
	mov	@r0,#000H
	jmp	L023A

L0222:
	mov	a,@r0
	jb6	L023A
	jmp	L0231

L0227:				;PolySix code
	jb7	L023A		;jump if ARP not pressed
	mov	a,@r1
	jb7	L023A		;jump if ARP bit set at addr 38
	mov	r0,#061H
	mov	a,@r0
	jb6	L0215
L0231:			
	orl	a,#040H
	anl	a,#0FEH
	mov	@r0,a
	anl	p2,#07FH
	jmp	L024A

L023A:
	mov	r0,#061H
	mov	a,@r0
	cpl	a
	jb6	L024C
	mov	r0,#07FH
	mov	a,@r0
	jz	L024C
	clr	a
	mov	@r0,a
	mov	r0,#060H
	mov	@r0,a
L024A:
	call	L0255
L024C:
	mov	r0,#027H	;check key row 7 state
	mov	a,@r0
	jb7	L0253		;if bit 7 is set, must be Mono/Poly
	jmp	L0051
L0253:
	jmp	L07D6		;jump to tune pts jumper code


L0255:
	mov	r0,#029H
	mov	a,@r0
	mov	r0,#03FH
	mov	r1,#03DH
	jb3	L026C		;jump if arp up/dn mode
	jb2	L0270		;jump if arp dn mode
	mov	@r1,#000H
	dec	r1
	mov	@r1,#005H
	mov	@r0,#027H
	dec	r0
	mov	@r0,#080H
	jmp	L027A

L026C:
	mov	@r1,#0FFH
	jmp	L0272

L0270:
	mov	@r1,#0FFH
L0272:
	dec	r1
	mov	@r1,#000H
	mov	@r0,#020H
	dec	r0
	mov	@r0,#001H
L027A:	ret

L027B:
	call	L02BD
L027D:
	clr	f0
	cpl	f0		;set f0
	mov	r0,#07EH
L0281:
	mov	a,@r0		;this code assigns notes in chord mem mode
	mov	r0,#060H	;and in Unison mode
	anl	a,@r0		;AND @r0 (58 or 7E) value with addr 60 value
	mov	@r0,a		;and save it in addr 60

	mov	r0,#05EH	;contains index of highest voice (05)
	mov	a,@r0
	inc	a
	mov	r7,a		;so set r7 to 6 (loop counter)

	mov	r0,#059H
	mov	a,@r0
	mov	r2,a		;get addr 59 (base chord key or unison key) value into r2

	mov	r0,#050H
	mov	r1,#062H
L0293:
	jf0	L029E
	mov	a,@r0		;add 50-55 
	add	a,r2		;to addr 59 value, write sum to 62-67
L0297:
	mov	@r1,a		;but if f0 is set, just put addr 59 value in 62-67
	inc	r0		;(Unison mode)
	inc	r1
	djnz	r7,L0293
	jmp	L06FC

L029E:
	mov	a,r2
	jmp	L0297

L02A1:
	mov	r0,#07DH
	mov	a,@r0
	jz	L02AC
L02A6:
	clr	a
	mov	r0,#060H
	mov	@r0,a
	jmp	L06FC

L02AC:
	mov	r0,#060H
	mov	@r0,#0FFH
	inc	r0
	mov	a,@r0
	jb1	L02B8		;if chord mem LED is on, jump
	jmp	L027D

L02B6:
	call	L02BD
L02B8:
	clr	f0		;seems like not unison mode?
	mov	r0,#058H
	jmp	L0281		;assign chord keys


L02BD:
	call	L03FF		;clr f0, r7=0, addr 0x5A=0, r0=0x20
L02BF:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,@r0		;so loop starts with r0=0x30, r1=0x30
	xrl	a,@r1
	jnz	L02E3		;compare 2x with 3x and jump if not equal
	inc	r0
	inc	r7
	mov	a,r7
	jb3	L02CC		;count from 0-7
	jmp	L02BF

L02CC:
	jf0	L02DE
	mov	r1,#060H
	mov	a,@r1
	xrl	a,#080H
	jnz	L02DE
	inc	r1
	mov	a,@r1
	jb0	L02DB
	jmp	L0310

L02DB:
	dec	r1
	mov	@r1,#0FFH
L02DE:
	ret
L02DF:
	jmp	L033F
L02E1:
	jmp	L0305


L02E3:
	call	L077B		;r2, acc = ((r0 value AND 0x07) << 3) + bitpos of lowest 1 bit in acc
	mov	a,@r0
	anl	a,r3
	jz	L02E1
	jf0	L02FD
	mov	r1,#059H
	mov	a,r2
	mov	@r1,a		;updates 0x59 value in Unison mode
	mov	r1,#060H
	mov	a,@r1
	jb6	L02DF
	mov	@r1,#0FFH
	call	L0351
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,@r1
	orl	a,r3
	mov	@r1,a
L02FD:
	mov	r1,#05AH
	inc	@r1
	mov	a,@r1
	jb2	L0361
	jmp	L02BF

L0305:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,r3
	cpl	a
	anl	a,@r1
	mov	@r1,a
	mov	r1,#061H
	mov	a,@r1
	jb0	L032D		;jump if Hold LED on
L0310:
	mov	r5,#008H
	mov	r6,#000H
L0314:
	mov	a,#040H
	add	a,r6
	mov	r1,a
	mov	a,@r1
	mov	r1,a
	mov	a,@r1
	mov	r2,a
	mov	a,#048H
	add	a,r6
	mov	r1,a
	mov	a,@r1
	anl	a,r2
	jnz	L032F
	inc	r6
	djnz	r5,L0314
	mov	r1,#060H
	mov	@r1,#000H
L032B:
	clr	f0
	cpl	f0		;set f0
L032D:
	jmp	L02FD

L032F:				;label only used 11 lines above
	mov	r2,a
	mov	a,#040H
	add	a,r6
	mov	r1,a
	mov	a,@r1
	mov	r0,a
	mov	a,r2
	call	L077B		;r2, acc = ((r0 value AND 0x07) << 3) + bitpos of lowest 1 bit in acc
	mov	r1,#059H
	mov	a,@r1
	xrl	a,r2
	jz	L032B
L033F:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,r3
	cpl	a
	anl	a,@r1
	mov	@r1,a
	mov	a,r3
	cpl	a
	anl	a,@r0
	mov	@r0,a
	mov	r1,#060H
	mov	a,@r1
	anl	a,#080H
	mov	@r1,a
	jmp	L032B

L0351:
	mov	r5,#008H
	mov	a,r0
	mov	r1,#040H
L0356:
	xch	a,@r1
	inc	r1
	djnz	r5,L0356
	mov	r5,#008H
	mov	a,r3
L035D:
	xch	a,@r1
	inc	r1
	djnz	r5,L035D
L0361:
	ret

L0362:
	call	L03FF		;clr f0, r7=0, addr 0x5A=0, r0=0x20
	mov	r1,#060H
	mov	a,@r1
	jnz	L036C
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	@r1,a
L036C:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,@r0
	xrl	a,@r1
	jnz	L037B
	inc	r0
	inc	r7
	mov	a,r7
	jb3	L0379
	jmp	L036C
L0379:
	jmp	L04D7

L037B:
	call	L077B		;r2, acc = ((r0 value AND 0x07) << 3) + bitpos of lowest 1 bit in acc
	mov	a,@r0
	anl	a,r3
	jz	L03B5
	jf0	L03F5
	mov	r1,#07EH
	mov	a,@r1
	mov	r1,#060H
	xrl	a,@r1
	jz	L039B
	mov	a,@r1
	jb6	L0390
	jmp	L03C7

L0390:
	anl	a,#0BFH
	mov	@r1,a
	mov	a,r3
	cpl	a
	anl	a,@r0
	mov	@r0,a
	clr	f0
	cpl	f0
	jmp	L03F5

L039B:
	call	L07C8		;set r5 to one-bit mask in bit pos of addr 0x5B, next voice to assign (0-5)
	clr	f0
	cpl	f0
	mov	a,r3
	cpl	a
	anl	a,@r0
	mov	@r0,a
	mov	r1,#060H
	mov	a,@r1
	anl	a,#0BFH
	mov	@r1,a
L03A9:
	mov	r1,#060H
	mov	a,r5
	cpl	a
	anl	a,@r1
	mov	@r1,a
	anl	a,#03FH
	jnz	L03F5
	jmp	L03F4

L03B5:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,r3
	cpl	a
	anl	a,@r1
	mov	@r1,a
	mov	r1,#061H
	mov	a,@r1
	jb0	L03F5		;jump if Hold LED on
	call	L07A2
	jmp	L03A9

L03C4:
	mov	@r1,a
	jmp	L03E9

L03C7:
	mov	r5,#001H
	mov	r4,#000H
	mov	a,@r1
	cpl	a
	clr	c
L03CE:
	rrc	a
	jc	L03D7
	xch	a,r5
	rl	a
	xch	a,r5
	inc	r4
	jmp	L03CE

L03D7:
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	a,r4
	mov	@r1,a
	add	a,#062H
	mov	r1,a
	mov	a,r2
	mov	@r1,a
	mov	r1,#05EH	;contains index of highest voice (05)
	mov	a,@r1
	mov	r1,#05BH
	xrl	a,@r1
	jz	L03C4		;if we have already assigned highest voice, jump
	inc	@r1		;otherwise bump nxt voice to assign
L03E9:
	mov	r1,#060H
	mov	a,@r1
	orl	a,r5
	orl	a,#0C0H
	mov	@r1,a
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,@r1
	orl	a,r3
L03F4:
	mov	@r1,a
L03F5:
	mov	r1,#05AH
	inc	@r1
	mov	a,@r1
	jb2	L03FD
	jmp	L036C
L03FD:
	jmp	L06FC


L03FF:				;clr f0, r7=0, addr 0x5A=0, r0=0x20		
	clr	f0
	mov	r7,#000H
	mov	r0,#05AH
	mov	@r0,#000H
	mov	r0,#020H
	ret



L0409:
	call	L03FF		;clr f0, r7=0, addr 0x5A=0, r0=0x20
L040B:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,@r0
	xrl	a,@r1
	jnz	L0418
	inc	r0
	inc	r7
	mov	a,r7
	jb3	L04E3
	jmp	L040B

L0418:
	call	L077B		;r2, acc = ((r0 value AND 0x07) << 3) + bitpos of lowest 1 bit in acc
	mov	a,@r0
	anl	a,r3
	jz	L0446
	jf0	L0436
	mov	r1,#07EH
	mov	a,@r1
	mov	r1,#060H
	xrl	a,@r1
	jz	L0436
	mov	a,@r1
	jb6	L042D
	jmp	L0498

L042D:
	anl	a,#0BFH
	mov	@r1,a
	mov	a,r3
	cpl	a
	anl	a,@r0
	mov	@r0,a
	jmp	L0481

L0436:
	call	L07C8		;set r5 to one-bit mask in bit pos of addr 0x5B, next voice to assign (0-5)
	clr	f0
	cpl	f0
	mov	a,r3
	cpl	a
	anl	a,@r0
	mov	@r0,a
	mov	r1,#060H
	mov	a,@r1
	anl	a,#0BFH
	mov	@r1,a
	jmp	L0453

L0446:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,r3
	cpl	a
	anl	a,@r1
	mov	@r1,a
	mov	r1,#061H
	mov	a,@r1
	jb0	L0481		;jump if Hold LED on
	call	L07A2
L0453:
	mov	r1,#060H
	mov	a,r5
	cpl	a
	anl	a,@r1
	mov	@r1,a
	anl	a,#03FH
	jnz	L0481
	mov	@r1,a
	jmp	L0481

L0460:
	mov	@r1,a
	jmp	L0475

L0463:
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	a,r6
	mov	@r1,a
	add	a,#062H
	mov	r1,a
	mov	a,r2
	mov	@r1,a		;this assigned a note to a voice in normal mode
	mov	r1,#05EH	;contains index of highest voice (05)
	mov	a,@r1
	mov	r1,#05BH
	xrl	a,@r1		;if voice we assigned is highest one, 
	jz	L0460		;jump
	inc	@r1		;otherwise, increment next voice to assign
L0475:
	mov	r1,#060H
	mov	a,@r1
	orl	a,r5
	orl	a,#0C0H
	mov	@r1,a
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,@r1
	orl	a,r3
	mov	@r1,a
L0481:
	mov	r1,#05AH
	inc	@r1
	mov	a,@r1
	jb2	L04E3
	jmp	L040B

L0489:
	mov	r0,#05AH
	mov	@r0,#003H
	mov	r0,#07DH
	mov	a,@r0
	jz	L0494
	jmp	L02A6

L0494:
	mov	r0,#03FH
	mov	a,@r0
	mov	r0,a
L0498:
	mov	r5,#001H
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	a,@r1
	mov	r6,a
	mov	r4,a
L049F:
	mov	a,r4
	jz	L04A8
	mov	a,r5
	rl	a
	mov	r5,a
	dec	r4
	jmp	L049F

L04A8:
	mov	r1,#060H
	mov	a,@r1
	mov	r4,a
	mov	r1,#07EH
L04AE:
	mov	a,r4
	anl	a,r5
	jz	L0463
	rl	a
	mov	r5,a
	inc	r6
	anl	a,@r1
	anl	a,#03FH
	jnz	L04AE
	mov	r5,#001H
	mov	r6,#000H
	jmp	L04AE

L04C0:
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	r0,#060H
	mov	a,@r0
	jnz	L04C8
	mov	@r1,a
L04C8:
	call	L03FF		;clr f0, r7=0, addr 0x5A=0, r0=0x20
L04CA:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,@r0
	xrl	a,@r1
	jnz	L04E5
	inc	r0
	inc	r7
	mov	a,r7
	jb3	L04D7
	jmp	L04CA

L04D7:
	jf0	L04E3
	mov	r0,#060H
	mov	a,@r0
	anl	a,#03FH
	jz	L04E3
	orl	a,#0C0H
	mov	@r0,a
L04E3:
	jmp	L06FC

L04E5:
	call	L077B		;r2, acc = ((r0 value AND 0x07) << 3) + bitpos of lowest 1 bit in acc
	mov	a,r2
	mov	r1,#059H
	mov	@r1,a
	mov	a,@r0
	anl	a,r3
	jnz	L04FA
	mov	r1,#061H
	mov	a,@r1
	jb0	L04F6		;jump if Hold LED on
	jmp	L0590
L04F6:
	jmp	L05B3
L04F8:
	jmp	L05B9

L04FA:
	jf0	L04F8
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	a,@r1
	mov	r6,a
	mov	r1,#060H
	jnz	L0506
	jmp	L050E

L0506:
	djnz	r6,L050A
	jmp	L051B

L050A:
	djnz	r6,L0576
	jmp	L054C

L050E:
	mov	@r1,#0CFH
	mov	a,r2
	mov	r1,#062H
	mov	r4,#004H
L0515:
	mov	@r1,a
	inc	r1
	djnz	r4,L0515
	jmp	L052B

L051B:
	mov	a,@r1
	jb6	L0540
	jb0	L0539
	jb1	L0539
	orl	a,#0C3H
	mov	@r1,a
	mov	r1,#062H
L0527:
	mov	a,r2
	mov	@r1,a
	inc	r1
	mov	@r1,a
L052B:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,@r1
	orl	a,r3
	mov	@r1,a
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	a,@r1
	cpl	a
	jz	L05B9
	inc	@r1
	jmp	L05B9

L0539:
	orl	a,#0CCH
	mov	@r1,a
	mov	r1,#064H
	jmp	L0527

L0540:
	jb2	L0548
	jb3	L0548
	anl	a,#0F3H
	jmp	L0585

L0548:
	anl	a,#0FCH
	jmp	L0585

L054C:
	mov	a,@r1
	jb6	L056D
L054F:
	mov	r5,#001H
	mov	r1,#062H
	mov	r6,#004H
	anl	a,#00FH
	mov	r4,a
L0558:
	mov	a,r4
	anl	a,r5
	jz	L0562
	mov	a,r5
	rl	a
	mov	r5,a
	inc	r1
	djnz	r6,L0558
L0562:
	mov	a,r2
	mov	@r1,a
	mov	r1,#060H
	mov	a,@r1
	orl	a,r5
	orl	a,#0C0H
	mov	@r1,a
	jmp	L052B

L056D:
	xrl	a,#0CFH
	jnz	L0584
	mov	a,@r1
	anl	a,#0C6H
	jmp	L0585

L0576:
	mov	a,@r1
	jb6	L057B
	jmp	L054F

L057B:
	xrl	a,#0CFH
	jnz	L0584
	mov	a,@r1
	anl	a,#0FEH
	jmp	L0585

L0584:
	mov	a,@r1
L0585:
	anl	a,#0BFH
	mov	@r1,a
	mov	a,r3
	cpl	a
	anl	a,@r0
	mov	@r0,a
	clr	f0
	cpl	f0
	jmp	L05B9

L0590:
	mov	r1,#062H
	mov	r5,#000H
	mov	r4,#001H
	mov	r6,#004H
L0598:
	mov	a,@r1
	xrl	a,r2
	jnz	L059F
	mov	a,r5
	orl	a,r4
	mov	r5,a
L059F:
	mov	a,r4
	rl	a
	mov	r4,a
	inc	r1
	djnz	r6,L0598
	mov	r1,#060H
	mov	a,r5
	cpl	a
	anl	a,@r1
	mov	@r1,a
	anl	a,#00FH
	jnz	L05C3
	mov	@r1,a
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	@r1,a
L05B3:
	call	L00DE		;add 0x10 to addr in r0, copy to r1
	mov	a,r3
	cpl	a
	anl	a,@r1
	mov	@r1,a
L05B9:
	mov	r1,#05AH
	inc	@r1
	mov	a,@r1
	jb2	L05C1
	jmp	L04CA
L05C1:
	jmp	L06FC

L05C3:
	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation
	mov	a,@r1
	dec	a
	mov	@r1,a
	jmp	L05B3

L05CA:
	clr	f0
	mov	r0,#03DH
	mov	r1,#029H
	mov	a,@r1
	jb2	L05D6		;jump if arp dn mode
	jb4	L05DA		;jump if arp up mode
	jmp	L05DC

L05D6:
	mov	@r0,#0FFH
	jmp	L05DC

L05DA:
	mov	@r0,#000H
L05DC:
	dec	r0
	jb5	L05E3
	jb6	L05E7
	jmp	L05EB

L05E3:
	mov	@r0,#000H
	jmp	L05EB

L05E7:
	mov	a,@r0
	anl	a,#001H
	mov	@r0,a
L05EB:
	inc	r0
	mov	a,@r0
L05ED:
	jz	L05F1
	jmp	L0622

L05F1:
	mov	r0,#03FH
	mov	a,@r0
	mov	r0,a
	mov	r1,#03EH
	mov	a,@r1
	clr	c
	rlc	a
	jnc	L05FE
	jmp	L0603

L05FE:
	mov	r3,a
L05FF:
	clr	c
	mov	a,@r0
	jnz	L060D
L0603:
	inc	r0
	mov	r3,#001H
	mov	a,r0
	xrl	a,#028H
	jz	L0678
	jmp	L05FF

L060D:
	mov	a,@r0
	anl	a,r3
	jnz	L0618		;save key row and bit of last note we sent out
	mov	a,r3
	rlc	a
	jc	L0603
	mov	r3,a
	jmp	L060D

L0618:				;save key row and bit of last note we sent out
	mov	a,r0
	mov	r0,#03FH	;3F: mask of keystate bit corresponding to
	mov	@r0,a		;last arp note we sent out	 	
	mov	r0,#03EH
	mov	a,r3		;3E: low bits point to keyrow of last arp
	mov	@r0,a		;note we sent out				
	jmp	L063D

L0622:
	mov	r0,#03FH
	mov	a,@r0
	mov	r0,a
	mov	r1,#03EH
	mov	a,@r1
	clr	c
	rrc	a
	jc	L0670
	mov	r3,a
L062E:
	clr	c
	mov	a,@r0
	jz	L0670
L0632:
	mov	a,@r0
	anl	a,r3
	jnz	L0618
	mov	a,r3
	rrc	a
	jc	L0670
	mov	r3,a
	jmp	L0632

L063D:
	mov	r0,#03FH
	mov	a,@r0
	mov	r0,a
	mov	r1,#03EH
	mov	a,@r1
	call	L077B		;r2, acc = ((r0 value AND 0x07) << 3) + bitpos of lowest 1 bit in acc
	mov	r1,#03CH	;3C holds current octave for arp note playing (0-4)
	mov	a,@r1
	inc	a
	mov	r6,a
	mov	a,r2
L064C:
	djnz	r6,L066C
	mov	r2,a
	mov	r1,#059H
	mov	a,r2
	mov	@r1,a
	clr	c
	add	a,#0C3H
	jc	L065C
	anl	p2,#07FH
	jmp	L0060

L065C:
	mov	r0,#029H
	mov	a,@r0
	mov	r0,#03FH
	mov	r1,#03DH
	clr	f0
	jb4	L067B		;jump if arp up mode
	jb2	L0622		;jump if arp down mode
	mov	a,@r1
	mov	@r1,a
	jmp	L05ED

L066C:
	add	a,#00CH
	jmp	L064C

L0670:
	dec	r0
	mov	r3,#080H
	mov	a,r0
	xrl	a,#01FH
	jnz	L062E
L0678:
	jf0	L06EE
	cpl	f0
L067B:
	mov	r0,#029H
	mov	r1,#03CH	;3C holds current octave for arp note playing (0-4)
	mov	a,@r0
	jb5	L0699		;jump if arp one oct mode
	mov	r1,#03DH
	mov	a,@r1
	jnz	L06A2
	mov	r1,#03CH	;3C holds current octave for arp note playing (0-4)
	mov	a,@r0
	jb6	L069D		;jump if arp two oct mode
	mov	a,@r1
	xrl	a,#005H
	jz	L0696
L0691:
	inc	@r1
	mov	r0,#03FH
	jmp	L06D4

L0696:
	mov	a,@r0
	jb3	L06C4		;jump if up/dn mode
L0699:
	mov	@r1,#000H
	jmp	L06C4

L069D:
	mov	a,@r1
	jnz	L0696
	jmp	L0691

L06A2:
	mov	a,@r0
	cpl	a
	jb6	L06AD
	mov	r1,#03CH	;3C holds current octave for arp note playing (0-4)
	mov	a,@r1
	anl	a,#001H
	jmp	L06B0

L06AD:
	mov	r1,#03CH	;3C holds current octave for arp note playing (0-4)
	mov	a,@r1
L06B0:
	jz	L06B8
	dec	a
	mov	@r1,a
	mov	r0,#03FH
	jmp	L06E2

L06B8:
	mov	r0,#029H
	mov	a,@r0
	jb3	L06C4		;jump if arp up/dn mode
	jb7	L06C2		;jump if arp full mode
	inc	@r1
	jmp	L06C4

L06C2:
	mov	@r1,#005H
L06C4:
	mov	r0,#029H
	mov	r1,#03DH
	mov	a,@r0
	mov	r0,#03FH
	jb4	L06D2		;jump if arp up mode
	jb2	L06E0		;jump if arp dn mode
	mov	a,@r1		;so must be up/dn
	jz	L06E0
L06D2:
	mov	@r1,#000H	;set ARP dir to up
L06D4:
	mov	@r0,#020H
	mov	a,@r0
	mov	r0,a
	mov	r1,#03EH
	mov	@r1,#001H
	mov	r3,#001H
	jmp	L05FF

L06E0:
	mov	@r1,#0FFH	;set ARP dir to down
L06E2:
	mov	@r0,#027H
	mov	a,@r0
	mov	r0,a
	mov	r1,#03EH
	mov	@r1,#080H
	mov	r3,#080H
	jmp	L062E

L06EE:
	mov	r0,#060H
	mov	@r0,#000H
	jmp	L0729

L06F4:
	mov	r1,#059H
	mov	a,@r1
	mov	r1,#06BH
	mov	@r1,a
	jmp	L0729

L06FC:
	mov	r0,#062H
	mov	r4,#001H
	mov	r5,#000H
	mov	r1,#061H
	mov	a,@r1
	jb1	L073C		;jump if Chord mem LED is on
	jb2	L073C		;jump if Unison LED is on

	mov	r1,#05EH	;contains index of highest voice (05)
	mov	a,@r1
	inc	a
	mov	r7,a		;so set r7 to 06 (loop ctr)
		
	mov	r1,#060H
	mov	a,@r1
	jz	L0729
L0713:
	mov	a,@r1
	anl	a,r4
	jz	L071F
	clr	c
	mov	a,r5
	cpl	a
	add	a,@r0
	jnc	L071F
	mov	a,@r0
	mov	r5,a
L071F:
	inc	r0
	mov	a,r4
	rl	a
	mov	r4,a
	djnz	r7,L0713

	mov	r1,#06BH
	mov	a,r5
	mov	@r1,a
L0729:
	clr	f0
	mov	r6,#000H	;clear r6
	mov	r0,#028H
	mov	a,@r0
	jb6	L0732		;jump if Mono/Poly
	cpl	f0
L0732:
	jnt0	L0738		;if 8', jump
	jnt1	L073E		;if 4', jump 
	jmp	L0740

L0738:
	mov	r6,#00CH	;8', load r6 with 12 dec
	jmp	L0740
L073C:
	jmp	L06F4

L073E:
	mov	r6,#018H	;4', load r6 with 24 dec
L0740:
	mov	r0,#060H
	mov	r1,#070H
	mov	a,@r0
	mov	@r1,a
	inc	r0
	inc	r1
	mov	a,@r0
	mov	@r1,a
	inc	r0
	inc	r1

	mov	r4,#00AH	;loop counter
L074E:
	mov	a,@r0
	add	a,r6		;add octave offset to ten note numbers
	jf0	L0772		;from 62 to 6B
L0752:
	mov	@r1,a		;and store them from 72 to 7B
	inc	r0
	inc	r1
	djnz	r4,L074E

	mov	r0,#028H
	mov	r1,#038H
	mov	a,@r0
	mov	@r1,a
	mov	r0,#07DH
	mov	a,@r0
	jnz	L0766
	dec	r0
	mov	@r0,a
	jmp	L076B

L0766:
	mov	@r0,#000H
	dec	r0
	mov	@r0,#0FFH
L076B:
	clr	f1
	cpl	f1		;set f1 so we wait for interrupt
	jmp	L0045		;jump back to wait loop



L076F:
	mov	a,r2
	add	a,#0F4H
L0772:
	mov	r2,a
	clr	c
	add	a,#0ABH
	jc	L076F
	mov	a,r2
	jmp	L0752


				;input values are acc, r0
				;on exit:
L077B:	mov	r2,#000H	;r2, acc = ((r0 value AND 0x07) << 3) + bitpos of lowest 1 bit in acc
	mov	r3,#001H	;value when called
	clr	c
L0780:
	rrc	a
	jc	L0789
	inc	r2

	xch	a,r3		;rotate r3 mask left one
	rl	a
	xch	a,r3

	jmp	L0780

L0789:	mov	a,r0		;at this pt, r2 pts to rightmost 1 bit in acc value
	anl	a,#007H		;and 3 is bitmask for same bit position
	rl	a
	rl	a
	rl	a		;shift low 3 bits of r0 value left three
	add	a,r2		;and add in r2 bit index
	mov	r2,a		;save that in r2
	mov	a,#028H
	xch	a,r0		;put 0x28 in r0, save r0 value

	xch	a,@r0		;check for Mono/Poly strap
	jb6	L079B		;if present, jump		
	xch	a,@r0		;

	xch	a,r0		;restore r0, 0x28 back in acc
	mov	a,r2		;get r2 result value into acc
	ret

L079B:	xch	a,@r0		;Mono/Poly code
	xch	a,r0
	mov	a,r2
	add	a,#005H
	mov	r2,a
	ret



L07A2:	mov	r1,#05EH	;contains index of highest voice (05)
	mov	a,@r1
	add	a,#002H
	mov	r6,a		;so set r6 to 07

	mov	r1,#062H
	mov	r5,#001H
L07AC:
	djnz	r6,L07B1
	mov	r5,#000H
	ret

L07B1:	mov	a,@r1
	xrl	a,r2
	jnz	L07C2
	mov	a,r1
	mov	r4,a
	mov	r1,#060H
	mov	a,@r1
	anl	a,r5
	jz	L07C0
	mov	a,r4
	mov	r1,a
	ret

L07C0:	mov	a,r4
	mov	r1,a
L07C2:
	mov	a,r5
	rl	a
	mov	r5,a
	inc	r1
	jmp	L07AC


				;set r5 to one-bit mask in bit pos of addr 0x5B, next voice to assign (0-5)
L07C8:	mov	r1,#05BH	;addr 5B points to next vce to be used in rotation (0-5)
	mov	r5,#001H
	mov	a,@r1
	mov	r6,a		;loop ctr
	jz	L07D5
L07D0:
	mov	a,r5
	rl	a
	mov	r5,a
	djnz	r6,L07D0
L07D5:	ret



L07D6:
	dis	tcnti
L07D7:				;jump here if tune pts jumper installed
	jnt1	L07E2		;then look at 4' and 8' inputs
	jnt0	L07DE
	clr	a
	jmp	L07E4

L07DE:
	mov	a,#03FH		;and write different values to the DAC
	jmp	L07E4

L07E2:
	mov	a,#07FH		;based on octave switch
L07E4:
	outl	bus,a
	nop
	anl	p2,#098H
	mov	r7,#00FH
L07EA:
	mov	r6,#0FFH
L07EC:
	djnz	r6,L07EC
	djnz	r7,L07EA
	orl	p2,#063H

	mov	a,#07FH
	outl	bus,a		;clear DB7 output
	nop
	in	a,p1
	cpl	a
	jb7	L07D7		;jump if Tune Pts jumper installed
	jmp	L0000

	mov	a,r4
	sel	mb0
	jmp	L00FF

	.end
