| 461 | } |
| 462 | |
| 463 | FL_OPTIMIZE_FUNCTION |
| 464 | void wave8Untranspose_16(const u8 (&FL_RESTRICT_PARAM transposed)[16 * sizeof(Wave8Byte)], |
| 465 | u8 (&FL_RESTRICT_PARAM output)[16 * sizeof(Wave8Byte)]) { |
| 466 | // Reverse the 16-lane transposition |
| 467 | // Input: 128 bytes of interleaved data (16 bytes per symbol, 8 symbols) |
| 468 | // Output: 16 Wave8Byte structures (128 bytes total, de-interleaved) |
| 469 | |
| 470 | Wave8Byte lane_waves[16]; |
| 471 | |
| 472 | // Process each of the 8 symbols |
| 473 | for (int symbol_idx = 0; symbol_idx < 8; symbol_idx++) { |
| 474 | u8 lane_bytes[16] = {0}; |
| 475 | |
| 476 | // Process 8 pulses (16 bytes total: 2 bytes per pulse) |
| 477 | for (int pulse_idx = 0; pulse_idx < 8; pulse_idx++) { |
| 478 | int pulse_bit = 7 - pulse_idx; |
| 479 | |
| 480 | // Read 16-bit word for this pulse |
| 481 | int input_offset = symbol_idx * 16 + pulse_idx * 2; |
| 482 | u16 input_word = (u16)transposed[input_offset] | |
| 483 | ((u16)transposed[input_offset + 1] << 8); |
| 484 | |
| 485 | // De-interleave 16 lanes from this word |
| 486 | // Bit layout: [L15, L14, L13, ..., L1, L0] |
| 487 | for (int lane = 0; lane < 16; lane++) { |
| 488 | // Extract bit for this lane (lane 0 = LSB, lane 15 = MSB) |
| 489 | u8 pulse = (input_word >> lane) & 1; |
| 490 | |
| 491 | // Reconstruct lane byte |
| 492 | lane_bytes[lane] |= (pulse << pulse_bit); |
| 493 | } |
| 494 | } |
| 495 | |
| 496 | // Store de-interleaved bytes |
| 497 | for (int lane = 0; lane < 16; lane++) { |
| 498 | lane_waves[lane].symbols[symbol_idx].data = lane_bytes[lane]; |
| 499 | } |
| 500 | } |
| 501 | |
| 502 | // Copy de-interleaved data to output |
| 503 | for (int lane = 0; lane < 16; lane++) { |
| 504 | fl::isr::memcpy(output + lane * sizeof(Wave8Byte), &lane_waves[lane], sizeof(Wave8Byte)); |
| 505 | } |
| 506 | } |
| 507 | |
| 508 | } // namespace fl |
| 509 |
no test coverage detected