サブページ
$BFE001

CIAの概要

Amigaは、カスタムチップDMAの速度を必要としない周辺I/O用に、2つのMOS 8520 Complex Interface Adapter(CIA)を使用する。8520はCommodore 64で知られる6526の派生型で、レジスタ8〜11のみが異なる(6526のTOD時計がイベントカウンタに置き換えられている)。

各8520は以下を提供する:

  • 2つの8ビットプログラマブルパラレルポート(PAとPB)
  • 2つの16ビットカウントダウンタイマー(タイマーAとタイマーB)
  • アラーム機能付き24ビットイベントカウンタ
  • 双方向シリアルシフトレジスタ
  • 5つの割り込みソースを持つ割り込み制御レジスタ(ICR)

8520は8ビットの6502ファミリプロセッサ用に設計され、68000とは同期的に通信する。クロックは68000のEクロック、約716kHz。

2つのCIA

CIAベースアドレス
$BFE001CIA-A — データバスD0〜D7に接続(奇数アドレス、256バイト間隔)
$BFD000CIA-B — データバスD8〜D15に接続(偶数アドレス、256バイト間隔)

アドレス$BFE001――CIA-Aのベース――が本サイトの名前の由来である。キーボード、ディスク状態、ジョイスティックのファイアボタン、電源LEDの状態を確認するためにシステムが最初に読むアドレスである。Amigaプログラマにとって、このアドレスは即座に認識できる存在だ。

CIA-Aはデータバスの下位バイト(D0〜D7)に接続されるため、すべてのレジスタは奇数アドレスに現れる。CIA-Bは上位バイト(D8〜D15)に接続され、レジスタは偶数アドレスに現れる。チップセレクト信号はアドレスラインA12(CIA-A、アクティブロー)とA13(CIA-B、アクティブロー)から導出され、レジスタはアドレスラインA8〜A11をチップ内部のレジスタセレクト(チップ上のA0〜A3)として使用し、256バイト($100)間隔で配置される。

割り込みルーティング

  • CIA-AのIRQはPAULAのINT2(PORTS、レベル2割り込み)に接続
  • CIA-BのIRQはPAULAのINT6(EXTER、レベル6割り込み)に接続
$BFE001

レジスタマップ

各CIAは16のレジスタを持つ(レジスタ11/$Bは未使用)。256バイト間隔のため、完全なレジスタマップは広いアドレス範囲にまたがる。

CIA-Aレジスタアドレス
$BFE001PRA — ポートAデータレジスタ
$BFE101PRB — ポートBデータレジスタ
$BFE201DDRA — ポートAデータ方向レジスタ
$BFE301DDRB — ポートBデータ方向レジスタ
$BFE401TALO — タイマーA下位バイト
$BFE501TAHI — タイマーA上位バイト
$BFE601TBLO — タイマーB下位バイト
$BFE701TBHI — タイマーB上位バイト
$BFE801EVENT LO — イベントカウンタ ビット0〜7
$BFE901EVENT MID — イベントカウンタ ビット8〜15
$BFEA01EVENT HI — イベントカウンタ ビット16〜23
$BFEB01—(未使用)
$BFEC01SP — シリアルデータレジスタ(キーボード)
$BFED01ICR — 割り込み制御レジスタ
$BFEE01CRA — 制御レジスタA
$BFEF01CRB — 制御レジスタB
CIA-Bレジスタアドレス
$BFD000PRA — ポートAデータレジスタ
$BFD100PRB — ポートBデータレジスタ
$BFD200DDRA — ポートAデータ方向レジスタ
$BFD300DDRB — ポートBデータ方向レジスタ
$BFD400TALO — タイマーA下位バイト
$BFD500TAHI — タイマーA上位バイト
$BFD600TBLO — タイマーB下位バイト
$BFD700TBHI — タイマーB上位バイト
$BFD800EVENT LO — イベントカウンタ ビット0〜7
$BFD900EVENT MID — イベントカウンタ ビット8〜15
$BFDA00EVENT HI — イベントカウンタ ビット16〜23
$BFDB00—(未使用)
$BFDC00SP — シリアルデータレジスタ
$BFDD00ICR — 割り込み制御レジスタ
$BFDE00CRA — 制御レジスタA
$BFDF00CRB — 制御レジスタB
$BFE001

パラレルポート

各CIAは2つの8ビット双方向パラレルポート(PAとPB)を持つ。各ビットの方向は対応するデータ方向レジスタ(DDR)で制御される:0ビットはピンを入力に、1ビットは出力に設定する。ポートレジスタの読み取りは、方向設定に関係なく常にピンの実際の状態を返す。

CIA-A ポートA($BFE001

ビット 方向 信号 機能
7IN/FIR1ジョイスティックポート1、ファイアボタン(アクティブロー)
6IN/FIR0ジョイスティックポート0、ファイアボタン(アクティブロー)
5IN/RDYディスクドライブレディ(アクティブロー)
4IN/TK0ディスクヘッドがトラック0(アクティブロー)
3IN/WPROディスク書き込み保護(アクティブロー)
2IN/CHNGディスク交換(アクティブロー)
1OUT/LED電源LED制御(0 = LED点灯)
0OUT/OVLメモリオーバーレイ(セット時ROMが$000000にマップ)

DDRAのデフォルトは$03(ビット0〜1が出力、ビット2〜7が入力)。/OVLビットはKickstart ROMがアドレス$000000にマップされるか(オーバーレイアクティブ)を制御し、ブートシーケンスで重要な役割を果たす。/LEDビットは電源LEDを直接制御する――おなじみのディスクアクティビティの点滅は、単にソフトウェアがこのビットをトグルしているだけである。

CIA-A ポートB($BFE101)

CIA-AのポートBはパラレル(Centronics)ポートに接続されている。8ビットすべてがプリンタ通信用のデータを伝送する。ハンドシェイク信号PC(/DRDY — データレディ)とFLAG(/ACK — アクノリッジ)が転送を調整する。

CIA-B ポートA($BFD000)

ビット 方向 信号 機能
7OUT/DTRシリアルポートDTR出力
6OUT/RTSシリアルポートRTS出力
5IN/CDシリアルポート キャリア検出
4IN/CTSシリアルポート 送信許可
3IN/DSRシリアルポート データセットレディ
2OUTSELパラレルポートSELECT
1OUTPOUTパラレルポート 用紙切れ
0INBUSYパラレルポート ビジー

DDRAデフォルト:$C0(ビット6〜7が出力、残りは入力)。

CIA-B ポートB($BFD100)

ビット 方向 信号 機能
7OUT/MTRディスクドライブモーター制御
6OUT/SEL3ドライブDF3:選択
5OUT/SEL2ドライブDF2:選択
4OUT/SEL1ドライブDF1:選択
3OUT/SEL0内蔵ドライブDF0:選択
2OUT/SIDEディスクサイド選択(0 = 上面、1 = 下面)
1OUTDIRディスクヘッドステップ方向(0 = 外側、1 = 内側)
0OUT/STEPディスクヘッドステップパルス(アクティブロー)

DDRBデフォルト:$FF(すべて出力)。このポートがフロッピーディスクドライブ機構全体を制御する。

ハンドシェイク(PCとFLAG)

ポートBのデータ転送は2つのハンドシェイク信号で調整できる。PC(ポートコントロール)ピンは、ポートBへのアクセスから3クロックサイクル後にローになり、データが書き込まれたことを通知する。FLAGピンは入力がハイからローに遷移すると発火し、ICRのFLAGビットをセットする。一方のCIAのPCをもう一方のFLAGに接続すると、効率的なハードウェアハンドシェイクが実現する。

CIA-A: SP = KDAT(キーボードシリアルデータ)、CNT = KCLK(キーボードクロック)、PC = /DRDY、FLAG = /ACK。 CIA-B: FLAG = /INDEX(ディスクインデックスパルス)、PCは未使用。

$BFE001

タイマー

各CIAは2つの独立した16ビットカウントダウンタイマーを持つ。タイマーはプリセット値からゼロまでカウントダウンし、ゼロに達するとICRにフラグをセットし、オプションで割り込みを生成する。

タイマーレジスタ

各タイマーは2つの8ビットレジスタを使用する。読み取り時は現在のカウンタ値を返す。書き込み時は値がラッチ(プリスケーラ)に格納され、カウンタには即座にロードされない。

タイマーレジスタアドレス(CIA-A)
$BFE401TALO — タイマーA 下位バイト(読み取り: カウンタ、書き込み: ラッチ)
$BFE501TAHI — タイマーA 上位バイト(読み取り: カウンタ、書き込み: ラッチ)
$BFE601TBLO — タイマーB 下位バイト(読み取り: カウンタ、書き込み: ラッチ)
$BFE701TBHI — タイマーB 上位バイト(読み取り: カウンタ、書き込み: ラッチ)

安全なカウンタ読み取り

タイマーは非同期にデクリメントされるため、上位バイトと下位バイトを別々に読むとレースコンディションが発生する可能性がある。例えば、カウンタが$0100の場合、上位バイトの読み取りは$01を返すが、下位バイトの読み取り前にカウンタがデクリメントされると、下位バイトは$FFを返し、不正な値$01FFが得られる。安全な方法は:上位を読み、下位を読み、再度上位を読む。上位バイトが変化していれば、プロセスを繰り返す。

クロックソース

タイマーAはCRAのINMODEビットで制御される2つの入力モードを持つ:

  • INMODE = 0:各クロックサイクルでデクリメント(Eクロックから約716kHz)
  • INMODE = 1:CNT信号の各正エッジでデクリメント

タイマーBはCRBのビット6〜5で制御される4つの入力モードを持つ:

  • 00:クロックサイクル(約716kHz)
  • 01:CNT信号の正エッジ
  • 10:タイマーAのアンダーフロー(A+Bを32ビットタイマーとして連結)
  • 11:CNTハイでゲートされたタイマーAアンダーフロー(CNTパルス幅の測定)

動作モード

RUNMODEビットで選択する:

  • 連続モード(RUNMODE = 0):ゼロに達した後、ラッチから再ロードしてカウントを継続
  • ワンショットモード(RUNMODE = 1):ゼロに達した後、カウンタが停止しSTARTビットがクリアされる

カウンタのロード

ラッチ値は3つの方法でカウンタに転送される:

  1. 強制ロード: 制御レジスタのLOADビット(ストローブ)をセットすると、即座にラッチ値がロードされる
  2. アンダーフロー: カウンタがゼロに達すると自動的にラッチが再ロードされる
  3. 停止時の自動ロード: タイマーが停止中にタイマー上位バイトに書き込むと自動ロードがトリガーされる

タイマー値を書き込む際は、意図しない自動ロードを避けるため、常に上位バイトを先に、次に下位バイトを書き込むこと。

ポートBへのタイマー出力

各タイマーはオプションでポートBのピンに出力可能:タイマーAはPB6へ、タイマーBはPB7へ。制御レジスタのPBONビットで有効化する。OUTMODEビットで選択:

  • パルスモード(OUTMODE = 0):各アンダーフローで1サイクルの正パルス
  • トグルモード(OUTMODE = 1):各アンダーフローで出力がトグル
$BFE001

制御レジスタ

制御レジスタA(CRA、レジスタ$E)

ビット 名前 機能
7TODIN0=60Hz, 1=50HzTOD入力周波数(イベントカウンタクロック選択)
6SPMODE0=入力, 1=出力シリアルポート方向
5INMODE0=クロック, 1=CNTタイマーAクロックソース
4LOADストローブラッチをカウンタに強制ロード(1を書き込んでトリガー)
3RUNMODE0=連続, 1=ワンショットタイマーA動作モード
2OUTMODE0=パルス, 1=トグルPB6上のタイマーA出力波形
1PBON0=オフ, 1=オンPB6へのタイマーA出力を有効化
0START0=停止, 1=開始タイマーAの開始/停止

制御レジスタB(CRB、レジスタ$F)

ビット 名前 機能
7ALARM0=TOD書込, 1=アラーム書込イベントカウンタアクセスモード: カウンタまたはアラームを書き込む
6–5INMODE00/01/10/11タイマーBクロックソース(上記参照)
4LOADストローブラッチをカウンタに強制ロード(1を書き込んでトリガー)
3RUNMODE0=連続, 1=ワンショットタイマーB動作モード
2OUTMODE0=パルス, 1=トグルPB7上のタイマーB出力波形
1PBON0=オフ, 1=オンPB7へのタイマーB出力を有効化
0START0=停止, 1=開始タイマーBの開始/停止

Amigaでのタイマー使用

  • CIA-A タイマーAはOSがキーボード通信に常時使用
  • CIA-A タイマーBは汎用に利用可能
  • CIA-B タイマーAはシリアルポートのボーレート生成に使用
  • CIA-B タイマーBはBlitterの同期モードで使用
$BFE001

イベントカウンタとシリアルポート

イベントカウンタ(レジスタ$8〜$A)

8520は6526のTOD(Time of Day)時計を単純な24ビットイベントカウンタに置き換えている。0から16,777,215($FFFFFF)までカウントし、TOD入力信号の各正エッジでインクリメントされる。$FFFFFFに達すると0にラップする。

Amigaでは: - CIA-Aのイベントカウンタは電源からの50Hzパルス(商用電源周波数)を受信し、単純な経過時間カウンタとして機能する。 - CIA-Bのイベントカウンタは15,625Hzの水平同期パルスを受信し、高分解能タイミングソースを提供する。

読み書き

カウンタはMSB(レジスタ$A)が読まれたときに値をラッチする。その後のレジスタ$9と$8の読み取りは、内部カウンタが動き続ける間、ラッチされた値を返す。LSB(レジスタ$8)が読まれるとラッチが解放され、次のスナップショットの準備が整う。

書き込み時は、MSBを書き込むとカウンタが停止する。LSBを書き込むと再開する。常にMSBを先に、次にミドルバイト、最後にLSBを書き込むこと。

アラーム機能

CRBのビット7(ALARM)をセットすると、レジスタ$8〜$Aへの書き込みがカウンタ値ではなくアラーム値を設定する。カウンタがアラーム値に達するとICRのAlarmビットがセットされ、割り込みが生成される。レジスタ$8〜$Aの読み取りはALARMビットの状態に関係なく常に現在のカウンタ値を返す。

シリアルシフトレジスタ(レジスタ$C)

シリアルポートはデータレジスタ(SDR)と内部シフトレジスタで構成される。方向はCRAのSPMODEビットで制御される:

入力モード(SPMODE = 0):SPピン上のデータがCNT信号の各正エッジでシフトインされる。8ビット後、シフトレジスタがSDRに転送され、SP割り込みフラグがセットされる。

出力モード(SPMODE = 1):タイマーAがボーレートを制御する。SDRに書き込まれたデータがシフトレジスタに転送され、タイマーA周波数の半分の速度でSPからMSBファーストでクロックアウトされる。CNTピンがクロック信号を出力する。最大出力レートは8520のクロック周波数の4分の1。

CIA-AではSPがキーボードシリアルデータ(KDAT)、CNTがキーボードクロック(KCLK)を伝送する。

$BFE001

割り込み制御レジスタ

ICR(レジスタ$D)は5つの割り込みソースをデュアルレジスタ構造で管理する:データレジスタ(読み取り)とマスクレジスタ(書き込み)で、同じアドレスからアクセスする。

ICRの読み取り(データレジスタ)

ビット 名前 ソース 機能
7IR割り込み発生(有効なソースが発火)
6–5常に0(未使用)
4FLAGFLAGピンFLAG入力で負エッジ検出
3SPシリアルシフトレジスタフル(入力時)またはエンプティ(出力時)
2ALARMカウンタイベントカウンタがアラーム値に一致
1TBタイマーBタイマーBアンダーフロー(ゼロに到達)
0TAタイマーAタイマーAアンダーフロー(ゼロに到達)

ICRを読むとデータレジスタの値が返され、IRを含むすべてのビットがクリアされる。後で値が必要な場合は、読み取り直後にRAMに保存すること。

ICRへの書き込み(マスクレジスタ)

ビット 名前 機能
7S/C0=クリア, 1=セットマスクビットのセット/クリア制御
6–5未使用
4FLAGマスクFLAG割り込みの有効化/無効化
3SPマスクシリアルポート割り込みの有効化/無効化
2ALARMマスクアラーム割り込みの有効化/無効化
1TBマスクタイマーB割り込みの有効化/無効化
0TAマスクタイマーA割り込みの有効化/無効化

マスクレジスタはDMACONと同じSET/CLR機構を使用する。S/C = 1のとき、書き込み値でセットされたビットがマスクで有効化される。S/C = 0のとき、無効化される。0として書き込まれたビットは影響を受けない。

割り込みは、データレジスタのビットがセットされかつ対応するマスクビットが有効な場合のみ生成される(IRQピンがローになる)。ICRが読まれる(データレジスタがクリアされる)と、IRQラインはハイに戻る。

    ; CIA-AのタイマーA割り込みを有効化:
    MOVE.B #$81,$BFED01    ; S/C=1, TA=1 → マスクでTAを有効化

    ; 両タイマー割り込みを無効化:
    MOVE.B #$03,$BFED01    ; S/C=0, TA=1, TB=1 → マスクでTAとTBをクリア

CIA割り込みの流れ

CIA割り込みが発生すると、以下のシーケンスで処理される:

  1. ソースがCIAのICRデータレジスタの対応ビットをセット
  2. 対応するマスクビットがセットされていれば、IRビット(ビット7)がセットされIRQがローになる
  3. PAULAがIRQを検出し、対応するINTREQビット(CIA-Aはビット3、CIA-Bはビット13)をセット
  4. INTENAが許可していれば、68000が割り込みを受信
  5. ハンドラがCIAのICRを読んでソースを特定(CIA側のフラグがクリアされる)
  6. ハンドラがPAULAのINTREQビットをクリア