NelsonUWP Posted July 7, 2010 Report Share Posted July 7, 2010 I'm looking at coding an application which needs to run with two different ARINC hardware types (CEI-715 & CEI-620 if you're playing along at home) with two different drivers, but the same functionality. I'm stuck at the best way to accomplish this and I have to imagine that this isn't as uncommon as one would think. Thanks Quote Link to comment
Wire Warrior Posted July 7, 2010 Report Share Posted July 7, 2010 At a quick glance I would approach this by developing a hardware abstraction layer for the two cards that presented identical data and command structures to the rest of the program. If you do that then you can develop a single set of code for your application. Check out the tutorial http://zone.ni.com/devzone/cda/tut/p/id/3271on Developing LabVIEW Plug and Play Instrument Drivers for more info. Jason 1 Quote Link to comment
Daklu Posted July 7, 2010 Report Share Posted July 7, 2010 I'm looking at coding an application which needs to run with two different ARINC hardware types (CEI-715 & CEI-620 if you're playing along at home) with two different drivers, but the same functionality. I'm stuck at the best way to accomplish this and I have to imagine that this isn't as uncommon as one would think. Jason is right. The best solution is to implement a hardware abstraction layer. His link is broken for me, but here's another example and lengthy explanation you can study to figure out how to do it. If the 715 and 620 have very similar behavior, you can accomplish what you want by (for instance) creating a CEI-715 class driver. Then derive a CEI-620 class from it and override only those operations that are different. I have done this in the past when there is very little difference between instrument models and needed a fast solution. (Warning - This is NOT a solution that lends itself to further evolution or extension. It is a short term patch to a problem that should be addressed using a HAL.) Quote Link to comment
MikaelH Posted July 8, 2010 Report Share Posted July 8, 2010 I would do it in the other order, The 715 should derive from 620, since I would guess that 715 have the same functions as 620 plus some additional functions, i.e. extending the 620 type. Or maybe create an abstract base class “ARINC” and then derive CEI-620 and CEI-715 from this class, if the won't share so much code. //Mikael Quote Link to comment
jcarmody Posted July 8, 2010 Report Share Posted July 8, 2010 I have a similar situation in that I'm working on abstracting CAN hardware because my company has NI, Kvaser and ValueCAN all over the place. I've begun a BaseCAN parent class, a ValueCAN class (which will have ValueCAN-2 and ValueCAN-3 children) and a Kvaser class. My ultimate goal is to dynamically dispatch whichever child classes are required based on the hardware (as indicated by an entry in a configuration file). I've got it working for simple read/write functions. I've printed out the document from Daklu's link about HALs. Is this along the lines of what you're discussing? Quote Link to comment
Daklu Posted July 13, 2010 Report Share Posted July 13, 2010 I have a similar situation in that I'm working on abstracting CAN hardware because my company has NI, Kvaser and ValueCAN all over the place. I've begun a BaseCAN parent class, a ValueCAN class (which will have ValueCAN-2 and ValueCAN-3 children) and a Kvaser class. My ultimate goal is to dynamically dispatch whichever child classes are required based on the hardware (as indicated by an entry in a configuration file). I've got it working for simple read/write functions. I've printed out the document from Daklu's link about HALs. Is this along the lines of what you're discussing? I thought I had replied to this message. I know I typed something up--wonder what happened to it? Maybe I never submitted it... Depending on how you're planning on using your CAN classes in your applications, what you're describing is part of your reuse library, not the HAL. They belong to the Instrument Driver layer on Figure 1 of that document. The HAL is written specifically for each application. It isn't intended to be used across different projects; it's intended to make it easier for you to use different modules from your Instrument Driver layer within a single application. (Or maybe that's just my own narrow view of a HAL.) Here's a class diagram of a project I'm currently working on that illustrates how I implemented a HAL. The yellow layer on the bottom contains the reusable device driver libraries and classes. The purple layer contains the business logic and is completely independent of any specific device drivers. I can work on that code without having the device drivers even installed on the computer. (This was handy since the device drivers hadn't been written.) The blue layer in between them is the HAL. It is responsible for translating high level application requests into low level device specific commands. This diagram doesn't show it very well, so I'll explain the calling hierarchy for one set of application functionality--the Data Collector. (Note: Following Elijah's terminology the DataCollector(Sniffer) class is part of the device specific software plugin (DSSP) layer and the DataCollectorInt class is in the application separation layer (ASL.) I couldn't diagram that very well in my UML tool while keeping my classes in their correct libraries, so I use slightly different terminology. It's essentially the same thing though.) DataCollectorInt is a class that is part of the application execution layer in purple. It has only a few high level abstract methods related to collecting data: Connect, Disconnect, IsConnected, StartCapture, StopCapture, etc. Any method inputs are either native LV types or other objects within this layer. i.e. The Connect method takes a ConnectionInfo object as an input parameter. StopCapture returns a Result object and a Trace object. DataCollector(Sniffer) is a child of DataCollectorInt and implements the abstract methods of its parent. This class is an instrument specific implementation for our Crossfire and Sniffer instruments. If I change the instruments used to collect data I'll derive a new class from DataCollectorInt and implement new device specific code for each of the higher level DataCollectorInt methods. Note that this class uses composition, not inheritance, for its lower level functionality. CrossfireDSL is the device specific layer for one of our instruments. It turns out this class is only a wrapper for the Crossfire class in the device driver layer. I'm not sure there's any immediate advantage to having this class in the design. There could be a long term benefit if we ever replace our current Crossfire instrument with a new version that requires a different Crossfire device driver. I'll be able to derive a new class from CrossfireDSL that uses the new Crossfire device driver and easily plug it in. SnifferDSL is another class in the device specific layer. In this case it made a lot more sense than it did for the Crossfiire. The Sniffer library in the device driver layer contains 7 classes. (The library and classes are a simple wrapper for a third party .Net api.) I was very unfamiliar with the Sniffer api, so I used SnifferDSL to learn the api while at the same time abstracting away all the details (and 7 classes) of the Sniffer api and giving me a few higher level Sniffer control methods. Both CrossfireDSL and SnifferDSL also use composition and delegation instead of inheritance to get the functionality of the classes from the device driver layer. In fact, the only inheritance relationship is between DataCollectorInt and DataCollector(Sniffer). I did this specifically because I wanted to invert the dependency between the application execution layer and the HAL. (In fact, inverting dependencies is one of the few reasons for creating abstract classes in Labview.) If the dependencies don't matter you could skip DataCollectorInt altogether and link directly to DataCollector(Sniffer). That is simpler and more in line with what Elijah's paper describes. ---------------------------- I don't know anything about CAN or the devices you're describing, but I'd be very cautious if you're planning on making BaseCAN part of your reuse library. I tried that and abandoned it. IMO instruments change too much for this kind of hierarchy to work well over the long term. Each instruments' idiosychrocies and slightly different command sets can make it impossible to maintain a coherent generic interface while providing the low level functionality you might need for your next application. These days my reusable instrument drivers are very thin wrappers that exposes each of the instrument's commands. Higher level abstractions are application specific code built on an as-needed basis. 1 Quote Link to comment
Yair Posted July 14, 2010 Report Share Posted July 14, 2010 I thought I had replied to this message. I know I typed something up--wonder what happened to it? Maybe I never submitted it... Next time have your speakers on. Your computer was probably saying "I'm sorry Dave. I'm afraid I can't do that". 1 Quote Link to comment
Daklu Posted July 14, 2010 Report Share Posted July 14, 2010 Next time have your speakers on. Your computer was probably saying "I'm sorry Dave. I'm afraid I can't do that". Funny you should mention that. Back in Windows 98 days I replaced the Windows warning dong with that sound clip. It was pretty funny to see people's reactions when my computer talked to me. After a while when I got bored I would repeatedly do illegal clicks in rapid succession. It was my own personal remix sample. "I I I I I I I I'm sorry Dave. I'm sorry Dave. I'm sorry Dave. I'm afraid I can't do that." Quote Link to comment
Dan DeFriese Posted July 14, 2010 Report Share Posted July 14, 2010 I'm looking at coding an application which needs to run with two different ARINC hardware types (CEI-715 & CEI-620 if you're playing along at home) with two different drivers, but the same functionality. I'm stuck at the best way to accomplish this and I have to imagine that this isn't as uncommon as one would think. Thanks 715...Yuck. Fortunately, GE Fanuc (Condor) did most of the work for you with the Interface.dll... their instrument driver handles the abstraction already (assuming you paid the $300 bucks and aren't building the VI-DLL calls from scratch). Unfortunately, the CEI-715 (PCMCIA) doesn't support many of the "Intelligent" features that the CEI-620 (cPCI) does (e.g. hardware sceduled transfers). If you have the option I recommend the RAR-EC (Express Card) version of the test card instead of the CEI-715 for your laptop. The RAR-EC would be "nearly" transparent as it supports almost all the calls that the CEI-620 does. Obviously, you still need to do some hardware abstraction, for channels assignments and such, but using the RAR-EC will have you a lot of time. HTH ~Dan Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.