Skip navigation
Home > All Places > Software Forums > WICED Studio Bluetooth > WICED Studio Bluetooth Forums > Blog > 2018 > January

CYW20719 Memory Layout

Posted by RanjithK_41 Jan 31, 2018

The memory layout for the CYW20719 is shown in Figure 1.

  • ROM
    • 2 Mbytes of ROM hosts the core firmware and various stack layers. The inclusion of core firmware, stack layers, and various libraries in the onboard ROM allow for most of the flash and RAM to be used for data and application code.
  • RAM
    • 512 Kbytes of RAM provide data storage and the ability to execute patch and application code.
  • OCF (On Chip Flash)
    • 1 Mbyte of flash provides storage for configuration data and application code. The OCF supports direct execution of application code.
  • AON (Always ON) Memory:
    • Stores Bluetooth states and connection related parameters when the device goes into its lowest power state.


Figure 1: Memory Layout of CYW20719


Typical Resource Utilization:

    The RAM requirement for application code space varies depending on the application use case and the profiles in use. For example, if the required profile stack is already part of ROM, then WICED uses it from ROM automatically.

The following table provides an approximate ballpark guidance on the available memory with a few of sample applications provided in WICED Studio.


Free RAM


~240 KB


~200 KB


~207 KB


~244 KB


~167 KB


(Freetronic 128x128 OLED Module)

~206 KB

Table 1: Typical RAM Utilization by various applications


Note: Typical MIPS utilization with the Headset sample application is 50% @48MHz.

The Analog to Digital Converter (ADC) block in CYW20719 and CYW20735 is a single-ended switched-cap sigma-delta ADC with 12 bits for Audio* measurements and 10 bits for DC measurements. The ADC has 32 DC input channels including 28 GPIO inputs.

The following pins can be programmed as ADC inputs in CYW20719 QFN40:

     P0, P1, P8–P19, P21–P23, P28–P38.

The following pins can be programmed as ADC inputs in CYW20735 QFN60:

      P0-P14, P16, P26-29, P32,P34,P38

For Audio* applications, the ADC uses a Programmable-Gain Amplifier (PGA) to control the gain.

The CYW20719 and CYW20735 supports two modes of operation: DC measurement mode and Audio mode*. Referefer to the datasheet for more details on supply voltage.


  *Note: The Audio mode (micn and micp pins) is not available in the 40 pin QFN package of the CYW20719.


1.1.  ADC Block Diagram

Figure 1: Block Diagram of CYW20719's ADC

1.2.  DC Measurement Mode

The DC Measurement mode refers to single-ended voltage measurement on an input pin referenced to ADC ground. From the ADC’s block diagram, 28 GPIO channels, VDDIO, VDDC, ADC_BGREF, and ADC_REFGND are multiplexed and fed into the switched-cap sigma-delta ADC.

The wiced_hal_adc_set_power() API allows the program to power up or power down the ADC.

The wiced_hal_adc_init() API initiates the necessary registers required for the ADC operation. The ADC needs to be initialized if the ADC has been powered down in specific low power modes.

2. ADC Output Data and Clock Timing

The ADC clock input is 24 MHz which is divided internally in the ADC hardware to operate at 12 MHz. The typical conversion rate is 100 kHz and the minimum conversion rate is 50 kHz for static measurements of the ADC. The practical time for reading DC voltages after ADC initialization is approximately 150 microseconds. Similarly, the practical time for reading DC raw samples from the ADC is approximately 50 microseconds. This conversion rate roughly translates to a range in between 16ksps and 20ksps(kilo samples per second). This reduction in conversion rate is because the firmware does filtering and averaging of sampled values for better accuracy.

3. ADC Input MUX Clocking in DC Measurement Mode

The ADC requires up to 2 microseconds to settle after switching of the DC input channels. It takes approximately 20 microseconds for the ADC REF to settle after powering up the ADC. The ADC DC input MUX should be held constant for 10 microseconds to 20 microseconds until the DC measurement is finished. This is taken care internally by the APIs. The ADC_DC_MUX_clk is the timing clock on the digital side to synchronize the DC input channel switching and measurement.

Figure 2: Timing Diagram of ADC

4. ADC Gain Calculation

The wiced_hal_adc_read_voltage() API allows the program to read the analog voltage from the ADC. The ADC must be initialized before reading the ADC voltage or else the function call will return 0. All read function calls to ADC registers are blocking. The ADC input and ADC output gain relation in the DC measurement mode can vary due to the following parameters:

  1. When the ADC input range is set to 0 to 1.8 V mode by calling wiced_hal_adc_set_input_range(ADC_RANGE_0_1P8V).
  2. When the ADC input range is set to 0 to 3.6 V mode by calling wiced_hal_adc_set_input_range(ADC_RANGE_0_3P6V).

CYW20719 supports SPI interface to communicate with other SPI devices. This block can be used to communicate with SPI-based sensors such as temperature sensors, motion sensors, and so on. The SPI blocks support the following features:

  • Three-wire (master) and four-wire (master and slave) SPI interface
  • Master and slave modes
  • Configurable SCK polarity and phase
  • Configurable LSB- or MSB-first transfer
  • 1024 byte transmit buffer and 1024 byte receive buffer (shared with HCI UART)


CYW20719 provides SPI APIs to choose between 2 SPI Hardware blocks. spi_interface_t allows the programmer to choose between SPI1 and SPI2. Each of the SPI Utility APIs will have an argument to choose between the 2 SPI blocks.


The SPI  block can be used as a generic master or a generic slave. Any LHL GPIOs can be used for the SPI interface. ModusToolbox provides a list of parameters and APIs to access the SPI 1 driver. click Help > ModusToolbox API Reference > WICED API Reference in ModusToolbox IDE and navigate to Peripheral SPI section under components > Hardware Drivers.

The SPI  block can be initialized in the required configuration using the function wiced_hal_pspi_init().


1.1.  Generic Slave Operation


TX operation

As a generic slave, data is transferred to the host when:

  1. There is data in the TxFIFO
  2. The TxFIFO is enabled
  3. The host toggles SPI_CLK and SPI_CSN is asserted

If condition (1) is false, but conditions (2) and (3) are true, a data underflow condition occurs.  The transmit APIs can place data in the TxFIFO. The wiced_hal_pspi_slave_tx_data() API can be used to transmit the data.

RX operation

As a generic slave, data is received from the host when:

  1. There is space in the RxFIFO
  2. The RxFIFO is enabled
  3. The host toggles SPI_CLK and SPI_CSN is asserted

If condition (1) is false, but conditions (2) and (3) are true, a data overflow condition occurs. Data can be retrieved from the RxFIFO using manual firmware reads. The wiced_hal_pspi_slave_rx_data() API can be used to receive the data.


1.2.  Generic Master Operation


In generic master mode, it is up to the firmware to assert the CS to various peripherals. The CS and INT pins can be used as GPIOs when in master mode. Three types of master transactions are available.


When data only needs to be sent, the SPI block is in TX-Only mode.  In this mode:

  1. TxFIFO must be enabled
  2. RxFIFO must be disabled

In this configuration, the SPI block will transmit any data placed in the TxFIFO.  Data can be placed in the TxFIFO using manual FW writes. The wiced_hal_pspi_tx_data() API can be used to transmit the data as a master.

When the TxFIFO becomes empty, SPI_CLK is paused at a byte boundary until more data is placed in the TxFIFO.  No data is stored in the RxFIFO.


When data only needs to be received, the SPI block is in RX-Only mode.  In this mode:

  • TxFIFO must be disabled
  • RxFIFO must be enabled

In this configuration, the SPI block will retrieve TransmissionLength bytes from the slave.  Data can be retrieved from the RxFIFO using manual firmware reads. The wiced_hal_pspi_rx_data() API can be used to receive the data as a master.

The data stream will be paused if the RxFIFO becomes full. The data stream will resume when there is space in the RxFIFO. No data is sent in this mode.


When data needs to be sent and received simultaneously, the SPI block is in full-duplex mode.  In this mode:

  • TxFIFO is enabled
  • RxFIFO is enabled

In this configuration, the SPI block will transfer data to both FIFOs if there is:

  1. Space in  RxFIFO
  2. Data in TxFIFO

If either of these conditions becomes false, SPI_CLK is paused until both conditions become true again. The wiced_hal_pspi_exchange_data() API can be used to send and receive data simultaneously.


Note: Since SPI and HCI UART use the same buffer, they cannot be used together.

This device has two UART blocks: PUART and HCI UART (BT_UART).

1. PUART (Peripheral UART)

CYW20719’s and CYW20735's PUART can be used to interface with peripherals. CYW20719 and CYW20735 can map the peripheral UART to any LHL GPIOs. The PUART is clocked at 24 MHz. Both PUART RX and PUART TX have a 256 byte FIFO.

PUART has the following features:

  • 8-bit transfer up to 3 Mbps
  • 9-bit transfer including stop bit up to 2.5 Mbps
  • Configurable flow control
  • Interrupt functionality on receive operation

PUART Initialization

The wiced_hal_puart_init() API in wiced_hal_puart.h is used to initialize the PUART block. The wiced_hal_puart_select_uart_pads() API can be used to select TX/RX and optional CTS/RTS pins for the PUART hardware to use.

Figure 1: Data Framing Format

PUART Baud rate

The default PUART baud rate is 115200. The wiced_hal_puart_set_baudrate() API is used to set the baud rate. Typical rates are 115200, 921600, 1500000, and 3000000 bps, although intermediate speeds are also available. For more details on the baud rate, see the datasheet.

PUART Transmit

The wiced_hal_puart_enable_tx() and wiced_hal_puart_disable_tx() APIs enable or disable transmit capability of the PUART, respectively.

The wiced_hal_puart_print() API is used to send a string of characters via the TX line.

The wiced_hal_puart_write() API is used to send one byte via the TX line.

PUART Receive

The wiced_hal_puart_enable_rx() API is used to enable receive capability.

The wiced_hal_puart_rx_fifo_not_empty() API is used to check if there are any data available in the RX FIFO.

PUART Flow control

The wiced_hal_puart_flow_on() and wiced_hal_puart_flow_off() APIs enable or disable the flow control of PUART, respectively.

PUART for RX Interrupt Operation

The wiced_hal_puart_set_watermark_level() API updates the watermark level with the specified value. The default hardware flow control watermark level is 4 which is set during PUART initialization. This value determines the number of bytes required in the RX FIFO before an interrupt is generated.

The wiced_hal_puart_register_interrupt() API is used to register the interrupt handler for the PUART RX.

The wiced_hal_puart_reset_puart_interrupt() API is used to clear and reenable the PUART RX interrupt.



This UART is used for HCI transport for the controller mode and is also used for programming the device. The HCI UART signals are fixed to specific I/O pads.

To understand the programming sequence over the HCI UART interface, see ${INSTALLDIR}libraries\bt_sdk-x.x\docs\BT-SDK\WICED-HCI-Control-Protocol.pdf.


Note: Since SPI 1 and HCI UART share the same FIFO buffer; they cannot be used together.

The CYW20719 and CYW20735 provides one I2C compatible master interface to communicate serially with I2C slave devices.

The I2C module features includes support for: 

  • 7-bit addressing mode.
  • Clock stretching as a master.
  • 100 kHz (Standard Mode), 400 kHz (Fast Mode), 800 kHz (Proprietary), and 1 MHz (Fast Mode+) SCL clock frequencies.
  • Multi-slave operation.


1.  I2C Clock

The I2C clock SCL is provided by the master on the I2C bus. When the I2C module is in master mode, the serial clock generator generates the SCL clock from the transport clock of 24 MHz. The wiced_hal_i2c_set_speed() function allows you to set the clock rate of SCL to any of the speeds listed in the introduction. The I2C block has 64 bytes of RX and TX FIFO for the transaction buffer, and thus each I2C transaction payload can be a maximum of 64 bytes.

Example frequencies for a 24-MHz system clock are given in the enum values description. The I2CM_SPEED_100KHz is set to 240 which is the dividing parameter, that is, when 24,000,000 divided by 240, it results in 100 kHz. Trying to use Multi-master will result in undefined behavior because the clocks from two or more masters will not be synchronized. Also, note that the proprietary 800 kHz mode is not expected to work on all I2C slaves. The wiced_hal_i2c_get_speed() function allows you to get the current clock frequency of the I2C block.


2.  I2C Initialization

The I2C module registers are initialized by calling wiced_hal_i2c_init() from wiced_hal_i2c.h. This function call initializes the I2C driver and its private values. It is required to call the above function before using I2C as some modules can turn this off for power saving. This function call ensures that the clock signal to this hardware block is turned on with the default SCL clock frequency of 100 kHz. Therefore, the wiced_hal_i2c_set_speed() function must be called after the wiced_hal_i2c_init() function if you want to use a speed other than 100 kHz.


3.  I2C Operations

The I2C Master module supports two modes of operations: Master write and Master Read. The modes are discussed in the following sections.

I2C Master Write

The wiced_hal_i2c_write() function writes data to the I2C hardware addressing a slave address. Although any arbitrary length of data may be written to the slave, atomic transactions greater than the hardware's capability are not possible and the data will be split into multiple transactions. This is a blocking call.  The I2C module waits until the I2C bus is free and then, it generates a START condition, transmits the 7-bit slave address followed by a 0 for write cycle's address phase. If there is an acknowledge returned, the I2C master will then start to transmit the data.

I2C Master Read

The wiced_hal_i2c_read() function reads data into the given buffer from the I2C hardware addressing a particular slave address. This is a blocking call. The I2C module waits until the I2C bus is free. When the I2C bus is free, it generates a START condition, sends the slave address, and transfers a receive direction bit. It then generates an interrupt, and the first byte is received. The I2C Master will release the SDA line for the slave device to transmit data only if it receives an acknowledge bit after it transmits the direction bit.

I2C Master Combined Write and then Read

The wiced_hal_i2c_combined_read() function executes a write transaction followed by a read transaction with a repeated start condition between the first and the second. In the first transaction, data is written to the slave address and after the repeated start, data is read from the slave in the second transaction. This operation is usually used to read a slave device's registers with the first write transaction specifying the slave's register address that needs to be read.


4.  I2C Bus Error

If the I2C master read or write operation is successful, the corresponding function will return I2CM_SUCCESS. When an attempted I2C operation fails because of no acknowledgement from the slave, I2CM_OP_FAILED is returned and the SDA and SCL lines are released (the STOP condition is not transmitted). I2CM_BUSY is returned when the I2C hardware block is busy with another transaction.

The CYW20719 and CYW20735 devices have two types of GPIOs: 40 LHL GPIOs and 8 Arm GPIOs.


The number of LHL GPIOs and Arm GPIOs available in the device depends on the package. For example, CYW20719 QFN 40 has 16 LHL GPIOs  whereas CYW20735 QFN60 has 23 LHL GPIOs.


LHL GPIOs are different from Arm GPIOs in few ways. LHL GPIOs can operate in low power modes and support mux-able peripherals, whereas Arm GPIOs can operate only in active mode with limited functionality. The functionalities that can be brought out to LHL I/Os are I2C, SPI, PUART, ACLK., and so on.


The wiced_hal_gpio_select_function() API can be used to map the functionality to specific pins.


Both LHL and ARM GPIOs are enumerated in wiced_bt_gpio_numbers_t() list in wiced_hal_gpio.h.


Though the SDK offers configuring all the I/Os, the selection of pins in an application needs to be made based on the following constraints with respect to the device:

  • Certain functionalities (for example, ADC input) are supported only on specific LHL I/Os and cannot be routed to other pins.
  • Only pins P26, P27, P28, and P29 can drive higher current compared to other pins. Refer to the datasheet for more details.
  • Some of the package pins are double or triple bonded with multiple I/O pads; therefore only one of the bonded pins can be used at a time.
  • P19, P20, and P39 are reserved for system use, and cannot be used in applications.


For using any pin as a generic GPIO, see the GPIO driver section by navigating to Hardware drivers in Components.

click Help > ModusToolbox API Reference > WICED API Reference in ModusToolbox IDE.

Using the driver, the pins can be set up as outputs, as inputs with optional pull-up, or as 16 mA or 8 mA drive-strength outputs on the device.


The WICED SDK has a SuperMUX pin selector utility to guide the pin selection for product designs.

The block diagram in Figure 1 shows the software architecture of the Bluetooth/BLE components and protocol layers, the partitioning of the components across ROM, and RAM/OCF (On-Chip Flash).


The CYW20719 ROM firmware runs on a real-time operating system and handles the programming and configuration of all on-chip hardware functions. This includes the BT/LE baseband, LM, HCI, GATT, ATT, L2CAP, and SDP layers. The ROM includes drivers for on-chip peripherals. In addition, the ROM includes on-chip power management functions including transitions between different power modes.


The application code runs in its own thread context from RAM or OCF and accesses the Bluetooth/BLE components via WICED BT APIs. The application code accesses the OS and peripheral drivers via WICED APIs. For a complete list of the supported APIs, see


For a complete list of sample applications, see the

CYW20719 implements support for building an application to execute in-place (XIP) from OCF. This XIP feature is helpful for applications with large code size and limited RAM constraints. By placing the application and the profile library code in flash, the application can save RAM to that extent. The .text (code) section and rodata (read-only data) section from the application and the profile libraries execute from the OCF. The remaining sections get loaded to SRAM. Patches will be executed from patch RAM.


Executing the code from FLASH will have an impact on the speed and power. So, time critical functionality should not be included in the XIP section.

For more details on the XIP feature, see the CYW20719 – XIP Support User Guide.

ModusToolbox provides an over-the-air firmware upgrade feature for CYW20719. For complete details see OTA Firmware Upgrade documentation



Figure 1: Software Architecture

CYW20719 and CYW20735 have multiple clock dividers and PLLs routed to several high-speed and low-speed peripherals. There are basically two types of clocks on the device: high-frequency and low-frequency clock sources.


High-frequency clock sources:

     This clock is derived from an external 24 MHz crystal oscillator  using internal PLLs to upscale the frequency.

  • HCLK: This clock powers the Resource Processing Unit (RPU). The RPU includes CM4, Floating-point Unit (FPU), and DMA Controller. This HCLK's frequency can range between 1 MHz and 48 MHz.
  • BT Core Clock: This clock powers the Bluetooth RF hardware. This BT Core's clock frequency can range between 1 MHz and 48 MHz.
  • PTU Clock: This clock powers the Peripheral Transport Unit (PTU) which includes SPI, I2C, UART, PCM, and Random Number Generator. This PTU's clock frequency can either be  24 MHz or 48 MHz. The peripherals will internally divide the clock frequency for their specific purpose. For example, the I2C master clock (SCL) can range between 100 kHz and 1 MHz.
  • The application timer (dual-input 32-bit timers) is clocked at 1 MHz.

Low frequency clock sources:

     There are three lean high land (LHL) low power oscillators (LPOs) available. They are LP-LPO (32 kHz), HP-LPO (32 kHz), and XTAL32K (32 kHz). The firmware decides which clock source to use among the available LPOs depending on the accuracy and power requirements. It is recommended to use an external 32.768 kHz crystal oscillator with low error PPM to improve the clock accuracy and lower average current consumption in Sleep, Power Down Sleep (PDS), or Shut-Down Sleep (SDS) mode. The firmware assumes the external LPO has lower (less than 250 PPM) error with little or no jitter.


1.1.  Real Time Clock (RTC)

The CYW20719 and CYW20735 supports a 48-bit RTC timer running on the 32-kHz crystal (XTAL32K) LPO. If an external LPO is not connected to CYW20719, then the firmware takes the clock input from the internal LPO for the RTC. WICED Studio provides APIs to set the current time, get the current time, or convert the current time value to a string. By default, the date and time are set to January 1, 2010 with a time of 00:00:00 denoting HH: MM: SS. It is mandatory to set the oscillator frequency to 32 kHz with the provided APIs when a 32-kHz external LPO is used. The RTC configuration structure (RTCconfig) has two member variables oscillatorFrequencykHz and rtcRefClock whose values must be set to RTC_REF_CLOCK_SRC_32KHZ.


1.2.  Watchdog

The Watchdog module in CYW20719 and CYW20735 is based on a 32-bit down counter that is used to detect and recover from malfunctions. During normal operation, the device regularly resets the watchdog timer before the count value reaches zero to prevent it from elapsing, or “timing out”. If, due to a hardware fault or program error, the device fails to reset the watchdog, the timer will elapse and generate a system reset on time out. The process of restarting the watchdog timer’s counter is referred to as “kicking or petting the dog”.

WICED Studio provides limited debugging functionalities via the watchdog timer. The default watchdog timeout is set to 2 seconds and watchdog petting is done in the idle thread. Production applications need not pet the watchdog. When the watchdog expires, the system will reset after a core-dump. The core-dump contains the following information: device firmware or hardware version, warning-flag, memory info, CPU/HW registers, SRAM, and Patch RAM image. The core dump is sent over the HCI-UART as BT-HCI vendor specific events.

  • wiced_hal_wdog_disable()
  • wiced_hal_wdog_reset_system()
  • wiced_hal_wdog_restart()

1.3.  Application Timers

CYW20719 and CYW20735 provides one general-purpose 32 bit dual-input timer. The firmware uses the 2 x 32-bit timers as a 1 x 64-bit timer. WICED Studio provides APIs to use the timer functionality. The timer supports two modes of operation:

  • Periodic Interrupt mode
  • Single-shot mode

The WICED API provides four timer types:


The two periodic timers mentioned above are triggered every time the timer count reaches zero whereas the other two timers are single-shot.

The wiced_init_timer() API initializes the timer. It allows you to specify the callback function to be invoked when the timer expires. This API also allows you to specify timer type that should be used. This API does not start the timer.

The wiced_start_timer() API is used to start the count down. The wiced_stop_timer() API can be used to stop the timer.

The wiced_is_timer_in_use() function allows you to know if the specified timer is currently in use by returning a Boolean value.

1.3.  Pulse Width Modulator(PWM)

There are six 16-bit Hardware PWM channels available in CYW20719 and CYW20735. The PWM of CYW20719 and CYW20735 is not glitch-free. The clock frequency of each PWM can be configured in one of the two ways. The LHL_CLK or PMU_CLK can be used as the clock source for the PWM. If the clock source is the LHL_CLK, then the clock frequency will be 32 kHz or 128 kHz based on the LHL clock priority. The PMU_CLK requires the auxiliary clock to be configured first. When configuring the auxiliary clock, ACLK0 is not available for use with the PWMs. Hence, ACLK1 is the only available PMU_CLK running at 24 MHz or at 1MHz using internal clock division. The wiced_hal_aclk_enable() function in wiced_hal_aclk.h enables the auxiliary clock and allows the functionality of choosing either 1 MHz or 24 MHz for routing to the PWMs.

The wiced_hal_pwm_start() function configures, enables, and starts the PWM and also routes it to a preconfigured GPIO pin. The desired GPIO pin must be configured as an output before configuring it for use with a PWM. Each PWM channel can be routed to GPIO pins using the SuperMUX. See the datasheet for more details. This function takes in 5 parameters (i.e., channel, clock source, toggle count, initial count and invert signal). The channel refers to PWM channels 0 to 5. The clock source can be either LHL_CLK or ACLK1 (PMU_CLK). The toggle count refers to the number of ticks to wait before toggling the signal. The initial count is the initial value of the register. The invert signal can be either 1 or 0. If the invert signal is 1, the PWM output starts HIGH and if the invert signal is 0, the PWM output starts LOW.

The wiced_hal_pwm_change_values() function changes the PWM settings such as toggle count and initial count of a specific PWM channel after the PWM hardware block has already been started.

The wiced_hal_pwm_configure_pin() function can be used to map any LHL GPIO to the specified PWM channel.

The wiced_hal_pwm_get_params() is a helper function that calculates the PWM parameters. This function takes in three parameters: input clock frequency, duty cycle, and desired PWM output frequency to determine the required initial count and toggle count. The initial count and toggle count is determined by the API using the following expression:

Initial count = 0xFFFF - (Input Clock Freq / PWM Freq out)

Toggle count = 0xFFFF - ((duty cycle in percentage) * (Input Clock Freq / PWM Freq out) / 100)

Bluetooth devices have a 48-bit address which is usually termed as BD_ADDR. For BR/EDR devices, there are three parts to this address: NAP, UAP and LAP whereas for BLE devices, the BD_ADDR consists of two parts: Company-ID and Company Assigned part. For more information regarding BD_ADDR and their formats, kindly refer to the BLE SIG specification.


On CYW20706, a single BD_ADDR is defined which is common for both BLE and BR/EDR applications. The BD_ADDR can be configured in the following ways:

  1. Using the API wiced_bt_set_local_bdaddr(wiced_bt_device_address_t bda, wiced_bt_ble_address_type_t addr_type)
    1. This API needs to be called after the stack is initialized, i.e. after the BTM_ENABLED_EVT.
    2. This API takes 2 parameters: the 6-byte device address and the address type.
    3. This is useful when you want to change the BD_ADDR during runtime.
  2. Using the BT_DEVICE_ADDRESS make option during build
    1. In the make target, you can include this optional parameter to set the BD_ADDR to the desired value.
    2. For example, demo.hello_sensor-CYW920706WCDEVAL download BT_DEVICE_ADDRESS=AABBCCDDEEFF.
    3. The BT_DEVICE_ADDRESS can also be set to random to make use of a random address.
  3. Using the Factory_Commit_BD_ADDR  VSC (Vendor Specific Command) to store the device address in flash.
    1. There are 2 steps to this procedure:
      1. First, set the device address to all 0xFFs by making use of the BT_DEVICE_ADDRESS=FFFFFFFFFFFF in the make target and download your application.
      2. Then, send the Factory_Commit_BD_ADDR vendor specific HCI command. This needs to be done only for the first time after the device is programmed.
    2. The Factory_Commit_BD_ADDR VSC has the below format:
      1. Opcode: 0xFC10
      2. Parameters Length: 7 bytes
      3. Parameters: 6 byte address followed by 0x00
      4. Example:  01 10 FC 07 AA BB CC DD EE FF 00
    3. You can either send this HCI command over HCI UART or use wiced_bt_dev_vendor_specific_command WICED API in your application.
      1. Example: wiced_bt_dev_vendor_specific_command(0x10, 7, bd_addr_param, addr_callback);
      2. Note that if you are sending the HCI command over HCI UART, you will have to send a HCI reset command (01 03 0C 00) before sending the VSC.
    4. If the device address is configured using these steps, then this address can be overwritten only by reprogramming the device, not otherwise. However, the wiced_bt_set_local_bdaddr()  API can still be used to change the address to be used but this API does not overwrite the address stored in flash.
    5. This method is most suitable for setting unique address for every device during production.

CYW20706 consists of a fully integrated Power Amplifier (PA) that supports Class 1 or Class 2 operation. The maximum possible Tx power is +12 dBm for BR/EDR applications and +9dBm for BLE applications. In WICED 5.2 and later, the wiced_bt_cfg_settings_t structure consists of a maximum power value, where you can specify the maximum transmit power in dBm necessary for your application.

The max Tx power can also be configured using the APIs mentioned below. Kindly note that the API definitions are not included in WICED. Nevertheless, these APIs can be used to modify the Tx power.


  1. wiced_result_t wiced_bt_dev_set_adv_tx_power( int power );
    1. This API can be used to change the max Tx power for BLE advertisement. It changes the power to be used on the advertisement channels.
    2. Power should be a multiple of 4 from +8 dBm to -16 dBm, i.e. power can be +8, +4, 0, -4, -8, -12, -16 dBm.
    3. Example: wiced_bt_dev_set_adv_tx_power(-8);
  2. wiced_result_t wiced_bt_dev_set_tx_power( wiced_bt_device_address_t bd_addr , int power );
    1. This API can be used to change the max Tx power for a BLE or BR/EDR connection. It changes the power to be used for the data channels for a specific connection.
    2. The first parameter should be the device address of the peer device.
    3. Power should be a multiple of 4 from +12 dBm to -16 dBm, i.e. power can be +12, +8, +4, 0, -4, -8, -12, -16 dBm.
    4. Example: wiced_bt_dev_set_tx_power(bd_addr,0);

Cypress BLE Mesh Solution

Posted by madhul_36 Jan 8, 2018

Disclaimer: BLE mesh solution in WICED Studio 6.1 and WICED Studio 6.2 is meant only for evaluation. Limited testing is done for BLE mesh in these releases. Cypress community won't provide any support for BLE mesh until the solution is officially rolled out for the broad market.


The Cypress BLE Mesh Solution is fully compliant with the Bluetooth SIG's Mesh Specification and is certified. It is available on WICED studio 6.1 SDK.


Part Numbers supported: CYW20706, CYW20719B1

Modules available: CYBT-343026-01 (Based on CYW20706 chip)

Eval Boards: CYBT-343026-EVAL (Based on the CYBT-343026-01 module), CYW920706WCDEVAL based on CYW20706 chip, CYW920719Q40EVB-01 (Based on CYW920719WCD1 module)

Bluetooth Specification: 5.0

Mesh Specification: 1.0


The WICED Studio SDK has resources that help in getting started with the BLE Mesh Solution by providing examples projects for all the SIG defined models specified in the Mesh Model Specification 1.0


The Mesh firmware examples are available in the WICED Studio in the location: WICED-Studio-6.1\<Platform>\apps\snip\mesh. The Mesh usecase requires a provisioner that creates the network, provisions, configures and control devices of the network. This provisioner can be realized using Cypress's MeshLighting App for Android (located in WICED-Studio-6.1\common\apps\snip\mesh\peerapps\Android\src\bin) or the windows ClientControlMesh Application.


Provisioning using MeshLighting Android Application:


1) Connect the Eval Board to the PC and load the mesh_onoff_server project. Refer to the corresponding Kit User Guide for details on programming the firmware. Once programmed, the device advertises as an unprovisioned mesh device.


2) Copy the apk file of the MeshLighting app to your android phone, install the application and open it.


3) In the Options, select "Create Network" and specify a name, say "TestNetwork".



4) Now you can add your own Rooms in the network. A room is a group of devices that form a part of the whole network, to which commands can be multicasted using a single address. Tap the + icon to add a room and specify a name, say "New Room".

Screenshot_2018-01-25-14-23-23-919_com.cypress.le.mesh.meshapp.png Screenshot_2018-01-25-14-23-53-322_com.cypress.le.mesh.meshapp.png



5) Tap the ADD DEVICE option to scan for of unprovisioned mesh devices. Once the device is detected, click OK to start the provisioning and also configures the device through series of messages sent to the on/off device. The proxy connection is establish with the first device by default. If the proxy disconnects for some reason, the user can tap the "Connect to proxy" and "Configure" buttons to resume the proxy connection and configuration.


6) Repeat step 4 to add any number of other devices to the room. Now we can control the ON/OFF status of the devices in the room by sliding the  ON/OFF switch. We can also specify the transition time. The proxy receives the message and transmits it to the nodes in the network. The change of state in the devices may be indicated by the UART Prints and a LED toggle on the board.




7) After receiving the messages, the devices send status, which is displayed in the Phone as shown below:




8) Instead of the mesh_onoff_server example, the mesh_light_hsl_server example can also be used with the App. The App can now modify the Color of the light (By setting Hue, Saturation and Lightness values). The Color setting in the GUI can now be accessed as below.




WICED Studio also provides an example for mesh_onoff_client which acts as a switch for the mesh_onoff_server devices. The device can be provisioned into the network using the App. Upon configuration, the device will be listed as a switch. In the below figure the light1 is a provisioned mesh_onoff_client device and the light2 is a mesh_onoff_server project as indicated by icons.




Tap on the light1 to see options for assigning light2 to the switch.




Provisioning using windows ClientControlMesh Application:


The ClientControlMesh Application for windows is located in "WICED-Studio-6.1\common\apps\snip\mesh\ClientControl\Release". This application sends WICED HCI commands to devices via HCI UART. This app can be used to perform provisioning by sending commands to an embedded mesh controller device that acts as a provision client. A provisioning client can be realized using the mesh_provision_client example firmware in the SDK. The ClientControlMesh tool sends Mesh events as WICED HCI commands. So make sure the C_FLAGS += -DHCI_CONTROL flag is enabled in the in your project.


1) Connect an Eval board to the PC and load the mesh_provison_client example to it.


2) Open the ClientControlMesh Application and choose the Light Control Tab. and select the HCI UART COM Port number of the provision client device in the GUI.


3) Click the "Open" button. This will configure the provision client device, as shown by the series of messages in Trace box in the bottom.


4) Click "Create" button to add a network and name it as say, "TestNetwork"


4) Connect one more Eval board to the PC and load the mesh_onoff_server or mesh_level_server or mesh_hsl_server example. The device will advertise as an unprovisioned mesh device.


5) Click the "Scan Unprovisioned" button. The provision client will scan for the unprovisioned device and lists the details.


6) Click "Stop Scanning" and then "Provision and Configure" buttons. The mesh device will be added to the "TestNetwork" after provisioning and configuration.


7) Now commands can be sent and status can be received using the tools in the bottom pane of the ClientControlMesh App. In the figure shown below, the "OnOff serve (0002)" device has been provisioned and the On/Off state of the light can be changed using the Get and Set buttons.


8) Repeat steps 4,5,6,7 to add more devices to the network and control them.




The ClientControlMesh App can also be used to control switches (say, mesh_Onoff_Client, mesh_hsl_client, mesh_level_client devices) by sending WICED HCI commands.


1) Create a network, provision a switch and a light using a provisioner (say MeshLighting Android App or Mesh_provision_client by following the above guidelines.

2) In ClientControl.exe and select the HCI UART COM Port number of the Switch device (say, mesh_onoff_client) in the GUI.

2) Open Models tab.

3) Choose "onoff" from dropdown.

4) Check the "use publication info" and "Reliable" checkboxes.

5)  Set appropriate on/off state and click on set. The light should respond appropriately.




To unprovision a device from the network, long press the user button on the Eval Board. Now the provisioning process can be started afresh.


The base code common for all the Mesh modules are located in:


BLE MIDI Server Example

Posted by madhul_36 Jan 7, 2018


In this example, the CYW20719 device is configured as a MIDI Server that sends MIDI data over BLE. The CYW920719Q40EVB_01 Eval board is connected to a PC and keypress from the keyboard is sent as input to the PUART terminal of the CYW20719 device via Serial COM terminal interface of the Eval board. The CYW20719 maps the ASCII inputs from the PUART to MIDI notes and sends them as BLE notification to a MIDI Central in accordance with the BLE MIDI Specification.



Tool: WICED Studio 6.1 and above, Any MIDI Central Client (Example: Garageband App for iOS), Serial Terminal (Example: TeraTerm, CoolTerm). This blog

Programming Language: C

Associated Parts: CYW20719

Related Hardware: CYW920719Q40EVB_01 Board

Block Diagram

middi.pngMIDI Protocol

The MIDI (Musical Instrument Digital Interface) protocol is a standard that defines the way various devices transfer music related audio data. The BLE Protocol can be used to implement the MIDI standards, enabling a connection between BLE enabled musical instruments and other devices such as Phones, computers, speakers etc., A BLE MIDI Controller should meet the following standards:


Scan Response Packet

  • Either the advertisement packet or scan response packet should contain the UUID of the MIDI Service in the Service UUID field. MIDI Service UUID: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700
  • Below is an example for a typical scan response packet that contains the service UUID alone:

        0x11 0x07 0x00 0xC7 0xC4 0x4E 0xE3 0x6C 0x51 0xA7 0x33 0x4B 0xE8 0xED 0x5A 0x0E 0xB8 0x03 (Totally 18 Bytes)

  • First Byte 0x11 is the length (17 Bytes, excluding the length byte)
  • The second byte 0x07 indicates 128 Bit Service UUID is present.
  • The last 16 bytes are the 128 Bit UUIDs for the MIDI Service. (UUID: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700)


GATT Database

  • The GATT Database should have a MIDI Service with UUID same as the UUID in the scan response packet (UUID: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700)
  • Inside the MIDI Service, there should be a characteristic (MIDI IO Characteristic) with UUID: (7772E5DB-3868-4112-A1A9-F2669D106BF3)
  • It's properties are Read, Write without response and Notify
  • The permissions should be set to "Encryption Required"
  • The MIDI IO Characteristic should have a CCCD (Client characteristic configuration descriptor)
  • Upon pairing the MIDI Client will read the MIDI Characteristic, for which the MIDI Controller should respond with an empty packet.


Other Requirements

  • Connection interval < 15 mS (to avoid Jitter)
  • MTU Negotiation should be supported


MIDI Data Format:

The MIDI events i.e. messages are sent as notifications. The first 2 bytes of the notifications contain the time stamps in millisecond resolution.

The Byte [0] is the MIDI header. The MSB (7th Bit) is always 1 and the 6th bit is always 0. The rest of the bits contain the Most Significant 6 bits of the time stamp.

The Byte [1] is the MIDI Timestamp byte. The 7th Bit is always 1 and the rest of the 7 bits contain the lest significant 7 bits of the timestamp.

Thus the Byte [0] and the Byte[1], together contain a 13 bit time stamp in milliseconds.

The Byte [2] contain the MIDI Status (NOTE ON, NOTE OFF, Control Change, Program Change etc.,)


The next bytes contain the MIDI messages (Status followed by MIDI Data. Refer the MIDI Specification for more details)


Simple Piano Example:

This is a simple example in case of a piano. For the sake of simplicity and testing we can set the time stamps to be 0.

When the key is pressed, it is called NOTE ON message. When you release the key it is called NOTE OFF message.  NOTE ON and NOTE OFF are send as notifications. The status field of the notifications indicate whether a message is NOTE ON of NOTE OFF.

Each NOTE ON and NOTE OFF may be 5 bytes :  Byte[0], Byte[1], Byte[2, Byte[3], Byte[4]


Byte[0] : MIDI Header. In this example, it is always 0x80, as the timestamp is set as 0.


Byte[1] : Timestamp. This too will remain 0x80


Byte[2] :

For a NOTE ON message Byte[2] = 0x90 | Channel number

For a NOTE OFF message Byte[2] = 0x80 | Channel number


Channel Number:

When different musical instruments need to be played, each one  is assigned one channel number. For example, if you are using piano and drum, piano is assigned channel number 0 and drum is assigned channel number 1.

In our example, only one instrument is used. So channel number is 0.

So BYTE[2] for NOTE ON message is 0x90, Byte[2] for NOTE OFF message is 0x80


Byte[3]: This contains the hex code of the actual note we play.

In keyboard we have basic 12 notes. The notes and their corresponding hex codes used in this example are given in the table below:

NoteHex Code


Byte [4]: This is the velocity. This denotes how fast we press the key. It ranges from 0 to 0x7F.

If velocity is 0, it also means NOTE OFF message, even though Byte [2] is 0x90. So, for NOTE ON messages, the velocity (Byte [4]) should be a non-zero value. We usually select the middle value between 0 and 127 i.e. 63 (0x3f)




Assume the following case.


1) User first presses C

2) Releases C

3) Presses D#

4) releases D#


Assuming the velocity to be 0x3F, This can be sent as 4 notifications:


Notification 1: 0x80 0x80 0x90 0x3c 0x3f

Notification 2: 0x80 0x80 0x80 0x3c 0x0

Notification 3: 0x80 0x80 0x90 0x3F 0x3f

Notification 4: 0x80 0x80 0x80 0x3F 0x0


Programming and Testing

  1. Install the WICED Studio 6.1 (or above) in your PC. Plug in two CYW920719Q40EVB_01 Boards and let the drivers bind
  2. to the devices. Make sure the jumpers are in place. Open WICED Studio and set the platform as 20719-B1_Bluetooth. For more details, please refer CYW920719Q40EVB_01-Kit-Guide.pdf present in Doc folder in the project explorer.
  3. Copy the midi_server project folder. In the WICED Studio, right-click the Apps folder in the Project Explorer pane and click Paste. You can see these folders under the Apps folder.
  4. Open two windows of Serial Terminal (Example: Teraterm or Coolterm), and bind each of those windows to the PUART COM Ports of each devices. Each device has two COM Ports with consecutive numbers. The COM Port with the bigger number corresponds to the PUART that displays Debug Messages. The one with the smaller number corresponds to the HCI UART. The BaudRate is set to 115200 in the firmware. Make sure the BaudRate in serial terminals is also set to 115200.
  5. Create a Make Target for the project by selecting Project -> Make Target -> Create. Paste the following as the entry in the Target Name field:

midi_server-CYW920719Q40EVB_01 UART=COMxx download

Make sure that the Same as the Target Name checkbox is checked. Click OK.

(Note: In the above target, XX is the HCI COM Port numbers of the device.)


     6. Double click the Target you just created, shown in the Make Target Pane on the right. You can see the midi_server program being built and downloaded into the  board. (For more details or troubleshooting, please refer the WICED-20706-BT-Quick-Start-Guide). Once downloaded, the PUART debug logs can be seen in Teraterm.


   7. Have any MIDI Client and Central for connecting to the server device. The example shown here is the Garageband App for iOS. Open Garageband and go to Settings -> Bluetooth MIDI Device. The advertising MIDI Server will be shown on the device with the name “MIDI”


  8.Tap on the device to initiate connection and pairing. Once the pairing is completed, the instrument (Keyboard or Guitar) can be selected in the Garageband App. Now, the user can make send MIDI notes to the phone by pressing keys on the computer’s keyboard via the Serial Terminal. The below picture shows the mapping of notes with the keys in the keyboard.




  9. As the keys are being pressed, corresponding sound heard from the phone.


10. If MIDI Timestamps need to be used, enable #define USE_TIMESTAMPS macro in midi_server.h


11. In order to initiate disconnection from the device side, press the user button on the Eval board.


Related Documents

The below table lists all relevant application notes, code examples, knowledge base articles, device datasheets, and Component / user module datasheets.






CYW920719Q40EVB-01 Evaluation Board User Guide

The  User Guide can be accessed in the WICED Studio from Project Explorer -> 20719-B1_Bluetooth -> Doc


Developing Custom Applications with BT Designer - Document

This document can be accessed from Project Explorer -> 20719-B1_Bluetooth -> Doc

Filter Blog

By date:
By tag: