/***************************************************************************** * SAMPLE3.C : DMA DATA ACQUISITION * * * * This is a demonstration program to be used with the ACCES AD12-16 A/D * * board. The program will display sixteen channels using DMA transfers. * * When all transfers are complete the DMA chip generates an interrupt to * * inform the driver that it is done. The timer starts the conversion and at* * the end of conversion the board genertes a DMA request. * * This program must be built using the large model. f * * * * The board should be set as follows: * * -- Polarity set to bipolar -- S2 TO BIP * * -- 16 channel singled ended mode -- S3 TO 16CH * * -- On board clock set to 1 MHz -- CLOCK jumper to 1MHZ * * -- DMA channel 1 -- S1 TO 1. * * * * LAST MODIFICATION: 2/3/98 * * * *****************************************************************************/ #include #include #include #include #include #include "aa16drvc.h" #ifndef FALSE #define FALSE 0 #define TRUE !FALSE #endif /* These variable MUST be declared as global. They are the ones whose offsets are passed to the driver routine. If they are not global then the driver will not find their segment. */ unsigned pntbuf[100],statcode,task; int datbuf[100],params[7]; unsigned AskForBaseAddress(unsigned int OldOne) { char msg[7]; int NewOne = 0, Success = 0, Dummy; int AddrInputPosX, AddrInputPosY; puts("\nPlease enter the Base Address for your card (in hex)"); printf("or press ENTER for %X.\n>", OldOne); AddrInputPosX = wherex(); AddrInputPosY = wherey(); do { gotoxy(AddrInputPosX, AddrInputPosY); clreol(); msg[0] = 5; msg[1] = 0; cgets(msg); sscanf(msg + 2, "%x", &NewOne); Success = 1; Dummy = NewOne; if (msg[1] == 0) { gotoxy(AddrInputPosX, AddrInputPosY); printf("%X", OldOne); Success = 1; Dummy = OldOne; } } while(!Success); return (Dummy); } /* end of AskForBaseAddress */ /***************************************************************************** * FUNCTION: call_driver -- local routine * * * * PURPOSE: Performs the call to the driver package. * * * * INPUT: None. * * * * CALLS: aa16drv - entry point to driver package. * * * * OUTPUT: Returns the error code supplied by the driver routine. * * * *****************************************************************************/ unsigned call_driver() { aa16drv(FP_OFF(&task),FP_OFF(params),FP_OFF(&statcode)); /* call the driver */ /* this section checks for an error code */ if (statcode > 0) { printf("A status error code of %i was detected.\n",statcode); printf("Program terminated."); return(statcode); } else return(0); } /* end call_driver */ /***************************************************************************** * FUNCTION: setup -- local routine * * * * PURPOSE: Initializes the driver and sets up the counter timers. * * * * INPUT: None. * * * * CALLS: call_driver - entry point to driver package. * * * * OUTPUT: Returns the error code supplied by the driver routine. * * * *****************************************************************************/ unsigned setup(Address) { unsigned I,status; /* initialize the board */ task = 0; params[0] = Address; /* assign base address to params[0] */ params[1] = 5; /* 5 volt range */ status = call_driver(); if (status > 0) return(status); /* set up the timers to divide the 1 MHz clock by 1000 to get 100Hz */ task = 14; params[0] = 1; /* set up counter 1 */ params[1] = 3; /* counter 1 set to mode 3 */ params[2] = 100; /* divide by 100 */ status = call_driver(); if (status > 0) return(status); /* set up the timers to divide the 1 MHz clock by 1000 to get 100Hz */ task = 14; params[0] = 2; /* set up counter 2 */ params[1] = 3; /* counter 2 set to mode 3 */ params[2] = 10; /* divide by 10 */ status = call_driver(); if (status > 0) return(status); /* Set the sample and hold settle time, this is only required for very fast computers such as 386's. */ task = 11; params[0] = 5; /* subtask 5 of task 11 */ params[1] = 50; /* settle count */ status = call_driver(); if (status > 0) return(status); /* set the scan limits for channel 0 to channel 15 */ task = 1; params[0] = 0; /* lower scan limit */ params[1] = 15; /* upper scan limit */ status = call_driver(); if (status > 0) return(status); /* set the AIM-16P to channel 0 */ task = 12; params[0] = 0; /* lower scan limit */ status = call_driver(); return(status); } /* end setup */ /***************************************************************************** * FUNCTION: get_readings -- local routine * * * * PURPOSE: Reads the 16 A/D channels and displays them on the screen. * * * * INPUT: None. * * * * CALLS: call_driver - entry point to driver package. * * * * OUTPUT: Returns the error code supplied by the driver routine. * *****************************************************************************/ unsigned get_readings() { unsigned I,status; /* set up to do timer driven DMA. The timer will start conversions at a 100Hz rate. The destination segment could be any unused area of memory. Make sure it is unused! When compete, the DMA chip will] interrupt and the driver will close the process.*/ task = 17; params[0] = 16; /* take 16 samples */ params[1] = 0x7000; /* destination, hope it's unused! */ params[2] = 1; /* use the timer for triggering */ params[3] = 0; /* do one cycle only */ params[4] = 1; /* Use DMA channel 1 */ params[5] = 5; /* Use IRQ 5 */ status = call_driver(); if (status > 0) return(status); /* this loop waits for the driver to signal that it has completed all conversions. If this were an application, other task could be performed within this loop while waiting for the conversion to be completed. */ task = 9; params[0] = 2; /* sub task 2, check int status */ do { /* other code could be executed here while waiting */ status = call_driver(); } while (params[1] > 0); /* we now can convert the values taken by task 5 into channel and counts and store in seperate arrays. This needs to be done because the board returns a conversion with the count in the upper 12 bits of a 16 bit integer and the channel number in the lower 4 bits. */ task = 18; params[0] = 16; params[1] = 0x7000; /* task 17 destination segment */ params[2] = 0; /* start with first value */ params[3] = FP_OFF(datbuf); /* offset of array for count data */ params[4] = FP_OFF(pntbuf); /* offset of array for channel data */ status = call_driver(); /* now if OK list the data to the screen */ clrscr(); printf("\n CHANNEL VALUE\n"); printf(" ------- ------\n"); for (I = 0;I < 16;I++) { printf(" %5i %5i\n",pntbuf[I],datbuf[I]); } return(0); } /* end get_readings */ /***************************************************************************** * FUNCTION: main -- local routine * * * * PURPOSE: Controls program flow, detects when user is ready to exit. * * * * INPUT: None. * * * * CALLS: setup - set up program and drivers. * * get_readings - read the A/D channels and display. * * * * OUTPUT: None. * *****************************************************************************/ void main() { unsigned int Address; unsigned status; char ch; clrscr(); printf( " SAMPLE3.C : DMA DATA ACQUISITION \n" " \n" " This is a demonstration program to be used with the ACCES AD12-16 A/D \n" " board. The program will display sixteen channels using DMA transfers. \n" " When all transfers are complete the DMA chip generates an interrupt to \n" " inform the driver that it is done. The timer starts the conversion and at\n" " the end of conversion the board genertes a DMA request. \n" "\n"); Address=AskForBaseAddress(0x350); clrscr(); printf("\n Board Configuration:\n\n" " -- The Base Address is %x hex\n",Address); printf(" - Jumper IRQ5 must be installed (required) \n" " -- Both TMP jumpers must be installed (required) \n" " -- The offset must be in STD position (required) \n" " -- One jumper is on OV0; none on OT (required) \n" " -- Polarity set to bipolar -- S2 TO BIP (required) \n" " -- 16 channel singled ended mode -- S3 TO 16CH (required) \n" " -- On board clock set to 1 MHz -- CLOCK jumper to 1MHZ (required) \n" " -- DMA channel 1 -- S1 TO 1. (required) \n" " -- All other jumper settings are irrelevant\n"); printf("\nPress any key to continue, or press 'E' to exit"); ch=getch(); clrscr(); status = setup(Address); /* set up program and the driver */ if (status != 0) return; /* is status > 0 then board error */ while (ch != 'E' && ch != 'e') { /* display current values for the 16 channels */ status = get_readings(); if (status != 0) return; /* if status > 0 then error */ /* check for program exit */ printf("\n\nPress 'E' to exit the program. Press any other key to rescan the data..."); while (!kbhit); /* wait for key press */ ch = getch(); /* read the char */ } clrscr(); } /* end main program */