dat parsing

 avatar
unknown
plain_text
a year ago
17 kB
36
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/stat.h>
#include "share/l1_api.h"
#include "config.h"

// Function declarations
int deserializeL1ConfigRequest(const char* filePath, L1ConfigRequest_t* config);
int printL1ConfigToFile(const L1ConfigRequest_t* config, const char* outputPath);

/**
 * @brief Deserializes L1ConfigRequest_t from binary data file
 * 
 * This function properly parses the .dat file and creates the structure that
 * ConfigReqParams expects. The key insight is that the .dat file already contains
 * data in the exact format that ConfigReqParams produces, so we need to treat 
 * the payload as the input to ConfigReqParams in reverse.
 * 
 * @param filePath Path to the .dat file
 * @param config Pointer to L1ConfigRequest_t structure to fill
 * @return 0 on success, -1 on error
 */
int deserializeL1ConfigRequest(const char* filePath, L1ConfigRequest_t* config) {
    FILE* file;
    struct stat st;
    uint8_t* buffer;
    size_t fileSize;

    if (!filePath || !config) {
        printf("ERROR: Invalid parameters\n");
        return -1;
    }

    // Open binary file
    file = fopen(filePath, "rb");
    if (!file) {
        printf("ERROR: Cannot open file %s\n", filePath);
        return -1;
    }

    // Get file size
    if (stat(filePath, &st) != 0) {
        printf("ERROR: Cannot get file size\n");
        fclose(file);
        return -1;
    }
    fileSize = st.st_size;

    // Allocate buffer for entire file
    buffer = (uint8_t*)malloc(fileSize);
    if (!buffer) {
        printf("ERROR: Memory allocation failed\n");
        fclose(file);
        return -1;
    }

    // Read entire file
    if (fread(buffer, 1, fileSize, file) != fileSize) {
        printf("ERROR: Failed to read file\n");
        free(buffer);
        fclose(file);
        return -1;
    }
    fclose(file);

    printf("INFO: Deserializing %zu bytes from %s\n", fileSize, filePath);

    // Parse header
    if (fileSize < sizeof(L1GeneralMsgHdr_t)) {
        printf("ERROR: File too small for header\n");
        free(buffer);
        return -1;
    }
    
    L1GeneralMsgHdr_t* header = (L1GeneralMsgHdr_t*)buffer;
    uint8_t* payloadStart = buffer + sizeof(L1GeneralMsgHdr_t);
    size_t payloadSize = fileSize - sizeof(L1GeneralMsgHdr_t);
    
    printf("INFO: Message Header:\n");
    printf("  msgId: 0x%08x (%s)\n", header->msgId, 
           header->msgId == 2 ? "CONFIG.request" : "Unknown");
    printf("  msgSize: 0x%08x (%u bytes)\n", header->msgSize, header->msgSize);
    printf("  Payload size: %zu bytes\n", payloadSize);

    // Initialize config to zero
    memset(config, 0, sizeof(L1ConfigRequest_t));

    // Parse the basic fixed structures from payload
    uint32_t offset = 0;
    
    // Parse CarriConfig
    if (offset + sizeof(L1CarriConfigInfo_t) > payloadSize) {
        printf("ERROR: Insufficient data for CarriConfig\n");
        free(buffer);
        return -1;
    }
    memcpy(&config->CarriConfig, payloadStart + offset, sizeof(L1CarriConfigInfo_t));
    offset += sizeof(L1CarriConfigInfo_t);
    
    // Parse CellConfig
    if (offset + sizeof(L1CellConfigInfo_t) > payloadSize) {
        printf("ERROR: Insufficient data for CellConfig\n");
        free(buffer);
        return -1;
    }
    memcpy(&config->CellConfig, payloadStart + offset, sizeof(L1CellConfigInfo_t));
    offset += sizeof(L1CellConfigInfo_t);
    
    // Parse SSBConfig
    if (offset + sizeof(L1SsbConfigInfo_t) > payloadSize) {
        printf("ERROR: Insufficient data for SSBConfig\n");
        free(buffer);
        return -1;
    }
    memcpy(&config->SSBConfig, payloadStart + offset, sizeof(L1SsbConfigInfo_t));
    offset += sizeof(L1SsbConfigInfo_t);
    
    // Parse PRACHCfgInfo header
    if (offset + sizeof(uint16_t) * 2 > payloadSize) {
        printf("ERROR: Insufficient data for PRACH header\n");
        free(buffer);
        return -1;
    }
    config->PRACHCfgInfo.numPrachConfigurations = *(uint16_t*)(payloadStart + offset);
    offset += 4; // Skip the variable array for now, just get the count
    
    // Parse SSBtableInfo
    if (offset + sizeof(L1SsbTableConfigInfo_t) > payloadSize) {
        printf("ERROR: Insufficient data for SSBtableInfo\n");
        free(buffer);
        return -1;
    }
    memcpy(&config->SSBtableInfo, payloadStart + offset, sizeof(L1SsbTableConfigInfo_t));
    offset += sizeof(L1SsbTableConfigInfo_t);
    
    // Parse TDDtableInfo
    if (offset + sizeof(L1TddTableConfigInfo_t) > payloadSize) {
        printf("ERROR: Insufficient data for TDDtableInfo\n");
        free(buffer);
        return -1;
    }
    memcpy(&config->TDDtableInfo, payloadStart + offset, sizeof(L1TddTableConfigInfo_t));
    offset += sizeof(L1TddTableConfigInfo_t);
    
    // Parse MeasurementCfgInfo
    if (offset + sizeof(L1MeasurementConfigInfo_t) > payloadSize) {
        printf("ERROR: Insufficient data for MeasurementCfgInfo\n");
        free(buffer);
        return -1;
    }
    memcpy(&config->MeasurementCfgInfo, payloadStart + offset, sizeof(L1MeasurementConfigInfo_t));
    offset += sizeof(L1MeasurementConfigInfo_t);
    
    // Parse UciConfigurationInfo header
    if (offset + 4 <= payloadSize) {
        config->UciConfigurationInfo.numUci2Maps = *(uint16_t*)(payloadStart + offset);
        offset += 4; // Skip variable array for now
    }
    
    // Parse PrbSym header  
    if (offset + 4 <= payloadSize) {
        config->PrbSymol.numberOfPrbSymbRateMatchPatterns = *(uint8_t*)(payloadStart + offset);
        config->PrbSymol.numCoresetRmPatterns = *(uint8_t*)(payloadStart + offset + 1);
        offset += 4; // Skip variable arrays for now
    }
    
    // Parse PucchSSConfig header
    if (offset + 4 <= payloadSize) {
        config->PucchSSConfig.numUlBwpIds = *(uint8_t*)(payloadStart + offset);
        offset += 4; // Skip variable array for now
    }
    
    // Parse PdschConfig
    if (offset + sizeof(L1PdschConfig_t) > payloadSize) {
        printf("WARNING: Insufficient data for PdschConfig\n");
    } else {
        memcpy(&config->PdschConfig, payloadStart + offset, sizeof(L1PdschConfig_t));
        offset += sizeof(L1PdschConfig_t);
    }
    
    // Parse DBTInfo header
    if (offset + 4 <= payloadSize) {
        config->DBTInfo.numDigBeams = *(uint16_t*)(payloadStart + offset);
        config->DBTInfo.numBasebandPorts = *(uint16_t*)(payloadStart + offset + 2);
        offset += 4; // Skip variable arrays for now
    }
    
    // Parse PMInfo header
    if (offset + 4 <= payloadSize) {
        config->PMInfo.numPMTables = *(uint16_t*)(payloadStart + offset);
        offset += 4; // Skip variable arrays for now
    }
    
    printf("INFO: Parsed all available structures (%u bytes)\n", offset);
    printf("INFO: CarriConfig - dlFreq: 0x%08x, ulFreq: 0x%08x\n", 
           config->CarriConfig.dlFrequency, config->CarriConfig.ulFrequency);
    printf("INFO: CellConfig - phyCellId: %u, FrameDuplexType: %u\n", 
           config->CellConfig.phyCellId, config->CellConfig.FrameDuplexType);
    printf("INFO: PRACH numConfigurations: %u\n", config->PRACHCfgInfo.numPrachConfigurations);
    printf("INFO: UCI numUci2Maps: %u\n", config->UciConfigurationInfo.numUci2Maps);
    printf("INFO: PrbSym numPatterns: %u, numCoresets: %u\n", 
           config->PrbSymol.numberOfPrbSymbRateMatchPatterns, config->PrbSymol.numCoresetRmPatterns);
    printf("INFO: DBT numDigBeams: %u, numBasebandPorts: %u\n", 
           config->DBTInfo.numDigBeams, config->DBTInfo.numBasebandPorts);
    printf("INFO: PM numTables: %u\n", config->PMInfo.numPMTables);

    free(buffer);
    return 0;
}

/**
 * @brief Print L1ConfigRequest_t data to a readable text file
 * 
 * This function outputs all the parsed configuration data in a human-readable format.
 */
int printL1ConfigToFile(const L1ConfigRequest_t* config, const char* outputPath) {
    FILE* file;
    
    if (!config || !outputPath) {
        printf("ERROR: Invalid parameters for file output\n");
        return -1;
    }
    
    file = fopen(outputPath, "w");
    if (!file) {
        printf("ERROR: Cannot create output file %s\n", outputPath);
        return -1;
    }
    
    fprintf(file, "===== L1 CONFIG REQUEST PARSED DATA =====\n\n");
    
    // Print CarriConfig
    fprintf(file, "1. CARRIER CONFIGURATION (L1CarriConfigInfo_t):\n");
    fprintf(file, "  dlFrequency: 0x%08x (%u Hz)\n", config->CarriConfig.dlFrequency, config->CarriConfig.dlFrequency);
    fprintf(file, "  ulFrequency: 0x%08x (%u Hz)\n", config->CarriConfig.ulFrequency, config->CarriConfig.ulFrequency);
    fprintf(file, "  dlBandwidth: %u\n", config->CarriConfig.dlBandwidth);
    fprintf(file, "  ulBandwidth: %u\n", config->CarriConfig.ulBandwidth);
    fprintf(file, "  dlCarrierOffset: [");
    for (int i = 0; i < NUM_EROLOGIES; i++) {
        fprintf(file, "%u%s", config->CarriConfig.dlCarrierOffset[i], i < NUM_EROLOGIES-1 ? ", " : "");
    }
    fprintf(file, "]\n");
    fprintf(file, "  ulCarrierOffset: [");
    for (int i = 0; i < NUM_EROLOGIES; i++) {
        fprintf(file, "%u%s", config->CarriConfig.ulCarrierOffset[i], i < NUM_EROLOGIES-1 ? ", " : "");
    }
    fprintf(file, "]\n");
    fprintf(file, "  dlGridSize: [");
    for (int i = 0; i < NUM_EROLOGIES; i++) {
        fprintf(file, "%u%s", config->CarriConfig.dlGridSize[i], i < NUM_EROLOGIES-1 ? ", " : "");
    }
    fprintf(file, "]\n");
    fprintf(file, "  ulGridSize: [");
    for (int i = 0; i < NUM_EROLOGIES; i++) {
        fprintf(file, "%u%s", config->CarriConfig.ulGridSize[i], i < NUM_EROLOGIES-1 ? ", " : "");
    }
    fprintf(file, "]\n");
    fprintf(file, "  numTxAnt: %u\n", config->CarriConfig.numTxAnt);
    fprintf(file, "  numRxAnt: %u\n", config->CarriConfig.numRxAnt);
    fprintf(file, "  FrequencyShift7p5KHz: %u\n", config->CarriConfig.FrequencyShift7p5KHz);
    fprintf(file, "  ulTimingAdvance: %u\n", config->CarriConfig.ulTimingAdvance);
    fprintf(file, "  frameOffset: %u\n", config->CarriConfig.frameOffset);
    fprintf(file, "\n");
    
    // Print CellConfig
    fprintf(file, "2. CELL CONFIGURATION (L1CellConfigInfo_t):\n");
    fprintf(file, "  phyCellId: %u\n", config->CellConfig.phyCellId);
    fprintf(file, "  FrameDuplexType: %u (%s)\n", config->CellConfig.FrameDuplexType,
            config->CellConfig.FrameDuplexType == 0 ? "FDD" : "TDD");
    fprintf(file, "  rev0: %u\n", config->CellConfig.rev0);
    fprintf(file, "\n");
    
    // Print SSBConfig
    fprintf(file, "3. SSB CONFIGURATION (L1SsbConfigInfo_t):\n");
    fprintf(file, "  ssPbchBlockPowerScaling: %d\n", config->SSBConfig.ssPbchBlockPowerScaling);
    fprintf(file, "  bchPayloadFlag: %u\n", config->SSBConfig.bchPayloadFlag);
    fprintf(file, "  rev0: %u\n", config->SSBConfig.rev0);
    fprintf(file, "\n");
    
    // Print PRACH Config
    fprintf(file, "4. PRACH CONFIGURATION (L1PrachConfigInfo_t):\n");
    fprintf(file, "  numPrachConfigurations: %u\n", config->PRACHCfgInfo.numPrachConfigurations);
    fprintf(file, "  [Variable-size arrays not fully parsed]\n");
    fprintf(file, "\n");
    
    // Print SSB Table Config
    fprintf(file, "5. SSB TABLE CONFIGURATION (L1SsbTableConfigInfo_t):\n");
    fprintf(file, "  ssbConfigIndex: %u\n", config->SSBtableInfo.ssbConfigIndex);
    fprintf(file, "  ssbOffsetPointA: %u\n", config->SSBtableInfo.ssbOffsetPointA);
    fprintf(file, "  betaPssProfileSSS: %d\n", config->SSBtableInfo.betaPssProfileSSS);
    fprintf(file, "  ssbPeriod: %u\n", config->SSBtableInfo.ssbPeriod);
    fprintf(file, "  ssbSubcarrierOffset: %u\n", config->SSBtableInfo.ssbSubcarrierOffset);
    fprintf(file, "  Case: %u\n", config->SSBtableInfo.Case);
    fprintf(file, "  subcarrierSpacing: %u\n", config->SSBtableInfo.subcarrierSpacing);
    fprintf(file, "  subCarrierSpacingCommon: %u\n", config->SSBtableInfo.subCarrierSpacingCommon);
    fprintf(file, "  lMax: %u\n", config->SSBtableInfo.lMax);
    fprintf(file, "  rmsiPresence: %u\n", config->SSBtableInfo.rmsiPresence);
    fprintf(file, "  addSsbSubcarrierOffset: [%u, %u, %u]\n", 
            config->SSBtableInfo.addSsbSubcarrierOffset[0],
            config->SSBtableInfo.addSsbSubcarrierOffset[1],
            config->SSBtableInfo.addSsbSubcarrierOffset[2]);
    fprintf(file, "  addSsbOffsetPointA: [%u, %u, %u]\n", 
            config->SSBtableInfo.addSsbOffsetPointA[0],
            config->SSBtableInfo.addSsbOffsetPointA[1],
            config->SSBtableInfo.addSsbOffsetPointA[2]);
    fprintf(file, "  BeamId: [");
    for (int i = 0; i < NUM_SSB_BEAM_ID && i < 16; i++) { // Show first 16 beam IDs
        fprintf(file, "0x%02x%s", config->SSBtableInfo.BeamId[i], i < 15 ? ", " : "");
    }
    if (NUM_SSB_BEAM_ID > 16) fprintf(file, "...");
    fprintf(file, "]\n");
    fprintf(file, "\n");
    
    // Print TDD Table Config
    fprintf(file, "6. TDD TABLE CONFIGURATION (L1TddTableConfigInfo_t):\n");
    fprintf(file, "  TddPeriod: %u\n", config->TDDtableInfo.TddPeriod);
    fprintf(file, "  rev0: %u\n", config->TDDtableInfo.rev0);
    fprintf(file, "  rev1: %u\n", config->TDDtableInfo.rev1);
    fprintf(file, "  SlotConfig: [");
    for (int i = 0; i < MAX_SLOT_CFG_NUM && i < 16; i++) { // Show first 16 slot configs
        fprintf(file, "0x%02x%s", config->TDDtableInfo.SlotConfig[i], i < 15 ? ", " : "");
    }
    if (MAX_SLOT_CFG_NUM > 16) fprintf(file, "...");
    fprintf(file, "]\n");
    fprintf(file, "\n");
    
    // Print Measurement Config
    fprintf(file, "7. MEASUREMENT CONFIGURATION (L1MeasurementConfigInfo_t):\n");
    fprintf(file, "  RssiMeasurement: %u\n", config->MeasurementCfgInfo.RssiMeasurement);
    fprintf(file, "  RsrpMeasurement: %u\n", config->MeasurementCfgInfo.RsrpMeasurement);
    fprintf(file, "  rev: %u\n", config->MeasurementCfgInfo.rev);
    fprintf(file, "\n");
    
    // Print UCI Configuration
    fprintf(file, "8. UCI CONFIGURATION (L1UciConfigurationInfo_t):\n");
    fprintf(file, "  numUci2Maps: %u\n", config->UciConfigurationInfo.numUci2Maps);
    fprintf(file, "  [Variable-size arrays not fully parsed]\n");
    fprintf(file, "\n");
    
    // Print PrbSym Configuration
    fprintf(file, "9. PRB SYMBOL CONFIGURATION (L1PrbSym_t):\n");
    fprintf(file, "  numberOfPrbSymbRateMatchPatterns: %u\n", config->PrbSymol.numberOfPrbSymbRateMatchPatterns);
    fprintf(file, "  numCoresetRmPatterns: %u\n", config->PrbSymol.numCoresetRmPatterns);
    fprintf(file, "  [Variable-size arrays not fully parsed]\n");
    fprintf(file, "\n");
    
    // Print PUCCH SS Config
    fprintf(file, "10. PUCCH SS CONFIGURATION (L1PucchSSConfig_t):\n");
    fprintf(file, "   numUlBwpIds: %u\n", config->PucchSSConfig.numUlBwpIds);
    fprintf(file, "   [Variable-size arrays not fully parsed]\n");
    fprintf(file, "\n");
    
    // Print PDSCH Config
    fprintf(file, "11. PDSCH CONFIGURATION (L1PdschConfig_t):\n");
    fprintf(file, "   pdschCbgScheme: %u\n", config->PdschConfig.pdschCbgScheme);
    fprintf(file, "   rev0: %u\n", config->PdschConfig.rev0);
    fprintf(file, "   rev1: %u\n", config->PdschConfig.rev1);
    fprintf(file, "\n");
    
    // Print DBT Configuration
    fprintf(file, "12. DBT CONFIGURATION (L1DBTConfigInfo_t):\n");
    fprintf(file, "   numDigBeams: %u\n", config->DBTInfo.numDigBeams);
    fprintf(file, "   numBasebandPorts: %u\n", config->DBTInfo.numBasebandPorts);
    fprintf(file, "   [Variable-size arrays not fully parsed]\n");
    fprintf(file, "\n");
    
    // Print PM Configuration
    fprintf(file, "13. PM CONFIGURATION (L1PMCfgTableInfo_t):\n");
    fprintf(file, "   numPMTables: %u\n", config->PMInfo.numPMTables);
    fprintf(file, "   [Variable-size arrays not fully parsed]\n");
    fprintf(file, "\n");
    
    fprintf(file, "===== END OF PARSED DATA =====\n");
    
    fclose(file);
    printf("INFO: Configuration data written to %s\n", outputPath);
    
    return 0;
}

int main(int argc, char* argv[]) {
    L1ConfigRequest_t config;
    const char* configFile;
    
    if (argc != 2) {
        printf("Usage: %s <config_file.dat>\n", argv[0]);
        printf("Example: %s src/test_CPHY/test_CPHY.t100.1.1/config/fapi_config_cell0_request.dat\n", argv[0]);
        return 1;
    }
    
    configFile = argv[1];
    
    printf("=== L1 Config Deserializer ===\n");
    printf("Input file: %s\n", configFile);
    
    if (deserializeL1ConfigRequest(configFile, &config) == 0) {
        printf("\n=== Deserialization SUCCESS ===\n");
        
        // Print configuration data to a readable file
        printf("\n=== Writing Parsed Data to Text File ===\n");
        const char* outputFile = "config_parsed.txt";
        
        if (printL1ConfigToFile(&config, outputFile) == 0) {
            printf("✅ SUCCESS: Configuration data written to %s\n", outputFile);
            printf("✅ All available fields have been parsed and displayed\n");
        } else {
            printf("❌ Failed to write configuration data to text file\n");
        }
        
    } else {
        printf("\n=== Deserialization FAILED ===\n");
        return 1;
    }
    
    return 0;
}
Editor is loading...
Leave a Comment