Splitting NAV frames into fields

Pulling out the individual values out of the NAV frames, then converting them into the correct range of values is quite a struggle. Here is my solution!

First off, here are a few worker routines that pull a range of bits out of the NAV subfields (where the parity bits are in the lowest 6 bits of each value):

Return the lowest ‘n_bits’ bits of the value ‘u’:

unsigned int mask(unsigned u, int n_bits) {
  return u & ((1<<n_bits)-1);
}

Bit ‘len’ is the sign, and if set it needs to be extended into all the more significant bits – note this returns an ‘int’ type:

int sign_extend(unsigned u,int len) {
 if(len < 32 && u >0)
 if(u>>(len-1)&1) u |= 0xFFFFFFFF << len;
 return (int)u;
}

This is the key function to extract bits. It returns ‘len’ bits of the value ‘val’,starting with the bit at ‘offset’:

unsigned int bits(int val, int offset, int len) {
 return mask(val >> offset,len);
}

This extracts two sets of bits, from two different values, and then concatenates them together to build an unsigned value

unsigned join_bits_u(int val1, int offset1, int len1,
                     int val2, int offset2, int len2) {
  return (bits(val1, offset1, len1) << len2) | bits(val2, offset2, len2);
}

This also extracts two sets of bits and concatenates them together, however it also sign-extends the leftmost bit, making a signed value:

signed join_bits_s(int val1, int offset1, int len1, 
                   int val2, int offset2, int len2) {
  return sign_extend(join_bits_u(val1, offset1, len1, val2, offset2, len2),len1+len2);
}

With this groundwork in place, extracting the parameters becomes pretty easy, and by always calling “join_bits” even if only one set of bits is needed makes it quite clean:

/******** From FRAME 2 *******/
 iode1     = join_bits_u(           0, 0, 0, n->frame2[2], 22, 8);
 Crs       = join_bits_s(           0, 0, 0, n->frame2[2],  6,16) * pow(2.0,-5.0);
 M0        = join_bits_s(n->frame2[3], 6, 8, n->frame2[4],  6,24) * pow(2.0,-31.0) * PI;
 delta_n   = join_bits_s(           0, 0, 0, n->frame2[3], 14,16) * pow(2.0,-43.0) * PI;
 Cuc       = join_bits_s(           0, 0, 0, n->frame2[5],  6,16) * pow(2.0,-29.0);
 e         = join_bits_s(n->frame2[5], 6, 8, n->frame2[6],  6,24) * pow(2.0,-31.0);
 Cus       = join_bits_s(           0, 0, 0, n->frame2[7], 14,16) * pow(2.0,-29.0);
 sqrt_A    = join_bits_u(n->frame2[7], 6, 8, n->frame2[8],  6,24) * pow(2.0,-19.0);
 Toe       = join_bits_u(           0, 0, 0, n->frame2[9], 14,16);
 fit_flag  = join_bits_u(           0, 0, 0, n->frame2[9], 13, 1);
 aodo      = join_bits_u(           0, 0, 0, n->frame2[9],  8, 6);

/******** From FRAME 3 *******/
 Cic       = join_bits_s(           0, 0, 0, n->frame3[2], 14,16) * pow(2.0,-29.0);
 omega_0   = join_bits_s(n->frame3[2], 6, 8, n->frame3[3],  6,24) * pow(2.0,-31.0) * PI;
 Cis       = join_bits_s(           0, 0, 0, n->frame3[4], 14,16) * pow(2.0,-29.0);
 i_0       = join_bits_s(n->frame3[4], 6, 8, n->frame3[5],  6,24) * pow(2.0,-31.0) * PI;
 Crc       = join_bits_s(           0, 0, 0, n->frame3[6], 14,16) * pow(2.0,-5.0);
 w         = join_bits_s(n->frame3[6], 6, 8, n->frame3[7],  6,24) * pow(2.0,-31.0) * PI;
 omega_dot = join_bits_u(           0, 0, 0, n->frame3[8],  6,24) * pow(2.0,-43.0) * PI;
 iode2     = join_bits_u(           0, 0, 0, n->frame3[9], 22, 8);
 idot      = join_bits_s(           0, 0, 0, n->frame3[9],  8,14) * pow(2.0,-43.0) * PI;

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s