Anciennes cartes vidéo ISA et AVR

Il y a environ dix ans, j'ai obtenu les cartes vidéo ISA de 286 ... 486 machines destinées au dumping. Les cartes vidéo ont été testées et ont depuis accumulé de la poussière dans un tiroir. Il y a quelques années, j'ai pensé, mais dois-je connecter une telle carte vidéo à un microcontrôleur? C'est ce dont je vais parler dans l'article.

Pour connecter une ancienne carte vidéo ISA, un bus de données 8 bits et un bus d'adresse 20 bits suffisent. Microcontrôleurs J'adore la famille AVR pour sa simplicité, j'ai donc pris Atmega16. Mais vous pouvez prendre n'importe quelle pratique pour vous - dans ce cas, les mêmes pieds stm32 suffiront certainement sans cerclage externe. Mais l'Atmega16 n'a pas assez de pieds pour tous ces bus, donc le bus d'adresse a été assemblé dans trois autres registres parallèles soviétiques (j'en ai une grande quantité) K588IR1. Le microcontrôleur définit à son tour les parties d'adresse dans ces trois registres. Plus n'est pas nécessaire.


Sur le connecteur ISA, les sorties de ce circuit doivent être connectées comme suit:

+5,
+12,
GND
REFRESH (tiré à + 5V via une résistance),
A0-A19,
D0-D7,
RÉINITIALISER
Memw,
Memr,
IOW
IOR
Ale
RDY,
AEN (se connecte à GND).


Dans l'image en rouge, j'ai marqué les broches du connecteur ISA qui doivent être connectées.

Pour certaines cartes vidéo, vous devez connecter -5 V et -12 V (vous devez les obtenir quelque part - par exemple, à partir de sources TracoPower) et le signal OSC (14,318 MHz) - il peut être généré par le générateur le plus simple du K155LN1. Les autres cartes graphiques n'ont pas besoin de ces lignes. Ici, c'est la chance. En général, si le pied correspondant de l'ISA se bloque en l'air sur la carte vidéo, vous ne pouvez certainement pas le connecter. Gardez à l'esprit que la consommation de la carte vidéo sur la ligne + 5V est assez importante - si vous utilisez quelque chose comme LM7805 pour l'alimentation, assurez-vous de la mettre sur un radiateur (de préférence avec un ventilateur).

Personnellement, ma conception assemblée ressemble à ceci:

image

Il ne reste plus qu'à initialiser la carte vidéo et à commencer à travailler avec elle. Il existe des projets similaires sur Internet - j'en ai trouvé un ( lien ), où j'ai obtenu le code d'initialisation de la carte vidéo Trident 9000i. Dans le même programme à partir d'Internet, il existe un code d'initialisation pour Trident9000C, mais les commentaires indiquent qu'il ne fonctionne pas. J'ai vérifié. Cela ne fonctionne vraiment pas - à l'écran, les ordures et la carte vidéo ne répondent pas à l'écriture de données dans la RAM.

Vidéo du travail (l'image a été transmise via SPI à Atmega16 (comme vous pouvez le voir, ces lignes sont laissées libres dans le diagramme) via le port LPT de l'ordinateur):


(J'ai fait une réservation dans la vidéo - mode 320x200, pas 320x240)

En combinant ce module avec une souris optique ( article sur l'utilisation du capteur de souris ), j'ai obtenu ceci:



Si vous souhaitez exécuter une carte graphique ISA existante, vous devez pour cela trouver le BIOS de la carte graphique requise (disons ici ) sur Internet et la démonter à l'aide d'IDA. Il existe un code X86 standard. Il ne démarre tout simplement pas à l'adresse 0 - il y a une signature (2 octets) et une somme de contrôle (1 octet). Total, vous devez commencer par le 3ème octet. Et découvrez toujours dans quels ports ce que vous devez enregistrer pour que la carte fonctionne. Franchement, je n'ai pas eu la patience de comprendre ce qui n'allait pas avec le Trident9000C.

Pour travailler avec le bus ISA, un module a été écrit:

Module pour travailler avec le 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); } 


L'initialisation de la carte graphique Trident 9000i est la suivante:

Initialisation des graphiques du Trident 9000i
 //**************************************************************************************************** //     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 } 


J'ai également lancé la carte vidéo OAK OTI077 (jusqu'à ce que je lui applique accidentellement du 12 V et qu'elle brûle):

Initialisation de la carte graphique 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); } 


Au fait, y a-t-il des spécialistes des registres d'adaptateurs VGA ici? Je vois des choses étranges dans le code de changement de mode vidéo lors de l'initialisation de la carte vidéo:

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

Ici, en général, il n'y a rien de spécial. L'écriture dans les registres du contrôleur d'attributs se fait en 2 étapes: nous écrivons d'abord le numéro de registre, puis les données. Pour toujours commencer par enregistrer le numéro, lisez ISR1 (à partir de 0x03DA) - c'est comme ça.

Mais voici l'étrange chose. Le contrôleur d'attribut n'a pas de registre 0x20! Il a le dernier registre 0x14. Et même s'il y avait un tel registre, pourquoi n'y a-t-il pas d'enregistrement de valeur? Il doit y avoir deux entrées dans le port. Et la voici seule. J'ai cherché sur Internet et j'ai découvert que pour une raison quelconque (je ne l'ai pas trouvée dans les livres), vous pouvez écrire, disons, dans le registre 0x10 la valeur 0x20 à la fois en combinant simplement les bits: System_Out8 (ATTRCON_ADDR, 0x10 | 0x20); L'enregistrement spécifié écrit alors 0x20 dans le registre 0x00? Mais pourquoi ça marche? Et en est-il ainsi? C'est intéressant pour moi, c'est pourquoi - le tout est que parfois la couleur tombe après l'initialisation. La palette n'est tout simplement pas définie. On voit que ça change, mais les couleurs ne sont pas du tout ce qu'elles devraient être. Si l'initialisation est refaite, tout est restauré. À quel stade cela se produit n'est pas clair. Expérimentalement, j'ai découvert qu'avec une forte probabilité, ce n'est que l'installation du mode vidéo. Mais ce qui n’est pas exactement là, je ne comprends pas.

Lien vers l'archive avec le circuit imprimé
Lien vers l'archive avec firmware

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


All Articles