| [4104] | 1 | /**************************************************************************** |
|---|
| 2 | |
|---|
| 3 | Copyright 2007 Virginia Polytechnic Institute and State University |
|---|
| 4 | |
|---|
| 5 | This file is part of the OSSIE Packetizer. |
|---|
| 6 | |
|---|
| 7 | OSSIE Packetizer 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 2 of the License, or |
|---|
| 10 | (at your option) any later version. |
|---|
| 11 | |
|---|
| 12 | OSSIE Packetizer 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 OSSIE Packetizer; if not, write to the Free Software |
|---|
| 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 20 | |
|---|
| 21 | ****************************************************************************/ |
|---|
| 22 | |
|---|
| 23 | |
|---|
| 24 | #include <iostream> |
|---|
| 25 | #include "PacketizerDSP.h" |
|---|
| 26 | #include <math.h> |
|---|
| 27 | |
|---|
| 28 | // Default constructor |
|---|
| [5485] | 29 | PacketizerBase::PacketizerBase() |
|---|
| [4104] | 30 | { |
|---|
| [5218] | 31 | // Initialize P/N synchronization code block |
|---|
| [5237] | 32 | pnSyncCode = pn_code_63; |
|---|
| [4106] | 33 | |
|---|
| [5218] | 34 | // Initialize P/N synchronization shift register |
|---|
| 35 | pn_sync_code = binary_sequence_create(); |
|---|
| 36 | binary_sequence_initialize(pn_sync_code, PN_SYNC_CODE_LENGTH); |
|---|
| 37 | for (unsigned int i=0; i<PN_SYNC_CODE_LENGTH; i++) |
|---|
| 38 | binary_sequence_push(pn_sync_code, pnSyncCode[i] & 0x01); |
|---|
| 39 | |
|---|
| [5237] | 40 | // Initialize P/N synchronization code block |
|---|
| 41 | pnControlCode = pn_code_7; |
|---|
| 42 | |
|---|
| 43 | // Initialize P/N control code shift register |
|---|
| 44 | pn_control_code = binary_sequence_create(); |
|---|
| 45 | binary_sequence_initialize(pn_control_code, PN_CONTROL_CODE_LENGTH); |
|---|
| 46 | for (unsigned int i=0; i<PN_CONTROL_CODE_LENGTH; i++) |
|---|
| 47 | binary_sequence_push(pn_control_code, pnControlCode[i] & 0x01); |
|---|
| 48 | |
|---|
| [5416] | 49 | packet_header_length = NUM_CONTROL_CODES*PN_CONTROL_CODE_LENGTH; |
|---|
| [5485] | 50 | |
|---|
| 51 | buf1 = new char[MAX_PACKET_SIZE]; |
|---|
| 52 | buf2 = new char[MAX_PACKET_SIZE]; |
|---|
| 53 | buf_len = MAX_PACKET_SIZE; |
|---|
| [5489] | 54 | |
|---|
| 55 | src_id = 0; |
|---|
| 56 | dst_id = 0; |
|---|
| 57 | port_id = 0; |
|---|
| 58 | app_id = 0; |
|---|
| 59 | packet_id = 0; |
|---|
| [5416] | 60 | } |
|---|
| 61 | |
|---|
| 62 | PacketEncoder::PacketEncoder() |
|---|
| 63 | { |
|---|
| [4104] | 64 | // Initialize control block pointers |
|---|
| [4106] | 65 | controlBlock = new char*[NUM_CONTROL_CODES]; |
|---|
| [4104] | 66 | |
|---|
| 67 | // Default control block codes to be all positive |
|---|
| [4106] | 68 | for (unsigned int i=0; i<NUM_CONTROL_CODES; i++) |
|---|
| [4104] | 69 | controlBlock[i] = pnControlCode; |
|---|
| [5416] | 70 | } |
|---|
| [5234] | 71 | |
|---|
| [5416] | 72 | PacketDecoder::PacketDecoder() |
|---|
| 73 | { |
|---|
| [5234] | 74 | // Initialize shift registers for receiver |
|---|
| 75 | pn_sync_buffer = binary_sequence_create(); |
|---|
| 76 | pn_control_buffer = binary_sequence_create(); |
|---|
| 77 | pn_eom_buffer = binary_sequence_create(); |
|---|
| 78 | binary_sequence_initialize( pn_sync_buffer, PN_SYNC_CODE_LENGTH ); |
|---|
| 79 | binary_sequence_initialize( pn_control_buffer, PN_CONTROL_CODE_LENGTH ); |
|---|
| 80 | binary_sequence_initialize( pn_eom_buffer, PN_SYNC_CODE_LENGTH ); |
|---|
| 81 | |
|---|
| [5395] | 82 | op_mode = FIND_HEADER; |
|---|
| [4104] | 83 | } |
|---|
| 84 | |
|---|
| 85 | // Destructor |
|---|
| [5416] | 86 | PacketEncoder::~PacketEncoder() |
|---|
| [4104] | 87 | { |
|---|
| 88 | delete [] controlBlock; |
|---|
| [5416] | 89 | } |
|---|
| [5234] | 90 | |
|---|
| [5416] | 91 | // Destructor |
|---|
| 92 | PacketDecoder::~PacketDecoder() |
|---|
| 93 | { |
|---|
| [5234] | 94 | binary_sequence_destroy( pn_sync_buffer ); |
|---|
| 95 | binary_sequence_destroy( pn_control_buffer ); |
|---|
| 96 | binary_sequence_destroy( pn_eom_buffer ); |
|---|
| [4104] | 97 | } |
|---|
| 98 | |
|---|
| [5416] | 99 | // Destructor |
|---|
| 100 | PacketizerBase::~PacketizerBase() |
|---|
| [5373] | 101 | { |
|---|
| [5416] | 102 | binary_sequence_destroy(pn_sync_code); |
|---|
| 103 | |
|---|
| [5485] | 104 | delete [] buf1; |
|---|
| 105 | delete [] buf2; |
|---|
| [5416] | 106 | } |
|---|
| 107 | |
|---|
| 108 | void PacketizerBase::SetBuffer(char *_b1, char *_b2, unsigned int _len) |
|---|
| 109 | { |
|---|
| [5373] | 110 | buf1 = _b1; |
|---|
| 111 | buf2 = _b2; |
|---|
| 112 | buf_len = _len; |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| [5277] | 115 | // Returns the necessary buffer size for processing given the current |
|---|
| 116 | // packet configuration |
|---|
| [5416] | 117 | unsigned int PacketizerBase::RequiredBufferSize(unsigned int input_length) |
|---|
| [5277] | 118 | { |
|---|
| 119 | switch (packet_type) { |
|---|
| 120 | case PACKET_RAW_400: |
|---|
| 121 | return 512; |
|---|
| 122 | default: |
|---|
| 123 | ///\todo calculate buffer size based on coding rate, etc. |
|---|
| [5416] | 124 | std::cerr << "ERROR! PacketizerBase::RequiredBufferSize() " |
|---|
| [5277] | 125 | << "Unsupported packet type: " << packet_type << std::endl; |
|---|
| 126 | throw 0; |
|---|
| 127 | } |
|---|
| 128 | |
|---|
| 129 | // should never get to this point, but include the return statement |
|---|
| 130 | // to keep the compiler happy |
|---|
| 131 | return 0; |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| [5416] | 134 | // |
|---|
| [5424] | 135 | void PacketizerBase::CheckBuffers(unsigned int input_length) |
|---|
| 136 | { |
|---|
| 137 | if (buf1 == NULL || buf2 == NULL) { |
|---|
| 138 | std::cerr << "ERROR! PacketizerBase:" << std::endl |
|---|
| 139 | << " => buffers not yet initialized!" << std::endl; |
|---|
| 140 | throw 0; |
|---|
| 141 | } |
|---|
| 142 | |
|---|
| 143 | // ensure buffer size is sufficient |
|---|
| 144 | unsigned int output_length_req = RequiredBufferSize(input_length); |
|---|
| 145 | |
|---|
| 146 | // ensure output buffer is sufficiently long |
|---|
| 147 | if ( output_length_req > buf_len ) { |
|---|
| 148 | std::cerr << "ERROR! PacketizerBase:" << std::endl |
|---|
| 149 | << " => required output length (" << output_length_req |
|---|
| 150 | << ") exceeds available buffer size (" << buf_len << ")" << std::endl; |
|---|
| 151 | throw 0; |
|---|
| 152 | } |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | |
|---|
| 156 | // |
|---|
| [5416] | 157 | void PacketEncoder::ConfigurePacketType( PacketType type ) |
|---|
| 158 | { |
|---|
| 159 | switch (type) { |
|---|
| 160 | case PACKET_RAW_400: |
|---|
| 161 | ConfigureControl( 0x00 ); |
|---|
| 162 | dynamic_packet_size = false; |
|---|
| 163 | packet_subheader_length = 21; |
|---|
| 164 | packet_data_length = 400; |
|---|
| [5428] | 165 | packet_data_length_encoded = 400; |
|---|
| [5416] | 166 | break; |
|---|
| [5485] | 167 | case PACKET_RS_512: |
|---|
| 168 | ConfigureControl( 0x01 ); |
|---|
| 169 | dynamic_packet_size = false; |
|---|
| 170 | packet_subheader_length = 213; |
|---|
| 171 | packet_data_length = 512; |
|---|
| 172 | packet_data_length_encoded = 720; |
|---|
| 173 | fec_inner = RS_4_15_11; |
|---|
| 174 | fec_outer = FEC_NONE; |
|---|
| 175 | crc = CRC_CHECKSUM_16; |
|---|
| 176 | break; |
|---|
| [5416] | 177 | default: |
|---|
| 178 | std::cerr << "ERROR! PacketEncoder::ConfigurePacketType() " |
|---|
| 179 | << "Unsupported packet type: " << type << std::endl; |
|---|
| [5485] | 180 | //throw 0; |
|---|
| 181 | ConfigurePacketType(PACKET_RAW_400); |
|---|
| 182 | return; |
|---|
| [5416] | 183 | } |
|---|
| 184 | |
|---|
| 185 | packet_type = type; |
|---|
| 186 | } |
|---|
| 187 | |
|---|
| 188 | |
|---|
| 189 | // |
|---|
| 190 | void PacketizerBase::ConfigurePacketType( PacketType type ) |
|---|
| 191 | { |
|---|
| 192 | switch (type) { |
|---|
| 193 | case PACKET_RAW_400: |
|---|
| 194 | dynamic_packet_size = false; |
|---|
| 195 | packet_subheader_length = 21; |
|---|
| 196 | packet_data_length = 400; |
|---|
| [5428] | 197 | packet_data_length_encoded = 400; |
|---|
| [5416] | 198 | break; |
|---|
| [5485] | 199 | case PACKET_RS_512: |
|---|
| 200 | dynamic_packet_size = false; |
|---|
| 201 | packet_subheader_length = 213; |
|---|
| 202 | packet_data_length = 512; |
|---|
| 203 | packet_data_length_encoded = 720; |
|---|
| 204 | fec_inner = RS_4_15_11; |
|---|
| 205 | fec_outer = FEC_NONE; |
|---|
| 206 | crc = CRC_CHECKSUM_16; |
|---|
| [5489] | 207 | break; |
|---|
| [5416] | 208 | default: |
|---|
| 209 | std::cerr << "ERROR! PacketizerBase::ConfigurePacketType() " |
|---|
| 210 | << "Unsupported packet type: " << type << std::endl; |
|---|
| [5485] | 211 | //throw 0; |
|---|
| 212 | ConfigurePacketType(PACKET_RAW_400); |
|---|
| 213 | return; |
|---|
| [5416] | 214 | } |
|---|
| 215 | |
|---|
| 216 | packet_type = type; |
|---|
| 217 | } |
|---|
| 218 | |
|---|
| 219 | |
|---|
| [5377] | 220 | // Completely constructs and encodes a packet from raw data bits |
|---|
| [5416] | 221 | bool PacketEncoder::CreatePacket( |
|---|
| [5377] | 222 | char* input, |
|---|
| 223 | unsigned int input_length, |
|---|
| [5428] | 224 | unsigned int &num_read, |
|---|
| [5377] | 225 | char* output, |
|---|
| [5382] | 226 | unsigned int output_length, |
|---|
| [5387] | 227 | unsigned int &num_written) |
|---|
| [5377] | 228 | { |
|---|
| [5383] | 229 | unsigned int encoded_packet_length; |
|---|
| [5428] | 230 | unsigned int nr; |
|---|
| 231 | EncodePacketData( |
|---|
| 232 | input, |
|---|
| 233 | input_length, |
|---|
| 234 | num_read, |
|---|
| 235 | buf1, |
|---|
| 236 | buf_len, |
|---|
| 237 | encoded_packet_length); |
|---|
| [5383] | 238 | |
|---|
| [5428] | 239 | AssemblePacket( |
|---|
| 240 | buf1, |
|---|
| 241 | encoded_packet_length, |
|---|
| 242 | nr, |
|---|
| 243 | output, |
|---|
| 244 | output_length, |
|---|
| 245 | num_written); |
|---|
| 246 | |
|---|
| [5399] | 247 | return true; |
|---|
| [5377] | 248 | } |
|---|
| 249 | |
|---|
| 250 | |
|---|
| 251 | // Completely finds and decodes a packet from raw data |
|---|
| [5416] | 252 | bool PacketDecoder::ExtractPacket( |
|---|
| [5377] | 253 | char* input, |
|---|
| 254 | unsigned int input_length, |
|---|
| [5428] | 255 | unsigned int &num_read, |
|---|
| [5377] | 256 | char* output, |
|---|
| [5387] | 257 | unsigned int output_length, |
|---|
| 258 | unsigned int &num_written) |
|---|
| [5377] | 259 | { |
|---|
| [5428] | 260 | unsigned int nr(0); // samples read from input buffer on each function |
|---|
| 261 | unsigned int nw(0); // samples written to output buffer on each function |
|---|
| [5379] | 262 | bool success; |
|---|
| [5377] | 263 | |
|---|
| [5428] | 264 | // reset counter return values |
|---|
| 265 | num_read = 0; |
|---|
| 266 | num_written = 0; |
|---|
| 267 | |
|---|
| [5377] | 268 | // |
|---|
| 269 | switch (op_mode) { |
|---|
| [5395] | 270 | case FIND_HEADER: |
|---|
| [5377] | 271 | // |
|---|
| [5396] | 272 | DEBUG_PRINTF(2, "MODE 0: EXTRACT_HEADER\n"); |
|---|
| [5428] | 273 | success = FindHeader(input, input_length, nr); |
|---|
| 274 | num_read += nr; |
|---|
| [5379] | 275 | |
|---|
| 276 | if ( success ) { |
|---|
| [5396] | 277 | DEBUG_PRINTF(2, " :: header found!\n"); |
|---|
| [5395] | 278 | op_mode = EXTRACT_HEADER; |
|---|
| 279 | } else { |
|---|
| 280 | return false; |
|---|
| 281 | } |
|---|
| 282 | case EXTRACT_HEADER: |
|---|
| 283 | // |
|---|
| [5396] | 284 | |
|---|
| 285 | DEBUG_PRINTF(2, "MODE 1: EXTRACT_HEADER\n"); |
|---|
| 286 | |
|---|
| [5395] | 287 | success = ExtractHeader( |
|---|
| [5428] | 288 | input + num_read, |
|---|
| 289 | input_length - num_read, |
|---|
| 290 | nr, |
|---|
| [5395] | 291 | buf1 + num_header_bits_read, |
|---|
| 292 | buf_len - num_header_bits_read, |
|---|
| [5428] | 293 | nw); |
|---|
| 294 | num_read += nr; |
|---|
| [5395] | 295 | |
|---|
| 296 | if ( success ) { |
|---|
| [5396] | 297 | DEBUG_PRINTF(2, " :: header extracted!\n"); |
|---|
| [5379] | 298 | op_mode = DECODE_HEADER; |
|---|
| 299 | } else { |
|---|
| 300 | return false; |
|---|
| 301 | } |
|---|
| [5395] | 302 | |
|---|
| [5377] | 303 | case DECODE_HEADER: |
|---|
| 304 | // |
|---|
| [5396] | 305 | |
|---|
| 306 | DEBUG_PRINTF(2, "MODE 2: DECODE_HEADER\n"); |
|---|
| 307 | |
|---|
| [5395] | 308 | success = DecodeHeader(buf1, buf_len); |
|---|
| [5379] | 309 | |
|---|
| 310 | if ( success ) { |
|---|
| [5396] | 311 | DEBUG_PRINTF(2, " :: header decoded!\n"); |
|---|
| [5379] | 312 | op_mode = EXTRACT_SUBHEADER; |
|---|
| 313 | } else { |
|---|
| 314 | return false; |
|---|
| 315 | } |
|---|
| [5377] | 316 | case EXTRACT_SUBHEADER: |
|---|
| 317 | // |
|---|
| [5396] | 318 | |
|---|
| 319 | DEBUG_PRINTF(2, "MODE 3: EXTRACT_SUBHEADER\n"); |
|---|
| 320 | |
|---|
| [5380] | 321 | // try to extract subheader and put into external buffer 1 |
|---|
| [5394] | 322 | success = ExtractSubheader( |
|---|
| [5428] | 323 | input + num_read, |
|---|
| 324 | input_length - num_read, |
|---|
| 325 | nr, |
|---|
| [5394] | 326 | buf1 + num_subheader_bits_read, |
|---|
| 327 | buf_len - num_subheader_bits_read, |
|---|
| [5428] | 328 | nw); |
|---|
| 329 | num_read += nr; |
|---|
| [5380] | 330 | |
|---|
| 331 | if ( success ) { |
|---|
| [5396] | 332 | DEBUG_PRINTF(2, " :: subheader extracted!\n"); |
|---|
| [5380] | 333 | op_mode = DECODE_SUBHEADER; |
|---|
| 334 | } else { |
|---|
| 335 | return false; |
|---|
| 336 | } |
|---|
| [5377] | 337 | case DECODE_SUBHEADER: |
|---|
| 338 | // |
|---|
| [5396] | 339 | |
|---|
| 340 | DEBUG_PRINTF(2, "MODE 4: DECODE_SUBHEADER\n"); |
|---|
| 341 | |
|---|
| [5380] | 342 | success = DecodeSubheader(buf1, buf_len); |
|---|
| 343 | |
|---|
| 344 | if ( success ) { |
|---|
| [5396] | 345 | DEBUG_PRINTF(2, " :: subheader decoded!\n"); |
|---|
| [5380] | 346 | op_mode = EXTRACT_PACKET_DATA; |
|---|
| 347 | } else { |
|---|
| [5396] | 348 | DEBUG_PRINTF(2, " COULD NOT DECODE SUBHEADER!\n"); |
|---|
| [5380] | 349 | op_mode = EXTRACT_HEADER; |
|---|
| 350 | return false; |
|---|
| 351 | } |
|---|
| 352 | |
|---|
| [5377] | 353 | case EXTRACT_PACKET_DATA: |
|---|
| 354 | // |
|---|
| [5396] | 355 | |
|---|
| 356 | DEBUG_PRINTF(2, "MODE 5: EXTRACT_PACKET_DATA\n"); |
|---|
| 357 | |
|---|
| [5380] | 358 | // try to extract subheader and put into external buffer 1 |
|---|
| [5394] | 359 | success = ExtractPacketData( |
|---|
| [5428] | 360 | input + num_read, |
|---|
| 361 | input_length - num_read, |
|---|
| 362 | nr, |
|---|
| [5394] | 363 | buf1 + num_packet_bits_read, |
|---|
| 364 | buf_len - num_packet_bits_read, |
|---|
| [5428] | 365 | nw); |
|---|
| 366 | num_read += nr; |
|---|
| [5380] | 367 | |
|---|
| 368 | if ( success ) { |
|---|
| [5396] | 369 | |
|---|
| 370 | DEBUG_PRINTF(2, " :: packet data extracted!\n"); |
|---|
| 371 | |
|---|
| [5380] | 372 | op_mode = DECODE_PACKET_DATA; |
|---|
| 373 | } else { |
|---|
| 374 | return false; |
|---|
| 375 | } |
|---|
| [5377] | 376 | case DECODE_PACKET_DATA: |
|---|
| 377 | // |
|---|
| [5396] | 378 | |
|---|
| 379 | DEBUG_PRINTF(2, "MODE 6: DECODE_PACKET_DATA\n"); |
|---|
| 380 | |
|---|
| [5428] | 381 | success = DecodePacketData( |
|---|
| 382 | buf1, |
|---|
| 383 | packet_data_length_encoded, |
|---|
| 384 | nr, |
|---|
| 385 | output, |
|---|
| 386 | output_length, |
|---|
| 387 | num_written); |
|---|
| [5380] | 388 | |
|---|
| [5395] | 389 | op_mode = FIND_HEADER; |
|---|
| [5380] | 390 | |
|---|
| 391 | if ( success ) { |
|---|
| [5396] | 392 | |
|---|
| 393 | DEBUG_PRINTF(2, " :: packet data decoded!\n"); |
|---|
| 394 | |
|---|
| [5380] | 395 | return true; |
|---|
| 396 | } else { |
|---|
| [5396] | 397 | DEBUG_PRINTF(2, " COULD NOT DECODE PACKET DATA!\n"); |
|---|
| [5380] | 398 | return false; |
|---|
| 399 | } |
|---|
| [5377] | 400 | default:; |
|---|
| 401 | } |
|---|
| 402 | |
|---|
| 403 | return false; |
|---|
| 404 | } |
|---|
| 405 | |
|---|
| 406 | |
|---|
| [5241] | 407 | |
|---|
| [4105] | 408 | // Sets pointers in controlBlock to appropriate control codes |
|---|
| [5416] | 409 | void PacketEncoder::ConfigureControl( unsigned char id ) |
|---|
| [4105] | 410 | { |
|---|
| [5234] | 411 | for (unsigned int i=NUM_CONTROL_CODES; i>0; i--) { |
|---|
| [5237] | 412 | controlBlock[i-1] = ( id & 0x01 ) ? pn_code_7 : pn_code_7_inv; |
|---|
| [4105] | 413 | id >>= 1; |
|---|
| 414 | } |
|---|
| 415 | } |
|---|
| [4104] | 416 | |
|---|
| [5236] | 417 | // Assemble packet and store in output buffer |
|---|
| [5416] | 418 | bool PacketEncoder::AssemblePacket( |
|---|
| [5280] | 419 | char* input, |
|---|
| 420 | unsigned int input_length, |
|---|
| [5428] | 421 | unsigned int &num_read, |
|---|
| [5280] | 422 | char* output, |
|---|
| [5382] | 423 | unsigned int output_length, |
|---|
| [5387] | 424 | unsigned int &num_written) |
|---|
| [5235] | 425 | { |
|---|
| [5282] | 426 | unsigned int i; |
|---|
| [5405] | 427 | unsigned int output_index(0); |
|---|
| [4105] | 428 | |
|---|
| [5279] | 429 | // check output size |
|---|
| 430 | unsigned int output_length_req = RequiredBufferSize(input_length); |
|---|
| 431 | |
|---|
| 432 | // ensure output buffer is sufficiently long |
|---|
| 433 | if ( output_length_req > output_length ) { |
|---|
| [5419] | 434 | std::cerr << "ERROR! PacketEncoder::AssemblePacket():" << std::endl |
|---|
| [5279] | 435 | << " => required output length (" << output_length_req |
|---|
| 436 | << ") exceeds buffer size (" << output_length << ")" << std::endl; |
|---|
| 437 | throw 0; |
|---|
| 438 | } |
|---|
| 439 | |
|---|
| 440 | // ensure output packet does not exceed the maximum allowable |
|---|
| 441 | if ( output_length_req > MAX_PACKET_SIZE ) { |
|---|
| [5419] | 442 | std::cerr << "ERROR! PacketEncoder::AssemblePacket():" << std::endl |
|---|
| [5279] | 443 | << " => required output length (" << output_length_req |
|---|
| 444 | << ") exceeds maximum size (" << MAX_PACKET_SIZE << ")" << std::endl; |
|---|
| 445 | throw 0; |
|---|
| 446 | } |
|---|
| 447 | |
|---|
| [5235] | 448 | // write P/N sync code |
|---|
| [5282] | 449 | memcpy(output+output_index, pnSyncCode, PN_SYNC_CODE_LENGTH); |
|---|
| 450 | output_index += PN_SYNC_CODE_LENGTH; |
|---|
| [5235] | 451 | |
|---|
| 452 | // write control codes |
|---|
| 453 | for (i=0; i<NUM_CONTROL_CODES; i++) { |
|---|
| [5282] | 454 | memcpy(output+output_index, controlBlock[i], PN_CONTROL_CODE_LENGTH); |
|---|
| 455 | output_index += PN_CONTROL_CODE_LENGTH; |
|---|
| [5235] | 456 | } |
|---|
| 457 | |
|---|
| [5428] | 458 | unsigned int nr; |
|---|
| 459 | unsigned int nw; |
|---|
| [5419] | 460 | |
|---|
| [5428] | 461 | EncodeSubheader(output+output_index, output_length-output_index, nw); |
|---|
| 462 | output_index += nw; |
|---|
| 463 | EncodePacketData(input, input_length, nr, output+output_index, output_length-output_index, nw); |
|---|
| 464 | output_index += nw; |
|---|
| [5424] | 465 | |
|---|
| 466 | num_written = output_index; |
|---|
| [5428] | 467 | num_read = packet_data_length; ///\todo num_read = input_length ??? |
|---|
| [5424] | 468 | |
|---|
| 469 | return true; |
|---|
| 470 | } |
|---|
| 471 | |
|---|
| 472 | // Encode subheader |
|---|
| 473 | bool PacketEncoder::EncodeSubheader( |
|---|
| 474 | char* output, |
|---|
| 475 | unsigned int output_length, |
|---|
| 476 | unsigned int &num_written) |
|---|
| 477 | { |
|---|
| 478 | ///\todo use function pointer for this |
|---|
| 479 | |
|---|
| [5383] | 480 | switch (packet_type) { |
|---|
| [5235] | 481 | case PACKET_RAW_400: |
|---|
| [5424] | 482 | return EncodeSubheader_PACKET_RAW_400(output, output_length, num_written); |
|---|
| [5489] | 483 | case PACKET_RS_512: |
|---|
| 484 | return EncodeSubheader_PACKET_RS_512(output, output_length, num_written); |
|---|
| [5235] | 485 | default: |
|---|
| [5424] | 486 | std::cerr << "ERROR! PacketEncoder::EncodeSubheader(): unsupported packet type" << std::endl; |
|---|
| [5235] | 487 | throw 0; |
|---|
| 488 | } |
|---|
| [5399] | 489 | |
|---|
| [5235] | 490 | } |
|---|
| 491 | |
|---|
| [5419] | 492 | // Encode subheader for PACKET_RAW_400 |
|---|
| 493 | bool PacketEncoder::EncodeSubheader_PACKET_RAW_400( |
|---|
| 494 | char* output, |
|---|
| 495 | unsigned int output_length, |
|---|
| 496 | unsigned int &num_written) |
|---|
| 497 | { |
|---|
| 498 | unsigned int i; |
|---|
| 499 | unsigned int N(0); |
|---|
| 500 | |
|---|
| 501 | ///\todo use reed-solomon codec to encode subheader data |
|---|
| 502 | // configure sub-header here |
|---|
| 503 | if ( packet_id > 7 ) |
|---|
| 504 | printf("WARNING! PacketEncoder::EncodeSubheader_PACKET_RAW_400() cannot encode packet_id > 7\n"); |
|---|
| 505 | |
|---|
| 506 | for (i=0; i<3; i++) { |
|---|
| 507 | if ( (packet_id >> (2-i)) & 0x01 ) |
|---|
| 508 | memcpy( output+N, pn_code_7, PN_CONTROL_CODE_LENGTH); |
|---|
| 509 | else |
|---|
| 510 | memcpy( output+N, pn_code_7_inv, PN_CONTROL_CODE_LENGTH); |
|---|
| 511 | |
|---|
| 512 | N += PN_CONTROL_CODE_LENGTH; |
|---|
| 513 | } |
|---|
| 514 | num_written = N; |
|---|
| 515 | return true; |
|---|
| 516 | } |
|---|
| 517 | |
|---|
| [5489] | 518 | // Encode subheader for PACKET_RS_512 |
|---|
| 519 | bool PacketEncoder::EncodeSubheader_PACKET_RS_512( |
|---|
| 520 | char* output, |
|---|
| 521 | unsigned int output_length, |
|---|
| 522 | unsigned int &num_written) |
|---|
| 523 | { |
|---|
| 524 | unsigned int nr; |
|---|
| 525 | unsigned int nw; |
|---|
| [5419] | 526 | |
|---|
| [5489] | 527 | // 1. push 16 8-bit symbols into buf1 |
|---|
| 528 | // variable num bits |
|---|
| 529 | // ---- ---- |
|---|
| 530 | // packet_id 32 |
|---|
| 531 | // src_id 16 |
|---|
| 532 | // dst_id 16 |
|---|
| 533 | // app_id 16 |
|---|
| 534 | // port_id 16 |
|---|
| 535 | // expansion 64 |
|---|
| [5490] | 536 | printf("packet_id = %d\n", packet_id); |
|---|
| 537 | buf1[0] = (packet_id >> 0) & 0xFF; |
|---|
| 538 | buf1[1] = (packet_id >> 8) & 0xFF; |
|---|
| 539 | buf1[2] = (packet_id >> 16) & 0xFF; |
|---|
| 540 | buf1[3] = (packet_id >> 24) & 0xFF; |
|---|
| 541 | printf("buf1[0] = %d\n", buf1[0]); |
|---|
| 542 | printf("buf1[1] = %d\n", buf1[1]); |
|---|
| 543 | printf("buf1[2] = %d\n", buf1[2]); |
|---|
| 544 | printf("buf1[3] = %d\n", buf1[3]); |
|---|
| 545 | printf("packet_id = %d\n", packet_id); |
|---|
| [5489] | 546 | |
|---|
| [5490] | 547 | buf1[4] = (src_id >> 0 ) & 0xFF; |
|---|
| 548 | buf1[5] = (src_id >> 8 ) & 0xFF; |
|---|
| [5489] | 549 | |
|---|
| [5490] | 550 | buf1[6] = (dst_id >> 0 ) & 0xFF; |
|---|
| 551 | buf1[7] = (dst_id >> 8 ) & 0xFF; |
|---|
| [5489] | 552 | |
|---|
| [5490] | 553 | buf1[8] = (app_id >> 0 ) & 0xFF; |
|---|
| 554 | buf1[9] = (app_id >> 8 ) & 0xFF; |
|---|
| [5489] | 555 | |
|---|
| [5490] | 556 | buf1[10] = (port_id >> 0 ) & 0xFF; |
|---|
| 557 | buf1[11] = (port_id >> 8 ) & 0xFF; |
|---|
| [5489] | 558 | |
|---|
| 559 | buf1[12] = 7; |
|---|
| 560 | buf1[13] = 7; |
|---|
| 561 | buf1[14] = 7; |
|---|
| 562 | buf1[15] = 7; |
|---|
| 563 | |
|---|
| 564 | // 2. compute CRC and append to end of message |
|---|
| 565 | FastCrc crc(0x04c11db7); |
|---|
| 566 | for (unsigned int i=0; i<16; i++) |
|---|
| 567 | crc.PutByte(buf1[i]); |
|---|
| 568 | UINT32 crc_code = crc.Done(); |
|---|
| [5490] | 569 | std::cout << "crc (encoder): 0x" << std::hex << crc_code << std::endl; |
|---|
| [5489] | 570 | |
|---|
| [5490] | 571 | buf1[16] = (crc_code >> 0 ) & 0xFF; |
|---|
| 572 | buf1[17] = (crc_code >> 8 ) & 0xFF; |
|---|
| 573 | buf1[18] = (crc_code >> 16 ) & 0xFF; |
|---|
| 574 | buf1[19] = (crc_code >> 24 ) & 0xFF; |
|---|
| 575 | for (unsigned int i=0; i<4; i++) |
|---|
| 576 | printf("crc[%d] = %d\n", i, (unsigned int) (buf1[16+i])); |
|---|
| [5489] | 577 | |
|---|
| 578 | // 3. repack 20 8-bit symbols (+2 bits) into 27 6-bit symbols |
|---|
| 579 | SigProc::repack_bytes(buf1, 8, 20, buf2, 2, buf_len, &nw); |
|---|
| 580 | printf("repack 8->2: nw=%d\n", nw); |
|---|
| 581 | buf2[640] = 0; |
|---|
| 582 | SigProc::repack_bytes(buf2, 2, 641, buf1, 6, buf_len, &nw); |
|---|
| 583 | printf("repack 2->6: nw=%d\n", nw); |
|---|
| 584 | |
|---|
| 585 | // 4. use 6-bit RS (63,55) punctured to (35,27) |
|---|
| 586 | // 27 symbols (uncoded) |
|---|
| 587 | // -> 35 symbols (coded) |
|---|
| 588 | int symsize = 6; |
|---|
| 589 | int npad = 28; |
|---|
| 590 | int nn = (1<<symsize)-1-npad; // 63-28 = 35 |
|---|
| 591 | int nroots = 8; |
|---|
| 592 | int kk = nn-nroots; // 35-8 = 27 |
|---|
| 593 | void *rs; |
|---|
| 594 | rs = init_rs_char(symsize,0x43,1,1,nroots,0); |
|---|
| 595 | encode_rs_char(rs, (unsigned char*) buf1, (unsigned char*) &buf1[kk]); |
|---|
| 596 | |
|---|
| 597 | // 5. unpack to output buffer |
|---|
| [5490] | 598 | SigProc::repack_bytes(buf1, 6, 35, output, 1, output_length, &num_written); |
|---|
| [5489] | 599 | num_written += 3; // pad to 213 |
|---|
| 600 | printf("PACKET_RS_512 subheader: num_written: %d (should be 213)\n", num_written); |
|---|
| 601 | return true; |
|---|
| 602 | } |
|---|
| 603 | |
|---|
| [5416] | 604 | bool PacketDecoder::FindHeader( |
|---|
| [5240] | 605 | char * input, |
|---|
| 606 | unsigned int input_length, |
|---|
| [5241] | 607 | unsigned int &num_bits_read) |
|---|
| [5240] | 608 | { |
|---|
| 609 | rxy = 0; |
|---|
| 610 | int correlator_threshold(60); |
|---|
| 611 | unsigned int i(0); |
|---|
| 612 | |
|---|
| [5249] | 613 | for (i=0; i<input_length; i++) { |
|---|
| [5240] | 614 | // push bit into shift register |
|---|
| 615 | binary_sequence_push( pn_sync_buffer, input[i] & 0x01 ); |
|---|
| 616 | |
|---|
| 617 | // correlate with P/N sync code |
|---|
| 618 | rxy = binary_sequence_correlate( pn_sync_buffer, pn_sync_code ); |
|---|
| 619 | |
|---|
| 620 | if ( abs(rxy) > correlator_threshold ) { |
|---|
| [5396] | 621 | DEBUG_PRINTF(4, "\nPN sync code found!!\n\n"); |
|---|
| [5283] | 622 | invert_bits = ( rxy < 0 ) ? true : false; |
|---|
| [5241] | 623 | num_bits_read = i+1; |
|---|
| [5395] | 624 | num_header_bits_read = 0; |
|---|
| [5240] | 625 | return true; |
|---|
| 626 | } |
|---|
| 627 | } |
|---|
| [5241] | 628 | |
|---|
| 629 | num_bits_read = input_length; |
|---|
| [5240] | 630 | return false; |
|---|
| 631 | |
|---|
| 632 | } |
|---|
| [5241] | 633 | |
|---|
| 634 | |
|---|
| [5416] | 635 | bool PacketDecoder::ExtractHeader( |
|---|
| [5241] | 636 | char * input, |
|---|
| 637 | unsigned int input_length, |
|---|
| [5428] | 638 | unsigned int &num_read, |
|---|
| [5395] | 639 | char * output, |
|---|
| 640 | unsigned int output_length, |
|---|
| 641 | unsigned int &num_written) |
|---|
| [5241] | 642 | { |
|---|
| [5249] | 643 | unsigned int i; |
|---|
| [5395] | 644 | num_written = 0; |
|---|
| [5428] | 645 | num_read = 0; |
|---|
| [5249] | 646 | |
|---|
| 647 | for (i=0; i<input_length; i++) { |
|---|
| [5395] | 648 | output[i] = invert_bits ? (~input[i]) & 0x01 : input[i]; |
|---|
| 649 | num_header_bits_read++; |
|---|
| 650 | num_written++; |
|---|
| [5428] | 651 | num_read++; |
|---|
| [5395] | 652 | |
|---|
| 653 | if ( num_header_bits_read == packet_header_length ) { |
|---|
| 654 | // header data have been extracted |
|---|
| 655 | num_subheader_bits_read = 0; |
|---|
| 656 | return true; |
|---|
| 657 | } |
|---|
| 658 | } |
|---|
| 659 | |
|---|
| 660 | return false; |
|---|
| 661 | } |
|---|
| 662 | |
|---|
| 663 | // decode control codes to describe packet type |
|---|
| [5416] | 664 | bool PacketDecoder::DecodeHeader( |
|---|
| [5395] | 665 | char * input, |
|---|
| 666 | unsigned int input_length) |
|---|
| 667 | { |
|---|
| 668 | // At this point the P/N sync code header has been found and |
|---|
| 669 | // the data should be completely stored in the input buffer |
|---|
| 670 | |
|---|
| [5405] | 671 | unsigned int new_packet_type(0); |
|---|
| [5395] | 672 | for (unsigned int i=0; i<NUM_CONTROL_CODES; i++) { |
|---|
| 673 | for (unsigned int j=0; j<PN_CONTROL_CODE_LENGTH; j++) { |
|---|
| 674 | binary_sequence_push( pn_control_buffer, input[j+i*PN_CONTROL_CODE_LENGTH] & 0x01 ); |
|---|
| 675 | } |
|---|
| 676 | |
|---|
| 677 | rxy = binary_sequence_correlate( pn_control_buffer, pn_control_code ); |
|---|
| 678 | |
|---|
| 679 | new_packet_type <<= 1; |
|---|
| 680 | new_packet_type |= ( rxy > 0 ) ? 0x01 : 0x00; |
|---|
| 681 | } |
|---|
| 682 | |
|---|
| 683 | ConfigurePacketType( (PacketType) new_packet_type ); |
|---|
| 684 | num_subheader_bits_read = 0; |
|---|
| 685 | return true; |
|---|
| 686 | } |
|---|
| 687 | |
|---|
| [5249] | 688 | |
|---|
| [5416] | 689 | bool PacketDecoder::ExtractSubheader( |
|---|
| [5280] | 690 | char * input, |
|---|
| 691 | unsigned int input_length, |
|---|
| [5428] | 692 | unsigned int &num_read, |
|---|
| [5373] | 693 | char * output, |
|---|
| [5393] | 694 | unsigned int output_length, |
|---|
| 695 | unsigned int &num_written) |
|---|
| [5280] | 696 | { |
|---|
| 697 | unsigned int i; |
|---|
| [5394] | 698 | num_written = 0; |
|---|
| [5428] | 699 | num_read = 0; |
|---|
| [5280] | 700 | |
|---|
| 701 | for (i=0; i<input_length; i++) { |
|---|
| [5373] | 702 | output[i] = invert_bits ? (~input[i]) & 0x01 : input[i]; |
|---|
| [5280] | 703 | num_subheader_bits_read++; |
|---|
| [5394] | 704 | num_written++; |
|---|
| [5428] | 705 | num_read++; |
|---|
| [5280] | 706 | |
|---|
| 707 | if ( num_subheader_bits_read == packet_subheader_length ) { |
|---|
| [5373] | 708 | // subheader data have been extracted |
|---|
| [5280] | 709 | num_packet_bits_read = 0; |
|---|
| 710 | return true; |
|---|
| 711 | } |
|---|
| 712 | } |
|---|
| [5281] | 713 | |
|---|
| 714 | return false; |
|---|
| [5280] | 715 | } |
|---|
| 716 | |
|---|
| [5374] | 717 | // |
|---|
| [5416] | 718 | bool PacketDecoder::DecodeSubheader( |
|---|
| [5374] | 719 | char * input, |
|---|
| 720 | unsigned int input_length) |
|---|
| 721 | { |
|---|
| [5419] | 722 | ///\todo use function pointer instead of switch statement |
|---|
| [5374] | 723 | |
|---|
| 724 | switch (packet_type) { |
|---|
| 725 | case PACKET_RAW_400: |
|---|
| [5419] | 726 | return PacketDecoder::DecodeSubheader_PACKET_RAW_400(input, input_length); |
|---|
| [5489] | 727 | case PACKET_RS_512: |
|---|
| 728 | return PacketDecoder::DecodeSubheader_PACKET_RS_512(input, input_length); |
|---|
| [5419] | 729 | default:; |
|---|
| 730 | } |
|---|
| [5374] | 731 | |
|---|
| [5419] | 732 | return true; |
|---|
| 733 | } |
|---|
| [5374] | 734 | |
|---|
| [5419] | 735 | // |
|---|
| 736 | bool PacketDecoder::DecodeSubheader_PACKET_RAW_400( |
|---|
| 737 | char * input, |
|---|
| 738 | unsigned int input_length) |
|---|
| 739 | { |
|---|
| 740 | ///\todo use reed-solomon codec to decode subheader data |
|---|
| 741 | packet_id = 0; |
|---|
| 742 | for (unsigned int i=0; i<3; i++) { |
|---|
| 743 | // shift 7 bits into buffer |
|---|
| 744 | for (unsigned int j=0; j<PN_CONTROL_CODE_LENGTH; j++) { |
|---|
| 745 | binary_sequence_push( pn_control_buffer, input[j+i*PN_CONTROL_CODE_LENGTH] & 0x01 ); |
|---|
| [5374] | 746 | } |
|---|
| [5419] | 747 | |
|---|
| 748 | rxy = binary_sequence_correlate( pn_control_buffer, pn_control_code ); |
|---|
| 749 | |
|---|
| 750 | packet_id <<= 1; |
|---|
| 751 | packet_id |= ( rxy > 0 ) ? 0x01 : 0x00; |
|---|
| [5374] | 752 | } |
|---|
| [5380] | 753 | return true; |
|---|
| [5374] | 754 | } |
|---|
| 755 | |
|---|
| [5489] | 756 | bool PacketDecoder::DecodeSubheader_PACKET_RS_512( |
|---|
| 757 | char * input, |
|---|
| 758 | unsigned int input_length) |
|---|
| 759 | { |
|---|
| 760 | unsigned int nr; |
|---|
| 761 | unsigned int nw; |
|---|
| 762 | |
|---|
| 763 | // 1. pack 210 bits into 35 6-bit symbols to buf2 |
|---|
| 764 | SigProc::repack_bytes(input, 1, 210, buf2, 6, buf_len, &nw); |
|---|
| 765 | |
|---|
| 766 | // 2. use RS 6-bit (63,55) code, punctured to (35,27) |
|---|
| 767 | int symsize = 6; |
|---|
| 768 | int npad = 28; |
|---|
| 769 | int nn = (1<<symsize)-1-npad; // 63-28 = 35 |
|---|
| 770 | int nroots = 8; |
|---|
| 771 | int kk = nn-nroots; // 35-8 = 27 |
|---|
| 772 | void *rs; |
|---|
| 773 | rs = init_rs_char(symsize,0x43,1,1,nroots,0); |
|---|
| 774 | int nerrors(0); |
|---|
| 775 | nerrors = decode_rs_char(rs, (unsigned char*) buf2, 0, 0); |
|---|
| 776 | |
|---|
| 777 | // 3. repack 27 6-bit symbols (-2 bits) to 20 8-bit symbols |
|---|
| 778 | SigProc::repack_bytes(buf2, 6, 27, buf1, 2, buf_len, &nw); |
|---|
| 779 | printf("decode, unpack: nw = %d (should be 81)\n", nw); |
|---|
| 780 | SigProc::repack_bytes(buf1, 2, 80, buf2, 8, buf_len, &nw); |
|---|
| 781 | printf("decode, unpack: nw = %d (should be 20)\n", nw); |
|---|
| 782 | |
|---|
| 783 | // 4. decode and compare CRC |
|---|
| 784 | FastCrc crc(0x04c11db7); |
|---|
| 785 | for (unsigned int i=0; i<16; i++) |
|---|
| 786 | crc.PutByte( buf2[i] ); |
|---|
| 787 | UINT32 crc_code = crc.Done(); |
|---|
| [5490] | 788 | UINT32 crc_rx(0); |
|---|
| 789 | for (unsigned int i=0; i<4; i++) |
|---|
| 790 | printf("crc[%d] = %d\n", i, (unsigned char) (buf2[16+i])); |
|---|
| 791 | for (unsigned int i=0; i<4; i++) { |
|---|
| 792 | crc_rx <<= 8; |
|---|
| 793 | crc_rx |= 0xFF & (UINT32) (buf2[20-i-1]); |
|---|
| [5489] | 794 | } |
|---|
| [5490] | 795 | crc_rx = 0; |
|---|
| 796 | crc_rx |= (buf2[16] << 0); |
|---|
| 797 | crc_rx |= (buf2[17] << 8); |
|---|
| 798 | crc_rx |= (buf2[18] << 16); |
|---|
| 799 | crc_rx |= (buf2[19] << 24); |
|---|
| 800 | std::cout << "crc_rx: 0x" << std::hex << crc_rx << ", crc_code = 0x" << crc_code << std::endl; |
|---|
| 801 | if (crc_rx != crc_code) { |
|---|
| 802 | printf("ERROR! PACKET_RS_512 subheader did not pass cyclic redundancy check\n"); |
|---|
| 803 | //return false; |
|---|
| 804 | } else { |
|---|
| 805 | printf("PACKET_RS_512 subheader passed cyclic redundancy check\n"); |
|---|
| 806 | } |
|---|
| [5489] | 807 | |
|---|
| 808 | // 5. decode 16 8-bit symbols... |
|---|
| [5490] | 809 | // variable num bits |
|---|
| 810 | // ---- ---- |
|---|
| 811 | // packet_id 32 |
|---|
| 812 | // src_id 16 |
|---|
| 813 | // dst_id 16 |
|---|
| 814 | // app_id 16 |
|---|
| 815 | // port_id 16 |
|---|
| 816 | // expansion 64 |
|---|
| 817 | packet_id = 0; |
|---|
| 818 | printf("buf2[0] = %d\n", buf2[0]); |
|---|
| 819 | printf("buf2[1] = %d\n", buf2[1]); |
|---|
| 820 | printf("buf2[2] = %d\n", buf2[2]); |
|---|
| 821 | printf("buf2[3] = %d\n", buf2[3]); |
|---|
| 822 | for (unsigned int i=0; i<4; i++) { |
|---|
| 823 | packet_id <<= 8; |
|---|
| 824 | packet_id |= 0xFF & (unsigned long) (buf2[4-i-1]); |
|---|
| 825 | } |
|---|
| 826 | packet_id = 0; |
|---|
| 827 | packet_id |= (buf2[0] << 0); |
|---|
| 828 | packet_id |= (buf2[1] << 8); |
|---|
| 829 | packet_id |= (buf2[2] << 16); |
|---|
| 830 | packet_id |= (buf2[3] << 24); |
|---|
| 831 | |
|---|
| 832 | src_id = 0; |
|---|
| 833 | src_id |= buf2[5]; |
|---|
| 834 | src_id <<= 8; |
|---|
| 835 | src_id |= buf2[4]; |
|---|
| 836 | /* |
|---|
| 837 | buf1[6] = (dst_id >> 0 ) & 0x0F; |
|---|
| 838 | buf1[7] = (dst_id >> 4 ) & 0x0F; |
|---|
| 839 | |
|---|
| 840 | buf1[8] = (app_id >> 0 ) & 0x0F; |
|---|
| 841 | buf1[9] = (app_id >> 4 ) & 0x0F; |
|---|
| 842 | |
|---|
| 843 | buf1[10] = (port_id >> 0 ) & 0x0F; |
|---|
| 844 | buf1[11] = (port_id >> 4 ) & 0x0F; |
|---|
| 845 | |
|---|
| 846 | buf1[12] = 7; |
|---|
| 847 | buf1[13] = 7; |
|---|
| 848 | buf1[14] = 7; |
|---|
| 849 | buf1[15] = 7; |
|---|
| 850 | */ |
|---|
| [5489] | 851 | return true; |
|---|
| 852 | } |
|---|
| 853 | |
|---|
| [5416] | 854 | bool PacketDecoder::ExtractPacketData( |
|---|
| [5241] | 855 | char * input, |
|---|
| 856 | unsigned int input_length, |
|---|
| [5428] | 857 | unsigned int &num_read, |
|---|
| [5241] | 858 | char * output, |
|---|
| [5387] | 859 | unsigned int output_length, |
|---|
| 860 | unsigned int &num_written) |
|---|
| [5241] | 861 | { |
|---|
| [5280] | 862 | bool packet_extracted; |
|---|
| 863 | |
|---|
| 864 | if (dynamic_packet_size) { |
|---|
| 865 | packet_extracted = |
|---|
| [5428] | 866 | ExtractPacketDataDynamicLength(input, input_length, num_read, output, output_length, num_written); |
|---|
| [5280] | 867 | } else { |
|---|
| 868 | packet_extracted = |
|---|
| [5428] | 869 | ExtractPacketDataFixedLength(input, input_length, num_read, output, output_length, num_written); |
|---|
| [5280] | 870 | } |
|---|
| 871 | |
|---|
| 872 | return packet_extracted; |
|---|
| 873 | } |
|---|
| 874 | |
|---|
| [5416] | 875 | bool PacketDecoder::ExtractPacketDataDynamicLength( |
|---|
| [5280] | 876 | char * input, |
|---|
| 877 | unsigned int input_length, |
|---|
| [5428] | 878 | unsigned int &num_read, |
|---|
| [5280] | 879 | char * output, |
|---|
| [5387] | 880 | unsigned int output_length, |
|---|
| 881 | unsigned int &num_written) |
|---|
| [5280] | 882 | { |
|---|
| 883 | ///\todo look for eom code |
|---|
| 884 | |
|---|
| [5428] | 885 | num_written = 0; |
|---|
| 886 | num_read = input_length; |
|---|
| [5241] | 887 | return false; |
|---|
| 888 | } |
|---|
| 889 | |
|---|
| 890 | |
|---|
| [5416] | 891 | bool PacketDecoder::ExtractPacketDataFixedLength( |
|---|
| [5280] | 892 | char * input, |
|---|
| 893 | unsigned int input_length, |
|---|
| [5428] | 894 | unsigned int &num_read, |
|---|
| [5280] | 895 | char * output, |
|---|
| [5387] | 896 | unsigned int output_length, |
|---|
| 897 | unsigned int &num_written) |
|---|
| [5280] | 898 | { |
|---|
| 899 | unsigned int i; |
|---|
| [5428] | 900 | num_read = 0; |
|---|
| 901 | num_written = 0; |
|---|
| [5280] | 902 | |
|---|
| 903 | for (i=0; i<input_length; i++) { |
|---|
| 904 | output[i] = invert_bits ? (~input[i]) & 0x01 : input[i]; |
|---|
| 905 | num_packet_bits_read++; |
|---|
| [5428] | 906 | num_read++; |
|---|
| 907 | num_written++; |
|---|
| [5280] | 908 | |
|---|
| [5428] | 909 | if (num_packet_bits_read == packet_data_length_encoded) { |
|---|
| [5280] | 910 | // packet data have been extracted |
|---|
| [5428] | 911 | num_packet_bits_read = 0; |
|---|
| [5280] | 912 | return true; |
|---|
| 913 | } |
|---|
| 914 | } |
|---|
| 915 | |
|---|
| 916 | return false; |
|---|
| 917 | } |
|---|
| 918 | |
|---|
| 919 | |
|---|
| [5380] | 920 | // |
|---|
| [5416] | 921 | bool PacketEncoder::EncodePacketData( |
|---|
| [5373] | 922 | char * input, |
|---|
| 923 | unsigned int input_length, |
|---|
| [5428] | 924 | unsigned int &num_read, |
|---|
| [5373] | 925 | char * output, |
|---|
| [5383] | 926 | unsigned int output_length, |
|---|
| 927 | unsigned int &num_written) |
|---|
| [5373] | 928 | { |
|---|
| [5424] | 929 | bool success; |
|---|
| [5373] | 930 | |
|---|
| [5424] | 931 | // CheckBuffers(); |
|---|
| [5373] | 932 | |
|---|
| 933 | switch (packet_type) { |
|---|
| 934 | case PACKET_RAW_400: |
|---|
| [5419] | 935 | success = EncodePacketData_PACKET_RAW_400( |
|---|
| [5428] | 936 | input, input_length, num_read, output, output_length, num_written); |
|---|
| [5419] | 937 | return success; |
|---|
| [5485] | 938 | case PACKET_RS_512: |
|---|
| 939 | success = EncodePacketData_PACKET_RS_512( |
|---|
| 940 | input, input_length, num_read, output, output_length, num_written); |
|---|
| 941 | return success; |
|---|
| [5373] | 942 | default:; |
|---|
| [5419] | 943 | std::cerr << "ERROR! PacketEncoder::EncodePacketData() " << std::endl |
|---|
| [5373] | 944 | << " => Unsupported packet type: " << packet_type << std::endl; |
|---|
| 945 | throw 0; |
|---|
| 946 | } |
|---|
| [5399] | 947 | |
|---|
| 948 | return false; |
|---|
| [5373] | 949 | } |
|---|
| 950 | |
|---|
| 951 | |
|---|
| [5419] | 952 | bool PacketEncoder::EncodePacketData_PACKET_RAW_400( |
|---|
| 953 | char * input, |
|---|
| 954 | unsigned int input_length, |
|---|
| [5428] | 955 | unsigned int &num_read, |
|---|
| [5419] | 956 | char * output, |
|---|
| 957 | unsigned int output_length, |
|---|
| 958 | unsigned int &num_written) |
|---|
| 959 | { |
|---|
| 960 | // nothing to do; just copy data |
|---|
| 961 | memcpy( output, input, packet_data_length ); |
|---|
| [5428] | 962 | num_read = packet_data_length; |
|---|
| 963 | num_written = packet_data_length_encoded; |
|---|
| [5419] | 964 | return true; |
|---|
| 965 | } |
|---|
| 966 | |
|---|
| [5485] | 967 | |
|---|
| 968 | bool PacketEncoder::EncodePacketData_PACKET_RS_512( |
|---|
| 969 | char * input, |
|---|
| 970 | unsigned int input_length, |
|---|
| 971 | unsigned int &num_read, |
|---|
| 972 | char * output, |
|---|
| 973 | unsigned int output_length, |
|---|
| 974 | unsigned int &num_written) |
|---|
| 975 | { |
|---|
| 976 | unsigned int nr; |
|---|
| 977 | unsigned int nw; |
|---|
| 978 | |
|---|
| 979 | // 1. pack data into symbols |
|---|
| 980 | // 512 1-bit symbols -> 128 4-bit symbols |
|---|
| 981 | SigProc::repack_bytes(input, 1, 512, buf2, 4, buf_len, &nw); |
|---|
| 982 | |
|---|
| 983 | // 2. add crc/checksum: 16-bit checksum |
|---|
| 984 | unsigned int ones(0); |
|---|
| 985 | for (unsigned int i=0; i<128; i++) |
|---|
| 986 | ones += c_ones[(unsigned int) (buf2[i])]; |
|---|
| 987 | ones = ones % 65536; // 2^16 |
|---|
| 988 | buf2[128] = ones & 0x0F; |
|---|
| 989 | buf2[129] = (ones >> 4) & 0x0F; |
|---|
| 990 | buf2[130] = (ones >> 8) & 0x0F; |
|---|
| 991 | buf2[131] = (ones >> 12) & 0x0F; |
|---|
| 992 | |
|---|
| 993 | // 3. apply RS 4-bit (15,11) code for 12 blocks |
|---|
| 994 | // 132 4-bit symbols (uncoded) |
|---|
| 995 | // -> 180 4-bit symbols (coded) |
|---|
| 996 | int symsize = 4; |
|---|
| 997 | int nn = (1<<symsize)-1; // 15 |
|---|
| 998 | int nroots = 4; |
|---|
| 999 | int kk = nn-nroots; // 11 |
|---|
| 1000 | void *rs; |
|---|
| 1001 | rs = init_rs_char(symsize,0x13,1,1,nroots,0); |
|---|
| 1002 | nw = 0; |
|---|
| 1003 | nr = 0; |
|---|
| 1004 | for (unsigned int i=0; i<12; i++) { |
|---|
| 1005 | // copy data from buf2 to buf1 |
|---|
| [5492] | 1006 | memmove(&buf1[nw], &buf2[nr], kk); |
|---|
| [5485] | 1007 | |
|---|
| 1008 | // apply encoder |
|---|
| 1009 | encode_rs_char(rs, (unsigned char*) &buf1[nw], (unsigned char*) &buf1[nw+kk]); |
|---|
| [5492] | 1010 | nr += kk; |
|---|
| [5485] | 1011 | nw += nn; |
|---|
| 1012 | } |
|---|
| 1013 | |
|---|
| 1014 | // 4. unpack data: move 4-bit symbols from buf1 to 1-bit symbols in output |
|---|
| 1015 | SigProc::repack_bytes(buf1, 4, nw, output, 1, output_length, &num_written); |
|---|
| 1016 | num_read = 512; |
|---|
| 1017 | |
|---|
| 1018 | return true; |
|---|
| 1019 | } |
|---|
| 1020 | |
|---|
| [5380] | 1021 | // |
|---|
| [5416] | 1022 | bool PacketDecoder::DecodePacketData( |
|---|
| [5380] | 1023 | char * input, |
|---|
| 1024 | unsigned int input_length, |
|---|
| [5428] | 1025 | unsigned int &num_read, |
|---|
| [5380] | 1026 | char * output, |
|---|
| [5387] | 1027 | unsigned int output_length, |
|---|
| 1028 | unsigned int &num_written) |
|---|
| [5380] | 1029 | { |
|---|
| [5419] | 1030 | bool success; |
|---|
| 1031 | |
|---|
| [5380] | 1032 | switch (packet_type) { |
|---|
| 1033 | case PACKET_RAW_400: |
|---|
| [5419] | 1034 | success = DecodePacketData_PACKET_RAW_400( |
|---|
| [5428] | 1035 | input, input_length, num_read, output, output_length, num_written); |
|---|
| [5419] | 1036 | return success; |
|---|
| [5485] | 1037 | case PACKET_RS_512: |
|---|
| 1038 | success = DecodePacketData_PACKET_RS_512( |
|---|
| 1039 | input, input_length, num_read, output, output_length, num_written); |
|---|
| 1040 | return success; |
|---|
| [5380] | 1041 | default:; |
|---|
| [5419] | 1042 | std::cerr << "ERROR! PacketDecoder::DecodePacketData() " << std::endl |
|---|
| [5380] | 1043 | << " => Unsupported packet type: " << packet_type << std::endl; |
|---|
| 1044 | throw 0; |
|---|
| 1045 | } |
|---|
| 1046 | |
|---|
| 1047 | return false; |
|---|
| 1048 | } |
|---|
| 1049 | |
|---|
| [5419] | 1050 | bool PacketDecoder::DecodePacketData_PACKET_RAW_400( |
|---|
| 1051 | char * input, |
|---|
| 1052 | unsigned int input_length, |
|---|
| [5428] | 1053 | unsigned int &num_read, |
|---|
| [5419] | 1054 | char * output, |
|---|
| 1055 | unsigned int output_length, |
|---|
| 1056 | unsigned int &num_written) |
|---|
| 1057 | { |
|---|
| 1058 | // nothing to do; just copy data |
|---|
| 1059 | memcpy( output, input, packet_data_length ); |
|---|
| [5428] | 1060 | num_read = packet_data_length_encoded; |
|---|
| 1061 | num_written = packet_data_length; |
|---|
| [5419] | 1062 | return true; |
|---|
| 1063 | } |
|---|
| 1064 | |
|---|
| [5485] | 1065 | bool PacketDecoder::DecodePacketData_PACKET_RS_512( |
|---|
| 1066 | char * input, |
|---|
| 1067 | unsigned int input_length, |
|---|
| 1068 | unsigned int &num_read, |
|---|
| 1069 | char * output, |
|---|
| 1070 | unsigned int output_length, |
|---|
| 1071 | unsigned int &num_written) |
|---|
| 1072 | { |
|---|
| 1073 | unsigned int nr; |
|---|
| 1074 | unsigned int nw; |
|---|
| 1075 | |
|---|
| 1076 | // 1. Pack data into 4-bit symbols, put into buf2 |
|---|
| 1077 | SigProc::repack_bytes(input, 1, 720, buf2, 4, buf_len, &nw); |
|---|
| 1078 | |
|---|
| 1079 | // 2. Decode using RS 4-bit (15,11) code on 12 blocks |
|---|
| 1080 | // 180 4-bit symbols (coded) |
|---|
| 1081 | // -> 132 4-bit symbols (uncoded) |
|---|
| 1082 | int symsize = 4; |
|---|
| 1083 | int nn = (1<<symsize)-1; // 15 |
|---|
| 1084 | int nroots = 4; |
|---|
| 1085 | int kk = nn-nroots; // 11 |
|---|
| 1086 | void *rs; |
|---|
| 1087 | rs = init_rs_char(symsize,0x13,1,1,nroots,0); |
|---|
| 1088 | nw = 0; |
|---|
| 1089 | nr = 0; |
|---|
| [5492] | 1090 | int nerrors(0); |
|---|
| 1091 | int nerrors_total(0); |
|---|
| [5485] | 1092 | for (unsigned int i=0; i<12; i++) { |
|---|
| 1093 | // apply decoder (no erasure knowledge) |
|---|
| 1094 | nerrors = decode_rs_char(rs, (unsigned char*) &buf2[nr], 0, 0); |
|---|
| [5492] | 1095 | nerrors_total = nerrors_total + nerrors; |
|---|
| [5485] | 1096 | |
|---|
| 1097 | // copy data from buf2 to buf1 |
|---|
| 1098 | memmove(&buf1[nw], &buf2[nr], kk); |
|---|
| [5492] | 1099 | |
|---|
| [5485] | 1100 | nr += nn; |
|---|
| 1101 | nw += kk; |
|---|
| 1102 | } |
|---|
| 1103 | |
|---|
| 1104 | // 3. calculate and compare crc/checksum (16-bit) |
|---|
| 1105 | unsigned int checksum(0); |
|---|
| 1106 | // read four 4-bit symbols from end of buffer |
|---|
| 1107 | for (unsigned int i=0; i<4; i++) { |
|---|
| 1108 | checksum <<= 4; |
|---|
| [5492] | 1109 | checksum |= buf1[nw-i-1]; |
|---|
| [5485] | 1110 | } |
|---|
| 1111 | unsigned int ones(0); |
|---|
| 1112 | for (unsigned int i=0; i<128; i++) |
|---|
| 1113 | ones += c_ones[(unsigned int) (buf1[i])]; |
|---|
| [5492] | 1114 | //printf("checksum: %d, ones: %d\n", checksum, ones); |
|---|
| [5485] | 1115 | |
|---|
| 1116 | // 4. unpack data: move 4-bit symbols from buf1 to 1-bit symbols in output |
|---|
| [5492] | 1117 | SigProc::repack_bytes(buf1, 4, nw-4, output, 1, output_length, &num_written); |
|---|
| 1118 | num_read = 720; |
|---|
| [5485] | 1119 | |
|---|
| 1120 | } |
|---|
| 1121 | |
|---|