Процедура попроще:
XOR A
LD (23560),A
LD IY,#5C3A
RST 56
Вешается на прерывания. Последнюю нажатую клавишу можно получить из ячейки по адресу 23560.
По адресам 23561 и 23562 можно изменить задержку опроса клавиш.
Автор процедуры Fyrex/Mayhem.
Процедура попроще:
XOR A
LD (23560),A
LD IY,#5C3A
RST 56
Вешается на прерывания. Последнюю нажатую клавишу можно получить из ячейки по адресу 23560.
По адресам 23561 и 23562 можно изменить задержку опроса клавиш.
Автор процедуры Fyrex/Mayhem.
Немного не то. Нужна с буфером.
Буферизованный опрос клавиатуры, реализованный для ZXDev. Коды клавиш берутся из LAST_K, соответственно, работает автоповтор клавиш. Исходник оформлен для сборки компилятором SDCC.
Вопросы, предложения, критика?Код:#define KeyBufSize 8 // Возвращает количество клавиш в буфере. unsigned char Input_Available (void); // Возвращает код нажатой клавиши. // Если нажатых клавиш нет, ожидает. char Input_Read (void); // Вызывайте из обработчика прерываний IM 2. void Input_RunMe50Hz (void); /*--------------------------------- Cut here ---------------------------------*/ char Input_keyBuf [KeyBufSize]; /* Закономерно считаем, что более актуальны клавиши, нажатые позднее, поэтому при переполнении буфера будем удалять из него нажатые ранее. Эта стратегия кажется более удачной, чем игнорирование всех клавиш, нажатых после переполнения буфера (как в контроллере клавиатуры IBM PC). */ char Input_Read (void) { __asm LOOPrptbuf$: LD HL,#_Input_keysAvailable+1 LD A,(HL) OR A JR Z,LOOPrptbuf$ DEC (HL) .globl _Input_keyOut _Input_keyOut: ; Read a key: LD HL,#_Input_keyBuf ; key := keyBuf[keyOut]; LD C,(HL) INC HL ; keyOut := (keyOut+1) MOD KeyBufSize; LD A,L SUB #<_Input_keyBuf+KeyBufSize JR NZ,Save_keyOut$ LD HL,#_Input_keyBuf Save_keyOut$: LD (_Input_keyOut+1),HL LD L,C ; RETURN key __endasm; } //Input_Read void Input_RunMe50Hz (void) __naked { __asm LD IY,#0x5C3A RST 0x38 BIT 5,1(IY) RET Z RES 5,1(IY) _Input_keyIn: LD HL,#_Input_keyBuf ; Add a key: LD A,-50(IY) ; keyBuf[keyIn] := CHR(keyCode); LD (HL),A INC HL LD A,L SUB #<_Input_keyBuf+KeyBufSize JR NZ,Save_keyIn$ LD HL,#_Input_keyBuf Save_keyIn$: LD (_Input_keyIn+1),HL .globl _Input_keysAvailable _Input_keysAvailable: LD A,#0 ; Check overflow: CP #8 ; IF keysAvailable > 8 THEN keysAvailable := 8 END; ADC #0 LD (_Input_keysAvailable+1),A RET C JR _Input_keyOut __endasm; } //Input_RunMe50Hz /*--------------------------------- Cut here ---------------------------------*/ unsigned char Input_Available (void) { __asm LD HL,(_Input_keysAvailable+1) __endasm; } //Input_Available
В приведённом выше коде есть баг (!). Было:
Стало:Код:.globl _Input_keysAvailable _Input_keysAvailable: LD A,#0 ; Check overflow: CP #8 ; IF keysAvailable > 8 THEN keysAvailable := 8 END; ADC #0 LD (_Input_keysAvailable+1),A RET C JR _Input_keyOut
Баг связан с тем, что не было учтено влияние команды ADC #0 на флаг переноса, и процедура реагировала без переполнения буфера как на его переполнение.Код:.globl _Input_keysAvailable _Input_keysAvailable: LD A,#0 ; Check overflow: CP #KeyBufSize ; IF keysAvailable > 8 THEN keysAvailable := 8 END; JR NC,_Input_keyOut INC A LD (_Input_keysAvailable+1),A RET
Последний раз редактировалось Oleg N. Cher; 25.12.2014 в 15:58.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)