Eevacademy #9 – Implementing Scpi In C++

Okay so today we’re going to be talking about Skippy this is a a set of commands like format the standard commands for programmable instruments Skippy commands are separated into these sections and they’re separated by colons so here we have the first node the second node and the third node and when you see these in document specifying how to.

Communicate with instruments you often get this strange syntax is like you get these square brackets and this means optional and so this is something that we’re going to have to implement commands are always separated by these colons each of these commands has two sections it’s a required section.

And an optional section the required section is in uppercase and the optional section is in lowercase now Skippy is not strictly case-sensitive so this is this command could be written as instrument or instrument or instrument those are all valid and the required section is of course always required but the.
Optional section isn’t so you could abbreviate that node as I and s.

N s T or if you’re really weird i n st and yeah so after the different nodes you get.

These parameters and parameters are always separated by commas and so here we have three different parameters a1 a2 and a3 and this is quite typical before the parameters you always see a white space but it’s an optional white space between.
Them it doesn’t have to be there so this is.

What we’re going to implement so let’s just go ahead and do that so I called this a command before I’ve called a keyword here.

It has two different sections a required section and an optional section and these are.

Just strings in an embedded system you wouldn’t use stood string you would use a fixed size array and I’ll talk about that at the very end for people who care but if you just want a higher level overview third string is probably the easiest.

Way to understand it so that’s what I’m going to do so here we have a the required section being defined in the constructor and the optional section being defined in the construction and the optional section is optional because you might have a keyword which is something that is always required such as the required commands in skippy these these are things like test and reset and identification they all this entire command is.

Required so this entire keyword is required so the optional section is actually optional and keywords are quite simple they consist of an O and it requires section at the start which is the capital letter section and then if.

That is found you then can pass an optional section and the optional section it it but obviously by the name may exist or may not and it always returns true the function that looks for the optional section is always found because something that’s optional always exists kind.

Return true after we find that so let’s have a look at how that works now all of these functions take two parameters all of the parts of functions that is they take.

The block which is to be processed and an.

Which to start processing and they always will return a boolean that is whether it is found or not or alternatively if it’s not an optional we’re talking about it’s whether the index changes or not so here we have a keyword and the keyword consists of Hell which is all required so hell is required and then lo ello which is optional so if we were to process it we can say if keyword hello with an index and if if that is true then we.
Know it’s found and I’m going to step through that function.

To show how it works so when you enter the.

Function we have two parameters we have hello and we have the index.

Index is initially 0 when the required section is found the index increments.

Length of that that section so that the length of that section is 3 H e L 1 2 3 so index is incremented by 3 which means the start the character will be processed next is at index 3 so and in this case as you can see from this array is an L a lowercase L.

Which means it’s optional so and then the optional section begins processing at that index so if it finds it which it does it increments it by the length of the section that it found so that’s 5 now at now the index is 5 which means it was incremented by that that optional section of length.

2 3 plus 2 is 5 there we go so and then it returns true because it found it so that’s sort of the structure of the the skipper command but how do we actually determine.

A required section or an optional section so let’s step through it again so we step in again and now.

We’re going to step into required so we’ve.

Keyword so we’re looking for H E L and we’re.

It in the block h-e-l-l-o and we’re starting at index 0 here we start we start by initializing a temporary index to zero and that index is going to go through the keyword and determine how much of.

The keyword is found and when it when it finds all of it it will kind of indicate that so here we go initially we are checking H the first letter of keyword and and then we calculate the block index which is just how far are we into this for loop plus the offset which is the starting index so if if the block index is within the bounds of the block then we can check the current letter.

Which is basically the start point of the block for the first iteration then the next one will be the next letter and the next one will.

Be the next letter so so we’re saying is it the same letter.

And if it is if current is the same as required and it is then we just continue and we just churn through all these letters until either we reach the end of the keyword with index or.

The block index is greater than the block size which means.

It breaks and if it breaks that means it basically wasn’t found because we didn’t completely find we didn’t completely find the keyword before the block ended so then all we have to.

Do is test whether the index is equal to the keyword size because if the index has incremented by the number of characters in keyword then we know that we actually have found every character in keyword and in this case we have so then all we do is say index.

Plus equals that length of keyword index on its final iteration increments once more so it actually equals the length so the length of it is three so we expect it to increment to three so index is now three which means that we have finished processing the first three characters.

In the block there we go returns true and that means that we can now start process in the optional section and optional is basically identical to required but it always returns true so it’s it’s really simple to implement it calls the required function it can nor as the result and returns true yep great that was easy so now you know how to kind.

Of implement a parser for the Skippy keywords.

Now let’s work on the next section okay so now we have to implement the node and the node is actually just.

A keyword with a with a colon in front of.

It that’s this and the root node the first node in Skippy that’s this node here is actually optional it’s the only optional : so we have to have this all ears root flag and you don’t really have to understand templates to understand this you just have to know it’s either true or false when.

You create one of these classes and if it’s true then the colon is optional and if it’s found it increments the index past the colon if it’s not it doesn’t and then that means we’re free to start processing the keyword and we process the keyword exactly the same as we did in our test case so after we process the keyword we know that we’ve found the whole the whole node so we’re free.

To increment the index and then we return true because it is found now if it’s if it isn’t the root node of.

The first node then we’re kind of fine to say the colon is required so this means that it’s always found and it will always increment index.

By one if it is found so if the colon is found and then the keyword is found then we can do the same thing as before we’re ready to if it means the whole node is found and we can increment index and ink and return true so let’s try that out so.

A node and we’re going to do a non.

Root node it’s a bit simpler and a node consists of a key word and the key word here is hello we can probably just do equals so the node is going to be constructed from this keyword here and we use the function exactly the same way only now we’re looking for that : so if we run it it won’t to be found because we don’t have the colon and we’re going to step into it.

And we step into it and this is not a root.

Node so it runs the required so the required colon in this block here is not going to be found and we return false because we haven’t found it so that’s what should happen now if we add a colon here the required colon is now inside the block and index is free to increment by one and.

It has so now we start looking for hello and we’re starting at index one now and it’s found and the index is now incremented to the end of the keyword so and we know the keywords found so we know we’ve.

Found this node so Skippy is really just a bunch of nodes and all we have to do to actually implement a full Skippy parser is use these nodes in basically some if statements so in this case.

We’re going to look at these commands we’re going to look at sense so a standard command in Skippy would be sense and this could be followed for your voltage or something so that’s what we’re going to do and well I’ve added one more thing which is query and I just look at this function before we go through this query just detects the question mark character increments the index if there.

Is one and returns true so that’s all it does so we have three nodes in.

This we have the sense node which is got.

The required Sen s and with an optional a at the end then we’ve got a voltage node with the required vol T and.

An optional a GE and then finally we have current which is an option with a required CU RR and an optional ENT here’s a table the required section and the optional section now again this is not case-sensitive so these could be upper.

Or lower case ok so how do we actually process a command well first we have to take the command as an input see in just gets gets a string and then we pass the string to our sense node a.

Sense node is like a function and the sense node takes the input in the index just as before and if it finds it that means we know that we found this section we found this SE NS e or SE NS or some variation of capitals and lower.

Cases so if we’ve done that we’re free to.

Go to the next section so because we’re looking for sense voltage or we’re looking for since current looking for either or either of those but not both we have voltage if that’s found then we process that else if current is found we process.

The current so it’s quite simple and then so in inside the processing of those two it’s either a query or a command and the query in this case it’s just going to print whether it’s a query or not with a question mark but usually this would mean that you would either either return a value or assign a value so it’s it’s relatively simple.

So let’s have a look let’s run this program all right so here we go so if we step through this program.

With the inputs sense voltage then our input is is what we just entered into the console and our index starts at 0 and if we find the word sense and because it’s in here we will then index increments to the end of.

The word sense and then we’re ready to process the next section of the command so sense here ends.

At character 5 so we’re now ready to process from character 5 onwards and that’s why.

Index is 5 so now we don’t know whether its voltage or current so we have to test it and this if statement tests that.

So if the voltage is found it’ll run this so it does because it is there and it moves the index to the end of the word voltage which is 13 the.

Raw array we’re at the right place and then we just determine whether it’s a query or not now it did not end in a question mark which was that query thing we talked about just before so it does not print a question mark this is an if statement in in a single line this says if this is true do this otherwise do.

This there colon separates the two it’s called a ternary operator it’s kind of weird yeah ok so then we just print it and there we go since voltage found now what about current what about current so let’s just continue through so since current so of course this is the same at the start it’s common between the two so we’re not going to process sense again each time.