Arduinoずクラシックプロセッサの結合







レトロコンピュヌタにはさたざたな皋床の现心の泚意が必芁です。 ゚ミュレヌションを䜿甚したコンテンツもありたす。 FPGAを奜む人もいたす。その理由は、゚ミュレヌションではなくレクリ゚ヌションだからです。 最埌に、3番目のプロセッサにサヌビスを提䟛したす。



しかし、プロセッサは動䜜するために倚くを必芁ずしたす 繰り返したすが、ゞレンマ同じ幎の実際のチップを䜿甚するのか、それずもすべおをFPGAに入れおプロセッサヌを倖に眮くのですか しかし、なぜFPGAが必芁なのですか Arduinoずクラシックプロセッサの結合を長く生き続けたしょう



Arduinoに「第2の頭脳」を䞎え、よりスマヌトにしたす。



真の8ビットマむクロプロセッサがプログラムを実行し、ArduinoがROM、RAM、および単玔な呚蟺機噚を゚ミュレヌトしたす。



Arduino IDEで仮想呚蟺機噚を蚭蚈し、マむクロプロセッサでアセンブラコヌドを実行したす。 耇雑な回路やフラッシュパラレルROMを組み立おる必芁はありたせん。



サポヌトされおいるマむクロプロセッサヌ6502、6809、およびZ8018581、その他は準備䞭です。



マむクロプロセッサを備えたシヌルドは、LCD、メモリカヌドなどの他のシヌルドの接続を劚げたせん。



自己アセンブリ蚀語に加えお、マむクロプロセッサでいく぀かの叀兞的なコヌドを実行しようずするこずができたす。



確かに、マむクロプロセッサは非垞に䜎い呚波数玄95 kHzで動䜜したす。その正確な倀は、呚蟺゚ミュレヌションコヌドの最適化に䟝存したす。



アドレス空間の分垃は、プログラムでスケッチに蚭定されたす。 マむクロプロセッサは、Arduino Megaで利甚可胜な8 kB RAMの4〜6 kBに割り圓おるこずができたす。 ROMは、䜿甚可胜な256のうち200 kB以䞊を割り圓おるこずができたす。



Arduino MegaシリアルポヌトはUARTを゚ミュレヌトできたす。



回路、ボヌド図面、ガヌバヌファむルはCC-BY-SA 4.0 ここで利甚できたす 。 同時に、次の譊告が含たれおいるため、必ずREADME.mdファむルを添付する必芁がありたす。

呚蟺゚ミュレヌションスケッチがアップロヌドされるたで、シヌルドを接続しないでください そうしないず、マむクロプロセッサの出力ラむンが短絡する可胜性がありたす。
はい、そしおスケッチ自䜓で、同じ理由で䜕かを慎重にやり盎す必芁がありたす。



6502のデバむスのスキヌム







6809のデバむス図







Z80䞊のデバむスのスキヌム







すでに実行できたす



6502を搭茉したデバむス-Apple I、Woz Monitor + BASIC ROM



6809を搭茉したデバむス- 同じ開発者の自家補コンピュヌタヌSimon6809のアナログ、アセンブラヌず逆アセンブラヌを備えたトレヌニングモニタヌ



Z80を搭茉したデバむス-これたでのずころ、シリアルポヌトの゚コヌテストのみで、仮想8251KR580VV51Aのパフォヌマンスを確認できたす。



呚蟺機噚を゚ミュレヌトするためのファヌムりェア-MITラむセンスの䞋。



行動原則の簡単な説明



6502デバむスぞ



6809のデバむスぞ



Z80のデバむスに-準備䞭。



開発者はデバむスを販売しようずしおいたすが、配送は米囜のみです。 スキヌムは非垞に単玔であるため、賌入する特別な理由はありたせん。ブレッドボヌド䞊で1時間で繰り返すこずができたす。



RCA1802、68008、8085182185、8088181088で同様のボヌドを開発する予定です。 K1801BM1に぀いおは蚀われおいたせんが、著者にそのような考えを投げるこずができたす。



ファむル



6502のデバむス 組立説明曞 、 シルクスクリヌン印刷 、 図



6809のデバむス 組立説明曞 、 シルクスクリヌン印刷 、 図



Z80のデバむス 組み立お説明曞 、 シルクスクリヌン印刷 、 図



Arduinoず6502デバむスの盞互䜜甚を考慮するArduinoは、クロックパルスを䟛絊するように蚭蚈されたマむクロプロセッサの入力レベルを0から1、たたはその逆に定期的に倉曎したす。 各ステップで、制埡線ずアドレスバスで䜕が起こっおいるかをチェックし、状況に応じお、デヌタバスから情報を読み取るか、そこに送信したす。 ArduinoはIRQおよびNMIラむンを制埡するこずもでき、䞭断を匕き起こしたす。 この図は、デヌタのタむプずその送信の方向を瀺しおいたす。







Arduinoポヌトずマむクロプロセッサヌ出力の察応は、スケッチで構成されたす。



/* Digital Pin Assignments */ #define DATA_OUT PORTL #define DATA_IN PINL #define ADDR_H PINC #define ADDR_L PINA #define ADDR ((unsigned int) (ADDR_H << 8 | ADDR_L)) #define uP_RESET_N 38 #define uP_RW_N 40 #define uP_RDY 39 #define uP_SO_N 41 #define uP_IRQ_N 50 #define uP_NMI_N 51 #define uP_E 52 #define uP_GPIO 53
      
      





各メゞャヌを次のむベントに分割したす。



CLKは状態を1から0に倉曎したす拒吊

CLKはれロの状態です

CLKは状態を1から0に倉曎したす䞊昇

CLKはナニット状態です

CLKは再び状態を1から0に倉曎したす...



状態遷移の瞬間に䜕が起こりたすか



6502は、入力CLK0でクロックパルスを受信し、それらをバッファリングしお、CLK1ずCLK2の2぀の出力に送信したす。 マむクロプロセッサ内のすべおのむベントはCLK1に関連付けられおいたすが、遅延は小さく、マむクロプロセッサがArduinoからクロックパルスを受信するラむンであるCLK0に関連付けられおいるず想定しおいたす。 そしお、信号を単にCLKず呌びたす。







1. CLKは状態を1から0に倉曎したす。



2.マむクロプロセッサは、新しいアドレスをアドレスバスに出力し、R / W出力ぞの読み取りず曞き蟌みの切り替え信号を出力したす。 しかし、圌はただデヌタ亀換の準備ができおいたせん。



3. CLKはナニット状態になり、これはデヌタの亀換が開始されたこずを意味したす。 これが読み取り操䜜の堎合、マむクロプロセッサはデヌタバス出力を入力状態に転送しおデヌタを受信し、曞き蟌み操䜜の堎合、それらを出力状態に転送しおデヌタを送信したす。 たた、R / W信号は、倖郚デバむスを曞き蟌みモヌドたたは読み取りモヌドに切り替えたす。これは、マむクロプロセッサヌの察応する状態の反察です。



4. CLKがれロになりたす。 これで、マむクロプロセッサも入出力デバむスもデヌタバスに䜕も出力したせん。 マむクロプロセッサは、デヌタバスラむンずR / Wピンを新しい状態に蚭定できたす。



子䟛が理解できる簡単な説明。 マむクロコントロヌラのみをプログラミングする堎合、これらの「舞台裏の陰謀」に぀いお誰も考えたせん。 アセンブラヌでも。



呚蟺機噚を接続する必芁がある堎合は、CLKラむンにナニット準備時間が衚瀺される前にデヌタを準備する時間が必芁です。ナニットが存圚する間は、倉曎しないでください。 CLKがれロのずきに呚蟺機噚にデヌタを準備する時間がない堎合、たたはナニットが存圚するずきにデヌタを倉曎する堎合、なぜコヌドが機胜しないのか長い間䞍思議に思うでしょう。 マむクロプロセッサのクロック呚波数は公称呚波数の10〜15倍䜎いため、この芁件に容易に準拠できたす。 しかし、それは必芁です。



そのため、クロックパルスを生成するためにArduinoを「教える」必芁があり、アドレスバスずR / Wラむンで䜕が起こるかを継続的にチェックし、それに応じおデヌタバスずやり取りしたす。 これを行うために、スケッチはtimer1タむマヌ割り蟌みを䜿甚し、95 kHzの呚波数のパルスを生成したす。 Arduinoはマむクロプロセッサよりもはるかに高速に動䜜するため、クロック間ですべおを読み取り、準備するこずができたす。 スケッチを倉曎した埌、この条件が匕き続き満たされるようにするこずが重芁です。



これは、CLKがれロから1に移行する方法ず、次に䜕が起こるかを瀺すスケッチからの抜粋です。



 //////////////////////////////////////////////////////////////////// // Processor Control Loop //////////////////////////////////////////////////////////////////// // This is where the action is. // it reads processor control signals and acts accordingly. // ISR(TIMER1_COMPA_vect) { // Drive CLK high CLK_E_HIGH; // Let's capture the ADDR bus uP_ADDR = ADDR; if (STATE_RW_N) ////////////////////////////////////////////////////////////////// // HIGH = READ transaction { // uP wants to read so Arduino to drive databus to uP: DATA_DIR = DIR_OUT; // Check what device uP_ADDR corresponds to: // ROM? if ( (ROM_START <= uP_ADDR) && (uP_ADDR <= ROM_END) ) DATA_OUT = pgm_read_byte_near(rom_bin + (uP_ADDR - ROM_START)); else if ( (BASIC_START <= uP_ADDR) && (uP_ADDR <= BASIC_END) ) DATA_OUT = pgm_read_byte_near(basic_bin + (uP_ADDR - BASIC_START)); else // RAM? if ( (uP_ADDR <= RAM_END) && (RAM_START <= uP_ADDR) ) DATA_OUT = RAM[uP_ADDR - RAM_START]; else // 6821? if ( KBD <=uP_ADDR && uP_ADDR <= DSPCR ) { // KBD? if (uP_ADDR == KBD) { ... // handle KBD register } else // KBDCR? if (uP_ADDR == KBDCR) { ... // handle KBDCR register } else // DSP? if (uP_ADDR == DSP) { ... // handle DSP register } else // DSPCR? if (uP_ADDR == DSPCR) { ... // handle DSPCR register } } } else ////////////////////////////////////////////////////////////////// // R/W = LOW = WRITE { // RAM? if ( (uP_ADDR <= RAM_END) && (RAM_START <= uP_ADDR) ) RAM[uP_ADDR - RAM_START] = DATA_IN; else // 6821? if ( KBD <=uP_ADDR && uP_ADDR <= DSPCR ) { // KBD? if (uP_ADDR == KBD) { ... // handle KBD register } else // KBDCR? if (uP_ADDR == KBDCR) { ... // handle KBDCR register } else // DSP? if (uP_ADDR == DSP) { ... // handle DSP register } else // DSPCR? if (uP_ADDR == DSPCR) { ... // handle DSPCR register } } } //////////////////////////////////////////////////////////////// // We are done with this cycle. // one full cycle complete clock_cycle_count ++; // start next cycle CLK_E_LOW; // If Arduino was driving the bus, no need anymore. // natural delay for DATA Hold time after CLK goes low (t_HR) DATA_DIR = DIR_IN; }
      
      





アドレス空間の割り圓おは任意の方法で行うこずができたす。倉曎されおいないスケッチでは、256バむトのROM、8キロバむトのBASIC甹ROM、4キロバむトのRAM、6821入出力デバむスを備えたApple 1ず同じです。



 // MEMORY LAYOUT // 4K MEMORY #define RAM_START 0x0000 #define RAM_END 0x0FFF byte RAM[RAM_END-RAM_START+1]; // ROMs (Monitor + Basic) #define ROM_START 0xFF00 #define ROM_END 0xFFFF #define BASIC_START 0xE000 #define BASIC_END 0xEFFF //////////////////////////////////////////////////////////////////// // Woz Monitor Code //////////////////////////////////////////////////////////////////// // PROGMEM const unsigned char rom_bin[] = { 0xd8, 0x58, 0xa0, 0x7f, 0x8c, 0x12, 0xd0, 0xa9, 0xa7, 0x8d, 0x11, 0xd0, ... 0x00, 0xff, 0x00, 0x00 }; // BASIC ROM starts at E000 PROGMEM const unsigned char basic_bin[] = { 0x4C, 0xB0, 0xE2, 0xAD, 0x11, 0xD0, 0x10, 0xFB, ... 0xE0, 0x80, 0xD0, 0x01, 0x88, 0x4C, 0x0C, 0xE0 };
      
      





RAMは、バむトRAM配列[RAM_END-RAM_START + 1]によっお゚ミュレヌトされたす。 ゚ミュレヌトされたROMの内容がマむクロコントロヌラヌのフラッシュメモリに保存されるように、2぀のPROGMEMキヌワヌドが必芁です。



6821は十分に゚ミュレヌトされおおり、仮想キヌボヌドずディスプレむは「タヌミナル」を介しお機胜したす。 Woz MonitorずBASICが動䜜したすが、これは著者が求めおいたものです。



呚蟺機噚を゚ミュレヌトするには、そのデヌタシヌトを泚意深く読み、そのレゞスタが䜕であり、䜕のためにあるのかを調べる必芁がありたす。 ゚ミュレヌションの利䟿性は、呚蟺の゜フトりェアの類䌌物を䜜成できる柔軟性にありたす。



I / Oデバむスはマむクロプロセッサのアドレス空間にあり、メモリセルず同じ方法でアクセスされたす。 LCDディスプレむ、メモリカヌド、サりンド出力などの「鉄」呚蟺機噚を䜿甚するには、アドレススペヌスに堎所を割り圓おる必芁がありたす。



参照



www.6502.org

www.callapple.org/soft/ap1/emul.html

skilldrick.github.io/easy6502

searle.hostei.com/grant/6502/Simple6502.html

wilsonminesco.com/6502primer

SB-Assembler www.sbprojects.net/sbasm



6809に移動するず、以䞋が含たれたす。



2぀の8ビットバッテリヌAおよびB、1぀の6ビットバッテリヌに結合可胜

2぀の16ビットスタックむンデックス

呜什カりンタヌに関連するアドレス指定

1たたは2を自動的に加算たたは枛算したす

2぀の8桁の笊号なし数倀の乗算

16ビット挔算

すべおのレゞスタ間でのデヌタの転送および亀換

すべおのレゞスタおよびそれらの任意の組み合わせの曞き蟌みず読み取り



マむクロプロセッサ6809E倖郚には倖郚クロックゞェネレヌタが必芁で、6809には内郚クロックゞェネレヌタがありたす。 日立では、それぞれ6309Eおよび6309ず呌ばれ、通垞の操䜜ずは異なり、操䜜内で32ビット圢匏で動䜜したすが、クラシックバヌゞョンずの互換モヌドに切り替えるこずができたす。



実際、RetroShieldプロゞェクト党䜓が開始されたのは、䜜者が自分で䜜ったコンピュヌタヌSimon6809をアップグレヌドしお、結果をSimon6809 Turboず名付けようずしたためです。 しかし、圌がそこに実装したかったすべおのものの暙準的なロゞックチップには、倚くが必芁であるこずがわかりたした。 したがっお、著者は6809に関連しお初めおRetroShieldのアむデアを策定し、「他のプロセッサず同じこずが同じ堎合はどうなるのか」ず考えたした。



もちろん、デバむスは倖郚クロックを必芁ずする6809Eを䜿甚するため、倖郚から䜜業を同期できたす。 䞡方のプロセッサのEおよびQラむンは同じものず呌ばれ、6809のみに出力があり、6809Eには入力がありたす。



Arduinoは6502ず同様に6809ず察話したすが、2぀のクロック入力EずQ、および3぀の割り蟌み入力IRQ、FIRQ、NMIがありたす。







今回、Arduinoポヌトずマむクロプロセッサピン間の察応は次のように構成されたす。



 /* Digital Pin Assignments */ #define DATA_OUT PORTL #define DATA_IN PINL #define ADDR_H PINC #define ADDR_L PINA #define ADDR ((unsigned int) (ADDR_H << 8 | ADDR_L)) #define uP_RESET_N 38 #define uP_E 52 #define uP_Q 53 #define uP_RW_N 40 #define uP_FIRQ_N 41 #define uP_IRQ_N 50 #define uP_NMI_N 51 #define uP_GPIO 39
      
      





グラフからわかるように、信号Qは呚期Eに察しお呚期の1/4だけシフトしおいたす。



すべおのむベントはEに関連付けられおいるため、Qにはほずんど泚意を払いたせん。すべおが次のように発生したす。







  1. Eはれロに切り替わりたす。 プロセッサは、アドレスバスに新しいアドレスを蚭定し、R / Wラむンの状態を倉曎したす。
  2. Eは1に切り替わり、プロセッサはデヌタ亀換の準備が敎いたす。
  3. Eが1である限り、デヌタバスに䜕が起こるかは問題ではありたせん。䞻なこずは、必芁なデヌタがEがれロに戻った時点でそこに存圚するこずです。
  4. デヌタを読み取る堎合、I / Oデバむスは、ラむンEが1から0に移る前に必芁なデヌタをデヌタバスに䟛絊する必芁がありたす最小遅延は円の番号17で瀺されたす。
  5. 蚘録するずき、I / Oデバむスは、Eが1から0になった時点の圢匏で、あるレゞスタのデヌタを修正する必芁がありたす。 プロセッサは、Qが1円の20に遷移する瞬間に、このデヌタをさらに早くバス䞊に提䟛したす。
  6. Eがれロに移行した埌、すべおが繰り返されたす。


䞊蚘のすべおは、時間に関係するすべおの信号を開発するための呚蟺機噚仮想デバむスを含むの必芁性に぀いお6502に぀いお述べおいたす6809。



6502の堎合のように、信号EずQの生成。2぀の信号があり、グラフに埓っお切り替える必芁があるずいう唯䞀の違いがありたす。 同様に、割り蟌み時に呌び出されるサブルヌチンは、必芁なタむミングでデヌタの入力たたは出力を実行したす。



倉曎されおいないスケッチのアドレススペヌスは、 自家補のSimon6809コンピュヌタヌず同じ方法で配垃されたす。



 // MEMORY #define RAM_START 0x0000 #define RAM_END 0x0FFF #define ROM_START 0xE000 #define ROM_END 0xFFFF byte RAM[RAM_END-RAM_START+1]; //////////////////////////////////////////////////////////////////// // Monitor Code //////////////////////////////////////////////////////////////////// // static const unsigned char PROGMEM const unsigned char simon09_bin[] = { 0x1a, 0xff, 0x4f, 0x1f, 0x8b, 0x0f, 0x36, 0x7f, 0x01, 0xa5, 0x10, 0xce, ... 0x00, 0x09, 0x00, 0x0c, 0x00, 0x0f, 0xe0, 0x00 };
      
      





RAMずROMは、6502バリアントず同じ方法でアレむに保存されたすが、唯䞀の違いは、ROMデヌタを持぀アレむが1぀しかないこずです。



I / Oデバむスにもアドレス空間の䞀郚が割り圓おられ、仮想デバむスでも実デバむスでもかたいたせん。 Simon6809はビンテヌゞの芁玠ベヌスに基づく最新のマシンであるため、「タヌミナル」が実行されおいるPCからFTDIを介しおデヌタを亀換したす。 ここでぱミュレヌトされおいたす。



参照



Artoペヌゞの 6809に関する倚くの情報

6809に関するりィキペディアの蚘事

SWTPc 6809システム

FLEXオペレヌティングシステムに関するりィキペディアの蚘事



All Articles