📄 keyboard_band.txt
字号:
;这是一个电子琴的力度键盘程序,每个键有两个点,程序的要求就是测试出两个点之间的时间差,并转换成音量数值(0-7f,转换表未附)。请注意,这个程序是有版权的。请勿使用于商业用途。
; ***********************************************************************
; * 8051 Velocity Keyscan Software *
; * *
; * (c) Richard Watts Associates 1991 *
; * DavB & MarkP 22-05-91 *
; * Updated SteveH 8-05-96 *
; ***********************************************************************
; This is for a keyboard with 88 keys with 12 scan lines and 16 return lines.
; Written for Evolution eKeys keyboard
; Switch pairs are read back in two cycles:
; First 8 upper (early)
; Second 8 lower (late)
; This version scans up the rows from P0.0 to P3.7
; This Software Implements Four State Machine For Each Key
;
; State Key Position UpperKey LowerKey
; ----- ------------ -------- --------
; [A] Key Fully Up Off Off
; [B] Key Going Down On Off
; [C] Key Fully Down On On
; [D] Key Going Up On Off
; Sequential Truth Table For Switch States
;
; |-------|-----|----------------------|---------------|---------------|
; | State | U L | Action | Counter State | Message Xfer |
; |-------|-----|----------------------|---------------|---------------|
; | A | 0 0 | Goto State [C] | Min Counter | Send Note On |
; | A | 0 1 | Goto State [B] | Capture | |
; | A | 1 0 | Nop | | | This is possible with upper and lower read on seperate cycles
; | A | 1 1 | Nop | | |
; |-------|-----|----------------------|---------------|---------------|
; | B | 0 0 | Goto State [C] | Compare | Send Note On |
; | B | 0 1 | Nop | | |
; | B | 1 0 | Illegal | | Send Error |
; | B | 1 1 | Goto State [A] | Reset | |
; |-------|-----|----------------------|---------------|---------------|
; | C | 0 0 | Nop | | |
; | C | 0 1 | Goto State [D] | | |
; | C | 1 0 | Illegal | | Send error |
; | C | 1 1 | Goto State [A] | Reset | Send Note Off |
; |-------|-----|----------------------|---------------|---------------|
; | D | 0 0 | Nop | | |
; | D | 0 1 | Nop | | |
; | D | 1 0 | Illegal | | Send Error |
; | D | 1 1 | Goto State [A] | Reset | Send Note Off |
; |-------|-----|----------------------|---------------|---------------|
;
; Notes:
; 1) Keys Have Inverse Logic ie KeyUp = 1
; 2) Key Debounce Handled By 'loops' in state diagram
; 3) Error Condition Flags Upper Bus Defective
;
; Output Format
; Data is sent as handshaked single bytes on Port 0
; A. Vel IC sets IRQ line from 1 to 0
; B. Wait for Control IC to set ST9_ACK from 1 to 0.
; C. Vel IC puts data on the bus, then sets IRQ from 0 to 1.
; D. Wait for Control IC to set ST9_ACK from 0 to 1.
;
; Data Byte Format
; 00-7F Velocity value based on selected curve
; 98-F5 Note number lowest note = 20 (needs translation by reciever to make into MIDI note)
; F6-FE Velcoity curve number
; Error Condition if MSB is set on 2 consecutive bytes.
; With Byte 2 As Error number
;
; Velocity Curve
; There are 10 curves to choose from. When VEL_CURVE pin is set (0 to 1).
; the curve number is incremented. Then Vel IC send curve num (F6-FE)
; corresponding to vel curves 0-9.
;EXTRN DATA (RCAP2L, RCAP2H, T2CON)
;EXTRN BIT (TF2)
;;;;;;
;
; BYTE Registers
; 8052 Extensions
T2CON DATA 0C8H
RCAP2L DATA 0CAH
RCAP2H DATA 0CBH
; T2CON
TF2 BIT 0CFH
;;;;;;
KEY_OUT_H_BITS equ 11110000b ; Used to set bits P3.4-7
KeyOut_H equ P3 ; Row Select lines 8-11 (P3.4-7)
KeyOut_L equ P1 ; Row Select lines 0-7
KeyIn_L equ P0 ; U0 U1 U2 U3 U4 U5 U6 U7 followed by L0 L1 L2 L3 L4 L5 L6 L7
KeyIn_H equ P2 ; U8 U9 U10 U11 U12 U13 U14 U15 followed by L8 L9 L10 L11 L12 L13 L14 L15
DataOut equ P0 ; Data sent on same port as keys read
ST9_ACK equ P3.3 ; Request Acknowledge From ST9
VEL_IRQ equ P3.1 ; Velocity interrupt to ST9
VEL_CURVE equ P3.2 ; Request new velcity curve
StateA equ 00000000b ; State Definitions
StateB equ 01000000b
StateC equ 10000000b
StateD equ 11000000b
LOWESTNOTE equ 24 ; Lowest note = C 0
NOTE_0 equ 20 ; Initial note returned from velocity keys
NOTES equ 88 ; 88 notes available
COUNTER equ 200 ; Counter reload value
ROWS_L equ 10 ; Number of rows on lower half of the keybed
ROWS_H equ 12 ; Number of rows on upper half of the keybed
ROW_0 equ 07FFFh ; Initial row select
NOTE_FLAG_ equ 7 ; Note data has MSB set
NOTE_FLAG equ 080h ; Note data has MSB set
NOTE_OFF equ 0 ; Velocity value for note off
DEF_VEL_CURVE equ 0 ; Default Velocity curve
VEL_CURVE_0 equ 0F6h ; Initial Velocity curve
VEL_CURVES equ 10 ; Number of velocity curves
DSEG AT 8
KeyInUpper: ds 1 ; Store for current switch high
KeyInLower: ds 1 ; Store for current switch low
RowIdx: ds 1 ; Offset into RowSelectTab
VelCurve: ds 1 ; Velocity Curve
ISEG AT 12
StackLocation: ds 8
; Allow room for 88 notes
ISEG AT NOTE_0
CountersHIGH: ds NOTES ; Bits 0-5 timer : Bits 6-7 KeyStatus
OldKeyStatUPPER: ds NOTES/8 ; Storage for previous key state Upper
ISEG AT NOTE_0+80h
CountersLOW: ds NOTES ; 8 bit captured timer value
OldKeyStatLOWER: ds NOTES/8 ; Storage for previous key state Lower
; Register Usage
; [ACC] General Purpose
; [B] Bit addressable temp for key input
; [R0] Points key counter HIGH : State flags
; [R1] Points previous row status
; [R2] Row Counter
; [R3] Captured Timer HIGH
; [R4] Captured Timer LOW
; [R5] Temp timer LOW
; [R6] Event timer HIGH
; [R7] Event timer LOW
; [DPTR] Nearly always points to Jump table start
; No Action In Jump Table ie Returns
NOACTION MACRO
db 022h,022h
ENDM
; Macro To Update State Of A Key
TestKey MACRO KeyNumber
mov a,@R0 ; Get previous key status
mov b,KeyInUpper
mov c,b.KeyNumber ; Get Upper into [A.5]
mov ACC.5,c
mov b,KeyInLower
mov c,b.Keynumber ; Get Lower into [A.4]
mov ACC.4,c
acall HandleState
ENDM
; Macro to select next scan row
NEXT_ROW MACRO
push ACC
mov a,RowIdx ;Get offset into row select
movc a,@a+dptr ;Get value from RowSelectTab
orl KeyOut_H,#KEY_OUT_H_BITS
anl KeyOut_H,a
; mov KeyOut_H,a
inc RowIdx
mov a,RowIdx ;Get offset into row select
movc a,@a+dptr ;Get value from RowSelectTab
mov KeyOut_L,a
inc RowIdx
pop ACC
ENDM
; Write value in [ACC] to [DataOut]
; This uses a polling method to wait for serial ready.
TX MACRO
LOCAL WaitAckClr, WaitAckSet
jnb ST9_ACK,$ ;Ensure ST9 has finished reading previous byte
clr VEL_IRQ ;Generate IRQ on the ST9
jb ST9_ACK,$ ;Wait for ST9 to respond to IRQ & set ACK low
mov DataOut,a ;Put data on the bus
setb VEL_IRQ ;Flag data is ready to read.
ENDM
CSEG AT 0
USING 0
VEL_A:
ljmp ProgSt ; Reset
ljmp ProgSt ; Power Down Interupt
db 'R-W-A'
ljmp ProgSt ; TF0
db 'R-W-A'
ljmp ProgSt ; IE1
db 'R-W-A'
ljmp ProgSt ; TF1
db 'R-W-A'
ljmp ProgSt ; Serial
db 'R-W-A'
; Timer 2 used to update SW counter
; [r6] is decremented when [r7]=1, so timer has offset of 1
; code which reads the timer takes this into account
clr TF2 ; Reset Timer 2 IRQ
djnz r7,ExitIRQ
dec r6
anl AR6,#00111111b
ExitIrq: reti
db '88-Note Velocity Keyscan Processor : '
db '(c) Evolution Electronics Ltd. : May 91 : '
db 'Version 1.6 : 22-Apr-04 : '
;----------------------------------------------------
;***** REAL CODE STARTS HERE *****
;----------------------------------------------------
ProgSt: mov IE,#0 ; Kill interupts
mov PSW,#0 ; For Emulator Restart
mov SP,#StackLocation-1 ; Set up stack pointer
mov KeyIn_L,#0FFh ; Config Key return lines as Input
mov KeyIn_H,#0FFh ; Config Key return lines as Input
mov P3,#0FFh ; Set VEL_IRQ high, set other port bits as Input
mov VelCurve,#DEF_VEL_CURVE ; Set initial velocity curve
mov r0,#OldKeyStatUpper ; Assume previous keys off
mov r2,#NOTES/8
InitOldKeyUpper:mov @r0,#0FFh
inc r0
djnz r2,InitOldKeyUpper
mov r0,#OldKeyStatLower ; Assume previous keys off
mov r2,#NOTES/8
InitOldKeyLower:mov @r0,#0FFh
inc r0
djnz r2,InitOldKeyLower
mov r0,#CountersHIGH ; Set all Keys To StateA
mov r1,#CountersLOW
mov r2,#NOTES
InitStateA: mov @r0,#StateA
mov @r1,#0
inc r0
inc r1
djnz r2,InitStateA
mov r6,#0
mov r7,#0
; Serial Mode 2 : 9 bits data : 375 kBits/sec
mov PCON,#80h ;Double Baud rate
mov SCON,#10010000b ;Serial Mode 2
mov T2CON,#00000100b ;Setup timer 2
mov RCAP2H,#HIGH (0 - COUNTER)
mov RCAP2L,#LOW (0 - COUNTER)
; setb TI ;Enable serial XMIT
mov IE,#10100000b ;Start timer2
; setb VEL_IRQ ;Setting IRQ low triggers interrupt on ST9, so start with it high
;***** Main Program Loop
ScanAllKeys: acall IncVelCurve ;Is there a request for a new velocity curve
mov dptr,#RowSelectTab
mov RowIdx,#0 ;Init offset into RowSelectTab
NEXT_ROW ;Select Initial row
mov r2,#ROWS_L/2 ;Init row counter, 2 rows read on each pass
mov r1,#OldKeyStatUpper ;+(NOTES/8)-1
;Capture timer so all notes in chord have same vel
CaptureTimer: mov a,r6
mov AR4,r7
cjne a,AR6,CaptureTimer
mov r3,a
dec r4 ; Allow for offset
; Check Next 8 Keys
; This Code Expanded Inline For Speed , e' spaghetti moltissimo
ScanUpr_L: mov a,KeyIn_L ; Sample new key state upper
NEXT_ROW ; Advance row
anl AR1,#01111111b
xch a,@r1 ; Save new : get old
xrl a,@r1 ; check for changes
jnz ScanLwr_L ; Capture lower if not same
mov a,KeyIn_L ; Sample new key state lower
; NEXT_ROW ; Advance row
mov KeyInLower,a
orl AR1,#10000000b
xch a,@r1 ; Save new : get old
xrl a,@r1 ; check for changes
jnz ProcKeys_L ; Process switches if not the same
jmp Ready4Next_L
ScanLwr_L: mov a,KeyIn_L ; Capture lower if upper different
; NEXT_ROW ; Advance row
orl AR1,#10000000b
mov @r1,a
ProcKeys_L: mov KeyOut_H,#0FFh ; Deselect rows during event processing
mov KeyOut_L,#0FFh
mov a,@r1 ; Get key in values to process
mov KeyInLower,a
anl AR1,#01111111b
mov a,@r1
mov KeyInUpper,a
mov a,r1 ; Calculate key address
add a,#-OldKeyStatUpper ; from Row pointer
swap a ; Multiply by 8
rr a
add a,#CountersHIGH
mov r0,a
TestKey 0 ; Go check keys
inc r0 ; Next Key
TestKey 1
inc r0
TestKey 2
inc r0
TestKey 3
inc r0
TestKey 4
inc r0
TestKey 5
inc r0
TestKey 6
inc r0
TestKey 7
mov dptr,#RowSelectTab ;Reset [dptr] back to RowSelectTab
jnb ST9_ACK,$ ;Ensure ST9 has finished reading previous byte
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -