AnyCloud Bluetooth Advertising Scanner (Part 1)

Summary

The first of several articles discussing the use of the AnyCloud BLE Stack to build advertising scanner/observers.

Story

A few summers ago while I was writing the WICED Bluetooth Academy book, I created a WICED based BLE advertising scanner.  Actually, I created a framework for the scanner and the remarkable summer intern I had finished the work.  That project has been sitting in the source code repository for the Bluetooth class, mostly only shown to face-to-face students.  This scanner is built using some of the original code combined with the new AnyCloud Bluetooth SDK.  It will act sort-of-like LightBlue or one of the other Bluetooth advertising scanners you might run on your phone, but with a serial console.

Sometime in the last few months we released the Bluetooth SDK for AnyCloud (things have been crazy and I have lost track of time)  This SDK has all of the stuff needed to add Bluetooth to your AnyCloud project using one of the Cypress Bluetooth/WiFi combo chips.  I had not had a chance to try it out, so I decided to build a Bluetooth project and then port the scanning code.

For this series of articles I will:

  1. Discuss an overview of Bluetooth Application Architecture (Part 1)
  2. Explain how to Start the AnyCloud Bluetooth Stack (Part 1) 
    1. Discuss the configuration structure: bt_platform_cfg_setting (Part 1)
    2. Discuss the configuration structure: wiced_bt_cfg_settings (Part 1)
    3. Discuss the Tasks created by the Bluetooth Stack (Part 1)
    4. Build the Basic Project (Part 2)
    5. Discuss BLE Advertising - Scanner/Observer (Part 3)
    6. Discuss BLE Advertising - Advertiser (Part 3)
    7. Add BLE Scanning Code to the project (Part 3)

    Bluetooth Application Architecture

    Bluetooth applications are divided into these four pieces

    1. You user application which responds to events and sends messages from/to the Bluetooth host stack
    2. A Bluetooth Host Stack
    3. A Bluetooth Controller Stack
    4. The Bluetooth Radio

    These four pieces can be divided into multiple chips, as few as one or as many as four.  However, for this article, the project will be built to run on a PSoC 6 + CYW43012 WiFi/Bluetooth Combo chip.  Specifically:

    1. My scanner application running on the PSoC 6
    2. The Bluetooth Host Stack running on the PSoC 6
    3. The BlueTooth Controller Firmware running on the CYW43012
    4. A Bluetooth Radio on the CYW43012

    But how do they talk?  Simple, there is:

    1. A UART Host Controller Interface (HCI) between the two chips
    2. A GPIO to serve as a deep sleep wakeup from the 43012 –> PSoC 6
    3. A GPIO to serve as the bluetooth controller wakeup from the PSoC 6 –> 43012
    4. A GPIO to turn on the Bluetooth regulator from the PSoC 6 –> 43012

    Here is the block diagram from the CY8CKIT-062S2-43012 Kit Guide.  Notice that signals labeled UART and Control going between the PSoC 6 and the CYW43012.

    And when you read more deeply into the schematic you can see the signals labeled

    • BT_UART_TXD/RXD/CTS/RTS
    • BT_HOST_WAKE
    • BT_DEV_WAKE
    • BT_REG_ON

    How to Start the AnyCloud Bluetooth Stack

    To actually start the AnyCloud Bluetooth stack you will call two functions

    1. cybt_platform_config_init – that will setup the hardware interface to the CYW43012
    2. wiced_bt_stack_init that will:
      1. Start a task to manage the Host Controller Interface
      2. Download the controller firmware to the CYW43012
      3. Start a task to manage the host stack
      4. Initialize both the host and the controller
      5. Call you back when that is all done

    Here is an example from main.

    When you look at these two function calls, you will find that you need to provide three things:

    1. A platform hardware configuration structure called bt_platform_cfg_settings
    2. The Bluetooth stack configuration settings structure called wiced_bt_cfg_settings
    3. A management callback called app_bt_management_callback

    bt_platform_cfg_settings

    The purpose of the hardware configuration structure is to define the UART + parameters and the wakeup GPIOs.  Specifically, the hardware configuration structure defines the configuration of the host controller interface (hci)

    1. The HCI transport scheme (in this case UART)
    2. The pins of the UART
    3. Baud Rate
    4. Data Bits
    5. Stop Bits
    6. Parity
    7. Flow Control

    And the controller low power behavior (in the .controller_config member)

    This is a fairly standard configuration and I think that we should help you by providing this structure somewhere in the BSP.  But for now, you need to provide it (in an upcoming article I’ll update the IoT Expert Bluetooth Library to provide it).  Here is the specific structure that I will be using.

    wiced_bt_cfg_settings

    The Cypress WICED Bluetooth Stack has a boatload of configuration settings.  When you call the stack start function you need to provide all of those settings in a structure of type “wiced_bt_cfg_settings_t” which is actually a structure of structures.  There are several basic ways to set these settings

    • Start from scratch and build you own settings
    • Copy from an example project
    • Use the Bluetooth Configurator to generate the structure

    For the purposes of THIS project I started by copying the structure from on of the example projects and then modifying the three numbers that were relevant to me.  Specifically

    • max_simultanous_link – which I changed to 0 because this is simply a Bluetooth Observer
    • low_duty_scan_interval – how long in the window to listen for advertising packets
    • low_duty_scan_window – how wide the window of listening should be

    app_bt_management_callback

    The last thing that you need to provide is a management callback.  This function is called by the Bluetooth Stack when a “management event” occurs.  There is a big-long-list of enumerated events of type wiced_bt_management_event_t.  The events include things like the the stack started “BTM_ENABLED_EVENT”.  Each event may have data associated with the event which is passed to you in a pointer to wiced_bt_management_event_data_t.

    You typically deal with these events with a giant switch statement like this:

    Tasks

    The Bluetooth stack on the PSoC6 is operated with two tasks.  Specifically, when you call the wiced_bt_stack_init it will startup:

    1. CYBT_HCI_Task – a task that sends and receives HCI packets going to the Radio chip
    2. CY_BT_Task – a task that manages the Bluetooth Host Stack

    Here is print of the task list from my project:

     

    Now with the background in place, in the next article I will discuss Bluetooth advertising and how to build the observer project.

    AnyCloud – Wireless Connection Manager (Part 1)

    Summary

    A discussion of using the Infineon (Cypress) PSoC 6 with a CYW4343W and the AnyCloud Connection Manager with Modus Toolbox.  The AnyCloud Connection Manager is an RTOS thread that lets you manage a connection to a WiFi network.  It knows how to scan for networks, attach, detach etc. and was recently released for use with PSoC6 and 43xxx WiFi combos.

    The Story

    In the WICED WiFI SDK there is an example program called “test.console” which allows you to use a UART command line to do networking “stuff”.  With the release of the new AnyCloud SDK I decided that I should rebuild some of that program using the PSoC and WiFi.  Basically a set of commands like “scan” to interact with the Radio World!  In the picture you below you can see that I use the command “scan” to list out the networks at my house.

    You can also use the command “help” to list out the commands.

    Architecture

    My implementation will have three tasks

    1. A Blinking LED Task (which doesn’t interact with any other tasks)
    2. The NT Shell – which will send commands to the network queue.
    3. The Network Task which will receive commands from the NT Shell task and trigger the Wireless Connection Manager to do something
    4. The Wireless Connection Manager which will interact with the WiFI Radio via the Wireless Host driver.

    Make the Basic Project

    To build this project start by creating a new project.  The development board that I had plugged into my computer when I began this project is a CY8CPROTO-062-4343W so this is the one I will select.

    In the new project creator pick the “CY8CPROTO-062-4343W”

    I created a FreeRTOS template project that does all of the right stuff.  I wrote an article about how to use the IoT Expert Manifestt here, and until you add the IoT Manifest to your setup you will not get the FreeRTOS Template project.

    After the new project work is done you should see

    Add the nt-shell, which comes from my IoT Expert library (read about how to add the IoT Expert library here).

    I have been on a kick of using Visual Studio code.  So, run “make vscode” to setup the project for Visual Studio Code.

    In the finder, copy the template files from nt-shell into your project.

    You can also do it with the command line.

    Edit main.c to include the configuration.

    Update the main.c to have the ntShellThread

    And start the ntshell task.

    When you want to add a command to the shell you need to do three things

    1. Add a function prototype for the command
    2. Add the command to the command list
    3. Write the function

    Here is an example of of the printargs command.  The shell will call your function with a ARGC=number of arguments and ARGV[] an array of the pointers to the actual arguments.

    Build and test your program.

    Turn on the Connection Manager and Core Middleware Library

    Now, add the wifi-mw-core library & Connection Manager using the library manager.  You can start it with “make modlibs”.  These two libraries are in the “WiFi Middleware” category.

    Copy the FreeRTOSConfig.h from the libs/wifi-mw-core/configs directory into your project (so you can modify it)

    Update the Makefile to include the WiFi components (line 71) and the MBED TLS configuration (line 86)

    Create networkTask.h/.c & Start the Task in main.c

    Now let’s create the networkTask.  This task will control all of the networking functions in the system.  The first file, networkTask.h, is the public interface.  It declares a Queue where you can push messages (line 5) an enumeration of the messages (lines 7-14), a definition of the message data (lines 17-22) and finally the network task declaration (line 24).

    Ill go ahead and modify main.c to start the yet to be written network task.  You need to include the header file for the task and define a handle for the task.

    Finally in main function, start the task.

    Create the file networkTask.c.  Make a bunch of includes.

    Now let’s define the actual task function.  This function will

    1. Call the wcm_init function to make a WiFi Station (lines 201-203)
    2. Tell the task that you would like to be called back when things happen (line 205)
    3. Initialize the Queue to receive command messages from other tasks.
    4. Make an infinite loop to receive the commands and process the messages.  Notice that I dont do anything with the message for now.  Ill add the code later.

    Create Utilities for Printing out the IP and MAC Address

    It the network task I want to be able to print out IP address (both IPV4 and IPV6).  I also want to be able to print out 6-byte MAC address.  In the Cypress drivers, an IP address is a structure that holds either a IPV4 or and IPV6 address.  It then contains the 4 or 6 bytes of the address.  Here is the type definition.

    The IP v ersion is just an enumeration.

    To print an address, figure out which version you are working on.  Then dump the raw bytes.  Notice in the IPV4 case it is encoded into a uint32_t as 4 continuous bytes.

    A MAC address is just an array of uint8_t of length CY_WCM_MAC_ADDR_LEN  (which we pound defined to 6)

    So, the print is just a loop. (probably should have done something slightly better so I dont end up with the trailing : – oh well)

    Add the Scan Command

    For the scan I want to print out the:

    1. SSID
    2. RSSI (in dBM)
    3. Channel
    4. Band
    5. Speed
    6. Type of Ap
    7. Country Code
    8. MAC address of the Access Point (AKA BSSID)
    9. Type of Security

    In order to have the WCM run a scan you need to call the function cy_wcm_start_scan.  What this will do is tell the 4343W to scan all the channels on the 2.4GHZ band and listen for access point beacons.  This function has three arguments

    1. A function pointer to call back when you find an AP
    2. A user settable data pointer
    3. A filter (which can limit to an SSID, BSSID or RSSI)

    Here is my version of the scanCallback which I put in the networkTask.c file.

    The result_ptr is a pointer to a structure that contains the data for the found access point.

    The other parameter to the callback is the status.  The status will either be CY_WCM_SCAN_COMPLETE or CY_WCM_SCAN_INCOMPLETE.  The first thing that to do is see if this callback is the one that tells me that the scan is complete, if so I just return (and don’t print anything)

    Then I print out the raw SSID, Signal Strength and Channel.

    Next I figure out what channel we are talking about.  The 4343W is single band 2.4GHZ, however, other Cypress chips have dual band.

    Then I printout the maximum data rate, which is 0 for all of my test cases.  I have no idea why.

    Then I printout what type of AP we are talking about.

    Then the country code.

    Then the Basic Service Set ID of the AP, which is also known as the MAC address of the AP.

    Then the security type.

    With a complete scanCallback function I can now update the networkTask to deal with the queued commands of net_scan type.  This simply either stops or starts the scan based on the message parameter.

    The last things to do is to add the scan command to the usrcmd.c

    OK.  Let it rip.  You should be able to run network scans.  In the next Article I will add a connect and disconnect commands.

    You can find all of this example code at https://github.com/iotexpert/wcm_example

    MBED OS & PSoC 6 & SSD1306

    Summary

    As I wrote about in the last article I have been working to get ready for Embedded World 2019 in a week and a bit.  For my demo, I will be handing out remote controls that have a 128×64 monochrome OLED display that is driven by an I2C SSD1306.  This whole board is controlled by a PSoC 6 & a 4343W WiFi / Bluetooth Combo.

    This morning I started to port the U8G2 library to MBEDOS… but ran into some problems, so I i decided to see what ports were already out there.  I immediately found a port of the Adafruit_GFX library.  This article talks about using it on my CY8CPROTO_062_4343W board.  As part of this journey I also wanted to be able to draw the Cypress logo on the screen… so I had to figure out how to create a logo in a format that could be drawn on the screen.

    I will follow these steps:

    1. Create a new project & add the Adafruit_GFX_library
    2. Create a main.cpp, configure the library and test
    3. Make a Cypress logo using GIMP
    4. Create a function to draw X11 bitmaps & test

    Create a new project & add the Adafruit_GFX_library

    The first step to get everything going by running

    1. mbed new .
    2. mbed add http://os.mbed.com/users/nkhorman/code/Adafruit_GFX/

    The way to figure out how to add the library is by going to the library webpage on the mbedos website.  Then clicking the arrow on “Import into Compiler” where you will see two options, “Import into Compiler” and “Import with mbed CLI”

    When you select that option you will get a window that tells you the exact command to run.

    I have been using Atom as an editor (and sort of IDE).  When you open the lcd-example directory using Atom you will see your project including

    1. The mbed-os directory with all of the mbed stuff in it.
    2. The Adafruit_GFX library

    Create a main.cpp, configure the library and test

    The next step is to create a main.cpp.

    1. Setup the I2C.  In order to use the graphics library you need to setup a communication vehicle.  In my case that is an I2C bus that is connected to P6[0] and P6[1] on my development board.  Lines 6-15 create the communication class of I2CPreInit, configure it to 400kbs and connect the I2C master to P6[0]/P6[1]
    2. Line 16 actually setups up the graphics library and get it going.
    3. The main simply prints out some information about the display on lines 22-23
    4. Line 24 causes the current frame buffer to be displayed (more on this in a second)
    5. The main loop blinks the LED and prints a counter on the top of the screen.

    In order to build this thing I run “mbed compile -t GCC_ARM -m CY8CPROTO_062_4343w”.  When I run the project it looks like this:

    There are several things to notice about this picture.  First, there is an Adafruit logo on the screen.  Where did this come from?  Simple on line 152 of Adafruit_ssd1306.cpp there is a function called “splash” which is called by the constructor.  The spash function just copies a bitmap into the frame buffer of the Adafruit_SSD1306 object.

    The constructor is in Adafruit_ssd1306.h on line 152

    And if you don’t want to have this splash screen you can uncomment the #define NO_SPLASH_ADAFRUIT in the file “Adafruit_GFC_Config.h”

    The next thing to notice in the picture is that I have lead wires attached to the LCD pins… and those wires are attached to a logic analyzer because I typed the I2C incorrectly and I couldn’t figure out why they didn’t talk.  And finally notice my grandfathers magnifying glass which I use every day.

    Make a Cypress logo using GIMP

    For my project I am less interested in displaying Adafruits Logo and more interested in displaying Cypress’.  To do this I loaded up the Cypress logo in Gimp.

    I then converted it to pure black and white using the “Image->Mode->Indexed…”

    Then selected “black and white palette”

    Then I scaled the image to 128×40 using the “Image->Scale Image”

    Unfortunately it made a bit of a mess of the logo during the scaling process… so I put my son to editing it.

    Which looks like this after he was done.  Pretty good eh?

    In order to use the image you need a “C program” version of it.  It turns out that there is a format called “X11” or “xbm” which is exactly that (a c-file).  You can read about the format on this website.  To get one of these files, just run “File->Export As”

    Then give it a name with a “.xbm” on the end

    Make sure and “de-select the X10 format bitmap” (and older version of the xbm format)

    When all that is said and done you will find the xbm file with goodness in it.  Here is the top of it.

    The format of this file is unsigned 8-bit integers… each bit represents the bit of one pixel… in BIG ENDIAN!!!! format.  In other words this table will be 128×40/8 bytes long.

    Create a function to draw X11 bitmaps & test

    But how do we use this format?  Well, write a new function in the Adafruit library to draw X11 bitmaps.

    First add the new function name to the class on line 168 of “Adafruit_GFX.h”

    Then add the code.

    This may not be the most beautiful code in the world… which I suppose makes it fit right in with some of the other stuff in this driver.  Oh well it works.

    Once you have added the function to the library, lets test it to see if it can draw the logo.  First, copy the “cylogo.xbm” into the project and call it “cylogo.h”.  Then modify the “main.cpp” to use it.  Add an include of the “cylogo.h”.  Then on line 26, call the function to draw it at 0,(half way down the screen)

    When you program this… everything seems to be good.

    By the way if it isn’t clear by now, I did a solder in a male header onto the board so that I could attach the I2C wires for the display.

    Cypress & MBED OS

    Summary

    This morning I saw something exciting.  When I went to the ARM mbed-os GitHub site I saw the latest accepted merge commit was from vmedcy and it says something interesting.  “Add Cypress PSoC 6 Targets”.  I cannot even begin to describe how gratifying it is to see this commit.

    But what does it mean?  Lets look.  I am using a Mac, so I simply install the MBED-CLI using the instructions found on the MBED CLI webpage.

    Like all good embedded people, the first thing to do is make sure that the toolchain and everything else works using a simple blinking LED project.  And, the easiest way to do this is to import the ARM example using: “mbed import mbed-os-example-blinky”.

    The current release of mbed-os is 5.11.3 which you can see on the Tags page of the mbed-os GitHub site.  Notice in the screenshot above that the commit number for mbed-os is “a8d1d2…”  which means that by default, when you import a project it gives you the “latest” version of mbed-os, which really means the latest official release.

    But, I want to use the version that was accepted with the new Cypress stuff (which will become part of the official release starting with mbed-os-5.11.4).  I can do this by running “cd mbed-os” and “mbed update master”.  This will move the git repository to point at the head of the master branch, AKA the latest and greatest.  When I do that I get a version that looks like “32525…”

    And when I look at the commit history in GitHub I can see the interesting commit has the same number.

    Now to the good stuff.  When I look in the targets directory I see that there is a TARGET_CYPRESS.  Where is see two targets:

    • TARGET_PSOC – the stuff that Cypress created
    • TARGET_PSOC6_FUTURE – a really cool target that Future Electronics created.

    When when I look in the Cypress directory I see a bunch of my favorite Cypress PSoC 6 and WICED wireless development Kits.

    • TARGET_CY8CKIT_062_BLE
    • TARGET_CY8CKIT_062_4343W
    • TARGET_CY8CKIT_062_WIFI_BT
    • TARGET_CYW943012P6EVB_01
    • TARGET_CY8CMOD_062_4343W
    • TARGET_CY8CPROTO_062_4343W

    I happen to have a CY8CPROTO_062_4343W on my desk at home.  This kit has a bunch of cool stuff on it, but most importantly it a 4343W WiFi Bluetooth Combo chip and a PSoC 6 together.  Finally, A PSoC 6 2M (which is really called CY8C624ABZI-D44) and a WICED 4343W – a Dual Band 802.11n and Bluetooth 5.0 Combo.  Here is a picture from the development kit guide.

    Now we have something to program.  Let’s look at the blinking LED example program.  It resides in the file “main.cpp” which is in the root directory of the “mbed-os-example-blinky”

    This looks simple enough, but I am never a fan of “other” stuff in the blinking LED example.  So Ill trim it down to the most basic.

    All-right, how do I compile this?  Well, run the mbed command line interface with “mbed compile -m CY8CPROTO_062_4343W -t GCC_ARM“… and after a bit of compiling you should end up with a window like this:

     

    Now I have a “hex file”.  How do I program it?  There are three ways.

    #1 You can add the “-f” option to the command line and it will “flash” the device after it gets done compiling using PyOCD.  In order to do this your development kit’s KitProg 3 must be in the DAPLink mode.  To get into this mode hold down the KitProg button for 2 seconds and the LED will turn off. (If the LED turns on that means you put the programmer into CMSIS-DAP mode, so hold down the button for 2 seconds again).  At the time of this writing the -f option doesn’t work in the released version of mbed-cli,  but that will be fixed shortly with an update to the program debug system in mbed (hopefully by the time you read this)

    #2 Copy the hex file from the BUILD directory onto the Mass Storage device called “DAP Link” using the finder. (drag and drop).  To use this method your KitProg needs to be in DAPLink mode.  (so follow the steps above)

    #3 Use the “Cypress Programmer” to program the flash.  You can download it for Windows, Mac or Linux from this link on cypress.com  When I run Cypress Programmer it looks like this:

    Open the hex file by pressing the “Open” button and navigating into the BUILD directory to find the hex file called “mbed-os-example-blinky.hex”

    Then press “connect” and “program”

    Nothing happens on my development kit?  So I press the reset button and now I get a blinking LED.  But why do I have to press reset?   Do you see the “Reset Chip” checkbox at the top of the “Program Settings” window?  That has to be clicked.  Now when you program, the debugger will reset the chip and you will be off to the races.

    So, what was going on with the rest of that program that came by default?  If you attach a serial terminal to the devkit you will see that the blinky example program is putting out information about the RTOS.

    It turns out the mbed-os is really an os… an operation system.  Actually it is a real time operating system that traces it genealogy to RTX, a product from the old Keil Corporation which was acquired by ARM…. a lot more on this later.

    One final note that may cause confusion (I certainly have been confused).  There are four different modes of KitProg 3 (the programmer that is built into most of the Cypress development kits).

    Mode LED Change modes
    CMSIS-DAP BULK Solid LED Short button press toggles between BULK and HID
    CMSIS-DAP HID Breathing LED Short button press toggles between BULK and HID
    DAPLink LED Off Hold KitProg button for >2 seconds (gets in and out of this mode)
    B00tloader Fast blinking LED hold reset button and plug in kit

    In order to program from the command line using “mbed compile -f” you need to be in “DAPLink” mode.  In order to program with Cypress Programmer you need one of the CMSIS-DAP modes.

     

     

    Mouser PSoC 6-WiFi-BT L8: Integrate WiFi and AWS Into the Game

    Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

    Summary

    In this lesson we will move the subscriber app functionality into the main GameBle project (now called GameBleAws).  In order to do this, you need to turn the subscriber into a thread, and fix it so that messages that are sent to the PADDLE topic get turned into messages that can be sent to the paddleQueue.

    To implement this lesson I will follow these steps:

    1. Create a New Project starting from L6GameBle
    2. Copy over subscriber.c and wifi_config_dct.h
    3. Update the Makefile
    4. Create subscriber.h
    5. Update main.c
    6. Update subscriber.c
    7. Test

    Create a New Project

    Copy and paste the L6GameBle project into a new project called L8GameBleAws using Copy/Paste

    Create a new Make target for the GameBleAws project

    Copy subscriber.c & wifi_config_dct.h

    Use copy/paste to make a copy of the subscriber application and paste it into the GameBleAws project.  Once done your folder should look like this:

    Update the Makefile

    Create subscriber.h

    In order for the main.c to know about the awsThread (which is the former application_start of subscriber.c) you should create a file called subscriber.h.  Then you should define the awsThread function to match the wiced_thread_t function prototype (just a function that takes a wiced_thread_arg and returns void).

    Update main.c

    To integrate the awsThread thread into your main project you need to add the “subscriber.h” to the includes:

    Add a new variable to hold the awsThreadHandle.

    Finally you should launch the AWS thread by creating it with wiced_rtos_create_thread.

    Update subscriber.c

    In order for subscriber.c to be useful you need to fix the includes, send the messages from the PADDLE topic to the game thread, and turn application_start into a thread.  Start by fixing the includes (just like we did in the BLE Example in Lesson 6)

    When you get a message to the PADDLE topic, you should parse it, then send a message to the game thread to move the paddle.  You do this exactly the same way as you did in the BLE project.  Notice that I protect the game thread by making sure it send a value less than 100.

    Test

    I don’t really have a good program (like the GoBle) to test moving the paddle live.  But you can see that when the game is over, you can still move the paddle using AWS console.  In the screen shot below you can see that I moved the paddle to position 0.  And you can see that the BLE started at the same time as AWS.  Score.

    Mouser PSoC 6-WiFi-BT L7 : Implement WiFi and AWS

    Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

    Summary

    In this lesson I am going to update one of the predefined application which we deliver as part of WICED Studio which knows how to connect to the AWS IoT Cloud to work on my network.  This will demonstrate WiFi and MQTT.  I will also fix the application so that it knows about a new MQTT Topic called “PADDLE” which will be used to send messages to move the game paddle.

    To implement this project I will:

    1. Copy the subscriber from demo/aws/iot/pub_sub/subscriber
    2. Setup a “thing” on AWS and download the certificates
    3. Update the certificates in the WICED installation
    4. Update the project with my AWS configuration
    5. Test
    6. Update the project to be compatible with the Game
    7. Test

    Copy Subscriber & Fix the Makefile

    The first thing that I will do is copy/paste the subscriber application which can be found at demo/aws/iot/pub_sub/subscriber into my folder.  I will also rename the project to L7subscriber. Once that is done it should look like this:

    Then you need to edit the Makefile to update the name of the project.

    Go to Amazon.com and Create a “thing”

    In order to connect to the AWS cloud you need to create a “thing”.  Go to the AWS console and click “Create”

    We are just going to create one thing.  So, click “Create a single thing”

    Give it a name, in this case Mouser.

    AWS has device level security which is implemented with RSA certificates for each device.  So,  you need to let AWS create a certificate for you.

    Once that is done download the device certificate and the two keys.  You need to 100% make sure you do this now, because you wont get another chance. I’m also going to activate the certificate once I have the certificate and keys.

    Now attach a policy to your thing.  I already have the “ww101_policy” setup.

    The policy looks like this.  Basically, things are wide open.

    Update the Certificates

    The last thing that you need is the most recent AWS certificate.  WICED expects that you use the RSA2048 bit key.

    Now that you have the four security documents., you need to integrate them into your WICED installation.  To do this, change directories to ~/Documents/WICED-Studio-6.2/43xxx_Wi-Fi/resources/apps/aws/iot  Then copy the files, and then make symbolic links.  If you are not on a Mac or Linux then just copy the files and rename them appropriately.

    Update the Project

    AWS creates a virtual machine and runs an MQTT server on that machine.  You can find out the DNS name of that machine on the settings screen.  Here you can see my endpoint.  You will need to configure the WICED project to talk to your server.

    You need to change the actual endpoint of your MQTT server in the AWS cloud on line 119

    In the file wifi_config_dct.h you will need to change the CLIENT_AP_SSID and CLIENT_AP_PASSPHRASE for your network

    Test

    In order to test the project you will need to create a make target and program your development kit.

    Once that is done you can go to the Amazon.com test console and send MQTT messages to the correct topic.

    Here you can see the project attached to my network.  And successfully received the LIGHT ON message.

    Update the Project for the Game

    We know that the game doesn’t care about the LIGHT topic so, let’s change it to PADDLE.

    And let’s assume that messages to the paddle topic are ASCII numbers <100.  So, we can parse the message and print it out.  Notice that I used sscanf to parse the message and we all know that is super dangerous.

    Test

    After making those updates let’s program the whole shooting match again.  Then test by sending some messages to the PADDLE topic.

    It’s good.  Things are working.

    Mouser PSoC6-WiFi-BT L6 : Integrate GoBle Bluetooth into the Game

    Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

    Summary

    At this point we have a working BLE Remote Control and a working Game.  In this lesson I’ll merge the two projects together so that the GoBle remote control will be able to control the game paddle.  It will do this by creating messages (just like the CapSense messages) and sending them to the Game thread via the paddleQueue.  And it will send “Button0” messages when “Button A” is pressed.

    To implement this lesson I will follow these steps:

    1. Copy everything into a new project
    2. Modify the Makefile
    3. Modify main.c
    4. Create a new make target
    5. Test it all to make sure things are still working
    6. Modify GoBleThread.c
    7. Program and Test

    Copy L4Game into a new project L6GameBle

    Use “copy” and “paste” to create a new project, when you paste give it the name “L6GameBle” (there is an error in the screenshot)

    Copy the files GoBle_db.c/h, GoBleThread.c/h, and wiced_bt_cfg.c from the GoBle project into your new GameBle project.  After that is done your project should look like this:

    Modify the Makefile

    1. Change the name of the App to “App_WStudio_L6GameBle”
    2. Add the new source files
    3. Add the BLE Library “libraries/drivers/bluetooth/low_energy”

    Modify main.c

    Add the include for the GeBleThread.

    In the application_start function add a call GoBleThread_start() to get the GoBle thread going

    Create a new make target

    Test it all to make sure things are still working

    Run the make target and make sure that the game still plays and that you can get remote control messages.

    Modify GoBleThread.c

    Add the includes for the GameThread (to get access to the game message structure) and SystemGlobal (to get access to the queue)

    I don’t need (or want) the button/slider printout information.  So I will delete the old button code from goble_event_handler. (delete this stuff)

    Now, update the code to send the slider and button information to the GameThread (via the paddleQueue).  You may have noticed that the slider on GoBle gives you 0->0xFF and the direction is the inverse from the game we setup.  So, I will scale the value to 100 and invert it so that the controller moves the paddle the right way on line 143.  The message format is exactly the same as what we setup for the CapSense.  This means the CapSense slider works at the same time as the GoBle controller.

    Program and Test

    Mouser PSoC6-WiFi-BT L5 : GoBLE – BLE Remote Control for the Game

    Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

    Summary

    Although I a like the video game, it is for sure missing something.  That something is IoT.  The first IoT thing that we will do to the game is to add a BLE remote control.  I wanted a pre-done remote control that could be downloaded from the App store.  After looking around a little bit I found GoBle.  I published a detailed article about GoBle here, but I’ll explain enough to make it work with the game.

    Here is a screen shot of what the remote control looks like.  You can see that on the left there is a joystick, and on the right there are some buttons.  My son tells me that this is a classic layout for a remote control.

    This remote control works as a “Central” meaning it knows how to connect to Peripherals.  For this lesson we will turn on the CYW4343W and make it be a Bluetooth Peripheral.

    To implement this lesson I will follow these steps:

    1. Create a folder called “L5GoBle”
    2. Create a makefile called L5GoBle.mk
    3. Setup a GATT database by creating GoBle_db.h and GoBle_db.c
    4. Setup wiced_bt_cfg.c
    5. Create GoBleThread.c
    6. Create GoBle.c to startup the GoBleThread
    7. Build, Program and Test

    Create a directory called “L5GoBle”

    Create a makefile called L5GoBle.mk

    Setup a GATT database by creating GoBle_db.h and GoBle_db.c

    Create a file called “GoBle_db.h”

    Create a file called “GoBle.c”

    Setup wiced_bt_cfg.c

    The WICED Bluetooth Configuration file is called “wiced_bt_config.c”.  The only change I made from the default is the timeout value of the advertising.  You can copy this directly into your file.

    Create GoBleThread.c

    In  order for the GoBleThread to work you need:

    1. The includes for the GATT Database and the WICED bluetooth stack.
    2. External References to the GATT Database.
    3. A few function prototypes.
    4. A function called “GoBleThread_start” to startup the Bluetooth stack and get things going. This includes providing Bluetooth management and GATT event handler functions.

    Create a function to setup the advertising data.  The GoBle iOS App looks for Peripherals that are advertising the UUID of the GoBLE Service.

    The Bluetooth Management Event Handler needs to take actions when the stack turns on, or one of the pairing events occur.

    The GATT Event Handler is called

    1. When a connection is made or terminated
    2. When the GoBle app writes to your GATT database.  When that happens we will just printout the value that was written

    Create GoBleThread.h

    Create GoBle.c to startup the GoBleThread

    Build, Program and Test

    Mouser PSoC6-WiFi-BT L4 : The Video Game

    Designing low-power, cloud-connected IoT devices with PSoC® 6 MCU’s and WICED® Wi-Fi/Bluetooth

    Summary

    In this lesson I’ll finish the video game thread by adding the graphics etc. to play the game.  In addition I’ll fix up the CapSense thread so that it is connected to the game via an RTOS queue.

    There are three main things going on in this game.

    1. A state machine for the game screen (Splash, Start, Running, Over)
    2. A 20ms timer that updates the screen while the game is running (moves the Paddle and the Ball)
    3. A GUI queue where the rest of the system – CapSense,  Bluetooth and WiFi – can send Button and Paddle messages.

    To implement this project I will:

    1. Setup the project and makefile by copying L3CapSenseTft
    2. Update gamethread.h to define the GUI queue messages
    3. Fix main.c to create the queue
    4. Create SystemGlobal.h to give the rest of the files access to the gui queue
    5. Updating the CapSenseThread to send GUI messages
    6. Update the includes in GameThread.c
    7. Add some #define macros to define game parameters
    8. Add a State Machine for the game & define some paddle movement methods
    9. Make forward declarations for the thread functions
    10. Create some variables to maintain game state
    11. Add display functions for the score and the speed
    12. Add functions to start and end the game
    13. Add helper functions to calculate the top and bottom of the paddle
    14. Add a function to update and draw the paddle
    15. Add a function to update and draw the ball
    16. Add a function for the game timer to call
    17. Update the main game thread

    Setup the project and makefile by copying L3CapSenseTft

    Use copy/paste to copy the L3CapSenseTft project to a new folder name L4Game.   Change the name of the makefile to be L4Game.mk.

    Edit the makefile and change the name of the application.

    Create a make target for this project

    Update GameThread.h to Define the GUI Messages

    All of the threads in the system (CapSense, Bluetooth, and WiFi) will control the paddle and the button by sending messages to an RTOS queue.  In gameThread.h we will add a definition of that message.  The message is just a structure with two values – which GUI element and what value to send.

    Fix main.c to Create the Queue

    I typically believe that the RTOS primitives should be owned by the main.c.  To do this edit main.c and fix the includes.

    Then define the queue variable “paddleQueue” which I should have names “guiQueue” but it is way to late to fix it now — oh well.

    Create the queue

    Create SystemGlobal.h

    Each of the threads in the system need to have access to the paddleQueue.  In order to do that create a file called SystemGlobal.h and extern the variable to give them that access.

    Updating the CapSenseThread to send GUI messages

    Remember that when we setup the CapSenseThread originally, it just printed out the values.  Let’s fix it so send messages.  So, edit CapSenseThread.c.

    1. Add a message variable (line 8)
    2. Fix the button0 and button 1 to make and send RTOS messages (lines 20/21 and 26/27)
    3. Fix the slider to send the position (lines 33-35)

    Update the includes in GameThread.c

    Now let’s fix GameThread.c.  Start by editing the includes to add a new file called “SystemGlobal.h” which contains the global variable for the GUI queue.

    Add some #define macros in GameThread.c

    There are a number of constants which I use in the game.  In this section I use #define macros to define them.

    Add a State Machine for the Game & Define Paddle Movement

    Open up GameThread.c – all of the game control functions will go there.

    There will be four screens in the game.  A splash screen to display Cypress and Mouser, a Ready Player 1 Screen, the actual game screen and a game over screen.

    In addition the paddle can move a little bit at a time (increment) or jump directly to the position (absolute)

    Fix the gameState statemachine

    In the splash screen I need to set the state machine to GS_SPLASH

    In the start screen I need to set the state machine to GS_START

    Make Forward Declarations for Functions

    You should define the functions in advance of using them

    Create some variables to maintain game state

    The updateScreenTimer is used while the game is running to call the updateScreen every 20ms.  The rest of the variables are self explanatory.

    Add Display Functions for the Score & Speed

    These two functions print the speed and score at the top of the screen.

    Add Function to Start the Game

    When the game needs to start you:

    1. Reset the score
    2. Set the paddle position
    3. Move the ball to the middle of the paddle
    4. Set the ball to move to the right and down
    5. Clear the screen, display score and speed
    6. Start the game running

    Add Function to End the Game

    When the game is over you should:

    1. Move the game state to over
    2. Stop the timer
    3. Display game over
    4. Display press button 0 to start

    Add Helper Functions to Calculate Paddle Top & Bottom

    There are two places where you need to know the position of the Paddle.  Specifically:

    1. To draw the paddle
    2. To figure out if the ball hit the paddle or not.

    These two functions calculate the pixel position of the top and bottom of the paddle based on it current position

    Add a Function to Update & Draw the Paddle

    While the game is running you need the paddle to move.  There are two methods:

    1. Absolute just moves the current position immediately to the desired position.
    2. Incremental, which moves the paddle a little bit towards the desired position.