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

No comments:

Post a Comment