AIS NMEA and 6bit ASCII

I am attempting to decode AIS messages sent over an NMEA input port. The data payload is encoded as 6bit ASCII and I started to recode in C# the code found here: Converting an ASCII 6-bit string to 8-Bic ASCII Charecters

however I am having some trouble s to perform the bitwise operation:

 If (I And (1 shl shl J)) Then b.Set(b0, True)
                    b0 += 1
  private BitArray StrToBit(String st)
        {
            var c = st.ToCharArray();
            var b = new BitArray(c.Length*6, false);
            int b0 = 0;
            foreach (char ch in c)
            {
                int I = ch;
                I = I - 48;
                if (I > 39)
                {
                    I = I - 8;
                }
                for (int J = 5; J == 0; J--)
                {
                    if (I &(1 shl shl J))
                    {
                        b.Set(b0,true);
                        b0 += 1;
                    }
                }
            }
            return b;
        }

Here’s the trick but I am sure this code can be improved:

private BitArray StrToBit(String st)
        {
            var c = st.ToCharArray();
            var b = new BitArray(c.Length*6, false);
            int b0 = 0;
            foreach (char ch in c)
            {
                int I = ch;
                I = I - 48;
                if (I > 39)
                {
                    I = I - 8;
                }
                for (int J = 5; J == 0; J--)
                {
                    if ( (I &(1 shl shl J))==1)
                    {
                        b.Set(b0,true);
                        b0 += 1;
                    }
                }
            }
            return b;
        }

In fact I do not understand clearly the purpose of the instruction: I&(1<<J).

I suppose it’s an endian problem and the author of the code in VB was performing the bitwise operation for the 6 LSB. I have not test yet the code but for sure the compiler doest not accept if(I&(1<<J)) like (problem to cast an int into a bool) the result of the operation is only a single bit but the compiler do not know that…

So first in order to not reinvent the wheel does anyone have already a decoder for AIS device that runs on .netmf?
if no, does anyone has already work with 6bit ascii encoding?
if no, I cross finger and will code it myself (not easy when your finger are crossed ???)

@ leforban - I have a C# AIS decoder in my archive - I will see if I can find it tonight.

The shift expression 1<<J essentially means “two to the power of J” (it is a one bit, shifted left J times)
The whole ‘if’ expression is checking whether the bit corresponding to “two to the power of J” is set.

So you could re-write it in C# as (variables changed to lower case to avoid confusion with look-alike numbers):

if ( ( i & (1 << j )) !=0 ) {

(Can’t use code markers because the shift operator confuses the code-coloring feature on the web site)

Indeed it checks if the J’th bit is one or zero;

Yep, I did the same :slight_smile: if ( ( i & (1 << j )) ==1 ) {
:smiley: :slight_smile:

I reported it in the tasktraker !

Thanks for your message, it confirms my assumption

Actually,

if ( ( i & (1 << j )) ==1 ) {

is not the same as :

if ( ( i & (1 << j )) !=0 ) {

Only the second one will work as expected. Consider i=0xffffffff and j=2
1<<j is then 4
and 0xffffffff & 0x4 is … 0x4
You will need the !=0 version.

2 Likes

Example posted here : https://www.ghielectronics.com/community/codeshare/entry/1031

It takes a fairly different approach from the VB code you started with, but should have significantly higher performance. This version copies groups of bits instead of shifting and copying single bits. I did get lazy with the GetBitsAsInt part and rotated single bits. There are more efficient approaches, but they are too complicated for the performance payoff they give. Anyway, this seems to work for the sample inputs I have. I used this in a program with fairly loose requirements, so be sure to test thoroughly.

1 Like

Correct! You got the point