Lesson 7 – WICED Bluetooth: Bluetooth Advertising

WICED Bluetooth Using the CYW20719

# Title Comment
0 A Two Hour WICED Bluetooth Class WICED Bluetooth Using the CYW20719 in all its glory
1 Resources Links to all of the Cypress WICED information including videos, application notes etc.
2 Your First Project Making Hello World & the Blinky LED
3 The Super Mux Tool Learning about platforms and the Super Mux Tool
4 Snips Using the example projects to learn Bluetooth
5 Bluetooth Designer Using the tool to customize a project and get going fast
6 The CCCD & Notification Writing back to the Central
7 Advertising  Beacon Building a beacon project to advertise your custom information 
8 Scanner Viewing the world around you
9 Bluetooth Classic SPP Using the Serial Port Profile to Transmit Lots of Data

Source code: 

  • git@github.com:iotexpert/wiced_bt_intro.git
  • https://github.com/iotexpert/wiced_bt_intro

 

Summary

Everywhere you go there are bunches of Bluetooth devices that are acting as beacons.  Apple has a standard called iBeacon.  Google has a standard called Eddystone.  Some companies use those standards, and some companies make proprietary beacons.  In this lesson we will build a beacon.

The important concepts in this lesson are:

  1. Advertising packet formats
  2. wiced_bt_cfg.c

The steps I will follow are:

  1. Run BT Designer
  2. Setup the device as “no gatt database”
  3. Move the project into the wiced_bt_class folder
  4. Edit the make target
  5. Fix the WICED_BT_TRACE to go to the PUART
  6. Run it
  7. Edit the wiced_bt_cfg.c to never timeout
  8. Setup no random address changing
  9. Add the manufacturing data uint8_t array and include the Cypress company code
  10. Change the start advertising call to BTM_BLE_ADVERT_NONCONN_HIGH, BLE_ADDR_PUBLIC
  11. Update the length of the advertising packet
  12. Update the set advertising packet to have the manufacturing data
  13. Add a button interrupt function
  14. Register the button interrupt

BLE Concepts

The Advertising Packet is a string of 3-31 bytes that is broadcast at a configurable interval. The packet is broken up into variable length fields. Each field has the form:

  • Length in bytes (not including the Length byte)
  • Type
  • Optional Data

The minimum packet requires the <<Flags>> field which is a set of flags that defines how the device behaves (e.g. is it connectable?). Here is a list of the other field Types that you can add:

/** Advertisement data types */
enum wiced_bt_ble_advert_type_e {
    BTM_BLE_ADVERT_TYPE_FLAG                        = 0x01,                 /**< Advertisement flags */
    BTM_BLE_ADVERT_TYPE_16SRV_PARTIAL               = 0x02,                 /**< List of supported services - 16 bit UUIDs (partial) */
    BTM_BLE_ADVERT_TYPE_16SRV_COMPLETE              = 0x03,                 /**< List of supported services - 16 bit UUIDs (complete) */
    BTM_BLE_ADVERT_TYPE_32SRV_PARTIAL               = 0x04,                 /**< List of supported services - 32 bit UUIDs (partial) */
    BTM_BLE_ADVERT_TYPE_32SRV_COMPLETE              = 0x05,                 /**< List of supported services - 32 bit UUIDs (complete) */
    BTM_BLE_ADVERT_TYPE_128SRV_PARTIAL              = 0x06,                 /**< List of supported services - 128 bit UUIDs (partial) */
    BTM_BLE_ADVERT_TYPE_128SRV_COMPLETE             = 0x07,                 /**< List of supported services - 128 bit UUIDs (complete) */
    BTM_BLE_ADVERT_TYPE_NAME_SHORT                  = 0x08,                 /**< Short name */
    BTM_BLE_ADVERT_TYPE_NAME_COMPLETE               = 0x09,                 /**< Complete name */
    BTM_BLE_ADVERT_TYPE_TX_POWER                    = 0x0A,                 /**< TX Power level  */
    BTM_BLE_ADVERT_TYPE_DEV_CLASS                   = 0x0D,                 /**< Device Class */
    BTM_BLE_ADVERT_TYPE_SIMPLE_PAIRING_HASH_C       = 0x0E,                 /**< Simple Pairing Hash C */
    BTM_BLE_ADVERT_TYPE_SIMPLE_PAIRING_RAND_C       = 0x0F,                 /**< Simple Pairing Randomizer R */
    BTM_BLE_ADVERT_TYPE_SM_TK                       = 0x10,                 /**< Security manager TK value */
    BTM_BLE_ADVERT_TYPE_SM_OOB_FLAG                 = 0x11,                 /**< Security manager Out-of-Band data */
    BTM_BLE_ADVERT_TYPE_INTERVAL_RANGE              = 0x12,                 /**< Slave connection interval range */
    BTM_BLE_ADVERT_TYPE_SOLICITATION_SRV_UUID       = 0x14,                 /**< List of solicitated services - 16 bit UUIDs */
    BTM_BLE_ADVERT_TYPE_128SOLICITATION_SRV_UUID    = 0x15,                 /**< List of solicitated services - 128 bit UUIDs */
    BTM_BLE_ADVERT_TYPE_SERVICE_DATA                = 0x16,                 /**< Service data - 16 bit UUID */
    BTM_BLE_ADVERT_TYPE_PUBLIC_TARGET               = 0x17,                 /**< Public target address */
    BTM_BLE_ADVERT_TYPE_RANDOM_TARGET               = 0x18,                 /**< Random target address */
    BTM_BLE_ADVERT_TYPE_APPEARANCE                  = 0x19,                 /**< Appearance */
    BTM_BLE_ADVERT_TYPE_ADVERT_INTERVAL             = 0x1a,                 /**< Advertising interval */
    BTM_BLE_ADVERT_TYPE_LE_BD_ADDR                  = 0x1b,                 /**< LE device bluetooth address */
    BTM_BLE_ADVERT_TYPE_LE_ROLE                     = 0x1c,                 /**< LE role */
    BTM_BLE_ADVERT_TYPE_256SIMPLE_PAIRING_HASH      = 0x1d,                 /**< Simple Pairing Hash C-256 */
    BTM_BLE_ADVERT_TYPE_256SIMPLE_PAIRING_RAND      = 0x1e,                 /**< Simple Pairing Randomizer R-256 */
    BTM_BLE_ADVERT_TYPE_32SOLICITATION_SRV_UUID     = 0x1f,                 /**< List of solicitated services - 32 bit UUIDs */
    BTM_BLE_ADVERT_TYPE_32SERVICE_DATA              = 0x20,                 /**< Service data - 32 bit UUID */
    BTM_BLE_ADVERT_TYPE_128SERVICE_DATA             = 0x21,                 /**< Service data - 128 bit UUID */
    BTM_BLE_ADVERT_TYPE_CONN_CONFIRM_VAL            = 0x22,                 /**< LE Secure Connections Confirmation Value */
    BTM_BLE_ADVERT_TYPE_CONN_RAND_VAL               = 0x23,                 /**< LE Secure Connections Random Value */
    BTM_BLE_ADVERT_TYPE_URI                         = 0x24,                 /**< URI */
    BTM_BLE_ADVERT_TYPE_INDOOR_POS                  = 0x25,                 /**< Indoor Positioning */
    BTM_BLE_ADVERT_TYPE_TRANS_DISCOVER_DATA         = 0x26,                 /**< Transport Discovery Data */
    BTM_BLE_ADVERT_TYPE_SUPPORTED_FEATURES          = 0x27,                 /**< LE Supported Features */
    BTM_BLE_ADVERT_TYPE_UPDATE_CH_MAP_IND           = 0x28,                 /**< Channel Map Update Indication */
    BTM_BLE_ADVERT_TYPE_PB_ADV                      = 0x29,                 /**< PB-ADV */
    BTM_BLE_ADVERT_TYPE_MESH_MSG                    = 0x2A,                 /**< Mesh Message */
    BTM_BLE_ADVERT_TYPE_MESH_BEACON                 = 0x2B,                 /**< Mesh Beacon */
    BTM_BLE_ADVERT_TYPE_3D_INFO_DATA                = 0x3D,                 /**< 3D Information Data */
    BTM_BLE_ADVERT_TYPE_MANUFACTURER                = 0xFF                  /**< Manufacturer data */
};

Here is an example of the advertising packet that we are going to generate

Implement the Project

Run BT Designer and create a new project called “L7_Advertising”

Turn off the GATT Database

Move the project into the wiced_bt_class folder

Edit the make target

Setup the the WICED_BT_TRACE to use the PUART

#if ((defined WICED_BT_TRACE_ENABLE) || (defined HCI_TRACE_OVER_TRANSPORT))
    /* Set the Debug UART as WICED_ROUTE_DEBUG_NONE to get rid of prints */
    //  wiced_set_debug_uart( WICED_ROUTE_DEBUG_NONE );

    /* Set Debug UART as WICED_ROUTE_DEBUG_TO_PUART to see debug traces on Peripheral UART (PUART) */
      wiced_set_debug_uart( WICED_ROUTE_DEBUG_TO_PUART );

    /* Set the Debug UART as WICED_ROUTE_DEBUG_TO_WICED_UART to send debug strings over the WICED debug interface */
    //wiced_set_debug_uart( WICED_ROUTE_DEBUG_TO_WICED_UART );
#endif

Run it

Now that we know it is working, Ill edit the wiced_bt_cfg.c to never timeout

        .high_duty_nonconn_duration =       0,                                                         /**< High Duty Non-Connectable Advertising Duration in seconds (0 for infinite) */

Setup no random address changing

    .rpa_refresh_timeout =                  WICED_BT_CFG_DEFAULT_RANDOM_ADDRESS_NEVER_CHANGE,         /**< Interval of random address refreshing - secs */

Now edit the L7_Advertising.c to add the manufacturing data uint8_t array

uint8_t manuf_data[] = {0x31,0x01,0x00};

Switch to non-connectable advertising

    wiced_bt_start_advertisements(BTM_BLE_ADVERT_NONCONN_HIGH, BLE_ADDR_PUBLIC, NULL);

Update the l7_advertising_set_advertisement_data function to have three elements in the advertising packet

    wiced_bt_ble_advert_elem_t adv_elem[3] = { 0 };

Add the Manufacturer information to the advertising packet

    /* Advertisement Element for Manufacturer Data */
    adv_elem[num_elem].advert_type = BTM_BLE_ADVERT_TYPE_MANUFACTURER;
    adv_elem[num_elem].len = sizeof(manuf_data);
    adv_elem[num_elem].p_data = manuf_data;
    num_elem++;

Add a button interrupt function

void buttonISR(void *data, uint8_t port_pin )
{

    manuf_data[2] += 1;
    l7_advertising_set_advertisement_data();
    WICED_BT_TRACE("Manufacturer Data = %d\n",manuf_data[2]);
}

Register the button interrupt

 wiced_hal_gpio_register_pin_for_interrupt( WICED_GPIO_PIN_BUTTON_1, buttonISR, NULL );
    wiced_hal_gpio_configure_pin( WICED_GPIO_PIN_BUTTON_1, ( GPIO_INPUT_ENABLE | GPIO_PULL_UP | GPIO_EN_INT_FALLING_EDGE ), GPIO_PIN_OUTPUT_HIGH );

Test using the AdvScanner

I have given you a project called the “AdvScanner”.  You can run it by creating a make target.

When I run the L7_Advertising project and press the buttons a few times my terminal will look like this

And when I look at the output of the scanner program you can see the advertising packet for the this project.  Notice that the last three bytes are 31 01 03.  The 03 is the count of button presses.

Lesson 5 – WICED Bluetooth: Bluetooth Designer – Turn up the Radio!

WICED Bluetooth Using the CYW20719

# Title Comment
0 A Two Hour WICED Bluetooth Class WICED Bluetooth Using the CYW20719 in all its glory
1 Resources Links to all of the Cypress WICED information including videos, application notes etc.
2 Your First Project Making Hello World & the Blinky LED
3 The Super Mux Tool Learning about platforms and the Super Mux Tool
4 Snips Using the example projects to learn Bluetooth
5 Bluetooth Designer Using the tool to customize a project and get going fast
6 The CCCD & Notification Writing back to the Central
7 Advertising  Beacon Building a beacon project to advertise your custom information 
8 Scanner Viewing the world around you
9 Bluetooth Classic SPP Using the Serial Port Profile to Transmit Lots of Data

Source code: 

  • git@github.com:iotexpert/wiced_bt_intro.git
  • https://github.com/iotexpert/wiced_bt_intro

 

Summary

In this lesson we are going to build the simplest project that I could think of… turning an LED on/off with Bluetooth Low Energy.

The important BLE concepts are

  1. What is a Central / Peripheral
  2. What is Advertising
  3. What is a GATT Database

The important WICED Bluetooth Concepts are:

  1. How do you run WICED Bluetooth Designer
  2. What is the structure of a WICED Bluetooth Project
  3. What is a Callback
  4. How is the GATT Database Implemented
  5. How to run CySmart

The steps that we will follow are:

  1. Run BT Designer
  2. Create a project called L5_BluetoothLED
  3. Go to the characteristics page
  4. Add a vendor specific service
  5. Name the Service L5Service
  6. Add an optional characteristic that is vendor specific
  7. Name it RED
  8. Make it 1 byte with an initial value of 01
  9. Set it up for host write
  10. Add a user description to the characteristic
  11. Generate the code
  12. Move the folder to the wiced_bt_class folder
  13. Fix the three include problems
  14. Reset the debug UART to PUART
  15. When there is a write, change the value of the WICED_LED_1 GPIO
  16. Test

BLE Concepts

In the world of BLE there are two sides of every connection

  • The Central – typically a cellphone
  • The Peripheral – your WICED device

Centrals listen for Peripherals that are Advertising.  Advertising is a periodic packet of up to 31 bytes of information that a Peripheral will send out to make it presence known.  When a Central hears the Advertising packets of a Peripheral that is “interesting” it can initiate a connection.

Once a connection is made, how do you exchange information?  The answer is that a Peripheral has a database running inside of it.  The database is called a “GATT database”.   A Central can perform “Service Discovery” to find all of the legal stuff in the database.  The GATT database is organized into one or more “Services” that have one or more “Characteristics”.  For instance a Heart Rate Monitor might have a “Heart Rate Service” with two characteristics, one for heart rate and one for battery level.

There are two types of Services.  Ones that are specified by the Bluetooth SIG, like heartrate.  And vendor specific custom services.

Run Bluetooth Designer

The Bluetooth Designer is a GUI tool that we built into Eclipse.  It allows you to configure some of the fundamental Bluetooth feature (like the GATT Database) and then automatically generate the code.  Start Bluetooth Designer by running File->New->WICED Bluetooth Designer.

Since this is Lesson 5 and we are going to write and LED… call the project “L5_BluetoothLED”

Once you start BT Designer, you screen should look like this.  The project is going to be a BLE only project.

The Characteristics button lets you setup the GATT database.

Add a service by selecting vendor specific service and then hitting the “+”

I’ll call the service “L5Service”

Next add a characteristic by selecting “vendor specific characteristic” and pressing “+”

Change the name to “RED”, Make the device role “Host write to or reads from service”.  Make the size 1 byte and set the initial value to 01 (it must be 01 not 1 or 001)

When we are looking at this remotely you would like to be able to see the user description.  So click that tab and give it a description.

Press Generate Code button.  You will end up with a folder in the top level apps directory.  I don’t like this, so lets move it into our class projects folder.  You can do this by dragging the folder to the wiced_bt_class folder.  Now it should look like this:

Unfortunately, there are three little issues that this creates which need to be fixed.  First, you need to fix L5_BluetoothLED.c as this include is wrong.

#include "../wiced_bt_class/L5_BluetoothLED/L5_BluetoothLED_db.h"

And change it to:

#include "L5_BluetoothLED_db.h"

Next edit L5_BluetoothLED_db.h and add the #include “wiced.h”

#include "wiced.h"

Finally edit the L5_BluetoothLED_db.c to fix the same include problem.

#include "../wiced_bt_class/L5_BluetoothLED/L5_BluetoothLED_db.h"

It should be like this.

#include "L5_BluetoothLED_db.h"

Now edit the make target that was created by the BT Designer and change it to:

Remember in the earlier lesson I showed you about the WICED HCI UART and the WICED PUART.  Well by default the WICED_BT_TRACE is setup to go to the HCI UART.  So, lets fix the output of BT_TRACE to go to the PUART by changing the file “L5_BluetoothLED.c”

#if ((defined WICED_BT_TRACE_ENABLE) || (defined HCI_TRACE_OVER_TRANSPORT))
    /* Set the Debug UART as WICED_ROUTE_DEBUG_NONE to get rid of prints */
    //  wiced_set_debug_uart( WICED_ROUTE_DEBUG_NONE );

    /* Set Debug UART as WICED_ROUTE_DEBUG_TO_PUART to see debug traces on Peripheral UART (PUART) */
      wiced_set_debug_uart( WICED_ROUTE_DEBUG_TO_PUART );

    /* Set the Debug UART as WICED_ROUTE_DEBUG_TO_WICED_UART to send debug strings over the WICED debug interface */
    //wiced_set_debug_uart( WICED_ROUTE_DEBUG_TO_WICED_UART );
#endif

The last thing that we want to do is fix it so that when the Central writes a new value into the RED LED characteristic we should write the GPIO to the new value.  In L5_BluetoothLED.c make this change.

     case HDLC_L5SERVICE_RED_VALUE:
                       WICED_BT_TRACE("LED = %d\n",l5_bluetoothled_l5service_red[0]);
                       wiced_hal_gpio_set_pin_output(WICED_GPIO_PIN_LED_2,l5_bluetoothled_l5service_red[0]);
                       break;

Now build the project and see what happens.  The first testing step will be to open CySmart.  You can see that a device called “L5_BluetoothLED” is advertising.

When I click it, you can see that there is a GattDB.

When I click on the database, I can see that there is only one service (which makes sense as we setup only one)

Click on the Service and you can see that there is only one characteristic in the service… and its value is 01.

When you click the descriptor button you can see that there is a Characteristic User Description

 

And finally the value is “Red LED Value”.  That is what we setup.

When you click back … then click on the write it will bring up this window where I can send a new value.

Now the value is 0x00 and the RED LED is on (remember from earlier that it is active low so that makes sense)

 

And when I look at the terminal I can see two writes (I wrote again before I took this screen shot)

A Tour of the Source Code

The GATT Database is in the file L5_BluetoothLED_db.c

const uint8_t gatt_database[] = // Define GATT database
{
    /* Primary Service 'Generic Attribute' */
    PRIMARY_SERVICE_UUID16 (HDLS_GENERIC_ATTRIBUTE, UUID_SERVICE_GATT),

    /* Primary Service 'Generic Access' */
    PRIMARY_SERVICE_UUID16 (HDLS_GENERIC_ACCESS, UUID_SERVICE_GAP),

        /* Characteristic 'Device Name' */
        CHARACTERISTIC_UUID16 (HDLC_GENERIC_ACCESS_DEVICE_NAME, HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE,
            UUID_CHARACTERISTIC_DEVICE_NAME, LEGATTDB_CHAR_PROP_READ,
            LEGATTDB_PERM_READABLE),

        /* Characteristic 'Appearance' */
        CHARACTERISTIC_UUID16 (HDLC_GENERIC_ACCESS_APPEARANCE, HDLC_GENERIC_ACCESS_APPEARANCE_VALUE,
            UUID_CHARACTERISTIC_APPEARANCE, LEGATTDB_CHAR_PROP_READ,
            LEGATTDB_PERM_READABLE),

    /* Primary Service 'L5Service' */
    PRIMARY_SERVICE_UUID128 (HDLS_L5SERVICE, __UUID_L5SERVICE),

        /* Characteristic 'RED' */
        CHARACTERISTIC_UUID128_WRITABLE (HDLC_L5SERVICE_RED, HDLC_L5SERVICE_RED_VALUE,
            __UUID_L5SERVICE_RED, LEGATTDB_CHAR_PROP_READ | LEGATTDB_CHAR_PROP_WRITE,
            LEGATTDB_PERM_READABLE | LEGATTDB_PERM_WRITE_REQ),

            /* Descriptor 'Characteristic User Description' */
            CHAR_DESCRIPTOR_UUID16 (HDLD_L5SERVICE_RED_USER_DESCRIPTION,
                UUID_DESCRIPTOR_CHARACTERISTIC_USER_DESCRIPTION, LEGATTDB_PERM_READABLE),

};

Each row in the Database table has a unique “Handle” that is defined in the L5_BluetoothLED_db.h

#define __UUID_L5SERVICE                      0x30, 0x9d, 0x7f, 0x29, 0x73, 0xca, 0x4f, 0xfd, 0xa5, 0x68, 0x17, 0xd8, 0x90, 0x67, 0x7f, 0x35
#define __UUID_L5SERVICE_RED                  0x29, 0xbf, 0x86, 0xa6, 0xc8, 0x6c, 0x4e, 0xa5, 0xaa, 0x56, 0xbd, 0xac, 0x72, 0x80, 0x93, 0xa9

// ***** Primary Service 'Generic Attribute'
#define HDLS_GENERIC_ATTRIBUTE                0x0001

// ***** Primary Service 'Generic Access'
#define HDLS_GENERIC_ACCESS                   0x0014
// ----- Characteristic 'Device Name'
#define HDLC_GENERIC_ACCESS_DEVICE_NAME       0x0015
#define HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE 0x0016
// ----- Characteristic 'Appearance'
#define HDLC_GENERIC_ACCESS_APPEARANCE        0x0017
#define HDLC_GENERIC_ACCESS_APPEARANCE_VALUE  0x0018

// ***** Primary Service 'L5Service'
#define HDLS_L5SERVICE                        0x0028
// ----- Characteristic 'RED'
#define HDLC_L5SERVICE_RED                    0x0029
#define HDLC_L5SERVICE_RED_VALUE              0x002A
// ===== Descriptor 'User Description'
#define HDLD_L5SERVICE_RED_USER_DESCRIPTION   0x002B

Each characteristic value is held in one of the uint8_t arrays found in “L5_BluetoothLED.c”

/*******************************************************************
 * GATT Initial Value Arrays
 ******************************************************************/
uint8_t l5_bluetoothled_generic_access_device_name[]     = {'L','5','_','B','l','u','e','t','o','o','t','h','L','E','D'};
uint8_t l5_bluetoothled_generic_access_appearance[]      = {0x00,0x00};
uint8_t l5_bluetoothled_l5service_red[]                  = {0x01};
uint8_t l5_bluetoothled_l5service_red_user_description[] = {'R','E','D',' ','L','e','d',' ','V','a','l','u','e'};

/*******************************************************************
 * GATT Lookup Table
 ******************************************************************/

/* GATT attribute lookup table                                */
/* (attributes externally referenced by GATT server database) */
gatt_db_lookup_table l5_bluetoothled_gatt_db_ext_attr_tbl[] =
{
    /* { attribute handle,                  maxlen,                                                 curlen,                                                 attribute data } */
    {HDLC_GENERIC_ACCESS_DEVICE_NAME_VALUE, 15,                                                     15,                                                     l5_bluetoothled_generic_access_device_name},
    {HDLC_GENERIC_ACCESS_APPEARANCE_VALUE,  2,                                                      2,                                                      l5_bluetoothled_generic_access_appearance},
    {HDLC_L5SERVICE_RED_VALUE,              1,                                                      1,                                                      l5_bluetoothled_l5service_red},
    {HDLD_L5SERVICE_RED_USER_DESCRIPTION,   sizeof(l5_bluetoothled_l5service_red_user_description), sizeof(l5_bluetoothled_l5service_red_user_description), l5_bluetoothled_l5service_red_user_description},
};

 

 

Lesson 4 – WICED Bluetooth: Using Snips

WICED Bluetooth Using the CYW20719

# Title Comment
0 A Two Hour WICED Bluetooth Class WICED Bluetooth Using the CYW20719 in all its glory
1 Resources Links to all of the Cypress WICED information including videos, application notes etc.
2 Your First Project Making Hello World & the Blinky LED
3 The Super Mux Tool Learning about platforms and the Super Mux Tool
4 Snips Using the example projects to learn Bluetooth
5 Bluetooth Designer Using the tool to customize a project and get going fast
6 The CCCD & Notification Writing back to the Central
7 Advertising  Beacon Building a beacon project to advertise your custom information 
8 Scanner Viewing the world around you
9 Bluetooth Classic SPP Using the Serial Port Profile to Transmit Lots of Data

Source code: 

  • git@github.com:iotexpert/wiced_bt_intro.git
  • https://github.com/iotexpert/wiced_bt_intro

 

Summary

In this lesson I am going to show you how to NOT write all of your own code and still get the job done.  In this lesson we are going to do three things.

  1. Examine & Run the hal_gpio snip
  2. Examine & Run the hal_i2c_master snip
  3. Copy the hal_i2c_master snip and make it “more better”

To modify the hal_i2c_master snip I will

  1. Make a new folder called L4_Accelerometer
  2. Copy the makefile.mk and hal_i2c_master.c into the L4_Accelerometer folder
  3. Create a new make target and make sure that things still work
  4. Look at the LSM9DS1 datasheet
  5. Update the function initialize_app to startup the Accelerometer and speed up the polling
  6. Update the function comboread_cb to read the Acceleration registers and print out the values

Run hal_gpio

If you dont already have a make target for snip.hal.hal_gpio create one and then program the board.

Notice that the light blinking will change speeds if you press the button.  Let’s look at the code that does this:

At the beginning it sets up a timer

        // Initialize timer to control the pin toggle frequency
        if (wiced_init_timer(&hal_gpio_app_timer, &hal_gpio_app_timer_cb, 0, WICED_SECONDS_PERIODIC_TIMER) == WICED_SUCCESS)
        {
            if (wiced_start_timer(&hal_gpio_app_timer, LED_BLINK_FREQ_A_IN_SECONDS) != WICED_SUCCESS)
            {
                WICED_BT_TRACE("Seconds Timer Error\n");
            }
        }

The timer calls this function each time the timer expires.

/*
 * The function invoked on timeout of app. seconds timer.
 */
void hal_gpio_app_timer_cb(uint32_t arg)
{
    static uint32_t wiced_seconds = 0; /* number of seconds elapsed */
    uint8_t index = 0;

    wiced_seconds++;

    if (wiced_seconds & 1)
    {
        for (index = 0; index < sizeof(output_pin_list); index++)
        {
            wiced_hal_gpio_set_pin_output(output_pin_list[index], GPIO_PIN_OUTPUT_LOW);
        }
    }
    else
    {
        for (index = 0; index < sizeof(output_pin_list); index++)
        {
            wiced_hal_gpio_set_pin_output(output_pin_list[index], GPIO_PIN_OUTPUT_HIGH);
        }
    }
}

And when the button is pressed all it does is switch back and forth between two different intervals for the timer.  And after the switch it restarts the timer.

/*
 * Handle interrupt generated due to change in the GPIO state
 */
void hal_gpio_app_interrrupt_handler(void *data, uint8_t pin)
{
    static uint32_t blink_freq = LED_BLINK_FREQ_A_IN_SECONDS;

    // toggle LED blink rate upon each button press
    if (blink_freq == LED_BLINK_FREQ_A_IN_SECONDS)
    {
        blink_freq = LED_BLINK_FREQ_B_IN_SECONDS;
    }
    else
    {
        blink_freq = LED_BLINK_FREQ_A_IN_SECONDS;
    }

    if (wiced_stop_timer(&hal_gpio_app_timer) == WICED_SUCCESS)
    {
        wiced_start_timer(&hal_gpio_app_timer, blink_freq);
    }

    // clear the interrupt status
    wiced_hal_gpio_clear_pin_interrupt_status(pin);
}

Run hal_i2c_master

This CYW920719Q40EVB_01 development kit has an I2C LSM9DS1 accelerometer on it.  And I noticed that when looking around in the snips that the Snip called “hal_i2c_master.c” appears to talk to the chip.  Here is a little section of the comments from the top of the snip

 *
 * WICED sample application for I2C Master usage
 *
 * This application demonstrates how to use I2C driver interface
 * to send and receive bytes or a stream of bytes over the I2C hardware as a master.
 * The on-board LSM9DS1 motion sensor acts as the I2C slave

So, lets run the snip and see what happens.  If you don’t have a make target… well then make one.

Then make the make target.

It turns out that “0” is a bug in the example project.  And printing out the WHO_AM_I register isnt really very interesting.

Modify the hal_i2c_master.c Create a Better Project

I don’t like making changes inside of the WICED SDK files.  But, I want to fix the bug and printout something more interesting.  So start by creating a new folder in the wiced_bt_class folder

Type in the directory name L4_Accelerometer (notice in the screenshot below I mistyped it)

Select the makefile.mk and the hal_i2c_master.c then right click copy the files.

Then select the L4_Accelerometer folder and pick paste.

Create a make target for the L4_Accelerometer

Build it to make sure it still works.

Now that we have a base to stand-on.  Let’s have a look at the data sheet.  I have used these before and I know that you need to turn on the Accelerometer to give you anything interesting.  Turns out CTRL_REG_6_XL is the control register we need.

The other interesting registers are the actual output of the accelerometer.  That is 0x28 –> 0x2D

Start by modifying the function initialize_app to turn on the accelerometer by writing 0x40 to register 0x20

uint8_t status;
    // Turn on Accelerometer - Register 0x20... 2g accelerometer on @ 50hz
    uint8_t data[] = {0x20, 0x40};
    status = wiced_hal_i2c_write(data,sizeof(data),LSM9DS1_ACC_GYRO_I2C_ADDRESS);

I dont really like printing the values every two seconds so I will modify the timer:

  • Make it a milisecond timer
  • Set it to print every 500ms
if ( WICED_SUCCESS == wiced_init_timer( &seconds_timer, &comboread_cb, 0, WICED_MILLI_SECONDS_PERIODIC_TIMER )) {
        if ( WICED_SUCCESS != wiced_start_timer( &seconds_timer, 500 )) {
            WICED_BT_TRACE( "Seconds Timer Error\n\r" );
        }
    }

Here is the whole function initialize_app together

void initialize_app( void )
{
    wiced_hal_i2c_init();
    uint8_t status;

    // Turn on Accelerometer - Register 0x20... 2g accelerometer on @ 50hz
    uint8_t data[] = {0x20, 0x40};
    status = wiced_hal_i2c_write(data,sizeof(data),LSM9DS1_ACC_GYRO_I2C_ADDRESS);


    /* register callback for button available on the platform */
    wiced_platform_register_button_callback( WICED_PLATFORM_BUTTON_1, button_cb, NULL, WICED_PLATFORM_BUTTON_RISING_EDGE);

    current_speed = wiced_hal_i2c_get_speed();

    WICED_BT_TRACE("Default I2C speed: %d KHz\n", (CLK_FREQ/current_speed));

    /*Start a timer for POLL_TIMER seconds*/

    if ( WICED_SUCCESS == wiced_init_timer( &seconds_timer, &comboread_cb, 0, WICED_MILLI_SECONDS_PERIODIC_TIMER )) {
        if ( WICED_SUCCESS != wiced_start_timer( &seconds_timer, 500 )) {
            WICED_BT_TRACE( "Seconds Timer Error\n\r" );
        }
    }

}

Next I need to modify the comboread_cb callback.  It will

  • Setup a structure to hold the three acceleration values (Line 145)
  • Then it will read from the LSM9DS1 (Line 152)
  • Then print them (Line 156)
/******************************************************************************
 * This function reads the value from I2C slave and prints it
 *****************************************************************************/

void comboread_cb (uint32_t arg)
{
    UINT8  status = 0xFF;
    UINT8 reg_add = 0x28; // Acceleromter register

    typedef struct {
        int16_t ax;
        int16_t ay;
        int16_t az;
    } __attribute__((packed)) accel_val_t;

    accel_val_t data;
    status = wiced_hal_i2c_combined_read((UINT8 *)&reg_add, sizeof(UINT8), (uint8_t *)&data, sizeof(data), LSM9DS1_ACC_GYRO_I2C_ADDRESS);

    if(I2CM_SUCCESS == status) {

        WICED_BT_TRACE("Ax=%d Ay=%d Az=%d\n",data.ax,data.ay,data.az);
    }else if(I2CM_OP_FAILED == status) {
        WICED_BT_TRACE("I2C comboread operation failed\r\n");
    }else if(I2CM_BUSY == status) {
        WICED_BT_TRACE("I2C busy\r\n");
    }else{
        WICED_BT_TRACE("Unknown status from I2C\r\n");
    }

}

Now double click the make target and make sure that everything is working.

Lesson 3 – WICED Bluetooth: The Super Mux Tool

WICED Bluetooth Using the CYW20719

# Title Comment
0 A Two Hour WICED Bluetooth Class WICED Bluetooth Using the CYW20719 in all its glory
1 Resources Links to all of the Cypress WICED information including videos, application notes etc.
2 Your First Project Making Hello World & the Blinky LED
3 The Super Mux Tool Learning about platforms and the Super Mux Tool
4 Snips Using the example projects to learn Bluetooth
5 Bluetooth Designer Using the tool to customize a project and get going fast
6 The CCCD & Notification Writing back to the Central
7 Advertising  Beacon Building a beacon project to advertise your custom information 
8 Scanner Viewing the world around you
9 Bluetooth Classic SPP Using the Serial Port Profile to Transmit Lots of Data

Source code: 

  • git@github.com:iotexpert/wiced_bt_intro.git
  • https://github.com/iotexpert/wiced_bt_intro

 

Summary

You probably noticed and wondered “Why did he use WICED_LED_2 instead of WICED_LED_1”?  The answer to that question is that by default the CYW920719Q40EVB_01 is setup with WICED_LED_2 enabled as a GPIO and WICED_LED_1 used for another purpose.  But to what purpose?  In this lesson we will answer the questions:

  1. What are the default pins?
  2. How do you use the SuperMux tool?
  3. How do you use a PWM?

To do this we are going to copy the L2_HelloWorld project and add a PWM to drive the Green LED also known as WICED_LED_1.

The steps we are going to follow are

  1. Copy the L2_HelloWorld to start a new project called L3_SuperMux
  2. Rename L2_HelloWorld.c
  3. Fix the makefile.mk for the updated source file
  4. Create a new make target
  5. Program to make sure everything is still working
  6. Look at the platform files for CYW920719Q40EVB_01
  7. Run  the SuperMux Tool
  8. Delete the SPI Slave_1 From the SuperMux
  9. Add an LED to the SuperMux
  10. Configure the LED to P28
  11. Apply the SuperMux configuration
  12. Look at the new files added to the project
  13. Look a the makefile.mk
  14. Look L3_SuperMux_pin_config.c
  15. Update L3_SuperMux.c to have correct includes
  16. Update L3_SuperMux.c to start the clock, pin and PWM
  17. Program the project
  18. Look at the Hardware Abstraction Layer Documentation

Copy L2_HelloWorld –> L3_SuperMux

Instead of starting from a blank project.  Lets make a copy of the L2_HelloWorld project.  If you right click on the L2_HelloWorld folder and select copy

Then click on the “wiced_bt_class” folder and select paste.

WICED Studio will then complain that you already have a directory called “L2_HelloWord” and give you the opportunity to rename it.  Call the new project “L3_SuperMux”

Now you need to rename the L2_HelloWorld.c to be L3_SuperMux.c.  Right click on the L2_HelloWorld.c and select rename

Then give it a new file name… like L3_SuperMux.c

Double click makefile.mk and edit it.  You need to change the comment, and the name of the APP_SRC source file.

#
# Lesson 3 - SuperMux
#
APP_SRC +=  L3_SuperMux.c

C_FLAGS += -DWICED_BT_TRACE_ENABLE

Create a make target for this project by right clicking the L2_HelloWorld Make Target, then selecting “New”

That will make a new target… and it will bring up this dialog box.  Notice that it named the target “Copy of …”

Fix it to be “L3_SuperMux” like this:

You should now have an exact copy of L2_HelloWorld, in the project L3_SuperMux.  Double click the make target and make sure that things are still working.  When you build you should get this.  Don’t forget to “Start the Bootloader” if the programming doesn’t work.

Platform Files

If you look on the back of your CYW920719Q40EVB-01 development kit you will find the exact pin map of this board.  On this picture you can see that LED1 is connected to P28

In WICED Studio, the world “Platform” is just another word for Board Support Package.  Basically all of the configuration required to build the firmware for a specific board.  If you click on platforms you will find a directory for the CYW920719Q40EVB.  All of the default configuration for the pins are located in the file “wiced_platform_pin_config.c”

If you look at this file closely, you will see on line 47 that pin P28 is setup as the MOSI of WICED_SPI_1.  That isnt a GPIO!!!.  And you will see a whole block of code on line 74 that is commented out that COULD   configure P28 as a GPIO.  But that would require modifying our default platform files, which I dont want to do.  Now what?  Simple use the SuperMux tool.

/* all the pins available on this platform and their chosen functionality */
const wiced_platform_gpio_t platform_gpio_pins[] =
    {
        [PLATFORM_GPIO_0 ] = {WICED_P00, WICED_GPIO              },      //Button
        [PLATFORM_GPIO_1 ] = {WICED_P01, WICED_SPI_1_MISO        },
        [PLATFORM_GPIO_2 ] = {WICED_P02, WICED_PCM_OUT_I2S_DO    },
        [PLATFORM_GPIO_3 ] = {WICED_P04, WICED_PCM_IN_I2S_DI     },
        [PLATFORM_GPIO_4 ] = {WICED_P06, WICED_GCI_SECI_IN       },
        [PLATFORM_GPIO_5 ] = {WICED_P07, WICED_SPI_1_CS          },
        [PLATFORM_GPIO_6 ] = {WICED_P10, WICED_GCI_SECI_OUT      },
        [PLATFORM_GPIO_7 ] = {WICED_P16, WICED_PCM_CLK_I2S_CLK   },
        [PLATFORM_GPIO_8 ] = {WICED_P17, WICED_PCM_SYNC_I2S_WS   },
        [PLATFORM_GPIO_9 ] = {WICED_P26, WICED_GPIO              },      //Default LED 2
        [PLATFORM_GPIO_10] = {WICED_P25, WICED_I2C_1_SCL         },
        [PLATFORM_GPIO_11] = {WICED_P28, WICED_SPI_1_MOSI        },      //Optional LED 1
        [PLATFORM_GPIO_12] = {WICED_P29, WICED_I2C_1_SDA         },
        [PLATFORM_GPIO_13] = {WICED_P33, WICED_UART_2_TXD        },
        [PLATFORM_GPIO_14] = {WICED_P34, WICED_UART_2_RXD        },
        [PLATFORM_GPIO_15] = {WICED_P38, WICED_SPI_1_CLK         },
    };

/* LED configuration */
const wiced_platform_led_config_t platform_led[] =
    {
        [WICED_PLATFORM_LED_2] =
            {
                .gpio          = (wiced_bt_gpio_numbers_t*)&platform_gpio_pins[PLATFORM_GPIO_9].gpio_pin,
                .config        = ( GPIO_OUTPUT_ENABLE | GPIO_PULL_UP ),
                .default_state = GPIO_PIN_OUTPUT_HIGH,
            },

// We can use either LED1 or SPI1 MOSI, by default we are using WICED_P28 for SPI1 MOSI,
// uncomment the following initialization if WICED_P28 is to be used as an LED and set PIN
// functionality in platform_gpio_pins as WICED_GPIO

//        [WICED_PLATFORM_LED_1] =
//            {
//                .gpio          = (wiced_bt_gpio_numbers_t*)&platform_gpio_pins[PLATFORM_GPIO_11].gpio_pin,
//                .config        = ( GPIO_OUTPUT_ENABLE | GPIO_PULL_UP ),
//                .default_state = GPIO_PIN_OUTPUT_HIGH,
//            }
    };

SuperMux Tool

The SuperMux tool is a GUI for setting the default configurations of the Pins on the chip.  Like all capable MCUs, this chip has PWMs, SPIs, UARTs, GPIOs, I2C, ADCs etc.  Each pin on the chip can do a bunch of different functions, but only one at a time.  Each pin has a multiplexor in front of it that selects the function of that pin.  The SuperMux tool helps you setup the multiplexors for each pin on the chip.

To run the SuperMux tool, first click on your project directory (remember L3_SuperMux).  The select File–>New–>WICED SuperMux GPIO Pin Configuration

It will ask you which “App Name” you want it to work on.  Since we clicked on the L3_SuperMux app, it uses that name by default.  Press Next

The SuperMux Wizard will give you the opportunity to select which pins you want to configure.  It also shows you the default configuration of each of the pins.  In this case just press “Next” because we want to configure them all.

Now you will see the functions of the chip and which pins they are assigned to.  Notice that WICED_P28 is assigned as the MOSI of SPI(Slave)_1.  We don’t want that.

Remove the SPI(Slave)_1 by selecting it and then pressing the “Remove” button

Now your screen will look like this.  In order to add a new pin configuration you can press the little “+” at the bottom of the function column.

Next press the little “+” button and select LED.

The select which Pin you want assigned to the LED.  In this case we want WICED_P28

After you press finish you will notice that it adds a several files to your project.  And you notice that it creates a file called “makefile.mk.bak” (which is the backup of the original makefile)

First look at the makefile and notice that it added the “L3_SuperMux_pin_config.c” to the sources and added a CFLAG

#
# Lesson 3 - SuperMux
#
APP_SRC +=  L3_SuperMux.c

C_FLAGS += -DWICED_BT_TRACE_ENABLE
C_FLAGS += -DSMUX_CHIP=$(CHIP)
APP_SRC += L3_SuperMux_pin_config.c

So, what is up with the  L3_SuperMux_pin_config.c.  OH!!! I See, this is just a replacement for the default platform configuration.  Notice that P28 is now a WICED_GPIO and that it is now defined in the LED list.

wiced_platform_gpio_t platform_gpio_pins[]=
	{
		[PLATFORM_GPIO_0]	= {WICED_P00, WICED_GPIO},
		[PLATFORM_GPIO_1]	= {WICED_P02, WICED_PCM_OUT_I2S_DO},
		[PLATFORM_GPIO_2]	= {WICED_P04, WICED_PCM_IN_I2S_DI},
		[PLATFORM_GPIO_3]	= {WICED_P06, WICED_GCI_SECI_IN},
		[PLATFORM_GPIO_4]	= {WICED_P10, WICED_GCI_SECI_OUT},
		[PLATFORM_GPIO_5]	= {WICED_P16, WICED_PCM_CLK_I2S_CLK},
		[PLATFORM_GPIO_6]	= {WICED_P17, WICED_PCM_SYNC_I2S_WS},
		[PLATFORM_GPIO_7]	= {WICED_P25, WICED_I2C_1_SCL},
		[PLATFORM_GPIO_8]	= {WICED_P26, WICED_GPIO},
		[PLATFORM_GPIO_9]	= {WICED_P28, WICED_GPIO},
		[PLATFORM_GPIO_10]	= {WICED_P29, WICED_I2C_1_SDA},
		[PLATFORM_GPIO_11]	= {WICED_P33, WICED_UART_2_TXD},
		[PLATFORM_GPIO_12]	= {WICED_P34, WICED_UART_2_RXD},
	};

const wiced_platform_button_config_t platform_button[WICED_PLATFORM_BUTTON_MAX]=
	{
		[WICED_PLATFORM_BUTTON_1] =
			{
				.gpio			= &platform_gpio_pins[PLATFORM_GPIO_0].gpio_pin,
				.config			= (GPIO_INPUT_ENABLE | GPIO_PULL_UP),
				.default_state	= GPIO_PIN_OUTPUT_LOW,
				.button_pressed_value	= GPIO_PIN_OUTPUT_LOW,
			},
	};

const size_t button_count =  (sizeof(platform_button) / sizeof(wiced_platform_button_config_t));


const wiced_platform_led_config_t platform_led[WICED_PLATFORM_LED_MAX]=
	{
		[WICED_PLATFORM_LED_1] =
			{
				.gpio			= &platform_gpio_pins[PLATFORM_GPIO_9].gpio_pin,
				.config			= (GPIO_OUTPUT_ENABLE | GPIO_PULL_UP),
				.default_state	= GPIO_PIN_OUTPUT_HIGH,
			},
		[WICED_PLATFORM_LED_2] =
			{
				.gpio			= &platform_gpio_pins[PLATFORM_GPIO_8].gpio_pin,
				.config			= (GPIO_OUTPUT_ENABLE | GPIO_PULL_UP),
				.default_state	= GPIO_PIN_OUTPUT_HIGH,
			},
	};

Now that the pins are configured.  We need to setup the PWM.

Configure the Clock and the PWM

Now I will add a little bit of code to the top of  our L3_SuperMux.c to configure the PWM, Clock and Pin.

First add includes for the ACLK and PWM driver.

#include "wiced_hal_aclk.h"
#include "wiced_hal_pwm.h"

Then startup the Clock, Pin and PWM.

    wiced_hal_aclk_enable(2000, ACLK1, ACLK_FREQ_1_MHZ );
    wiced_hal_pwm_configure_pin (WICED_GPIO_PIN_LED_1, PWM1 );
    wiced_hal_pwm_start(PWM1, PMU_CLK, 0xFFFF-500, 0xFFFF-999,0);

If you want to turn on the PWM you need to do three things

  1. Turn on a clock to drive it (line 17) sets the clock frequency to 2000hz
  2. Attach the PWM to a Pin (line 18) attaches PWM 1 to the pin
  3. Turn on the PWM which is a 16-bit up-counting PWM.  When the PWM is reset it will go to 0xFFFF-999 (the period)… then it will switch at 0xFFFF-500 (the compare value)

When you program this your Green LED aka WICED_LED_1 is being driven by the PWM.  And your RED LED is being driven by your firmware.

Documentation

All of the hardware blocks on the chip have a set of API functions to help you interface with them.  You can find all of that in the Documentation

Lesson 2 – WICED Bluetooth: Your First Project(s)

WICED Bluetooth Using the CYW20719

# Title Comment
0 A Two Hour WICED Bluetooth Class WICED Bluetooth Using the CYW20719 in all its glory
1 Resources Links to all of the Cypress WICED information including videos, application notes etc.
2 Your First Project Making Hello World & the Blinky LED
3 The Super Mux Tool Learning about platforms and the Super Mux Tool
4 Snips Using the example projects to learn Bluetooth
5 Bluetooth Designer Using the tool to customize a project and get going fast
6 The CCCD & Notification Writing back to the Central
7 Advertising  Beacon Building a beacon project to advertise your custom information 
8 Scanner Viewing the world around you
9 Bluetooth Classic SPP Using the Serial Port Profile to Transmit Lots of Data

Source code: 

  • git@github.com:iotexpert/wiced_bt_intro.git
  • https://github.com/iotexpert/wiced_bt_intro

 

Summary

For our first project, I am going to stand on the shoulder of giants.  In 1978, Brian Kernighan and Dennis Ritchie published “The C Programming Language”.  Here are pictures of my copy.

Kernighan & Ritchie

The reason you do “Hello, World” is that you want to make sure that your compiler chain, programmer etc are all working correctly with something that is super simple.  The only change that I will make to their classic program is to add the “Blinking LED” which is the embedded developers version of “Hello, World”.

The concepts that I want to show in this lesson are.

  1. How to make a new project – makefile.mk, <appname>.c
  2. How NOT to make a new project
  3. How to create a “Make Target”
  4. CYW920719Q40EVB01 Development Kit
  5. WICED PUART and WICED HCI UART
  6. How to start the bootloader
  7. Where the documentation resides for the WICED 20719 hardware abstraction layer
  8. WICED uses ThreadX RTOS

To make this first project the steps are:

  1. Make a new folder called wiced_bt_class  in the Apps Folder
  2. Make a new folder called L2_HelloWorld in the wiced_bt_intro Folder
  3. Create a new file called L2_HelloWorld.c
  4. Create a new file called makefile.mk
  5. Add the code to print HelloWorld & blink the LED to L2_HelloWorld.c
  6. Add the secret incantation to makefile.mk to build the project
  7. Create a “Make Target”
  8. Connect the development kit to your computer
  9. Attach a serial terminal to the PUART
  10. Run the Make Target to Build and Program

Lets do this!

DO NOT DO File->New Project

I always hate to start with a negative statement… but DO NOT make a file project by doing File->New Project.  This is used for creating a new Eclipse project, not a new WICED Studio project.  In WICED Studio we use the make external build system.  If you do File->New Project all hell is going to break loose.  So don’t do any of the things on this menu:

Hello World & Blinking LED

Now lets get on with making a WICED Studio Project.  First create a new folder to hold the projects for the Class in the “Apps” folder by right-clicking and selecting New->Folder

Give it the name “wiced_bt_class”

Create a folder to hold the first project called L2_HelloWorld

Call the folder L2_HelloWorld

Make a new file called L2_HelloWorld.c by right clicking on the L2_HelloWorld folder and selecting New–>File

Give it the name L2_HelloWorld.c

Make a new file called makefile.mk by right clicking on the L2_HelloWorld directory and selecting New->File

and giving it the name makefile.mk

Add some code to the L2_HelloWorld.c

#include "wiced.h"
#include "sparcommon.h"
#include "wiced_platform.h"
#include "wiced_rtos.h"
#include "wiced_hal_gpio.h"
#include "wiced_bt_trace.h"

APPLICATION_START()
{
    wiced_set_debug_uart(WICED_ROUTE_DEBUG_TO_PUART);

    WICED_BT_TRACE("Hello, World\n");
    while(1)
    {

        WICED_BT_TRACE("Setting 0\n");
        wiced_hal_gpio_set_pin_output(WICED_GPIO_PIN_LED_2,0);
        wiced_rtos_delay_milliseconds(500,KEEP_THREAD_ACTIVE );
        WICED_BT_TRACE("Setting 1\n");
        wiced_hal_gpio_set_pin_output(WICED_GPIO_PIN_LED_2,1);
        wiced_rtos_delay_milliseconds(500,KEEP_THREAD_ACTIVE );
    }
}

Add the secret incantation to the makefile.mk

#
# Lesson 2 - Hello, World
#
APP_SRC +=  L2_HelloWorld.c

C_FLAGS += -DWICED_BT_TRACE_ENABLE

Create a make target

The make target has a VERY specific format.  It is:

directory.directory.appname-platform download

In our case we have all of our projects in a directory called “wiced_bt_class”.  Then we have a directory called “L2_HelloWorld” which holds the exact project.  And our platform name is “CYW920719Q40EVB_01”

Connect the Development Kit To Your Computer

When you plug in your development kit, it will USB enumerate a TWO serial ports.  One of the serial ports (the first one) is called the “WICED HCI UART”.  The second serial port is called the “WICED Peripheral UART” (this is often abbreviated “PUART”)

One of the key things that the WICED HCI UART is used as is a UART to download new code to the bootloader.

The PUART is used as a general purpose serial port.  When we call this function it causes all of our “WICED_BT_TRACE” outputs to go to the the PUART.

    wiced_set_debug_uart(WICED_ROUTE_DEBUG_TO_PUART);

You can see these two UARTs on a PC by running the device manager.

You can see COM17 is the “WICED HCI UART” and COM18 is the “WICED Peripheral UART”

On my Mac I use the program “Serial” which I downloaded from the App Store.

When I run Serial and then to open a Port

You can see the two UARTs.

In order to see the output I will connect to the port with the settings

  • 115200 Baud
  • 8-n-1 (Data bits, Parity, Stop Bits)

With my PC I typically use Putty (remember it was COM18 from the screen above)

On the Mac program serial you can configure it with Terminal->Settings

Program your Development Kit

In the Make Target window you should see a bunch of “targets”.  You probably have a bunch more targets, which came in your installation of WICED Studio by default, but I deleted a bunch of them so I could just see the ones that I created.

To build and program your project, double click the make target we made before.

When you look in the console you should see something like this:

And when you look at your serial terminal you will see this:

And you should also see the blinking LED!!!

Start the Bootloader

If you get this message there are three posibilites

  1. The kit isn’t plugged in
  2. The driver didn’t install properly
  3. The bootloader wont start

Check the first two… and if that doesnt work then what this means is that the bootloader is not listening on the WICED HCI UART.  In order to fix this you need to press reset and hold down the button called “Recover”.  Then release the reset, then release the recover button.  What does this do?  Simple, when the chip comes out of reset, if the recover button is pressed, the chip starts the bootloader instead of the main application.

Here is a picture of the bottom corner of the board.  The button circled in Green is the “Recover”.  The button in Red is “Reset” and the Blue surrounds the LED circuit.

The two LEDs are labeled LED1 and LED2.  LED2 is the Red one, LED1 is the Green one.  The dip switches circled in Blue connect or disconnect the LEDs from the CYW20719.  In my case you can see (barely) that the switch is set to On.  Both of these LEDs are active LOW (0 turns them on)

Lesson 1 – WICED Bluetooth: A Tour of the Resources

WICED Bluetooth Using the CYW20719

# Title Comment
0 A Two Hour WICED Bluetooth Class WICED Bluetooth Using the CYW20719 in all its glory
1 Resources Links to all of the Cypress WICED information including videos, application notes etc.
2 Your First Project Making Hello World & the Blinky LED
3 The Super Mux Tool Learning about platforms and the Super Mux Tool
4 Snips Using the example projects to learn Bluetooth
5 Bluetooth Designer Using the tool to customize a project and get going fast
6 The CCCD & Notification Writing back to the Central
7 Advertising  Beacon Building a beacon project to advertise your custom information 
8 Scanner Viewing the world around you
9 Bluetooth Classic SPP Using the Serial Port Profile to Transmit Lots of Data

Source code: 

  • git@github.com:iotexpert/wiced_bt_intro.git
  • https://github.com/iotexpert/wiced_bt_intro

 

A Tour of the Resources

Cypress is committed to the “Whole Product”.  What that means is that we believe that you should have great software, hardware, dev kits, community etc. experience while using our chip.  So, before we get started Id like to show you all of the learning and development resources available to you.

  1. BLE & Bluetooth Connectivity Solutions
  2. WICED CYW20719 Product Page
  3. CYW20719 Product Guide
  4. CYW20719 Datasheet
  5. CYW20719 Software Features
  6. WICED Module Selection Guide
  7. CYW920719Q40EVB-01 Development Kit
  8. CYW920719Q40EVB-01 Product Page
  9. CYW920719 Quick Start
  10. CYW920719Q40EVB-01 Evaluation Board User Guide
  11. Cypress Community
  12. WICED Studio Bluetooth Community
  13. WICED Studio Bluetooth Forums
  14. WICED Studio
  15. WICED Studio Bluetooth Example Projects
  16. WICED Studio Documentation
  17. WICED Bluetooth API Guide
  18. WICED README.txt
  19. WICED Studio Release Notes
  20. WICED Studio Technical Brief
  21. WICED Bluetooth 101

Bluetooth BR+EDR Connectivity Solutions Page

This pages gets to you all of the Cypress WICED BR+EDR+Bluetooth products

WICED CYW20719 Product Page

When you get the the BLE+Bluetooth products page, then click “BLE+BT” to see just the chips Im talking about here (CYW20719)

CYW20719 Product Guide

The Product Guide is a website that has all (most?) of the links you might need to learn about the CYW20719

CYW20719 Datasheet

The Datasheet always anchors you to the reality of what the chip can and cannot do

CYW20719 Software Features

This webpage has a list of all of the stuff that you have access to inside of the WICED Bluetooth SDK.

And it goes on and on and on from here.

WICED Module Selection Guide

If you feel like building a Bluetooth Product, you are almost certainly going to want to use a FCC certified module.  This guide is a discussion of all of the module vendors.

CYW920719Q40EVB-01 Development Kit

Here is the development kit.  You can see in the picture that this is an Arduino form factor board.  It has a button and and LED plus programmer and UART bridge.  Most importantly it has a daughter card with the 20719 and and antenna.

CYW920719Q40EVB-01 Product Page

The product landing pages for the development kit has lots of resources specific to this kit including the manual and quick start guide.

CYW920719 Quick Start

The Quickstart guide is included in the kit.  Just a single sheet of paper that points out all of the features of the development kit.

CYW920719Q40EVB-01 Evaluation Board User Guide

The Users Guide is the manual for the development kit.  It shows you how to use all of the resouces on the board and how to get going with WICED Studio.

Cypress Community

The community is your anchor for support.  It has all of the documentation etc… and most importantly a vibrant user forum.

WICED Studio Bluetooth Community

The Bluetooth Community website brings together all of the people and product collateral for WICED Bluetooth.

WICED Studio Bluetooth Forums

The actual forum is accessible to everyone to ask questions about the Cypress products.  It is staffed by our technical support team and you will get good answers.

WICED Studio

WICED Studio is the development tool which you can use to build projects.  This will be the central tool used for the rest of this class.

WICED Studio Bluetooth Example Projects

Cypress delivers a bunch of “apps” which range from small examples we call SNIPs to more fully featured projects (in the Demo) folder.  Ill be showing you how to use the in the next set of tutorials.

WICED Studio Documentation

In the “doc” folder resides all of the documentation for WICED bluetooth.

WICED Bluetooth API Guide

The API guide is doxygen generated API documentation for the WICED Bluetooth SDK.

WICED Studio README.txt

WICED Studio Release Notes

 

WICED Studio Technical Brief

WICED Bluetooth 101

I have been working with  some amazing people to build a class for learning WICED Bluetooth.  You can find all of the material at https://github.com/cypresssemiconductorco/CypressAcademy_WBT101_Files

Lesson 0 – A Two Hour WICED Bluetooth Class

Summary

This is the top level web page for a two hour class about getting you started building products with WICED Bluetooth using the CYW20719.  My friend Victor told me that I am totally insane and that I have enough material for a semester long class, but I have faith in you.  The whole point of WICED Bluetooth is to make it possible for you to build your own Bluetooth application using the best Bluetooth radios in the world.  Life is too short for flaky Bluetooth!

When I started working on this class the marketing guys asked if they could show a “few” powerpoint slides at the begining.  But I knew that is just a euphemism for power point carpet bombing you to sleep.  That sucks, so we aren’t doing that.

AFH, TDD, ∏/4 DQPSK, ISM, 8DPSK, Symbol Rate, binary FM modulation, dBi, LMP, AMP, Gaussian Frequency Shift Keying,  Modulation Index, ppm, eye diagram, FCC, Frequency Offset, Slot Length, Frequency Drift, Differential Phase Encoding, Pulse Shaping, Modulation Accuracy, Differential Error Vector Magnitude, BER, Sensitivity, Co-Chanel interference, Intermodulation Characteristics, Symbol rate, Timeslot, piconet clock, piconet channel timing,  blah blah blah blah….

Whew… now that is out of the way.  Forget that.  Rather than start at the bottom with the radio and Maxwells equations I going to start at the top.  Cypress has a huge team of radio designers to deal with all of that so you don’t have to.  To be clear, this stuff matter A LOT to how well your product works but it is only the second best reason to use Cypress WICED Bluetooth.  The best reason to use Cypress is that our software team lets you have access to the most robust Bluetooth stack and radio infrastructure without having to figure all that crap out.  You may, in time, dig into all of that.  But none of it matters for building your applications.

This workshop is hands on, as that is the only real way to learn.  This series of web pages have the exact steps that I am going to use, so you can follow along with me.

You will need a few things for the class:

  • WICED Studio 6.2.1 which you can download from the Cypress Community
  • Copies of the example projects which you can get from GitHub.
  • A CYW920719Q40EVB-01 which you can get from Mouser
  • A Terminal Program like Putty
  • CySmart, a Bluetooth GATT DB Browser for Android (Google Play Store) or iPhone (Apple App Store)
  • The courage to be WICED!

Todays virtual workshop is going to go like this:

WICED Bluetooth Using the CYW20719

# Title Comment
0 A Two Hour WICED Bluetooth Class WICED Bluetooth Using the CYW20719 in all its glory
1 Resources Links to all of the Cypress WICED information including videos, application notes etc.
2 Your First Project Making Hello World & the Blinky LED
3 The Super Mux Tool Learning about platforms and the Super Mux Tool
4 Snips Using the example projects to learn Bluetooth
5 Bluetooth Designer Using the tool to customize a project and get going fast
6 The CCCD & Notification Writing back to the Central
7 Advertising  Beacon Building a beacon project to advertise your custom information 
8 Scanner Viewing the world around you
9 Bluetooth Classic SPP Using the Serial Port Profile to Transmit Lots of Data

Source code: 

  • git@github.com:iotexpert/wiced_bt_intro.git
  • https://github.com/iotexpert/wiced_bt_intro

 

WICED Studio 6.2.1

This class is build around WICED Studio 6.2, the Cypress IDE built on top of Eclipse.  WICED Studio has all of the tools, examples and SDKs to build projects for the Cypress WICED Bluetooth and WiFi products.  We support Windows, Mac and Linux and you can download it from our community website: https://community.cypress.com/community/wireless (which I hope you have done by now)

CYW920719Q40EVB-01

I am going to build and program all of the projects in this class into our development kit, the CY920719Q40EVB-01.  This development kit (which you should buy from Mouser) uses the Cypress CYW20719 Bluetooth chip.  This is the worlds best Dual-mode Bluetooth 5.0 chip.  Dual mode means that it does Bluetooth Classic BR/EDR as well as Bluetooth Low Energy.  Even better it can do both standards at the same time.

JST Connector Crimping Insanity

[Edit] Since I published this article, Tom Nardi at Hackaday wrote an article entitled “The unnecessary? Art of Connector Crimping” about my article where he pointed out that I am not the first person to come to that conclusion.  He made reference to several useful things

  1. JST is not a Connector
  2. BRADLEY GAWTHROP: WHAT YOU NEED TO KNOW ABOUT WIRING

[Edit] The Wikipedia article on JST has a nice table.

Summary

Last week I was using a CY8CKIT-062-BLE PSoC 6 development kit with a Digilent PMOD-HB5 connected to the PMOD port.  Specifically, I was using the PMOD HB5 as a solid state switch to drive a higher voltage, higher current than the GPIO on the PSoC 6 can drive.  In order to do this I needed to connect to the “6-pin JST connector for direct connection” which is on the right side of the board in the picture below.

Digilent PMOD HB5

But, what I might ask, is a JST Connector?  And, how might you make a connection to it.  Well, this where the insanity starts.  The first thing that you will discover is that “JST” stands for Japan Solderless Technology and that they make about 50,000 different types of connectors.  The next thing that you will discover is that all around the internet on the maker websites you will find people referring to connections as “JST” and acting like there is only one type of JST connector.  Then you will discover that there are tons of youtube videos that “show” you how to crimp JST connectors, and that most of them are absolute crap, particularly if you are 50 years old can barely see the freaking crimp connectors.  Finally, you will discover that there are a boatload of crimping tools that range in price from $10 (for a crap pair of pliers) to $500 (for the OEM JST Crimpers)

For this article I am going:

  1. Tour the common version of the JST connectors, where they are used.
  2. Consider not crimping
  3. Show pictures of a proper crimp
  4. Show some JST crimping tools
  5. Take you through my crimping procedure – which seems to work
  6. Some other videos/resources

Honestly the whole thing is pretty annoying.  The crimps are a bit hard to make and there is this inherent assumption everywhere that you should have just “known” how to do this.

I will also observe that the “JST” problem extends to some other crimp connectors including “Molex” and “Dupont” (which has a crazy history).  I will write about these other two types later on.

The JST Connector Series

Series Pitch Wire Connector Use
PH 2.0 24 JST PH Connector Digilent PMOD HB5
SM 2.5 28 JST SM Connector Adafruit Adafruit NEOLED
SH 1.0 28 JST SH Connector Spark Fun QWIIC 
XH 2.5 22 JST XH Connector Some batteries
ZH 1.5 26 JST ZH

Consider not Crimping

The first thing that I will say about the crimping process is that you should consider not doing it.  It is possible that purchase pre-crimped wires which will then easily slip inside of the connector housing to create almost any combination you might want.  Here is a pile of the the raw wires with crimps on one end:

JST PH Connector

And here are some that are pre-made into 6-pin connections.

JST Connector

A Good Crimp

So… you really want to make your own crimps?  OK.  Before I tell you HOW to do a good crimp, I want to show you what you are trying to do.  When you buy the crimp connectors, they will come on a metal strips which are meant to go through a machine that automatically crimps wires in China (obviously we are going to do it manually).

JST Connector

Each crimp connector has two sets of wings, which you will bend during the process.  One set holds the wire and the other holds the insulation.  Here is a zoom of some of the connectors where you can see the wings.

JST Connector

In the picture below you can see that there are two sets of wings.  The set in the middle crimps the raw wire.  The set that is near the strip is for the insulation.

JST Connector

Here is a picture of what we are trying to achieve with the crimp.  You can see that the inner crimp grabs all of the wires and the outer crimp grabs the insulation on the wire.

JST Connector

Once you have the wires crimped they will snap into a plastic housing that gangs them together.  In the picture below you can see that on the backside of the crimp connector there is a little piece that is bent up.  That will snap under the little plastic tab on the housing.  (it is a 2-pin housing)

JST Connector

In this picture you can see another view of the piece of metal that is bent up to grab the plastic.

JST Connector

Once you stick the crimp connector into the housing it will look something like this.  When you push the wire into the housing you will get a very satisfying little click (assuming you haven’t destroyed the crimp connector metal too much)

JST Connector

Crimping Tools

I bought a range of tools, but these tools from a Japanese company called “Engineer” seemed to be the best.  These tools are less “efficient” because you have to crimp twice, once for the wires and once for the insulation, but they seem to be easier not to screw up with.  The difference between PA-09 and PA-20 is the range of crimp sizes that you can do.

Engineer PA-20 & PA-09

I bought these two tools from Amazon for about $20… and they crimp both sets of wings at one time… but I have not had good luck with them.

IWISS Crimper

The actual JST crimper is really cool, but it had better be for $470.  I haven’t tried it because the Engineer PA-09 worked so well.  It can crimp both sets of wings at the same time and automatically positions the crimp connector to the exact right place.  But it also only works for one type of connector, in this case the JST-PH

JST WC-240

JST Connector Crimping Procedure

I would not say that my process is canonical, but it works.

(1) Start by stripping the end of your wire, then giving it a little twist.  I use a stripping tool called a “Knipex 12 42 195”.  The strip should be about 2-3mm

Knipex Stripper

(2) Then break off a crimp connector from the strand.  Hold it in your left hand and stick the wire wings into the 1.6mm section of the tool.  The wings should point into the crimper (look at the picture) so that when you crimp, that they bend back on themselves.  You want to make sure that the outer insulation wings are not in the crimper, meaning we are only going to crimp the inside wings on the first crimp.

JST Connector

Here is a picture where you can see that things are all lined up.

JST Connector

Dont crimp yet, but push down a little bit to hold the crimp connection in place while you use your left hand to pick up the wire.

JST Connector

(3) Insert the wire into the crimp connection.  The plastic insulation should end at the edge of the crimper (it should not stick into the connection).  In my experience, the insulation is too big to go into the connection and the side of the crimp tool keeps it from going in.

  JST Connector

(4) Then crimp it… and you will have something that looks like this.  You can see that the strands of the wire are under the newly folded wings… and the outer wings are still open.

JST Connector

(5) Use the end of the crimper to bend the out wings in just a little bit so that it can fit into the crimp tool.  Just make them so that they are parallel.

JST Connector

(6) Next put it in the crimp connection into the 1.9mm slot (from the other side) & crimp.

JST Connector

Now you should have a crimped connection

And here is a short video of me completing a JST Connector crimp

In my experience the thing that go wrong when crimping a JST Connector are

  1. I over crimp and bend the crap out of the connection
  2. I strip either too much or not enough wire
  3. I dont push the wire in far enough, which ends up with me not crimping insulation.

 

IOT Expert 2017 Year in Review and 2018 Goals

Summary

I have been struggling a little bit to write the 2017 year end review.  The basic reason is that although I made a boatload of progress on the website, it has been feeling a little bit like a job.  That being said, I made significant progress on posts, visits, unique visitors and page views.  Also, with the help of Yakob we released a major facelift to the look and feel of the website.

Here is a summary of the data.

Metric 2016 2017 Multiple
Visitors 16156 64493 4.0
Visits 54582 262299 4.8
Page Views 207551 595179 2.9
Posts 76 90 1.2

However, you might notice that I don’t have the goals for those metrics in the table, which as you might guess, means that I was far away from where I was hoping to get.

2017 Data

The data from the web server looks really good with generally increasing numbers of visits and visitors.  For the next year I want to get google analytics going again.

2017 Goals

I copied the following text directly from my article last year called IoT Expert Year in Review 2016 and 2017 Goals

For 2017 my goals fall into three broad categories.  First, I want to continue creating (hopefully) interesting, high-quality IOT engineering content [I think I did pretty well here].  To that end I would like to:

  1. Achieve 2x/week posts and hit 104 posts for the year. [I completed 90 posts… which in hindsight is pretty good, but didn’t meet my goal]
  2. Create a new video series and post 12 videos [I did not make any progress on this idea]

In addition to the new content, I would like to improve the accessibility of my website by

  1. Deploying a mailing list [Not Done]
  2. Automatically connecting to Twitter [Not Done]
  3. Automatically connecting to Facebook [Not Done]
  4. Developing a Linked-In strategy [Not Done]
  5. Fixing my release process to use best practices for all meta-data [Done]

such that I achieve

  1. 10x User Traffic (15,594 –> 69,493)
  2. 10x Twitter followers on @askiotexpert (50–>146)
  3. 10 Google keywords where www.iotexpert.com is a first page hit

Lastly, I want to update and deploy a new brand for iotexpert including logo’s, web page headers, Facebook covers, etc. [Done]

2018 Goals

For 2018, I think that I will strive to make it more fun for myself, with the goal of publishing 1/week.  I hope to create articles on:

  • WICED WiFi
  • WICED Bluetooth
  • PSoC 6
  • RTOS (Linaro, MBEDOS, Apache Newt)
  • FileSystem

I do not think that I will set specific goals for the rest of the data and we will just have to see what happens.

EEWeb – IoT Expert Site of the Day

This morning I was looking around on the Web… and look what I found,  IoT Expert was site of the day with EEWeb yesterday.  How cool is that?  I had been trading email with Aubrey Kagan about getting this arranged – so thank you Aubrey.

EEWeb is a super cool website thas a lot gong on.  There are articles and example projects, a lot of similar to stuff to what I do. I got introduced to EEWeb earlier this year by a friend of mine, Adam Carlson (the editor) who I met face to face earlier this  year at a Maker Faire.

What I didn’t realize (though it should have been obvious) was this website was the spawn of EETimes, which was for years the classic industry publication.

Here are two screen shots.

IoTExpert on EEWEB

 

IoTExpert on EEWEB

 

Lesson 5 – PSoC 6 Introduction: Bluetooth Low Energy

PSoC 6 Introduction

# Title Comment
0 A Two Hour PSoC 6 Class An introduction to the PSoC 6 class with links to all of the documents
1 Resources Links to all of the Cypress PSoC 6 information including videos, application notes etc.
2 Your First Project Learn how to build a PSoC 6 project and program your CY8CKIT-062-BLE development kit
3 FreeRTOS and a Debugging UART Build a project using FreeRTOS including a debug console with the UART
4 CapSense Build a project using the Mutual Cap Buttons and Self Cap Slider
5 Bluetooth Low Energy Build a CapSense project using BLE and CySmart

Since I did the webinar several things have happened

  1. Lesson 4: I fixed an error in the stack size for FreeRTOS
  2. Lesson 5: The PSoC Creator BLE PDL has been upgraded to greatly simplify the notifyCapSense function

All of the projects are available at git@github.com:iotexpert/psoc-6-introduction.git or www.github.com/iotexpert/psoc-6-introduction

Project Description

This project is a PSoC 6 BLE extension of the previous project with CapSense and UART.

The BLE will:

  • Advertise the device with the name “P6Intro” and as having the CapSense Service
  • Will allow one connection (with no security)
  • A BLE CapSense Service with the CapSense Slider characteristic as “notify”
  • When the CapSense slider updates it will send a notification to any connected device

The CapSense will (same as before)

  • BTN0 will set the intensity to 0%
  • BTN1 will set the intensity to 100%
  • CapSense slider will set the intensity (0-100) when touched

The UART will (same as before)

  • UART Key ‘0’ turn the LED to intensity = 0%
  • UART Key ‘1’ turn the LED to intensity = 100%
  • UART Key ‘5’ turn the LED to intensity = 50%
  • UART Key ‘?’ will printout help

How does it work?

This device will act as a GAP Peripheral with a GATT database server with the CapSense Service.  The PSoC 6 BLE component will allow you to split the BLE function onto the CM0+ (Controller) and the CM4 (Host and Profiles).  On the CM4 you will build an event handler which will act each time something happens in the Bluetooth world e.g. a connection, a disconnection, a read or write.

(same as previous project) You can control the intensity of an LED with a pulse width modulator and a high frequency input clock.  If the duty cycle is “small” then the intensity of the LED is low (meaning dim).  If the duty cycle is “big” then the intensity is “high”.  A 0% duty cycle will be off, a 50% duty cycle will be in the middle and 100% duty cycle will be all on.  To make this work I will set the input clock to 1 MHZ and the PWM Period to 100.  The PWM Compare value will then be set between 0 and 100 to represent brightness in percent.

(same as previous project) The Cypress CapSense block has two sensing modes, mutual capacitance and self-capacitance.   The CY8CKIT-062-BLE has two Mutual Capacitance buttons and a 5-Segment Self or Mutual Capacitance Slider.

The project will have four tasks

  • BLE – Will act as a BLE GATT Peripheral that advertises the CapSense Service with the CapSense Slider.  The value of the slider will ‘Notify’
  • UART – Read data from the keyboard and send messages to the PWM Task
  • CapSense – Read finger positions from the slider and buttons and send messages to the PWM Task
  • PWM – Will have an input queue, when a integer message is received it will set the PWM compare value to the integer received (0 >= msg <= 100)

How am I going to do it?

  1. Copy, Paste and Rename the CapSense UART Project
  2. Add and Configure the BLE Component
  3. Fix the Interrupts
  4. Update the main_cm0p. c to run the BLE radio
  5. Add three global variables to main_cm4.c
  6. Create a new task to process the BLE
  7. Create an Event Handler
  8. Make a Function to Send Notifications
  9. Update the capSenseTask to Send Values
  10. Add the bleTask to main function in main_cm4.c
  11. Program and Test

Copy, Paste and Rename the CapSense UART Project

Right click on the PSoC-6-Introdution and Paste

Right click and rename the project to be CapSense_BLE

When is asks you to rename… do it

It should look like this now.

Add and Configure the BLE Component

Go to the Component Catalog and find the Bluetooth Low Energy component and drag/drop it into your design schematic.

Configure the component to be a “Dual Core …” and set the  number of connections to 1.

Add the Capsense service to your server by clicking “Load Service…”

And selecting the “CapSense.service” file.  I created this file to have the right UUIDs and characteristics.

You can now look at the CapSense Slider service and the CapSlider characteristic

Set the name of our peripheral in the “GAP Settings”.  In this case I will call it P6INTRO.

Configure the advertising settings to advertise the name of the device and the CapSense Service.

Fix the Interrupts

Almost all of the interrupt sources in the PSoC 6 can be connected to one or both of the Cortex cores.  I think that you are probably crazy to attach it to both.  In this case the BLE interrupt needs to be connected to the “ARM CM0+”

Update main_cm0p. c to Run the BLE Radio Controller

#include <project.h>
int main(void)
{
    __enable_irq(); /* Enable global interrupts. */
  
   
    Cy_BLE_Start(0);
    
    /* Enable CM4.  CY_CORTEX_M4_APPL_ADDR must be updated if CM4 memory layout is changed. */
    Cy_SysEnableCM4(CY_CORTEX_M4_APPL_ADDR); 
    

    for(;;)
    {
        Cy_BLE_ProcessEvents();
    }
}

Add three global variables to main_cm4.c

The BLE Task will have a queue that the CapSense will use to send out changes in the CapSense Slider.

QueueHandle_t bleQueueHandle;
int connected=0;
int notify=0;

Create a new task to process the BLE

The. task will just start up the BLE processing on the CM4.  Then it will cause the BLE event manager to run.  If a new value of the CapSense slider is set, it will send out a notification using the “notifyCapSense” function

// bleTask handles the BLE connection (or not).. if the user connects and turns on
// notifications then it sends out new values of the CapSense slider
void bleTask(void *arg)
{
    (void)arg;   
    uint32_t msg;
    
    printf("Starting BLE Task\r\n");
    bleQueueHandle = xQueueCreate(1,sizeof(uint32_t));
    Cy_BLE_Start(customEventHandler);
    
    for(;;)
    {
        Cy_BLE_ProcessEvents();
        
        // CapSense task will put CapSense slider values in the bleQueueHandle
        if(xQueueReceive(bleQueueHandle,&msg,0) == pdTRUE)
            notifyCapSense((uint8_t)msg);
       
        taskYIELD();
    }
}

Create an Event Handler

You will need a task to handle the BLE processing on the CM4.  Each time a Bluetooth event occurs you will need to do “something”

// This event handler is called by BLE
void customEventHandler(uint32_t event, void *eventParameter)
{
     cy_stc_ble_gatts_write_cmd_req_param_t   *writeReqParameter;   

    switch (event)
    {
        case CY_BLE_EVT_STACK_ON:
        case CY_BLE_EVT_GAP_DEVICE_DISCONNECTED: // Central disconnects
            Cy_BLE_GAPP_StartAdvertisement(CY_BLE_ADVERTISING_FAST,CY_BLE_PERIPHERAL_CONFIGURATION_0_INDEX);
            connected = 0;
            notify=0;
        break;

        case CY_BLE_EVT_GATT_CONNECT_IND: // A Central connection is made
            connected = 1;
        break;
        
        case CY_BLE_EVT_GATTS_WRITE_REQ:
            writeReqParameter = (cy_stc_ble_gatts_write_cmd_req_param_t *)eventParameter;

            if(CY_BLE_CAPSENSE_CAPSLIDER_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE ==  writeReqParameter->handleValPair.attrHandle)
                notify = writeReqParameter->handleValPair.value.val[0];
              
            Cy_BLE_GATTS_WriteRsp(writeReqParameter->connHandle);
        break;

        default: // Ignore all other events
        break;
    }
}

Make a Function to Send Notifications

// This function is run inside BLE Task and sends notification if you are connected and notifications are on
void notifyCapSense(uint8_t capValue)
{    
    if(!(connected && notify))
        return;
    
    cy_stc_ble_gatts_handle_value_ntf_t v1;
    v1.connHandle = cy_ble_connHandle[0];
    v1.handleValPair.attrHandle = CY_BLE_CAPSENSE_CAPSLIDER_CHAR_HANDLE;
    v1.handleValPair.value.len = 1;
    v1.handleValPair.value.val = &capValue;
    
    Cy_BLE_GATTS_Notification(&v1);
        
}

EDIT!!!!

If you look at the source code at GitHub you will find that I removed the variables “connected” and “notify” and I changed the notifyCapSense function.  This was done because the BLE PDL implementation was greatly improved and simplified. The new function iterates through the connections and sends the notification to all of them.  This was done to handle multiple connections.

// This function is run inside BLE Task and sends notification if you are connected and notifications are on
void notifyCapSense(uint8_t capValue)
{    
   
    unsigned int index;
    
    printf("Sending CapSense %d\r\n",capValue);
   
    cy_stc_ble_gatt_handle_value_pair_t handleValuePair;
    handleValuePair.attrHandle = CY_BLE_CAPSENSE_CAPSLIDER_CHAR_HANDLE;
    handleValuePair.value.val = &capValue;
    handleValuePair.value.len = 1;
    
    Cy_BLE_GATTS_WriteAttributeValueLocal(&handleValuePair);
   
    /* Iterate and send notiication to all the connected devices that are ready to receive notification */
    for(index = 0; index <CY_BLE_CONN_COUNT; index++)
    {     
        Cy_BLE_GATTS_SendNotification(&cy_ble_connHandle[index], &handleValuePair);
    }
        
}

Update the capSenseTask to Send Values

Inside of the capsenseTask you need to send new values of the slider to the BLE task via the Queue.  Meaning the BLE task needs to send out notifications, but it can only do that if the capsenseTask notifies it of changes.

sliderPos=CapSense_GetCentroidPos(CapSense_LINEARSLIDER0_WDGT_ID);
            if(sliderPos<0xFFFF) // If they are touching the slider then send the %
            {
                msg = sliderPos;
                xQueueSend(pwmQueueHandle,&msg,0); // Send message to PWM - change brightness
                xQueueSend(bleQueueHandle,&msg,0); // Send message to BLE
            }

Add the bleTask to main function in main_cm4.c

In the main function you need to start the BLE Task.

xTaskCreate( bleTask, "BLE Task",4096,0,3,0);

Program and Test

To test this project I will run the CySmart iOS App.  First, you can see all of the devices that are advertising

CySmart

Scroll left (or right) to find the “CapSense Slider”

When you see it, Press on the CapSense Slider Icon

Then put your finger on the slider and you should see it change

Here is a picture of the whole system.

PSoC 6 BLE CapSense & CySmart

Lesson 4 – PSoC 6 Introduction: CapSense

PSoC 6 Introduction

# Title Comment
0 A Two Hour PSoC 6 Class An introduction to the PSoC 6 class with links to all of the documents
1 Resources Links to all of the Cypress PSoC 6 information including videos, application notes etc.
2 Your First Project Learn how to build a PSoC 6 project and program your CY8CKIT-062-BLE development kit
3 FreeRTOS and a Debugging UART Build a project using FreeRTOS including a debug console with the UART
4 CapSense Build a project using the Mutual Cap Buttons and Self Cap Slider
5 Bluetooth Low Energy Build a CapSense project using BLE and CySmart

Since I did the webinar several things have happened

  1. Lesson 4: I fixed an error in the stack size for FreeRTOS
  2. Lesson 5: The PSoC Creator BLE PDL has been upgraded to greatly simplify the notifyCapSense function

All of the projects are available at git@github.com:iotexpert/psoc-6-introduction.git or www.github.com/iotexpert/psoc-6-introduction

Project Description

This project is a demonstration of a PSoC 6 running an RTOS using CapSense and the UART to control the intensity of the Red LED with a Pulse Width Modulator (PWM)

The CapSense will:

  • BTN0 will set the intensity to 0%
  • BTN1 will set the intensity to 100%
  • CapSense slider will set the intensity (0-100) when touched

The UART will:

  • UART Key ‘0’ turn the LED to intensity = 0%
  • UART Key ‘1’ turn the LED to intensity = 100%
  • UART Key ‘5’ turn the LED to intensity = 50%
  • UART Key ‘?’ will printout help

How does it work?

You can control the intensity of an LED with a pulse width modulator and a high frequency input clock.  If the duty cycle is “small” then the intensity of the LED is low (meaning dim).  If the duty cycle is “big” then the intensity is “high”.  A 0% duty cycle will be off, a 50% duty cycle will be in the middle and 100% duty cycle will be all on.  To make this work I will set the input clock to 1 MHz and the PWM Period to 100.  The PWM Compare value will then be set between 0 and 100 to represent brightness in percent.

The Cypress CapSense block has two sensing modes, mutual capacitance and self capacitance.   The CY8CKIT-062-BLE has two Mutual Capacitance buttons and a 5 segment Self or Mutual Capacitance Slider.

The project will have three tasks

  • UART – Read data from the keyboard and send messages to the PWM Task
  • CapSense – Read finger positions from the slider and buttons and send messages to the PWM Task
  • PWM – Will have an input queue, when a integer message is received it will set the PWM compare value to the integer received (0 >= msg <= 100)

How am I going to do it?

  1. Create a new project by copy/paste the FreeRTOS-UART Project
  2. Configure Schematic for Higher Frequency Clock and Change PWM Settings
  3. Add a new PWM task and modify the UART
  4. Program and Test
  5. Edit the FreeRTOS.h and make a bigger heap
  6. Add the CapSense Buttons to the Schematic and Set the Pins
  7. Add the capsenseTask
  8. Program and Test
  9. Add the CapSense Slider to the Schematic and Set the Pins
  10. Update the capsenseTask
  11. Program and Test

Create a new Project by Copy/Paste of FreeRTOS-UART Project

Right click on the FreeRTOS-UART Project then select “Copy”

PSoC 6 Create New Project - Copy

Then right click on the Workspace and select “Paste”

PSoC 6 Create New Project - Paste

 

Right click on “FreeRTOS-UART-Copy01)” and rename it to “CapSense”

PSoC 6 Create New Project - Rename

Click “Rename” (all of these files will be regenerated so it doesn’t really matter)

PSoC 6 Create New Project - Rename

Close all windows by right clicking “Close All But This” on the start tab

PSoC Creator Close All Windows

Configure Schematic for Higher Frequency Clock and Change PWM Settings

If you blink the LED fast enough, you will not be able to see the “Blink” it will just appear to be bright or dim based on the duty cycle.  Start by changing the clock to 1 MHz.

PSoC 6 Update Clock

Double click on the PWM_1

PSoC 6 Update TCPWM

Fix the Period to be 100 and the compare to be 50

PSoC 6 Update TCPWM

The LED on the CY8CKIT-062-BLE is active low which means that when it is 0 the LED is on.  I want the opposite behavior so I can configure the PWM output to be inverted on the advanced tab.  Click the button next to “Invert PWM Output”

PSoC 6 Update TCPWM Advanced

Add a new PWM Task and Modify the UART Task

Next, I will create the pwmTask function.  It will simply wait for someone to send a message to the pwmQueue.  The message is simply a uint32_t that represents the PWM compare value … aka the percent intensity of the LED.  When it gets the value, it will update the hardware.

Edit: In the comments below you can see that Charles asked that I clarify where these functions should go.  When I did this, I put them basically at the top of the file… just under the #includes.   The only thing that really matters is that they need to be put before they are used so that the compiler knows the function prototypes.  If you put them after they are used then you need to make forward declarations.

#include "queue.h"
QueueHandle_t pwmQueueHandle; 

// This task controls the PWM
void pwmTask(void *arg)
{
    (void)arg;
    
    uint32_t msg;
    
    printf("Starting PWM Task\r\n");
    pwmQueueHandle = xQueueCreate(1,sizeof(uint32_t));
   
    while(1)
    {
        xQueueReceive(pwmQueueHandle,&msg,portMAX_DELAY);
        Cy_TCPWM_PWM_SetCompare0(PWM_1_HW,PWM_1_CNT_NUM,msg);
   }
}

In the main function you need to start the pwmTask

xTaskCreate(pwmTask,"PWM Task",configMINIMAL_STACK_SIZE*8,0,3,0);

Next, I will update the uartTask

  • To not getchar’s unless there is something in the RX buffer of the UART (line 13).
  • Create a message aka a uin32_t based on the key pressed and send it with xQueueSend
  • If there was nothing there then taskYIELD to one of the other tasks (line 35)
// uartTask - the function which handles input from the UART
void uartTask(void *arg)
{
    (void)arg;
    
    char c;
    uint32_t msg;

    printf("Started UART Task\r\n");
    setvbuf(stdin,0,_IONBF,0);
	while(1)
	{
		if(Cy_SCB_UART_GetNumInRxFifo(UART_1_HW))
		{
		    c = getchar();
    		switch(c)
	    	{
		    	case '0': // send the stop message
			    	msg = 0;
		    		xQueueSend(pwmQueueHandle,&msg,portMAX_DELAY);               
		    	break;
		    	case '1': // Send the start message
		    		msg = 100;
		    		xQueueSend(pwmQueueHandle,&msg,portMAX_DELAY);
		    	break;
			    case '5':
				    msg = 50;
				    xQueueSend(pwmQueueHandle,&msg,portMAX_DELAY);
			    break;
			    case '?': // Print Help 
				    printf("s - stop PWM\r\nS - start PWM\r\n");
			    break;
		    }
		}
		taskYIELD();
    }
}

Program and Test

PSoC 6 Test PWM

Edit the FreeRTOS.h and make a bigger heap

The CapSense task is going to take more heap space that is currently allocated for FreeRTOS.  To fix this I need to edit the FreeRTOS.h and change the heap size to 48K (which I picked out of the air)

#define configTOTAL_HEAP_SIZE                   (48*1024)

Add the CapSense Buttons to the Schematic and Set the Pins

In order to add CapSense to the design, you find the CapSense component in the Component Catalog. Then you drag it into your schematic.

PSoC 6 Add CapSense Component

The next thing to do is configure the CapSense block.  I start by re-naming it to “CapSense”.  Then I click on the plus and add two “Button”s to the design.

PSoC 6 Add CapSense Buttons

Then I change the configuration to “CSX (Mutual-cap).

PSoC 6 Setup Mutual CapSense

On the CY8CKIT-062-BLE, there is a shared transmit line. This saves 1 pin.  You need to tell the CapSense component that you are using a shared Tx.  To do this click on Advanced -> Widget Details.  Then pick “Button1_tx” and set the Sensor Connection / Ganging to “Button0_Tx”

PSoC 6 Setup CapSense Tx

Once the CapSense is configured you need to Set the Pins.

PSoC 6 Fix Pins

Next you run “Generate Application” which will let PSoC Creator place and route the design plus bring in all of the required drivers.

Add the capsenseTask

Now create a new task function called capsenseTask it will

  • Use 4 variables to hold the previous and current state of the buttons (line 81-84)
  • Start the CapSense Block (line 88)
  • Start CapSense Scanning (line 89)
  • If the CapSense hardware is not busy then you can talk to it. (line 93)
  • Start by turning the raw data into useable information (line 96)
  • Read the state of the buttons (line 98-99)
  • If the button state has changed, then send a message to the PWM Task (line 101-110)
  • Save the state of the buttons (line 111-112)
  • Update the baseline information (line 114)
  • Start Scanning again (line 115)
  • If the CapSense block is busy then yield to the other tasks (line 118)
// capsenseTask
// Read buttons and slider using CapSense and send messages to pwmQueue
void capsenseTask(void *arg)
{
    (void)arg;
    
    uint32_t msg;
    
    int b0prev=0;
    int b1prev=0;
    int b0current=0;
    int b1current=0;
    int sliderPos;
    
    printf("Starting CapSense Task\r\n");
    
    CapSense_Start();
    CapSense_ScanAllWidgets();
        
    for(;;)
    {
        if(!CapSense_IsBusy())
        {
            CapSense_ProcessAllWidgets();
/*
            sliderPos=CapSense_GetCentroidPos(CapSense_LINEARSLIDER0_WDGT_ID);
            if(sliderPos<0xFFFF) // If they are touching the slider then send the %
            {
                msg = sliderPos;
                xQueueSend(pwmQueueHandle,&msg,portMAX_DELAY);
            }
*/
            b0current = CapSense_IsWidgetActive(CapSense_BUTTON0_WDGT_ID);
            b1current = CapSense_IsWidgetActive(CapSense_BUTTON1_WDGT_ID); 
            
            if(b0current && b0prev == 0) // If they pressed btn0
            {
                msg = 0; 
                xQueueSend(pwmQueueHandle,&msg,portMAX_DELAY);
            }
            if( b1current && b1prev == 0) // If they pressed btn0
            {
               msg = 100;
               xQueueSend(pwmQueueHandle,&msg,portMAX_DELAY);  
            }
            b0prev = b0current;
            b1prev = b1current;
               
            CapSense_UpdateAllBaselines();
            CapSense_ScanAllWidgets();
        }
        else
            taskYIELD();
            
    }    
}

And start the capSense task in main.

xTaskCreate( capsenseTask, "CapSense Task",2048*2,0,3,0);

Program and Test

PSoC 6 Test CapSense Buttons

Add the CapSense Slider to the Schematic and Set the Pins

To make the slider work you need to add a LinearSlider widget by pressing the “+” and selecting LinearSlider

PSoC 6 Add CapSense Slider

Once you have added the LinearSlider you need to set the pins for the new CapSense Slider

PSoC 6 Fix CapSense Slider Pins

Update the capsenseTask to Include the Slider

The changes are small to make the LinearSlider work.  You just need to

  1. Read the position of the slider (line 99)
  2. The slider will be 0xFFFF if there is no touch… in which case ignore it (line 100)
  3. If you got a touch, then make that a message and set it to the PWM (line 102-103)
          sliderPos=CapSense_GetCentroidPos(CapSense_LINEARSLIDER0_WDGT_ID);
            if(sliderPos<0xFFFF) // If they are touching the slider then send the %
            {
                msg = sliderPos;
                xQueueSend(pwmQueueHandle,&msg,portMAX_DELAY);
            }

Program and Test

PSoC 6 CapSense Slider

Lesson 3 – PSoC 6 Introduction: FreeRTOS and a Debugging UART

PSoC 6 Introduction

# Title Comment
0 A Two Hour PSoC 6 Class An introduction to the PSoC 6 class with links to all of the documents
1 Resources Links to all of the Cypress PSoC 6 information including videos, application notes etc.
2 Your First Project Learn how to build a PSoC 6 project and program your CY8CKIT-062-BLE development kit
3 FreeRTOS and a Debugging UART Build a project using FreeRTOS including a debug console with the UART
4 CapSense Build a project using the Mutual Cap Buttons and Self Cap Slider
5 Bluetooth Low Energy Build a CapSense project using BLE and CySmart

Since I did the webinar several things have happened

  1. Lesson 4: I fixed an error in the stack size for FreeRTOS
  2. Lesson 5: The PSoC Creator BLE PDL has been upgraded to greatly simplify the notifyCapSense function

All of the projects are available at git@github.com:iotexpert/psoc-6-introduction.git or www.github.com/iotexpert/psoc-6-introduction

Project Description

This project will show you how to build a PSoC 6 project that is running FreeRTOS and printing information to the debugging UART

How does it work?

The PSoC 6 is a very capable, fast dual Coretex-M MCU.  In order to manage your design complexity that can be attacked with this chip, we gave you the ability to use a Real Time Operating System – FreeRTOS.  With a few simple clicks it will startup for you.

The CY8CKIT-062-BLE has a KitProg-2 Debugger/Programmer on board.  In addition to Program/Debug it can also serve as a USB <–> UART bridge which will allow you to open a terminal program on your PC to do Input/Output with a UART in the PSoC 6.

How am I going to do it?

  1. Copy “MyFirstDesign” to Start a New Project
  2. Modify the Build Settings to add Debug Printing and FreeRTOS
  3. Add the UART to the Schematic and Assign the Pins
  4. Create the UART Test Firmware
  5. Program and Test the Debug UART
  6. Modify firmware for FreeRTOS
  7. Program and Test
  8. A Tour of PDL for the TCPWM

Copy “MyFirstDesign” to Start a New Project

Right click on “MyFirstDesign” and select “Copy”

PSoC Creator Copy Project

Then right click on the workspace and select “Paste”

PSoC Creator Copy/Paste

Then right click on “MyFirstDesign_Copy_01” and select rename.  Then type in a reasonable name like “FreeRTOS-UART”

PSoC Creator Copy / Paste

PSoC Creator will ask you about some files.  Just click “Rename”

PSoC Creator Rename

Now you will have three projects in your workspace.  I typically click “Program” which will build the copied project and program the development kit… just to make sure that stuff still works.

PSoC Creator Workspace

Modify the build settings to add debug printing and FreeRTOS

You can build massively complex systems with PSoC 6.  In order to help manage that complexity I like to turn on debug printing so that “printf” works.  I also like to use a Real Time Operating System (FreeRTOS).  PSoC Creator has both of these things built in.  We called the printf functionality “Retarget I/O” because you need to “target” the Input / Output of the printf … aka STDIN and STDOUT to a peripheral in the PSoC.  The best peripheral to use for printf is the UART that is attached to your computer via kitprog2.

To add printf and FreeRTOS to your project you need to: Right click on the project and select “Build Settings…”

PSoC Creator Modify Build Settings

Click on the Peripheral Driver Library and then select “FreeRTOS” and “Memory Management heap_4”.  Then select “Retarget I/O”.  When you build your project this will cause PSoC Creator to add both of these to your project.

PSoC Creator Build Settings FreeRTOS

Select Build->Generate Application and notice that PSoC Creator added a number of files to your project including the FreeRTOS, stdio_user.c/.h and retarget_io

PSoC Creator retarget_io.c

Add the UART to the Schematic and Assign the Pins

In order to printf, getchar and putchar  you need to attach c standard library stdin and stdout to “something”.  The best “something” is the UART that is attached to the KitProg2 which is attached to your computer.  Then you can open a terminal program (like Putty) and read and write to the PSoC.

So, to do this you need to add a UART to your design schematic from the component catalog.  In the picture below I just typed “uart” in the search box.

PSoC Creator Debug UART

What pins on the PSoC 6 BLE is the UART attached to?  Well… if you turn over your CY8CKIT-062-BLE you will find a little map that show that the PSoC 6 BLE UART is attached to the PSoC 5LP UART.  The PSoC 5LP is programmed with the KitProg2 firmware.

PSoC 6 CY8CKIT-062-BLE

To attach those pins in your firmware you just double click on the “Pins” tab in the DWR.  Then you can select “Port” for the UART RX and TX.  Look at the picture below.

PSoC 6 PSoC Creator Pin Settings

Now that I have all of that done, I run “Build->Generate Application” to get all of the new settings into my project.

Create the UART Test Firmware

The next step in making the printf work is to “retarget” it to the UART we just put in the schematic.  Open “stdio_user.h” and add “include <project.h>” (line 130) and change IO_STDOUT_UART and IO_STDIN_UART to be UART_1_HW.  The name “UART_1” on lines 136-137

#include <project.h>
#include "cy_device_headers.h"

/* Must remain uncommented to use this utility */
#define IO_STDOUT_ENABLE
#define IO_STDIN_ENABLE
#define IO_STDOUT_UART      UART_1_HW
#define IO_STDIN_UART       UART_1_HW

Now edit your main_cm4.c to:

  • Turn on the UART with UART_1_Start() on line
  • Then a couple of printfs lines 24-25

Note that “\033[2J\033[H” is just a VT100 escape sequence for clear screen and go home.

#include "project.h"
#include <stdio.h>

int main(void)
{
    __enable_irq(); /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    PWM_1_Start();
    UART_1_Start();
    
    printf("3[2J3[H"); // Clear Screen
    printf("Test\r\n");
    
    
    for(;;)
    {
        /* Place your application code here. */
    }
}

Program and Test the Debug UART

You need to figure out which com port that the KitProg2 is attached to.  To do this run the device manager by pressing the “windows” button then typing “device manger”

Device Manager

Click on ports.  Then you can see that the programmer is “KitProg2” and that the UART is attached to COM9 (everyone will have a different number)

Device Manager

Run Putty (or  your favorite terminal program)

Putty

Press the program button on PSoC Creator and you should see your test print

Putty PSoC 6 UART

Modify firmware for FreeRTOS

When I look out the output window from the previous step you can see that there is a warning message from FreeRTOS.  Lets fix that warning (by deleting line 83).  While we are at it, lets change the heap size to 48K (48*1024)

Now lets turn on FreeRTOS. Double click on main_cm4.c to open it in the code editor.

Modify FreeRTOS Firmware

Add the following firmware to your project.

The uartTask is function that FreeRTOS uses to create a Task.  This task will control the uart. (which is amazingly enough why I named it uartTask)

  • The function call “setvbuff” turns of buffering on stdin… which means every character will immediately come through to your program
  • getchar just gets a character from the terminal
  • the ‘s’ and ‘S’ will start and stop the PWM (more to follow)

In main I

  • Create a task for the uartTask (line 56)
  • Start FreeRTOS (line 57)
/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include "project.h"
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"

// uartTask - the function which handles input from the UART
void uartTask(void *arg)
{
    (void)arg;
    char c;
    setvbuf(stdin,0,_IONBF,0);
    while(1)
    {
        c = getchar();
        switch(c)
        {
            case 's': // Stop the PWM
                printf("Stopped PWM\r\n");
                Cy_TCPWM_PWM_Disable(PWM_1_HW,PWM_1_CNT_NUM);
                
            break;
            case 'S': // Start the PWM
                printf("Started PWM\r\n");
                Cy_TCPWM_PWM_Enable(PWM_1_HW,PWM_1_CNT_NUM);
                Cy_TCPWM_TriggerStart(PWM_1_HW, PWM_1_CNT_MASK);
            break;
        }
    }
}


int main(void)
{
    __enable_irq(); /* Enable global interrupts. */

    /* Place your initialization/startup code here (e.g. MyInst_Start()) */

    PWM_1_Start();
    UART_1_Start();
    
    printf("3[2J3[H"); // VT100 Clear Screen
    printf("Test\r\n");
 
    // Mask a FreeRTOS Task called uartTask
    xTaskCreate(uartTask,"UART Task",configMINIMAL_STACK_SIZE,0,3,0);
    vTaskStartScheduler();  // Will never return
    
    for(;;) // It will never get here
    {
    }
}

How did I figure out how to start/stop the PWM?  To find the documentation for “PDL” aka the Peripheral Driver Library, you can right click on the component in the schematic and select “Open PDL Documentation”

PSoC 6 TCPWM

Or you can open “Help –> Documentation –> Peripheral Driver Library”

PSoC Creator Help

In the documentation I can see all kind of functions, including “Cy_TCPWM_PWM_Disable”

PSoC 6 PDL

Program and Test

PSoC 6 FreeRTOS Test

A Tour of PDL for the TCPWM

How did I figure out that the TCPWM_Type *base should be “UART_1_HW”?  ….. well …. You might ask yourself, “What does PWM_1_Start()” do?  It just calls PDL start function.  OK… so what does that do?  To find out you can right click on the “PWM_1_Start” function and select “Go To Definition” which will take you to the source code.

PSoC 6 Tour of PDL

You will end up in a file called “PWM_1.c”.  This file was created for you automatically by PSoC Creator.   This function is really simple.

  • If it has never been initialized then it calls init (lines 15-19)
  • Then it enables the TCPWM (line 22)
  • Then if there not an external pin on the PWM, then it causes a software trigger (line 25)
/*******************************************************************************
* Function Name: PWM_1_Start
****************************************************************************//**
*
*  Calls the PWM_1_Init() when called the first time and enables 
*  the PWM_1. For subsequent calls the configuration is left 
*  unchanged and the component is just enabled.
*
* \globalvars
*  \ref PWM_1_initVar
*
*******************************************************************************/
void PWM_1_Start(void)
{
    if (0U == PWM_1_initVar)
    {
        (void) Cy_TCPWM_PWM_Init(PWM_1_HW, PWM_1_CNT_NUM, &PWM_1_config);

        PWM_1_initVar = 1U;
    }

    Cy_TCPWM_Enable_Multiple(PWM_1_HW, PWM_1_CNT_MASK);
    
    #if (PWM_1_INPUT_DISABLED == 7UL)
        Cy_TCPWM_TriggerStart(PWM_1_HW, PWM_1_CNT_MASK);
    #endif /* (PWM_1_INPUT_DISABLED == 7UL) */    
}

So, you might ask yourself what is “PWM_1_HW”?  Well this is just the base address of the registers for the PWM_1.  Lets follow that.  Right click on it and go to definition.

PSoC 6 PDL

This will take you to PWM_1.h and you will see PWM_1_HW is setup as PWM_1_TCPWM_HW.  What is that?  Well do the right click thing again and find out.

/***************************************
*           API Constants
***************************************/

/**
* \addtogroup group_macros
* @{
*/
/** This is a ptr to the base address of the TCPWM instance */
#define PWM_1_HW                 (PWM_1_TCPWM__HW)

/** This is a ptr to the base address of the TCPWM CNT instance */
#define PWM_1_CNT_HW             (PWM_1_TCPWM__CNT_HW)

/** This is the counter instance number in the selected TCPWM */
#define PWM_1_CNT_NUM            (PWM_1_TCPWM__CNT_IDX)

/** This is the bit field representing the counter instance in the selected TCPWM */
#define PWM_1_CNT_MASK           (1UL << PWM_1_CNT_NUM)
/** @} group_macros */

#define PWM_1_INPUT_MODE_MASK    (0x3U)
#define PWM_1_INPUT_DISABLED     (7U)

PSoC 6 PDL

This will take you to “cyfitter.h” which is the output of the place and route.  It tell you that PWM_1_TCP is really TCPWM0

/* PWM_1_TCPWM */
#define PWM_1_TCPWM__CNT_HW TCPWM0_CNT0
#define PWM_1_TCPWM__CNT_IDX 0u
#define PWM_1_TCPWM__HW TCPWM0
#define PWM_1_TCPWM__IDX 0u

 

Lesson 1 – PSoC 6 Introduction: Resources

PSoC 6 Introduction

# Title Comment
0 A Two Hour PSoC 6 Class An introduction to the PSoC 6 class with links to all of the documents
1 Resources Links to all of the Cypress PSoC 6 information including videos, application notes etc.
2 Your First Project Learn how to build a PSoC 6 project and program your CY8CKIT-062-BLE development kit
3 FreeRTOS and a Debugging UART Build a project using FreeRTOS including a debug console with the UART
4 CapSense Build a project using the Mutual Cap Buttons and Self Cap Slider
5 Bluetooth Low Energy Build a CapSense project using BLE and CySmart

Since I did the webinar several things have happened

  1. Lesson 4: I fixed an error in the stack size for FreeRTOS
  2. Lesson 5: The PSoC Creator BLE PDL has been upgraded to greatly simplify the notifyCapSense function

All of the projects are available at git@github.com:iotexpert/psoc-6-introduction.git or www.github.com/iotexpert/psoc-6-introduction

Summary

This is an index with links to all of the PSoC 6 learning resources.  You can click the links to go the website or see screen captures of the resources.

  1. PSoC 6 Product Page
  2. PSoC 6 Documentation
  3. PSoC 6 Community
  4. CY8CKIT-062-BLE Development Kit Web Page
  5. CY8CKIT-062-BLE Development Kit Guide
  6. PSoC 6 Datasheet
  7. PSoC 6 Technical Reference Manuals
  8. Application Notes
  9. Videos
  10. Code Examples
  11. Knowledge Base
  12. PSoC Creator Help Page
  13. PSoC Creator Component Datasheet
  14. Peripheral Driver Library Documentation (Doxygen)

PSoC 6 Product Page

You can find the PSoC 6 Product landing page for PSoC 6 here

PSoC 6 Documentation

On the PSoC 6 Product Landing page there is a documentation tab that has links to all of the current documentation.

Community

Cypress has an active development community and forum.  It can be found here.

Development Kit Web Page

Every Cypress development kit has a web page that contains all of the information about it, including links to the documentation and store.  The CY8CKIT-062-BLE kit page is here.

CY8CKIT-062-BLE Development Kit Guide

PSoC 6 Datasheet

The PSoC 6 Datasheet is available on Cypress.com here.

Technical Reference Manual

Each of the PSoC 6 devices has a lengthy discussion of the Technical Resources.  These documents can be found here

Application Notes

You can get them all on our website… here is a link to the filtered list of PSoC 6 Application Notes.

The best application note is always the “Getting Started”.  In this case it is AN210781 “Getting Started with PSoC 6 MCU with Bluetooth Low Energy (BLE) Connectivity”

Code Examples

You can find all of the PSoC 6 code examples on the web.  In addition they are built into PSoC Creator.

Or in PSoC Creator:

Videos

Cypress has made a bunch of videos that take you step by step through an introduction to PSoC 6.  You can find them on the Cypress training website.

https://www.youtube.com/watch?v=vefexHmf_Us

Knowledge Base

The Cypress technical support team writes “Knowledge Base” articles when there are repeated issues reported by customers.  You can find them here.

PSoC Creator Help Page

There is a bunch of help on the PSoC Creator Help Page.

On the PSoC Creator Help page there are tons of resources including

PSoC Creator Component Datasheet

Every component in PSoC Creator can be right clicked -> datasheet

For example the datasheet for the UART

Peripheral Driver Library Documentation (Doxygen)

All of the APIs in the PDL are documented in a Doxygen generated HTML document.  You can get there from

  • Help -> Peripheral Driver Library (this link is live only when you have a PSoC 6 project open)
  • Right click on a component -> Open PDL Documentation

Lesson 0 – PSoC 6 Introduction: A Two Hour PSoC 6 Class

Summary

This is the top level web page for a two hour class about getting started with PSoC 6.  I was initially a bit worried about how much could be covered in only two hours… then I remembered how awesome PSoC Creator is at getting people going.  Originally, I was planning on writing a lab manual document describing all of the getting started exercises, but upon reflection, I decided to make a series of IoT Expert articles so that the content could be live.

I believe strongly that hands-on is best for real learning, so this class is built as four lab exercises for you to do by following along with my instructions.  I supplement the lab exercises with a survey of the PSoC 6 ecosystem… meaning all of the resources you can use to get help and learn.

You will need a few things for the class:

Todays virtual workshop agenda is as follows:

PSoC 6 Introduction

# Title Comment
0 A Two Hour PSoC 6 Class An introduction to the PSoC 6 class with links to all of the documents
1 Resources Links to all of the Cypress PSoC 6 information including videos, application notes etc.
2 Your First Project Learn how to build a PSoC 6 project and program your CY8CKIT-062-BLE development kit
3 FreeRTOS and a Debugging UART Build a project using FreeRTOS including a debug console with the UART
4 CapSense Build a project using the Mutual Cap Buttons and Self Cap Slider
5 Bluetooth Low Energy Build a CapSense project using BLE and CySmart

Since I did the webinar several things have happened

  1. Lesson 4: I fixed an error in the stack size for FreeRTOS
  2. Lesson 5: The PSoC Creator BLE PDL has been upgraded to greatly simplify the notifyCapSense function

All of the projects are available at git@github.com:iotexpert/psoc-6-introduction.git or www.github.com/iotexpert/psoc-6-introduction

PSoC Creator 4.2

The class is built on PSoC Creator 4.2 which is currently in beta.  Here is a screenshot (of the class workspace) that includes the example projects (which you can download).  It also shows that some of the components are still prototypes.  Don’t worry, Cypress will be releasing production silicon and final development software soon.

PSoC Creator

CY8CKIT-062-BLE

The class is built for the CY8CKIT-062-BLE.  Here is a picture of my development kit taken from the table at Starbucks where I am finishing the material for this class.

CY8CKIT-062-BLE PSoC 6 Development Kit

And here is the nice picture from our website (that the marketing guys made me use)

CY8CKIT-062-BLE