flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Converting scan codes to ascii

Author
Thread Post new topic Reply to topic
StringCheesian



Joined: 20 Feb 2004
Posts: 20
StringCheesian
I found both an ascii table and a scan code table online, so now all I have to do is manually cross reference the two and put together a look up table... ugh.

Would somebody who's already solved this problem be willing to give me permission to use their code and/or look up table? Anybody? Please?

I tried looking in MenuetOS's source, but I can't find the relevent code.
Post 01 Mar 2004, 07:02
View user's profile Send private message Reply with quote
Ralph



Joined: 04 Oct 2003
Posts: 86
Ralph
My OS is based on forth, but I'm sure you can figure out how to make it work. This is the source to ACCEPT:
Code:
;accept.wrd
;Reads character string from keyboard.  limited.
accept:
    dpop    edi
    mov     dword [.buffer_start],edi
    sub     ecx,ecx
    mov     ebp,ASCIITableL

.a: call    .get_key
.b: cmp     al,KBksp
    jz      .backspace
    dec     ecx
    cmp     al,KEnter
    jz      .done
    cmp     ecx,TIBSIZE
    jg      .a
    stosb
    pusha
    dpush   eax
    call    emit
    popa
    inc     ecx
    jmp     .a
.done:
    dpush   ecx
    ret
.backspace:
    push    .b
    dec     ecx
    cmp     edi,dword [.buffer_start]
    jle     .get_key
    push    edi
    sub     edi,edi
    sub     dword [_cursor],02h
    mov     edi,dword [_cursor]
    add     edi,VGASEGMENT
    mov     eax,dword [_color]
    mov     al,20h
    stosw
    pop     edi
    dec     edi
    dec     ecx
    jmp     .get_key
    .buffer_start dd 0

.get_key:
    sub     eax,eax
@@: in      al,64h
    and     al,01h
    jz      @b              ;wait for key
    in      al,60h
    sub     edx,edx

    test    al,80h
    jz      @f
    inc     edx
@@: and     al,7Fh
    cmp     al,39h
    ja      .get_key        ;filter ignored keys
    mov     ebx,ebp
    xlatb
    or      al,al
    js      .shift
    jz      .get_key
    or      dl,dl
    jnz     .get_key
    inc     ecx
    ret

.shift:
    or      dl,dl
    jnz     @f
    mov     ebp,ASCIITableU
    jmp     .get_key
@@: mov     ebp,ASCIITableL
    jmp     .get_key


ASCIITableL:
 DB 00, KEsc, "1234567890-=", KBksp, KTab
 DB "qwertyuiop[]", KEnter, KCtrl, "asdfghjkl;'`", KLShift, "\zxcvbnm,./"
 DB KRShift, KPrtScr, KAlt, KSpace, KCaps

ASCIITableU:
 DB 00, KEsc, "!@#$%^&*()_+", KBksp, KTab
 DB "QWERTYUIOP{}", KEnter, KCtrl, 'ASDFGHJKL:"~', KLShift, "|ZXCVBNM<>?"
 DB KRShift, KPrtScr, KAlt, KSpace, KCaps

KEsc    = 27h
KBksp   = 08h
KTab    = 09h
KEnter  = 0Ah
KCtrl   = 00h
KLShift = -1h
KRShift = -1h
KPrtScr = "*"
KAlt    = 00h
KSpace  = 20h
KCaps   = -2h
    


Hope that helps.


Last edited by Ralph on 12 Jun 2004, 23:11; edited 1 time in total
Post 01 Mar 2004, 07:32
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7755
Location: Kraków, Poland
Tomasz Grysztar
You can use the keyboard handler from my dead Titan OS project, it allows to use custom conversion tables. Below is the KEYBOARD.INC file from that system, the "irq_1" is the handler for keyboard IRQ (if you don't reprogramm the PIC, it is interrupt 9), "int_22h" is the handler for interrupt 22h, which in Titan was to access keyboard functions (like BIOS interrupt 16h).

Code:
KEYS_MAX = 10h                        ; size of keyboard buffer

irq_1:
        push    eax ecx ds
        push    FLAT_SEL
        pop     ds
        in      al,60h                  ; read scan code
        cmp     al,0F0h
        ja      irq_1_exit              ; ignore if special scan code
        movzx   ecx,[keys_counter]
        lea     ecx,[keys_data + 4*ecx]
        cmp     [keys_counter],KEYS_MAX ; check for full buffer
        je      keys_data_full
        mov     ah,[ecx]
        cmp     ax,0E02Ah
        je      ignore_special_code
        cmp     ax,0E0AAh
        je      ignore_special_code
        mov     [ecx],ax                ; store key info
        cmp     al,0E0h                 ; if prefix only, exit interrupt
        je      irq_1_exit
        cmp     al,0E1h
        je      irq_1_exit
        cmp     al,0F0h
        je      irq_1_exit
        push    [keyb_status]
        pop     word [ecx+2]            ; store keyboard status
        inc     [keys_counter]          ; key information is full
        jmp     keyb_status_check
  ignore_special_code:
        mov     byte [ecx],0
        jmp     irq_1_exit
  keys_data_full:
        mov     ah,[ecx]
        mov     [ecx],al
        cmp     ah,0E0h
        je      keyb_status_check
        xor     ah,ah
  keyb_status_check:                    ; check for change of keyboard status
        lea     ecx,[keyb_status_table]
  check_key:
        cmp     byte [ecx],0            ; end of table?
        je      irq_1_exit              ; if yes, exit interrupt
        cmp     ax,[ecx]                ; compare key codes
        je      keyb_status_change      ; if equal, change keyboard status
        add     ecx,3
        jmp     check_key
  keyb_status_change:
        mov     ax,1
        mov     cl,[ecx+2]              ; CL = number of bit and command
        test    cl,10h
        jnz     set_bit
        test    cl,20h
        jnz     switch_bit
      clear_bit:                        ; clear bit in keyboard status word
        shl     ax,cl
        not     ax
        and     [keyb_status],ax
        jmp     irq_1_exit
      set_bit:                          ; set bit in keyboard status word
        and     cl,0Fh
        shl     ax,cl
        or      [keyb_status],ax
        jmp     irq_1_exit
      switch_bit:                       ; switch bit in keyboard status word
        and     cl,0Fh
        shl     ax,cl
        xor     [keyb_status],ax
        call    set_keyb_leds
  irq_1_exit:
        in      al,61h                  ; give finishing information
        out     61h,al                  ; to keyboard...
        mov     al,20h
        out     20h,al                  ; ...and interrupt controller
        pop     ds ecx eax
        iret                            ; exit interrupt

set_keyb_leds:
        mov     al,0EDh                 ; keyboard command 0EDh:
        out     60h,al                  ; set/reset mode indicators
      keyb_wait:
        in      al,64h
        test    al,10b                  ; is input buffer full?
        jne     keyb_wait               ; if yes, wait
        mov     al,byte [keyb_status]
        and     al,111b
        out     60h,al                  ; set keyboard LEDs
        ret

int_22h:
        push    ds es
        cli
        cld
        push    FLAT_SEL
        pop     ds
        push    ds
        pop     es
        or      ah,ah                   ; function 00h:
        jz      check_for_key           ;  check for key
        cmp     ah,01h                  ; function 01h:
        je      read_key                ;  read key
        cmp     ah,10h                  ; function 10h:
        je      get_keyb_status         ;  get keyboard status
        cmp     ah,11h                  ; function 11h:
        je      set_keyb_status         ;  set keyboard status
        cmp     ah,20h                  ; function 20h:
        je      get_conversion_table    ;  get key conversion table
        cmp     ah,21h                  ; function 21h:
        je      set_conversion_table    ;  set key conversion table
        pop     es ds
        mov     eax,_function_unavailable
        or      byte [esp+8],1          ; set CF
        iret
  check_for_key:
        cmp     [keys_counter],0
        je      no_key
        pop     es ds
        and     byte [esp+8],not (1 shl 6); clear ZF
        and     byte [esp+8],not 1      ; clear CF
        iret
      no_key:
        pop     es ds
        or      byte [esp+8],1 shl 6    ; set ZF
        and     byte [esp+8],not 1      ; clear CF
        iret
  get_keyb_status:
        mov     bx,[keyb_status]
        pop     es ds
        and     byte [esp+8],not 1      ; clear CF
        iret
  set_keyb_status:
        mov     [keyb_status],bx
        call    set_keyb_leds
        pop     es ds
        and     byte [esp+8],not 1      ; clear CF
        iret
  get_conversion_table:
        mov     ebx,[key_conversion_table]
        pop     es ds
        and     byte [esp+8],not 1      ; clear CF
        iret
  set_conversion_table:
        mov     [key_conversion_table],ebx
        pop     es ds
        and     byte [esp+8],not 1      ; clear CF
        iret
  read_key:
        push    ecx esi edi
        sti                             ; enable interrupts
      wait_for_key:
        movzx   ecx,[keys_counter]
        or      cl,cl                   ; is any key in buffer?
        jz      wait_for_key            ; if no, wait
        cli
        lea     ecx,[keys_data]
        xor     al,al
        xchg    ax,[ecx]                ; get and clear scan code info
        mov     bx,[ecx+2]              ; get keyboard status
        lea     esi,[ecx+4]
        lea     edi,[ecx]
        movzx   ecx,[keys_counter]
        rep     movsd                   ; move keys data
        dec     [keys_counter]          ; key removed from buffer
        xor     dl,dl
        mov     esi,[key_conversion_table]
      key_conversion:
        mov     cx,[esi]
        or      cl,cl                   ; end of table?
        je      key_converted           ; yes, ASCII code is 0
        add     esi,2
      compare_status:
        mov     di,bx
        and     di,[esi]                ; compare only bits from mask
        cmp     di,[esi+2]              ; compare keyboard status
        je      scan_table              ; if equal, search for key code
        add     esi,4
        dec     cl
        jnz     compare_status          ; compare next status
        movzx   edi,ch
        imul    edi,3
        add     esi,edi
        jmp     key_conversion          ; next part of table
      scan_table:
        movzx   edi,cl
        lea     esi,[esi+4*edi]
      compare_key:
        cmp     ax,[esi]                ; compare key codes
        je      convert_key             ; if equal, get ASCII code
        add     esi,3
        dec     ch
        jnz     compare_key             ; compare with next key code
        jmp     key_conversion          ; next part of table
      convert_key:
        mov     dl,[esi+2]              ; DL = ASCII code for this key
      key_converted:                    ; AL = scan code, AH = prefix
        pop     edi esi ecx             ; BX = keyboard status
        pop     es ds
        and     byte [esp+8],not 1      ; clear CF
        iret

keyb_status dw 0                        ; current keyboard status
keys_counter db 0                       ; number of keys in buffer
keys_data rd 2*KEYS_MAX                 ; keyboard buffer
  db 0

keyb_status_table:
  db 2Ah,0,        13h                  ; LShift press - set bit 3
  db 80h+2Ah,0,    03h                  ; LShift release - clear bit 3
  db 36h,0,        14h                  ; RShift press - set bit 4
  db 80h+36h,0,    04h                  ; RShift release - clear bit 4
  db 1Dh,0,        15h                  ; LCtrl press - set bit 5
  db 80h+1Dh,0,    05h                  ; LCtrl release - clear bit 5
  db 1Dh,0E0h,     16h                  ; RCtrl press - set bit 6
  db 80h+1Dh,0E0h, 06h                  ; RCtrl release - clear bit 6
  db 38h,0,        17h                  ; LAlt press - set bit 7
  db 80h+38h,0,    07h                  ; LAlt release - clear bit 7
  db 38h,0E0h,     18h                  ; RAlt press - set bit 8
  db 80h+38h,0E0h, 08h                  ; RAlt release - clear bit 8
  db 46h,0,        20h                  ; ScrollLock press - switch bit 0
  db 45h,0,        21h                  ; NumLock press - switch bit 1
  db 3Ah,0,        22h                  ; CapsLock press - switch bit 2
  db 0

key_conversion_table dd default_table

default_table:
  db 3                                  ; number of keyboard status cases
  db 26                                 ; number of key codes
     dw 111111100b                      ; keyboard status mask
     dw 000000000b                      ; keyboard status
     dw 111101100b
     dw 000001100b
     dw 111110100b
     dw 000010100b
     db 10h,0,    'q'                   ; scan code and matching ASCII code
     db 11h,0,    'w'
     db 12h,0,    'e'
     db 13h,0,    'r'
     db 14h,0,    't'
     db 15h,0,    'y'
     db 16h,0,    'u'
     db 17h,0,    'i'
     db 18h,0,    'o'
     db 19h,0,    'p'
     db 1Eh,0,    'a'
     db 1Fh,0,    's'
     db 20h,0,    'd'
     db 21h,0,    'f'
     db 22h,0,    'g'
     db 23h,0,    'h'
     db 24h,0,    'j'
     db 25h,0,    'k'
     db 26h,0,    'l'
     db 2Ch,0,    'z'
     db 2Dh,0,    'x'
     db 2Eh,0,    'c'
     db 2Fh,0,    'v'
     db 30h,0,    'b'
     db 31h,0,    'n'
     db 32h,0,    'm'
  db 3
  db 26
     dw 111101100b
     dw 000001000b
     dw 111110100b
     dw 000010000b
     dw 111111100b
     dw 000000100b
     db 10h,0,    'Q'
     db 11h,0,    'W'
     db 12h,0,    'E'
     db 13h,0,    'R'
     db 14h,0,    'T'
     db 15h,0,    'Y'
     db 16h,0,    'U'
     db 17h,0,    'I'
     db 18h,0,    'O'
     db 19h,0,    'P'
     db 1Eh,0,    'A'
     db 1Fh,0,    'S'
     db 20h,0,    'D'
     db 21h,0,    'F'
     db 22h,0,    'G'
     db 23h,0,    'H'
     db 24h,0,    'J'
     db 25h,0,    'K'
     db 26h,0,    'L'
     db 2Ch,0,    'Z'
     db 2Dh,0,    'X'
     db 2Eh,0,    'C'
     db 2Fh,0,    'V'
     db 30h,0,    'B'
     db 31h,0,    'N'
     db 32h,0,    'M'
  db 1
  db 5
     dw 111100000b
     dw 000000000b
     db 39h,0,    ' '
     db 35h,0E0h, '/'
     db 37h,0,    '*'
     db 4Ah,0,    '-'
     db 4Eh,0,    '+'
  db 1
  db 21
     dw 111111000b
     dw 000000000b
     db 02h,0,    '1'
     db 03h,0,    '2'
     db 04h,0,    '3'
     db 05h,0,    '4'
     db 06h,0,    '5'
     db 07h,0,    '6'
     db 08h,0,    '7'
     db 09h,0,    '8'
     db 0Ah,0,    '9'
     db 0Bh,0,    '0'
     db 0Ch,0,    '-'
     db 0Dh,0,    '='
     db 1Ah,0,    '['
     db 1Bh,0,    ']'
     db 27h,0,    3Bh
     db 28h,0,    27h
     db 29h,0,    60h
     db 2Bh,0,    '\'
     db 33h,0,    ','
     db 34h,0,    '.'
     db 35h,0,    '/'
  db 2
  db 21
     dw 111110000b
     dw 000010000b
     dw 111101000b
     dw 000001000b
     db 02h,0,    '!'
     db 03h,0,    '@'
     db 04h,0,    '#'
     db 05h,0,    '$'
     db 06h,0,    '%'
     db 07h,0,    '^'
     db 08h,0,    '&'
     db 09h,0,    '*'
     db 0Ah,0,    '('
     db 0Bh,0,    ')'
     db 0Ch,0,    '_'
     db 0Dh,0,    '+'
     db 1Ah,0,    '{'
     db 1Bh,0,    '}'
     db 27h,0,    ':'
     db 28h,0,    22h
     db 29h,0,    7Eh
     db 2Bh,0,    '|'
     db 33h,0,    '<'
     db 34h,0,    '>'
     db 35h,0,    '?'
  db 1
  db 11
     dw 111111010b
     dw 000000010b
     db 47h,0,    '7'
     db 48h,0,    '8'
     db 49h,0,    '9'
     db 4Bh,0,    '4'
     db 4Ch,0,    '5'
     db 4Dh,0,    '6'
     db 4Fh,0,    '1'
     db 50h,0,    '2'
     db 51h,0,    '3'
     db 52h,0,    '0'
     db 53h,0,    '.'
  db 2
  db 1
     dw 110111000b
     dw 000100000b
     dw 111011000b
     dw 001000000b
     db 39h,0,    0FFh
  db 0    

Because I'm not going to continue that old project (I've lost sources of more advanced versions), I'm releasing the Titan source as Public Domain code, which means you can do with it anything you want.
Post 01 Mar 2004, 10:15
View user's profile Send private message Visit poster's website Reply with quote
StringCheesian



Joined: 20 Feb 2004
Posts: 20
StringCheesian
Thanks Privalov and Ralph!
Post 01 Mar 2004, 19:32
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.