Archive for the ‘Write’ tag
(Disappointing) Thoughts on CyberResearch "H" Series DIO Cards OR Reading and Writing with the HDIO ISO32LU
The last few days I've been working with CyberResearch's HDIO ISO32LU Low Profile PCI Digital I/O Board. My mission? Easy. Read and Write a few bits of DIO. How hard can it be right? I thought that because I was familiar with CyberResearch's PCIDAQ1210, getting up and going with the HDIO would be easy. I thought 30 minutes, max. It's DIO. How hard can it be? Hard enough it seems.
Bad Programming Examples
The HDIO software provides you with a multitudinous number of programming examples. Great, right? Surely there’s a simple console programming example for reading and/or writing a single BIT to the card with the DIO card because I’m quite certain that 90% of people/companies using the card are ONLY going using it for simple reads and writes. OK, let’s see. Well, first we have to translate the cryptic programming example folder naming scheme.
DI_INT
DI_PATTN
DI_SOFT
DI_SOFT-DWORD
Are they only given DOS machines to work with over at CyberResearch? Come on guys, XP gives you 255 characters in which to name filenames and folders. Let’s be a little more specific shall we? With new technologies, the learning curves are already high enough. Give us a break.
I finally figured out that DI is short for “DIO”. INT is short for “interrupt”. Pattn short for pattern. Soft is short for…? Software? It’s a mystery. Opening a few of these examples yields bloated ugly laberinthian MFC GUI code with a tiny bit of actual API calls to the DIO demonstating advanced card functionality that most people probably will never use. Listen guys, I don’t care to look at your ugly GUI code ESPECIALLY if it hides the actual real functionaity of the code. Give Me a Text Based Example. You aren’t teaching us how to use MFC. You are teaching us how to use the DIO card.
To add insult to injury, after running these examples, I had no idea what a single one of them were actually trying to do.
So I turned to “Driver.chm” document provided by the installed software (c:/ProgramFiles/CyberResearch/ADSAPI/Manual) which contains a list of all API commands. In the document, I found that the command for reading a single BIT was “DRV_DioReadBit.” I did a serach for this phrase in all the examples and yielded zero results. There were no programming examples which showed me how to read a simple BIT from DIO.
(ASIDE: Microsoft Help files (.chm) are gastly. I don’t care if they are industry standard. They are hard to navigate, difficult to search, and impossible to print out the entire thing. Give me an Online API or a PDF please).
The irony is that CyberResearch actually provides a test program where you can simply toggle or read a single bit and view the results. But for some reason, they don’t feel like it’s important enough to give you the code for that application. Just another example of a company not being in touch with their customer.
Not the same API Commands (not even close)
Another thing that perturbs me about the H-Series DIO API calls, is that the call to Read a Single BIT is nothing like PCIDAQ 1210’s API calls. Well, actually, they are exactly alike. But you wouldn’t know it just by looking at the API.
The API call to Read a Bit on the HDIO ISO32LU:
FTYPE DRV_DioReadBit(LONG DriverHandle, LPT_DioReadBit lpDioReadBit);
The API call to Read a Bit on the PCIDAQ 1210:
I16 DI_ReadLine(U16 CardNumber, U16 Port, U16 Line, U16 * state);
To perform the exact same functionality, these two cards have two completely different function names. These two functions also take different data types and have a few different variable names for the exact same information. Let me show you how the two translate:
‘DriverHandle’ on the IDO32LU = ‘CardNumber’ on the DAQ
LPT_DioReadBit lpDioReadBit is a structure with the following elements: Port, Bit and State.
Port = Port
Line = Bit (confusing)
State = State
How easy would it be to use a universal naming structure between API’s for different cards CyberResearch?
Reading and Writing with the HDIO IDO32LU
Open a Device
OK, enough of me ranting and raving about CyberResarch rediculousness. I know why you are here. You want to know how to simply Read and Write a single Bit. The first thing you need to do if open the Device you intend to use. A call to DRV_DeviceOpen returns a DriverHandle which will be used in the API calls to Read and Write a single BIT.
LRESULT ErrCde; char szErrMsg[80]; static ULONG dwDeviceNum; static LONG DriverHandle = (LONG)NULL; ErrCde = DRV_DeviceOpen(dwDeviceNum, (LONG far *)&DriverHandle); if (ErrCde != SUCCESS) { DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg); cout << ErrCde << endl; return 0; }
Writing a Bit
To write a single BIT to the DIO card, declare a new instance of the structure PT_DioWriteBi and define the port, bit, and state in that structure. Then, just pass the address of the structure to the API call DRV_DioWriteBit along with the DriverHandle. If case you are wondering about which port to use, Port 0 refers to IDO0 through IDO7 on the IDO32LU. Port 1 refers to IDO8 through 15. You can see the pin-outs on page 25 of the manual provided to you by CyberResearch.
PT_DioWriteBit lpDIOWriteBit; lpDIOWriteBit.port = 0; lpDIOWriteBit.bit = 0; lpDIOWriteBit.state = 1; ErrCde = DRV_DioWriteBit(DriverHandle, (LPT_DioWriteBit)&lpDIOWriteBit ); if (ErrCde != SUCCESS) { DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg); cout << ErrCde << endl; return 0; }
Reading a Bit
Reading is a little ticker. In order to Read a BIT, you again provide a Driver Handle, but this time provide an address to a declared PT_DioReadBit structure. The real tricky part? Remembering to allocate memory of size USHORT that will hold the state information once it has been populated by the call to DRV_DIOReadBit. Below, rbvalue is declared of type USHORT, then this memory is pointed to by the state variable in the declared 'PT_DioReadBit' structure. If you forget to allocate that memory, prepare for your program to crash. If case you are wondering about which port to use, Port 0 refers to IDI0 through IDI7 on the IDO32LU. Port 1 refers to IDI8 through IDI15.
PT_DioReadBit lpDIOReadBit; USHORT rbValue; lpDIOReadBit.port = 0; lpDIOReadBit.bit = 5; lpDIOReadBit.state = (USHORT far *)&rbValue; ErrCde = DRV_DioReadBit( DriverHandle, (LPT_DioReadBit)&lpDIOReadBit ); if (ErrCde != SUCCESS) { DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg); cout << ErrCde << endl; return 0; } USHORT state = *lpDIOReadBit.state;
In my opinion, having to allocate your memory for the state variable is unnecessary complexity that could have been side-stepped by CyberResearch in the programming of the API for the IDO32LU. Especially with the newest generation of programmers being so unfamilar with C, I find they could have been a wee bit more user friendly.
In Conclusion
I wrote this entry to save you a little bit of time. It took me three hours to figure out how to read and write a bit to the DIO card. Maybe I'm just dumb. Or maybe, it was a little bit harder then it should of been. I normally don't take the time to write scathing reviews of products, but I firmly believe that DIO is fundamental and should be one of the easiest tasks to complete. I should be able to call a function called WriteBit(int Port, int Bit, int State) and it should write the BIT. I should be able to call a function ReadBit(int Port, int Bit, int * state) and it should return the state. It should be this easy. These two functions would be printed on the front cover of my manual of the DIO card I'm trying to sell. If not in the manual, they should be in simple text based console programming examples entitled 'Reading a Bit From the DIO' and 'Write a single BIT to the DIO.' If not in an example, they should be in an online API or pdf. Am I asking for too much? I don't think so. Get with the program CyberResearch.

