Project tutorial
Atari 65XE as USB-Keyboard

Atari 65XE as USB-Keyboard © GPL3+

Retro Atari 65XE plus Arduino Leonardo as USB-keyboard for a modern computer. It will leave the opportunity to use this Atari in native mode.

  • 1,945 views
  • 0 comments
  • 6 respects

Components and supplies

Apps and online services

About this project

Making retro Atari 65XE as USB-keyboard for a modern computer. And it will leave the opportunity to use this Atari in the native mode. Arduino Leonardo is used for connect the Atari's keyboard to an USB. With an UNIX this keyboard will works without any restrictions. With Windows it is need to switch on some USB-mouse at BIOS startup for boot with this keyboard. For Apple or others will need some corrections within the Arduino program for a keys order correction.

There are no other reasons besides a nostalgia.

This Atari 65XE is near 30 years old. And he works. For add one more function for him - the USB-keyboard - is needed only Arduino Leonardo, not a lot of wires, an USB-cable. No a DC-adapter of Atari will needed for this function.

Only 34 soldering points is need to make. Because the pitch of contacts on slots of the Atari's keyboard and on Arduino is 2.54 mm, the process of soldering is easy.

After soldering wires from Arduino to J8 connector of Atari, Arduino can be placed at any cozi position under the case. The USB-cable need to be connect to Arduino and let out from the Atari's case. Now possible to use this Atari like regular USB-keyboard.

Not all keys of the retro Atari is correspond to keys of a modern PC-keyboard. Some keys of Atari will be with 2 functions to make all PC's comands. It is possible to make some differents layots within the Arduino sketch. Within the layot of the Arduido sketch thats here, mainly keys of Atari corresponded to PC-keys, but this ones are need to be noted:

In addition to the USB-keyboard usage it remains possible to enable this Atari in the native mode. But, of course, not at the same time when he are connected via an USB to a PC like a keyboard.

Flash Arduino Leonardo is easy via an USB. So, download:

* Because here all ICs of Atari is stayed in his places (that makes possibility of Atari to work in the native mode) when Arduino scanning the keyboard's matrix, time to time some random signals is appears from a chips. Mainly them affects keys "Pause" and "Control" as tested. Some protection from this signals is maked within the Arduino sketch and was tested. But if libraries "keyboard" and "keypad", that is developed independent will change incompatible, some weirds can ocured. For this case here fixed for download the versions of libraries that was tested with the Arduino sketch. This libraries will be need only if the Arduino sketch will no work with actual libraries.

Code

Arduino sketchArduino
the Arduino sketch that need to flash to Arduino Leonard within Arduino ID
#include <Keypad.h> // with v.3.1.1 tested
#include <Keyboard.h> // with v.1.0.2 tested

const byte ROWS=8;
const byte COLS=9;
// key names for keyboard scanning
char keys[ROWS][COLS] = {
{'7',NO_KEY,'8','9','N','<','>','B','P'},
{'6',NO_KEY,'5','4','3','2','1','E',NO_KEY},
{'u',NO_KEY,'i','o','p','_','=','R',NO_KEY},
{'y',NO_KEY,'t','r','e','w','q','T',NO_KEY},
{NO_KEY,'j','k','l',';','+','*',NO_KEY,'C'},
{NO_KEY,'h','g','f','d','s','a','U',NO_KEY},
{'n',' ','m',',','.','/','A',NO_KEY,NO_KEY},
{NO_KEY,'F','b','v','c','x','z',NO_KEY,'S'}};

// key aliases for Alt/Ctrl/Shift+Ctrl(arrows)/without modifiers cases
char kb[ROWS][COLS] = {
{'7',NO_KEY,'8','9','0','<','>',KEY_BACKSPACE,NO_KEY},
{'6',NO_KEY,'5','4','3','2','1',KEY_ESC,NO_KEY},
{'u',NO_KEY,'i','o','p','_','=',KEY_RETURN,NO_KEY},
{'y',NO_KEY,'t','r','e','w','q',KEY_TAB,NO_KEY},
{NO_KEY,'j','k','l',';','+','*',NO_KEY,NO_KEY},
{NO_KEY,'h','g','f','d','s','a',KEY_CAPS_LOCK,NO_KEY},
{'n',' ','m',',','.','/',NO_KEY,NO_KEY,NO_KEY},
{NO_KEY,KEY_F1,'b','v','c','x','z',NO_KEY,NO_KEY}};

// key aliases for Shift case
char kbShft[ROWS][COLS] = {
{byte(39),NO_KEY,'@','(',')',NO_KEY,KEY_INSERT,KEY_DELETE,NO_KEY},
{'&',NO_KEY,'%','$','#','"','!',KEY_ESC,NO_KEY},
{'U',NO_KEY,'I','O','P','-','|',KEY_RETURN,NO_KEY},
{'Y',NO_KEY,'T','R','E','W','Q',KEY_TAB,NO_KEY},
{NO_KEY,'J','K','L',':',byte(92),'^',NO_KEY,KEY_LEFT_CTRL},
{NO_KEY,'H','G','F','D','S','A',KEY_CAPS_LOCK,NO_KEY},
{'N',' ','M','[',']','?',KEY_LEFT_ALT,NO_KEY,NO_KEY},
{NO_KEY,KEY_F1,'B','V','C','X','Z',NO_KEY,NO_KEY}};

// key aliases for Ctrl+Tab case
char kbM[ROWS][COLS] = {
{KEY_F7,NO_KEY,KEY_F8,KEY_F9,KEY_F10,KEY_F11,KEY_F12,KEY_BACKSPACE,NO_KEY},
{KEY_F6,NO_KEY,KEY_F5,KEY_F4,KEY_F3,KEY_F2,KEY_F1,'`',NO_KEY},
{'u',NO_KEY,'i','o','p',KEY_PAGE_UP,KEY_PAGE_DOWN,KEY_RETURN,NO_KEY},
{'y',NO_KEY,'t','r','e','w','q',NO_KEY,NO_KEY},
{NO_KEY,'j','k','l',';',KEY_HOME,KEY_END,NO_KEY,NO_KEY},
{NO_KEY,'h','g','f','d','s','a',KEY_CAPS_LOCK,NO_KEY},
{byte(252),' ','m','{','}','~',KEY_LEFT_ALT,NO_KEY,NO_KEY},
{NO_KEY,KEY_F1,'b','v','c','x','z',NO_KEY,KEY_LEFT_SHIFT}};

byte rowPins[ROWS] = {11, 12, 18, 19, 20, 21, 22, 23};
byte colPins[COLS] = {2, 3, 4, 5, 6, 7, 8, 9, 10};
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
int r, c;
bool isShft, isAlt, isCtrl, isM, isCSArrows, isTab, isPause;
bool isPress, isHold, isReleased;
bool PurgeM;
char kp;

void setup() {
  kpd.setDebounceTime(20);  // may need to be tuned
  r=c=0;
  isPress=isHold=isReleased=false;
  PurgeM=false;
  Keyboard.begin();
}

void loop() {
if (kpd.getKeys() || isHold || isShft || isM || isCSArrows || isAlt || isCtrl) {
  isShft=isAlt=isCtrl=isM=isCSArrows=isTab=isPause=false;
  kp=NO_KEY;
  
  // scan the whole key list
  for (int i=0; i<LIST_MAX; i++) {
    switch (kpd.key[i].kchar){
      case 'S': isShft=true; break;
      case 'A': isAlt=true; if (kpd.key[i].kstate==RELEASED) {isReleased=true; isPress=isHold=false;} break;
      case 'C': isCtrl=true; break;
      case 'P': isPause=true; break;
      case 'T': isTab=true; break;
      case NO_KEY: break;
      default: kp=kpd.key[i].kchar; break;
    }
    if (!isPause && (kp!=NO_KEY)) {
      switch (kpd.key[i].kstate) {
        case PRESSED: isPress=true; isHold=isReleased=false; break; 
        case HOLD: isHold=true; isPress=isReleased=false; break;
        case RELEASED: isReleased=true; isPress=isHold=false; break;
      }                
    }
  }
  
  // parse for modifiers and state
  if ((isShft || isCtrl || isAlt) && isPause) {isPause=false;}
  if (isShft && isCtrl) {isCtrl=false;}
  if (isCtrl && isTab) {isM=true; isCtrl=false; isTab=false;}
  if (isShft && isTab) {isCSArrows=true; isShft=false; isTab=false;}
  if (isTab) {
    kp='T';
    if (kpd.isPressed(kp)) {isPress=true; isHold=isReleased=false;} else {isReleased=true; isPress=isHold=false;}
  }
  if (isPause) {isPause=false;}

  // parse for only Alt and only Shift+Alt cases
  if (kp==NO_KEY) {
    if (isAlt && isReleased && !PurgeM) {
      if (isShft) {
        Keyboard.press(KEY_LEFT_ALT); Keyboard.press(KEY_LEFT_SHIFT); Keyboard.releaseAll();
        } else {
        Keyboard.press(KEY_LEFT_ALT); Keyboard.releaseAll();
      }
      while (kpd.findInList('A')>=0) {kpd.getKeys();}
      isReleased=false; PurgeM=false;
    }
    if (isAlt && isReleased && PurgeM) {
      while (kpd.findInList('A')>=0) {kpd.getKeys();}
      isReleased=false; PurgeM=false;
    }
  }

  // parse for keys with modifiers
  if (kp=='P') {kp=NO_KEY;}
  if (kp!=NO_KEY) {
    if (isPress || isHold) {
      if (isHold) {delay (40);} // may need to be tuned
      for (int rc=0; rc<ROWS; rc++) {
        for (int cc=0; cc<COLS; cc++)
        {
          if (kp==keys[rc][cc]) {r=rc; c=cc;};
        }
      }
      if (isShft && !isAlt) {
        Keyboard.print(kbShft[r][c]);
        delay (100);  // may need to be tuned
      }
      if (isCtrl) {
        switch (kb[r][c])
        {
          case '_': Keyboard.press(KEY_UP_ARROW); break;
          case '+': Keyboard.press(KEY_LEFT_ARROW); break;
          case '*': Keyboard.press(KEY_RIGHT_ARROW); break;
          case '=': Keyboard.press(KEY_DOWN_ARROW); break;
          case '>': Keyboard.press(KEY_LEFT_CTRL); Keyboard.print('>'); break;
          default: Keyboard.press(KEY_LEFT_CTRL); Keyboard.print(kb[r][c]); break;
        }
        while (kpd.findInList(kp)>=0) {kpd.getKeys();}
        isReleased=true;
      }
      if (isAlt) {
        Keyboard.press(KEY_LEFT_ALT);
        if (!isShft) {Keyboard.print(kb[r][c]);} else {Keyboard.print(kbShft[r][c]);}
        while (kpd.findInList(kp)>=0) {kpd.getKeys();}
        isReleased=true;
      }
      if (isM) {
        Keyboard.print(kbM[r][c]);
        while (kpd.findInList(kp)>=0) {kpd.getKeys();}
        isReleased=true;
      }
      if (isCSArrows) {
        switch (kb[r][c])
        {
          case '_': Keyboard.press(KEY_LEFT_SHIFT); Keyboard.press(KEY_UP_ARROW); break;
          case '+': Keyboard.press(KEY_LEFT_SHIFT); Keyboard.press(KEY_LEFT_ARROW); break;
          case '*': Keyboard.press(KEY_LEFT_SHIFT); Keyboard.press(KEY_RIGHT_ARROW); break;
          case '=': Keyboard.press(KEY_LEFT_SHIFT); Keyboard.press(KEY_DOWN_ARROW); break;
          default: Keyboard.press(KEY_LEFT_CTRL); Keyboard.press(KEY_LEFT_SHIFT); Keyboard.print(kb[r][c]); break;
        }
        while (kpd.findInList(kp)>=0) {kpd.getKeys();}
        isReleased=true;
      }
      if (!isShft && !isCtrl && !isAlt && !isM && !isCSArrows)
      {
        Keyboard.print(kb[r][c]);
      }
    }
    if (isReleased) {
      if (isAlt) {PurgeM=true;}
      Keyboard.releaseAll();
      isPress=isHold=isReleased=false;
    }
  }
}
}

Comments

Similar projects you might like

Mega Bread - Atari Joystick Linking for Robotics Control

Project in progress by Pigeon-Kicker

  • 2,016 views
  • 3 comments
  • 10 respects

Arduino Atari Adaptor

Project tutorial by Dante Roumega

  • 11,269 views
  • 6 comments
  • 31 respects

Ternary Chord Keyboard

Project tutorial by Mr_Glenn

  • 4,015 views
  • 4 comments
  • 9 respects

Arduino Telegraph

Project showcase by Dylan Todtfeld

  • 2,157 views
  • 0 comments
  • 8 respects

Retro Arcade Clock

Project tutorial by NZDoug

  • 7,539 views
  • 13 comments
  • 61 respects

Simon Says 80s Power

Project tutorial by Giovanni Gentile

  • 1,557 views
  • 0 comments
  • 5 respects
Add projectSign up / Login