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 解码结果与代码不一致(DN504 FEC 实现)

Guru**** 2578945 points
Other Parts Discussed in Thread: CC1312R, CC1101, CC1352P

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/1121452/cc1352p-dn507-fec-decoding-results-are-inconsistent-with-the-code-dn504-fec-implementation

器件型号:CC1352P
主题中讨论的其他器件:CC1312RCC1101

大家好、

以下是客户提出的问题、可能需要您的帮助:

以 DN504 FEC 实现为基准、客户 FEC 使用以下数据对源数据(0x01 0x02 0x03 0x04 0x05)进行编码:4C F0 30 10 C8 7C C3 23 40 34 7C E3。

并引用了 DN507 FEC 解码、以解码上述编码数据并获得以下数据: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;
        }
		
		// Running here, the rxPacket contents are 01 02 73 04 05 (hex)

        // 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;
     }
    

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Siri、

    感谢您的支持。

    客户已根据您提供的代码在 CC1352P 上运行 fectDecode、但仍有0x01 0x02 0x73 0x04 0x05、这不是预期的那样。

    在该方案中,修改了两个位置:

    1) rf_runCmd ()被屏蔽;

    2) 2)强制数组数据包的初始值为0x4C、0xF0、0x30、0x10、0xC80x7C、 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;
    }

    开发环境如下:

      Code Composer Studio 版本:9.2.0.00013
       2. SimpleLink CC13x2 26x2 SDK 3.20.0.68
       编译器版本:TI v18.12.3.LTS

    同时将相同的代码移植到 MSP432P411R 并获取0x01 0x02 0x03 0x04 0x05。

    为什么? 项目属性的配置问题?

    谢谢、此致、

    樱桃

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,Cherry

    我肯定认为这是一个与工具相关的问题。

    在我的工作示例中、我使用 TI Clang v2.0.STS (CCS 11.20和 SDK 版本6.20)

    我使用 CCS 9.3和 TI v18.12.8.LTS 进行了测试、结果与您相同。  

    我将把这个文件传输给 CCS 团队并让他们进行评论。

    BR

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,Cherry

    我和工具团队不能直接找出问题的确切位置以及编译器之间的区别。

    我能不能问客户为什么要使用这样的 SDK 和 CCS 版本?  

    如果他们正在启动新项目、强烈建议使用最新的 SDK。

    另一种选择是尝试仅更新 CCS、然后查看问题是否消失。

    不确定我们何时能够到达其底部。

    BR

    Siri

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Siri、

    很抱歉、由于问题未得到妥善解决、因此采取了相应措施。

    SimpleLink CC13x2 26x2 SDK 和编译器版本:TI v18.12.3.LTS 上仍然存在此问题。  

    1)使用当前的开发环境(CCS、SDK、编译器)、能否解决此问题? 如果是、如何解决?

    2) 2)如果无法在当前开发环境(CCS、SDK、编译器)下解决此问题、则不会在哪个版本的开发环境中发生此问题? (MCU 必须是 CC1352P)

    谢谢、此致、

    樱桃

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我们无法找到导致这种情况的根本原因、但正如我之前所写的、我已经使用最新的 SDK (6.20)进行了测试并使用了 TI Clang  v2.0.STS (CCS 11.20) 、我没有发现任何问题。

    Siri