GNSS-SDR  0.0.21
An Open Source GNSS Software Defined Receiver
ion_gsms_chunk_unpacking_ctx.h
Go to the documentation of this file.
1 /*!
2  * \file ion_gsms_chunk_unpacking_ctx.h
3  * \brief Holds state and provides utilities for unpacking samples from a chunk
4  * \author Víctor Castillo Agüero, 2024. victorcastilloaguero(at)gmail.com
5  *
6  * This is a template class, and thus, its member functions must be defined in the header file.
7  *
8  * -----------------------------------------------------------------------------
9  *
10  * GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
11  * This file is part of GNSS-SDR.
12  *
13  * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors)
14  * SPDX-License-Identifier: GPL-3.0-or-later
15  *
16  * -----------------------------------------------------------------------------
17  */
18 
19 #ifndef GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H
20 #define GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H
21 
22 #include <gnuradio/block.h>
23 #include <GnssMetadata.h>
24 #include <cstdint>
25 
26 /** \addtogroup Signal_Source
27  * \{ */
28 /** \addtogroup Signal_Source_libs
29  * \{ */
30 
31 template <typename WT>
33 {
34  static constexpr uint8_t word_bitsize_ = sizeof(WT) * 8;
35 
36  const GnssMetadata::Chunk::WordShift word_shift_direction_;
37  WT* iterator_ = nullptr; // Not owned by this class, MUST NOT destroy
38  WT current_word_{};
39  uint8_t bitshift_ = 0;
40 
42  const GnssMetadata::Chunk::WordShift word_shift,
43  WT* data_buffer,
44  uint8_t data_buffer_word_count) : word_shift_direction_(word_shift)
45  {
46  if (word_shift_direction_ == GnssMetadata::Chunk::Left)
47  {
48  iterator_ = data_buffer;
49  }
50  else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
51  {
52  iterator_ = &data_buffer[data_buffer_word_count];
53  }
54  if (iterator_)
55  {
56  advance_word(); // Initializes current_word_
57  }
58  }
59 
60  void advance_word()
61  {
62  WT word = *iterator_;
63  if (word_shift_direction_ == GnssMetadata::Chunk::Left)
64  {
65  ++iterator_;
66  }
67  else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
68  {
69  --iterator_;
70  }
71 
72  current_word_ = word;
73  }
74 
75  void shift_current_word(uint8_t n)
76  {
77  if ((n % word_bitsize_) == 0)
78  {
79  for (uint8_t i = 0; i < (n / word_bitsize_); ++i)
80  {
81  advance_word();
82  }
83  return;
84  }
85 
86  if (word_shift_direction_ == GnssMetadata::Chunk::Left)
87  {
88  current_word_ <<= n;
89  }
90  else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
91  {
92  current_word_ >>= n;
93  }
94 
95  bitshift_ += n;
96  if (bitshift_ >= word_bitsize_)
97  {
98  advance_word();
99  bitshift_ -= word_bitsize_;
100  }
101  }
102 
103  void shift_padding(uint8_t n_bits)
104  {
105  if (n_bits == 0)
106  {
107  return;
108  }
109 
110  if ((n_bits + (bitshift_ % word_bitsize_)) >= word_bitsize_)
111  {
112  const uint8_t bits_shifted = word_bitsize_ - (bitshift_ % word_bitsize_);
113 
114  shift_current_word(bits_shifted);
115  shift_padding(n_bits - bits_shifted);
116  }
117  else
118  {
119  shift_current_word(n_bits);
120  }
121  }
122 
123  template <typename OT>
124  void shift_sample(uint8_t sample_bitsize, OT* output, uint8_t output_bit_offset = 0)
125  {
126  if (sample_bitsize % word_bitsize_ == 0)
127  {
128  const uint8_t words_per_sample = sample_bitsize / word_bitsize_;
129  for (uint8_t i = 0; i < words_per_sample; ++i)
130  {
131  if (word_shift_direction_ == GnssMetadata::Chunk::Left)
132  {
133  *output |= (current_word_ << ((words_per_sample - 1 - i) * word_bitsize_));
134  }
135  else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
136  {
137  *output |= (current_word_ << (i * word_bitsize_));
138  // TODO - reverse bit order of sample? maybe?
139  }
140  advance_word();
141  }
142  }
143  else if ((sample_bitsize + (bitshift_ % word_bitsize_)) > word_bitsize_)
144  {
145  const uint8_t bits_shifted = word_bitsize_ - (bitshift_ % word_bitsize_);
146 
147  if (word_shift_direction_ == GnssMetadata::Chunk::Left)
148  {
149  WT mask = ~((1 << (word_bitsize_ - bits_shifted)) - 1);
150  *output |= ((current_word_ & mask) >> output_bit_offset);
151  }
152  else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
153  {
154  WT mask = ((1 << (bits_shifted)) - 1);
155  *output |= (current_word_ & mask) << output_bit_offset;
156  // TODO - reverse bit order of sample? maybe?
157  }
158 
159  shift_current_word(bits_shifted);
160  shift_sample(sample_bitsize - bits_shifted, output, bits_shifted);
161  }
162  else
163  {
164  if (word_shift_direction_ == GnssMetadata::Chunk::Left)
165  {
166  WT mask = ~((1 << (word_bitsize_ - sample_bitsize)) - 1);
167  OT sample = (current_word_ & mask) >> (word_bitsize_ - sample_bitsize);
168  *output |= (sample) >> output_bit_offset;
169  }
170  else if (word_shift_direction_ == GnssMetadata::Chunk::Right)
171  {
172  WT mask = ((1 << (sample_bitsize)) - 1);
173  *output |= (current_word_ & mask) << output_bit_offset;
174  // TODO - reverse bit order of sample? maybe?
175  }
176 
177  shift_current_word(sample_bitsize);
178  }
179  }
180 };
181 
182 /** \} */
183 /** \} */
184 #endif // GNSS_SDR_ION_GSMS_CHUNK_UNPACKING_CTX_H