1

我正在尝试构建 RTCM SC104 v3 消息。该标准仅要求使用最小位数将数据传输到最大定义范围。因此,要加入数据,我将使用工会。但是如何将奇数大小的工会联合到以前的奇数工会?例如,消息 1002 每个卫星需要 74 位。直到消息完成并显示 n 个卫星的所有数据之前,没有填充位。我可以建立以前工会的工会吗?

 typedef union headerGPS
    {
    struct
    {
    unsigned int  msgNo    :12; // creates a 12 bit wide integral field
    unsigned int  baseID   :12; //base index number
    unsigned int  tow      :30; //time of measurement
    unsigned int  syncFlg  :1;  //1 if all GNSS readings same time
    unsigned int  no_gps   :5;  //number of gps readings
    unsigned int smoothInd :1;  //smoothing indicator
    unsigned int smoothInt :3;  //smoothing int rep
    } fields;
    unsigned char header[8];
} headerGPS;
typedef union data1002
{
    struct            //74 bits / 9.25 bytes per SV
    {
    INT8U      satID   :6;  //sat ID 6 bit
    INT8U      L1ind   :1;  //L1 indicator 1 bit set 1
    INT32U     L1range :24; //L1 psuedorange uint24
    int        diff    :20; //L1 phaserange - psuedorange int20
    INT8U      lockInd :7;  //L1 locktime indicator uint7
    INT8U      ambi    :8;  //L1 int ambiguity uint8
    INT8U      cnr     :8;  //L1 CNR uint8
    }fields;
    INT8U data[];
}data1002;

bool encode1002( int baseNumber, int gpsEpoch , int numberGpsSV, int numberGloSV, int  numberGalSV )
{
    std::string message1002;
    headerGPS h1002; //create header object
    h1002.fields.msgNo = 1002;
    h1002.fields.baseID = baseNumber;
    h1002.fields.tow = gpsEpoch;
    if(numberGloSV > 0 || numberGalSV > 0)
    {
        h1002.fields.syncFlg = 1;
    }
    else
   {
        h1002.fields.syncFlg = 0;
    }

    h1002.fields.no_gps = numberGpsSV;
    h1002.fields.smoothInd = 0;
    h1002.fields.smoothInt = 0;
    for(int n=0; n<8; n++)
    {
        message1002 += h1002.header[n];
    }//1002 header is complete







return true;
}

好的,所以我正在尝试设置一个位集来准备要发送的数据。我正在使用这种状态以所需的顺序填充位集,而无需添加额外的填充位。这是在“for”语句和“if channel data good”语句中。

for(varPos = 0; varPos < 6; varPos ++) //start on 0, end on 5
        {
            data_1002.set(bitPos,datastream[baseNumber].channel[n].satID & (1<<varPos)); //test bit
            bitPos++;
        }
        data_1002.set(bitPos,1);
        bitPos++;
        for(varPos = 0; varPos < 24; varPos ++) //start on 0, end on 5
        {
            data_1002.set(bitPos,codeRange & (1<<varPos)); //test bit
            bitPos++;
        }

我想将 bitset 中的所有位值复制到字节数组中,以使用以下命令发送 TCP/IP 端口:

int noBytes = (bitPos+7)/8; //number of data bytes to copy to array
if(noBytes <=0)
{
    noBytes = 0;
}
cout << "number of bytes to process=  " << noBytes <<endl;
cout <<"completed bitset size= " << bitPos << endl;

//convert bits to bytes

bitPos = 0;
int byteCount;
for (int w=0; w<noBytes; w++)  //bitPos/8 = number of bytes; w+8 because 8 bytes in header
{
    for(int q=0; q<8; q++)
    {
        if(data_1002.test(bitPos+q) == 1)
        {
            BUFFER[(w+8)] = BUFFER[(w+8)] | (1<<q);
        }
        else
        {
            BUFFER[(w+8)] = BUFFER[(w+8)] & (0xFF & (0<<q));
        }
    }
    bitPos = bitPos +8;
    byteCount = w+8;
}
cout << "bytecounter=  " << byteCount << endl;
cout<<"number btes processed plus header=  "<< noBytes+8 <<endl;
for(int w=0; w<noBytes+8; w++)
{
   output += BUFFER[w];
}

这似乎应该可以工作,但是如果我在编码中遗漏了一个错误,我将不胜感激。还有没有更简单的方法可以将位集传输到字节数组中发送出去?我阅读并尝试在字符串流中插入一个位集,但它将每个位插入为一个字符而不是一个位。

4

2 回答 2

0

您写道,您想通过创建另一个奇数结构的联合来加入数据?这将导致 2 个奇数大小的结构引用相同的二进制数据。我认为您想要的是附加,例如创建一个带有 2 个联合的新结构;而你想要的是它们被夹在一起而没有填充位?

奇数大小的位压缩结构将始终按字节、字或编译器选择的任何内容对齐。如果将其中两个放在另一个结构中,它们将被填充。你必须以不同的方式去做。

那么,为什么不将所有声明打包到一个结构中呢?也许是因为你有多个 headerGPS 和 data1002 的出现?如果是这样,一个解决方案可能是:(尽管我发现预处理器宏是一种黑客攻击,但有时这是唯一的方法)。

#define headerGPS(n) \
        unsigned int  msgNo_##n    :12; \
        unsigned int  baseID_##n   :12; \
        unsigned int  tow_##n      :30; \
        unsigned int  syncFlg_##n  :1;  \
        unsigned int  no_gps_##n   :5;  \
        unsigned int smoothInd_##n :1;  \
        unsigned int smoothInt_##n :3

#define data1002(n) \
        INT8U      satID_##n   :6; \
        INT8U      L1ind_##n   :1; \
        INT32U     L1range_##n :24;\
        int        diff_##n    :20;\
        INT8U      lockInd_##n :7; \
        INT8U      ambi_##n    :8; \
        INT8U      cnr_##n     :8

union gpsdata {
    struct {
    headerGPS(1);
    data1002(1);
    data1002(2);
    };
    INT8U data[];
};

请注意 append 运算符的用法##,因此您可以添加唯一的扩展名,使名称变为satID_1and satID_2

这个解决方案有点小技巧,它可能会混淆你的 IDE 解析器;当我测试时,Eclipse 确实为我正确地推荐了成员。

于 2013-08-08T01:25:27.110 回答
0

我不喜欢专门处理不是字节对齐的数据,因为在 C 中没有很好的管理方法。话虽如此,我不会做其他地方描述的宏魔术,因为,嘿,这是标记为 C++!

试试这个:

template< class ValueT, int OffsetV, int BitsV >
class BitfieldAt
{
   typedef ValueT ValueType;
   static const int Offset = OffsetV;
   static const int Bits = BitsV;
   static const int Mask = (1<<Bits) - 1;

   //do a static assert that sizeof(ValueType)<<3 >= BitsV + 7
};

template< int BitLength >
class BitStruct
{
   template< class Field >
   inline Type fetch( int index )
   {
      unsigned int offset = index * BitLength + Field::Offset;

      //find offset into memory, pull up value that is too large;
      ValueType retVal = (*(Field::ValueType *)(&((UInt8 *)this)[offset >> 3]));

      //shift it, then mask it
      return (retVal >> (offset & 0x07)) & Field::Mask;
   }

   //create explicit specialization for fetch<BoolFieldAt>
}

像这样使用:

//define the fields, their bit offsets and bit widths
typedef BitFieldAt<UInt16,0,6> satID;
typedef BitFieldAt<UInt8,6,1>  L1ind;

//demonstrate how to lookup some element
void Foo( BitStruct *dataBlock )
{
   if ( dataBlock->fetch<satID>(3) == 0x05 )

这应该优化到几乎没有(乘法,数组偏移,位移和按位与。如果您在编译时知道索引,您还可以添加备用成员模板:

   if ( dataBlock->fetch<satID,3>() == 0x05 )

这消除了乘法,并且应该允许编译器静态定义数组索引和移位。

无论如何,这是一种方式。

于 2013-08-08T03:33:12.573 回答