![Smile :)](./images/smilies/grayscale_smile.gif)
[Staff][Alpha] Emerson - TI-83+ Keyboard/Mouse
Moderator: MaxCoderz Staff
- KermMartian
- Calc Wizard
- Posts: 549
- Joined: Tue 05 Jul, 2005 11:28 pm
- Contact:
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
Get it here.
Obviously, there is no keyboard code in there at all, it's just the mouse (I'm still pondering the keyboard).
The Mouse Demo.asm file could be useful, I know it's missing the mouse icon I used so just create a little 8x8 bitmap of a mouse if you want to test it.
Just .include Emerson.asm at the end of your file, but before that you need to specift what you want to use.
I think adding cursor clipping could be useful, rather than having to do it yourself.
I tried modding Solytare to use the external mouse, but the code was... strange, and whilst the game was fully playable I'd get an "ERR:MEMORY" followed by the screen turning off and RAM Clear when exiting. Not good.![Razz :P](./images/smilies/grayscale_grin.gif)
Emerson.asm is fairly well documented inside, though the readme.htm is clearly missing.
Obviously, there is no keyboard code in there at all, it's just the mouse (I'm still pondering the keyboard).
The Mouse Demo.asm file could be useful, I know it's missing the mouse icon I used so just create a little 8x8 bitmap of a mouse if you want to test it.
Just .include Emerson.asm at the end of your file, but before that you need to specift what you want to use.
Code: Select all
.define Emerson.Mouse ; <- adds mouse routines
.define Emerson.Mouse.InvertY ; <- inverts the Y axis (by default, the origin is in the bottom-left for a mouse)
.define Emerson.Mouse.Intellimouse ; <- enable Intellimouse extensions
I tried modding Solytare to use the external mouse, but the code was... strange, and whilst the game was fully playable I'd get an "ERR:MEMORY" followed by the screen turning off and RAM Clear when exiting. Not good.
![Razz :P](./images/smilies/grayscale_grin.gif)
Emerson.asm is fairly well documented inside, though the readme.htm is clearly missing.
- KermMartian
- Calc Wizard
- Posts: 549
- Joined: Tue 05 Jul, 2005 11:28 pm
- Contact:
- KermMartian
- Calc Wizard
- Posts: 549
- Joined: Tue 05 Jul, 2005 11:28 pm
- Contact:
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
It's been a while, I know, but I'm fed up with a the library sitting on my hard drive and not being available for people to use, so I'm gradually (I don't have a lot of spare time) trying to get it into shape for a proper release. It's 90% there, just needs a bit of tidying and documentation.
The mouse stuff I'm happy with. All you need to do is call Mouse.Update in your main loop and you have access to Mouse.Position.X, Mouse.Position.Y, Mouse.Position.Z and Mouse.Status.Buttons. Mouse.Intialise will reset the mouse, automatically detect if it's an Intellimouse and so on. All routines return Z on success, NZ on failure. For example, if Mouse.Update returns NZ you could just call Mouse.Initialise after it, effectively making the mouse reinitialise if you lose position information. This would make the mouse entirely hot-pluggable.
The mouse routines will also (optionally) clip the mouse to a bounding rectangle for you, will invert (again, optionally) the Y axis for you (so it points down the screen - when inverted you can use the x,y directly as a cursor coordinate on screen) and so on. It's all good.
The keyboard stuff I'm not happy about at all. The problem is that the keyboard has a lot of different scancodes, some of which are multibyte! This makes life difficult, so the library automatically converts keyboard scancodes into single byte Emerson-specific scancodes. This is all well and good, but for the fact that this conversion relies on some chunky tables and the equate names are UK keyboard specific.
Once that is fixed, there is still the issue of rewriting the scancode->key value conversion, which is pretty ugly (having to take into consideration things like shift, caps lock, num lock, ctrl and so on). Bah.
To make this worse, the keyboard I'm using is horribly cheap and doesn't send back correct acknowledgements (either it doesn't send them back at all or it sends $F5 instead of $FA). This isn't a problem with the library (I hope) as said keyboard had a habit of not being picked up by the BIOS of the PC it used to be on, so it is broken. When I plug in my normal keyboard, it works perfectly.
The main modules that will be available are AT (for byte-level comms - not optional), Mouse, Keyboard and Device.
Device hasn't been written yet, but the idea is that this (optional) module can be used to identify the device that has been attached to the calculator (so, return NZ if nothing, or a value in A that corresponds to keyboard, standard mouse or Intellimouse).
Would anyone use this?![Smile :)](./images/smilies/grayscale_smile.gif)
The mouse stuff I'm happy with. All you need to do is call Mouse.Update in your main loop and you have access to Mouse.Position.X, Mouse.Position.Y, Mouse.Position.Z and Mouse.Status.Buttons. Mouse.Intialise will reset the mouse, automatically detect if it's an Intellimouse and so on. All routines return Z on success, NZ on failure. For example, if Mouse.Update returns NZ you could just call Mouse.Initialise after it, effectively making the mouse reinitialise if you lose position information. This would make the mouse entirely hot-pluggable.
The mouse routines will also (optionally) clip the mouse to a bounding rectangle for you, will invert (again, optionally) the Y axis for you (so it points down the screen - when inverted you can use the x,y directly as a cursor coordinate on screen) and so on. It's all good.
The keyboard stuff I'm not happy about at all. The problem is that the keyboard has a lot of different scancodes, some of which are multibyte! This makes life difficult, so the library automatically converts keyboard scancodes into single byte Emerson-specific scancodes. This is all well and good, but for the fact that this conversion relies on some chunky tables and the equate names are UK keyboard specific.
Once that is fixed, there is still the issue of rewriting the scancode->key value conversion, which is pretty ugly (having to take into consideration things like shift, caps lock, num lock, ctrl and so on). Bah.
To make this worse, the keyboard I'm using is horribly cheap and doesn't send back correct acknowledgements (either it doesn't send them back at all or it sends $F5 instead of $FA). This isn't a problem with the library (I hope) as said keyboard had a habit of not being picked up by the BIOS of the PC it used to be on, so it is broken. When I plug in my normal keyboard, it works perfectly.
The main modules that will be available are AT (for byte-level comms - not optional), Mouse, Keyboard and Device.
Device hasn't been written yet, but the idea is that this (optional) module can be used to identify the device that has been attached to the calculator (so, return NZ if nothing, or a value in A that corresponds to keyboard, standard mouse or Intellimouse).
Would anyone use this?
![Smile :)](./images/smilies/grayscale_smile.gif)
- KermMartian
- Calc Wizard
- Posts: 549
- Joined: Tue 05 Jul, 2005 11:28 pm
- Contact:
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
Seems like the general consensus is that I should release it, so I shall ![Wink ;)](./images/smilies/grayscale_wink.gif)
As mentioned, I have a vast amount of work at the moment preventing me from doing any of my own projects, but this project is pretty much there, just needs wrapping up - nothing too taxing.![Wink ;)](./images/smilies/grayscale_wink.gif)
Overall, these routines are not too large - the mouse routines (+AT routines), for example, come to a little over 400 bytes at the moment.
![Wink ;)](./images/smilies/grayscale_wink.gif)
As mentioned, I have a vast amount of work at the moment preventing me from doing any of my own projects, but this project is pretty much there, just needs wrapping up - nothing too taxing.
![Wink ;)](./images/smilies/grayscale_wink.gif)
Overall, these routines are not too large - the mouse routines (+AT routines), for example, come to a little over 400 bytes at the moment.
- KermMartian
- Calc Wizard
- Posts: 549
- Joined: Tue 05 Jul, 2005 11:28 pm
- Contact:
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
The big challenge with a keyboard is handling various different keyboard layouts in a flexible manner. To understand the challenge, here's a quick run down of how a keyboard operates.
When a key is pressed or released, the keyboard transmits a sequence of bytes. The format of this is:
The old Emerson code was pretty much hard-coded to a UK layout. It would look on one of two tables (depending on whether the scancode was enhanced or not) to work out what the value of the key was, and then convert that to an ASCII-ish value after handling modifiers. You could load different tables, but the behaviour depended on modifiers being in the same place and having the same effect on all devices.
The new system is geared towards being much more flexible. The way I intend on structuring the layout files is a bit like this...
First up, you have a list of available scancodes. One scancode represents one key. This table is an index onto further data for each key.
A key can be one of two types - a "modifier" (Shift, Num Lock, AltGr, Ctrl) or a "valued" (A, B, 6, Home) key. A modifier key won't actually return a value, but will be used to modify the current state of the keyboard.
Modifier keys map onto a bit index for the status byte. This byte holds the current modifier state of the keyboard. Multiple modifier keys can share the same bit - for example, both Shift keys could share bit 0, both Ctrl keys could share bit 1 - but as there's only one AltGr key, that would have bit 2 all to itself. Which bit you pick doesn't matter. The keys would also have an "LED" bit index - this could be used to set/reset the LED status on the keyboard.
Modifier keys can be either temporary (Shift, AltGr, Ctrl) or a toggle (Num Lock). A temporary key would only set the status bit it is tied to when it is held down, a toggle would switch the status of the bit when pressed.
For each value key, you would have a bitmask which contains the bits of the status byte that can affect it. For example, for the space key you would have a bitmask of 0 - it produces a space whatever the state of the modifier keys. For something like 5 you would have a bitmask of whatever the bitmask for shift is - it can either be 5 or %. Something like E would have to have a bitmask of Ctrl OR Shift OR Caps Lock OR AltGr. And so on.![Smile :)](./images/smilies/grayscale_smile.gif)
There's a rough editor for all this:
![Image](http://benryves.com/bin/emerson/keyboard_editor.gif)
When the code working out what value the key is, based on modifiers, it would take the current status and AND it with the bitmask of which modifiers affect it. It could then use the resulting value as an index into the different values associated with that key and return it.
The return values can be one of two types - a character or control code that corresponds to the key ('A', '1', BS), or a "non-displayable" key (Page Up, Left). Users will have to handle values < 32 (or 127) themselves (for example, it is expected that the Del key returns character 127, DEL, or that Enter returns 13, CR).
Hopefully this system is flexible enough for most layouts!
When a key is pressed or released, the keyboard transmits a sequence of bytes. The format of this is:
- (Optional) $E0 if the key is an enhanced/extended key.
- (Optional) $F0 if the key is being released (not sent if pressed).
- The scancode itself.
The old Emerson code was pretty much hard-coded to a UK layout. It would look on one of two tables (depending on whether the scancode was enhanced or not) to work out what the value of the key was, and then convert that to an ASCII-ish value after handling modifiers. You could load different tables, but the behaviour depended on modifiers being in the same place and having the same effect on all devices.
The new system is geared towards being much more flexible. The way I intend on structuring the layout files is a bit like this...
First up, you have a list of available scancodes. One scancode represents one key. This table is an index onto further data for each key.
A key can be one of two types - a "modifier" (Shift, Num Lock, AltGr, Ctrl) or a "valued" (A, B, 6, Home) key. A modifier key won't actually return a value, but will be used to modify the current state of the keyboard.
Modifier keys map onto a bit index for the status byte. This byte holds the current modifier state of the keyboard. Multiple modifier keys can share the same bit - for example, both Shift keys could share bit 0, both Ctrl keys could share bit 1 - but as there's only one AltGr key, that would have bit 2 all to itself. Which bit you pick doesn't matter. The keys would also have an "LED" bit index - this could be used to set/reset the LED status on the keyboard.
Modifier keys can be either temporary (Shift, AltGr, Ctrl) or a toggle (Num Lock). A temporary key would only set the status bit it is tied to when it is held down, a toggle would switch the status of the bit when pressed.
For each value key, you would have a bitmask which contains the bits of the status byte that can affect it. For example, for the space key you would have a bitmask of 0 - it produces a space whatever the state of the modifier keys. For something like 5 you would have a bitmask of whatever the bitmask for shift is - it can either be 5 or %. Something like E would have to have a bitmask of Ctrl OR Shift OR Caps Lock OR AltGr. And so on.
![Smile :)](./images/smilies/grayscale_smile.gif)
There's a rough editor for all this:
![Image](http://benryves.com/bin/emerson/keyboard_editor.gif)
When the code working out what value the key is, based on modifiers, it would take the current status and AND it with the bitmask of which modifiers affect it. It could then use the resulting value as an index into the different values associated with that key and return it.
The return values can be one of two types - a character or control code that corresponds to the key ('A', '1', BS), or a "non-displayable" key (Page Up, Left). Users will have to handle values < 32 (or 127) themselves (for example, it is expected that the Del key returns character 127, DEL, or that Enter returns 13, CR).
Hopefully this system is flexible enough for most layouts!
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
OK, I now have it loading and managing layouts based on a layout variable (I've arranged a 102 key UK layout file). I need to get it to flag if a key is non-character key, then get the editor to export .8xp/.83p files (currently it just exports an assembly listing). The old (and rather bizarre) event-handler method has been scrapped, and there are now a few functions:
Keyboard.LoadLayout
Input: None.
Output: NZ on failure.
Other: Loads the default layout from a file on the calculator, if one is installed.
Keyboard.GetScancode
Inputs: None.
Outputs: NZ on failure/no key. A is scancode. C is set if the key was pressed, reset if released. S is set if the key was an extended key, reset if not.
Keyboard.ConvertScancode
Inputs: A is scancode. C for if the key was pressed. S if the key was extended (same as GetScancode output).
Outputs: NZ on unrecognised scancode. A is key code. C is set if the key was pressed, reset if released. S is set if the key is a non-printable key (such as Left or Right. Keys such as Delete, Backspace or Enter all have ASCII codes, so are treated as printable).
Other: The status of the keyboard is updated, including LEDs.
Keyboard.GetKey
Inputs: None.
Outputs: Same as ConvertScancode, but also returns NZ if no key was pressed.
Once I have it (cleanly) handling non-printable keys, I just need to polish off the Device routines (for working out what the connected device is, and providing a few common functions).
Keyboard.LoadLayout
Input: None.
Output: NZ on failure.
Other: Loads the default layout from a file on the calculator, if one is installed.
Keyboard.GetScancode
Inputs: None.
Outputs: NZ on failure/no key. A is scancode. C is set if the key was pressed, reset if released. S is set if the key was an extended key, reset if not.
Keyboard.ConvertScancode
Inputs: A is scancode. C for if the key was pressed. S if the key was extended (same as GetScancode output).
Outputs: NZ on unrecognised scancode. A is key code. C is set if the key was pressed, reset if released. S is set if the key is a non-printable key (such as Left or Right. Keys such as Delete, Backspace or Enter all have ASCII codes, so are treated as printable).
Other: The status of the keyboard is updated, including LEDs.
Keyboard.GetKey
Inputs: None.
Outputs: Same as ConvertScancode, but also returns NZ if no key was pressed.
Once I have it (cleanly) handling non-printable keys, I just need to polish off the Device routines (for working out what the connected device is, and providing a few common functions).