#include #include #include #include #include "irq0-15.h" unsigned IRQCounter=0; unsigned BASE=0x300; unsigned IRQ=5; //DIVISOR0 is the load value for counter 0 to get 1second gate pulses //derivation of this number: Input to C0 is 873.9 hertz. We want 1s: #define DIVISOR0 (874*2) //RPM is the desired error speed for the fan's tachometer #define RPM 2500 //DIVISOR12 is the divisor for counters 1 and 2, derived from the RPM /* derivation is as follows: If the desired RPM is X, the actual number of pulses is twice that, or X*2. We will work in Hz, not P/M, so divide this by 60. This yields X*2/60. Next, the actual oncard signal is divided by 8, so we get X*2/60/80. We want the counters to time out just before the gate signal occurs. We have set the gate signal for 1 seconds, so we multiply by 1. Also, want to ensure some failure threshold, so we set it lower. This gives us the equation shown below. */ #define DIVISOR12 (RPM*2/60/8*(DIVISOR0/874) - 2) //IRQBits contains the bit mask for IRQ selection #define IRQBits ((IRQ-4)<<1) int khit() {int x; x=kbhit(); if (x) getch(); return x; } void CtrMode2(unsigned addr, char cntr, char mode) { int ctrl; ctrl = (cntr << 6) | 0x10 | (mode << 1); //read lsb only outportb(addr+3,ctrl); } void CtrLoad2(unsigned addr ,int c,int val) { outportb(addr+c,val & 0xFF); } void CtrMode(unsigned addr, char cntr, char mode) { int ctrl; ctrl = (cntr << 6) | 0x30 | (mode << 1); outportb(addr+3,ctrl); } void CtrLoad(unsigned addr ,int c,int val) { outportb(addr+c,val & 0x00FF); outportb(addr+c,(val>>8) & 0x00FF); } void interrupt far (*oldisr)(...); //global to store old handler pointer void sendEOI() { outportb(0x20, 0x20); } unsigned char initirq(char IRQnumber,void interrupt (*ISR)(...)) { unsigned char intmask, oldmask; oldmask = inportb(0x21); oldisr = getvect(IRQnumber + 8); setvect(IRQnumber + 8,ISR); intmask = oldmask & (~(1 << IRQnumber)); outportb(0x21,intmask); return(oldmask); } void restoreirq(char IRQnumber) { unsigned char intmask; intmask = inportb(0x21); intmask |= (1 << IRQnumber); setvect(IRQnumber + 8,oldisr); outportb(0x21, intmask); } void interrupt ISR(...) { sendEOI(); IRQCounter++; //add code to clear IRQ from card } unsigned char RL() // Read the limit register at B+4 {return inportb(BASE+4);} unsigned char RE() // Read the Error Register at B+5 {return inportb(BASE+5)&0xE0;} unsigned char RS() // Read the status register at B+6 {return inportb(BASE+6);} void WC(unsigned char data) // Write the control register at B+6 {outportb(BASE+6,data|IRQBits);} void InitCard() { CtrMode(BASE,0,2); //Set counter 0 in mode 2 CtrLoad(BASE,0,DIVISOR0); CtrMode2(BASE,1,1); //set counter 1 as LSB and mode 1 CtrMode2(BASE,2,1); //set counter 2 a s LSB and mode 1 CtrLoad2(BASE,1,DIVISOR12); //load lsb divisor into counter 1 CtrLoad2(BASE,2,DIVISOR12); //load lsb divisor into counter 2 WC(IRQBits); //set card to IRQ5 } void init(void) { clrscr(); printf("%s Dated:%s %s\n",__FILE__,__DATE__,__TIME__); puts("This program is a demonstration and test tool for the ENVIR-PSM01 card."); puts("All GUI functions are isolated from card functions to facilitate"); puts("Embedded development. This program is written in Borland C++ 3.5"); puts("\nConfigure Card for BASE 300 (A8 and A9 removed, rest shorted)"); } void main(void) { int x,done=0,key=0; init(); initirq(IRQ,ISR); x=IRQBits; //step 1 puts("Step 1. No configuration has occurred"); if (IRQCounter!=0) puts("ERROR! IRQ Occurred at initial power on!"); if (x=RL()) printf("ERROR! Limit Register contains non-zero at power on! =%02x\n",x); if (x=RE()) printf("ERROR! Error Register contains non-zero at power on! =%02x\n",x); if (x=RS()) printf("ERROR! Status Register contains non-zero at power on! =%02x\n",x); IRQCounter=0; //step 2 puts("Step 2. Hardware will be configured - press a key"); getch(); InitCard(); if ((x=RL())!=DIVISOR12) printf("ERROR! Limit Register not equal to divisor! %02x!=%02x\n",x,DIVISOR12); else puts( "OKAY! Limit Register holds divisor!"); if (IRQCounter!=0) puts("ERROR! IRQ Occurred during Initialization!"); else puts("OKAY! NO spurious IRQ!"); IRQCounter=0; //step3 puts("Step 3. Testing the functionality of the SWRESET bit - press a key"); getch(); WC(0xC0); // Set RESET Bit in Control Register if (IRQCounter!=0) puts("ERROR! IRQ Occurred at SWRESET!"); else puts("OKAY! No spurious IRQ st SWRESET!"); if (x=RL()) printf("ERROR! Limit Register contains non-zero at SWRESET! =%02x\n",x); else puts( "OKAY! Limit Register clear at SWRESET!"); if (x=RE()) printf("ERROR! Error Register contains non-zero at SWRESET! =%02x\n",x); else puts( "OKAY! Error Register clear at SWRESET!"); if (x=RS()) printf("ERROR! Status Register contains non-zero at SWRESET! =%02x\n",x); else puts( "OKAY! Status Register clear at SWRESET!"); IRQCounter=0; getch(); clrscr(); //step 4 InitCard(); puts("Step 4. Error detection circuits"); puts("Cause an error, and the program will tell you which."); puts("Press 0 to clear, 1,2,3 for FAN1 FAN2 PS force"); puts("Press B to reset Buzzer"); puts("Press X key to continue with test"); do{ gotoxy(1,7); printf("Control: %02x Errstatus:%02x IRQCount:%5i",RS(),RE(),IRQCounter);clreol(); gotoxy(1,8);clreol(); switch(RE()){ case 0x20:cputs(" PS ");break; case 0x40:cputs(" FAN2");break; case 0x60:cputs(" FAN2 PS");break; case 0x80:cputs("FAN1");break; case 0xA0:cputs("FAN1 PS");break; case 0xC0:cputs("FAN1 FAN2");break; case 0xE0:cputs("FAN1 FAN2 PS"); }//end switch if (kbhit()) key=toupper(getch());else key=0; switch(key){ case '0' : WC(0x00);break; case '1' : WC(0x20);break; case '2' : WC(0x10);break; case '3' : WC(0x08);break; case 0x1b://ESC key case 'X' : done=1;break; case 'B' : WC(0x40);break; }//end if kbhit(); }while (!done); puts("Finished with status check\n\n"); restoreirq(IRQ); }