目次
前
次
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のピンにアサインしておきます。
- PD7 : RESET
- PD6 : nCS
- PC5 : IO/nM
- PC4 : ALE
- PC3-PC0 : upper nibble
- PB5 : nWR
- PB4 : nRD
- PB3-PB0 : lower nibble
制御は、次の4種に分割して考えます。
- メモリへのライト
- メモリからのリード
- I/Oへのライト
- I/Oからのリード
タイミングチャートを見ると、メモリ、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レジスタのアドレスは、以下。
- xxxxx000 Command/Status register
- xxxxx001 PORT A(1byte)
- xxxxx010 PORT B(1byte)
- xxxxx011 PORT C(6 bits)
- xxxxx100 Timer register lower byte
- xxxxx101 Timer register upper byte
(under construction)
目次
前
次