1 /* -*- c++ -*- */
2 /*
3 * Copyright 2004,2006,2013,2018 Free Software Foundation, Inc.
4 *
5 * This file is part of GNU Radio
6 *
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
11 *
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Radio; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
21 */
22
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "unpacked_to_packed_impl.h"
29 #include <gnuradio/io_signature.h>
30 #include <assert.h>
31
32 namespace gr {
33 namespace blocks {
34
35
36 template <class T>
37 typename unpacked_to_packed<T>::sptr
make(unsigned int bits_per_chunk,endianness_t endianness)38 unpacked_to_packed<T>::make(unsigned int bits_per_chunk, endianness_t endianness)
39 {
40 return gnuradio::get_initial_sptr(
41 new unpacked_to_packed_impl<T>(bits_per_chunk, endianness));
42 }
43
44 template <class T>
unpacked_to_packed_impl(unsigned int bits_per_chunk,endianness_t endianness)45 unpacked_to_packed_impl<T>::unpacked_to_packed_impl(unsigned int bits_per_chunk,
46 endianness_t endianness)
47 : block("unpacked_to_packed",
48 io_signature::make(1, -1, sizeof(T)),
49 io_signature::make(1, -1, sizeof(T))),
50 d_bits_per_chunk(bits_per_chunk),
51 d_endianness(endianness),
52 d_index(0)
53 {
54 assert(bits_per_chunk <= d_bits_per_type);
55 assert(bits_per_chunk > 0);
56
57 this->set_relative_rate((uint64_t)bits_per_chunk, (uint64_t)this->d_bits_per_type);
58 }
59
60 template <class T>
~unpacked_to_packed_impl()61 unpacked_to_packed_impl<T>::~unpacked_to_packed_impl()
62 {
63 }
64
65 template <class T>
forecast(int noutput_items,gr_vector_int & ninput_items_required)66 void unpacked_to_packed_impl<T>::forecast(int noutput_items,
67 gr_vector_int& ninput_items_required)
68 {
69 int input_required =
70 (int)ceil((d_index + noutput_items * 1.0 * d_bits_per_type) / d_bits_per_chunk);
71 unsigned ninputs = ninput_items_required.size();
72 for (unsigned int i = 0; i < ninputs; i++) {
73 ninput_items_required[i] = input_required;
74 }
75 }
76
77 template <class T>
get_bit_be1(const T * in_vector,unsigned int bit_addr,unsigned int bits_per_chunk)78 unsigned int unpacked_to_packed_impl<T>::get_bit_be1(const T* in_vector,
79 unsigned int bit_addr,
80 unsigned int bits_per_chunk)
81 {
82 unsigned int byte_addr = (int)bit_addr / bits_per_chunk;
83 T x = in_vector[byte_addr];
84 unsigned int residue = bit_addr - byte_addr * bits_per_chunk;
85 // printf("Bit addr %d byte addr %d residue %d val
86 // %d\n",bit_addr,byte_addr,residue,(x>>(bits_per_chunk-1-residue))&1);
87 return (x >> (bits_per_chunk - 1 - residue)) & 1;
88 }
89
90 template <class T>
general_work(int noutput_items,gr_vector_int & ninput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)91 int unpacked_to_packed_impl<T>::general_work(int noutput_items,
92 gr_vector_int& ninput_items,
93 gr_vector_const_void_star& input_items,
94 gr_vector_void_star& output_items)
95 {
96 unsigned int index_tmp = d_index;
97
98 assert(input_items.size() == output_items.size());
99 int nstreams = input_items.size();
100
101 for (int m = 0; m < nstreams; m++) {
102 const T* in = (T*)input_items[m];
103 T* out = (T*)output_items[m];
104 index_tmp = d_index;
105
106 // per stream processing
107
108 // assert((ninput_items[m]-d_index)*d_bits_per_chunk >=
109 // noutput_items*d_bits_per_type);
110
111 switch (d_endianness) {
112
113 case GR_MSB_FIRST:
114 for (int i = 0; i < noutput_items; i++) {
115 T tmp = 0;
116 for (unsigned int j = 0; j < d_bits_per_type; j++) {
117 tmp = (tmp << 1) | get_bit_be1(in, index_tmp, d_bits_per_chunk);
118 index_tmp++;
119 }
120 out[i] = tmp;
121 }
122 break;
123
124 case GR_LSB_FIRST:
125 for (int i = 0; i < noutput_items; i++) {
126 unsigned long tmp = 0;
127 for (unsigned int j = 0; j < d_bits_per_type; j++) {
128 tmp = (tmp >> 1) | (get_bit_be1(in, index_tmp, d_bits_per_chunk)
129 << (d_bits_per_type - 1));
130 index_tmp++;
131 }
132 out[i] = tmp;
133 }
134 break;
135
136 default:
137 assert(0);
138 }
139 }
140
141 d_index = index_tmp;
142 this->consume_each((int)(d_index / d_bits_per_chunk));
143 d_index = d_index % d_bits_per_chunk;
144
145 return noutput_items;
146 }
147
148 template class unpacked_to_packed<std::uint8_t>;
149 template class unpacked_to_packed<std::int16_t>;
150 template class unpacked_to_packed<std::int32_t>;
151 } /* namespace blocks */
152 } /* namespace gr */
153