Monday, October 26, 2015
Sword for The Spider Ninja!
A new attraction is opening up at Winterground Fairlands! "The Adventures of the Spider Ninja" It's an exciting attraction with Spider Ninjas, and various challenges and action and probably a lot of running around with swords. This attraction required costuming to create something all new for the cast members. Shown in the picture is Jasper with his uniform. The ninja mask and spider outfit were created by Pam the Costumer specifically for Jasper's small frame.
The new swords were built using various corrugated cardboard products.
The blade was made by rubber-cementing three layers of cardboard together, with their "grain" going in different directions for strength. The blade actually continues through the hilt and into the handle, much like a real metal sword.
The handle is just a piece of thick cardboard tubing originally from wrapping paper. It has a smaller diameter and is stronger than paper towel tubing to accommodate the cast member's smaller hands.
The hilt was a paper towel tube, with a round hole on one side to accept the handle, and a rectangular hole on the other side to accept the top portion of the blade.
Once the blade is pushed through the hilt and into the handle, everything fit very snugly, and didn't need any additional adhesives... but just in case, and for extra strength, the hilt was loaded up with lots of hot glue, and additional glue was added around the joints from the outside.
A couple coats of plain 'ol black spray paint and then the fine detail work could be done. Jasper added some spiders he made out of Perler beads and the sword was completed!
Monday, October 19, 2015
Major Blog Announcement!
Hi and welcome to the new readers!
Just to let you all know, this blog will be slightly changing over the upcoming months. The focus will still be on projects that we're working on/have worked on... but for a new venue
!I've recently picked up and moved to Sklarsville, Maine and am working full time at the world famous Winterground Fairlands Park and Adventurefun Center!!!
The wonderful part of this whole thing is that being hired as the head of the "Funmagineering Gang", I am able to make posts about the various projects we're working on for the park and in our skunkworks in general. There may even be some great blue-sky projects we'll be able to share with you!
So sit back, and "Enjoy the Adventurefun!"TM
Just to let you all know, this blog will be slightly changing over the upcoming months. The focus will still be on projects that we're working on/have worked on... but for a new venue
!I've recently picked up and moved to Sklarsville, Maine and am working full time at the world famous Winterground Fairlands Park and Adventurefun Center!!!
The wonderful part of this whole thing is that being hired as the head of the "Funmagineering Gang", I am able to make posts about the various projects we're working on for the park and in our skunkworks in general. There may even be some great blue-sky projects we'll be able to share with you!
So sit back, and "Enjoy the Adventurefun!"TM
Tuesday, October 13, 2015
Nintendo DS Lite case mod
Many years ago, I bought a white Nintendo DS Lite. I loved the form factor, the look of it and the games I could play on it. There were a lot of games for it, and for the GameBoy Advance which I already had which I'd love to play on it.
Over time, I've gotten a R4DS card so I could play homebrew (yeah, let's go with that) and use it as a kind of PDA type of thing. I also got an EZFlash V for the same reasons. For homebrew. Because that's still a thing, right? (The screenshot above shows the R4DS interface, which I've re-skinned to like AmigaDOS 1.3 because that's something I do.
Anyway, at some point, I got a completely transparent shell for it, which was really neat for a while. It was a pain to move the guts over to that shell, but it looked neat for a while. Then The upper screen failed and the touch scanner failed on the bottom. So I replaced those. Then the right shoulder button failed, so I replaced that... which never really worked well, as the button broke off of the main board. There just wasn't enough structure there to support it.
Fast forward a few years, and I picked up a European black DS Lite in a trade for some old GBA stuff I didn't want anymore. That one worked GREAT, except that the screen hinge was completely destroyed. I used that for a while, but ended up shelving it.
For a while I've been meaning to take the best parts of all of this and put together one fully functional DS Lite.
I had planned to take the top screen from the black unit, but the ribbon cable broke while I was removing it from that unit.
What I ended up with was this:
- Case enclosures - White
- Top and shoulder buttons, switch cover plastics - Black
- Upper Screen - White (replacement, colors aren't perfect on it, but it's good)
- Lower Screen - Black
- Motherboard - Black
- Battery - Black
- Wifi Antenna - Black (The cable was broken on the white one)
- Rubber feet, screw covers - Black
- Stylus - White (Black one is on order)
I think the final form here is pretty sharp. Best of all, it's fully functional again! Yay!
Monday, October 5, 2015
Arduino Ethernet Library Modification
I was recently working on a piece of test/demo code running on an Arduino that talked through a Seeed Studio Ethernet shield. The standard Ethernet library will not acknowledge a connection back to the host code until it receives something from the client. For most things, this works out just fine (HTTP, chat servers, etc) but in some cases, like for RFB/VNC servers, it must first send out something itself to the client. The as-shipped library does not allow for this, so it required a minor hack to the library code to make this option available.
in (Libraries)/Ethernet/src/EthernetServer.cpp, we can see the following code:
01 EthernetClient EthernetServer::available() 02 { 03 accept(); 04 for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { 05 EthernetClient client(sock); 06 if (EthernetClass::_server_port[sock] == _port) { 07 uint8_t s = client.status(); 08 if (s == SnSR::ESTABLISHED || s == SnSR::CLOSE_WAIT) { 09 if (client.available()) { 10 return client; 11 } 12 } 13 } 14 } 15 return EthernetClient(MAX_SOCK_NUM); 16 }
As you can see, it checks to see if there is a connection established (line 08), then it checks to see if there's any content available from the client (bolded line 09), and only then will it return the handle to the newly connected client. This will be called in your Arduino code like this (from the WebServer example, packed with the Ethernet library)
void loop() { // listen for incoming clients EthernetClient client = server.available(); if (client) { Serial.println("new client"); // do stuff here... client.stop(); Serial.println("client disconnected"); } }
This loop will only make and break connections if the client is actually connected AND it has data available. For most servers, this is sufficient. However, if you want to allow for clients that connect and then just listen, you need to do the following...
In EthernetServer.cpp, create a copy of the ::available() method, eliminating lines 9 and 11 above. I call this function ::connectionEstablished(), plopped right into the EthernetServer.cpp file, just after the ::available() method, and it is implemented as follows:
EthernetClient EthernetServer::connectionEstablished() { accept(); for (int sock = 0; sock < MAX_SOCK_NUM; sock++) { EthernetClient client(sock); if (EthernetClass::_server_port[sock] == _port) { uint8_t s = client.status(); if (s == SnSR::ESTABLISHED || s == SnSR::CLOSE_WAIT) { // "if" statement removed return client; } } } return EthernetClient(MAX_SOCK_NUM); }
Next, you need to add the method to the header file, EthernetServer.h, as seen in this snippet
class EthernetServer : public Server { private: uint16_t _port; void accept(); public: EthernetServer(uint16_t); EthernetClient connectionEstablished(); EthernetClient available(); virtual void begin(); virtual size_t write(uint8_t); virtual size_t write(const uint8_t *buf, size_t size); using Print::write; };
Now, you can call this new method like this:
void loop() { // listen for incoming clients EthernetClient client = server.connectionEstablished(); if (client) { Serial.println("new client has connected"); // do stuff here... client.println( "Hello, goodbye!" ); client.stop(); Serial.println("client disconnected"); } }
Thursday, September 10, 2015
Living Room Planetarium (work in progress)
This was just a quick brainstorm that I'm trying to poke at with a pointy stick to see if I can make anything interesting happen with...
The basic concept is to turn as much of the entire ceiling of my living room into a planetarium as possible. Earlier, I had the idea to project video onto the ceiling, and lie down on the floor to watch movies. The issue here was that I was getting ghosting of the image since I didn't have a front surface mirror to use. The image was also fairly small compared to the size of the ceiling.
This brought in the idea of using a tele-expander, magnifier or convex mirror to expand the image on the ceiling. While cleaning the basement I found a somewhat scuffed, convex plexiglass baby seat mirror. Just the perfect thing to try out!
You can see in the above picture the results of this first experiment. The projector is precariously hanging on the back of a cat scratching post thingy that our cat refuses to use. It's pointing down onto the mirror, sitting on the floor.
The image projected onto the ceiling is nice and big, although there's a hell of a lot of distortion. The surface isn't perfectly curved, it's pretty badly scuffed, and it's a back surface mirror, so the image is distorted, fuzzy and there are ghosts and smears of the star points.
One thing I did notice though was that when I used more of the mirror to reflect the projector's image, the final image looked better. I dug out the 0.7 wide angle screw on lens for my old Canon Optura DV video camera, and shoved it onto the front of the DLP with rubber bands. This both maximized the image onto the mirror, and increased the size of the final image on the ceiling. It's still far from perfect, but not bad considering that I put this together with some rubber bands and a cheap mirror...
For the star field generation, I used Stellarium, running on my MacBook. That side of it works pretty well. ;)
The basic concept is to turn as much of the entire ceiling of my living room into a planetarium as possible. Earlier, I had the idea to project video onto the ceiling, and lie down on the floor to watch movies. The issue here was that I was getting ghosting of the image since I didn't have a front surface mirror to use. The image was also fairly small compared to the size of the ceiling.
This brought in the idea of using a tele-expander, magnifier or convex mirror to expand the image on the ceiling. While cleaning the basement I found a somewhat scuffed, convex plexiglass baby seat mirror. Just the perfect thing to try out!
You can see in the above picture the results of this first experiment. The projector is precariously hanging on the back of a cat scratching post thingy that our cat refuses to use. It's pointing down onto the mirror, sitting on the floor.
The image projected onto the ceiling is nice and big, although there's a hell of a lot of distortion. The surface isn't perfectly curved, it's pretty badly scuffed, and it's a back surface mirror, so the image is distorted, fuzzy and there are ghosts and smears of the star points.
One thing I did notice though was that when I used more of the mirror to reflect the projector's image, the final image looked better. I dug out the 0.7 wide angle screw on lens for my old Canon Optura DV video camera, and shoved it onto the front of the DLP with rubber bands. This both maximized the image onto the mirror, and increased the size of the final image on the ceiling. It's still far from perfect, but not bad considering that I put this together with some rubber bands and a cheap mirror...
For the star field generation, I used Stellarium, running on my MacBook. That side of it works pretty well. ;)
Tuesday, August 18, 2015
Retro Challenge 2015/7: Post-Mortem and project notes...
Current Project State
For this Summer's Retro Challenge (2015/7), I worked on a small widget that lets you use an Amiga mouse, Atari ST mouse or Atari-style Joystick. I was successful in building it and having it be manually configurable. There's a shell based interface that you can use to select which input device and output style is used.All of the code for this project as well as further and future documentation is available at the project's github repository.
There are a bunch of things that I did complete during the "challenge"...
- Arduino Leonardo based firmware with simple direct connection to a single D9 male connector
- Two versions of the hardware, one quick and dirty, the other optimized for the parts I had.
- Designed to use minimal external parts - just the Arduino board and a D9.
- Serial interface shell to configure which device it is
- Amiga Mouse (fully tested)
- Atari ST Mouse (fully tested)
- Atari Digital Joystick (fully tested)
- Serial interface to select which output the joystick provides
- Mouse movements
- WASD keypress input
- Arrow Key keypress input
- HJKL keypress input
- etc. (support for MAME, Stella, Vice, etc)
- "Explorer" to experiment with input device auto detection algorithm (which does work)
- Amiga 500 keyboard input header (incomplete)
- Amiga 500 to Amiga 1000 keyboard adapter (to RJ-22 4P4C telephone handset jack)
- Documented Amiga keyboard adaption
- Documented Amiga - Atari ST mouse differences
- Documented other D9 joystick pinouts (and how they relate, etc)
There are two features that I did not complete before the end of the month...
First of all, I was unable to get the keyboard support working before the end of the month. I was having a hard time with it only to realize it was a power issue. The keyboard was consuming more power than my widget could provide. It will require a secondary power supply to give enough oomph to get it working. I also was unable to read from it once I hacked in some power.Secondly, I had designed an algorithm to autodetect between the three different supported input devices, but I was not able to integrate the code in before the end of the month. At some point I'll mix it in, and it will switch the kind of device it will be based on analysis of the signals (and signal pairs) of data coming in when it detects "motion".
Next Steps
At this point, I'd like to take the codebase as it exists now, and change the program flow to do the auto-detection of the device type, and then do the "appropriate" thing with it. "out of the box" it will just "do the right thing" when devices are plugged in. Namely:- Amiga mouse becomes USB HID Mouse
- Atari ST mouse becomes USB HID Mouse
- Atari Digital Joystick gets configured to send STELLA keypresses (arrow keys, etc)
Animatronic Avian: Sizing up a skull
I was realizing for a while that I could easily determine the size of the bird I need to make for the "animatronic avian" project. There are photos of José the Macaw, alongside of a "reference human". This reference human is a known 5' 10" tall. Let's call him "Uncle Walt".
Based on a few photos, and general human proportions, we can estimate heights of various unknowns here... (These are all estimations so I'm sure they're off by a little bit, but that's ok for this project.)
Uncle walt is 5'10" tall, or 70". The average human being is 7.5-8 heads tall. Therefore, his head is approximately 8 3/4" tall. Yes. Walt Disney's head was 8 3/4" tall.
I found an image with Walt and José the macaw, where Walt's head is 100 pixels tall. To be fair, it could have been the "barker bird" rather than José. Anyway, in the same image, José is 135 pixels tall. Some simple fractional math from here (which I won't do here since I don't want to spend 30 minutes figuring out how get Blogger to display math stuff) yields that the bird is 11.8" tall from bottom of feet to top of head. Since this is all estimations, I would say that the bird is between 11 3/4" - 12" tall with feathers and fuzz and such.
Now that I have the proportions, and the sizing for this documented, I can proceed to learning how to use the laser cutter at Interlock and design an internal structure a la boat ribs and stringers. I made a boat using this technique back in high school out of balsa wood and MonoKote that worked out well. This time, i'll use some 1/8" wood of some kind instead. I also plan on doing 3d printing for the beak, at least for a form to use for vacuum forming, or perhaps as-is. I haven't figure that all out yet.
Based on a few photos, and general human proportions, we can estimate heights of various unknowns here... (These are all estimations so I'm sure they're off by a little bit, but that's ok for this project.)
Uncle walt is 5'10" tall, or 70". The average human being is 7.5-8 heads tall. Therefore, his head is approximately 8 3/4" tall. Yes. Walt Disney's head was 8 3/4" tall.
I found an image with Walt and José the macaw, where Walt's head is 100 pixels tall. To be fair, it could have been the "barker bird" rather than José. Anyway, in the same image, José is 135 pixels tall. Some simple fractional math from here (which I won't do here since I don't want to spend 30 minutes figuring out how get Blogger to display math stuff) yields that the bird is 11.8" tall from bottom of feet to top of head. Since this is all estimations, I would say that the bird is between 11 3/4" - 12" tall with feathers and fuzz and such.
Now that I have the proportions, and the sizing for this documented, I can proceed to learning how to use the laser cutter at Interlock and design an internal structure a la boat ribs and stringers. I made a boat using this technique back in high school out of balsa wood and MonoKote that worked out well. This time, i'll use some 1/8" wood of some kind instead. I also plan on doing 3d printing for the beak, at least for a form to use for vacuum forming, or perhaps as-is. I haven't figure that all out yet.
Monday, July 13, 2015
Retro Challenge 2015/7 Update 2: Keyboard And Joysticks
Space Invaders running in Stella on my Mac. Jasper loved it!
(He also liked the green light-up USB cable. That's my kid!)
As of last night, I have finished code for the joystick-to-keypress controller, as well as the ability to save the configuration in the EEPROM in the ATmega chip. As usual, the code is all available here on github. What this basically means is that moving the joystick will send down keypress codes to the host computer... so the computer thinks that a keyboard is being used. This means that applications like Stella, an Atari 2600 VCS emulator, which expect you to use the arrow keys and space bar in place of a real joystick, can see those key presses when you move your actual Atari joystick!
You can now pick from a list of keyboard mappings, including:
- Stella (Atari 2600 emulator) (shown above)
- Vice (Commodore 64 emulator)
- Mame (Arcade game emulator)
- WASD (general PC game usage)
- HJKL (vi cursor movements (because why not!))
I have also implemented a basic settings system that saves settings to the EEPROM within the ATmega32u4 chip. It currently has "slots" for a few things, but could be expanded with the above joystick-to-keyboard mapping, to send other keypresses from joystick movements or what have you.
The settings system works with 4 bytes in the EEPROM to determine what's going on with respect to saved settings. The first 3 bytes are a sentinel. If the code does not read the sentinel, it will assume it's on a new device, and will install default values to the EEPROM. The current sentinel are the three hex bytes: { 0x53, 0x44, 0x4c } which are the ASCII string "SDL", my initials. ;) Next at setting slot [3] is the settings version number. Currently this is just '1'. Settings slot [4] contains the usage mode for the interface port. (Mouse/keyboard mapping, etc).
I attempted last week to get an Amiga Keyboard working with this. I wired up an 8 position pin header to the interface board, using the Amiga 500 pinout:
- Data
- Clock
- Reset (toggled when Ctrl-A-A is pressed)
- +5v
- key (missing pin)
- Ground
- Status LED (power)
- In-Use LED (disk access)
I was going to just wire out the Data, Clock, +5 and ground but decided that it made more sense to use the actual A500 pinout. I ran into a problem on this though. The interface can't provide enough power to drive the chips on the interface board. I measured 4.5v at the pin header, then 3.2v down on the interface board itself. This isn't good. I will have to wire up a new interface connector with an external power connector, probably a USB-B jack, to provide dedicated power to the keyboard.
I did however find a phone being discarded, and retrieved the two 4P4C (RJ-22) connectors from it so that I can make a better A1000 keyboard jack. The first one I made used an RJ-45 wall mount jack, which worked somewhat for RJ-22, but it was pretty hacked. ;)
Some thoughts for future additional expansion:
I'm currently going for the "cheap as chips" version of this, which is why there's no interface on it, and you have to connect via serial port to configure it. This was all intentional to keep the build parts list down... to the point where the only necessary part is a D9 connector! However, in using it, a few future revisions may offer more usability at the cost of parts expense:
- Multiple D9 jacks for multiple devices
- Ports dedicated for Mouse, Trackball, Multiple Joysticks, etc
- Could be just 2 that simulate Commodore/Amiga
- Could be 4 to simulate Atari 800 joystick ports
- Could be 1 for mouse, 5 for joysticks, so you never have to disconnect them.
- Would require a parallel-in, serial out shift register, or a port expander
- Expansion at the cost of a few cents, additional wiring, and time to read in the content
- (related) configuration for multiple ports
- User interface - Was thinking that this could be a variety of different methods:
- single pushbutton, Red/Green LED for indication codes (flashing colors)
- single or dual pushbutton, RGB color addressable LED for indication codes
- each could be wired directly to IO pins
- dual pushbutton, 7 segment LED display
- Could indicate use mode(s), etc
- 'C' for commodore mouse, 'A' for atari mouse
- '0'..'7' for joystick mode display
- Could flash multiple digits sequentially for info etc
- Would require LED driver chip
Tuesday, July 7, 2015
Retro Challenge 2015/7 - Amiga Mouse, Joystick, Keyboard USB interface
Once again, it is time for the Retro Challenge! This time around... well, I wasn't sure what I was going to work on,... In my "I want to partake" email, I listed projects such as working on an SD-card based storage drive for the KIM-Uno, my "Bare Metal C64" long term project.. which will likely wait until I retire, as well as working on the Interlock Homebrew Computer System.
Then I started to get parts from an aliexpress order that I placed. I received my Arduino Pro Micro which is the teeny tiny version of the Arduino Leonardo. What makes this special is that the main chip on it is the ATmega 32u4. This is the USB interface chip used in the Arduino Uno. It has all of the standard IO of the 168/328, but with USB HID support. This means that it can pretend to be a USB keyboard, mouse, etc. This is a HUGE feature if you want to make standard computer peripherals.
For some reason, it clicked that I wanted to make a USB HID interface for my Amiga mice. Long story short, within an hour, I had a functional prototype. I was moving my Amiga mouse, and the cursor on my MacBook's screen was moving.
I figure that this will be great for using the Amiga emulators. It'll be nice to use an authentic mouse, joystick and maybe keyboard with UAE, Vice or just for fun for regular usage. I know that there are other projects out there or products that do this kind of thing, but they're a bit pricey to have a widget that I can't expand or repurpose... and besides at its core, this is not really a difficult or expensive product. The most expensive single part so far is the microcontroller, and that was $3.
A little background on the Amiga's mouse...
The way old optical ball mice work is that they have two rollers that sit on a weighted ball, one for the horizontal, and one for the vertical. As the mouse moves horizontally, the horizontal roller moves, and the ball slips on the vertical one. The rollers have an encoding wheel with little windows that make and break optical connections with a pair of sensors. These two sensors generate two bits of data for each direction. (four total.) These two rotary encoders generate a gray code quadrature output.
Movement in one direction outputs: 00 01 11 10 00
Movement in the other direction outputs: 00 10 11 01 00
So, if you read these in a tight loop, and detect changes you can detect movements in the horizontal and vertical directions. In the same loop, if you look at the button inputs, you can determine if the buttons are pressed.
This is the basis for this project. By reading these values from a dumb (no internal processing) Amiga mouse, I can generate vertical and horizontal motion values. I can then send these down the USB HID stack through the Arduino libraries, and voilà , we have an Amiga Mouse to HID USB mouse adapter. NOTE: PS2 and ADB mice have more smarts in them and output movement deltas rather than optical sensor pulses. Reading either of those requires serial communications and protocol decoding instead.
Within an hour of this brainstorm, I had this prototype:
Unfortunately, the serial cable I was using had all of the wires connected except for the line used for the right mouse button. Oh well... For the "what's available on my desk" approach, it was good enough for a proof of concept.
From there, some simple acceleration was added to convert "quick" movements of the mouse to "large deltas" sent down as mouse movements...
The way I implemented acceleration was that each time through the loop, i check for Horizontal or Vertical ticks. I store the ticks as +1, 0, or -1 in an array of the last 128 readings. Then, I sum the entire 128 elements of each (horizontal and vertical) array, and use that as the mouse movement. The faster the mouse is being moved, the more +1s or -1s there will be, so it sends a larger number. It was a quick hack that I thought might work, that turned out to work perfectly!
Some upcoming additions that I might / probably will do:
- Atari ST Mouse Support. The only difference between an Atari and Amiga mouse are that two of the lines (specifically D9 pins 1 and 4) are swapped. This is an easy change in software. The difficult part is tracking down an Atari ST mouse to test with!
- Atari (Digital) Joystick Support. By combining the button read code with the acceleration code hinted at above, I can convert Joystick movements to HID mouse movements
And really, from that point, it would be near trivial to add in HID keyboard support as well... I can send down WASD key presses for joystick movements... or really any other key presses based on joystick movements.
Additional features may include support for Amiga keyboards as HID keyboard, joystick as HID gamepad, etc. In preparation for working with one of my old Amiga 1000 keyboards, I cleaned one up to get the years of finger grime of of it...
Here's the (yellowed) keyboard with some keys removed. (The 'X' key has been missing for years, sadly.) The proprietary cleaning solution is in that "Cascade" container. I would use that dental pick tool and my hand noodles to pop the keys off of the keyboard. Then I dropped them into the cleaning solution. After about 30 minutes, I pulled each one out, wiped it off with my fingers, rinsed it off, and they were as clean as new. The proprietary cleaning solution is one squirt of dish soap with some warm water. ;)
NOTE: Not shown is the process of removing all of the lint, hair and other bits of whatever that were stuck between the keys because that's kinda gross and you don't really want to see that anyway..
More on this project to come...
I briefly explored the idea of supporting Mac/Apple IIgs ADB mouse and keyboard support, but I quickly learned the complexity of the ADB spec, and am putting that safely outside of the scope of this project!
The code for this project and other development details are available on github in the AmigaInputToUSB repository.
Then I started to get parts from an aliexpress order that I placed. I received my Arduino Pro Micro which is the teeny tiny version of the Arduino Leonardo. What makes this special is that the main chip on it is the ATmega 32u4. This is the USB interface chip used in the Arduino Uno. It has all of the standard IO of the 168/328, but with USB HID support. This means that it can pretend to be a USB keyboard, mouse, etc. This is a HUGE feature if you want to make standard computer peripherals.
For some reason, it clicked that I wanted to make a USB HID interface for my Amiga mice. Long story short, within an hour, I had a functional prototype. I was moving my Amiga mouse, and the cursor on my MacBook's screen was moving.
I figure that this will be great for using the Amiga emulators. It'll be nice to use an authentic mouse, joystick and maybe keyboard with UAE, Vice or just for fun for regular usage. I know that there are other projects out there or products that do this kind of thing, but they're a bit pricey to have a widget that I can't expand or repurpose... and besides at its core, this is not really a difficult or expensive product. The most expensive single part so far is the microcontroller, and that was $3.
A little background on the Amiga's mouse...
The way old optical ball mice work is that they have two rollers that sit on a weighted ball, one for the horizontal, and one for the vertical. As the mouse moves horizontally, the horizontal roller moves, and the ball slips on the vertical one. The rollers have an encoding wheel with little windows that make and break optical connections with a pair of sensors. These two sensors generate two bits of data for each direction. (four total.) These two rotary encoders generate a gray code quadrature output.
Movement in one direction outputs: 00 01 11 10 00
Movement in the other direction outputs: 00 10 11 01 00
So, if you read these in a tight loop, and detect changes you can detect movements in the horizontal and vertical directions. In the same loop, if you look at the button inputs, you can determine if the buttons are pressed.
This is the basis for this project. By reading these values from a dumb (no internal processing) Amiga mouse, I can generate vertical and horizontal motion values. I can then send these down the USB HID stack through the Arduino libraries, and voilà , we have an Amiga Mouse to HID USB mouse adapter. NOTE: PS2 and ADB mice have more smarts in them and output movement deltas rather than optical sensor pulses. Reading either of those requires serial communications and protocol decoding instead.
My cheat sheet for pinouts and connection information.
Within an hour of this brainstorm, I had this prototype:
Arduino Pro Micro (ATmega32u4), with headers and D9 cable attached.
Commodore Amiga mouse plugged into a spare serial cable re-used as a D9 cable.
From there, some simple acceleration was added to convert "quick" movements of the mouse to "large deltas" sent down as mouse movements...
The way I implemented acceleration was that each time through the loop, i check for Horizontal or Vertical ticks. I store the ticks as +1, 0, or -1 in an array of the last 128 readings. Then, I sum the entire 128 elements of each (horizontal and vertical) array, and use that as the mouse movement. The faster the mouse is being moved, the more +1s or -1s there will be, so it sends a larger number. It was a quick hack that I thought might work, that turned out to work perfectly!
Some upcoming additions that I might / probably will do:
- Atari ST Mouse Support. The only difference between an Atari and Amiga mouse are that two of the lines (specifically D9 pins 1 and 4) are swapped. This is an easy change in software. The difficult part is tracking down an Atari ST mouse to test with!
- Atari (Digital) Joystick Support. By combining the button read code with the acceleration code hinted at above, I can convert Joystick movements to HID mouse movements
And really, from that point, it would be near trivial to add in HID keyboard support as well... I can send down WASD key presses for joystick movements... or really any other key presses based on joystick movements.
Additional features may include support for Amiga keyboards as HID keyboard, joystick as HID gamepad, etc. In preparation for working with one of my old Amiga 1000 keyboards, I cleaned one up to get the years of finger grime of of it...
The right side has been cleaned using my proprietary cleaning technique described below.
Keyboard in the process of being cleaned. More like CLEANBOARD. HAHAHA. :(
NOTE: Not shown is the process of removing all of the lint, hair and other bits of whatever that were stuck between the keys because that's kinda gross and you don't really want to see that anyway..
More on this project to come...
I briefly explored the idea of supporting Mac/Apple IIgs ADB mouse and keyboard support, but I quickly learned the complexity of the ADB spec, and am putting that safely outside of the scope of this project!
The code for this project and other development details are available on github in the AmigaInputToUSB repository.
Post Backlog...
I've got a bunch of projects I've been working on here and there. I'm a bit behind with this. That seems to be a theme. I'll be putting up posts over time of various things...
Sunday, January 18, 2015
KIM-UNO (Software)
As mentioned in the previous post about the hardware for my implementation of the KIM-UNO, some changes needed to be made to accommodate the updated hardware. First, let's look at the new schematic layout for the updated circuitry:
The reference version had a 3x8 matrix, and this one uses 4x6. I tried doing this a few different ways. I knew (or at least I thought I knew) that I needed to come up with something different for scanning the keypad since this has a common-cathode LED display. (It's what I had in my toolbox.) I tried one version that added about a dozen resistors... It didn't work. I tried one with a half dozen resistors, and a dozen 1N1914 diodes... that didn't work either.
On a whim, I decided to just hook it up directly and see how it goes... I tried scanning the keypad myself but it wasn't working. I tried scanning the keypad using the Arduino Keypad library, with nothing else, and that worked fine... okay. got something.
I then added the Keypad library to my test program that displayed stuff to the LED display, and it was broken again. Okay. so it's something between the two of them. What I came up with is far from optimal, but it works. (The screen flickers visibly a tiny bit... which might also be due to the added 220 ohm resistors, making the display dimmer than before.)
First, I replaced the code block that handles the LED rendering in the KIM UNO program with my display routine which works well. I've included the arduino/c code here in case someone else is crazy enough to do this.
Next, I replaced the code block that handles the 3x8 keypad scanning with mine; It initializes the keypad lines every time through the loop. The LED scanning gets things into an unexpected/unwanted state for the Keypad scanning. It's kind of a kludge, but it works well enough. Once it scans the keypad, I munge the output data slightly to match up with the original code. I filled in the keypad library to return the proper key codes. The only one i had to monkey with was the SST toggling. Not a big deal though.
The reference version had a 3x8 matrix, and this one uses 4x6. I tried doing this a few different ways. I knew (or at least I thought I knew) that I needed to come up with something different for scanning the keypad since this has a common-cathode LED display. (It's what I had in my toolbox.) I tried one version that added about a dozen resistors... It didn't work. I tried one with a half dozen resistors, and a dozen 1N1914 diodes... that didn't work either.
On a whim, I decided to just hook it up directly and see how it goes... I tried scanning the keypad myself but it wasn't working. I tried scanning the keypad using the Arduino Keypad library, with nothing else, and that worked fine... okay. got something.
I then added the Keypad library to my test program that displayed stuff to the LED display, and it was broken again. Okay. so it's something between the two of them. What I came up with is far from optimal, but it works. (The screen flickers visibly a tiny bit... which might also be due to the added 220 ohm resistors, making the display dimmer than before.)
First, I replaced the code block that handles the LED rendering in the KIM UNO program with my display routine which works well. I've included the arduino/c code here in case someone else is crazy enough to do this.
void driveLEDs_CommonCathode( void )
{
char digit = 0;
for( byte i = 0 ; i<3 ; i++ )
{
for( byte j = 0 ; j<2 ; j++ )
{
// get the current byte to display
byte b = threeHex[i][j];
// get the segment mask
byte s = dig[b];
// select just this digit
for( int d=0 ; d<8 ; d++ ) {
pinMode( ledSelect[d], OUTPUT ); // make sure we're output
digitalWrite( ledSelect[d], (d==digit)?LOW:HIGH );
}
// now go through and turn on/off the right segments
for( byte col =0 ; col <8 ; col++ )
{
pinMode( aCols[col], OUTPUT );
digitalWrite( aCols[col], (s & (0x80>>col))? HIGH : LOW );
}
// wait a moment...
delay( 2 ); // necessary?
// go to the next display digit
digit++;
}
}
}
Next, I replaced the code block that handles the 3x8 keypad scanning with mine; It initializes the keypad lines every time through the loop. The LED scanning gets things into an unexpected/unwanted state for the Keypad scanning. It's kind of a kludge, but it works well enough. Once it scans the keypad, I munge the output data slightly to match up with the original code. I filled in the keypad library to return the proper key codes. The only one i had to monkey with was the SST toggling. Not a big deal though.
The second half is pretty much lifted directly from the core scanKeys().
#include <Keyboard.h>
void scanKeysFourBySix()
{
static int keyCode = -1, prevKey = 0;
static unsigned long timeFirstPressed = 0;
// scan the keys and then remap them
int i;
// first, wipe everything
for( i = 0 ; i<8 ; i++ ) {
pinMode( aCols[i], INPUT );
digitalWrite( aCols[i], LOW );
pinMode( ledSelect[i], INPUT );
digitalWrite( ledSelect[i], LOW );
}
for( i=0 ; i<ROWS ; i++ ) {
pinMode( rowPins[i], INPUT );
digitalWrite( rowPins[i], HIGH );
}
for( i=0 ; i<COLS ; i++ ) {
pinMode( colPins[i], OUTPUT );
digitalWrite( colPins[i], HIGH );
}
char key = keypad.getKey();
if( key == NO_KEY && ((keypad.getState() == IDLE) || ( keypad.getState() == RELEASED ))) {
prevKey = 0;
return;
}
// convert key to keycode (addressing in the other matrix )
if( key == 't' ) {
// sst toggle
key = SSTmode==0?']':'[';
}
if( key != NO_KEY )
keyCode = key; // fill this.
if (keyCode!=prevKey)
{
prevKey = keyCode;
curkey = key; // we're already decoded. parseChar(keyCode);
timeFirstPressed=millis(); //
}
else // if pressed for >1sec, it's a ModeShift key
{
if ((millis()-timeFirstPressed)>1000) // more than 1000 ms
{
if (key == '[' || key == ']' ) //keyCode==17) //it was the SST button
{
keyboardMode=(keyboardMode==0?1:0); // toggle
// Serial.print(F(" Eeprom R/O "));
Serial.print(F(" keyboardMode: ")); Serial.print(keyboardMode, DEC);
SSTmode=0;
curkey=0; // don't do anything else with this keypress
}
if (keyCode==18) // it was RS button // fix
curkey = '>'; // toggle eeprom write protect
timeFirstPressed=millis(); // because otherwise you toggle right back!
}
}
}
Saturday, January 17, 2015
KIM-Uno
I ordered a KIM-UNO kit, which should arrive in a couple weeks, but in the meantime, I decided to see if I could cobble one together with parts I had around... Turns out, I can.
I used an Arduino Uno R3 as the base micro board. On top of that I have a Seeed Studio protoshield, with connectors for the display and keypad, as well as 220 ohm resistors for the display.
Not the best soldering job ever, but it'll do.
I went through a bunch of different versions of the circuit for the keypad scanning, and I finally resorted to using a breadboard to figure things out. Since I switched this from a common anode to a common cathode display, the circuit for the keypad matrix got all confused as-is.
In a nut, the polarity of the power to the display was reversed, which caused the keyboard to not scan properly. I had tried a few circuits that should have worked, but didn't... one with a load of diodes, one with a mess of resistors... I eventually decided to just wire it in directly, and use the Keypad library. Once I realized i had to manually initialize the pins before scanning, it all Just Worked(TM).
To test those bits, I made a sample Arduino sketch that displays and scans the keyboard so that I could get the code working with these devices.
The display itself is an 11 digit 7 segment display that I found up in Active Surplus on Queen Street, Toronto, a bunch of years back. KIM emulation only uses 6 of the digits. (More about this display module in this other post.)
The keypad and case I got from a hamfest... they were part of some project that someone was working on at one point. I have a second case like this somewhere. The above picture shows the printed out keypad labels (Futura font) which I cheapo-laminated to the case using lots of magic transparent tape.
Mix in a little 9v battery snap, a power switch, a piece of red gel, and I've got my own little portable KIM clone
I should note that I also had to hack the KIM-UNO source project a little to support my display (Common Cathode instead of Common Anode) as well as to support my keypad which is wired as 4x6 buttons, rather than the 3x8 that the reference project uses. A few evenings of hacking on the source and here we are!
I've also got a post up about the software/firmware modifications I made on the KIM-UNO source...
I've also got a post up about the software/firmware modifications I made on the KIM-UNO source...
Subscribe to:
Posts (Atom)