Trybotics Logo

Atari 65XE as USB-Keyboard © GPL3+

DESCRIPTION

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.

Note: for Linux usage it is applicable, as restrictions described bottom is not important. But for full usage (in Windows, for example) need to make more soldering (described here in the Appendix) and to modify the Arduino sketch.

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.

Appendix (not a required, but improves buttons handling in its combinations)

For the full usage of all buttons and all its possible combinations for USB application, while keep the native Atari mode alive, need to exclude from the work a part of the Atari circuit (marked red) when the keyboard is connected via USB; and to engage this section if Atari is running in native mode.

It is not very difficult to do, only a lot of soldering is required (of course, not in the Atari scheme) and one chip CD4066.
One more thing that will help is that the 0.1 in (2.54 mm) male PCB strip connector is fits perfectly into the Atari J8 slot.


Description:

Description:

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.

Note: for Linux usage it is applicable, as restrictions described bottom is not important. But for full usage (in Windows, for example) need to make more soldering (described here in the Appendix) and to modify the Arduino sketch.

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.

Appendix (not a required, but improves buttons handling in its combinations)

For the full usage of all buttons and all its possible combinations for USB application, while keep the native Atari mode alive, need to exclude from the work a part of the Atari circuit (marked red) when the keyboard is connected via USB; and to engage this section if Atari is running in native mode.

It is not very difficult to do, only a lot of soldering is required (of course, not in the Atari scheme) and one chip CD4066.
One more thing that will help is that the 0.1 in (2.54 mm) male PCB strip connector is fits perfectly into the Atari J8 slot.


Description:

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;
    }
  }
}
}


YOU MIGHT ALSO LIKE