Creating your own Protocol Decoder: Difference between revisions

From LabNation Wiki
Jump to navigation Jump to search
(Created page with "''Work in progress'' The decoder framework has been created from the ground up with extensibility in mind. In case you want to use your own decoder in the SmartScope app, sim...")
 
No edit summary
Line 15: Line 15:
= Start from an existing decoder file=
= Start from an existing decoder file=
Open up the DefaultDecoders project, and add a reference to the LabNationInterfaceDefinitions.dll file downloaded in the previous step. To to so, underneath your project name (DefaultDecoders in this example), right-click on References and select Add reference. Select Browse from the menu on the left, and browse to the LabNationInterfaceDefinitions.dll file. You should see LabNationInterfaceDefinitions listed as reference to your project.
Open up the DefaultDecoders project, and add a reference to the LabNationInterfaceDefinitions.dll file downloaded in the previous step. To to so, underneath your project name (DefaultDecoders in this example), right-click on References and select Add reference. Select Browse from the menu on the left, and browse to the LabNationInterfaceDefinitions.dll file. You should see LabNationInterfaceDefinitions listed as reference to your project.
<br>[[File:custDec_reference.png]]  
<br>[[File:custDec_reference.png]]  
<br>Next, click on the “DigitalDecoderI2C.cs” file in the Solution Explorer at the top-right of your screen. Hit Ctrl+C and Ctrl+V to duplicate that file. Select the resulting “DigitalDecoderI2C - Copy.cs” file, right-click -> Rename to give the file a meaningful name.
<br>Next, click on the “DigitalDecoderI2C.cs” file in the Solution Explorer at the top-right of your screen. Hit Ctrl+C and Ctrl+V to duplicate that file. Select the resulting “DigitalDecoderI2C - Copy.cs” file, right-click -> Rename to give the file a meaningful name.
<br>[[File:custDec_solution.png]]  
<br>[[File:custDec_solution.png]]  
<br>Inside the file, change the class name DigitalDecoderI2C to a name suiting your filename (note: this has to be done twice, on line 12 and line 14).
<br>Inside the file, change the class name DigitalDecoderI2C to a name suiting your filename (note: this has to be done twice, on line 12 and line 14).
<br>[[File:custDec_className.png]]   
<br>[[File:custDec_className.png]]   
= Define the metadata =
= Define the metadata =
Time to focus on the code. Just underneath the class name, you’ll notice a couple of properties which define everything of your decoder the SmartScope app needs to know, except the decoding itself. Change all of them to suite your new decoder’s needs:
Time to focus on the code. Just underneath the class name, you’ll notice a couple of properties which define everything of your decoder the SmartScope app needs to know, except the decoding itself. Change all of them to suite your new decoder’s needs:
Line 33: Line 39:




Note: if you specify bool, the SmartScope app will pick up all logic channels and analog channels (the app will convert them to binary values for you). If you specify float, the SmartScope app will pick up analog channels only. In case you want to build a decoder which consumes the output of another decoder, you can also specify DecoderOutput as input type.
'''NOTE:''' if you specify bool, the SmartScope app will pick up all logic channels and analog channels (the app will convert them to binary values for you). If you specify float, the SmartScope app will pick up analog channels only. In case you want to build a decoder which consumes the output of another decoder, you can also specify DecoderOutput as input type.


Now you’ll notice the inputWaveforms is a Dictionary, providing a typeless Array for each input you require. Before you can use the actual values inside the Arrays, you’ll want to cast them to Arrays containing the type your defined earlier. In case of our previous example, this is how this would be done:
Now you’ll notice the inputWaveforms is a Dictionary, providing a typeless Array for each input you require. Before you can use the actual values inside the Arrays, you’ll want to cast them to Arrays containing the type your defined earlier. In case of our previous example, this is how this would be done:
Line 53: Line 59:


Now when you restart the SmartScope app, it should automagically pick up your new decoder and list it as available decoder!
Now when you restart the SmartScope app, it should automagically pick up your new decoder and list it as available decoder!
<br>[[File:custDec_finished.png]]   
<br>[[File:custDec_finished.png]]   
= Debugging your decoder in real-time =
= Debugging your decoder in real-time =
Even though your project passes compilation successfully, there are many reasons why your decoder might not produce the desired result, or even cause the SmartScope throw an error message. The best way to figure out why, is to put a breakpoint in your code so you can step through your code while live data is being fed in.
Even though your project passes compilation successfully, there are many reasons why your decoder might not produce the desired result, or even cause the SmartScope throw an error message. The best way to figure out why, is to put a breakpoint in your code so you can step through your code while live data is being fed in.
In order to do so, simply put a breakpoint at the first line of code of your DecodeWaveform method, as shown below. Start up the SmartScope app, and add your decoder.
In order to do so, simply put a breakpoint at the first line of code of your DecodeWaveform method, as shown below. Start up the SmartScope app, and add your decoder.
<br>[[File:custDec_breakpoint.png]]   
<br>[[File:custDec_breakpoint.png]]   
<br>Now usually you would expect the code to break at your breakpoint, but not in this case as the SmartScope app is using your compiled .dll, and not the code source you’re looking at. But not worries, we just need to let Visual Studio know that your source is exactly the same as the .dll which is currently being executed. To do so, select Debug -> Attach to process. Select SmartScope.exe from the list, and hit Attach.  You should see that the SmartScope app is being halted, and your breakpoint is active now. Step through your code using F11 and F10 as you would debug any other program!
<br>Now usually you would expect the code to break at your breakpoint, but not in this case as the SmartScope app is using your compiled .dll, and not the code source you’re looking at. But not worries, we just need to let Visual Studio know that your source is exactly the same as the .dll which is currently being executed. To do so, select Debug -> Attach to process. Select SmartScope.exe from the list, and hit Attach.  You should see that the SmartScope app is being halted, and your breakpoint is active now. Step through your code using F11 and F10 as you would debug any other program!

Revision as of 21:28, 24 February 2015

Work in progress

The decoder framework has been created from the ground up with extensibility in mind. In case you want to use your own decoder in the SmartScope app, simply follow these steps (details info further down):

  • Download the Decoder source package containing the sample decoder project
  • Copy an existing decoder file
  • Change the metadata, like Name and RequiredInputWaveforms
  • Code the logic of your decoder in the DecodeWaveform method
  • Compile the project
  • Copy the resulting .dll file into the same folder as the SmartScope app

And voila, your custom decoder will show up nicely in the list of available processors!

Download the Decoder source package

Click here to go to xxx, where you can download the following software sources:

  • LabNationInterfaceDefinitions: this project contains the definitions your code should comply with. You only need the .dll to reference to in your project.
  • DefaultDecoders: here you find the source of the decoders that are included by default in the SmartScope app. They can be used as sample or as starting point.

Start from an existing decoder file

Open up the DefaultDecoders project, and add a reference to the LabNationInterfaceDefinitions.dll file downloaded in the previous step. To to so, underneath your project name (DefaultDecoders in this example), right-click on References and select Add reference. Select Browse from the menu on the left, and browse to the LabNationInterfaceDefinitions.dll file. You should see LabNationInterfaceDefinitions listed as reference to your project.


CustDec reference.png


Next, click on the “DigitalDecoderI2C.cs” file in the Solution Explorer at the top-right of your screen. Hit Ctrl+C and Ctrl+V to duplicate that file. Select the resulting “DigitalDecoderI2C - Copy.cs” file, right-click -> Rename to give the file a meaningful name.


CustDec solution.png


Inside the file, change the class name DigitalDecoderI2C to a name suiting your filename (note: this has to be done twice, on line 12 and line 14).


CustDec className.png

Define the metadata

Time to focus on the code. Just underneath the class name, you’ll notice a couple of properties which define everything of your decoder the SmartScope app needs to know, except the decoding itself. Change all of them to suite your new decoder’s needs:

  • Name: This is how your decoder will be presented by the SmartScope app in the list of available decoders.
  • Abbreviation: Max 4 characters describing your decoder. These will be printed inside the indicator of your decoder wave at the very left of the SmartScope app.
  • Author: Your name. Not used at the moment, sorry about that.
  • VersionMajor & VersionMinor: In case multiple decoders with same name are detected, these field allow the SmartScope app to detect which instance it the most recent one.
  • RequiredInputWaveforms: Here you define how many input waveforms your decoder requires, and which type of data they need to contain. This is done by using a Dictionary, linking the name of the wave to the type of required contents.

Code your logic

With all preparations done, it’s time to focus on the fun stuff. Head to the Process method, which has 2 arguments:

  • inputWaveforms: this is a list of arrays, containing all waveforms you specified above in the RequiredInputWaveforms property.
  • samplePeriod: in case your decoder requires absolute timestamps, this argument is for you. By multiplying this value by the indices of your input arrays, you can find the exact time between them. In case your decoder would require 2 digital waveform and 1 waveform containing voltages (floats), you should have this:


NOTE: if you specify bool, the SmartScope app will pick up all logic channels and analog channels (the app will convert them to binary values for you). If you specify float, the SmartScope app will pick up analog channels only. In case you want to build a decoder which consumes the output of another decoder, you can also specify DecoderOutput as input type.

Now you’ll notice the inputWaveforms is a Dictionary, providing a typeless Array for each input you require. Before you can use the actual values inside the Arrays, you’ll want to cast them to Arrays containing the type your defined earlier. In case of our previous example, this is how this would be done:

Now you can go ahead and implement your decoder. The output of your decoder must be a List of DecoderOutput elements.

Such a DecoderOutput object can serve to either contain a decoded value (such as an address byte), or a decoded event (such as a Start condition). When creating a DecoderOutput object, the first and second arguments you have to specify indicate the indices at which the visualization should start and end.

In case your decoder has detected and event and would like to add this to the output, you can use this line:

If you have decoded a value and would like to add this to the output of your decoder, simply use the following line:

Once you have defined the list of outputs for your decoder, transform it into an array and send it back to the SmartScope app, which will gladly display your newly created waveform. Additionally, other decoders will now also be able to select your decoder as input source.

Compile the project

Select Build -> Build solution (F6), solve any bugs and iterate until all bugs have been squashed.

Move the .dll file to the right folder

Once compilation is finished, find the resulting .dll file. You can find the location where the .dll is being generated by right-clicking on your project (DefaultDecoders in the screenshot at the top of this page), selecting Properties, selecting Build in the menu on the left and then checking the Output path on the bottom of the page presented. Copy or move that .dll file (DefaultDecoders.dll in case of this example) to the same folder as where SmartScope.exe is located (on Windows this typically is C:\Program Files (x86)\LabNation\SmartScope).

Now when you restart the SmartScope app, it should automagically pick up your new decoder and list it as available decoder!


CustDec finished.png

Debugging your decoder in real-time

Even though your project passes compilation successfully, there are many reasons why your decoder might not produce the desired result, or even cause the SmartScope throw an error message. The best way to figure out why, is to put a breakpoint in your code so you can step through your code while live data is being fed in. In order to do so, simply put a breakpoint at the first line of code of your DecodeWaveform method, as shown below. Start up the SmartScope app, and add your decoder.


CustDec breakpoint.png


Now usually you would expect the code to break at your breakpoint, but not in this case as the SmartScope app is using your compiled .dll, and not the code source you’re looking at. But not worries, we just need to let Visual Studio know that your source is exactly the same as the .dll which is currently being executed. To do so, select Debug -> Attach to process. Select SmartScope.exe from the list, and hit Attach. You should see that the SmartScope app is being halted, and your breakpoint is active now. Step through your code using F11 and F10 as you would debug any other program!