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.
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.

#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!
    }          
  }

}

The second half is pretty much lifted directly from the core scanKeys().

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...

Monday, November 10, 2014

Flat panel light box


I've been getting into making stained glass pieces, as I've been taking a class at the Rochester Memorial Art Gallery.  One of the tools they have available there is a light box, which I have used to make the template for the macaw piece I'm making.  I used it to help me adapt a pattern I found online into something that better suits my needs.  I traced it, then retraced that sketch.

The light box also works well to see how things look with light behind them, however it's not something I can use a lot for this, since my project is a couple dozen pieces of glass and we have to share the light box.


On the recycle pile at work was a couple of old, broken laptops.  I snagged two of them; one with an LED backlight, and one with a CCFT backlight.  I thought that the LED one would be easier to get working.


Over at Interlock, I tore apart the screens, tossing out the LCD panel, so I was left with just the light source, light guide, diffusion screens, and control circuitry.  Its control/driver board also managed the LCD itself.  There were many test points on the back, so I applied power to the "LED PWR" pin, ground to a ground point, then about +5 volts to the BLEN (assuming it to be "backlight enable") as well as the "PWM" test point. After futzing with it for a little bit, I gave up and focused efforts on the CCFT-based one.

The slightly larger CCFT (Fluorescent) based one had a single board that connected to the backlight tube through standard white/pink silicone-insulated wiring.  The board itself had one tiny connector on one side with a few pins that seemed to have obvious use.  V+, which assumably powers the backlight circuitry, should be connected to +5 or maybe +12.  GND, which of course is ground. Then two other connections "EN" and "CTRL", which I guessed to be "Enable" and "Control".  A guess would be to tie these to a logic "high" which might maybe enable the thing.

I connected just the V+ and GND to a power supply, and applied power.  Ranging from 0v up through 12v yielded no results. I connected the other two logic lines to power too, and started ramping up the power.  At around 7v, the backlight flickered on, but then wouldn't do anything until I brought the power back to 0v, and then back up again.

On a hunch, I figured that the backlight needs a higher voltage, and the logic stays at TTL levels.  Applying the same power to both would give a possible point between the two where both kinda worked, which is where I saw the flicker.  I hacked together two power supplies, with grounds tied together, 5v from one power brick, and the V+ to the variable supply.


I ramped up the voltage, and sure enough, it would get dim around 7v, then go full brightness around 12v.  It seemed to use about 300mA to drive it too. Good to know.  I found a 12v power brick and.. it would light for about 20 seconds then power itself off.  The 12v brick put out 18v.

I eventually found a brick that worked, so i hooked up two supplies, a 5v and a 12v and it was stable and bright.  Next would be the task to put in a 5v regulator to provide the 5v it needs, so i can run it all on one single power supply.


A simple circuit using a 7805 and two capacitors later, and I have 12v in, and a backlight lit!  I wrapped the circuit in tape (purple because it was there), hooked it up to a power connector, and reassembled the case.


Best of all, it all managed to fit within the old plastics. Huzzah!

Now I just need to put something on the diffusers to protect them from cut glass, maybe a piece of plexi, or even a large Ziplock or plastic wrap, and I'll be set!

Wednesday, November 5, 2014

Kindle 2 Repair



Again, from the recycle pile, I found something very nifty.  It was a broken Amazon Kindle 2 with 3G cell modem.  The screen was very messed up.  I attempted to charge it, which seemed to work.  I was able to connect it to my computer, and see the files on it, so I knew it was somewhat working.  A quick search on ebay showed a used, working eInk screen was $20.  I asked around on a few Kindle boards online about repairs, or getting Amazon to repair it, and the basic overall response was "just buy a new one".  That wasn't the point.


I eventually decided to drop the $20, order the screen, and take my chances that the main unit works and has decent battery life.  A few days later, I received what you see above.  I love how eInk displays hold their last image.  It's a pretty good sign that this one has a standard Kindle startup image showing on it.


Lots of screws holding this thing together.  After assembling and reassembling it a few times I got pretty fast at doing the whole procedure.  I wouldn't have been able to do it without resources like iFixit who provided teardown and disassembly procedures.


The battery removed from the left.  You can see, left to right, Battery bay, 3G sim card slot, cellular modem.  The orange bit at the top is the display screen ribbon connection.


The inside of the upper case, showing the orange flex cables for the side buttons and such.


Just for good measure, here's the entire board, removed from the casing.

That explains the bad screen display.

All in all, it took about an hour.  I had to disassemble and reassemble it a few times to get the display flex cable seated properly, but once it was, it all just worked.  Battery life is still excellent on it, the 3G service works great, and I've loaded it up with a bunch of books to read.


I hacked it a little to change the sleep display images but other than that, it's pretty stock.  Not bad for $20 and some manual labor!

I should note that about a week after I performed this operation, it suddenly decided that it would constantly press the "4" key for me.  Very nice of it, but not very convenient.  I disassembled it all again.  The keypad buttons all looked okay to me.  I even removed the '4' key from the main board to examine it, but it looked fine.  Something about that process, however, seemed to have fixed the problem.  It is currently working perfectly, and other than the battery dying on me, after 4 months of use, it has performed excellently.  :D

Friday, August 1, 2014

Been Busy...

I've been busy on things recently, although any time in front of the computer has been spent on programming project(s)/paying contract work rather than writing blog posts, so I'm a bit behind in getting things documented here.

I've done quite a bit of hardware-ey projects in the past few months... every Tuesday night for me is my "hardware hacking" night at Interlock, but by the time I get home I'm too tired to write up what I worked on... so I've gotten horribly behind!

I've got a bunch of what I think are really neat things I've worked on that I'll get up online here soon...  One cool retro-programming-hardware project, a few item repairs (monitor, Kindle, etc), and a couple of Lego-based electronic projects..

Monday, June 16, 2014

Lego Series 1: Benny's Spaceship

This is the first post of a new series of Lego-related posts.  I have a few things I've been designing that I think are neat, or in this case, are fixes for existing sets.

The Lego Movie came out last year, and it was AWESOME.  I bought 70816 "Benny's Spaceship, Spaceship, SPACESHIP", and had a great time building it.

After re-watching the film, I noticed a couple of differences between the model in the movie and the real-life one.  Let's start off this series by showing two of these differences in Benny's spaceship, as well as a very simple modification to fix one if them.

Behold, the completed spaceship, and it is awesome:


First, I'll point out something that cannot be fixed.  Here's a shot of the ship from the movie:


1.  The side intake

 

Right in the center of the above images, you can see a 61409 1x2 slope with 4 slots. I should note here that there are a few different versions/names of grays, including light blue-gray, dark gray etc, but for the sake of simplicity, I'll just use "light gray" and "dark gray" in this series.  The model in the movie (first image) shows this part in light gray, while the constructed model is dark gray.  This part is not available, nor has it ever been, in light gray.  So, sadly, we can't fix this one.

2.  Astro Kitty's bracket





If you look carefully in the above image of Benny's ship, you will notice that the area that holds Astro Kitty in place is different than the model.  I have fixed this and you can see the results in the above images.  The first one shows the version from the model, whereas the second one is film-accurate.

The parts for the storebought model: (left to right)
- 30375 dark gray robot torso
- 11476 light gray 1.2 with clip on horizontal side
- 11477 dark gray 2x1 curved slope (x2)

The parts for the film-accurate model: (left to right)
- 2555 light gray 1x1 with clip
- 30375 dark gray robot torso
- 30377 light gray robot arm (x2)
- 2540 dark gray 1x2 with handle on side
- 11477 blue 2x1 curved slope (x2)

Thursday, April 24, 2014

Fixing Pac-Man - Attract mode with less burn-in


One of the problems with Pac-Man, especially for home use, is that once a coin is dropped in, or you have it in Free Play mode, it will sit on the "Press Start" button screen forever, until all of the credits are depleated... which can take a long time, especially in Free Play mode. ;)

After being inspired by the ET bugfix project (a great read, btw), I decided to attempt to fix this myself. I should note that there are other versions of this fix on the net, and I have no idea if any of those are better or worse than mine.  Mine is a total of 30 bytes changed in the ROM.


My first thought is that it switches into the "Press Start" screen after it has some credits in it.  So the first thing to look for in the Ms. Pac-Man documented disassembly is the RAM location for number of credits in the machine.


At the top of the disassembly, are a bunch of RAM locations that have been decoded by contributors. As you can see, 0x4e6e contains the number of credits in the system.  Next thing to do is to search for "4e6e" in the file, and sooner or later, I figured I'd find the right location.  There's got to be a section of code that reads a value in from this, and compares it with 0 to determine if it should stay in attract mode or show the "Press Start" screen.  Sure enough...


Here we see a snippet of code.  This is in the main attract sequence.  This block of code above draws the number of credits on the screen (at 03fe), then checks the number of credits against zero (0401-0405).  If it's still 0, it goes to 0x0413, where it continues through the attract sequences.  Otherwise, it falls through, to some code (0407-0412) that advances the game mode to the dreaded "Press Start" screen that we want to eliminate.  Jackpot!

All that I need to do now, is to patch off of this code to my own routine.  The basic thought (which did work out) is that the only way that it will switch to the "Press Start" screen is if the user is pressing start.  Once it changes to that screen, the start button will still be pressed, and the game will just start.

This means that the only way that the code from 0407-0412 will get run here is if there is not zero credits AND a start button is being pressed.  On top of this, we don't want to run that code when the user is pressing 2P start unless there's at least 2 credits.



And that is the entire patch.  30 bytes of code.

The original code will check if there's credits in the machine.  If there are, it falls through to 0407, which is where my code takes over.

It simply jumps to some unused space in the ROM, starting at 0f3c.  "attStTest" checks to see if the user is pressing P1 or P2 start.  If they're not, we jump on over to 0413, as before, to continue with the attract sequence.  If they are pressing P2 start, it does the extra check in "credChk2" to make sure that there's at least 2 credits in the machine.  If there's not, it again will jump over to 0413.  Finally, we know that we can switch the game mode to the "Press Start" screen, where our button press will promptly get gobbled up, and the game will start.

The code in "startIt" should look a little familiar.  The first two opcodes are the opcodes we overwrote in 0407 where we jumped over here to this mess.  Then we jump back to "startItR" return location, and the original code resumes at 040b, performing the game mode switch.  For clarity, I could have dropped the remaining 4 opcodes which start at 040b in here, but I decided to save space and do it this way.

30 bytes different, and the game is the way it should be... especially if your friends come over to your basement arcade, and press the credit button 12 times, or you have it set on Free Play. ;)