mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-14 12:10:34 +00:00
Added unpack_2bit_samples
This is a generic gnuradio block for handling 2 bit samples packed into bytes or shorts. It can handle big or little endian ordering of the samples within the byte, as well as big or little endian ordering of the bytes within a short. This is a utility function for a generic sample source which will be able to handle all of these cases for both real and complex signals.
This commit is contained in:
parent
62b77c3f73
commit
3ca18df229
@ -22,6 +22,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
||||
unpack_byte_2bit_cpx_samples.cc
|
||||
unpack_intspir_1bit_samples.cc
|
||||
rtl_tcp_signal_source_c.cc
|
||||
unpack_2bit_samples.cc
|
||||
)
|
||||
|
||||
include_directories(
|
||||
|
@ -0,0 +1,184 @@
|
||||
/*!
|
||||
* \file unpack_2bit_samples.cc
|
||||
*
|
||||
* \brief Unpacks 2 bit samples that have been packed into bytes or shorts
|
||||
* \author Cillian O'Driscoll cillian.odriscoll (at) gmail.com
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "unpack_2bit_samples.h"
|
||||
#include <iostream>
|
||||
#include <gnuradio/io_signature.h>
|
||||
|
||||
struct byte_2bit_struct
|
||||
{
|
||||
signed sample_0:2; // <- 2 bits wide only
|
||||
signed sample_1:2; // <- 2 bits wide only
|
||||
signed sample_2:2; // <- 2 bits wide only
|
||||
signed sample_3:2; // <- 2 bits wide only
|
||||
};
|
||||
|
||||
union byte_and_samples
|
||||
{
|
||||
int8_t byte;
|
||||
byte_2bit_struct samples;
|
||||
};
|
||||
|
||||
bool systemIsBigEndian()
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t i;
|
||||
char c[4];
|
||||
} test_int = {0x01020304};
|
||||
|
||||
return test_int.c[0] == 1;
|
||||
}
|
||||
|
||||
bool systemBytesAreBigEndian()
|
||||
{
|
||||
byte_and_samples b;
|
||||
b.byte = static_cast< int8_t>(0x1B);
|
||||
|
||||
return b.samples.sample_0 == 0x3;
|
||||
}
|
||||
|
||||
void swapEndianness( int8_t const *in, std::vector< int8_t > &out, size_t item_size, unsigned int ninput_items )
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int j = 0;
|
||||
int k = 0;
|
||||
size_t skip = item_size - 1;
|
||||
|
||||
for( i = 0; i < ninput_items; ++i )
|
||||
{
|
||||
k = j + skip;
|
||||
while( k >= 0 )
|
||||
{
|
||||
out[j++] = in[k--];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unpack_2bit_samples_sptr make_unpack_2bit_samples( bool big_endian_bytes,
|
||||
size_t item_size,
|
||||
bool big_endian_items )
|
||||
{
|
||||
return unpack_2bit_samples_sptr(
|
||||
new unpack_2bit_samples( big_endian_bytes,
|
||||
item_size,
|
||||
big_endian_items )
|
||||
);
|
||||
}
|
||||
|
||||
unpack_2bit_samples::unpack_2bit_samples( bool big_endian_bytes,
|
||||
size_t item_size,
|
||||
bool big_endian_items )
|
||||
: sync_interpolator("unpack_2bit_samples",
|
||||
gr::io_signature::make(1, 1, item_size),
|
||||
gr::io_signature::make(1, 1, sizeof(char)),
|
||||
4*item_size ), // we make 4 bytes out for every byte in
|
||||
big_endian_bytes_(big_endian_bytes),
|
||||
item_size_(item_size),
|
||||
big_endian_items_(big_endian_items),
|
||||
swap_endian_items_(false)
|
||||
{
|
||||
|
||||
bool big_endian_system = systemIsBigEndian();
|
||||
|
||||
// Only swap the item bytes if the item size > 1 byte and the system
|
||||
// endianess is not the same as the item endianness:
|
||||
swap_endian_items_ = ( item_size_ > 1 ) &&
|
||||
( big_endian_system != big_endian_items);
|
||||
|
||||
bool big_endian_bytes_system = systemBytesAreBigEndian();
|
||||
|
||||
swap_endian_bytes_ = ( big_endian_bytes_system != big_endian_bytes_ );
|
||||
|
||||
}
|
||||
|
||||
unpack_2bit_samples::~unpack_2bit_samples()
|
||||
{}
|
||||
|
||||
int unpack_2bit_samples::work(int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
signed char const *in = (signed char const *)input_items[0];
|
||||
int8_t *out = (int8_t*)output_items[0];
|
||||
|
||||
size_t ninput_bytes = noutput_items/4;
|
||||
size_t ninput_items = ninput_bytes/item_size_;
|
||||
|
||||
// Handle endian swap if needed
|
||||
if( swap_endian_items_ )
|
||||
{
|
||||
work_buffer_.resize( ninput_bytes );
|
||||
swapEndianness( in, work_buffer_, item_size_, ninput_items );
|
||||
|
||||
in = const_cast< signed char const *> ( &work_buffer_[0] );
|
||||
}
|
||||
|
||||
// Here the in pointer can be interpreted as a stream of bytes to be
|
||||
// converted. But we now have two possibilities:
|
||||
// 1) The samples in a byte are in big endian order
|
||||
// 2) The samples in a byte are in little endian order
|
||||
|
||||
byte_and_samples raw_byte;
|
||||
int n = 0;
|
||||
|
||||
if( swap_endian_bytes_ )
|
||||
{
|
||||
for(int i = 0; i < ninput_bytes; ++i)
|
||||
{
|
||||
// Read packed input sample (1 byte = 4 samples)
|
||||
raw_byte.byte = in[i];
|
||||
|
||||
out[n++] = (int8_t)( 2*raw_byte.samples.sample_3 + 1 );
|
||||
out[n++] = (int8_t)( 2*raw_byte.samples.sample_2 + 1 );
|
||||
out[n++] = (int8_t)( 2*raw_byte.samples.sample_1 + 1 );
|
||||
out[n++] = (int8_t)( 2*raw_byte.samples.sample_0 + 1 );
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < ninput_bytes; ++i )
|
||||
{
|
||||
|
||||
// Read packed input sample (1 byte = 4 samples)
|
||||
raw_byte.byte = in[i];
|
||||
|
||||
out[n++] = (int8_t)( 2*raw_byte.samples.sample_0 + 1 );
|
||||
out[n++] = (int8_t)( 2*raw_byte.samples.sample_1 + 1 );
|
||||
out[n++] = (int8_t)( 2*raw_byte.samples.sample_2 + 1 );
|
||||
out[n++] = (int8_t)( 2*raw_byte.samples.sample_3 + 1 );
|
||||
}
|
||||
}
|
||||
|
||||
return noutput_items;
|
||||
}
|
||||
|
@ -0,0 +1,115 @@
|
||||
/*!
|
||||
* \file unpack_2bit_samples.h
|
||||
*
|
||||
* \brief Unpacks 2 bit samples
|
||||
* samples may be packed in any of the following ways:
|
||||
* 1) Into bytes [ item == byte ]
|
||||
* 1a) Big endian ordering within the byte
|
||||
* 1b) Little endian ordering within the byte
|
||||
* 2) Into shorts [ item == short ]
|
||||
* 2a) Big endian ordering of bytes, big endian within the byte
|
||||
* 2b) Big endian ordering of bytes, little endian within the byte
|
||||
* 2c) Little endian ordering of bytes, big endian within the byte
|
||||
* 2d) Little endian ordering of bytes, little endian within the byte
|
||||
*
|
||||
* Within a byte the two possibilities look like this:
|
||||
* 7 6 5 4 3 2 1 0 : Bit number
|
||||
* x_n,1 x_n,0 x_n+1,1 x_n+1,0 x_n+2,1 x_n+2,0 x_n+3,1 x_n+3,0 : Little endian
|
||||
* x_n+3,1 x_n+3,0 x_n+2,1 x_n+2,0 x_n+1,0 x_n+1,0 x_n,1 x_n, 0 : Big Endian
|
||||
*
|
||||
* For a short (uint16_t) the bytes are either transmitted as follows:
|
||||
*
|
||||
* 1 0 : Byte number
|
||||
* Byte_n Byte_n+1 : Little endian
|
||||
* Byte_n+1 Byte_n : Bit endian
|
||||
*
|
||||
* The two bit values are assumed to have the following mapping:
|
||||
*
|
||||
* x_1 x_0 Value
|
||||
* 0 0 +1
|
||||
* 0 1 +3
|
||||
* 1 0 -3
|
||||
* 1 1 -1
|
||||
*
|
||||
* Letting x denote the two's complement interpretation of x_1 x_0, then:
|
||||
*
|
||||
* Value = 2*x + 1
|
||||
*
|
||||
* We want to output the data in the order:
|
||||
*
|
||||
* Value_0, Value_1, Value_2, ..., Value_n, Value_n+1, Value_n+2, ...
|
||||
*
|
||||
* \author Cillian O'Driscoll cillian.odriscoll (at) gmail . com
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_UNPACK_2BIT_SAMPLES_H
|
||||
#define GNSS_SDR_UNPACK_2BIT_SAMPLES_H
|
||||
|
||||
#include <gnuradio/sync_interpolator.h>
|
||||
|
||||
class unpack_2bit_samples;
|
||||
|
||||
typedef boost::shared_ptr<unpack_2bit_samples> unpack_2bit_samples_sptr;
|
||||
|
||||
unpack_2bit_samples_sptr make_unpack_2bit_samples( bool big_endian_bytes,
|
||||
size_t item_size,
|
||||
bool big_endian_items );
|
||||
|
||||
/*!
|
||||
* \brief This class takes 2 bit samples that have been packed into bytes or
|
||||
* shorts as input and generates a byte for each sample. It generates eight
|
||||
* times as much data as is input (every two bits become 16 bits)
|
||||
*/
|
||||
class unpack_2bit_samples: public gr::sync_interpolator
|
||||
{
|
||||
private:
|
||||
friend unpack_2bit_samples_sptr
|
||||
make_unpack_2bit_samples_sptr( bool big_endian_bytes,
|
||||
size_t item_size,
|
||||
bool big_endian_items );
|
||||
|
||||
public:
|
||||
unpack_2bit_samples( bool big_endianBytes,
|
||||
size_t item_size,
|
||||
bool big_endian_items );
|
||||
|
||||
~unpack_2bit_samples();
|
||||
|
||||
int work (int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
|
||||
private:
|
||||
bool big_endian_bytes_;
|
||||
size_t item_size_;
|
||||
bool big_endian_items_;
|
||||
bool swap_endian_items_;
|
||||
bool swap_endian_bytes_;
|
||||
std::vector< int8_t > work_buffer_;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user