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