Support

If you have a problem or need to report a bug please email : support@dsprobotics.com

There are 3 sections to this support area:

DOWNLOADS: access to product manuals, support files and drivers

HELP & INFORMATION: tutorials and example files for learning or finding pre-made modules for your projects

USER FORUMS: meet with other users and exchange ideas, you can also get help and assistance here

NEW REGISTRATIONS - please contact us if you wish to register on the forum

Bitmasking in DSP Code

DSP related issues, mathematics, processing and techniques

Re: Bitmasking in DSP Code

Postby Spogg » Wed Sep 27, 2017 9:38 am

I found DSP difficult to understand, and I still have to experiment until I get the intended outcome. If something even simple works first time, it’s a cause for immediately getting a coffee to celebrate.

But in my case I don’t think about the bit masking itself. I’ve kinda learnt the syntax of what to do to get what I want, and I never refer to the process under the hood. I look at work by others and try to figure out what’s going on. I remember totally struggling to modify an AHD envelope generator to work in sample increments rather than 16-sample hops. I got there but never once thought about bit masking. And that applies to literally all my DSP modules.

The only time I found it necessary to think about it was Martin’s tutorial, in relation to the abs alternative. This method was very odd to me but happily it makes sense to me now, but of course I could use it without remembering the explanation itself.

I think the method of learning that I’m proposing goes against the grain for you though. I personally find favour with top-down learning to some extent, with a lot of trial and much error. I like to learn what to do to get what I want and worry about what’s behind it all only when necessary or interesting. This is a bit like a child learning a language, they make certain noises and when they get it right, or good enough, stuff happens. It gets more polished as they practice.

On the technical reason for bit masking I believe that it’s simply faster and so more CPU efficient than conditional branching etc. but I hope Martin will correct me if that’s not right.


Cheers

Spogg
User avatar
Spogg
 
Posts: 3318
Joined: Thu Nov 20, 2014 4:24 pm
Location: Birmingham, England

Re: Bitmasking in DSP Code

Postby adamszabo » Wed Sep 27, 2017 10:54 am

At first I didnt understand it either, but once it 'clicks' you get it. Working with streams is a bit different than normal coding where you use objects, and, if, else, clauses. You have think like an engineer instead of a programmer. Streams are a flow of data, just like electricity would be. Look at this schematic:

http://www.electroschematics.com/wp-content/uploads/2011/10/simple-water-detector.gif

There are streams, additions, comparisons with conditions etc. You have to take everything step by step. If you learn to think this way the code box will be much simpler. You need to take everything bit by bit. What do I need? I need to compare this value with that, to get an answer, then use that answer to do something else and so on.
adamszabo
 
Posts: 657
Joined: Sun Jul 11, 2010 7:21 am

Re: Bitmasking in DSP Code

Postby KG_is_back » Fri Sep 29, 2017 4:31 pm

tulamide wrote:Or is there somebody that will program a translator? A tool, where I enter normal (nested) conditionals and get the resulting bitmasking line? Optimzed?


If you want to just convert ternary operator into bitmasks quick and dirty, that is rather easy to do:
Code: Select all
C ? A : B
= B +(A-B)&C //faster version, but has rounding errors if A and B are dissimilar size
= (A&C) + (B&(C==0)) //slower, but not sensitive to rounding errors
in case when one branch is zero
C ? A : 0 = A&C

To optimize it, just put as much of the stuff outside the ternary operator as possible, because unlike in C where only the picked branch A/B gets executed, in DSP both are executed. Example:
Code: Select all
y= condition ? (x*x*x) :( x*x);
y=x*x * ( condition ? x : 1);
//now convert
y=x*x* ( x + (1-x)&condition);

In case you need to nest them, just nest them. I recommend converting from inside out, because you may notice possible optimizations in the process. The branches may end up with a few identical terms inside them, which you can just put outside the conditional or merge them.
Code: Select all
expression & condition1 + expression & condition2 = expression & (condition1 | condition2)

C ? (A+B&D) : (E+B&D) = B&D + C ? A : E


This is how I think about the expressions with bitwise logic in DSP code. Simply first imagine them with ternary operators (or case statements that return value like in ruby, in case of multi-branching) and then just simplify them.

I guess it should be possible to automate the process and write some sort of "C to DSP" translator, but to make the result somewhat optimized it would have to parse the code. If I recall correctly, the newest version of FS implements the ternary operator directly, which solves most of these issues anyway...
KG_is_back
 
Posts: 1196
Joined: Tue Oct 22, 2013 5:43 pm
Location: Slovakia

Re: 2. Examples

Postby MichaelBenjamin » Fri Oct 06, 2017 3:22 pm

.
Last edited by MichaelBenjamin on Mon Sep 21, 2020 11:04 am, edited 2 times in total.
MichaelBenjamin
 
Posts: 275
Joined: Tue Jul 13, 2010 1:32 pm

Re: 2. Examples

Postby martinvicanek » Fri Oct 06, 2017 4:47 pm

MichaelBenjamin wrote:I would argue the code box should be as readable as possible, then the asm box can be optuscated to hell and back.
Makes sense.
The second example also could have some problems with floating point behaviour, since b+a-b in float might not be the same as a.
True, as also pointed out by KG.
User avatar
martinvicanek
 
Posts: 1315
Joined: Sat Jun 22, 2013 8:28 pm

Re: Bitmasking in DSP Code

Postby Spogg » Fri Oct 06, 2017 4:47 pm

Yes FS uses the ! symbol for not expressions so != means not equal to.

Cheers

Spogg
User avatar
Spogg
 
Posts: 3318
Joined: Thu Nov 20, 2014 4:24 pm
Location: Birmingham, England

Re: Bitmasking in DSP Code

Postby martinvicanek » Sat Oct 07, 2017 1:22 am

I think what he means is negate a boolean expression. I believe there is a NOT operator in the betas, but not in 3.0.8.1 or before. However, in FS Version >= 3.0.8 we have the xorps and the andnps operators which you can use to create a negation:
Code: Select all
streamin A;
streamout NOTA;
int TRUE=-1;

movaps xmm0,A;
xorps xmm0,TRUE;
movaps NOTA,xmm0;

and similarly for andnps, refer to Adams post above.
User avatar
martinvicanek
 
Posts: 1315
Joined: Sat Jun 22, 2013 8:28 pm

Bitmasking Example: the Schmitt trigger

Postby martinvicanek » Mon Dec 25, 2017 3:45 am

Here is another example.
wikipedia wrote:A Schmitt trigger is a comparator [...] which converts an analog input signal to a digital output signal. [...] When the input is higher than a chosen threshold, the output is high. When the input is below a different (lower) chosen threshold the output is low, and when the input is between the two levels the output retains its value.


Here is the code:

Code: Select all
streamin in;
streamout out;
streamin thr1;   // on threshold
streamin thr2;   // off threshold

out = out&(in>thr2);     // keep state if input above thr2 else set to 0

out = out|(1&(in>thr1)); // keep state if input below thr1 else set to 1

User avatar
martinvicanek
 
Posts: 1315
Joined: Sat Jun 22, 2013 8:28 pm

Re: Bitmasking Example: the Schmitt trigger

Postby tulamide » Tue Dec 26, 2017 8:56 pm

martinvicanek wrote:Here is another example.
wikipedia wrote:A Schmitt trigger is a comparator [...] which converts an analog input signal to a digital output signal. [...] When the input is higher than a chosen threshold, the output is high. When the input is below a different (lower) chosen threshold the output is low, and when the input is between the two levels the output retains its value.


Here is the code:

Code: Select all
streamin in;
streamout out;
streamin thr1;   // on threshold
streamin thr2;   // off threshold

out = out&(in>thr2);     // keep state if input above thr2 else set to 0

out = out|(1&(in>thr1)); // keep state if input below thr1 else set to 1


I'm so sorry, Martin, but I see a big question mark once again. the first "out =" line is now readable for me, thanks to your efforts. But I'm not sure about the second line. You're "or-ing", but I'm not sure what exactly. The right part will either be 1 or 0, but bitwise or would mean "if either bit is set, resulting bit is set". So 0 would not change anything, and 1 would change the lsb. What am I missing?
"There lies the dog buried" (German saying translated literally)
tulamide
 
Posts: 2686
Joined: Sat Jun 21, 2014 2:48 pm
Location: Germany

Re: Bitmasking Example: the Schmitt trigger

Postby martinvicanek » Wed Dec 27, 2017 1:54 am

tulamide wrote:I'm not sure about the second line.

Thanks for asking. Yes, this one is a bit tricky so let me explain step by step.

Consider thus the instruction
out = out|(1&(in>thr1));

The expression (in>thr1) is either true or false.

If false then 1&(in>thr1) is zero (both as a float variable and bitwise). Hence "or"-ing it with the out variable will bring no change, because
out|0 = out.

If (in>thr1) is true then 1&(in>thr1) is simply 1 or, in binary representation,
0 01111111 00000000000000000000000 (the two spaces are for better readability).
Now this expression is bitwise "or"-ed with the out variable, which can only have the the float values 1 or 0. (It has its value from previous code evaluations.)
Either way, the result will be 1 because both 1|1 = 1 and 0|1 = 1.

So to summarize in pseudocode:

Code: Select all
if (in>thr1) then
  out = 1
else
  out = out // no change
end if

Hope that helps!
User avatar
martinvicanek
 
Posts: 1315
Joined: Sat Jun 22, 2013 8:28 pm

PreviousNext

Return to DSP

Who is online

Users browsing this forum: No registered users and 26 guests