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.

CC2541: CC2541 (CC2543)

Part Number: CC2541

Hi All, please whrere can I download swrc291 mini BLE broadcaster? The link "http://www.ti.com/lit/zip/swrc291" is not working.

Thanks!

  • Hi Ferdinand,

    The Mini BLE Broadcaster reference design is discontinued. For a small form factor reference design for the CC2541 you can look at: www.ti.com/.../CC2541-POSTAGE-STAMP-RD

    Regards,
    Fredrik
  • Hi Fredrik,

    Thanks for your answer and sorry for my later answer. Simply I would need to make simple BLE broadcaster (beacon) based on CC2541. The BLE Stack is very complicated for my primitive experiment and there is also osal.. I need make simple solution based on pure C language and CC controller with proprietary radio. Please exist some code example for simple BLE beacon in proprietary mode or registers value for SmartRF Studio?
    Thank you!
    Have a nice day,
    Ferdinand
  • Hi Ferdinand,

    We do not really support what you ask for, but I will help you out. Attached are the broadcaster.c and .h files from the Mini BLE Broadcaster project. These will show you how to configure the radio to transmit BLE advertisement packets.

    As there is no support for this, do not open any new E2E threads to ask questions about the content of these files. You are basically on your own here.

    Cheers,

    Fredrik

    1401.broadcaster.c
    /**************************************************************************************************
      Filename:     broadcaster.c
      Revised:      $Date: 2013-03-08 10:00:00 +0100 (Fri, 08 March 2013) $
      Revision:     $Revision: 1$
    
      Description:  Transmit ADV_NONCONN_IND broadcast packets. The broadcast mode transmit 
                    the same payload back2back on all active boradcast channels (maximum 3 
                    channels ch.37, ch38 and ch. 39). After the packet is transmitted the 
                    device will enter power mode 2 and repeat the operation at a given 
                    interval.
    
    
        note:            
    
                 
    
      Copyright 2013 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
     contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    
    
    /***********************************************************************************
    * INCLUDES
    */
    #include "ioCC2543.h"
    #include "ioCC254x_bitdef.h"
    #include "hal_types.h"
    #include "broadcaster.h"
    #include "hal_rf_broadcast.h"
    #include "prop_regs.h"
    #include "hal_sleep.h"
    #include "hal_int.h"
    #include "hal_board.h"
    #include "clock.h"
    #include "power_mode.h"
    
    #include "hal_sensor.h"
    #include "hal_acc.h"
    #include "hal_humi.h"
    #include "hal_bar.h"
    #include "string.h"
    
    #include "hal_battery.h"
    
    /******************************************************************************
    * DEFINES
    */
    #define HIST_COUNT    12
    #define AVG_COUNT      6
    
    #define CALIBRATION_DATA_ID   0x0A;
    #define MOMENTARY_DATA_ID     0xBB;
    #define HISTORICAL_DATA_1_ID  0xF1  // <-1,-3> hours
    #define HISTORICAL_DATA_2_ID  0xF2  // <-4,-6> hours
    #define HISTORICAL_DATA_3_ID  0xF3  // <-7,-9> hours
    #define HISTORICAL_DATA_4_ID  0xF4  // <-10,-12> hours
    
    #define DEVICEID 0x00; //device ID for sensor 
    
    
    /******************************************************************************
    * TYPEDEFS
    */
    
    typedef struct entry {
      uint16 hTemp;
      uint16 humi;
      uint16 bTemp;
      uint16 bar;
    } sensordata_t;
    
    
    /***********************************************************************************
    * GLOBAL VARIABLES
    */
    unsigned char AdvData[26];                  // Variable to store packet payload (AdvData).
    unsigned char addr[6];                              //array to store pseudo random addres
    unsigned char ActiveChannels;               // Channel Map for active broadcast channels.
    unsigned char FirstActiveChannel;           // Variable to set first active channel.
    static unsigned char volatile adv_event_done;        // Flag to indicate end of advertising event.
    
    
    /***********************************************************************************
    * LOCAL VARIABLES
    */
    static uint8 aData[3]; //data from accelerometer
    static uint8 hData[4]; //data from hydrometer (both temp and hum.)
    static uint8 bData[4]; //data from barometer (both temp and press.)
    static uint8 cData[16]; //cal data from barometer
    
    static uint8 AdvDataLength;
    static uint8 loopCntr = 0;
    static uint16 loopCntrHour = 3700; //must be higher than 3600 to make sure a historical sample is taken upon start-up
    static uint8 specPackage = 0;
    
    static uint16 histDataPos = 0;
    static uint8 listFilled = FALSE;
    
    static sensordata_t histData[HIST_COUNT]; // Average per hour
    
    uint32 hTempAvg  = 0;
    uint32 humiAvg   = 0;
    uint32 bTempAvg  = 0;
    uint32 barAvg    = 0;
    
    static uint8 *info = (uint8 *)(0x7800 + 0x7F4); //pointer to die-id in info page
    
    static uint8 battLevel = 100;
    
    /***********************************************************************************
    * LOCAL FUNCTIONS
    */
    
    
    /*******************************************************************************
    * @fn          creatAddress
    *
    * @brief       Function creates a pseudo random address based on die ID.
    *
    * @note        
     *
    * @return      
     */
    void createAddress(){
        
        //seed random number generator
        RNDL = info[7];
        RNDL = info[8];
        ADCCON1 |= 0x04; //clock the LFSR once
        
        for (uint8 i = 0; i < 6; i++){
            addr[i] = RNDL;
            RNDL = info[i];
            ADCCON1 |= 0x04;
        }  
    }
    
    
    /*******************************************************************************
    * @fn          broadcast
    *
    * @brief       Function enables broadcast mode.
    *
    * @note        
     *
    * @return      
     */
    void broadcast(){
    
        PRF.TASK_CONF.START_CONF = 0;    // Start each receive/transmit immediately on Command.
        
        // Use same payload for all packets.
        halRfBroadcastLoadPacket(&AdvData[0],AdvDataLength,&addr[0]);
    
        // Clear end of advertisment flag.
        adv_event_done = 0;
      
        // Set first active channel.
        halRfBroadcastSetChannel(FirstActiveChannel);
    
        // Start transmitter.
        while(RFST != 0);
        RFST = CMD_TX;
                
        // Wait until message is broadcasted on all active channels.
        while(!adv_event_done);
    
        // RESET TXFIFO.
        while(RFST != 0);
        RFST = CMD_TXFIFO_RESET;          
      
    }
    
    /*******************************************************************************
    * @fn          readSensors
    *
    * @brief       Function reads data from all sensors.
    *
    * @note        
     *
    * @return     
     */
    void readSensors(){
            //read accelerometer data
            HalAccRead(aData);
        
            
            //read humidity data
            HalHumiExecMeasurementStep(0); //start temp measurement
            
            halSleepSetSleepTimer(491); //sleep for 15 ms
            halSleepEnterPowerMode(2);
            
            HalHumiExecMeasurementStep(1); //read temp data and start humi measurement
            
            halSleepSetSleepTimer(655); //sleep for 20 ms
            halSleepEnterPowerMode(2);
            
            HalHumiExecMeasurementStep(2); //read humi data
            
            halSleepSetSleepTimer(655); //sleep for 20 ms
            halSleepEnterPowerMode(2);
            
            HalHumiReadMeasurement(hData); //load temp and humi data
    
            
            //read barometer data. Must be read twice due to alternate temp / bar reads
            HalBarStartMeasurement();
            
            halSleepSetSleepTimer(164); //sleep for 5 ms
           halSleepEnterPowerMode(2);
            
            HalBarReadMeasurement(bData);
            
            HalBarStartMeasurement();
            
            halSleepSetSleepTimer(164); //sleep for 5 ms
            halSleepEnterPowerMode(2);
            
            HalBarReadMeasurement(bData);
    }
    
    /***********************************************************************************
    * @fn          main
    *
    * @brief       Main program
    *
    * @param       void
    *
    * @return      void
    */
    void main(void) 
    {
    
        // Switch to 32 MHz XOSC
        CLKCONCMD = 0x80; //32 MHz XOSC, no clk-div
        while(CLKCONSTA & 0x40);  // Wait until system clock source has changed to HS XOSC (CLKCON.OSC = 0)
        
        //Configure I2C
        P0SEL |= 0xC0; // Set P0_7 and P0_6 as peripheral I/O (I2C)
            
        //Configure GPIOs 
        P0DIR |= BV(4) | BV(3); //P0_4 = hum-power, P0_3 = press-power
        P1DIR |= BV(4); //P1_4 = acc-power
        P1INP |= BV(3); //tri-state acc. interrupt pin  
    
        // Setup sleep timer interrupt
        STIF = 0;
        STIE = 1;
              
        // Init radio.
        halRfBroadcastInit();
        
        // Enable the radio.
        LLECTRL |= LLECTRL_LLE_EN;
        
        // Set RF isr top priority.
        IP0 = IP0_RFERR_RF_DMA;
        IP1 = IP1_RFERR_RF_DMA;
        
        // Enable RF interrupt.
        RFIRQM1 |= RFIRQM1_TASKDONE;
        IEN2 |= 0x01;
        
        // Enable global interrupt.  
        HAL_INT_ON();
        
        /* Choose active broadcast channels */
        // Manually setting first channel.
        FirstActiveChannel = BLE_BROADCAST_CHANNEL_37;
        
        // Set channel map default: all active.
        ActiveChannels = halRfBroadcastChannelMap(1,1,1);
        
        //Create individual address based on die-ID
        createAddress();
        
        //Wait to stabilize voltage after inserting battery
        halMcuWaitMs(100);
        
        // Init sensor drivers
        HalHumiInit();
        HalAccInit();
        HalBarInit();
        
        //read calibration data from barometer (only has to be done once)
        HalBarReadCalibration(cData);
        
        //////////////////////////
        //      Main  loop      //
        //////////////////////////
        
        while(1){
           
            //read all sensors
            readSensors();
            
            //check battery level
            battLevel = battMeasure();
            
            
            // Create Payload (AdvData).
            if(loopCntr < 1){
                
                //send sensor data
                AdvDataLength = 14;
                
                //ID Byte
                AdvData[0] = MOMENTARY_DATA_ID;
                
                AdvData[1] = aData[0]; //x
                AdvData[2] = aData[1]; //y
                AdvData[3] = aData[2]; //z
                
                AdvData[4] = hData[0]; //temp
                AdvData[5] = hData[1]; //temp
                AdvData[6] = hData[2]; //humi
                AdvData[7] = hData[3]; //humi
                
                AdvData[8] = bData[0]; //temp                     
                AdvData[9] = bData[1]; //temp
                AdvData[10] = bData[2]; //bar
                AdvData[11] = bData[3]; //bar
                
                AdvData[12] = battLevel; //battery level from 0% to 100%
                
                AdvData[13] = DEVICEID;
                
                loopCntr++;
            }
            else
            {   
                loopCntr = 0;
                if(specPackage == 0)
                {
                    //send calibration data
                    AdvDataLength = 1+ sizeof(cData);
                    AdvData[0] = CALIBRATION_DATA_ID;
                    
                    for(uint8 i = 0; i < sizeof(cData); i++){
                        AdvData[i+1] = cData[i];
                    }
                    // Only advance if we have historical data to send
                    if (histDataPos >= 1 || listFilled){
                      specPackage++;
                    }
                }
                else
                {
                    AdvData[0] = 0xF0 + specPackage; // Identifier for period
                    AdvDataLength = 1;
    
                    uint8 histStart = 3 * (specPackage - 1)  + 1;
                    for ( uint8 i = histStart; i < histStart + 3; ++i )
                    {
                        // Don't send if we don't have data
                        if (histDataPos >= i || listFilled)
                        {
                          uint8 pos = ( histDataPos >= i ? histDataPos : HIST_COUNT + histDataPos) - i;
                          memcpy(&AdvData[AdvDataLength], &histData[pos], sizeof(sensordata_t));
                          AdvDataLength += sizeof(sensordata_t);
                        }
                    }
    
                    // Only advance if we have more historical data to send
                    if (specPackage < 4 && ( histDataPos >= histStart + 3 || listFilled )){
                      specPackage++;
                    }
                    else{
                      specPackage = 0;
                    }
                }
            }
    
            //broadcast sensor data
            broadcast();
            
     
            // Save historical data every hour.
            if(loopCntrHour > 3600){ //approximately 1 hour has elapsed
                
                histData[histDataPos].hTemp =  BUILD_UINT16(hData[0], hData[1]);
                histData[histDataPos].humi =   BUILD_UINT16(hData[2], hData[3]);
                histData[histDataPos].bTemp =  BUILD_UINT16(bData[0], bData[1]);
                histData[histDataPos].bar =    BUILD_UINT16(bData[2], bData[3]);
                
                loopCntrHour = 0; // Reset second ticker
                histDataPos += 1;
                if (histDataPos == 13){
                    listFilled = TRUE;
                    histDataPos = 0;
                }
            }
            else{
                loopCntrHour++;
            }
            
            
            //Go to sleep        
            halSleepSetSleepTimer(32753); //sleep for 1 sec
            halSleepEnterPowerMode(2);
            
            while(CLKCONSTA & 0x40); //wait for XOSC to be stable when waking up from PM2
        }
    }
    
    
    
    /***********************************************************************************
    * @fn           RF interrupt service routine.
    *
    * @brief        Handle RF interrupt events and clear flags. The isr will also handle 
    *               the frequency hop between the active broadcast channels and will initiate 
    *               restart of transmission.
    *
    * @return       void
    */
    #pragma vector = RF_VECTOR
    __interrupt void RF_ISR() {
      
        unsigned char tx_flag   = 0;
        unsigned char channel   = 0;
        unsigned char rfirqf1;
        
        // Read the IRQ flag register only once not to miss interrupt events.
        rfirqf1 = RFIRQF1;
        
        // Check if task ends in any other way than OK. 
        if(PRF.ENDCAUSE != TASK_ENDOK) {
        }
      
        // Check for TASKDONE. 
        if(rfirqf1 & RFIRQF1_TASKDONE) {
          
            // Check to see if radio operation is aborted.
            if (PRF.ENDCAUSE == TASK_ABORT) {
                asm("NOP");
            }
            else if(rfirqf1 & RFIRQF1_TXDONE) {
              
                /* Read out current frequency and change to next active broadcast channel.
                 * If There is no more active channels than the current, clear the tx_flag
                 * to make sure no transmission is started. Also deallocate the TXFIFO so that
                 * it is ready to accept a new payload.
                 */
                channel = PRF.CHAN.FREQ;
                switch(channel) {
                case 23 :
                    if(ActiveChannels & 0x02) {
                        if(!halRfBroadcastSetChannel(BLE_BROADCAST_CHANNEL_38)) {
                            tx_flag = 1;
                        }
                    }
                    else if(ActiveChannels & 0x04) {
                        if(!halRfBroadcastSetChannel(BLE_BROADCAST_CHANNEL_39)) {
                            tx_flag = 1;
                        }
                    }
                    else {
                        tx_flag = 0;
                    }
                    break;    
                case 47 :
                    if(ActiveChannels & 0x04) {
                        if(!halRfBroadcastSetChannel(BLE_BROADCAST_CHANNEL_39)) {
                            tx_flag = 1;
                        }
                    }
                    else {
                        tx_flag = 0;
                    }
                    break;
                case 101 :
                    tx_flag = 0;
                    break;
                default :
                    tx_flag = 0;
                    break;
                }
                // Clear the TXDONE flag in RFIRQF1.
                RFIRQF1 = ~RFIRQF1_TXDONE;
            }
            // Clear the TASKDONE flag in RFIRQF1.
            RFIRQF1 = ~RFIRQF1_TASKDONE;
        }
        
        // Clear RF interrupt flags.
        S1CON = 0;
        // Set to a undefined value in enum type end cause.
        PRF.ENDCAUSE = TASK_UNDEF;
        
        if(tx_flag) {      
          
            /* 
             * Set RFRXFRP:= RFRXFSRP in TXFIFO ("read pointer" to same address as "start read pointer")
             * To resue last packet transmitted to avoid loading payload into TXFIFO again. REUSE must 
             * be set to 1 for this to work, otherwise radio LLE will deallocate packet in TXFIFO after transmission.
             */
            while(RFST != 0);
            RFST = CMD_TXFIFO_RETRY;
          
            // Start transmitter.
            while(RFST != 0);
            RFST = CMD_TX;
        } 
        else {
            // Reuse packet already loaded in TXFIFO.
            while(RFST != 0);
            RFST = CMD_TXFIFO_RETRY;
            
            // Start each receive/transmit on Timer 2 event 1.
            PRF.TASK_CONF.START_CONF = 1;
            
            // Set event flag.
            adv_event_done = 1;
        }
    }
    
    
    

    1440.broadcaster.h

  • Hi Fredrik, Thank you very much! This may help me, if I would can to see functions "halRfBroadcastInit();", "halRfBroadcastLoadPacket(...);", "halRfBroadcastSetChannel(...);".. Simply important halRFxxxxxxxxx(...);...
    Regards...
    Ferdinand
  • Hi Ferdinand,

    I uploaded the wrong files, sorry about that. Take a look at these:

    hal_rf_broadcast.c
    /**************************************************************************************************
      Filename:     hal_rf_broadcast.c
      Revised:      $Date: 2013-03-08 10:00:00 +0100 (Fri, 08 March 2013) $
      Revision:     $Revision: 1$
    
      Description:  hal library for for all RF broadcast related functions.
    
      Copyright 2013 Texas Instruments Incorporated. All rights reserved.
    
      IMPORTANT: Your use of this Software is limited to those specific rights
      granted under the terms of a software license agreement between the user
      who downloaded the software, his/her employer (which must be your employer)
      and Texas Instruments Incorporated (the "License").  You may not use this
      Software unless you agree to abide by the terms of the License. The License
      limits your use, and you acknowledge, that the Software may not be modified,
      copied or distributed unless embedded on a Texas Instruments microcontroller
      or used solely and exclusively in conjunction with a Texas Instruments radio
      frequency transceiver, which is integrated into your product.  Other than for
      the foregoing purpose, you may not use, reproduce, copy, prepare derivative
      works of, modify, distribute, perform, display or sell this Software and/or
      its documentation for any purpose.
    
      YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
      PROVIDED �AS IS� WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
      INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
      NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
      TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
      NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
      LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
      INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
      OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
      OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
      (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
    
      Should you have any questions regarding your right to use this Software,
      contact Texas Instruments Incorporated at www.TI.com.
    **************************************************************************************************/
    
    
    /******************************************************************************
    * INCLUDES
    */
    #include "hal_rf_broadcast.h"
    #include "string.h"
    #include "ioCC2543.h"
    #include "prop_regs.h"
    
    /***********************************************************************************
    * @fn          halRfBroadcastInit
    *
    * @brief       Initialize CC2541 radio in broadcast mode.
    *
    * @return      void
    */
    void halRfBroadcastInit(void) 
    { 
        // Clear radio memory (The RAM registers don't have a default value set, must be set manually). 
        memset((void*)RFCORE_RAM_PAGE, 0, RFCORE_RAM_PAGE_SZ);
      
        // No timer 2 events sent to LLE.
        T2EVTCFG = 0x77;
        
        PRF.TASK_CONF.MODE              = 0;    // Basic mode, fixed length.
        PRF.TASK_CONF.REPEAT            = 0;    // no repeat.
        PRF.TASK_CONF.START_CONF        = 0;    // Start transmit immediately on command.
        PRF.TASK_CONF.STOP_CONF         = 0;    // Don't stop on timer 2 event 2.
        PRF.FIFO_CONF.TX_ADDR_CONF      = 0;    // Read address from PRF.ADDR_ENTRY[0].ADDRESS.
        PRF.PKT_CONF.ADDR_LEN           = 0;    // No address byte.
        PRF.PKT_CONF.AGC_EN             = 0;    // AGC disabled.
        PRF.PKT_CONF.START_TONE         = 0;    // No tone in front of packet.   
        PRF.ADDR_ENTRY[0].CONF.REUSE    = 1;    // Reuse packet on same adv event (same payload on all three if active broadcast channels.)
        
        
        // Update these
        TXCTRL    = 0x69;
        TXPOWER   = 0xE5;               // Set output power: 4 dBm.
        TXFILTCFG = 0x07;               // Set Tx filter bandwidth.
        IVCTRL    = 0x13;               // Set PA, mixer and DAC bias.
        ADCTEST0  = 0x10;               // Adjust ADC gain.
        
        FRMCTRL0  = 0x40;               // Data goes LSB over the air. 
        MDMCTRL0  = 0x04;               // Set 1 Mbps at 250 kHz deviation. 
        MDMCTRL1  = 0x48;               // Correlation threshold.
        MDMCTRL2  = 0x00;               // Syncword transmitted LSB to MSB, 1 leading preamble byte.
        MDMCTRL3  = 0x63;               // Set RSSI mode to peak detect after sync.
        MDMTEST0  = 0x01; 
        
        // Set 32 bit sync word:
        SW_CONF = 0x00;
        SW0 = 0xD6;
        SW1 = 0xBE;
        SW2 = 0x89;
        SW3 = 0x8E;
        
        // Set 3 byte CRC.
        PRF_CRC_LEN = 0x03;
        PRF_CRC_INIT[0] = 0x00;
        PRF_CRC_INIT[1] = 0x55;
        PRF_CRC_INIT[2] = 0x55;
        PRF_CRC_INIT[3] = 0x55;
        
        // Enable PN7 whitener.
        BSP_P0 = 0x00;
        BSP_P1 = 0x5B;
        BSP_P2 = 0x06;
        BSP_P3 = 0x00;
        BSP_MODE = 0x01;
    }
    
    
    /***********************************************************************************
    * @fn          	halRfBroadcastSetChannel
    *
    * @brief       	Change broadcast channel.
    *	     
    * @note         LLE must be idle while changing frequency.
    *				
    * @param        unsigned char AdvChannel: Advertising channel 37, 38 or 39.
    *
    * @return       SUCCESS:                Channel changed successfully.
    *               FAIL_INVALID_PARAMETER: An illegal argument was supplied.
    *               FAIL_RADIO_ACTIVE:      Radio is in TX/RX.
    */
    unsigned char halRfBroadcastSetChannel(unsigned char AdvChannel) 
    {
     
        // Check if radio is idle or else return failure.
        if(RFSTAT & (RFSTAT_TX_ACTIVE | RFSTAT_RX_ACTIVE)) {
            // Radio is in TX/RX, exit with fail.
            return FAIL_RADIO_ACTIVE;
        }
        
      /* Initialization of PN7 whitener in accordance with advertising channel.
       * PRF_W_INIT should be set to 37, 38, or 39 (0x25, 0x26, or 0x27).
       */
        switch(AdvChannel) {
        case BLE_BROADCAST_CHANNEL_37 :
            PRF.CHAN.FREQ = 23;                 // Set frequency to 2402 MHz.
            PRF_W_INIT = 0x25;                  // Init according to BLE channel 37.
            break;
        case BLE_BROADCAST_CHANNEL_38 :
            PRF.CHAN.FREQ = 47;                 // Set frequency to 2426 MHz.
            PRF_W_INIT = 0x26;                  // Init according to BLE channel 37.
            break;
        case BLE_BROADCAST_CHANNEL_39 :
            PRF.CHAN.FREQ = 101;                // Set frequency to 2480 MHz.
            PRF_W_INIT = 0x27;                  // Init according to BLE channel 37.
            break;
        default :
            // Illegal channel in argument.
            return FAIL_INVALID_PARAMETER;
            break;
        }
        return SUCCESS;
    }
    
    
    /***********************************************************************************
    * @fn          halRfLoadBleBroadcastPacket
    *
    * @brief       Load a ADV_NONCONN_IND BLE broadcast packet.
    *              Hard coded public address: 0x112233445566
    *
    * @param       unsigned char *AdvData: Advertising data.
    * @param       unsigned char AdvDataLength: Length of advertising data. 
    *
    * @return      SUCCESS: Packet loaded in to TXFIFO without errors.
    *              FAIL_LENGTH: AdvData length is above maximum limit (26 bytes). 
    */
    unsigned char halRfBroadcastLoadPacket(unsigned char *AdvData, unsigned char AdvDataLength, unsigned char *Address) {
    
        /* Local variables */
        unsigned char i = 0;  
      
        /* Check for maximum allowed payload size (AdvData allowed size: 0-31 bytes) */
        if(AdvDataLength > 26) {
          return FAIL_LENGTH;
        }
      
        /* BLE header and TXFIFO length paramter (required) */
        RFD = AdvDataLength + 13;       // FIFO entry length (Payload + BLE header + BLE length byte), (not transmitted).
        RFD = 0x02;                     // BLE header ADV_NONCONN_IND PDU type (transmitted).
        RFD = AdvDataLength + 11;       // BLE length byte (transmitted).
      
        /* Advertiser�s public or random device address (required) */
        RFD = Address[0]; // Address (LSB)
        RFD = Address[1];
        RFD = Address[2];
        RFD = Address[3];
        RFD = Address[4];
        RFD = Address[5]; // Address (MSB)  
        
        /* AdvData/payload (required) */
    
        // Flags.
        RFD = 0x02;     // Length of next Data (3  Byte).
        RFD = 0x01;     // Type flag.
        RFD = 0x04;     // BR/EDR Not Supported.
    
        // Manufacturer Specific Data
        RFD = AdvDataLength + 1;    // Length of next Data.
        RFD = 0xFF;                 // Type "Manufacturer Specific Data"
        
        /* AdvData/payload (optional) */
        for (i = 0; i < AdvDataLength; i++) {
            RFD = AdvData[i];
        }
        
        /* Packet successfully loaded in to TXFIFO. */
        return SUCCESS;
    }
    
    
    /***********************************************************************************
    * @fn           halRfChannelMap
    *
    * @brief        Active or suspend broadcast channels. The three
    *               RF Channel  0,  2402 MHz, Advertising channel 37
    *               RF Channel 12,  2426 MHz, Advertising channel 38
    *               RF Channel 39,  2480 MHz, Advertising channel 39
    *
    * @param        unsigned char AdvChan37: Set value bigger than 0 to activate broadcast channel 37.
    * @param        unsigned char AdvChan38: Set value bigger than 0 to activate broadcast channel 38.
    * @param        unsigned char AdvChan39: Set value bigger than 0 to activate broadcast channel 39.
    *
    * @return       unsigned char:
    *               Single byte returned where the three least significant bits (LSb) indicate active (1) or suspend (0) channel 37, 38, 39.
    */
    unsigned char halRfBroadcastChannelMap(unsigned char AdvChan37,unsigned char AdvChan38,unsigned char AdvChan39) {
        unsigned char ActiveChannels = 0;
        if(AdvChan37) {
            ActiveChannels |= 0x01;
        }
        if(AdvChan38) {
            ActiveChannels |= 0x02;
        }
        if(AdvChan39) {
            ActiveChannels |= 0x04;
        }
        return ActiveChannels;
    }

    hal_rf_broadcast.h

  • Hi Fredrik,
    Thank you very much! Now I have probably everything what I would need for my experiment. Yesterday I debug SimpleBLEPeripheral example from your BLE Stack, there are similar settings in XData RAM Radio registers.
    Regards...