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