/* * User Mode Test Program for testing MOTENC PCI Motion Card * * Compile with 'gcc -Wall -O2 vsitest.c -lpci -o vsitest' (-O *is* mandatory) */ #include #include #include #include #include #include #include #include #include // for read() static struct termios initial_settings, new_settings; static int peek_character = -1; #define VENDOR 0x10b5 #define DEVICE 0x3001 void init_keyboard(void); void close_keyboard(void); int kbhit(void); int readch(void); void ShowHelp() { printf( "\n\nVSI MOTENC BOARD TEST\n" ); printf( "All Indexes are zero based\n\n" ); printf( "0..7: Encoder 0..7\n" ); printf( "C: Clear encoder counters and reset outputs\n" ); printf( "D: Write to DAC\n" ); printf( "L: Read Encoder at Index pulse\n" ); printf( "O: Write Outputs Reg (Loc 4 & 12)\n" ); printf( "I: Read Input/Output Reg\n" ); printf( "?: Help\n" ); printf( "Q: Quit\n" ); } int main (int argc, char *argv[]) { struct pci_access *pacc; /* Struct to access the PCI devices. */ struct pci_dev *dev = NULL; /* Struct for the PCI device See /usr/include/pci/pci.h for the gory details */ u32 bar[3]; /* PCI Region addresses */ u32 *mem = NULL; /* Pointer to the mmapped memory */ int fd; /* File descriptor for /dev/mem access */ u32 base, ofs; int gQuit = 0; /* Check IO permissions to be able to open /dev/mem */ if (iopl (3)) { printf ("Cannot get I/O permissions (being root helps)\n"); return -1; } pacc = pci_alloc ();/* initialise the pci_access struct */ pci_init (pacc); /* initialise the pci lib */ pci_scan_bus(pacc); /* Build a list of devices on the PCI bus */ dev = pacc->devices; while (dev != NULL) { //printf ("found %x %x\n", dev->vendor_id, dev->device_id); if ((dev->vendor_id != VENDOR) || (dev->device_id != DEVICE)) dev = dev->next; else break; } if (dev == NULL) { printf ("\nVendor %X Device %X\n", dev->vendor_id, dev->device_id); printf ("PCI Motenc Card Not Found\n"); return -1; } //printf ("\nVendor %X Device %X\n", dev->vendor_id, dev->device_id); //printf ("Class %X Revision %X\n", pci_read_word (dev, 0x0a), pci_read_word (dev, 0x08)); /* Here we assume that BAR0 (offset 0x10) is of memory type... */ /* ...and that BAR1 (offset 0x14) is IO type */ bar[0] = dev->base_addr[0] & PCI_BASE_ADDRESS_MEM_MASK; bar[1] = dev->base_addr[1] & PCI_BASE_ADDRESS_IO_MASK; /* BAR2 is the one we're interested in... */ bar[2] = dev->base_addr[2] & PCI_BASE_ADDRESS_MEM_MASK; /* for (n = 0; n < 3; n++) { printf ("BAR[%x] %x %x %lx\n", n, dev->vendor_id, dev->device_id, (long int) bar[n]); } if (bar[2] & 0x0FFF) { printf ("Address not page aligned - mapping into user space will fail.\n"); return -1; } */ fd = open ("/dev/mem", O_RDWR); if (fd == 0) { printf ("open(/dev/mem) failed\n"); return -1; } base = bar[2] & 0xfffff000; ofs = bar[2] & 0xfff; #define PCI_MEM_LEN 512 /* This must be <= than the actual amount of PCI memory */ /* ...and map the PCI memory area (man 2 mmap for more info) */ mem = mmap (0, PCI_MEM_LEN + ofs, PROT_READ|PROT_WRITE, MAP_SHARED, fd, base); if (mem == (void *) -1) { perror ("mmap() failed"); } else { mem = mem + (ofs/4); init_keyboard(); //printf ("Memory pointer: %p\n", mem); ShowHelp(); while(!gQuit) { u32 * pDev; long dat; int option; float dVolt; unsigned long mask; unsigned int xmask; long nCount; long index_dat; if( !kbhit() ) continue; option = readch(); fflush(stdin); fflush(stdout); switch( option ) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': // Read Encoders dat = *(mem + (((option - '0')/4) * 8) + ((option - '0') % 4)); printf ("Encoder %c : %ld\n", option, dat); break; case 'i': case 'I': // Read I/O xmask = *(mem + 4); printf ("I/O @ Loc 4: %X\n", xmask); break; case 'l': case 'L': // Read Encoder at Index pulse printf( "\nEncoder Number (0 Based): " ); scanf( "%ld", &dat ); printf( "%ld\nScanning Index Line......\n\n", dat); pDev = mem + 5 + ((dat/4) * 8) + (dat % 4); mask = 0x100000 << (dat%4); while(!kbhit() ) { index_dat = (*pDev) & mask; if( index_dat ) { nCount = *(mem + (((dat)/4) * 8) + ((dat) % 4)); printf ("Encoder %ld @Index: %ld\n", dat, nCount); break; } } break; case 'Q': case 'q': //Quit gQuit = 1; break; case '?': ShowHelp(); break; case 'o': case 'O': //Write To Output Reg printf( "\nRegister Loc (4 or 12): " ); scanf( "%ld", &dat ); printf( "%ld\n", dat); printf( "\nRegister Data (0...FFFF): " ); scanf( "%x", &xmask ); printf( "%x Hex\n", xmask); if( dat != 4 && dat != 12 ) { printf( "Loc/Data out of range\n" ); break; } pDev = mem + dat; *pDev = (u32)xmask; break; case 'D': case 'd': //Write To DAC printf( "\nDAC Number (0 Based): " ); scanf( "%ld", &dat ); printf( "%ld\n", dat); printf( "Voltage (-10.00 ... 10.00): " ); scanf( "%g", &dVolt ); printf( "%g\n", dVolt); if( dat < 0 || dat > 7 || dVolt < -10.0 || dVolt > 10.0 ) { printf( "Data out of range\n" ); break; } pDev = mem + 24 + dat; // convert -10.0 -> 10.0 to 0x1FFF -> 0x0000 dat = (int) ((10.0 - dVolt) / 20.0 * 0x1FFF); *pDev = (u32)dat; break; case 'c': case 'C': printf( "Are you sure? (y/n): " ); fflush(stdout); dat = readch(); printf( "%c\n", (char)dat ); if( dat == 'y' || dat == 'Y' ) { pDev = mem + 5; *pDev = 0xF; //clear counter 0..3 pDev = mem + 5 + 8; *pDev = 0xF; //clear counter 4..7 pDev = mem + 24; for( dat = 0; dat < 8; dat++ ) *(pDev+dat) = 0x1000; printf( "Done\n" ); } break; default: printf("press ? for list of commands\n"); break; } } close_keyboard(); munmap (mem-(ofs/4), PCI_MEM_LEN+ofs); } close (fd); pci_cleanup (pacc); return 0; } void init_keyboard() { tcgetattr(0,&initial_settings); new_settings = initial_settings; new_settings.c_lflag &= ~ICANON; new_settings.c_lflag &= ~ECHO; new_settings.c_lflag &= ~ISIG; new_settings.c_cc[VMIN] = 1; new_settings.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &new_settings); } void close_keyboard() { tcsetattr(0, TCSANOW, &initial_settings); } int kbhit() { unsigned char ch; int nread; if (peek_character != -1) return 1; new_settings.c_cc[VMIN]=0; tcsetattr(0, TCSANOW, &new_settings); nread = read(0,&ch,1); new_settings.c_cc[VMIN]=1; tcsetattr(0, TCSANOW, &new_settings); if(nread == 1) { peek_character = ch; return 1; } return 0; } int readch() { char ch; if(peek_character != -1) { ch = peek_character; peek_character = -1; return ch; } read(0,&ch,1); return ch; }