Thursday, January 17, 2019

How to output 32K crystal signal to specific pin on LAUNCHXL-CC2640R2

The following steps show you how to output 32K crystal signal to specific pin on LAUNCHXL-CC2640R2 using simple_peripheral example.

1. Add " #include  < driverlib/aon_ioc.h > " in simple_peripheral.c.

2. Add the following two lines in the end of SimplePeripheral_init() to output 32K crystal signal to DIO_10.


3. Use scope to check wave form and frequency on DIO_10.

Thursday, January 3, 2019

How to generate PWM on EFR32

The following codes show you how to generate PWM on Silicon Labs EFR32 when button is pressed. In this example, I will use BRD4151A radio board with mainboard BRD4001A to output 1KHz PMW on PC10 pin

#include "em_chip.h"
#include "em_cmu.h"
#include "em_emu.h"
#include "em_gpio.h"
#include "em_timer.h"

/* Use 1 kHz for PWM frequency */
#define PWM_FREQ 1000

void emberAfHalButtonIsrCallback(uint8_t button, uint8_t state)
  uint32_t topValue;
  CMU_ClockEnable(cmuClock_GPIO, true);
  CMU_ClockEnable(cmuClock_TIMER0, true);
  /* set CC0 location 15 pin (PC10) as output, initially high */
  GPIO_PinModeSet (gpioPortC, 10, gpioModePushPull, 1);
  /* select CC channel parameters */
  TIMER_InitCC_TypeDef timerCCInit =
    .eventCtrl  = timerEventEveryEdge,
    .edge       = timerEdgeBoth,
    .prsSel     = timerPRSSELCh0,
    .cufoa      = timerOutputActionNone,
    .cofoa      = timerOutputActionNone,
    .cmoa       = timerOutputActionToggle,
    .mode       = timerCCModePWM,
    .filter     = false,
    .prsInput   = false,
    .coist      = true,
    .outInvert  = false,
  /* configure CC channel 0 */
  TIMER_InitCC (TIMER0, 0, &timerCCInit);

  /* route CC0 to location 15 (PC10) and enable pin */

  /* set PWM period */
  topValue = CMU_ClockFreqGet (cmuClock_HFPER) / PWM_FREQ;
  TIMER_TopSet (TIMER0, topValue);

  /* Set PWM duty cycle to 50% */
  TIMER_CompareSet (TIMER0, 0, topValue >> 1);

  /* set timer parameters */
  TIMER_Init_TypeDef timerInit =
    .enable     = true,
    .debugRun   = true,
    .prescale   = timerPrescale1,
    .clkSel     = timerClkSelHFPerClk,
    .fallAction = timerInputActionNone,
    .riseAction = timerInputActionNone,
    .mode       = timerModeUp,
    .dmaClrAct  = false,
    .quadModeX4 = false,
    .oneShot    = false,
    .sync       = false,

  /* configure and start timer */
  TIMER_Init (TIMER0, &timerInit); 

p.s. Here, we set route CC0 to location 15 (PC10) according to Table 6.6  Alternate Functionality Overview in efr32mg1 datasheet.

Tuesday, December 25, 2018

How to do ADC reading on Silicon Labs EFR32

The following steps show you how to do ADC reading on Silicon Labs EFR32. In this example, I will use BRD4151A radio board with mainboard BRD4001A to do ADC reading from PC9 pin.

1.Use Simplicity Studio to new a Z3Light example and open brd4151a_efr32mg1p232f256gm48.heconf to adjust POS_BX to use PC9 pin.

2. Add the following codes in Z3LightSoc_callbacks.c so we can press PB0/PB1 to do ADC reading from PC9 pin. Here we set ADC reference to internal 2.5V and 12-bit resolution so the max measurement value would be 2.5V which max reading from ADC is 4095.

#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_adc.h"

#define adcFreq   16000000

volatile uint32_t sample;
volatile uint32_t millivolts;


 * @brief  Initialize ADC function
void initADC (void)
  // Enable ADC0 clock
  CMU_ClockEnable(cmuClock_ADC0, true);

  // Declare init structs
  ADC_Init_TypeDef init = ADC_INIT_DEFAULT;
  ADC_InitSingle_TypeDef initSingle = ADC_INITSINGLE_DEFAULT;

  // Modify init structs and initialize
  init.prescale = ADC_PrescaleCalc(adcFreq, 0); // Init to max ADC clock for Series 1

  initSingle.diff       = false;        // single ended
  initSingle.reference  = adcRef2V5;    // internal 2.5V reference
  initSingle.resolution = adcRes12Bit;  // 12-bit resolution
  initSingle.acqTime    = adcAcqTime4;  // set acquisition time to meet minimum requirement

  // Select ADC input.
  initSingle.posSel = adcPosSelAPORT2XCH9;

  ADC_Init(ADC0, &init);
  ADC_InitSingle(ADC0, &initSingle);

void emberAfHalButtonIsrCallback(uint8_t button, uint8_t state)

  // Start ADC conversion
  ADC_Start(ADC0, adcStartSingle);

  // Wait for conversion to be complete

  // Get ADC result
  sample = ADC_DataSingleGet(ADC0);

  // Calculate input voltage in mV
  millivolts = (sample * 2500) / 4096;

p.s. Here, we set initSingle.posSel = adcPosSelAPORT2XCH9 since we set POS_BX to use PC9 pin in HW configurator. You can refer to Table 6.9. ADC0 Bus and Pin Mapping in efr32mg1 datasheet.

3. Build and download the code into BRD4151+ BRD4001A.

4. According to Figure 2.1. BRD4151A Radio Board Connector Pin Mapping, PC9 would be mapped to pin 10 on BRD4001A EXP header and we can apply different voltage between 0V-2.5V to test the ADC reading.

Thursday, December 13, 2018

How to use EmberZNet to do ZCL report

The following steps show you how to use EmberZNet to do ZCL report

Using ZCL_TEMP_MEASUREMENT_CLUSTER_ID to send temperature attribute report as example.

1. Prepare ZCL data buffer with emberAfFillCommandGlobalServerToClientReportAttributes. The buffer format is Attribute ID -> Data type -> Attribute data. For Attribute ID and Attribute data, it's low byte first.

uint8_t buff[5] = {0x00, 0x00, 0x29, 0x05, 0x06};  //Attribute ID (0x0000) -> Data type (0x29) -> Attribute data (0x0605). emberAfFillCommandGlobalServerToClientReportAttributes(ZCL_TEMP_MEASUREMENT_CLUSTER_ID, (uint8_t *) buff, 5);

2. Set source and destination endpoint with emberAfSetCommandEndpoints

emberAfSetCommandEndpoints(1, 1); //endpoint(uint8_t sourceEndpoint, uint8_t destinationEndpoint):

3. Call the following line to do unicast to coordinator

emberAfSendCommandUnicast(EMBER_OUTGOING_DIRECT, 0x0000);

Or call the following line to do unicast using binding address.


Tuesday, December 4, 2018

How to detect button hold in CC26x2, CC13x0, CC13x2 SDK.

The following steps show you how to detect button hold in CC26x2, CC13x0, CC13x2 SDK. I use zed_switch example to add related code to detect if right button (active-low) is pressed (low status) and hold for 3 seconds.

1. In board_key.c, change Board_PIN_BUTTON1 to use PIN_IRQ_BOTHEDGES

static PIN_Config keyPinTable[] = {
      PIN_TERMINATE /* Terminate list */

2. Add the following red codes in board_key.c

UInt32 button_pressed_time=0;
UInt32 button_released_time=0;
static void board_key_keyFxn(PIN_Handle keyPinHandle, PIN_Id keyPinId)

    if(keyPinId == keyButton0)
        keysPressed |= KEY_LEFT;
    else if(keyPinId == keyButton1)
        if(PIN_getInputValue(keyButton1) == false){
            button_pressed_time=Clock_getTicks(); //Clock_getTicks will return counts in 10us.
         } else {
            if (PIN_getInputValue(keyButton1) == true){
                button_released_time=Clock_getTicks(); //Clock_getTicks will return counts in 10us.
        if ( (button_released_time-button_pressed_time)>300000 )
            keysPressed |= KEY_RIGHT_HOLD_3SEC;
        else if ( (button_released_time-button_pressed_time)>0 )
            keysPressed |= KEY_RIGHT;


    if(Timer_isActive(&keyChangeClock) != true)

3. Define KEY_RIGHT_HOLD_3SEC in board_key.h

/*! Select Key ID */
#define KEY_SELECT            0x01
/*! Up Key ID */
#define KEY_UP                0x02
/*! Down Key ID */
#define KEY_DOWN              0x04
/*! Left Key ID */
#define KEY_LEFT              0x08
/*! Right Key ID */
#define KEY_RIGHT             0x10
/*! Hold 3 seconds Right Key ID */
#define KEY_RIGHT_HOLD_3SEC   0x20

4. Add "if(keysPressed == KEY_RIGHT_HOLD_3SEC){...}" in zclSampleSw_processKey of zcl_samplesw.c to process event for right button pressing and holding for 3 seconds.

static void zclSampleSw_processKey(uint8 keysPressed)
    //Button 1
    if(keysPressed == KEY_LEFT)
        zstack_bdbStartCommissioningReq_t zstack_bdbStartCommissioningReq;

            zstack_bdbStartCommissioningReq.commissioning_mode = BDB_COMMISSIONING_MODE_NWK_STEERING | BDB_COMMISSIONING_MODE_FINDING_BINDING;
    //Button 2
    if(keysPressed == KEY_RIGHT)
        zstack_bdbGetZCLFrameCounterRsp_t Rsp;

        Zstackapi_bdbGetZCLFrameCounterReq(zclSampleSw_Entity, &Rsp);
        zclGeneral_SendOnOff_CmdToggle( SAMPLESW_ENDPOINT, &zclSampleSw_DstAddr, FALSE, Rsp.zclFrameCounter );
    if(keysPressed == KEY_RIGHT_HOLD_3SEC)
        //Event for right button pressing and holding for 3 seconds.


Wednesday, October 31, 2018

How to use CC2531EMK and Wireshark as Zigbee sniffer.

The following steps show you how to use CC2531EMK and Wireshark as Zigbee sniffer.

1. Download and install TI Wireshark Packet Converter 1.

2. Download and install TI Packet sniffer to get sniffer_fw_cc2531.hex under C:\Program Files (x86)\Texas Instruments\SmartRF Tools\Packet Sniffer\bin\general\firmware. After getting sniffer_fw_cc2531.hex, you can download it to your CC2531EMK using CC Debugger.

3. Plug CC2531EMK into PC and start TiWsPc to select CC2531EMK and Zigbee channel to start TI Wireshark Packet Converter 1.

4. Download and install TI Packet sniffer 2. Copy ti802154ge-x64-2x.dll and tirpi-x64-2x.dll from C:\Program Files (x86)\Texas Instruments\SmartRF Tools\SmartRF Packet Sniffer 2\wireshark\plugins\2.4.x to C:\Program Files (x86)\Wireshark\plugins\2.4.8 (my Wireshar version is 2.4.8 and yours might be different.)

5. Open Wireshark go to Edit > Preferences > Protocols > Zigbee add the Zigbee TC Link Key 5a6967426565416c6c69616e63653039

6. Create a new Desktop shortcut for Wireshark and add the following to the path: -i\\.\pipe\tiwspc_data -k

7. Start Wireshark with the new shortcut created in step 6 and you will see Wireshark sniffing Zigbee data.

Tuesday, October 16, 2018

How to build TI Z-Stack Linux Home Gateway for Beaglebone Black

The following steps show you how to build TI Z-Stack Linux Home Gateway from source codes for Beaglebone Black.

1.Setup and run Ubuntu 18.04.01 on VirtualBox

2. Install build-essential with the following command

    sudo apt-get install build-essential

3. Change to home directory (mine is /home/yk) and install cross compiler for building BBB binary.
    wget -c
    tar xf gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz

4. Add cross compiler path into PATH variable

     export PATH=$PATH:/home/yk/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf/bin

5. Add TCLIB path by the following command

     export TCLIB=/home/yk/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf/lib

6. Download Z-STACK-LINUX-GATEWAY and install to home directory (mine is ~/Z-Stack_Linux_Gateway-1.0.1-src).

7. Change directory to ~/Z-Stack_Linux_Gateway-1.0.1-src/Source and run "./build_all"

8. Will see the following error after build finished and it doesn't matter. You can find z-stack_linux_gateway_arm_binaries_.tar under /home/yk/Z-Stack_Linux_Gateway-1.0.1-src/Source/ERROR__out and you can scp z-stack_linux_gateway_arm_binaries_.tar to BBB to run/test it.