I/O라는 말을 처음 들어보셨나요?
I/O는 Input/Output의 준말로 CPU와 주변 기기와의 입출력의 의미합니다.
참고로, 자주 쓰는 말인 'BIOS'의 IO도 Input Output을 의미하고 있습니다.
만약 컴퓨터에 CPU와 ROM/RAM만 달려있으면, 별로 쓸만한 기기가 못되겠죠?
뭔가 사용자로 부터 입력(키보드/조이스틱 등)도 받고,
결과를 출력(모니터/프린터 등)도 하는 방법이 있어야겠습니다.
사운드를 듣고 싶다면 PSG 등의 사운드 칩을 제어할 수 있는 방법이 있어야하겠지요.
Z80 CPU와 주변 장치를 제어할 수 있는 방법은 크게 두가지가 있습니다.
Memory Mapped IO와 IO Mapped IO 인데요.
메모리맵 방식은 CPU가 보기엔 RAM 같은 메모리에 값을 읽기/쓰기를 하는 것 처럼 보이지만,
실제로는 주변 장치에 데이터를 입력/출력하는 방법입니다.
IO맵 방식은 CPU에서 주변기기 입출력을 위해 만들어진 별도의 명령으로,
데이터를 입력/출력하는 방법입니다.
MSX에서는 메모리를 슬롯이라는 것으로 여러개의 공간으로 관리한다고 그랬었죠?
메모리맵 방식의 IO를 쓸때는 특정 슬롯에 RAM 같은 메모리 아닌,
HW 기기를 연결하고 CPU의 /MERQ, /RD, /WR 신호에 맞춰 동작하게 구성합니다.
참고로 CPU의 /MERQ는 메모리 액세스 요청, /RD는 읽기 신호, /WR은 쓰기 신호입니다.
IO맵 방식의 IO를 쓸때는 슬롯의 메모리 공간과는 별도로,
특정 IO 주소에 HW 기기를 연결하고 CPU의 /IORQ, /RD, /WR 신호에 맞춰 동작하게 구성합니다.
참고로 CPU의 /IORQ는 IO 액세스 요청하는 신호입니다.
기억하실 부분은...
Z80 CPU에서 메모리 R/W와 IO R/W 관련된 명령이 따로 존재한다는 것.
MSX에서 메모리는 슬롯으로 관리되니까,
같은 주소에 메모리맵 IO를 만들더라도 선택된 슬롯에만 실제 IO가 이루어집니다.
IO맵 IO는 슬롯 상관없이 주소만 맞으면, IO가 이루어집니다.
만약 같은 주소의 IO맵 IO를 쓰는 기기를 2개가 연결되었다면 동시에 동작하게 됩니다.
그럼, 실제로 메모리맵 또는 IO맵 방식 사용시, 어떤 장단점이 있을까요?
장점을 먼저 생각해보면,
메모리맵 IO는 컨트롤 주소가 같은 기기를 여러개 쓰더라도,
슬롯 선택을 먼저 해야되니까 개별로 동작시키는 것이 가능합니다.
예)FDD 같은 디스크 장치는 기본적으로 메모리맵 IO방식입니다.
여러개를 연결했을때 개별로 동작이 가능해야되니까요.
코나미 메가롬팩 등의 카트리지 내에도 뱅킹을 위한 IO가 들어있습니다.
그냥 롬 영역을 읽을 때는 롬의 코드가 읽혀지지만,
IO 영역에 데이터를 쓰면 8KB 단위 등으로 페이지가 바뀌는 것이지요.
물론, 해당 주소의 롬 데이터가 바뀌지는 않습니다.
IO맵 IO는 슬롯 선택에 관한 메모리 제한이 없으니, 쉽게 SW로 컨트롤이 가능합니다.
예)키보드, VDP, PSG 등의 경우가 대표적이죠.
SW 구동 환경이 DOS이거나 BASIC이거나 32KB롬팩이거나 FDD의 디스크롬 상관없이,
쉽게 키보드의 눌러진 키를 확인하거나 화면의 글자색을 바꾸는 것들을 할 수 있습니다.
그럼, 단점은 뭘까요? 각각의 장점이 서로의 단점이 됩니다. ^^
메모리맵 IO의 경우는 해당 기기가 장착된 슬롯으로 먼저 전환해야만 액세스가 가능하니까,
SW를 만들때 좀 복잡해지는 경우가 많습니다.
같은 기기가 몇개나 장착되어 있는지, 해당 기기는 메모리의 어떤 PAGE에서만 구동이 되는지 등등
인터럽트 또는 BIOS 구동시 제약은 없는지 상당히 고려를 해야합니다.
예) 도스에서 DIR C: 라고 명령했을때,
해당 드라이브는 누구의 디스크 인터페이스가 처리하는지,
그 인터페이스는 어느 슬롯에 있는지 미리 다 알고 있어야 하겠죠?
김준성님의 MPX 카트리지도 메모리맵 IO방식이라서,
저의 MPXP 프로그램을 구동하면 먼저 MPX가 어느 슬롯에 존재하는지 검색하게됩니다.
IO맵 IO의 경우는 같은 IO 주소에 한개의 기기(물론 예외도 있습니다)만 존재해야합니다.
예) FM 사운드 칩의 경우, FM-PAC, MSX-AUDIO, MOON-SOUND, turboR PCM, PPI 1BIT Sound 등
MSX에서 여러가지 사운드를 쓸수 있는데요. 모두 주소가 다릅니다.
MOON-SOUND의 경우 비교적 레어 기기인 MSX-AUDIO를 대체하기 위해서 같은 주소를 쓰지만,
이 경우엔 두개의 사운드 기기를 동시에 사용하는 것은 불가능합니다.
이런 각각의 장단점으로 있으니 대개 주변기기 구현시는 아래 사항이 고려되겠지요.
자주 액세스가 필요하고 슬롯같은 메모리 제한을 받지않고 쉽게 액세스 가능해야되지만,
시스템에는 하나만 있으면 충분한 기기의 경우는 IO맵 IO를 쓰게 됩니다.
예) 키보드, VDP의 경우 왠만한 SW는 자주 컨트롤할 필요성이 높죠?
하지만 컴퓨터에는 하나만 있으면 충분한 경우입니다.
반대로 여러개의 기기를 동시에 사용가능해야 하는 경우는,
컨트롤시 메모리의 슬롯 제한이나 여러가지 불편하더라도 메모리맵 IO방식을 쓰게 됩니다.
그 외, 메모리맵 방식은 특성상 IO 메모리 영역을 비교적 넓게 쓸수 있지만,
이건 HW 만들기 나름이라 IO맵 IO방식도 가능합니다.
예) V9938 칩은 IO맵 IO방식으로 만들어져 있는데, (몇개의 Port로만 컨트롤합니다.)
128KB의 VRAM을 R/W 가능하도록 되어있습니다.
그럼 실제로는 어떤 명령어를 써야 하는지 보겠습니다.
-메모리맵 방식으로 B000H 주소에 'K'를 출력하는 경우.
(참고로 'K'는 ASCII 코드로 문자 A의 값을 의미합니다.)
어셈블리의 경우,
LD A,'K' ; CPU 레지스터 A에 'K'문자 값을 넣음.
LD (0B000H),A ; 메모리 주소 B000H에 레지스터 A의 내용을 출력.
BASIC의 경우,
A = ASC("K") ; A 변수에 'K'문자 값을 넣음.
POKE &HB000,A ; 메모리 주소 B000H에 변수 A의 내용을 출력.
너무 간단한가요? ㅋ
물론, 주소에 데이터를 출력하기 전에 해당 슬롯이 전환되어 있어야합니다.
-IO맵 방식으로 20H 주소에 'K'를 출력하는 경우.
(참고로, 원래 Z80은 IO맵 IO 사용시 16비트 주소를 쓸 수 있지만, MSX는 하위 8비트만 사용합니다.)
어셈블리의 경우,
LD A,'K' ; CPU 레지스터 A에 'K'문자 값을 넣음.
OUT (020H),A ; IO 주소 20H에 레지스터 A의 내용을 출력.
BASIC의 경우,
A = ASC("K") ; A 변수에 'K'문자 값을 넣음.
OUT &H20,A ; IO 주소 B000H에 변수 A의 내용을 출력.
어셈블리/BASIC 명령어가 거의 똑같죠?
근데, 코드가 별로 가슴에 와닿지 않죠? ^^
자~ 그럼, 실제 MSX에 존재하는 하드웨어를 제어해봅시다.
키보드를 보면 대문자 선택을 나타내는 CAPS LED가 있죠?
MSX의 기본 인터럽트 서비스 루틴(보통 ISR이라고 합니다)이 동작하는 동안에는,
메인 BIOS가 키의 상태를 주기적으로 스캔해서 저장해놓는데요,
이 때 CAPS LOCK 키가 눌러지면 CAPS LED를 켜고 끄는 일도 합니다.
이걸 수동으로 한번 해보는거에요.
그냥 LED만 켜고 끄면 재미없으니, PPI의 1BIT 사운드를 같이 ON/OFF하면서 소리도 들어봅시다.
MSX의 키보드와 1BIT 사운드 하드웨어는 8255라는 병렬 포트 칩으로 컨트롤하게 되어있습니다.
회로도를 보면서 설명해도 좋겠습니다만, 일단 실습부터 해보죠.
여기서 8255는 IO맵 방식으로 컨트롤하는데 AAH 주소에 값을 쓰게 되면,
키보드 신호 셀렉트, CAPS LED, 1BIT SOUND, 카세트 출력을 한번에 조작할 수 있습니다.
데이터는 아래처럼 사용할 수 있는데요.
비트0-3: 키보드 매트릭스의 ROW 선택
비트4: 카세트 모터 0:ON, 1:OFF
비트5: 카세트 출력 0:LOW, 1:HIGH
비트6: CAPS LED 0:ON, 1:OFF
비트7: 1BIT 사운드 출력 0:LOW, 1:HIGH
여기서 비트7,6을 한번에 바꿔서, 사운드 출력 주파수에 맞춰 LED가 반짝이도록 합니다.
카세트 포트도 바꿔주면 카세트 출력도 함께되겠지만 일단 비트7,6만 바꿔봅니다.
BASIC에서 아래 프로그램을 실행해보세요.
10 FOR L=0 TO 20
20 OUT &HAA,&B00110000
30 FOR I=0 TO L:NEXT
40 OUT &HAA,&B11110000
50 FOR I=0 TO L:NEXT
60 NEXT:GOTO 10
터보알 고속모드에서는 10 FOR L=0 TO 70 으로 하고 실행해보세요.
쀼~웅~ 소리와 함께 CAPS LED가 반짝이는 것을 볼수 있습니다.
위의 예처럼 간단한 하드웨어는, IO맵 방식으로 만들면 쉽게 조작할수 있습니다.
하지만 주소 공간이 256개 뿐이라 MSX에서는 이미 많은 주소가 할당(예약)되어 있지요.
궁금하신 분은 아래 싸이트에서 IO맵을 확인할 수 있습니다.
http://map.grauw.nl/resources/msx_io_ports.php
메모리맵 IO는 선택된 슬롯에서만 동작하니까, 다른 기기의 IO 주소가 겹칠수가 없겠죠.
MPXP 같은 메모리맵 IO로 된 기기를 두개를 장착하면,
두개의 MP3 파일을 동시에 소리나게 할수도 있겠습니다.