Arduinoでポケコンプリンタインターフェース

以前に書いたArduinoを使った印刷用のインターフェースについて、暫定版ができた。

基板に実装するため、秋月電子のAE-ATMEGA-328 MINIを使用。
当初はプリンタ側はデジタルポートで、ポケコン側はアナログポートをデジタルとする予定だったが、ポケコン側の信号を割り込み処理で実行するため、一部の配線がめんどいことになってしまった。

仕様としては以下の通り。

インターフェース仕様
・CE-126とLPRTの両方をサポート
・リセット時に文字セット初期化を行うので、ポケコン側から初期化コマンドを送る必要なし
・プリンタへの出力が、そのままシリアルポートに出力される
・プリンタへの出力をOFFにできる(シリアルポートはそのまま出力される)

CE-126 mode
・ポケコン側の仕様に影響される
・1行24桁固定
・シリアルポートの出力は24桁で、不足分は空白で置き換わる。
・空行でも24桁の空白
・7Fh~9Fh,F0h~F4h,F8h~FFhあたりはポケコン側で空白に変換したり、別のコードに変換している
・MONモードやTEXTモードなどでも印刷できる

LPRT mode
・LPRINT CHR$コマンドで、指定したコードをそのまま出力する。
・MONモードやTEXTモードなどでは印刷できない
プリンタが対応していればハードコピーが可能(予定)(暫定版では正常動作せず)9/14追記
・印刷が若干遅い(シフトレジスタICを使ったロジック回路でも同様)

まずはCE-126 modeで印刷してみる。

1行24桁固定で印刷され、一部の文字コードは印刷されない。
MONモードでダンプリストの印刷も行ってみる。

CE-126でなければ印刷できなかったものも印刷できた。
ついでにシリアルポートからの出力は以下のとおり。

 !"#$%&'()*+,-./01234567
89<=>?@ABCDEFGHIJKLMNO
PQRSTUVWXYZ[\]^_`abcdefg
hijklmnopqrstuvwxyz{|}~ 
                        
        。「」、・ヲァィゥェォャュョッ
ーアイウエオカキクケコサシスセソタチツテトナニヌ
ネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚
10:REM OPEN "LPRT:"     
11:REM LPRINT CHR$ &H1B;"t"; CHR$ 1           
12:REM LPRINT CHR$ &H1B;"R"; CHR$ 8           
20:FOR A=32 TO 255      
29:PRINT CHR$ A;        
30:LPRINT CHR$ A;       
40:NEXT                 
50:LPRINT               
0100 : AF CD 5F 11  ッヘ_.
(CB)   11 04 02 21  ...!
       42 01 CD 20  B.ヘ 
       11 CD 8F 0A  .ヘ .
0110 : 2A A2 11 56  *「.V
(E8)   23 5E 23 ED  #^# 
       53 01 7D 7E  S.}~
       32 03 7D 23  2.}#
0120 : 7E B7 F4 7B  ~キ
(1E)   0A 2A A4 11  .*、.
       22 04 7D 3E  ".}>
       01 32 00 7D  .2.}

次にLPRTモードで印刷した場合。

こちらは、20h以降の文字がすべて印刷されている。
また、1行も用紙の幅いっぱい印刷されている。
シリアルポートからの出力は以下の通り。

 !"#$%&'()*+,-./0123456789<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~	


。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚珮粤蒟跚韜・・ⅰ涇・

80h~9Fh,E0h~FFhの部分はShiftJISで使っている領域になるので文字が化けている。

10:OPEN "LPRT:"
11:REM LPRINT CHR$ &H1B;"t"; CHR$ 1
12:REM LPRINT CHR$ &H1B;"R"; CHR$ 8
20:FOR A=32 TO 255
29:PRINT CHR$ A;
30:LPRINT CHR$ A;
40:NEXT
50:LPRINT

最後に、暫定版Arduinoスケッチ。

// Emulator Sharp CE-126P fur PC-1401 u. PC-E500
const int OUT_ACK = 17; // ACK  Sharp CE-126P, pin 9 der 11-pol. Buchsenleiste
const int IN_Xout = 3;  // Xout Sharp PC-1401, pin 7 der 11-pol. Buchsenleiste / INT1
const int IN_Dout = 16; // Dout Sharp PC-1401, pin 5 der 11-pol. Buchsenleiste
const int IN_Busy = 2;  // Busy Sharp PC-1401, pin 4 der 11-pol. Buchsenleiste / INT0
const int InfoLED = 13;

// printer interface
const int Pstrb = 15;  // Printer STROBE
const int PD0out = 14; // Printer D0
const int PD1out = 4;  // Printer D1
const int PD2out = 5;  // Printer D2
const int PD3out = 6;  // Printer D3
const int PD4out = 7;  // Printer D4
const int PD5out = 8;  // Printer D5
const int PD6out = 9;  // Printer D6
const int PD7out = 10; // Printer D7
const int Pbusy = 11;  // Printer BUSY

// Mode SW
const int EMmode = 12; // Emulator mode SW (Hi:CE126P/Lo:LPRT)
const int EMsw = 18;   // Emulator SW (Hi:Serial and Parallel / Lo:Serial only)

boolean Busy;  // Busy signal
boolean Xout;  // Xout signal
boolean Dout;  // Dout signal

int DataBit;   // work of CE-126P mode
int DataByte;  // work of CE-126P mode
long Timeout;
int i; 

byte SPif;       // work of LPRT mode

boolean PrtBusy; // work of Printer interface

////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  // Serial port 98600BPS
	Serial.begin(9600);

	// E500/G8xx interface set
	pinMode(OUT_ACK, OUTPUT);
	pinMode(IN_Xout, INPUT);
	pinMode(IN_Dout, INPUT);
	pinMode(IN_Busy, INPUT);
	pinMode(InfoLED, OUTPUT);

  // Printer interface set
  pinMode(PD0out, OUTPUT);
  pinMode(PD1out, OUTPUT);
  pinMode(PD2out, OUTPUT);
  pinMode(PD3out, OUTPUT);
  pinMode(PD4out, OUTPUT);
  pinMode(PD5out, OUTPUT);
  pinMode(PD6out, OUTPUT);
  pinMode(PD7out, OUTPUT);
  pinMode(Pstrb, OUTPUT);
  pinMode(Pbusy, INPUT);

  // Emulator mode SW
  pinMode(EMmode, INPUT);
  pinMode(EMsw, INPUT);

  // Sirial header
  Serial.println();
  Serial.println("Bereit:");
  Serial.println();

  // Printer STROBE is HIGH
  digitalWrite(Pstrb, HIGH);
  
  // Printer BUSY pull up
  digitalWrite(Pbusy, HIGH);

  // sw port pull up
  digitalWrite(EMmode, HIGH);
  digitalWrite(EMsw, HIGH);

  // ESC/POS printer init
  PRTinit ();
}

////////////////////////////////////////////////////////////////////////////////////////////

void loop() {

  if (digitalRead(EMmode) == HIGH ){
    ce126pemu();
  } else {
    lprtemu();
  }

} // Ende loop

////////////////////////////////////////////////////////////////////////////////////////////

// Emulator Sharp CE-126P
void ce126pemu() {
  do{
    digitalWrite(InfoLED, LOW);
    Xout = digitalRead(IN_Xout);
  
    if (Xout) {
      // DeviceSelect:
      digitalWrite(InfoLED, HIGH);
      delayMicroseconds(50);
      i = 0;
      do {
        digitalWrite(OUT_ACK, HIGH);
        Timeout = millis();
        do {
          Busy = digitalRead(IN_Busy);
          if (millis() - Timeout > 50) break;
        } while (!Busy);
        delayMicroseconds(50);
        digitalWrite(OUT_ACK, LOW);
        do {
          Busy = digitalRead(IN_Busy);
        } while (Busy);
        delayMicroseconds(150);
        i++;
      } while (i < 8);
    }
  
    Busy = digitalRead(IN_Busy);
  
    if (Busy && !Xout) { 
      // Daten:
      digitalWrite(InfoLED, HIGH);
      i = 0;
      DataByte = 0;
      do {
        do {
          Busy = digitalRead(IN_Busy);
        } while (!Busy);
        delayMicroseconds(50);
        DataBit = digitalRead(IN_Dout);
        digitalWrite(OUT_ACK, HIGH);
        do {
          Busy = digitalRead(IN_Busy);
        } while (Busy);
        delayMicroseconds(50);
        if (i != 8) digitalWrite(OUT_ACK, LOW); // add : now receve to low. but printing is high 
        DataByte = DataByte | (DataBit << i);
        i++;
      } while (i < 8);
      // Ausgabe:
      switch (DataByte) {
        case 13:
          Serial.println();
          praout(0x0d); // CR
          praout(0x0A); // LF
          break;
        case 48:
          Serial.print("O"); // Buchstabe "O"
          praout(0x4f);
          break;
        case 240:
          Serial.print("0"); // Ziffer Null
          praout(0x30);
          break;
        default:
          if (DataByte >= 31 && DataByte <= 255) {
            Serial.print(char(DataByte));
            praout(byte(DataByte));
          }
      }
      if (i == 8) digitalWrite(OUT_ACK, LOW); // add : print after ack low
    }
  } while (digitalRead(EMmode) == HIGH );

}

////////////////////////////////////////////////////////////////////////////////////////////

// Emulator LPRT:
void lprtemu() {

  // Interrupt set
  attachInterrupt(0,IntBusy,RISING);
  attachInterrupt(1,IntXout,RISING);

  do{
    digitalRead(EMmode); // dummy
  } while (digitalRead(EMmode) == LOW );

  // Interrupt off
  detachInterrupt(0);
  detachInterrupt(1);
  
}

////////////////////////////////////////////////////////////////////////////////////////////

// Interrupt routine
// BUSY to High (strobe)
void IntBusy() {
  digitalWrite(OUT_ACK, HIGH);
  digitalWrite(InfoLED, HIGH);
  Serial.print(char(SPif));
  praout(SPif);
  SPif=0;
  delay(5);
  digitalWrite(InfoLED, LOW);
  digitalWrite(OUT_ACK, LOW);
}

// Xout to High (data clock)
void IntXout() {
  SPif = SPif << 1 ;
  if (digitalRead(IN_Dout) == HIGH) {
    SPif++;
  }
}

////////////////////////////////////////////////////////////////////////////////////////////

// init ESC/POS printer caractor set to Jananese
void PRTinit () {
  // init print char set
  // ESC t n : Select international character set
  praout(0x1b); // ESC
  praout(0x74); // t
  praout(0x01); // 1:Katakana
  // ESC R n : Select character code table
  praout(0x1b); // ESC
  praout(0x52); // R
  praout(0x08); // 8:Japan
  delay(10);
}

////////////////////////////////////////////////////////////////////////////////////////////

// Parallel Printer interface
void praout (byte POdata) {

  // If EMsw is low as no operation 
  if (digitalRead(EMsw) == LOW) return;

  // wait busy low
  PrtBusy=digitalRead(Pbusy);
  do {
    PrtBusy=digitalRead(Pbusy);
  } while (PrtBusy != LOW);

  // Printer data output
  digitalWrite(PD0out, bitRead(POdata,0));
  digitalWrite(PD1out, bitRead(POdata,1));
  digitalWrite(PD2out, bitRead(POdata,2));
  digitalWrite(PD3out, bitRead(POdata,3));
  digitalWrite(PD4out, bitRead(POdata,4));
  digitalWrite(PD5out, bitRead(POdata,5));
  digitalWrite(PD6out, bitRead(POdata,6));
  digitalWrite(PD7out, bitRead(POdata,7));
  delayMicroseconds(1);

  // Strobe to low
  digitalWrite(Pstrb,LOW);

  // wait busy high
  Timeout = millis();
  do {
    PrtBusy=digitalRead(Pbusy);
    //if (millis() - Timeout > 50) break;
  } while (PrtBusy == HIGH);

  // Strobe to high
  delayMicroseconds(50);
  digitalWrite(Pstrb, HIGH);
  
  // wait busy low
  do {
    PrtBusy=digitalRead(Pbusy);
  } while (PrtBusy != LOW);
  delayMicroseconds(50);
}

シリアルポートから印刷データを垂れ流しているので、少し手直しすればプリンタシールドでも利用可能かもしれない。
雑な作りなので少し手直しは必要かも。

カテゴリー: Arduino, PC-G850VS, ポケコン, 電子工作 パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください