目次

8155ハンドリングスケッチ

 知人から不要となったICをもらいました。その中に
 Intel 8155が含まれています。このICが動作するか
 をArduinoでテストしてみました。



 ピンアサインは、以下となっています。



 内部ブロック図は、次のようになっています。



 メモリは256バイト、パラレルI/OがポートA、B、Cで
 22ビットあり、1チャネルのタイマー/カウンタがあり
 ます。

 ピンアサインを見ると、バスインタフェースを利用
 して、データ入出力する仕様です。

 8085の仕様で、IO/nM、nCS、AD7からAD0を確定して
 おいて、ALEにパルスを与えます。nRD、nWRでメモリ
 またはIOのレジスタをアクセスします。

 タイミングチャートでは、以下です。



 RESET、IO/nM、ALE、nCS、nWR、nRDは、次のように
 Arduinoのピンにアサインしておきます。

 制御は、次の4種に分割して考えます。

 タイミングチャートを見ると、メモリ、I/Oのアクセス
 にはIO/nMの論理値とアドレスを与えるのは共通なので
 必要な信号をH、Lにする関数を定義しておきます。

void cs_8155(byte x)
{
  if ( x == SIG_ENABLE ) { PORTD &= ~(1 << CS_BIT); }
  else                   { PORTD |=  (1 << CS_BIT); }
}

void wr_8155(byte x)
{
  if ( x == SIG_ENABLE ) { PORTC &= ~(1 << WR_BIT); }
  else                   { PORTC |=  (1 << WR_BIT); }
}

void rd_8155(byte x)
{
  if ( x == SIG_ENABLE ) { PORTC &= ~(1 << RD_BIT); }
  else                   { PORTC |=  (1 << RD_BIT); }
}

void ale_8155()
{
  PORTD |=  (1 << ALE_BIT);
  PORTD &= ~(1 << ALE_BIT);
}

void rst_8155()
{
  PORTD |=  (1 << RST_BIT);
  PORTD &= ~(1 << RST_BIT);
}

 メモリアクセスの関数を定義します。
 アドレスとデータがあればよいので
 ライトとリードに分けて定義します。

void put_memory(byte xadr,byte xdat)
{
  /* send signals */
  cs_8155(SIG_ENABLE);
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xadr >> 4) & MASK0F ;
  PORTB |= (xadr & MASK0F) ;
  PORTC &= ~(1 << IO_BIT) ;
  ale_8155();
  cs_8155(SIG_DISABLE);
  /* impress data */
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xdat >> 4) & MASK0F ;
  PORTB |= (xdat & MASK0F) ;
  /* enable nWR */
  wr_8155(SIG_ENABLE) ;
  /* disable nWR */
  wr_8155(SIG_DISABLE) ;
}

byte get_memory(byte xadr)
{
  byte dh ;
  byte dl ;
  /* send signals */
  cs_8155(SIG_ENABLE);
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xadr >> 4) & MASK0F ;
  PORTB |= (xadr & MASK0F) ;
  PORTC &= ~(1 << IO_BIT) ;
  ale_8155();
  cs_8155(SIG_DISABLE);
  /* change port direction */
  DDRC = MASKF0 ;
  DDRB = MASKF0 ;
  /* enable nRD */
  rd_8155(SIG_ENABLE) ;
  /* get upper nibble */
  dh = PINC & MASK0F ;
  /* get lower nibble */
  dl = PINB & MASK0F ;
  /* disable nRD */
  rd_8155(SIG_DISABLE) ;
  /* change port direction */
  DDRC = MASKFF ;
  DDRB = MASKFF ;

  return( (dh << 4) | dl ) ;
}

 IOアクセスの関数を定義します。
 アドレスとデータがあればよいので
 ライトとリードに分けて定義します。

void put_io(byte xadr,byte xdat)
{
  /* send signals */
  cs_8155(SIG_ENABLE);
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xadr >> 4) & MASK0F ;
  PORTB |= (xadr & MASK0F) ;
  PORTC {= (1 << IO_BIT) ;
  ale_8155();
  cs_8155(SIG_DISABLE);
  /* impress data */
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xdat >> 4) & MASK0F ;
  PORTB |= (xdat & MASK0F) ;
  /* enable nWR */
  wr_8155(SIG_ENABLE) ;
  /* disable nWR */
  wr_8155(SIG_DISABLE) ;
}

byte get_io(byte xadr)
{
  byte dh ;
  byte dl ;
  /* send signals */
  cs_8155(SIG_ENABLE);
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xadr >> 4) & MASK0F ;
  PORTB |= (xadr & MASK0F) ;
  PORTC |= (1 << IO_BIT) ;
  ale_8155();
  cs_8155(SIG_DISABLE);
  /* change port direction */
  DDRC = MASKF0 ;
  DDRB = MASKF0 ;
  /* enable nRD */
  rd_8155(SIG_ENABLE) ;
  /* get upper nibble */
  dh = PINC & MASK0F ;
  /* get lower nibble */
  dl = PINB & MASK0F ;
  /* disable nRD */
  rd_8155(SIG_DISABLE) ;
  /* change port direction */
  DDRC = MASKFF ;
  DDRB = MASKFF ;

  return( (dh << 4) | dl ) ;
}

 メモリ、IOのアクセスでは、一部の信号の扱いが
 異なるだけなので、まとめてわかりやすくします。

void put_iom(byte which,byte xadr,byte xdat)
{
  /* send signals */
  cs_8155(SIG_ENABLE);
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xadr >> 4) & MASK0F ;
  PORTB |= (xadr & MASK0F) ;
  PORTC &= ~(1 << IO_BIT) ;
  if ( which ) { PORTC |= (1 << IO_BIT) ; }
  ale_8155();
  cs_8155(SIG_DISABLE);
  /* impress data */
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xdat >> 4) & MASK0F ;
  PORTB |= (xdat & MASK0F) ;
  /* enable nWR */
  wr_8155(SIG_ENABLE) ;
  /* disable nWR */
  wr_8155(SIG_DISABLE) ;
}

byte get_iom(byte which,byte xadr)
{
  byte dh ;
  byte dl ;
  /* send signals */
  cs_8155(SIG_ENABLE);
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xadr >> 4) & MASK0F ;
  PORTB |= (xadr & MASK0F) ;
  PORTC &= ~(1 << IO_BIT) ;
  if ( which ) { PORTC |= (1 << IO_BIT) ; }
  ale_8155();
  cs_8155(SIG_DISABLE);
  /* change port direction */
  DDRC = MASKF0 ;
  DDRB = MASKF0 ;
  /* enable nRD */
  rd_8155(SIG_ENABLE) ;
  /* get upper nibble */
  dh = PINC & MASK0F ;
  /* get lower nibble */
  dl = PINB & MASK0F ;
  /* disable nRD */
  rd_8155(SIG_DISABLE) ;
  /* change port direction */
  DDRC = MASKFF ;
  DDRB = MASKFF ;

  return( (dh << 4) | dl ) ;
}

void put_memory(byte xadr,byte xdat)
{
  put_iom(OFF,xadr,xdat);
}

byte get_memory(byte xadr)
{
  return get_iom(OFF,xadr);
}

void put_io(byte xadr,byte xdat)
{
  put_iom(ON,xadr,xdat);
}

byte get_io(byte xadr)
{
  return get_iom(ON,xadr);
}

 8155をアクセスするために使う関数を定義したので
 メモリとIOに分けて、テストスケッチを作成します。

 メモリのテストは、0から255のアドレスに
 アドレスと同じ値をライトし、それを読み出す
 スケッチとします。

 仕様を決めれば、スケッチは簡単です。

 コマンドを、'?'、'I'、'S'の3種類にして対応します。

#define OFF 0
#define ON  OFF+1

#define WR_BIT 5
#define RD_BIT 4

#define IO_BIT  5
#define ALE_BIT 4

#define RST_BIT 7
#define CS_BIT  6

#define SIG_ENABLE  0
#define SIG_DISABLE 1
  
#define BSIZE 8

#define MASK0F 0x0f
#define MASKF0 0xf0 
#define MASKFF 0xff 

#define LAST 256

byte uflag ;
char sbuf[BSIZE] ;
byte sindex ;
char cmd ;

void rs_putchar(char x)
{
  Serial.write( x );
}

void  rs_puts(char *ptr)
{
  while ( *ptr ) {
    rs_putchar( *ptr );
    ptr++ ;
  }
}

void  crlf()
{
  rs_putchar('\r');
  rs_putchar('\n');
}

void  show_help() 
{
  rs_puts("? help");                 crlf();
  rs_puts("I initialize memory");    crlf();
  rs_puts("S show memory contents"); crlf();
}

byte get_hex(char x)
{
  byte result ;
  /* default */
  result = 0 ;
  /* convert */
  if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
  if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
  if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }

  return result ;
}

void rst_8155()
{
  PORTD |=  (1 << RST_BIT);
  PORTD &= ~(1 << RST_BIT);
}

void cs_8155(byte x)
{
  if ( x == SIG_ENABLE ) { PORTD &= ~(1 << CS_BIT); }
  else                   { PORTD |=  (1 << CS_BIT); }
}

void wr_8155(byte x)
{
  if ( x == SIG_ENABLE ) { PORTC &= ~(1 << WR_BIT); }
  else                   { PORTC |=  (1 << WR_BIT); }
}

void rd_8155(byte x)
{
  if ( x == SIG_ENABLE ) { PORTC &= ~(1 << RD_BIT); }
  else                   { PORTC |=  (1 << RD_BIT); }
}

void ale_8155()
{
  PORTD |=  (1 << ALE_BIT);
  PORTD &= ~(1 << ALE_BIT);
}

void put_iom(byte which,byte xadr,byte xdat)
{
  /* send signals */
  cs_8155(SIG_ENABLE);
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xadr >> 4) & MASK0F ;
  PORTB |= (xadr & MASK0F) ;
  PORTC &= ~(1 << IO_BIT) ;
  if ( which ) { PORTC |= (1 << IO_BIT) ; }
  ale_8155();
  cs_8155(SIG_DISABLE);
  /* impress data */
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xdat >> 4) & MASK0F ;
  PORTB |= (xdat & MASK0F) ;
  /* enable nWR */
  wr_8155(SIG_ENABLE) ;
  /* disable nWR */
  wr_8155(SIG_DISABLE) ;
}

byte get_iom(byte which,byte xadr)
{
  byte dh ;
  byte dl ;
  /* send signals */
  cs_8155(SIG_ENABLE);
  PORTC &= MASKF0 ;
  PORTB &= MASKF0 ;
  PORTC |= (xadr >> 4) & MASK0F ;
  PORTB |= (xadr & MASK0F) ;
  PORTC &= ~(1 << IO_BIT) ;
  if ( which ) { PORTC |= (1 << IO_BIT) ; }
  ale_8155();
  cs_8155(SIG_DISABLE);
  /* change port direction */
  DDRC = MASKF0 ;
  DDRB = MASKF0 ;
  /* enable nRD */
  rd_8155(SIG_ENABLE) ;
  /* get upper nibble */
  dh = PINC & MASK0F ;
  /* get lower nibble */
  dl = PINB & MASK0F ;
  /* disable nRD */
  rd_8155(SIG_DISABLE) ;
  /* change port direction */
  DDRC = MASKFF ;
  DDRB = MASKFF ;

  return( (dh << 4) | dl ) ;
}

void put_memory(byte xadr,byte xdat)
{
  put_iom(OFF,xadr,xdat);
}

byte get_memory(byte xadr)
{
  return get_iom(OFF,xadr);
}

void put_io(byte xadr,byte xdat)
{
  put_iom(ON,xadr,xdat);
}

byte get_io(byte xadr)
{
  return get_iom(ON,xadr);
}

char  get_asc(byte x)
{
  char result ;

  if ( x < 10 ) {
    result = x + '0' ;
  } else {
    result = x - 10 + 'A' ;
  }

  return result ;
}

void  set_memory()
{
  word i ;

  rs_puts("Start ");
  /* loop */
  for ( i = 0 ; i < LAST ; i++ ) {
    put_memory((byte)i,(byte)(255-i)) ;
    rs_putchar('.');
  }
  rs_puts("Complete !");
  crlf();
}

void  show_memory()
{
  word i ;
  byte tmp ;
  char msg[4] ;

  *(msg+2) = ' ' ;
  *(msg+3) = 0 ;
  for ( i = 0 ; i < LAST ; i++ ) {
    /* get data */
    tmp = get_memory((byte)i) ;
    /* separate */
    *(msg+0) = get_asc( (tmp >> 4) & MASK0F ) ;
    *(msg+1) = get_asc( tmp & MASK0F );
    /* show */
    rs_puts( msg );
    /* new line */
    if ( (i % 16) == 15 ) { crlf(); }
  }
}

void  setup()
{
  /* initialize serial port*/
  Serial.begin(9600);
  sindex = 0 ;
  /* initialize PORT values */
  PORTB = 0x00 ;
  PORTC = 0x0e ;
  PORTD = 0x41 ;
  /* initialize PORT directions */
  DDRB = 0xff ;
  DDRC = 0xff ;
  DDRD = 0xfe ;
  /* clear flags */
  uflag = OFF ;
}

void loop()
{
  /* command interpreter */
  if ( uflag == ON ) {
    /* clear flag */
    uflag = OFF ;
    /* new line */
    crlf();
    /* get command */ 
    cmd = *(sbuf+0) ;
    /* help */
    if ( cmd == '?' ) { show_help(); }
    /* set memory */
    if ( cmd == 'I' ) { set_memory(); }
    /* show memory contents */
    if ( cmd == 'S' ) { show_memory(); }
  }
}

void serialEvent() 
{
  char ch;

  if ( Serial.available() > 0 ) {
    /* get 1 charactor */
    ch = Serial.read();
    /* store */
    sbuf[sindex] = ch ;
    /* increment */
    sindex++ ;
    /* judge */
    if ( ch == '\r' ) {
      sindex = 0 ; 
      uflag = ON ;
    }
  }
}

 8155のI/Oレジスタのアドレスは、以下。

(under construction)

目次

inserted by FC2 system