PC-8801MA2にPS/2日本語キーボードをつなぐ その2

ある程度動いたので、arduino基板をジャパニーノから、ちびでぃーの2に変更する。

http://tiisai.dip.jp/?page_id=1296

通信速度20800 bpsとか、データビット12bitとか、いやらしい仕様ですが19200 bps、データビット8bitを元に作って行きます。以下は8bit送信する関数を、無理やり12bit偶数パリティで送信するよう改造したもの。補足すると、19200 bpsの時にちびでぃーの2では、_tx_delayとXMIT_START_ADJUSTMENTは、それぞれ114と5でした。20800 bpsで動くようトライ&エラーで値を104と5に変えてみました。これは基板毎に調整が必要だと思います。

http://www.nisoc.or.jp/~karl/freebsd-pc98/serial.html

SoftwareSerial.h

  virtual size_t write2(uint8_t b, uint8_t c);

SoftwareSerial.cpp

#if F_CPU == 16000000

static const DELAY_TABLE PROGMEM table[] = 
{
  //  baud    rxcenter   rxintra    rxstop    tx
  { 115200,   1,         17,        17,       12,    },
  { 57600,    10,        37,        37,       33,    },
  { 38400,    25,        57,        57,       54,    },
  { 31250,    31,        70,        70,       68,    },
  { 28800,    34,        77,        77,       74,    },
//  { 19200,    54,        117,       117,      114,   },
  { 19200,    54,        117,       117,      104,   },
  { 14400,    74,        156,       156,      153,   },
  { 9600,     114,       236,       236,      233,   },
  { 4800,     233,       474,       474,      471,   },
  { 2400,     471,       950,       950,      947,   },
  { 1200,     947,       1902,      1902,     1899,  },
  { 600,      1902,      3804,      3804,     3800,  },
  { 300,      3804,      7617,      7617,     7614,  },
};

const int XMIT_START_ADJUSTMENT = 5;

#elif F_CPU == 8000000

static const DELAY_TABLE table[] PROGMEM = 
{
  //  baud    rxcenter    rxintra    rxstop  tx
  { 115200,   1,          5,         5,      3,      },
  { 57600,    1,          15,        15,     13,     },
  { 38400,    2,          25,        26,     23,     },
  { 31250,    7,          32,        33,     29,     },
  { 28800,    11,         35,        35,     32,     },
//  { 19200,    20,         55,        55,     52,     },
  { 19200,    20,         55,        55,     50,     },
  { 14400,    30,         75,        75,     72,     },
  { 9600,     50,         114,       114,    112,    },
  { 4800,     110,        233,       233,    230,    },
  { 2400,     229,        472,       472,    469,    },
  { 1200,     467,        948,       948,    945,    },
  { 600,      948,        1895,      1895,   1890,   },
  { 300,      1895,       3805,      3805,   3802,   },
};

const int XMIT_START_ADJUSTMENT = 4;

(省略)

size_t SoftwareSerial::write2(uint8_t b, uint8_t c)
{
  if (_tx_delay == 0) {
    setWriteError();
    return 0;
  }
  boolean parity=false;
  for (byte mask = 0x01; mask; mask <<= 1)
  {
    if (b & mask) parity=!parity;
  }
  for (byte mask = 0x01; mask; mask <<= 1)
  {
    if (mask == 0x10) {
      if (parity) c|=0x10;
      else c&=0xef;
      break;
    }
    if (c & mask) parity=!parity;
  }

  uint8_t oldSREG = SREG;
  cli();  // turn off interrupts for a clean txmit

  // Write the start bit
  tx_pin_write(LOW);
  tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);

  for (byte mask = 0x01; mask; mask <<= 1)
  {
    if (b & mask) // choose bit
      tx_pin_write(HIGH); // send 1
    else
      tx_pin_write(LOW); // send 0
    
    tunedDelay(_tx_delay);
  }
  for (byte mask = 0x01; mask; mask <<= 1)
  {
    if (c & mask) // choose bit
      tx_pin_write(HIGH); // send 1
    else
      tx_pin_write(LOW); // send 0
  
    tunedDelay(_tx_delay);
  }

  tx_pin_write(HIGH); // restore pin to natural state

  SREG = oldSREG; // turn interrupts back on
  tunedDelay(_tx_delay);
  
  return 1;
}