Kartu video ISA lama dan AVR

Sekitar sepuluh tahun yang lalu saya mendapat kartu ISA-video dari 286 ... 486 mesin yang ditujukan untuk dumping. Kartu video telah diuji dan sejak itu telah mengumpulkan debu di dalam laci. Beberapa tahun yang lalu, saya punya pemikiran, tetapi haruskah saya menghubungkan kartu video ke mikrokontroler? Inilah yang akan saya bicarakan dalam artikel ini.

Untuk menghubungkan kartu video ISA lama, bus data 8-bit dan bus alamat 20-bit sudah cukup. Mikrokontroler Saya suka keluarga AVR karena kesederhanaannya, jadi saya mengambil Atmega16. Tetapi Anda dapat mengambil kenyamanan bagi Anda - dalam hal ini, kaki stm32 yang sama pasti akan cukup tanpa pengikat eksternal. Tetapi Atmega16 tidak memiliki cukup kaki untuk semua bus ini, sehingga bus alamat dirakit di tiga register paralel Soviet (saya punya banyak persediaan) K588IR1. Mikrokontroler pada gilirannya menetapkan bagian-bagian alamat dalam tiga register ini. Lebih banyak tidak diperlukan.


Pada konektor ISA, output dari sirkuit ini harus terhubung sebagai berikut:

+5,
+12,
GND
REFRESH (ditarik ke + 5V melalui resistor),
A0-A19,
D0-D7,
RESET
Memw,
Memr,
TKI
IOR
Ale
RDY,
AEN (terhubung ke GND).


Pada gambar berwarna merah, saya menandai pin konektor ISA yang perlu dihubungkan.

Untuk beberapa kartu video, Anda perlu menghubungkan -5 V dan -12 V (Anda harus mendapatkannya di suatu tempat - misalnya, dari sumber TracoPower) dan sinyal OSC (14,318 MHz) - dapat dihasilkan oleh generator paling sederhana pada K155LN1. Kartu grafis lain tidak perlu garis-garis ini. Ini dia betapa beruntungnya. Secara umum, jika kaki yang sesuai pada ISA menggantung di udara pada kartu video, Anda pasti tidak dapat menghubungkannya. Perlu diingat bahwa konsumsi kartu video pada jalur + 5V cukup besar - jika Anda menggunakan sesuatu seperti LM7805 untuk catu daya, pastikan untuk meletakkannya di radiator (sebaiknya dengan kipas angin).

Secara pribadi, desain rakitan saya terlihat seperti ini:

gambar

Satu-satunya yang tersisa adalah entah bagaimana menginisialisasi kartu video dan mulai bekerja dengannya. Ada proyek serupa di Internet - Saya menemukan satu ( tautan ), di mana saya mendapat kode inisialisasi untuk kartu video Trident 9000i. Dalam program yang sama dari Internet, ada kode inisialisasi untuk Trident9000C, tetapi komentar menunjukkan bahwa itu tidak berfungsi. Saya sudah memeriksa. Ini benar-benar tidak berfungsi - di layar sampah dan kartu video tidak menanggapi penulisan data ke RAM.

Video kerja (gambar ditransmisikan melalui SPI ke Atmega16 (seperti yang Anda lihat, garis-garis ini dibiarkan bebas dalam diagram) melalui port LPT komputer):


(Saya membuat reservasi dalam video - mode 320x200, bukan 320x240)

Dengan menggabungkan modul ini dengan mouse optik ( artikel tentang menggunakan sensor mouse ) saya mendapatkan ini:



Jika Anda memiliki keinginan untuk menjalankan kartu grafis ISA yang ada, maka untuk ini Anda harus menemukan BIOS dari kartu grafis yang diperlukan (katakanlah, di sini ) di Internet dan bongkar menggunakan IDA. Ada kode X86 biasa. Itu tidak dimulai pada alamat 0 - ada tanda tangan (2 byte) dan sebuah checksum (1 byte). Total, Anda harus mulai dengan byte ke-3. Dan secara konsisten temukan port mana yang perlu Anda rekam agar kartu berfungsi. Terus terang, saya tidak punya kesabaran untuk memahami apa yang salah dengan Trident9000C.

Untuk bekerja dengan bus ISA, modul ditulis:

Modul untuk bekerja dengan bus ISA
//**************************************************************************************************** //       ISA //**************************************************************************************************** //**************************************************************************************************** // //**************************************************************************************************** //  #define ADDR_BUS_PORT PORTA #define ADDR_BUS_DDR DDRA //  A0-A7 #define ADDR_BUS_0_7_SELECT_PORT PORTC #define ADDR_BUS_0_7_SELECT_DDR DDRC #define ADDR_BUS_0_7_SELECT 7 //  A8-A15 #define ADDR_BUS_8_15_SELECT_PORT PORTC #define ADDR_BUS_8_15_SELECT_DDR DDRC #define ADDR_BUS_8_15_SELECT 6 //  A16-A19 #define ADDR_BUS_16_19_SELECT_PORT PORTC #define ADDR_BUS_16_19_SELECT_DDR DDRC #define ADDR_BUS_16_19_SELECT 5 //  #define DATA_BUS_PORT PORTB #define DATA_BUS_DDR DDRB #define DATA_BUS_PIN PINB //RESET #define RESET_DDR DDRD #define RESET_PORT PORTD #define RESET 0 //MEMW #define MEMW_DDR DDRD #define MEMW_PORT PORTD #define MEMW 1 //MEMR #define MEMR_DDR DDRD #define MEMR_PORT PORTD #define MEMR 2 //IOW #define IOW_DDR DDRD #define IOW_PORT PORTD #define IOW 3 //IOR #define IOR_DDR DDRD #define IOR_PORT PORTD #define IOR 4 //ALE #define ALE_DDR DDRD #define ALE_PORT PORTD #define ALE 5 //RDY #define RDY_DDR DDRD #define RDY_PORT PORTD #define RDY_PIN PIND #define RDY 6 //**************************************************************************************************** //  //**************************************************************************************************** void System_Init(void);//  void System_SetAddr(unsigned long addr);//    void System_RESET_HI(void);// RESET  1 void System_RESET_LO(void);// RESET  0 void System_MEMW_HI(void);// MEMW  1 void System_MEMW_LO(void);// MEMW  0 void System_MEMR_HI(void);// MEMR  1 void System_MEMR_LO(void);// MEMR  0 void System_IOW_HI(void);// IOW  1 void System_IOW_LO(void);// IOW  0 void System_IOR_HI(void);// IOR  1 void System_IOR_LO(void);// IOR  0 void System_ALE_HI(void);// ALE  1 void System_ALE_LO(void);// ALE  0 void System_WaitReady(void);//   void System_Out8(unsigned short port,unsigned char value);//    UInt8 void System_Out16(unsigned short port,unsigned short value);//    UInt16 unsigned char System_In8(unsigned short port);//    UInt8 unsigned short System_In16(unsigned short port);//    UInt16 void System_Poke8(unsigned long addr,unsigned char value);//    UInt8 void System_Poke16(unsigned long addr,unsigned short value);//    UInt16 unsigned char System_Peek8(unsigned long addr);//    UInt8 unsigned short System_Peek16(unsigned long addr);//    UInt16 //**************************************************************************************************** //  //**************************************************************************************************** //---------------------------------------------------------------------------------------------------- //  //---------------------------------------------------------------------------------------------------- void System_Init(void) { //  DDRA=0; DDRB=0; DDRD=0; DDRC=0; ADDR_BUS_DDR=0xff; DATA_BUS_DDR=0; ADDR_BUS_0_7_SELECT_DDR|=(1<<ADDR_BUS_0_7_SELECT); ADDR_BUS_8_15_SELECT_DDR|=(1<<ADDR_BUS_8_15_SELECT); ADDR_BUS_16_19_SELECT_DDR|=(1<<ADDR_BUS_16_19_SELECT); RESET_DDR|=(1<<RESET); MEMW_DDR|=(1<<MEMW); MEMR_DDR|=(1<<MEMR); IOW_DDR|=(1<<IOW); IOR_DDR|=(1<<IOR); ALE_DDR|=(1<<ALE); RDY_DDR&=0xff^(1<<RDY); RDY_PORT|=1<<RDY; //   asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_0_7_SELECT_PORT)),[bit]"M"(ADDR_BUS_0_7_SELECT)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_8_15_SELECT_PORT)),[bit]"M"(ADDR_BUS_8_15_SELECT)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_16_19_SELECT_PORT)),[bit]"M"(ADDR_BUS_16_19_SELECT)); asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(RESET_PORT)),[bit]"M"(RESET)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(IOW_PORT)),[bit]"M"(IOW)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(IOR_PORT)),[bit]"M"(IOR)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(MEMW_PORT)),[bit]"M"(MEMW)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(MEMR_PORT)),[bit]"M"(MEMR)); asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ALE_PORT)),[bit]"M"(ALE)); } //---------------------------------------------------------------------------------------------------- //    //---------------------------------------------------------------------------------------------------- void System_SetAddr(unsigned long addr) { unsigned char al=addr&0xff; unsigned char am=(addr>>8)&0xff; unsigned char ah=(addr>>16)&0xff; System_ALE_LO();//  ALE //     ADDR_BUS_PORT=ah; asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_16_19_SELECT_PORT)),[bit]"M"(ADDR_BUS_16_19_SELECT)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_16_19_SELECT_PORT)),[bit]"M"(ADDR_BUS_16_19_SELECT)); ADDR_BUS_PORT=am; asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_8_15_SELECT_PORT)),[bit]"M"(ADDR_BUS_8_15_SELECT)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_8_15_SELECT_PORT)),[bit]"M"(ADDR_BUS_8_15_SELECT)); ADDR_BUS_PORT=al; asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_0_7_SELECT_PORT)),[bit]"M"(ADDR_BUS_0_7_SELECT)); asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ADDR_BUS_0_7_SELECT_PORT)),[bit]"M"(ADDR_BUS_0_7_SELECT)); System_ALE_HI();//  ALE } //---------------------------------------------------------------------------------------------------- // RESET  1 //---------------------------------------------------------------------------------------------------- inline void System_RESET_HI(void) { asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(RESET_PORT)),[bit]"M"(RESET)); } //---------------------------------------------------------------------------------------------------- // RESET  0 //---------------------------------------------------------------------------------------------------- inline void System_RESET_LO(void) { asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(RESET_PORT)),[bit]"M"(RESET)); } //---------------------------------------------------------------------------------------------------- // MEMW  1 //---------------------------------------------------------------------------------------------------- inline void System_MEMW_HI(void) { asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(MEMW_PORT)),[bit]"M"(MEMW)); } //---------------------------------------------------------------------------------------------------- // MEMW  0 //---------------------------------------------------------------------------------------------------- inline void System_MEMW_LO(void) { asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(MEMW_PORT)),[bit]"M"(MEMW)); } //---------------------------------------------------------------------------------------------------- // MEMR  1 //---------------------------------------------------------------------------------------------------- inline void System_MEMR_HI(void) { asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(MEMR_PORT)),[bit]"M"(MEMR)); } //---------------------------------------------------------------------------------------------------- // MEMR  0 //---------------------------------------------------------------------------------------------------- inline void System_MEMR_LO(void) { asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(MEMR_PORT)),[bit]"M"(MEMR)); } //---------------------------------------------------------------------------------------------------- // IOW  1 //---------------------------------------------------------------------------------------------------- inline void System_IOW_HI(void) { asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(IOW_PORT)),[bit]"M"(IOW)); } //---------------------------------------------------------------------------------------------------- // IOW  0 //---------------------------------------------------------------------------------------------------- inline void System_IOW_LO(void) { asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(IOW_PORT)),[bit]"M"(IOW)); } //---------------------------------------------------------------------------------------------------- // IOR  1 //---------------------------------------------------------------------------------------------------- inline void System_IOR_HI(void) { asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(IOR_PORT)),[bit]"M"(IOR)); } //---------------------------------------------------------------------------------------------------- // IOR  0 //---------------------------------------------------------------------------------------------------- inline void System_IOR_LO(void) { asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(IOR_PORT)),[bit]"M"(IOR)); } //---------------------------------------------------------------------------------------------------- // ALE  1 //---------------------------------------------------------------------------------------------------- inline void System_ALE_HI(void) { asm volatile ("sbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ALE_PORT)),[bit]"M"(ALE)); } //---------------------------------------------------------------------------------------------------- // ALE  0 //---------------------------------------------------------------------------------------------------- inline void System_ALE_LO(void) { asm volatile ("cbi %[port],%[bit]"::[port]"I"(_SFR_IO_ADDR(ALE_PORT)),[bit]"M"(ALE)); } //---------------------------------------------------------------------------------------------------- //   //---------------------------------------------------------------------------------------------------- void System_WaitReady(void) { asm volatile ("nop"::); asm volatile ("nop"::); while(1) { if (RDY_PIN&(1<<RDY)) break; } } //---------------------------------------------------------------------------------------------------- //    UInt8 //---------------------------------------------------------------------------------------------------- void System_Out8(unsigned short port,unsigned char value) { //     DATA_BUS_DDR=0xff; DATA_BUS_PORT=value; System_SetAddr(port); //   System_IOW_LO(); System_WaitReady();//  System_IOW_HI(); DATA_BUS_DDR=0; } //---------------------------------------------------------------------------------------------------- //    UInt16 //---------------------------------------------------------------------------------------------------- void System_Out16(unsigned short port,unsigned short value) { System_Out8(port,value&0xff); System_Out8(port+1,(value>>8)&0xff); } //---------------------------------------------------------------------------------------------------- //    UInt8 //---------------------------------------------------------------------------------------------------- unsigned char System_In8(unsigned short port) { unsigned char byte; System_SetAddr(port); DATA_BUS_DDR=0; //   System_IOR_LO(); System_WaitReady();//  byte=DATA_BUS_PIN; System_IOR_HI(); return(byte); } //---------------------------------------------------------------------------------------------------- //    UInt16 //---------------------------------------------------------------------------------------------------- unsigned short System_In16(unsigned short port) { unsigned short ret=System_In8(port+1); ret<<=8; ret|=System_In8(port); return(ret); } //---------------------------------------------------------------------------------------------------- //    UInt8 //---------------------------------------------------------------------------------------------------- void System_Poke8(unsigned long addr,unsigned char value) { //     DATA_BUS_DDR=0xff; DATA_BUS_PORT=value; System_SetAddr(addr); //   System_MEMW_LO(); System_WaitReady();//  System_MEMW_HI(); DATA_BUS_DDR=0; } //---------------------------------------------------------------------------------------------------- //    UInt16 //---------------------------------------------------------------------------------------------------- void System_Poke16(unsigned long addr,unsigned short value) { System_Poke8(addr,value&0xff); System_Poke8(addr+1,(value>>8)&0xff); } //---------------------------------------------------------------------------------------------------- //    UInt8 //---------------------------------------------------------------------------------------------------- unsigned char System_Peek8(unsigned long addr) { unsigned char byte; System_SetAddr(addr); DATA_BUS_DDR=0; //   System_MEMR_LO(); System_WaitReady();//  byte=DATA_BUS_PIN; System_MEMR_HI(); return(byte); } //---------------------------------------------------------------------------------------------------- //    UInt16 //---------------------------------------------------------------------------------------------------- unsigned short System_Peek16(unsigned long addr) { unsigned short ret=System_Peek8(addr+1); ret<<=8; ret|=System_Peek8(addr); return(ret); } 


Inisialisasi kartu grafis Trident 9000i adalah sebagai berikut:

Menginisialisasi Trident 9000i Graphics
 //**************************************************************************************************** //     trident //**************************************************************************************************** //**************************************************************************************************** // //**************************************************************************************************** //**************************************************************************************************** //  //**************************************************************************************************** CHIP_TYPE TRIDENT_Init(void);//   Trident unsigned char TRIDENT_TestInx2(unsigned short rg,unsigned char ix,unsigned char msk);// true,   MSK  PT   RG  1 void TRIDENT_TR9000i_Init(void);//  Trident9000i void TRIDENT_TR8900D_Init(void);//  Trident8900D bool TRIDENT_Unit_594(void);// 594 void TRIDENT_Unit_5A6(void);// 5A6 bool TRIDENT_Unit_4D9(void);// 4D9 void TRIDENT_Unit_51A(void);// 51A unsigned char TRIDENT_Unit_26A(void);// 26A void TRIDENT_Unit_179(void);// 179 void TRIDENT_Unit_2EA(void);// 2EA unsigned char TRIDENT_Unit_292(void);// 292 //**************************************************************************************************** //  //**************************************************************************************************** //---------------------------------------------------------------------------------------------------- //   Trident //---------------------------------------------------------------------------------------------------- CHIP_TYPE TRIDENT_Init(void) { VGA_Reset();//   CHIP_TYPE chiptype=UNKNOWN;//     //Trident VGA (  8800BR)    2 : // ,   128k,      A000h - BFFFh //     64k,     A000h - AFFFh. System_Out8(VGAENABLE_ADDR,0x00); System_Out8(0x46E8,0x16);//    (D3=0) System_Out8(0x46E9,0x00); System_Out8(0x0102,0x01); System_Out8(0x0103,0x00); System_Out8(0x46E8,0x0E);//    (D3=1) System_Out8(0x46E9,0x00); System_Out8(0x4AE8,0x00); System_Out8(0x4AE9,0x00); VGA_OutReg8(SEQ_ADDR,0x0B,0x00);//  ID    unsigned char chip=System_In8(0x3C5);//    unsigned char old=VGA_InReg8(SEQ_ADDR,0x0E); System_Out8(0x3C5,0x00); unsigned char value=System_In8(0x3C5)&0x0F; System_Out8(0x3C5,old); //   if (value==2) { System_Out8(0x3C5,old^2); switch(chip) { case 0x01: chiptype=TR8800BR; break; case 0x02: chiptype=TR8800CS; break; case 0x03: chiptype=TR8900; break; case 0x04: chiptype=TR8900C; TRIDENT_TR8900D_Init(); break; case 0x13: chiptype=TR8900C; TRIDENT_TR8900D_Init(); break; case 0x23: chiptype=TR9000; TRIDENT_TR9000i_Init(); break; case 0x33: chiptype=TR8900CLD; TRIDENT_TR8900D_Init(); break; case 0x43: chiptype=TR9000i; TRIDENT_TR9000i_Init(); break; case 0x53: chiptype=TR8900CXr; break; case 0x63: chiptype=LCD9100B; break; case 0x83: chiptype=LX8200; break; case 0x93: chiptype=TVGA9400CXi; break; case 0xA3: chiptype=LCD9320; break; case 0x73: chiptype=GUI9420; break; case 0xF3: chiptype=GUI9420; break; } } else { if ((chip==1)&TRIDENT_TestInx2(SEQ_ADDR,0x0E,6)) chiptype=TVGA8800BR; } return(chiptype); } //---------------------------------------------------------------------------------------------------- // true,   MSK  PT   RG  1 //---------------------------------------------------------------------------------------------------- unsigned char TRIDENT_TestInx2(unsigned short rg,unsigned char ix,unsigned char msk) { unsigned char old,nw1,nw2; old=VGA_InReg8(rg,ix); VGA_OutReg8(rg,ix,old&(~msk)); nw1=VGA_InReg8(rg,ix)&msk; VGA_OutReg8(rg,ix,old|msk); nw2=VGA_InReg8(rg,ix)&msk; VGA_OutReg8(rg,ix,old); return((nw1==0)&(nw2==msk)); } //---------------------------------------------------------------------------------------------------- //  Trident9000i //---------------------------------------------------------------------------------------------------- void TRIDENT_TR9000i_Init(void) { unsigned short i=0; System_Out8(VGAENABLE_ADDR,0x00); if (TRIDENT_Unit_4D9()==false) return;// do { System_Out8(0x3C9,0x00); i++; } while (i<768); System_Out8(MISC_ADDR,0x23); TRIDENT_Unit_51A(); } //---------------------------------------------------------------------------------------------------- //  Trident8900D //---------------------------------------------------------------------------------------------------- void TRIDENT_TR8900D_Init(void) { if (TRIDENT_Unit_594()==true) { //  256  System_Out8(0x3C8,0x00); for(unsigned short n=0;n<256;n++) { System_Out8(0x3C9,n);//R System_Out8(0x3C9,0);//G System_Out8(0x3C9,0);//B } System_Out8(MISC_ADDR,0x23); TRIDENT_Unit_5A6(); } if (TRIDENT_Unit_594()==false) { System_In8(STATUS_ADDR); System_Out8(ATTRCON_ADDR,0x20); System_In8(STATUS_ADDR); VGA_OutReg8(CRTC_ADDR,0x020,VGA_InReg8(CRTC_ADDR,0x20)&0xDF); } System_Out8(0x3D8,0x00); VGA_OutReg8(CRTC_ADDR,0x23,0x10); System_Out8(0x3C6,0xff); } //---------------------------------------------------------------------------------------------------- // 594 //---------------------------------------------------------------------------------------------------- bool TRIDENT_Unit_594(void) { VGA_OutReg8(SEQ_ADDR,0x0B,0x00);//   if ((VGA_InReg8(SEQ_ADDR,0x0D)&0x0E)!=0x0C) return(true); if ((System_In8(0x3CC)&0x67)!=0x67) return(true); return(false); } //---------------------------------------------------------------------------------------------------- // 5A6 //---------------------------------------------------------------------------------------------------- void TRIDENT_Unit_5A6(void) { unsigned char al,bh; VGA_InReg8(SEQ_ADDR,0x0B);//   VGA_OutReg8(SEQ_ADDR,0x0E,(VGA_InReg8(SEQ_ADDR,0x0E)|0x80)^2); bh=(VGA_InReg8(SEQ_ADDR,0x0C)&0xFE)|0x80; if (VGA_InReg8(SEQ_ADDR,0x0B)==0x53)//   { VGA_InReg8(CRTC_ADDR,0x29); VGA_OutReg8(CRTC_ADDR,0x29,0x44); VGA_OutReg8(CRTC_ADDR,0x2B,0x03); VGA_OutReg8(CRTC_ADDR,0x2C,0x3D); VGA_OutReg8(CRTC_ADDR,0x25,0x27); } if (!(!VGA_InReg8(CRTC_ADDR,0x28)&1)) { bh&=0xCE; bh|=0x80; VGA_OutReg8(MISC_ADDR,0x01,0x00);//  0x3D2 (  0x01) al=(VGA_InReg8(CRTC_ADDR,0x28))&0x0C; if (al==0) { al|=0x04; VGA_OutReg8(CRTC_ADDR,0x28,al); } VGA_OutReg8(SEQ_ADDR,0x0F,VGA_InReg8(SEQ_ADDR,0x0F)&0x7F); VGA_InReg8(SEQ_ADDR,0x0C); VGA_OutReg8(SEQ_ADDR,0x0C,bh); VGA_OutReg8(SEQ_ADDR,0x0E,(VGA_InReg8(SEQ_ADDR,0x0E)&0x7F)^2); if (VGA_InReg8(SEQ_ADDR,0x0F)&0x08) { VGA_InReg8(SEQ_ADDR,0x0B);//   VGA_OutReg8(SEQ_ADDR,0x0E,(VGA_InReg8(SEQ_ADDR,0x0E)|0x80)^2); al=(VGA_InReg8(SEQ_ADDR,0x0C)&0xFE)|0x80; al&=0xFE; VGA_OutReg8(SEQ_ADDR,0x0C,al); VGA_OutReg8(GRACON_ADDR,0x0F,0x00); al=VGA_InReg8(SEQ_ADDR,0x0C);//  VGA_OutReg8(SEQ_ADDR,0x0F,VGA_InReg8(SEQ_ADDR,0x0F)|0x80); VGA_OutReg8(SEQ_ADDR,0x0E,(VGA_InReg8(SEQ_ADDR,0x0E)&0x7F)^0x02); } } VGA_OutReg8(SEQ_ADDR,0x0B,0x00);//  VGA_OutReg8(SEQ_ADDR,0x0D,0x20); VGA_OutReg8(SEQ_ADDR,0x0E,0xA0); VGA_InReg8(SEQ_ADDR,0x0B);//   VGA_OutReg8(SEQ_ADDR,0x0E,0x02); al=VGA_InReg8(GRACON_ADDR,0x06);//atvizsglni if (al==0) { al&=0xF3; al|=0x04; VGA_OutReg8(GRACON_ADDR,0x06,al); } VGA_OutReg8(SEQ_ADDR,0x0D,0x00); VGA_InReg8(CRTC_ADDR,0x1E); VGA_OutReg8(CRTC_ADDR,0x1E,0x00); if (VGA_InReg8(SEQ_ADDR,0x0B)==0x53) VGA_OutReg8(CRTC_ADDR,0x20,0x1D);//   else VGA_OutReg8(CRTC_ADDR,0x20,0x1C); VGA_OutReg8(CRTC_ADDR,0x29,0x44); } //---------------------------------------------------------------------------------------------------- // 4D9 //---------------------------------------------------------------------------------------------------- bool TRIDENT_Unit_4D9(void) { unsigned char al; al=TRIDENT_Unit_292()&0x0E; if (al!=0x0C) return(true); al=System_In8(0x3CC)&0x67; if (al!=0x67) return(true); return(false); } //---------------------------------------------------------------------------------------------------- // 51A //---------------------------------------------------------------------------------------------------- void TRIDENT_Unit_51A(void) { unsigned char al,bh; bh=(TRIDENT_Unit_26A()|0x80)&0xFE; VGA_OutReg8(SEQ_ADDR,0x07,0x24); System_Out8(MISC_ADDR,0x01); if (!((al=VGA_InReg8(CRTC_ADDR,0x28))&0x0C)) { al|=0x04; VGA_OutReg8(CRTC_ADDR,0x28,al); } VGA_OutReg8(SEQ_ADDR,0x0F,VGA_InReg8(SEQ_ADDR,0x0F)&0x7F); VGA_OutReg8(SEQ_ADDR,0x0C,bh); VGA_OutReg8(SEQ_ADDR,0x0E,(VGA_InReg8(SEQ_ADDR,0x0E)&0x7F)^2); if (VGA_InReg8(SEQ_ADDR,0x0F)&0x08) TRIDENT_Unit_179(); TRIDENT_Unit_2EA();//  VGA_OutReg8(SEQ_ADDR,0x0D,0x20); VGA_OutReg8(SEQ_ADDR,0x0E,0xA0); VGA_InReg8(SEQ_ADDR,0x0B);//  VGA_OutReg8(SEQ_ADDR,0x0E,0x02); if (!((al=VGA_InReg8(GRACON_ADDR,0x06))&0x0C)) VGA_OutReg8(GRACON_ADDR,0x06,(al&0xF3)|0x04); VGA_OutReg8(SEQ_ADDR,0x0D,0x00); al=VGA_InReg8(CRTC_ADDR,0x1E); VGA_OutReg8(CRTC_ADDR,0x1E,0x00); } //---------------------------------------------------------------------------------------------------- // 26A //---------------------------------------------------------------------------------------------------- unsigned char TRIDENT_Unit_26A(void) { VGA_InReg8(SEQ_ADDR,0x0B);//   VGA_OutReg8(SEQ_ADDR,0x0E,(VGA_InReg8(SEQ_ADDR,0x0E)|0x80)^2); return(VGA_InReg8(SEQ_ADDR,0x0C)); } //---------------------------------------------------------------------------------------------------- // 179 //---------------------------------------------------------------------------------------------------- void TRIDENT_Unit_179(void) { // SP  BP VGA_OutReg8(SEQ_ADDR,0x0C,(TRIDENT_Unit_26A()|0x42)&0xFE); VGA_OutReg8(SEQ_ADDR,0x0F,VGA_InReg8(SEQ_ADDR,0x0F)|0x80); VGA_OutReg8(SEQ_ADDR,0x0E,(VGA_InReg8(SEQ_ADDR,0x0E)&0x7F)^2); } //---------------------------------------------------------------------------------------------------- // 2EA //---------------------------------------------------------------------------------------------------- void TRIDENT_Unit_2EA(void) { VGA_OutReg8(SEQ_ADDR,0x0B,0x00);//   } //---------------------------------------------------------------------------------------------------- // 292 //---------------------------------------------------------------------------------------------------- unsigned char TRIDENT_Unit_292(void) { TRIDENT_Unit_2EA();//   return(VGA_InReg8(SEQ_ADDR,0x0D));// ,  SEQ_ADDR 0x0D } 


Saya juga meluncurkan kartu video OAK OTI077 (sampai saya secara tidak sengaja menerapkan 12 V ke dalamnya dan kartu itu hangus):

Inisialisasi Kartu Grafis OAK OTI077
 //**************************************************************************************************** //     oak //**************************************************************************************************** //**************************************************************************************************** // //**************************************************************************************************** //**************************************************************************************************** //  //**************************************************************************************************** unsigned char OAK_InitData[77] PROGMEM= { 0x01,0x29,0x04,0x10,0x07,0x00,0x01,0x3E, 0x00,0x00,0x80,0x70,0xFF,0x01,0xFF,0xFF, 0x7F,0x00,0xFF,0xC8,0x00,0x00,0xFF,0x00, 0x01,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x01,0x00,0x08,0x00,0x00,0x00,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00, 0x00,0x00,0x00,0x00,0x10 }; //**************************************************************************************************** //  //**************************************************************************************************** CHIP_TYPE OAK_Init(void);//   Trident unsigned char OAK_TestInx2(unsigned short rg,unsigned char ix,unsigned char msk);// true,   MSK  PT   RG  1 void OAK_OTI077_Init(void);// OAK077 void OAK_OTI087_Init(void);// OAK087 void OAK_Unit218C(void);// 218C void OAK_Unit201B(void);// 201B void OAK_Unit50F(void);// 50F void OAK_Unit58F(unsigned char ah,unsigned char al);// 58F void OAK_Unit552(void);// 552 unsigned char OAK_Unit53D(void);// 53D void OAK_Unit21A8(void);// 21A8 void OAK_Fill3DE(void);// Fill3DE bool OAK_Unit21C9(void);// 21C9 void OAK_Unit2167(unsigned short addr,unsigned char v);// 2167 void OAK_Unit2148(unsigned char v);// 2148 void OAK_Unit2A0F(void);// 2A0F void OAK_Unit28E2(unsigned char al,unsigned char ah);// 28E2 void OAK_Unit28AC(unsigned char al,unsigned char ah);// 28AC void OAK_Unit29E0(void);// 29E0 unsigned char OAK_Unit1CED(void);// 1CED void OAK_Unit1E12(void);// 1E12 void OAK_Unit292D(unsigned char al,unsigned char bl,unsigned char bh);// 292D //**************************************************************************************************** //  //**************************************************************************************************** //---------------------------------------------------------------------------------------------------- //   Trident //---------------------------------------------------------------------------------------------------- CHIP_TYPE OAK_Init(void) { CHIP_TYPE chiptype=UNKNOWN; VGA_Reset(); System_Out8(0x46E8,0x17); System_Out8(0x0102,System_In8(0x0102)|1); System_Out8(0x46E8,0x0F); if (OAK_TestInx2(0x3DE,0x0D,0x38)) { if (OAK_TestInx2(0x3DE,0x23,0x1F)) { if((VGA_InReg8(0x3DE,0x00)&0x02)==0) { chiptype=OAK_087; OAK_OTI087_Init(); } else chiptype=OAK_083; } else { switch(System_In8(0x3DE)/32) { case 0: chiptype=OAK_037C; break; case 2: chiptype=OAK_067; break; case 5: chiptype=OAK_077; OAK_OTI077_Init(); break; case 7: chiptype=OAK_057; break; } } } return(chiptype); } //---------------------------------------------------------------------------------------------------- // true,   MSK  PT   RG  1 //---------------------------------------------------------------------------------------------------- unsigned char OAK_TestInx2(unsigned short rg,unsigned char ix,unsigned char msk) { unsigned char old,nw1,nw2; old=VGA_InReg8(rg,ix); VGA_OutReg8(rg,ix,old&(~msk)); nw1=VGA_InReg8(rg,ix)&msk; VGA_OutReg8(rg,ix,old|msk); nw2=VGA_InReg8(rg,ix)&msk; VGA_OutReg8(rg,ix,old<<8); return((nw1==0)&(nw2==msk)); } //---------------------------------------------------------------------------------------------------- // OAK087 //---------------------------------------------------------------------------------------------------- void OAK_OTI087_Init(void) { System_Out8(0x320,1); System_In8(0x320); OAK_Unit218C(); VGA_OutReg8(0x3DE,0x13,VGA_InReg8(0x3DE,0x13)&0xBF); VGA_OutReg8(0x3DE,0x0B,((VGA_InReg8(0x3DE,0x0B)&0x0F)|(VGA_InReg8(0x3DE,0x10)))&0xF0); OAK_Unit201B(); OAK_Unit50F(); OAK_Unit552(); System_Out8(0x320,2); OAK_Fill3DE(); OAK_Unit21A8(); OAK_Unit218C(); System_Out8(0x320,0x0c); System_Out8(0x46E8,0x17); System_Out8(0x0102,System_In8(0x0102)|1); System_Out8(0x46E8,0x0F); OAK_Fill3DE(); } //---------------------------------------------------------------------------------------------------- // OAK077 //---------------------------------------------------------------------------------------------------- void OAK_OTI077_Init(void) { OAK_Unit2A0F(); VGA_OutReg8(0x3DE,0x0E,VGA_InReg8(0x3DE,0x0E)&0xDE); OAK_Unit1E12(); System_Out8(0x46E8,0x17); System_Out8(0x0102,System_In8(0x0102)|1); System_Out8(0x46E8,0x0F); } //---------------------------------------------------------------------------------------------------- // 218C //---------------------------------------------------------------------------------------------------- void OAK_Unit218C(void) { OAK_Unit2148(0x0F); if (OAK_Unit21C9()==false) return; OAK_Unit2167(0x0094,0x01); if (OAK_Unit21C9()==false) return; OAK_Unit2167(0x0394,0x01); return; } //---------------------------------------------------------------------------------------------------- // 201B //---------------------------------------------------------------------------------------------------- void OAK_Unit201B(void) { unsigned char ah; System_In8(0x3C8); ah=System_In8(0x3C6); System_In8(0x3C8); System_In8(0x3C6); System_In8(0x3C6); System_In8(0x3C6); System_In8(0x3C6); System_Out8(0x3C6,0); System_In8(0x3C8); System_Out8(0x3C6,ah); System_In8(0x3C8); } //---------------------------------------------------------------------------------------------------- // 50F //---------------------------------------------------------------------------------------------------- void OAK_Unit50F(void) { if ((VGA_InReg8(0x3DE,0x07)&0x04)) return; OAK_Unit58F(0xFF,0x05); } //---------------------------------------------------------------------------------------------------- // 58F //---------------------------------------------------------------------------------------------------- void OAK_Unit58F(unsigned char ah,unsigned char al) { System_Out8(0x1E,al); System_Out8(0x1F,ah); } //---------------------------------------------------------------------------------------------------- // 552 //---------------------------------------------------------------------------------------------------- void OAK_Unit552(void) { if (OAK_Unit53D()) return; OAK_Unit58F(0x07,0x04); OAK_Unit58F(0xFF,0x05); OAK_Unit58F((VGA_InReg8(0x1E,0xFE)|0x40),0xFE); } //---------------------------------------------------------------------------------------------------- // 53D //---------------------------------------------------------------------------------------------------- unsigned char OAK_Unit53D(void) { if (VGA_InReg8(0x3DE,0x07)&0x04) return(1); return(VGA_InReg8(0x3DE,0x08)&0x03); } //---------------------------------------------------------------------------------------------------- // 21A8 //---------------------------------------------------------------------------------------------------- void OAK_Unit21A8(void) { if (VGA_InReg8(0x3DE,0x07)&0x04) OAK_Unit2148(0x00); else { OAK_Unit2167(0x0094,0x00); OAK_Unit2167(0x0394,0x00); } } //---------------------------------------------------------------------------------------------------- // Fill3DE //---------------------------------------------------------------------------------------------------- void OAK_Fill3DE(void) { unsigned char i; for(i=0;i<77;i++) { unsigned short byte=pgm_read_byte(&(OAK_InitData[i])); VGA_OutReg8(0x3DE,i,byte); } } //---------------------------------------------------------------------------------------------------- // 21C9 //---------------------------------------------------------------------------------------------------- bool OAK_Unit21C9(void) { unsigned char al=0x55,ah=al; while(1) { System_Out8(0x3DE,al); if (al==ah) return(true); al^=0xFF; ah^=0xFF; if (al==0x55 && ah==0x55) return(false); } } //---------------------------------------------------------------------------------------------------- // 2167 //---------------------------------------------------------------------------------------------------- void OAK_Unit2167(unsigned short addr,unsigned char v) { unsigned char ah; ah=System_In8(addr); System_Out8(addr,0x80); System_Out8(0x102,0x01); System_Out8(addr,ah); System_Out8(0x3C3,v); } //---------------------------------------------------------------------------------------------------- // 2148 //---------------------------------------------------------------------------------------------------- void OAK_Unit2148(unsigned char v) { System_Out8(0x46E8,0x17); System_Out8(0x0102,System_In8(0x0102)|1); System_Out8(0x46E8,v); } //---------------------------------------------------------------------------------------------------- // 2A0F //---------------------------------------------------------------------------------------------------- void OAK_Unit2A0F(void) { OAK_Unit28E2(0,8); OAK_Unit28AC(0,0xBE); OAK_Unit29E0(); OAK_Unit292D(0,0x11,0x06); OAK_Unit292D(1,0x11,0x07); OAK_Unit292D(2,0x06,0x1F); OAK_Unit292D(3,0x06,0x15); } //---------------------------------------------------------------------------------------------------- // 28E2 //---------------------------------------------------------------------------------------------------- void OAK_Unit28E2(unsigned char al,unsigned char ah) { unsigned char bl=al,bh=ah; VGA_OutReg8(0x3DE,0x0D,VGA_InReg8(0x3DE,0x0D)|0x20); System_Out8(0x3C7,0x0E); al=System_In8(0x3C9)&bh; ah^=0xFF; bl&=ah; bl|=al; System_Out8(0x3C8,0x0E); System_Out8(0x3C9,bl); VGA_OutReg8(0x3DE,0x0D,VGA_InReg8(0x3DE,0x0D)&0xDF); } //---------------------------------------------------------------------------------------------------- // 28AC //---------------------------------------------------------------------------------------------------- void OAK_Unit28AC(unsigned char al,unsigned char ah) { unsigned char bl=al; VGA_OutReg8(0x3DE,0x0D,VGA_InReg8(0x3DE,0x0D)|0x20); al=System_In8(0x3C6)&ah; ah^=0xFF; bl&=ah; al|=bl; System_Out8(0x3C6,al); VGA_OutReg8(0x3DE,0x0D,VGA_InReg8(0x3DE,0x0D)&0xDF); } //---------------------------------------------------------------------------------------------------- // 29E0 //---------------------------------------------------------------------------------------------------- void OAK_Unit29E0(void) { if ((System_In8(0x3DE)&0xE0)==0xA0) { if (!(OAK_Unit1CED()&0x20)) OAK_Unit292D(0x0A,0x02,0x0C); else OAK_Unit292D(0x0A,0x03,0x0D); } else OAK_Unit292D(0x0A,0x03,0x0D); } //---------------------------------------------------------------------------------------------------- // 1CED //---------------------------------------------------------------------------------------------------- unsigned char OAK_Unit1CED(void) { return((VGA_InReg8(0x3DE,0x10)&0x4F)|(VGA_InReg8(0x3DE,0x0B)&0xB0)); } //---------------------------------------------------------------------------------------------------- // 1E12 //---------------------------------------------------------------------------------------------------- void OAK_Unit1E12(void) { System_Out8(0x46E8,0x17); System_Out8(0x0102,System_In8(0x0102)|1); System_Out8(0x46E8,0x00); } //---------------------------------------------------------------------------------------------------- // 292D //---------------------------------------------------------------------------------------------------- void OAK_Unit292D(unsigned char al,unsigned char bl,unsigned char bh) { VGA_OutReg8(0x3DE,0x0D,VGA_InReg8(0x3DE,0x0D)|0x20); System_Out8(0x3C8,al); System_Out8(0x3C9,bh); System_Out8(0x3C9,bl); VGA_OutReg8(0x3DE,0x0D,VGA_InReg8(0x3DE,0x0D)&0xDF); } 


Omong-omong, apakah ada spesialis register adaptor VGA di sini? Saya melihat hal-hal aneh dalam kode perubahan mode video saat menginisialisasi kartu video:

 //   #define ATTRCON_ADDR 0x03C0 System_In8(0x03DA); System_Out8(ATTRCON_ADDR,0x20); 

Di sini, secara umum, tidak ada yang istimewa. Menulis ke register pengontrol atribut dilakukan dalam 2 langkah: pertama kita menulis nomor register, dan kemudian data. Untuk selalu memulai dengan merekam nomor, baca ISR1 (dari 0x03DA) - begitulah adanya.

Tapi ini yang aneh. Pengontrol atribut tidak memiliki register 0x20! Ia memiliki register terakhir 0x14. Dan bahkan jika akan ada register seperti itu, mengapa tidak ada catatan nilai? Seharusnya ada dua entri di port. Dan di sini dia sendirian. Saya mencari di internet dan menemukan bahwa untuk beberapa alasan (dalam buku saya tidak menemukan ini), Anda dapat menulis, katakanlah, di 0x10 daftarkan nilai 0x20 sekaligus hanya dengan menggabungkan bit: System_Out8 (ATTRCON_ADDR, 0x10 | 0x20); Lalu catatan yang ditentukan menulis 0x20 ke register 0x00? Tetapi mengapa ini bekerja? Dan begitukah? Ini menarik bagi saya, itu sebabnya - semuanya adalah kadang-kadang warna jatuh setelah inisialisasi. Palet tidak diatur. Dapat dilihat bahwa itu sedang berubah, tetapi warnanya sama sekali tidak seperti seharusnya. Jika inisialisasi dilakukan lagi, maka semuanya dikembalikan. Pada tahap apa ini terjadi tidak jelas. Secara eksperimental, saya menemukan bahwa dengan probabilitas tinggi, ini hanya pemasangan mode video. Tetapi apa yang sebenarnya tidak ada di sana, saya tidak mengerti.

Tautan ke arsip dengan papan sirkuit cetak
Tautan ke arsip dengan firmware

Source: https://habr.com/ru/post/id406193/


All Articles