NO_KEY = $FF
END_OF_KEYS = NO_KEY

handleKeyboard
	jsr getKey
	cmp #NO_KEY
	bne handleKeyboard1
	rts
handleKeyboard1
	jsr getToggleWaveKeyIndex
	beq handleKeyboard2
	inc voiceControlX,X
	lda voiceControlX,X
	cmp #3
	bcc handleKeyboard1a
	lda #0
	sta voiceControlX,X
handleKeyboard1a
	inc syncWithPoly4Flag
	jmp rfshWave
handleKeyboard2
	jsr getIncAudFKeyIndex
	beq handleKeyboard3
	inc vAudFx,X
	inc syncWithPoly4Flag
	jmp rfshAudF
handleKeyboard3
	jsr getDecAudFKeyIndex
	beq handleKeyboard4
	dec vAudFx,X
	inc syncWithPoly4Flag
	jmp rfshAudF
handleKeyboard4
	jsr getIncSmpShfKeyIndex
	beq handleKeyboard5
	inc poly4SyncPointX,X
	lda poly4SyncPointX,X
	cmp #15
	bcc handleKeyboard4a
	lda #0
	sta poly4SyncPointX,X
handleKeyboard4a
	inc syncWithPoly4Flag
	jmp rfshSmpShf
handleKeyboard5
	jsr getDecSmpShfKeyIndex
	beq handleKeyboard6
	dec poly4SyncPointX,X
	bpl handleKeyboard5a
	lda #14
	sta poly4SyncPointX,X
handleKeyboard5a
	inc syncWithPoly4Flag
	jmp rfshSmpShf
handleKeyboard6
	jsr getIncSmpShfBy3KeyIndex
	beq handleKeyboard7
	lda poly4SyncPointX,X
	clc
	adc #3
	cmp #15
	bcc handleKeyboard6a
	sbc #15
handleKeyboard6a
	sta poly4SyncPointX,X
	inc syncWithPoly4Flag
	jmp rfshSmpShf
handleKeyboard7
	jsr handlePianoKeys
	beq handleKeyboard12
	rts
handleKeyboard12
	cmp #KEY_P
	bne handleKeyboard13
	lda vAudCtl
	eor #$01 ; switch base clock: 0 = 64kHz, 1 = 15kHz
	sta vAudCtl
	inc syncWithPoly4Flag
	jmp rfshBaseClk
handleKeyboard13
	cmp #KEY_L
	bne handleKeyboard14
	lda syncWithPoly4MasterFlag
	eor #$01 ; switch on/off synchronization after change of divisor, sampling shift or base clock
	sta syncWithPoly4MasterFlag
	jmp rfshSync
handleKeyboard14
	cmp #KEY_O
	bne handleKeyboard15
	inc octave
	lda octave
	cmp #6
	bcc handleKeyboard14a
	lda #1
	sta octave
handleKeyboard14a
	jmp rfshOctave
handleKeyboard15
	cmp #KEY_O + KEY_CONTROL
	bne handleKeyboard16
	dec octave
	lda octave
	cmp #1
	bcs handleKeyboard15a
	lda #5
	sta octave
handleKeyboard15a
	jmp rfshOctave
handleKeyboard16
	cmp #KEY_9
	bne handleKeyboard17
	lda scale
	eor #$01
	sta scale
	jmp rfshScale
handleKeyboard17
	cmp #KEY_0 ; zero
	bne handleKeyboard18
	lda continuousPhaseMod
	eor #$01
	sta continuousPhaseMod
handleKeyboard18
	rts


getToggleWaveKeyIndex
	ldx >toggleWaveKeys
	ldy <toggleWaveKeys
	jmp getInGroupKeyIndex

toggleWaveKeys
	.db	KEY_1, KEY_2, KEY_3, KEY_4, END_OF_KEYS

getIncAudFKeyIndex
	ldx >incAudFKeys
	ldy <incAudFKeys
	jmp getInGroupKeyIndex

incAudFKeys
	.db	KEY_Q, KEY_W, KEY_E, KEY_R, END_OF_KEYS

getDecAudFKeyIndex
	ldx >decAudFKeys
	ldy <decAudFKeys
	jmp getInGroupKeyIndex

decAudFKeys
	.db	KEY_A, KEY_S, KEY_D, KEY_F, END_OF_KEYS

getIncSmpShfKeyIndex
	ldx >incSmpShfKeys
	ldy <incSmpShfKeys
	jmp getInGroupKeyIndex

incSmpShfKeys
	.db	KEY_T, KEY_Y, KEY_U, KEY_I, END_OF_KEYS

getDecSmpShfKeyIndex
	ldx >decSmpShfKeys
	ldy <decSmpShfKeys
	jmp getInGroupKeyIndex

decSmpShfKeys
	.db	KEY_G, KEY_H, KEY_J, KEY_K, END_OF_KEYS

getIncSmpShfBy3KeyIndex
	ldx >incSmpShfBy3Keys
	ldy <incSmpShfBy3Keys
	jmp getInGroupKeyIndex

incSmpShfBy3Keys
	.db	KEY_5, KEY_6, KEY_7, KEY_8, END_OF_KEYS

getDiatonicNoteKeyIndex
	ldx >diatonicNoteKeys
	ldy <diatonicNoteKeys
	jmp getInGroupKeyIndex

diatonicNoteKeys
	.db KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, END_OF_KEYS

getNoteKeyIndex
	ldx >noteKeys
	ldy <noteKeys
	jmp getInGroupKeyIndex

noteKeys
	.db	KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_N, KEY_M, KEY_COMMA, KEY_DOT, KEY_SLASH, KEY_SEMICOLON, KEY_MINUS, KEY_EQUALS, END_OF_KEYS

handlePianoKeys
	ldx scale
	bne hndPianKey1
	; handle keys for diatonic scale
	jsr getDiatonicNoteKeyIndex
	beq hndPianKey3
	; calculate octave * 8 + key index
	lda octave
	sec
	sbc #1
	asl
	asl
	asl
	sta temp0
	txa
	clc
	adc temp0
	tax
	lda diaNoteDiv,X
	sta vAudF1
	sta vAudF2
	sta vAudF3
	sta vAudF4
	ldy diaNoteWave,X
	jmp hndPianKey2
hndPianKey1
	; handle keys for chromatic (full) scale
	jsr getNoteKeyIndex
	beq hndPianKey3
	; calculate octave * 16 + key index
	lda octave
	sec
	sbc #1
	asl
	asl
	asl
	asl
	sta temp0
	txa
	clc
	adc temp0
	tax
	lda noteDiv,X
	sta vAudF1
	sta vAudF2
	sta vAudF3
	sta vAudF4
	ldy noteWave,X
hndPianKey2
	;sta voiceControlX+2 ; turn on channel 3
	jsr updateWaveOfTurnedOnChannels
	inc syncWithPoly4Flag
	lda vAudCtl
	and #$FE
	sta vAudCtl ; switch base clock to 64kHz
	jsr rfshAllChnWaveAudF
	jsr rfshBaseClk
	ldx #1 ; signal that key has been found (set Z = 0)
hndPianKey3
	rts

; input:
;	Y: wave id
updateWaveOfTurnedOnChannels
	lda #VoiceOff
	cmp voiceControlX
	beq updWavTrOnChn1
	sty voiceControlX
updWavTrOnChn1
	cmp voiceControlX+1
	beq updWavTrOnChn2
	sty voiceControlX+1
updWavTrOnChn2
	cmp voiceControlX+2
	beq updWavTrOnChn3
	sty voiceControlX+2
updWavTrOnChn3
	cmp voiceControlX+3
	beq updWavTrOnChn4
	sty voiceControlX+3
updWavTrOnChn4
	rts


; returns 0-based index of key in given group or NO_KEY ($FF) if not found
; value of ACC is preserved
; input:
;	ACC: number key value
;	X: key group table MSB
;	Y: key group table LSB
; output:
;	X: 0-based index of key in given group or NO_KEY ($FF) if not found
;	Z: 0 = key found, 1 = key not found; use bne to branch if key found
getInGroupKeyIndex
	sta getIGrpKIdxVal
	sty getIGrpKIdxGrpPtr
	stx getIGrpKIdxGrpPtr + 1
	ldx #0
getIGrpKIdx1
getIGrpKIdxGrpPtr = * + 1
	lda $1000,X
	cmp #END_OF_KEYS
	beq getIGrpKIdx2
	cmp getIGrpKIdxVal
	beq getIGrpKIdx3
	inx
	bne getIGrpKIdx1 ;branch always
getIGrpKIdx2
	tax ;NO_KEY -> A as NO_KEY = END_OF_KEYS
getIGrpKIdx3
	lda getIGrpKIdxVal ;restore ACC
	cpx #NO_KEY ; set Z bit's output value
	rts

getIGrpKIdxVal
	.db 0


getKey
	;handle debouncing to avoid too fast receiving different keys (this may happen after resetting POKEY because of temporary lack of debouncing)
	lda debouncingCnt
	beq kbdHnd8
	dec debouncingCnt
	jmp kbdHnd9
kbdHnd8:
	;test regular keys
	lda skstat    ;test if any key pressed
	and #$04
	beq kbdHnd10
	lda #NO_KEY
	sta lastKey
kbdHnd9:
	lda #NO_KEY
	rts
kbdHnd10:
	;handle regular keys
	lda kbcode
	tax
	cmp lastKey
	bne kbdHnd11
	lda repetitionDelay
	;beq kbdHnd10a ;no repetition
	beq kbdHnd10b
	dec repetitionDelay
kbdHnd10a:
	jmp kbdHnd9
kbdHnd10b:
	lda #$04
	bne kbdHnd11b
	;lda #$00
	;beq kbdHnd11b
kbdHnd11:
	lda #$14
kbdHnd11b:
	sta repetitionDelay
	txa
	sta lastKey
	rts

repetitionDelay	.db 0
lastKey	.db 0
debouncingCnt .db 0

;activates one frame long debouncing to avoid too fast receiving different keys (this may happen after resetting POKEY because of temporary lack of debouncing)
activateKeyDebouncing
	lda #1
	sta debouncingCnt
	rts

