hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/kernel/input.rv
blob: 26ce545ec36947c6e36a1cf17f715bf6006c8405 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# keyboard scancode table
# ts is not a good way to write a driver lmao

const KEYMAP       = "  1234567890-=  qwertyuiop[]  asdfghjkl;'` \\zxcvbnm,./    "
const KEYMAP_SHIFT = "  !@#$%^&*()_+  QWERTYUIOP{}  ASDFGHJKL:\"~ |ZXCVBNM<>?    "

# 8259 pic
fn pic_remap() do
  outb(0x20, 0x11)  outb(0xa0, 0x11)
  outb(0x21, 0x20)  outb(0xa1, 0x28)
  outb(0x21, 0x04)  outb(0xa1, 0x02)
  outb(0x21, 0x01)  outb(0xa1, 0x01)
  outb(0x21, 0xff)  outb(0xa1, 0xff)
end
fn pic_unmask(line) outb(0x21, inb(0x21) band (255 bxor (1 shl line)))

# 8253/8254 pit channel 0, mode 3 (square wave)
# divisor 11931 -> ~100 hz (1193182 / 11931)
# the isr just counts ticks
fn pit_init() do
  outb(0x43, 0x36)
  outb(0x40, 11931 band 0xff)
  outb(0x40, (11931 shr 8) band 0xff)
end

# she stroke my keys till i handle
# no fr this is just a key stroke handler
global shell = { line = "", shift = :false, extended = :false }

fn decode_key(code) do
  if code == 0x2a or code == 0x36 do shell.shift = :true  return :nil end # shift down
  if code == 0xaa or code == 0xb6 do shell.shift = :false return :nil end # shift up
  if code >= 128 return :nil            # other releases
  if code == 28 return "\n"             # enter
  if code == 14 return "\x08"           # backspace
  if code < 2 return :nil
  if code >= KEYMAP:len() return :nil
  const character = if shell.shift KEYMAP_SHIFT[code] else KEYMAP[code]
  if character == " " and code != 0x39 return :nil # blank cells = modifiers/unmapped
  character
end

global on_key = fn(code) do
  if code == 0xe0 do shell.extended = :true return :nil end
  if shell.extended do
    shell.extended = :false
    let final = 0
    if code == 0x48 do final = 65 end      # up
    else if code == 0x50 do final = 66 end # down
    else if code == 0x4d do final = 67 end # right
    else if code == 0x4b do final = 68 end # left
    if final != 0 do
      stdin_deliver(27)
      stdin_deliver(91)
      stdin_deliver(final)
    end
    return :nil
  end
  const character = decode_key(code)
  if character == :nil return :nil
  if stdin_deliver(character:ascii()) return :nil
  if character == "\n" do puts("\n") run(shell.line) shell.line = "" return :nil end
  if character == "\x08" do
    if shell.line:len() > 0 do shell.line = shell.line:sub(0, shell.line:len() - 1) puts("\x08 \x08") end
    return :nil
  end
  shell.line ~= character
  puts(character)
end