fnuecke / Circuity

Other
10 stars 0 forks source link

Add a screen block #7

Open fnuecke opened 8 years ago

fnuecke commented 8 years ago

Should provide generic rendering of bus devices that provide graphical output.

iamgreaser commented 8 years ago

Welp. That was one hell of a merge conflict.

I'm going to find out if my attempt at drawing the screen in a GUI was worth my time.

...OK, seems it was. Very nice work anyway.

iamgreaser commented 8 years ago

GUI is now in place, and now reveals that we definitely want our own font handler.

Here's a font for now: https://i.imgur.com/ZkRnzxt.png

fnuecke commented 8 years ago

I was afraid you'd have more to merge after I had my little conflict, sorry about that :P Awesome tho! I'll probably use the font renderer from TIS-3D.

Q: do we need the screen to have an address?

We should probably move the boilerplate for the keyboard input interrupt from the serial console to the screen now.

iamgreaser commented 8 years ago

Here's an updated font with the entirety of codepage 437: https://i.imgur.com/yMrtkwz.png

The idea for the screen having an address is so software can easily rebind a screen to a GPU or a SC - you'd feed the address into the screen, and it'd automatically go for the physical device index as denoted by the bus controller.

fnuecke commented 8 years ago

Font looks good.

dynamic rebinding

Ah, right, good point! Need a stable order for attached ScreenRenderers then. Probably just sorted by their UUID.

iamgreaser commented 8 years ago

It'd basically be a one-time write and then it'd bind to the UUID, so stable ordering isn't strictly necessary.

fnuecke commented 8 years ago

I was thinking of exposing that sorted list, so that for selecting one writing an index would be sufficient. For that the order would have to be stable.

fnuecke commented 8 years ago

Boilerplate is in, no implementation yet. However, the screen now emits an interrupt upon keypress, and builds a queue of up to 16 keypresses which can be read via its serial interface. Not sure if it'd be better to overwrite the oldest in case more than those queue up? Now new ones get dropped.

iamgreaser commented 8 years ago

I can find no info on what actually happens when the keyboard buffer is full on the IBM PC BIOS (other than the fact that the buffer capacity is 15 and it beeps when you try to add a new key).

For the actual keyboard as opposed to the OS handler, I'd probably drop the new keypresses just because if we then decide to extend this with multi-byte codes we don't end up with prefix bytes omitted.

fnuecke commented 8 years ago

Hmm, multi-byte keyboard codes? Interesting. As far as I can tell LWJGL doesn't produce any keycodes that wouldn't fit in a single byte, any examples for this? But hey, as long as dropping new ones is fine, great. Nothing to change ;)

So while in principle just buffering a single input on the keyboard would be fine when pushing them in a software queue via the interrupt handler, I'd still prefer to keep the buffering in the keyboard itself for redundancy. Just in case, to prevent drops due to lag becoming an issue; I think it's typically unlikely they would, but theoretically multiple packets could be processed inbetween CPU execution, leading to lost inputs if there's no queue in the keyboard itself.

iamgreaser commented 8 years ago

The PC AT keyboard controller uses the top bit as a make/break flag for the most part, but also has a 0xE0 prefix byte to denote different variations of a key, e.g. left and right ctrl, up and numpad-8, probably some other things (there's even a key with 0xE1 as a prefix but I forget what it is).

Make/break would be useful to have, although I suspect we could get away with using, say, 0x80 as an alt-type prefix if we ever have or need such a thing. Or maybe we could expand the range such that 7x yy / Fx yy denotes key xyy, or maybe something else. Typematic delay could be useful to have as well - that way you'd have several make codes if you hold a key down.

The actual semantics will vary in practice, and ideally would match the ASCII code where possible.

Only real problem is working out what to do when someone holds shift + a key, as different layouts work differently - for instance, shift -2 is @ on a US keyboard, but " on a UK keyboard. (Don't ask me why, because @ makes no damn sense in the context of ASCII, whereas " is the logical thing to put there.)

If you link me the list of LWJGL keyboard scancodes I can take a look and work out what would actually make sense.

fnuecke commented 8 years ago

Interesting, but yeah, actual input will realistically speaking be based on LWJGL - documentation here (actual numeric constants). Soo... would it be bad to just have two ports, one for the chars, one for the key codes? Too different to how actual keyboards work? What codes do those provide? How does/does LWJGL mangle those? Hmmm.

iamgreaser commented 8 years ago

LWJGL scancodes are literally just IBM PC scancodes w/ the top bit set for keys which would be 0xE0-prefixed

Really, see for yourself: https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html

EDIT: One more thing: If you read from an I/O port on the serial console, just translate the charcodes to UTF-8 and skip the scancodes. This stuff is more for if you read keyboard input directly from the screen keyboard, which is what you will do in a more conventional setup.

Note how there are no keys assigned to 96 or 97 (0x60, 0x61) due to break code conflicts.

You may notice that some keys are just plain weird, so it's probably better to just use LWJGL's codes for KEY_SYSRQ and KEY_PAUSE instead of doing it how the PC does it.

If you do that, then 0xE1 is free for use as a prefix for encoding the key code. The fun thing is 0xE2 and 0xE3 are also free for use.

One thing that would be important to maintain is that when you fetch a byte when the buffer has been fully read, it just returns the last byte that was read. That way, something which isn't the interrupt keyboard handler can get the last scancode and whether it was a make or break, even though they don't have the 0xE0 prefix.

Here's a proposal: If it's a valid text key, send 0xE1 and a suitably-encoded character before the expected scancode. I'm thinking do something along the lines of how MIDI encodes things.

Encoding scheme: If the top bit is set, then add the lower 7 bits and shift left by 7, and if the top bit is clear, then just add the lower 7 bits and there's your scancode.

The nice thing about this approach is you can skip charcodes easily:

in a,(c)
cp $E1
jr nz, +
-:
in a, (c)
bit 7, a
jr nz, -
ret ; wait for next interrupt before we read the next byte
+:

Pressing 'A' w/ no shift or capslock enabled:

Pressing 'Ä' (U+00C4) w/ no shift or capslock enabled:

fnuecke commented 8 years ago

So then to indicate that we're not currently repeating the last scancode, if there's no "suitable" character, would we still queue E1 ??? E1 00?

iamgreaser commented 8 years ago

If there's no suitable character we just skip the E1 thing... and it won't be E1 xx xx E1, it'll just be E1 xx xx and then the scancode.