This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1352P: DN507 FEC Decoding 解码结果与编码(DN504 FEC Implementation)不一致

Part Number: CC1352P
Other Parts Discussed in Thread: CC1312R, CC1101,

1. 参考DN504 FEC Implementation 我们将源数据(0x01 0x02 0x03 0x04 0x05)进行FEC编码,得到:4C F0 30 10 C8 7C C3 23 40 34 7C E3;

2. 参考DN507 FEC Decoding 对上述编码数据进行解码,得到结果是:0x01 0x02 0x73 0x04 0x05与源数据不一致!

 

// NUMBER_OF_BYTES_AFTER_DECODING should be given the length of the payload + CRC (CRC is optional)
#define NUMBER_OF_BYTES_AFTER_DECODING  5
#define NUMBER_OF_BYTES_BEFORE_DECODING (4 * ((NUMBER_OF_BYTES_AFTER_DECODING / 2) + 1))

/*******************************************************************************
 * @fn:
 * @brief:
 * @para:
 * @return:
 ******************************************************************************/
void ReadRxFifo(uint8_t* rxBuf, uint16_t startAddr, uint16_t readLen)
{
    // 01 02 03 04 05
    const uint8_t rxRawData[] = {   //
            0x4C, 0xF0, 0x30, 0x10, //
            0xC8, 0x7C, 0xC3, 0x23, //
            0x40, 0x34, 0x7C, 0xE3, //
            };

    uint8_t iX;

    for (iX = 0; iX < readLen; iX++)
    {
        if (startAddr + iX >= sizeof(rxRawData))
        {
            break;
        }

        rxBuf[iX] = rxRawData[startAddr + iX];
    }
}

/*******************************************************************************
 * @fn:
 * @brief:      
 * @para:
 * @return:
 ******************************************************************************/
void main(void)
{
    unsigned short checksum;
    unsigned short nBytes;
    unsigned char *pDecData = rxPacket; // Destination for decoded data
    uint16_t total = 0;

    // Init MCU and Radio

    while (1)
    {
//        while (!packetReceived)
//            ; // Wait for packet to be received (64 bytes in the RXFIFO)
//        packetReceived = 0;

        memset(rxPacket, 0, sizeof(rxPacket));
        pDecData = rxPacket;
        // Perform de-interleaving and decoding (both done in the same function)
        fecDecode(NULL, NULL, 0); // The function needs to be called with a NULL pointer for
        // initialization before every packet to decode
        nBytes = NUMBER_OF_BYTES_AFTER_DECODING;
        total = 0;
        while (nBytes > 0)
        {
            unsigned short nBytesOut;
//            readRxFifo(RF_RXFIFO, rxBuffer, 4); // Read 4 bytes from the RXFIFO and store them in rxBuffer
            ReadRxFifo(rxBuffer, total, 4);
            nBytesOut = fecDecode(pDecData, rxBuffer, nBytes);
            total += 4;
            nBytes -= nBytesOut;
            pDecData += nBytesOut;
        }
		
		// 运行到此处,rxPacket的内容是:01 02 73 04 05 (十六进制)

        // Perform CRC check (Optional)
        {
            unsigned short i;
            nBytes = NUMBER_OF_BYTES_AFTER_DECODING;
            checksum = 0xFFFF; // Init value for CRC calculation
            for (i = 0; i < nBytes; i++)
                checksum = calcCRC(rxPacket[i], checksum);
            if (!checksum)
            {
                // Do something to indicate that the CRC is OK
            }
        }
    }
}

  • 您好我们已收到您的问题并升级到英文论坛寻求帮助,如有答复将尽快回复您。谢谢!

  • 您好,

    工程师这边做了如下测试:使用 CC1312编码并发送了数据0x01、0x02、0x03、0x04、0x05,并使用 CC1312R 接收它们。

    可以成功实现应用手册中描述的代码,但重新编写了代码所指的读取 FIFO 的部分,因为 CC1312没有 FIFO。

    数据包已正确编码和解码,此外,还通过与 CC1101和 SmartRF Studio 通信(使能 FEC)验证了这一点:

    工程师使用 CC1312R rfPacketRX 示例作为起点。请注意,缓冲区大小经过优化,仅适合此特定数据包(5字节有效载荷、无 CRC),从而产生12字节交错数据。

    修改后的代码如下所示:

    /***** Includes *****/
    /* Standard C Libraries */
    #include <stdlib.h>
    
    /* TI Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/GPIO.h>
    
    /* Driverlib Header files */
    #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
    
    /* Board Header files */
    #include "ti_drivers_config.h"
    
    /* Application Header files */
    #include "RFQueue.h"
    #include <ti_radio_config.h>
    
    /***** Defines *****/
    
    /* Packet RX Configuration */
    #define MAX_LENGTH             12 //(Number of bytes received when transmitting payload of 5 bytes)
    #define DATA_ENTRY_HEADER_SIZE 8  /* Constant header size of a Generic Data Entry */
    #define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES     0
    
    
    
    /***** Prototypes *****/
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    static uint16_t culCalcCRC(uint8_t crcData, uint16_t crcReg);
    
    /***** Variable declarations *****/
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    /* Buffer which contains all Data Entries for receiving data.
     * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      MAX_LENGTH,
                                                      NUM_APPENDED_BYTES)];
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      MAX_LENGTH,
                                                      NUM_APPENDED_BYTES)];
    #elif defined(__GNUC__)
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                      MAX_LENGTH,
                                                      NUM_APPENDED_BYTES)]
                                                      __attribute__((aligned(4)));
    #else
    #error This compiler is not supported.
    #endif
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    static uint8_t* packetDataPointer;
    
    uint16_t fecDecode(uint8_t *pDecData, uint8_t* pInData, uint16_t RemBytes);
    static uint8_t hammWeight(uint8_t a);
    static uint8_t min(uint8_t a, uint8_t b);
    static uint16_t calcCRC(uint8_t crcData, uint16_t crcReg);
    uint8_t hammWeight(uint8_t a);
    uint8_t min(uint8_t a, uint8_t b);
    
    static uint8_t packet[MAX_LENGTH];
    
    // The payload + CRC are 31 bytes. This way the complete packet to be received will fit in the RXFIFO
    uint8_t rxBuffer[4]; // Buffer used to hold data read from the RXFIFO (4 bytes are read at a time)
    uint8_t rxPacket[5]; // Data + CRC after being interleaved and decoded
    
    uint8_t aTrellisSourceStateLut[8][2] =
    {
         {0, 4}, // State {0,4} -> State 0
         {0, 4}, // State {0,4} -> State 1
         {1, 5}, // State {1,5} -> State 2
         {1, 5}, // State {1,5} -> State 3
         {2, 6}, // State {2,6} -> State 4
         {2, 6}, // State {2,6} -> State 5
         {3, 7}, // State {3,7} -> State 6
         {3, 7}, // State {3,7} -> State 7
    };
    
    uint8_t aTrellisTransitionOutput[8][2] =
    {
         {0, 3}, // State {0,4} -> State 0 produces {"00", "11"}
         {3, 0}, // State {0,4} -> State 1 produces {"11", "00"}
         {1, 2}, // State {1,5} -> State 2 produces {"01", "10"}
         {2, 1}, // State {1,5} -> State 3 produces {"10", "01"}
         {3, 0}, // State {2,6} -> State 4 produces {"11", "00"}
         {0, 3}, // State {2,6} -> State 5 produces {"00", "11"}
         {2, 1}, // State {3,7} -> State 6 produces {"10", "01"}
         {1, 2}, // State {3,7} -> State 7 produces {"01", "10"}
    };
    // Look-up input bit at encoder when:
    // Destination state
    uint8_t aTrellisTransitionInput[8] =
    {
         0,
         1,
         0,
         1,
         0,
         1,
         0,
         1,
    };
    
    // NUMBER_OF_BYTES_AFTER_DECODING should be given the length of the payload + CRC (CRC is optional)
    #define NUMBER_OF_BYTES_AFTER_DECODING 5
    #define NUMBER_OF_BYTES_BEFORE_DECODING (4 * ((NUMBER_OF_BYTES_AFTER_DECODING / 2) + 1))
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        GPIO_setConfig(CONFIG_GPIO_RLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
        GPIO_write(CONFIG_GPIO_RLED, CONFIG_GPIO_LED_OFF);
    
        if( RFQueue_defineQueue(&dataQueue,
                                rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while(1);
        }
    
        /* Modify CMD_PROP_RX command for application needs */
        /* Set the Data Entity queue for received data */
        RF_cmdPropRx.pQueue = &dataQueue;
        /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 0;
        /* Discard packets with CRC error from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 0;
        RF_cmdPropRx.rxConf.bIncludeHdr = 0;
        RF_cmdPropRx.rxConf.bAppendStatus = 0;
    
        RF_cmdPropRx.maxPktLen = MAX_LENGTH;
    
        RF_cmdPropRx.pktConf.bUseCrc = 0;   // Turn off CRC
        RF_cmdPropRx.pktConf.bVarLen = 0;   // Use fixed packet length mode (length is manually FEC encoded
        RF_cmdPropRx.syncWord = 0xD391D391; // CC1101 compatible Sync word
    
        /* Request access to the radio */
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        while(1)
        {
            RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
    
            {
                uint16_t nBytes;
                uint8_t *pDecData = rxPacket; // Destination for decoded data
    
                pDecData = rxPacket;
    
                // Perform de-interleaving and decoding (both done in the same function)
                fecDecode(NULL, NULL, 0); // The function needs to be called with a NULL pointer for
    
                // initialization before every packet to decode
                nBytes = NUMBER_OF_BYTES_AFTER_DECODING;
                uint8_t packetIndex = 0;
                while (nBytes > 0)
                {
                    uint16_t nBytesOut;
    
                    memcpy(rxBuffer, &packet[packetIndex], 4);
                    packetIndex += 4;
    
                    nBytesOut = fecDecode(pDecData, rxBuffer, nBytes);
                    nBytes -= nBytesOut;
                    pDecData += nBytesOut;
                }
            }
        }
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
            GPIO_toggle(CONFIG_GPIO_RLED);
    
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            packetDataPointer = (uint8_t*)(&currentDataEntry->data);
    
            /* Copy the payload + the status byte to the packet variable */
            memcpy(packet, packetDataPointer, MAX_LENGTH);
    
            RFQueue_nextEntry();
        }
    }
    
    uint16_t culCalcCRC(uint8_t crcData, uint16_t crcReg) {
        uint8_t i;
        for (i = 0; i < 8; i++)
        {
            if (((crcReg & 0x8000) >> 8) ^ (crcData & 0x80))
            {
                crcReg = (crcReg << 1) ^ 0x8005;
            }
            else
            {
                crcReg = (crcReg << 1);
            }
            crcData <<= 1;
        }
        return crcReg;
    }
    
    uint8_t hammWeight(uint8_t a)
    {
         a = ((a & 0xAA) >> 1) + (a & 0x55);
         a = ((a & 0xCC) >> 2) + (a & 0x33);
         a = ((a & 0xF0) >> 4) + (a & 0x0F);
         return a;
    }
    
    uint8_t min(uint8_t a, uint8_t b)
    {
        return (a <= b ? a : b);
    }
    
    uint16_t fecDecode(uint8_t *pDecData, uint8_t* pInData, uint16_t nRemBytes)
    {
        // Two sets of buffers (last, current) for each destination state for holding:
        static uint8_t nCost[2][8]; // Accumulated path cost
        static uint32_t aPath[2][8]; // Encoder input data (32b window)
    
        // Indices of (last, current) buffer for each iteration
        static uint8_t iLastBuf;
        static uint8_t iCurrBuf;
    
        // Number of bits in each path buffer
        static uint8_t nPathBits;
    
        // Variables used to hold # Viterbi iterations to run, # bytes output,
        // minimum cost for any destination state, bit index of input symbol
        uint8_t nIterations;
        uint16_t nOutputBytes = 0;
        uint8_t nMinCost;
        int8_t iBit = 8 - 2;
    
        // Initialize variables at start of packet (and return without doing any more)
        if (pDecData == NULL)
        {
            uint8_t n ;
            memset(nCost, 0, sizeof(nCost));
            for (n = 1; n < 8; n++)
            {
                nCost[0][n] = 100;
            }
            iLastBuf = 0;
            iCurrBuf = 1;
            nPathBits = 0;
            return 0;
        }
    
        {
            uint8_t aDeintData[4];
            int8_t iOut;
            int8_t iIn;
    
            // De-interleave received data (and change pInData to point to de-interleaved data)
            for (iOut = 0; iOut < 4; iOut++)
            {
                uint8_t dataByte = 0;
                for (iIn = 3; iIn >= 0; iIn--)
                {
                    dataByte = (dataByte << 2) | ((pInData[iIn] >>( 2 * iOut)) & 0x03);
                }
                aDeintData[iOut] = dataByte;
            }
            pInData = aDeintData;
        }
    
        // Process up to 4 bytes of de-interleaved input data, processing one encoder symbol (2b) at a time
        for (nIterations = 16; nIterations > 0; nIterations--)
        {
            uint8_t iDestState;
            uint8_t symbol = ((*pInData) >> iBit) & 0x03;
    
            // Find minimum cost so that we can normalize costs (only last iteration used)
            nMinCost = 0xFF;
    
            // Get 2b input symbol (MSB first) and do one iteration of Viterbi decoding
            if ((iBit -= 2) < 0)
            {
                iBit = 6;
                pInData++; // Update pointer to the next byte of received data
            }
    
            // For each destination state in the trellis, calculate hamming costs for both possible paths into state and
            // select the one with lowest cost.
            for (iDestState = 0; iDestState < 8; iDestState++)
            {
                uint8_t nCost0;
                uint8_t nCost1;
                uint8_t iSrcState0;
                uint8_t iSrcState1;
                uint8_t nInputBit;
    
                nInputBit = aTrellisTransitionInput[iDestState];
    
                // Calculate cost of transition from each of the two source states (cost is Hamming difference between
                // received 2b symbol and expected symbol for transition)
                iSrcState0 = aTrellisSourceStateLut[iDestState][0];
                nCost0 = nCost[iLastBuf][iSrcState0];
                nCost0 += hammWeight(symbol ^ aTrellisTransitionOutput[iDestState][0]);
    
                iSrcState1 = aTrellisSourceStateLut[iDestState][1];
                nCost1 = nCost[iLastBuf][iSrcState1];
                nCost1 += hammWeight(symbol ^ aTrellisTransitionOutput[iDestState][1]);
    
                // Select transition that gives lowest cost in destination state, copy that source state's path and add
                // new decoded bit
                if (nCost0 <= nCost1)
                {
                    nCost[iCurrBuf][iDestState] = nCost0;
                    nMinCost = min(nMinCost, nCost0);
                    aPath[iCurrBuf][iDestState] = (aPath[iLastBuf][iSrcState0] << 1) | nInputBit;
                }
                else
                {
                    nCost[iCurrBuf][iDestState] = nCost1;
                    nMinCost = min(nMinCost, nCost1);
                    aPath[iCurrBuf][iDestState] = (aPath[iLastBuf][iSrcState1] << 1) | nInputBit;
                }
            }
            nPathBits++;
    
            // If trellis history is sufficiently long, output a byte of decoded data
            if (nPathBits == 32)
            {
                *pDecData++ = (aPath[iCurrBuf][0] >> 24) & 0xFF;
                nOutputBytes++;
                nPathBits -= 8;
                nRemBytes--;
            }
    
            // After having processed 3-symbol trellis terminator, flush out remaining data
            if ((nRemBytes <= 3) && (nPathBits == ((8 * nRemBytes) + 3)))
            {
                while (nPathBits >= 8)
                {
                    *pDecData++ = (aPath[iCurrBuf][0] >> (nPathBits - 8)) & 0xFF;
                    nOutputBytes++;
                    nPathBits -= 8;
                }
                return nOutputBytes;
            }
    
            // Swap current and last buffers for next iteration
            iLastBuf = (iLastBuf + 1) % 2;
            iCurrBuf = (iCurrBuf + 1) % 2;
        }
    
        // Normalize costs so that minimum cost becomes 0
        {
            unsigned char iState;
            for (iState = 0; iState < 8; iState++)
            {
                nCost[iLastBuf][iState] -= nMinCost;
            }
        }
        return nOutputBytes;
     }

  • 您好,

          我按照您提供的代码在CC1352P上运行了一下fecDecode,得到的结果依然是:0x01 0x02 0x73 0x04 0x05,与期望值不符。

          在程序中,我修改了两个地方:

          1. 屏蔽了RF_runCmd();

          2. 将数组packet的初始值强制设为:0x4C, 0xF0, 0x30, 0x10, 0xC8, 0x7C, 0xC3, 0x23, 0x40, 0x34, 0x7C, 0xE3;

          我的调试结果如下图:

         

         我的源代码如下:

          

    /***** Includes *****/
    /* Standard C Libraries */
    #include <stdlib.h>
    
    /* TI Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/GPIO.h>
    
    /* Driverlib Header files */
    #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
    
    /* Application Header files */
    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"
    
    /***** Defines *****/
    
    /* Packet RX Configuration */
    #define MAX_LENGTH             12 //(Number of bytes received when transmitting payload of 5 bytes)
    #define DATA_ENTRY_HEADER_SIZE 8  /* Constant header size of a Generic Data Entry */
    #define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES     0
    
    /***** Prototypes *****/
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    static uint16_t culCalcCRC(uint8_t crcData, uint16_t crcReg);
    
    /***** Variable declarations *****/
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    /* Buffer which contains all Data Entries for receiving data.
     * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
    static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(
            NUM_DATA_ENTRIES, MAX_LENGTH, NUM_APPENDED_BYTES)];
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
            MAX_LENGTH,
            NUM_APPENDED_BYTES)];
    #elif defined(__GNUC__)
    static uint8_t
    rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
            MAX_LENGTH,
            NUM_APPENDED_BYTES)]
    __attribute__((aligned(4)));
    #else
    #error This compiler is not supported.
    #endif
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    static uint8_t* packetDataPointer;
    
    uint16_t fecDecode(uint8_t *pDecData, uint8_t* pInData, uint16_t RemBytes);
    static uint8_t hammWeight(uint8_t a);
    static uint8_t min(uint8_t a, uint8_t b);
    static uint16_t calcCRC(uint8_t crcData, uint16_t crcReg);
    uint8_t hammWeight(uint8_t a);
    uint8_t min(uint8_t a, uint8_t b);
    
    static uint8_t packet[MAX_LENGTH] = { 0x4C, 0xF0, 0x30, 0x10, //
                                          0xC8, 0x7C, 0xC3, 0x23, //
                                          0x40, 0x34, 0x7C, 0xE3, //
            };
    
    // The payload + CRC are 31 bytes. This way the complete packet to be received will fit in the RXFIFO
    uint8_t rxBuffer[4]; // Buffer used to hold data read from the RXFIFO (4 bytes are read at a time)
    uint8_t rxPacket[5]; // Data + CRC after being interleaved and decoded
    
    uint8_t aTrellisSourceStateLut[8][2] = { { 0, 4 }, // State {0,4} -> State 0
            { 0, 4 }, // State {0,4} -> State 1
            { 1, 5 }, // State {1,5} -> State 2
            { 1, 5 }, // State {1,5} -> State 3
            { 2, 6 }, // State {2,6} -> State 4
            { 2, 6 }, // State {2,6} -> State 5
            { 3, 7 }, // State {3,7} -> State 6
            { 3, 7 }, // State {3,7} -> State 7
            };
    
    uint8_t aTrellisTransitionOutput[8][2] = { { 0, 3 }, // State {0,4} -> State 0 produces {"00", "11"}
            { 3, 0 }, // State {0,4} -> State 1 produces {"11", "00"}
            { 1, 2 }, // State {1,5} -> State 2 produces {"01", "10"}
            { 2, 1 }, // State {1,5} -> State 3 produces {"10", "01"}
            { 3, 0 }, // State {2,6} -> State 4 produces {"11", "00"}
            { 0, 3 }, // State {2,6} -> State 5 produces {"00", "11"}
            { 2, 1 }, // State {3,7} -> State 6 produces {"10", "01"}
            { 1, 2 }, // State {3,7} -> State 7 produces {"01", "10"}
            };
    // Look-up input bit at encoder when:
    // Destination state
    uint8_t aTrellisTransitionInput[8] = { 0, 1, 0, 1, 0, 1, 0, 1, };
    
    // NUMBER_OF_BYTES_AFTER_DECODING should be given the length of the payload + CRC (CRC is optional)
    #define NUMBER_OF_BYTES_AFTER_DECODING 5
    #define NUMBER_OF_BYTES_BEFORE_DECODING (4 * ((NUMBER_OF_BYTES_AFTER_DECODING / 2) + 1))
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        if (RFQueue_defineQueue(&dataQueue, rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while (1)
                ;
        }
    
        /* Modify CMD_PROP_RX command for application needs */
        /* Set the Data Entity queue for received data */
        RF_cmdPropRx.pQueue = &dataQueue;
        /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 0;
        /* Discard packets with CRC error from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 0;
        RF_cmdPropRx.rxConf.bIncludeHdr = 0;
        RF_cmdPropRx.rxConf.bAppendStatus = 0;
    
        RF_cmdPropRx.maxPktLen = MAX_LENGTH;
    
        RF_cmdPropRx.pktConf.bUseCrc = 0;   // Turn off CRC
        RF_cmdPropRx.pktConf.bVarLen = 0; // Use fixed packet length mode (length is manually FEC encoded
        RF_cmdPropRx.syncWord = 0xD391D391; // CC1101 compatible Sync word
    
        /* Request access to the radio */
        rfHandle = RF_open(&rfObject, &RF_prop,
                           (RF_RadioSetup*) &RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*) &RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        while (1)
        {
    //        RF_runCmd(rfHandle, (RF_Op*) &RF_cmdPropRx, RF_PriorityNormal,
    //                  &callback, RF_EventRxEntryDone);
    
            {
                uint16_t nBytes;
                uint8_t *pDecData = rxPacket; // Destination for decoded data
    
                pDecData = rxPacket;
    
                // Perform de-interleaving and decoding (both done in the same function)
                fecDecode(NULL, NULL, 0); // The function needs to be called with a NULL pointer for
    
                // initialization before every packet to decode
                nBytes = NUMBER_OF_BYTES_AFTER_DECODING;
                uint8_t packetIndex = 0;
                while (nBytes > 0)
                {
                    uint16_t nBytesOut;
    
                    memcpy(rxBuffer, &packet[packetIndex], 4);
                    packetIndex += 4;
    
                    nBytesOut = fecDecode(pDecData, rxBuffer, nBytes);
                    nBytes -= nBytesOut;
                    pDecData += nBytesOut;
                }
            }
        }
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            packetDataPointer = (uint8_t*) (&currentDataEntry->data);
    
            /* Copy the payload + the status byte to the packet variable */
            memcpy(packet, packetDataPointer, MAX_LENGTH);
    
            RFQueue_nextEntry();
        }
    }
    
    uint16_t culCalcCRC(uint8_t crcData, uint16_t crcReg)
    {
        uint8_t i;
        for (i = 0; i < 8; i++)
        {
            if (((crcReg & 0x8000) >> 8) ^ (crcData & 0x80))
            {
                crcReg = (crcReg << 1) ^ 0x8005;
            }
            else
            {
                crcReg = (crcReg << 1);
            }
            crcData <<= 1;
        }
        return crcReg;
    }
    
    uint8_t hammWeight(uint8_t a)
    {
        a = ((a & 0xAA) >> 1) + (a & 0x55);
        a = ((a & 0xCC) >> 2) + (a & 0x33);
        a = ((a & 0xF0) >> 4) + (a & 0x0F);
        return a;
    }
    
    uint8_t min(uint8_t a, uint8_t b)
    {
        return (a <= b ? a : b);
    }
    
    uint16_t fecDecode(uint8_t *pDecData, uint8_t* pInData, uint16_t nRemBytes)
    {
        // Two sets of buffers (last, current) for each destination state for holding:
        static uint8_t nCost[2][8]; // Accumulated path cost
        static uint32_t aPath[2][8]; // Encoder input data (32b window)
    
        // Indices of (last, current) buffer for each iteration
        static uint8_t iLastBuf;
        static uint8_t iCurrBuf;
    
        // Number of bits in each path buffer
        static uint8_t nPathBits;
    
        // Variables used to hold # Viterbi iterations to run, # bytes output,
        // minimum cost for any destination state, bit index of input symbol
        uint8_t nIterations;
        uint16_t nOutputBytes = 0;
        uint8_t nMinCost;
        int8_t iBit = 8 - 2;
    
        // Initialize variables at start of packet (and return without doing any more)
        if (pDecData == NULL)
        {
            uint8_t n;
            memset(nCost, 0, sizeof(nCost));
            for (n = 1; n < 8; n++)
            {
                nCost[0][n] = 100;
            }
            iLastBuf = 0;
            iCurrBuf = 1;
            nPathBits = 0;
            return 0;
        }
    
        {
            uint8_t aDeintData[4];
            int8_t iOut;
            int8_t iIn;
    
            // De-interleave received data (and change pInData to point to de-interleaved data)
            for (iOut = 0; iOut < 4; iOut++)
            {
                uint8_t dataByte = 0;
                for (iIn = 3; iIn >= 0; iIn--)
                {
                    dataByte = (dataByte << 2)
                            | ((pInData[iIn] >> (2 * iOut)) & 0x03);
                }
                aDeintData[iOut] = dataByte;
            }
            pInData = aDeintData;
        }
    
        // Process up to 4 bytes of de-interleaved input data, processing one encoder symbol (2b) at a time
        for (nIterations = 16; nIterations > 0; nIterations--)
        {
            uint8_t iDestState;
            uint8_t symbol = ((*pInData) >> iBit) & 0x03;
    
            // Find minimum cost so that we can normalize costs (only last iteration used)
            nMinCost = 0xFF;
    
            // Get 2b input symbol (MSB first) and do one iteration of Viterbi decoding
            if ((iBit -= 2) < 0)
            {
                iBit = 6;
                pInData++; // Update pointer to the next byte of received data
            }
    
            // For each destination state in the trellis, calculate hamming costs for both possible paths into state and
            // select the one with lowest cost.
            for (iDestState = 0; iDestState < 8; iDestState++)
            {
                uint8_t nCost0;
                uint8_t nCost1;
                uint8_t iSrcState0;
                uint8_t iSrcState1;
                uint8_t nInputBit;
    
                nInputBit = aTrellisTransitionInput[iDestState];
    
                // Calculate cost of transition from each of the two source states (cost is Hamming difference between
                // received 2b symbol and expected symbol for transition)
                iSrcState0 = aTrellisSourceStateLut[iDestState][0];
                nCost0 = nCost[iLastBuf][iSrcState0];
                nCost0 += hammWeight(
                        symbol ^ aTrellisTransitionOutput[iDestState][0]);
    
                iSrcState1 = aTrellisSourceStateLut[iDestState][1];
                nCost1 = nCost[iLastBuf][iSrcState1];
                nCost1 += hammWeight(
                        symbol ^ aTrellisTransitionOutput[iDestState][1]);
    
                // Select transition that gives lowest cost in destination state, copy that source state's path and add
                // new decoded bit
                if (nCost0 <= nCost1)
                {
                    nCost[iCurrBuf][iDestState] = nCost0;
                    nMinCost = min(nMinCost, nCost0);
                    aPath[iCurrBuf][iDestState] = (aPath[iLastBuf][iSrcState0] << 1)
                            | nInputBit;
                }
                else
                {
                    nCost[iCurrBuf][iDestState] = nCost1;
                    nMinCost = min(nMinCost, nCost1);
                    aPath[iCurrBuf][iDestState] = (aPath[iLastBuf][iSrcState1] << 1)
                            | nInputBit;
                }
            }
            nPathBits++;
    
            // If trellis history is sufficiently long, output a byte of decoded data
            if (nPathBits == 32)
            {
                *pDecData++ = (aPath[iCurrBuf][0] >> 24) & 0xFF;
                nOutputBytes++;
                nPathBits -= 8;
                nRemBytes--;
            }
    
            // After having processed 3-symbol trellis terminator, flush out remaining data
            if ((nRemBytes <= 3) && (nPathBits == ((8 * nRemBytes) + 3)))
            {
                while (nPathBits >= 8)
                {
                    *pDecData++ = (aPath[iCurrBuf][0] >> (nPathBits - 8)) & 0xFF;
                    nOutputBytes++;
                    nPathBits -= 8;
                }
                return nOutputBytes;
            }
    
            // Swap current and last buffers for next iteration
            iLastBuf = (iLastBuf + 1) % 2;
            iCurrBuf = (iCurrBuf + 1) % 2;
        }
    
        // Normalize costs so that minimum cost becomes 0
        {
            unsigned char iState;
            for (iState = 0; iState < 8; iState++)
            {
                nCost[iLastBuf][iState] -= nMinCost;
            }
        }
        return nOutputBytes;
    }
    
    

  • 我的开发环境:

    ​    1. Code Composer Studio Version: 9.2.0.00013
        2. SimpleLink CC13x2 26x2 SDK 3.20.0.68
        3. Compiler version: TI v18.12.3.LTS

  • 同样的代码,将其移植到MSP432P411R上运行,得到的结果就是:0x01 0x02 0x03 0x04 0x05。

    这是什么原因造成的?project properties的配置问题吗?

  • 我们跟进给英文论坛的工程师看下哈。

  • 您好,

    应该是与您使用什么工具相关。

    工程师给出的working example中使用的是 TI Clang v2.0.STS (CCS 11.20和 SDK 版本6.20)

    工程师也试了使用 CCS 9.3和 TI v18.12.8.LTS 进行测试,得到的结果与您相同。

    我们会再请求下CCS 团队的帮助,有新的进展尽快给到您。

  • 您好,这个问题有新的进展吗?
    另外,麻烦分享一下该问题的英文论坛帖子的链接。

  • 您好,

    您的问题并没有解决吗?因为看到您点击了“认为已解决”?

    您可以在英文论坛看下:

    e2e.ti.com/.../cc1352p-dn507-fec-decoding-results-are-inconsistent-with-the-code-dn504-fec-implementation

  • 您好,

    这个问题还没解决,在SimpleLink CC13x2 26x2 SDK 和 Compiler version: TI v18.12.3.LTS 上依然是存在这个问题的。

    我的诉求有两个:
    1. 在当前开发环境(CCS、 SDK、 Compiler )下,能否解决这个问题?如果能,该怎么做?
    2. 如果在当前开发环境(CCS、 SDK、 Compiler )下,无法解决这个问题,请高祖我什么版本的开发环境,不会出现这个问题。MCU必须是CC1352P。

    谢谢!

  • 我们跟进给工程师了,您可以多关注英文论坛的答复。

  • 抱歉我们的工程师这边也并不太清楚此问题的根本原因,但正如之前给您的答复,工程师这边使用最新的SDK (6.20) 和 TI Clang v2.0.0.STS (CCS 11.20) 进行了测试,是没有任何问题的。