summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnuradio-core/src/lib/general/CMakeLists.txt1
-rw-r--r--gnuradio-core/src/lib/general/general.i2
-rw-r--r--gnuradio-core/src/lib/general/gr_endian_swap.cc101
-rw-r--r--gnuradio-core/src/lib/general/gr_endian_swap.h57
-rw-r--r--gnuradio-core/src/lib/general/gr_endian_swap.i31
-rw-r--r--gnuradio-core/src/python/gnuradio/gr/qa_endian_swap.py66
-rw-r--r--grc/blocks/block_tree.xml2
-rw-r--r--grc/blocks/gr_endian_swap.xml41
-rw-r--r--volk/include/volk/volk_32u_byteswap_u.h77
-rw-r--r--volk/include/volk/volk_64u_byteswap_u.h88
10 files changed, 466 insertions, 0 deletions
diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt
index 5c7b0f374..3cf7f74e4 100644
--- a/gnuradio-core/src/lib/general/CMakeLists.txt
+++ b/gnuradio-core/src/lib/general/CMakeLists.txt
@@ -207,6 +207,7 @@ set(gr_core_general_triple_threats
gr_deinterleave
gr_delay
gr_encode_ccsds_27_bb
+ gr_endian_swap
gr_fake_channel_coder_pp
gr_feedforward_agc_cc
gr_feval
diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i
index c0ce65527..790549c4d 100644
--- a/gnuradio-core/src/lib/general/general.i
+++ b/gnuradio-core/src/lib/general/general.i
@@ -60,6 +60,7 @@
#include <gr_complex_to_interleaved_short.h>
#include <gr_interleaved_short_to_complex.h>
//#include <gr_endianness.h>
+#include <gr_endian_swap.h>
#include <gr_firdes.h>
#include <gr_interleave.h>
#include <gr_deinterleave.h>
@@ -181,6 +182,7 @@
%include "gr_complex_to_xxx.i"
%include "gr_complex_to_interleaved_short.i"
//%include "gr_endianness.i"
+%include "gr_endian_swap.i"
%include "gr_interleaved_short_to_complex.i"
%include "gr_firdes.i"
%include "gr_interleave.i"
diff --git a/gnuradio-core/src/lib/general/gr_endian_swap.cc b/gnuradio-core/src/lib/general/gr_endian_swap.cc
new file mode 100644
index 000000000..d86da5aa7
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_endian_swap.cc
@@ -0,0 +1,101 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2010,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_endian_swap.h>
+#include <gr_io_signature.h>
+#include <volk/volk.h>
+
+gr_endian_swap_sptr
+gr_make_endian_swap (size_t item_size_bytes)
+{
+ return gnuradio::get_initial_sptr(new gr_endian_swap (item_size_bytes));
+}
+
+gr_endian_swap::gr_endian_swap (size_t item_size_bytes)
+ : gr_sync_block ("gr_endian_swap",
+ gr_make_io_signature (1, 1, item_size_bytes),
+ gr_make_io_signature (1, 1, item_size_bytes))
+{
+ const int alignment_multiple = volk_get_alignment();
+ set_alignment(std::max(1,alignment_multiple));
+}
+
+int
+gr_endian_swap::work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const char *in = (const char *) input_items[0];
+ char *out = (char *) output_items[0];
+
+ int nbytes( d_output_signature->sizeof_stream_item(0) );
+ if(is_unaligned()) {
+ switch(nbytes){
+ case 1:
+ memcpy(out,in,noutput_items);
+ break;
+ case 2:
+ memcpy(out,in,2*noutput_items);
+ volk_16u_byteswap_u((uint16_t*)out,noutput_items);
+ break;
+ case 4:
+ memcpy(out,in,4*noutput_items);
+ volk_32u_byteswap_u((uint32_t*)out,noutput_items);
+ break;
+ case 8:
+ memcpy(out,in,8*noutput_items);
+ volk_64u_byteswap_u((uint64_t*)out,noutput_items);
+ break;
+ default:
+ throw std::runtime_error("itemsize is not valid for gr_endian_swap!");
+ }
+ } else {
+ switch(nbytes){
+ case 1:
+ memcpy(out,in,noutput_items);
+ break;
+ case 2:
+ memcpy(out,in,2*noutput_items);
+ volk_16u_byteswap_a((uint16_t*)out,noutput_items);
+ break;
+ case 4:
+ memcpy(out,in,4*noutput_items);
+ volk_32u_byteswap_a((uint32_t*)out,noutput_items);
+ break;
+ case 8:
+ memcpy(out,in,8*noutput_items);
+ volk_64u_byteswap_a((uint64_t*)out,noutput_items);
+ break;
+ default:
+ throw std::runtime_error("itemsize is not valid for gr_endian_swap!");
+ }
+ }
+
+ return noutput_items;
+}
+
+
+
diff --git a/gnuradio-core/src/lib/general/gr_endian_swap.h b/gnuradio-core/src/lib/general/gr_endian_swap.h
new file mode 100644
index 000000000..0baa3f338
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_endian_swap.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_ENDIAN_SWAP_H
+#define INCLUDED_GR_ENDIAN_SWAP_H
+
+#include <gr_core_api.h>
+#include <gr_sync_block.h>
+
+class gr_endian_swap;
+typedef boost::shared_ptr<gr_endian_swap> gr_endian_swap_sptr;
+
+GR_CORE_API gr_endian_swap_sptr
+gr_make_endian_swap (size_t item_size_bytes=1);
+
+/*!
+ * \brief Convert stream of items into thier byte swapped version
+ *
+ * \param item_size_bytes number of bytes per item, 1=no-op,2=uint16_t,4=uint32_t,8=uint64_t
+ */
+
+class GR_CORE_API gr_endian_swap : public gr_sync_block
+{
+ private:
+ friend GR_CORE_API gr_endian_swap_sptr
+ gr_make_endian_swap (size_t item_size_bytes);
+ gr_endian_swap (size_t item_size_bytes);
+
+ size_t item_size_bytes;
+
+ public:
+ virtual int work (int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+
+#endif /* INCLUDED_GR_ENDIAN_SWAP_H */
diff --git a/gnuradio-core/src/lib/general/gr_endian_swap.i b/gnuradio-core/src/lib/general/gr_endian_swap.i
new file mode 100644
index 000000000..6058b9de7
--- /dev/null
+++ b/gnuradio-core/src/lib/general/gr_endian_swap.i
@@ -0,0 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2012 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+GR_SWIG_BLOCK_MAGIC(gr,endian_swap)
+
+gr_endian_swap_sptr
+gr_make_endian_swap (size_t bytes_per_item=1);
+
+class gr_endian_swap : public gr_sync_block
+{
+public:
+};
diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_endian_swap.py b/gnuradio-core/src/python/gnuradio/gr/qa_endian_swap.py
new file mode 100644
index 000000000..4d2555cc4
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gr/qa_endian_swap.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+from gnuradio import gr, gr_unittest
+import ctypes
+
+class test_endian_swap (gr_unittest.TestCase):
+
+ def setUp (self):
+ self.tb = gr.top_block ()
+
+ def tearDown (self):
+ self.tb = None
+
+ def test_001(self):
+
+ src_data = [1,2,3,4]
+ expected_result = [256, 512, 768, 1024];
+
+ src = gr.vector_source_s(src_data)
+ op = gr.endian_swap(2)
+ dst = gr.vector_sink_s()
+
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = list(dst.data())
+
+ self.assertEqual(expected_result, result_data)
+
+ def test_002(self):
+
+ src_data = [1,2,3,4]
+ expected_result = [16777216, 33554432, 50331648, 67108864];
+
+ src = gr.vector_source_i(src_data)
+ op = gr.endian_swap(4)
+ dst = gr.vector_sink_i()
+
+ self.tb.connect(src, op, dst)
+ self.tb.run()
+ result_data = list(dst.data())
+
+ self.assertEqual(expected_result, result_data)
+
+if __name__ == '__main__':
+ gr_unittest.run(test_endian_swap, "test_endian_swap.xml")
+
diff --git a/grc/blocks/block_tree.xml b/grc/blocks/block_tree.xml
index 3b5491a74..d7ec82e4a 100644
--- a/grc/blocks/block_tree.xml
+++ b/grc/blocks/block_tree.xml
@@ -64,6 +64,8 @@
<block>gr_fft_vxx</block>
<block>blks2_logpwrfft_x</block>
<block>gr_vector_insert_x</block>
+
+ <block>gr_endian_swap</block>
</cat>
<cat>
<name>Type Conversions</name>
diff --git a/grc/blocks/gr_endian_swap.xml b/grc/blocks/gr_endian_swap.xml
new file mode 100644
index 000000000..aa564026c
--- /dev/null
+++ b/grc/blocks/gr_endian_swap.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+###################################################
+##Add Block:
+## all types, 1 output, 2 to inf inputs
+###################################################
+ -->
+<block>
+ <name>Endian Swap</name>
+ <key>gr_endian_swap</key>
+ <import>from gnuradio import gr</import>
+ <make>gr.endian_swap($type.size)</make>
+ <param>
+ <name>IO Type</name>
+ <key>type</key>
+ <type>enum</type>
+ <option>
+ <name>Complex</name>
+ <key>complex</key>
+ <opt>size:8</opt>
+ </option>
+ <option>
+ <name>Int</name>
+ <key>s32</key>
+ <opt>size:4</opt>
+ </option>
+ <option>
+ <name>Short</name>
+ <key>s16</key>
+ <opt>size:2</opt>
+ </option>
+ </param>
+ <sink>
+ <name>in</name>
+ <type>$type</type>
+ </sink>
+ <source>
+ <name>out</name>
+ <type>$type</type>
+ </source>
+</block>
diff --git a/volk/include/volk/volk_32u_byteswap_u.h b/volk/include/volk/volk_32u_byteswap_u.h
new file mode 100644
index 000000000..e27d1f03d
--- /dev/null
+++ b/volk/include/volk/volk_32u_byteswap_u.h
@@ -0,0 +1,77 @@
+#ifndef INCLUDED_volk_32u_byteswap_u_H
+#define INCLUDED_volk_32u_byteswap_u_H
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#ifdef LV_HAVE_SSE2
+#include <emmintrin.h>
+
+/*!
+ \brief Byteswaps (in-place) an aligned vector of int32_t's.
+ \param intsToSwap The vector of data to byte swap
+ \param numDataPoints The number of data points
+*/
+static inline void volk_32u_byteswap_u_sse2(uint32_t* intsToSwap, unsigned int num_points){
+ unsigned int number = 0;
+
+ uint32_t* inputPtr = intsToSwap;
+ __m128i input, byte1, byte2, byte3, byte4, output;
+ __m128i byte2mask = _mm_set1_epi32(0x00FF0000);
+ __m128i byte3mask = _mm_set1_epi32(0x0000FF00);
+
+ const uint64_t quarterPoints = num_points / 4;
+ for(;number < quarterPoints; number++){
+ // Load the 32t values, increment inputPtr later since we're doing it in-place.
+ input = _mm_loadu_si128((__m128i*)inputPtr);
+ // Do the four shifts
+ byte1 = _mm_slli_epi32(input, 24);
+ byte2 = _mm_slli_epi32(input, 8);
+ byte3 = _mm_srli_epi32(input, 8);
+ byte4 = _mm_srli_epi32(input, 24);
+ // Or bytes together
+ output = _mm_or_si128(byte1, byte4);
+ byte2 = _mm_and_si128(byte2, byte2mask);
+ output = _mm_or_si128(output, byte2);
+ byte3 = _mm_and_si128(byte3, byte3mask);
+ output = _mm_or_si128(output, byte3);
+ // Store the results
+ _mm_storeu_si128((__m128i*)inputPtr, output);
+ inputPtr += 4;
+ }
+
+ // Byteswap any remaining points:
+ number = quarterPoints*4;
+ for(; number < num_points; number++){
+ uint32_t outputVal = *inputPtr;
+ outputVal = (((outputVal >> 24) & 0xff) | ((outputVal >> 8) & 0x0000ff00) | ((outputVal << 8) & 0x00ff0000) | ((outputVal << 24) & 0xff000000));
+ *inputPtr = outputVal;
+ inputPtr++;
+ }
+}
+#endif /* LV_HAVE_SSE2 */
+
+#ifdef LV_HAVE_GENERIC
+/*!
+ \brief Byteswaps (in-place) an aligned vector of int32_t's.
+ \param intsToSwap The vector of data to byte swap
+ \param numDataPoints The number of data points
+*/
+static inline void volk_32u_byteswap_u_generic(uint32_t* intsToSwap, unsigned int num_points){
+ uint32_t* inputPtr = intsToSwap;
+
+ unsigned int point;
+ for(point = 0; point < num_points; point++){
+ uint32_t output = *inputPtr;
+ output = (((output >> 24) & 0xff) | ((output >> 8) & 0x0000ff00) | ((output << 8) & 0x00ff0000) | ((output << 24) & 0xff000000));
+
+ *inputPtr = output;
+ inputPtr++;
+ }
+}
+#endif /* LV_HAVE_GENERIC */
+
+
+
+
+#endif /* INCLUDED_volk_32u_byteswap_u_H */
diff --git a/volk/include/volk/volk_64u_byteswap_u.h b/volk/include/volk/volk_64u_byteswap_u.h
new file mode 100644
index 000000000..41a4a3130
--- /dev/null
+++ b/volk/include/volk/volk_64u_byteswap_u.h
@@ -0,0 +1,88 @@
+#ifndef INCLUDED_volk_64u_byteswap_u_H
+#define INCLUDED_volk_64u_byteswap_u_H
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#ifdef LV_HAVE_SSE2
+#include <emmintrin.h>
+
+/*!
+ \brief Byteswaps (in-place) an aligned vector of int64_t's.
+ \param intsToSwap The vector of data to byte swap
+ \param numDataPoints The number of data points
+*/
+static inline void volk_64u_byteswap_u_sse2(uint64_t* intsToSwap, unsigned int num_points){
+ uint32_t* inputPtr = (uint32_t*)intsToSwap;
+ __m128i input, byte1, byte2, byte3, byte4, output;
+ __m128i byte2mask = _mm_set1_epi32(0x00FF0000);
+ __m128i byte3mask = _mm_set1_epi32(0x0000FF00);
+ uint64_t number = 0;
+ const unsigned int halfPoints = num_points / 2;
+ for(;number < halfPoints; number++){
+ // Load the 32t values, increment inputPtr later since we're doing it in-place.
+ input = _mm_loadu_si128((__m128i*)inputPtr);
+
+ // Do the four shifts
+ byte1 = _mm_slli_epi32(input, 24);
+ byte2 = _mm_slli_epi32(input, 8);
+ byte3 = _mm_srli_epi32(input, 8);
+ byte4 = _mm_srli_epi32(input, 24);
+ // Or bytes together
+ output = _mm_or_si128(byte1, byte4);
+ byte2 = _mm_and_si128(byte2, byte2mask);
+ output = _mm_or_si128(output, byte2);
+ byte3 = _mm_and_si128(byte3, byte3mask);
+ output = _mm_or_si128(output, byte3);
+
+ // Reorder the two words
+ output = _mm_shuffle_epi32(output, _MM_SHUFFLE(2, 3, 0, 1));
+
+ // Store the results
+ _mm_storeu_si128((__m128i*)inputPtr, output);
+ inputPtr += 4;
+ }
+
+ // Byteswap any remaining points:
+ number = halfPoints*2;
+ for(; number < num_points; number++){
+ uint32_t output1 = *inputPtr;
+ uint32_t output2 = inputPtr[1];
+
+ output1 = (((output1 >> 24) & 0xff) | ((output1 >> 8) & 0x0000ff00) | ((output1 << 8) & 0x00ff0000) | ((output1 << 24) & 0xff000000));
+
+ output2 = (((output2 >> 24) & 0xff) | ((output2 >> 8) & 0x0000ff00) | ((output2 << 8) & 0x00ff0000) | ((output2 << 24) & 0xff000000));
+
+ *inputPtr++ = output2;
+ *inputPtr++ = output1;
+ }
+}
+#endif /* LV_HAVE_SSE2 */
+
+#ifdef LV_HAVE_GENERIC
+/*!
+ \brief Byteswaps (in-place) an aligned vector of int64_t's.
+ \param intsToSwap The vector of data to byte swap
+ \param numDataPoints The number of data points
+*/
+static inline void volk_64u_byteswap_u_generic(uint64_t* intsToSwap, unsigned int num_points){
+ uint32_t* inputPtr = (uint32_t*)intsToSwap;
+ unsigned int point;
+ for(point = 0; point < num_points; point++){
+ uint32_t output1 = *inputPtr;
+ uint32_t output2 = inputPtr[1];
+
+ output1 = (((output1 >> 24) & 0xff) | ((output1 >> 8) & 0x0000ff00) | ((output1 << 8) & 0x00ff0000) | ((output1 << 24) & 0xff000000));
+
+ output2 = (((output2 >> 24) & 0xff) | ((output2 >> 8) & 0x0000ff00) | ((output2 << 8) & 0x00ff0000) | ((output2 << 24) & 0xff000000));
+
+ *inputPtr++ = output2;
+ *inputPtr++ = output1;
+ }
+}
+#endif /* LV_HAVE_GENERIC */
+
+
+
+
+#endif /* INCLUDED_volk_64u_byteswap_u_H */