Sharp PC-1401 als Eingabegerät für Arduino

Bild: Arduino Micro und Sharp PC-1401

Im folgenden Beispiel zeige ich, wie ein alter Sharp Pocket Computer aus den 1980er Jahren als Eingabegerät für Arduino Projekte genutzt werden kann.
Ich verwende dazu den damals sehr weit verbreiteten und heute gebraucht noch immer erhältlichen Sharp PC-1401.
Geeignete funktionierende Geräte mit Abnützungserscheinungen oder Displayfehlern sind bei ebay um wenige Euro zu haben, gut erhaltene Rechner werden zu Sammlerpreisen gehandelt.
Es lassen sich mit untenstehendem Basic-Programm alle 76 Tasten des PC-1401 abfragen und für Arduino Projekte verwenden.
- Tastencodes siehe Tastaturmatrix des Sharp PC-1401
Beim ersten Aufruf muß das BASIC Programm mit RUN gestartet werden, damit das Maschinenprogramm in den Speicher geladen wird (Dauer 6 Sekunden).
Weitere Aufrufe können mit DEF A erfolgen. Das Programm startet mit einem Piepton (BEEP 1).
Ein Tastendruck wird durch einen kurzen Piepston im Pocket Computer und ein Blinken der Info-LED (D13) am Arduino angezeigt.
Die Datenübertragung erfolgt über Pin 4 (Busy) und Pin 5 (Dout) der Schnittstelle des Pocket Computers zu den Digitaleingängen D9 und D8 am Arduino.
Über Dout wird der eigentliche Tastencode seriell übertragen, ein HIGH auf der Leitung Busy dient zur Anzeige gültiger Daten.
An externer Beschaltung sind lediglich zwei pull-down Widerstände und eine Verbindung von GND zu Pin 3 erforderlich.
Im Arduino Beispielprogramm wird die Tasten-Eingabe über die Arduino Hardware (Micro bzw. UNO) am Serial-Monitor der Arduino-IDE ausgegeben.

Im Anschluß folgen Ergänzungen für das Arduino Beispielprogramm mit dem auch das benötigte BASIC Programm vom Arduino mittels CLOAD in den Sharp PC-1401 geladen werden kann.
Man erspart sich so nicht nur das mühsame Eintippen des BASIC Programms in den Pocket Computer, sondern es können auch Geräte mit stark beschädigtem Display verwendet werden.
Die wenigen nötigen Eingaben schafft man auch im Blindflug.
Dazu wird der Digitalausgang D7 des Arduino mit Pin 6 (Port Xi) des Pocket Computers verbunden. Über D19 (A5) wird eine Status LED angesteuert, die während der Übertragung des BASIC Programms leuchtet.
Die Übertragung dauert ca. 9 Sekunden und wird durch Drücken eines Tasters gestartet, der GND mit D17 (A3) des Arduino verbindet.
Zuvor muß am Sharp Pocket Computer im Run-Mode der Befehl CLOAD eingegeben und die ENTER Taste gedrückt werden.

BASIC Programm für Sharp PC-1401:


10:RESTORE
20:FOR X=0 TO 49
30:READ A
40:POKE &4200+X,A
50:NEXT X
100:"A"
110:BEEP 1
120:CALL &4200
130:GOTO 120
200:DATA &E4,&8F,103,255,57,5
210:DATA 218,2,128,131,198,18,&5E,56,3
220:DATA 97,2,97,1,95,206,96,0,95,209,210,43,18
230:DATA 80,2,32,219,223,35,219,2,20,52,78,100,47,3,223
240:DATA &E4,&8F,103,76,59,5,55


Assemblerdarstellung des Maschinenprogramms:

Tastaturabfrage
&4200:CAL&048F<
 CPIA255 
 JRZM5
Serielle Ausgabe
 EXAB     
 LIA128    
 LP03 < 
 TSMA    
 LIP&5E   
 JRZP3 
 ORIM2  
 ORIM1< 
 OUTF    
 NOPT    
 ANIM0   
 OUTF    
 RC    
 SR    
 JRNCM18 
Piepston
 INCP   
 LIA32  
 EXAM   
 OUTC   
 RA   
 EXAM   
 LIA20  
 PUSH   
 WAIT100<
 LOOP3
 OUTC   
Tastaturabfrage BRK
 CAL&048F<
 CPIA76 
 JRCM5
 RTN   


Steckbrett mit Arduino UNO:


Bild: Steckbrett mit Arduino UNO


Programm für Arduino:


// Sendkey für Sharp PC-1401
// Sharp Pocket Computer als Eingabegerät für Arduino UNO/Micro

const int IN_Dout = 8; // Pin D8, Dout Sharp PC-1401, pin 5 der 11-pol. Buchsenleiste
const int IN_Busy = 9; // Pin D9, Busy Sharp PC-1401, pin 4 der 11-pol. Buchsenleiste
const int InfoLED = 13;
boolean Busy;
int DataBit;
int DataByte;
int i;

void setup() {
  Serial.begin(9600);
  pinMode(IN_Dout, INPUT);
  pinMode(IN_Busy, INPUT);
  pinMode(InfoLED, OUTPUT);
  Serial.println();
  Serial.println("Bereit:");
  Serial.println();
}

void loop() {
  i = 8;
  DataByte = 0;
  Busy = digitalRead(IN_Busy);
  if (Busy) { // Data valid
    digitalWrite(InfoLED, HIGH);
    do {
      do {
        Busy = digitalRead(IN_Busy);
      } while (!Busy);
      i--;
      DataBit = digitalRead(IN_Dout);
      DataByte = DataByte | (DataBit << i);
      do {
        Busy = digitalRead(IN_Busy);
      } while (Busy);
    } while (i > 0);
    Ausgabe();
    delay(10);
    digitalWrite(InfoLED, LOW);
  }
} // Ende loop

void Ausgabe() {
  DataByte = DataByte & 127;
  switch (DataByte) {
    case 0:
      Serial.print("V");
      break;
    case 1:
      Serial.print("F");
      break;
    case 2:
      Serial.print("R");
      break;
    case 3:
      // Taste  Pfeil nach unten
      break;
    case 4:
      Serial.print("4");
      break;
    case 5:
      Serial.print("1");
      break;
    case 6:
      Serial.print("7");
      break;
    case 7:
      Serial.print("B");
      break;
    case 8:
      Serial.print("G");
      break;
    case 9:
      Serial.print("T");
      break;
    case 10:
      // Taste  Pfeil nach oben
      break;
    case 11:
      Serial.print("P");
      break;
    case 12:
      Serial.print(",");
      break;
    case 13:
      Serial.print("N");
      break;
    case 14:
      Serial.print("H");
      break;
    case 15:
      Serial.print("Y");
      break;
    case 16:
      // Taste  Pfeil nach links
      break;
    case 17:
      Serial.print("O");
      break;
    case 18:
      Serial.print("M");
      break;
    case 19:
      Serial.print("J");
      break;
    case 20:
      Serial.print("U");
      break;
    case 21:
      // Taste  Pfeil nach rechts
      break;
    case 22:
      // Taste  SPC
      Serial.print(" ");
      break;
    case 23:
      Serial.print("K");
      break;
    case 24:
      Serial.print("I");
      break;
    case 25:
      // Taste  ENTER
      Serial.println();
      break;
    case 26:
      Serial.print("L");
      break;
    case 27:
      Serial.print("0");
      break;
    case 28:
      Serial.print("Z");
      break;
    case 29:
      Serial.print("A");
      break;
    case 30:
      Serial.print("Q");
      break;
    case 31:
      // Taste  CAL
      break;
    case 32:
      Serial.print("5");
      break;
    case 33:
      Serial.print("2");
      break;
    case 34:
      Serial.print("8");
      break;
    case 35:
      // Taste  +/-
      break;
    case 36:
      Serial.print("X");
      break;
    case 37:
      Serial.print("S");
      break;
    case 38:
      Serial.print("W");
      break;
    case 39:
      // Taste  BASIC
      break;
    case 40:
      Serial.print("6");
      break;
    case 41:
      Serial.print("3");
      break;
    case 42:
      Serial.print("9");
      break;
    case 43:
      Serial.print(".");
      break;
    case 44:
      Serial.print("C");
      break;
    case 45:
      Serial.print("D");
      break;
    case 46:
      Serial.print("E");
      break;
    case 47:
      // Taste  DEF
      break;
    case 48:
      Serial.print("*");
      break;
    case 49:
      Serial.print("-");
      break;
    case 50:
      Serial.print("/");
      break;
    case 51:
      Serial.print("+");
      break;
    case 52:
      Serial.print("=");
      break;
    case 53:
      // Taste  X->M
      break;
    case 54:
      // Taste  EXP
      break;
    case 55:
      // Taste  Y^X
      break;
    case 56:
      // Taste  WURZEL
      break;
    case 57:
      // Taste  X^2
      break;
    case 58:
      Serial.print("(");
      break;
    case 59:
      Serial.print(")");
      break;
    case 60:
      // Taste  M+
      break;
    case 62:
      // Taste  ->HEX
      break;
    case 63:
      // Taste  ->DEG
      break;
    case 64:
      // Taste  LN
      break;
    case 65:
      // Taste  LOG
      break;
    case 66:
      // Taste  1/X
      break;
    case 67:
      // Taste  Austausch
      break;
    case 68:
      // Taste  RM
      break;
    case 69:
      // Taste  SHIFT
      break;
    case 70:
      // Taste  HYP
      break;
    case 71:
      // Taste  SIN
      break;
    case 72:
      // Taste  COS
      break;
    case 73:
      // Taste  TAN
      break;
    case 74:
      // Taste  F<->E
      break;
    case 75:
      // Taste  C.CE
      break;
    case 76:
      // Taste  BRK
      break;
  }
}

Ausgabe über Serial-Monitor:


Bild: Screenshot Serial-Monitor

Signalverlauf:

Signalverlauf für die Tasteneingabe 'H' 'A' 'L' 'L' 'O' 'SPC' 'W' 'E' 'L' 'T'
Bild: Signalverlauf



Steckbrett mit Arduino UNO für Programm mit BASIC Loader:


Bild: Steckbrett mit Arduino UNO mit BASIC Loader


Programmergänzung für Arduino mit BASIC Loader:

Folgende Ergänzungen sind in obigem Arduino Programmm nötig, um die BASIC-Loader Funktion hinzuzufügen:

const int OUT_Xi =  7; // Pin D7, Xi   Sharp PC-1401, pin 6 der 11-pol. Buchsenleiste
const int StatusLED = 19;
const int Btn1 = 17; // Btn1 = Taster zum Start von CSAVE
const int headersize = 10;
const int basicsize = 257;
const int pulse8 = 125;  // μs, short pulse bei CSAVE/CLOAD (8 x pulse8 = HIGH)
const int pulse4 = 250;  // μs, long  pulse bei CSAVE/CLOAD (4 x pulse4 = LOW)
const byte DATA_HEADER[headersize] = { 7,0,0,0,0,0,0,0,245,65 };
const byte DATA_BASIC[basicsize] = {
  // Zeile 10:
  0,10,2,228,13,
  // Zeile 20:
  0,20,8,213,88,61,48,208,52,57,13,
  // Zeile 30:
  0,30,3,219,65,13,
  // Zeile 40:
  0,40,11,205,38,52,50,48,48,43,88,44,65,13,
  // Zeile 50:
  0,50,3,217,88,13,
  // Zeile 100:
  0,100,4,34,65,34,13,
  // Zeile 110:
  0,110,3,196,49,13,
  // Zeile 120:
  0,120,7,204,38,52,50,48,48,13,
  // Zeile 130:
  0,130,5,198,49,50,48,13,
  // Zeile 200:
  0,200,22,220,38,69,52,44,38,56,70,44,49,48,51,44,50,53,53,44,53,55,44,53,13,
  // Zeile 210:
  0,210,31,220,50,49,56,44,50,44,49,50,56,44,49,51,49,44,49,57,56,44,72,49,56,44,38,53,69,44,53,54,44,51,13,
  // Zeile 220:
  0,220,40,220,57,55,44,50,44,57,55,44,49,44,57,53,44,50,48,54,44,57,54,44,48,44,57,53,44,50,48,57,44,50,49,
  48,44,52,51,44,49,56,13,
  // Zeile 230:
  0,230,48,220,56,48,44,50,44,51,50,44,50,49,57,44,50,50,51,44,51,53,44,50,49,57,44,50,44,50,48,44,53,50,44,
  55,56,44,49,48,48,44,52,55,44,51,44,50,50,51,13,
  // Zeile 240:
  0,240,24,220,38,69,52,44,38,56,70,44,49,48,124,51,44,55,54,44,53,57,44,53,44,53,53,13,255,255
};
const byte DATA_CHK = 168;

Ergänzungen in der Setup-Prozedur:

void setup() {
  pinMode(OUT_Xi, OUTPUT);
  pinMode(StatusLED, OUTPUT);
  pinMode(Btn1, INPUT_PULLUP);
  ...
}

Ergänzungen in der Loop-Prozedur:

void loop() {
  if (digitalRead(Btn1) == LOW) CSAVE(); // Basic Programm an Sharp PC-1401, Port-Xi senden
  ...
} // Ende loop

Ergänzung der neuen Prozeduren CSAVE, sendbit und pulseout:

void CSAVE() {  // Basic Programm an Sharp PC-1401, Port-Xi senden
  Serial.println();
  Serial.print("CSAVE Beginn ... ");
  digitalWrite(StatusLED, HIGH);
  delay(500);
  // Syncing an Xi:
  for (int x = 0; x < 125; x++) sendbit(1); // 125 High Bits (= 1000 kurze Pulse) an Xi senden
  sendbit(0);// 1 Low Bit (=4 lange Pulse) an Xi senden
  // Header an Xi senden:
  for (int x = 0; x < headersize; x++) {
    for (int y = 0; x < 4; y++) sendbit(bitRead(DATA_HEADER[x], y));
    sendbit(1);
    sendbit(0);
    for (int y = 4; x < 8; y++) sendbit(bitRead(DATA_HEADER[x], y));
    sendbit(1);
    sendbit(1);
    sendbit(0);
  }
  // Programm an Xi senden:
  for (int x = 0; x < basicsize; x++) {
    for (int y = 4; y < 8; y++) sendbit(bitRead(DATA_BASIC[x], y));
    sendbit(1);
    sendbit(0);
    for (int y = 0; y < 4; y++) sendbit(bitRead(DATA_BASIC[x], y));
    sendbit(1);
    sendbit(1);
    sendbit(0);
  }
  // Letzte Pruefsumme an Xi senden:
  for (int y = 4; y < 8; y++) sendbit(bitRead(DATA_CHK, y));
  sendbit(1);
  sendbit(0);
  for (int y = 0; y < 4; y++) sendbit(bitRead(DATA_CHK, y));
  sendbit(1);
  sendbit(1);
  sendbit(1);
  sendbit(1);
  digitalWrite(StatusLED, LOW);
  Serial.println("Ende");
  Serial.println();
}

void sendbit(int b) {
  if (b == 1) { // Bit = 1
    for (int z = 0; z < 8; z++) pulseout(pulse8); // 8 kurze Pulse = HIGH
  }
  if (b == 0) { // Bit = 0
    for (int z = 0; z < 4; z++) pulseout(pulse4); // 4 lange Pulse = LOW
  }
}

void pulseout(int d) {
  digitalWrite(OUT_Xi, HIGH);
  delayMicroseconds(d);
  digitalWrite(OUT_Xi, LOW);
  delayMicroseconds(d);
}


zum Seitenanfang


© 2016-2017: Walter Fischer