26、BDS B1I电文处理实现

\qquad 下面是HD-GR GNSS导航软件的BDS B1I电文处理实现代码,入口函数b1i _process_message (…):

// b1i_message.c -- BDS B1I Navigation message processing.

/* 
 * Copyright (C) 2005 Andrew Greenberg
 * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
 * See the "COPYING" file distributed with this software for more information.
 */

/* Namuru GPS receiver project
 * Original : message.c
 * Mods     : driving LED part has commented/replaced for Namuru HW
 * version  : V1.1
 * date     : 8/7/2008
 */

/* 
 * HD-GR GNSS receiver project
 * Modes    : Inherited the code of message.c in the Namuru GPS receiver project 
 *            V1.0 and made necessary adjustments to adapt to the new RTOS and 
 *            functions.
 * version  : V1.0
 * date     : xx/xx/2015
 */

#include <io.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "includes.h"
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"
#include "sys/alt_irq.h"
#include "gnsstime.h"
#include "b1i_message.h"
#include "b1i_accum_task.h"
#include "main_ephemeris.h"

/******************************************************************************
 * Defines
 ******************************************************************************/

#define B1I_PREAMBLE        (0x712 << (30-11))	// b1i_look_for_preamble is 0x712, but it's
												// located in the MSBits of a 30 bit word.

// ROM table list for BDS error correction
unsigned short m_BCH1511_ErrCorrTable[] __attribute__ ((section(".isrdata.rwdata"))) = {
    
    
	0x0000, 0x0001, 0x0002, 0x0010, 0x0004, 0x0100, 0x0020, 0x0400,
	0x0008, 0x4000, 0x0200, 0x0080, 0x0040, 0x2000, 0x0800, 0x1000};

/*
unsigned short m_BCH1511_ErrCorrTable[] = {	// reverse bit-order
	0x0000, 0x4000, 0x2000, 0x0400, 0x1000, 0x0040, 0x0200, 0x0010,
	0x0800, 0x0001, 0x0020, 0x0080, 0x0100, 0x0002, 0x0008, 0x0004};
*/


/******************************************************************************
 * Globals
 ******************************************************************************/

// Right now we're declaring a message structure per channel, since the
// messages come out of locked channels.. but you could argue they should be
// in a per satellite array.
b1i_message_t m_b1i_messages[B1I_MAX_CHANNELS] __attribute__ ((section(".isrdata.rwdata")));


/******************************************************************************
 * Statics
 ******************************************************************************/

static void b1i_look_for_preamble( unsigned short ch) __attribute__ ((section(".isrcode.txt")));
static int DecodeBCH1511(unsigned short *pus) __attribute__ ((section(".isrcode.txt")));
static int DecodeBCH3022(unsigned long *pul) __attribute__ ((section(".isrcode.txt")));

static void b1i_store_bit( unsigned short ch, unsigned short bit) __attribute__ ((section(".isrcode.txt")));
static void b1i_store_word( unsigned short ch) __attribute__ ((section(".isrcode.txt")));

/******************************************************************************
 * New satellite in a channel; clear the message. For now that means just
 * clearing the valid flags (and the current subframe for display purposes)
 *****************************************************************************/
void b1i_clear_messages(unsigned short ch)
{
    
    
	unsigned short i;

	m_b1i_messages[ch].frame_sync = 0;
	m_b1i_messages[ch].subframe = 0;
	m_b1i_messages[ch].set_epoch_flag = 0;
	m_b1i_messages[ch].wordbuf0 = 0;
	m_b1i_messages[ch].wordbuf1 = 0;
	for (i = 0; i < 5; ++i)
		m_b1i_messages[ch].subframes[i].valid = 0;
}


/******************************************************************************
 * Load bits into wordbuf0 and wordbuf1. Flip the incoming bit if we're sync'd
 * onto a subframe and the bits are inverted.
 *
 * Note, see coments about weird 2+ 30 bit pattern below in the words below.
 *****************************************************************************/
static void b1i_store_bit( unsigned short ch, unsigned short bit)
{
    
    
	// If the data is inverted, flip the incoming bit.
	if (m_b1i_messages[ch].data_inverted) {
    
    
		bit ^= 1;
	}

	unsigned short G1;
	unsigned short idx = m_b1i_messages[ch].bitcount / 2;
	bchdc_t *pbch_dc = (m_b1i_messages[ch].bitcount & 1) ?
		(&m_b1i_messages[ch].bch_dc2):(&m_b1i_messages[ch].bch_dc1);

	// decoder:
	// G1 = D[3];
	// D[3] = D[2];
	// D[2] = D[1];
	// D[1] = D[0] ^ G1;
	// D[0] = bit ^ G1;
	G1 = pbch_dc->D & 8;
	pbch_dc->D <<= 1;
	pbch_dc->D |= bit;
	if (G1) {
    
    
		pbch_dc->D ^= 3;
	}

	pbch_dc->swd |= bit;
	if (idx<14) {
    
    
		pbch_dc->swd <<= 1;
	}
}

/******************************************************************************
 * Take the message's buffer of 2 + 30 bits (2 from the previous word) and
 * store it in the subframe's word as 24 bits of data after completing a parity
 * check.
 *
 *****************************************************************************/
static void b1i_store_word( unsigned short ch)
{
    
    
	unsigned short sf = m_b1i_messages[ch].subframe;
	unsigned short wc = m_b1i_messages[ch].wordcount;
	// error correction
	unsigned short sw1 = m_b1i_messages[ch].bch_dc1.swd ^ m_BCH1511_ErrCorrTable[m_b1i_messages[ch].bch_dc1.D & 0xf];
	unsigned short sw2 = m_b1i_messages[ch].bch_dc2.swd ^ m_BCH1511_ErrCorrTable[m_b1i_messages[ch].bch_dc2.D & 0xf];

	// re-encoder
	unsigned short i, bit;
	unsigned short G1, D1=0, D2=0;
	unsigned short us1 = sw1;
	unsigned short us2 = sw2;
	for (i=0; i<11; i++, us1<<=1, us2<<=1) {
    
    
		bit = (us1 & 0x4000) ? 1:0;
		G1 = ((D1 & 8) ? 1:0) ^ bit;
		D1 <<= 1;
		if (G1) {
    
    
			D1 ^= 3;
		}

		bit = (us2 & 0x4000) ? 1:0;
		G1 = ((D2 & 8) ? 1:0) ^ bit;
		D2 <<= 1;
		if (G1) {
    
    
			D2 ^= 3;
		}
	}

	// parity check
	if ((D1 & 0xf) == (sw1 & 0xf) && (D2 & 0xf) == (sw2 & 0xf)) {
    
    
		// Store the word in the subframes array
		m_b1i_messages[ch].subframes[sf].word[wc] =
			((unsigned long)(sw1 & 0xfff0) << 15)|
			((unsigned long)(sw2 & 0xfff0) << 4) |
			((unsigned long)(sw1 & 0x000f) << 4) |
			((unsigned long)(sw2 & 0x000f));
		// Mark it as valid
		m_b1i_messages[ch].subframes[sf].valid |= (1 << wc);
	}
}

static int DecodeBCH1511(unsigned short *pus)
{
    
    
	unsigned short i, us, bit;
	unsigned short G1, D=0, DEC=0;

	// decoder:
	// G1 = D[3];
	// D[3] = D[2];
	// D[2] = D[1];
	// D[1] = D[0] ^ G1;
	// D[0] = bit ^ G1;
	us = *pus;
	for (i=0; i<15; i++, us<<=1) {
    
    
		bit = (us & 0x4000) ? 1:0;
		G1 = (D & 8);
		D <<= 1;
		D |= bit;
		if (G1) {
    
    
			D ^= 3;
		}
	}

	// error correction
	*pus ^= m_BCH1511_ErrCorrTable[D & 0xf];

	// re-encoder
	// G1 = D[3]^bit;
	// D[3] = D[2];
	// D[2] = D[1];
	// D[1] = D[0] ^ G1;
	// D[0] = G1;
	us = *pus;
	for (i=0; i<11; i++, us<<=1) {
    
    
		bit = (us & 0x4000) ? 1:0;
		G1 = ((DEC & 8) ? 1:0) ^ bit;
		DEC <<= 1;
		if (G1) {
    
    
			DEC ^= 3;
		}
	}

	// parity check
	if ((DEC & 0xf) == (*pus & 0xf)) {
    
    
		return 1;
	}
	return 0;
}

static int DecodeBCH3022(unsigned long *pul)
{
    
    
	unsigned long ul;
	unsigned short i, us1, us2;

	ul = *pul;
	i = us1 = us2 = 0;
	while (i < 15) {
    
    
		if (ul & 0x20000000)
			us1 |= 1;
		ul <<= 1;
		if (ul & 0x20000000)
			us2 |= 1;
		ul <<= 1;
		i ++;
		if (i < 15) {
    
    
			us1 <<= 1;
			us2 <<= 1;
		}
	}

	if (DecodeBCH1511(&us1) && DecodeBCH1511(&us2)) {
    
    
		*pul = ((unsigned long)(us1 & 0xfff0) << 15)|
			   ((unsigned long)(us2 & 0xfff0) << 4) |
			   ((unsigned long)(us1 & 0x000f) << 4) |
			   ((unsigned long)(us2 & 0x000f));
		return 1;
	}
	return 0;
}

/*******************************************************************************
 * This function finds the preamble, TLM and HOW in the navigation message and
 * synchronizes to the nav message.
*******************************************************************************/
static void b1i_look_for_preamble( unsigned short ch)
{
    
    
	unsigned long TLM, SOW;
	unsigned short current_subframe;
	unsigned short previous_subframe;
	unsigned short data_inverted, us;

	// Note: Bits are stored in wordbuf0/1 in store_bits()

	// Save local copies of the wordbuf's for local checks of TLM
	TLM = m_b1i_messages[ch].wordbuf1;
	SOW = m_b1i_messages[ch].wordbuf0;

	// Test for preamble
	if ((TLM & 0x3ff80000) == B1I_PREAMBLE) {
    
    
        data_inverted = 0;
	}
	else {
    
    
		TLM = ~TLM;
		if ((TLM & 0x3ff80000) == B1I_PREAMBLE) {
    
    
			SOW = ~SOW;
			data_inverted = 1;
		}
		else {
    
    
			return;
		}
	}

	us = TLM & 0x7fff;
	if (!DecodeBCH1511(&us)) {
    
    
		return;
	}
	TLM = (TLM & 0xffff8000) | us;

	if (!DecodeBCH3022(&SOW)) {
    
    
		return;
	}

	// Subframe ID
	current_subframe = (int)((TLM >> 12) & 7);

	// subframe range test
	if ((current_subframe < 1) || (current_subframe > 5)) {
    
    
		return;
	}

	// Hooray! We found a valid preamble and a SOW word, so for now we'll
	// assume we're synced. We won't really know until we get the next
	// subframe and check that the SOW has incremented by exactly 6.
	m_b1i_messages[ch].frame_sync = 1;

	// Record the current subframe number (from zero)
	m_b1i_messages[ch].subframe = --current_subframe;

	// Flag whether the bits are inverted.
	m_b1i_messages[ch].data_inverted = data_inverted;

	// We've just stored two words into the current subframe
	m_b1i_messages[ch].subframes[current_subframe].word[0] = TLM;
	m_b1i_messages[ch].subframes[current_subframe].word[1] = SOW;
	m_b1i_messages[ch].wordcount = 2;

	// Flag Words 0 and 1 as valid words
	m_b1i_messages[ch].subframes[current_subframe].valid = 3;

	// Extract and store the SOW from the TPW and SOW so we can easily compare
	// it to future SOWs to verify our frame sync.
	m_b1i_messages[ch].subframes[current_subframe].SOW =
		((TLM & 0xff0) << 8) | ((SOW >> 18) & 0xfff);

	previous_subframe = (current_subframe > 0) ? (current_subframe - 1):4;

	// Even if the previous subframe had valid TLM and SOW words, kill both the
	// current and previous subframes if their SOW's are not incrementally
	// different.
	if (m_b1i_messages[ch].subframes[previous_subframe].valid & 3) {
    
    
		unsigned long time_in_ms;
		unsigned short IsInvalid = 0;
		unsigned short D1Msg = IS_D1_NAVMESSAGE(m_b1i_messages[ch].prn);

		if (D1Msg) {
    
    
			if ((m_b1i_messages[ch].subframes[current_subframe].SOW) !=
				(m_b1i_messages[ch].subframes[previous_subframe].SOW + 6)) {
    
    
				IsInvalid = 1;
			}
		}
		else {
    
    
			if (current_subframe == 0) {
    
    
				if ((m_b1i_messages[ch].subframes[current_subframe].SOW) !=
					(m_b1i_messages[ch].subframes[previous_subframe].SOW + 3)) {
    
    
					IsInvalid = 1;
				}
			}
			else {
    
    
				if ((m_b1i_messages[ch].subframes[current_subframe].SOW) !=
					(m_b1i_messages[ch].subframes[previous_subframe].SOW)) {
    
    
					IsInvalid = 1;
				}
			}
		}
		if (IsInvalid) {
    
    
			// We're not actually synced. Kill everything and start
			// the sync search over again.
			b1i_clear_messages( ch);

			GNSS_ENTER_CRITICAL();
			// We must also go back to pull-in, as the sync process
			// is done there not in lock. If this is not done
			// the sync can get corrupted, leading to bad pseudoranges.
			m_B1I_CH[ch].backto_pull_in = 1;
		}
		else {
    
    
			// Now that we have a valid TLM/SOW, we know the actual time of week.
			time_in_ms = m_b1i_messages[ch].subframes[current_subframe].SOW * 1000;
			if (D1Msg) {
    
    
				// Note that the SOW in the SOW word is actually the time at the start
				// of the subframe.

				// Update the gps "time_in_ms". Given that we know the current bit
				// is the last bit of the SOW word (the 60th bit of the subframe), we
				// can calculate the gps time in ms. Note, time_in_bits is incremented
				// in the tracking.c lock() function.
				time_in_ms += 1200;
			}
			else {
    
    
				time_in_ms += current_subframe * 600 + 120;
			}
			// Update the GNSS time in seconds (the receiver's main clock).
			set_time_with_sow(time_in_ms/1000.0);
			time_in_ms /= 20;
			if (time_in_ms >= BITS_IN_WEEK_50HZ)
				time_in_ms -= BITS_IN_WEEK_50HZ;

			GNSS_ENTER_CRITICAL();
			m_B1I_CH[ch].time_in_bits = time_in_ms;
			m_B1I_CH[ch].ms_count_20 = 19;

			if (!m_b1i_messages[ch].set_epoch_flag) {
    
    
				// Finally, flag the tracking loop that the next bit (20ms epoch)
				// is the beginning of a new word. This will reset the epoch counter
				// to 0 every 30 bits to track words... but ONLY once.
				m_B1I_CH[ch].sync_20ms_epoch_count = 50 + (time_in_ms % 50);
				m_b1i_messages[ch].set_epoch_flag = 1;
			}
		}
	}
	// Hand off the current satellite to the message structure
	m_b1i_messages[ch].prn = m_B1I_CH[ch].prn;
	GNSS_EXIT_CRITICAL();
}

void b1i_sync_frame(unsigned short ch, unsigned short bit)
{
    
    
	// NAV messages come MSBit 1st, so the most recent bit is the LSBit.
	m_b1i_messages[ch].wordbuf0 = (m_b1i_messages[ch].wordbuf0 << 1) | bit;

	// NAV words are 30 bits long. Note that we use wordbuf1 to look for the
	// preamble (TLM and SOW at the same time)
	if( m_b1i_messages[ch].wordbuf0 & (1 << 30))
		m_b1i_messages[ch].wordbuf1 = (m_b1i_messages[ch].wordbuf1 << 1) | 1;
	else
		m_b1i_messages[ch].wordbuf1 = (m_b1i_messages[ch].wordbuf1 << 1);

    b1i_look_for_preamble(ch);

	// If we just found sync, then reset the counters
	if( m_b1i_messages[ch].frame_sync) {
    
    
		m_b1i_messages[ch].bitcount = 0;
		memset(&m_b1i_messages[ch].bch_dc1, 0, sizeof(bchdc_t));
		memset(&m_b1i_messages[ch].bch_dc2, 0, sizeof(bchdc_t));
	}
}


void b1i_process_message(OS_FLAGS channels_with_bits, OS_FLAGS channel_bits)
{
    
    
	INT8U err;
	INT32U pbit;
	unsigned short ch;
    OS_FLAGS which_subframe;

	for (ch = 0, pbit = 1; ch < B1I_MAX_CHANNELS; ch++, pbit <<= 1) {
    
    
		if (channels_with_bits & pbit) {
    
    
			// If the channel isn't sync'd to the message frame,
			// store the bit and look for the preamble
			if (!m_b1i_messages[ch].frame_sync) {
    
    
#ifndef SYNC_PROCESS_FRAME_SYNC
				b1i_sync_frame( ch, (channel_bits & pbit) ? 1:0);
#endif // SYNC_PROCESS_FRAME_SYNC
			}
            // Frame is sync'd, so get bits and words.
			else {
    
    
				// Store the bit
				b1i_store_bit( ch, (channel_bits & pbit) ? 1:0);

				// If we have 30 bits, that's a word so store it
				m_b1i_messages[ch].bitcount++;
				if (m_b1i_messages[ch].bitcount >= 30) {
    
    
					// Store the word in the subframes array
					b1i_store_word( ch);
					m_b1i_messages[ch].bitcount = 0;
					memset(&m_b1i_messages[ch].bch_dc1, 0, sizeof(bchdc_t));
					memset(&m_b1i_messages[ch].bch_dc2, 0, sizeof(bchdc_t));

					m_b1i_messages[ch].wordcount++;
					if (m_b1i_messages[ch].wordcount >= 10) {
    
    
						// We've got 10 words so we have a subframe. Use
						// frame_sync to restart the subframe parsing.
						// Note that preamble will reset wordcount.
						m_b1i_messages[ch].frame_sync = 0;
						m_b1i_messages[ch].wordbuf0 = 0;
						m_b1i_messages[ch].wordbuf1 = 0;

						// Only send along complete, error free subframes
						if (m_b1i_messages[ch].subframes[m_b1i_messages[ch].subframe].valid == 0x3ff) {
    
    
							// Set the flag to wake up the ephemeris thread
							channels_with_subframes |= (1 << ch);

							// Set the subframe flag so we know which
							// subframe to process. We don't need a
							// shadow register here because we're only
							// going to set one subframe per channel
							// at a time.
							which_subframe = (1 << m_b1i_messages[ch].subframe);
							OSFlagPost(m_EphemerisSubframeFlags[GPS_MAX_CHANNELS+ch], which_subframe, OS_FLAG_SET, &err);
						}
					}
				}
			}
		}
	}
}


猜你喜欢

转载自blog.csdn.net/turing321_huaide/article/details/120062365
26