#include #include #include #include #define FIFOHALF 1024 //The FIFO is 2048 samples long, half is 1024 words unsigned short Buf[FIFOHALF]; unsigned long IRQCount; unsigned int BASE=0x300; unsigned int IRQPIN=5; //INSW - input string of words void insw(unsigned short Port, void far *Buf, int Count) { _ES = FP_SEG(Buf); /* Segment of Buf */ _DI = FP_OFF(Buf); /* Offset of Buf */ _CX = Count; /* Number to read */ _DX = Port; /* Port */ asm REP INSW; } char far *VM = (char far *)MK_FP(0xB800, 0); const char HexDigit[16] = "0123456789ABCDEF"; char *WordToPChar(unsigned short Data) { static char Lit[5]; Lit[4] = 0; Lit[3] = HexDigit[Data & 0xF]; Lit[2] = HexDigit[(Data >> 4) & 0xF]; Lit[1] = HexDigit[(Data >> 8) & 0xF]; Lit[0] = HexDigit[(Data >> 12) & 0xF]; return Lit; } void PrintWord(int XR, int Y, unsigned short Data) { char far *Tar = VM + (Y * 80 + XR) * 2; *Tar = HexDigit[Data & 0xF]; Data >>= 4; Tar -= 2; *Tar = HexDigit[Data & 0xF]; Data >>= 4; Tar -= 2; *Tar = HexDigit[Data & 0xF]; Data >>= 4; Tar -= 2; *Tar = HexDigit[Data & 0xF]; } void PrintNybble(int X, int Y, unsigned char Data) { char far *Tar = VM + (Y * 80 + X) * 2; *Tar = HexDigit[Data & 0xF]; } void PrintChar(int X, int Y, char Data) { char far *Tar = VM + (Y * 80 + X) * 2; *Tar = Data; } unsigned AskFor(char *prompt, unsigned int OldOne) { char msg[8]; unsigned int NewOne = 0, Success = 0, Dummy; int AddrInputPosX, AddrInputPosY; printf("\n\nPlease enter the %s for your card (in hex)",prompt); printf("or press ENTER for %X.\n>", OldOne); AddrInputPosX = wherex(); AddrInputPosY = wherey(); do { gotoxy(AddrInputPosX, AddrInputPosY); clreol(); msg[0] = 3; msg[1] = 0; cgets(msg); sscanf(msg + 2, "%x", &NewOne); if ( (NewOne >= 0x2) && (NewOne <= 0xF) ) { Success = 1; Dummy = NewOne; } else if (msg[1] == 0) { gotoxy(AddrInputPosX, AddrInputPosY); printf("%X", OldOne); Success = 1; Dummy = OldOne; } } while(!Success); return (Dummy); } /* end of AskForIRQ */ //8254 functions void CtrMode(unsigned char Ctr, unsigned char Mode) { unsigned char Ctrl = (Ctr << 6) | 0x30 | (Mode << 1); outportb(BASE+0x14+3, Ctrl); } void CtrLoad(unsigned char Ctr, unsigned short Data) { outportb(BASE+0x14+Ctr, Data & 0xFF); outportb(BASE+0x14+Ctr, Data >> 8); } //Baseless 8254 functions void CtrMode(unsigned short Base, unsigned char Ctr, unsigned char Mode) { unsigned char Ctrl = (Ctr << 6) | 0x30 | (Mode << 1); outportb(Base+3, Ctrl); } void CtrLoad(unsigned short Base, unsigned char Ctr, unsigned short Data) { outportb(Base+Ctr, Data & 0xFF); outportb(Base+Ctr, Data >> 8); } //IRQ array and functions //In C++, ISRs take (...) arguments #ifdef __cplusplus #define __CPPARGS ... #else #define __CPPARGS #endif void interrupt far (*oldisr[16])(__CPPARGS); //global to store old handler pointer void SendEOI(void) { outportb(0xA0, 0x20); outportb(0x20, 0x20); } unsigned char initirq(char IRQnumber,void interrupt (*ISR)(__CPPARGS)) { unsigned char intmask, oldmask; if (IRQnumber <=7) { oldmask = inportb(0x21); oldisr[IRQnumber] = getvect(IRQnumber + 8); setvect(IRQnumber + 8,ISR); intmask = oldmask & (~(1 << IRQnumber)); outportb(0x21,intmask); } else { oldmask = inportb(0xA1); oldisr[IRQnumber] = getvect(IRQnumber + 0x70 - 8); setvect(IRQnumber - 8 + 0x70, ISR); intmask = oldmask & (~(1 << (IRQnumber - 8))); outportb(0xA1, intmask); } return(oldmask); } void restoreirq(char IRQnumber) { unsigned char intmask; if (IRQnumber <=7 ){ intmask = inportb(0x21); intmask |= (1 << IRQnumber); setvect(IRQnumber + 8,oldisr[IRQnumber]); outportb(0x21, intmask); } else { intmask = inportb(0xA1); intmask |= (1 << (IRQnumber - 8)); setvect(IRQnumber - 8 + 0x70, oldisr[IRQnumber]); outportb(0xA1, intmask); } } //board config variables and utility functions unsigned char ADRange, dacArange, dacBrange; //sbitd takes data and bit, then returns 0x81 or 0x01 based on data[bit] unsigned char sbitd(unsigned int data,unsigned char bit) { return (data & (1<>3) & 0x01;//d4,d3 are 5V for daca,b dacArange = (jumpers>>4) & 0x01; CAL(); } void StopAndReset(void) //Checked vs Manual { inportb(BASE+0x1D);//perform master RESET outportb(BASE+0x1E, 0x00); outportb(BASE+0x1A, 0x00); outportb(BASE+0x1C,0x00); outportb(BASE+0x03, 0x00); } void StartTimedConversions(void) //Checked vs Manual { //Start process outportb(BASE+0x01, 0x00); //Clear FIFO outportb(BASE+0x0C, 0x10); //Enable FIFO half full IRQs CtrMode(0, 2); CtrLoad(0, 0x0005); //Ctr 0 is an unknown, but we think it needs to be set like this //Ctr 1 & 2 total divisor of 80 (with our 10MHz clock) gives 125kHz scan rate. // 125kHz is the maximum scan rate for two channel operation on this card CtrMode(1, 2); CtrMode(2, 2); CtrLoad(1, 0x0002); CtrLoad(2, 0x0028); //0x02 x 0x28 == 80 decimal outportb(BASE+0x1A, 0x10); //Enable Operation outportb(BASE+0x1E, 0x40); //Enable triggered conversions } void interrupt far newisr(__CPPARGS) { insw(BASE + 0x0, Buf, FIFOHALF); //Read half a fifo from the card on each IRQ ++IRQCount; PrintChar(13, 6, IRQCount); outportb(BASE+0x0C, 0x10); //Clear/enable FIFO half full IRQs SendEOI(); } void PrintHeader(void) { clrscr(); cputs("Speed Sample\r\n"); cprintf("Card at Base Address %04X and IRQ %02X (hex).\n\r",BASE,IRQPIN); cputs("This sample acquires from A/D channels 0 and 1 at 125kHz per channel.\r\n"); cputs("Data is displayed in the idle time between acquisition.\r\n\r\n"); cprintf("A/D: %s %s\r\n\r\n", (ADRange&0x02)? ((ADRange&0x04)?"ñ5V":"ñ10V") : ((ADRange&0x04)?"0-10V":"0-10V(Low Res)") //0-10V(Low Res) is , //in theory 0-20V, (ADRange&0x01)?"16ch":"8ch" //but the amps cap //at 10V ); gotoxy(11, 9); cputs("Ch 0 Ch 1"); gotoxy(11, 10); cputs(".... ...."); gotoxy(1, 12); cputs("Press any key to exit.\r\n"); } void main(void) { unsigned long OIRQCount = 0; IRQCount = 0; directvideo = 1; clrscr(); BASE = AskFor("Base Address",BASE); IRQPIN = AskFor("IRQ Number",IRQPIN); StopAndReset(); Init(); PrintHeader(); outport(BASE + 0x04, 0x0000);//set all gains to code zero, which is "times 1" of the jumper configured range. outportb(BASE + 0x02, 0x10);//set start channel to zero, set end channel to one. StartTimedConversions(); initirq(IRQPIN, newisr); /* This sample demonstrates how to acquire fast data in the background using IRQs on FIFO HALF. It does NOT properly demonstrate how to use or display that data. Specifically, multiple IRQs can occur between display passes. kbhit() is very slow, for example. This sample takes all the data off the card, but only displays as it can. Also, we're only displaying the first reading in the FIFO for each channel. The rest of the data is thrown away. */ while(-1) { if ( IRQCount != OIRQCount ) { OIRQCount = IRQCount; PrintWord(13, 9, Buf[0]); PrintWord(23, 9, Buf[1]); } if ( kbhit() ) { getch(); break; } } StopAndReset(); restoreirq(IRQPIN); }