AnyCloud Bluetooth Advertising Scanner (Part 5)

Summary

In this article I will add a new task to the AnyCloud BLE Advertising Scanning application which will save the advertising data into a database.

Story

There is still a boatload of mostly unintelligible advertising data coming ripping onto our screen.  It is FINALLY time to start fixing that.  In this article I will create a new task called the advertising database task which will hold the history of advertising packets that I have seen.  I will update the Bluetooth Manager task to submit the advertising packets to a queue running in the advertising database task.

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. Explain BLE Advertising - Scanner/Observer (Part 3)
    6. Explain BLE Advertising - Advertiser (Part 3)
    7. How does scanning work in the AnyCloud Bluetooth Stack? (Part 3)
    8. Add Observing to our Project (Part 3)
    9. Program and Test the Project (Part 3)
    10. Add the IoT Expert Bluetooth Utility Library (Part 4)
    11. Mulithreading Dangers (Part 4)
    12. Add a Queue to the Bluetooth Manager Thread (Part 4)
    13. Add a Timer to Process the Queue (Part 4)
    14. A Potential Threading Bug (Part 4)
    15. Add a Scan Off & On Command (Part 4)
    16. Create an Advertising Data Database Task (Part 5)
    17. Update the Advertising Database to Accept Submitted ADV Packets (Part 5)
    18. Update the Bluetooth Manager to Submit Adv Packets (Part 5)
    19. Create an Advertising Data Database (Part 5)
    20. Add a Command to Print the Database (Part 5)
    21. Refactor a silly duplication (Part 6)
    22. Update the print (Part 6)
    23. Add the "decode" command (Part 6)
    24. Add the decode packets functionality (Part 6)
    25. Program and test (Part 6)
    26. Design a new advertising database (Part 7)
    27. Update to the new database (Part 7)
    28. Update printing (Part 7)
    29. Update the advertising add (Part 7)
    30. Create a watch command (Part 7)
    31. Create a record command (Part 7)
    32. Create an erase command (Part 7)
    33. Update the filter data structure (Part 8)
    34. Fix the Add function (Part 8)
    35. Add the filter command (Part 8)
    36. Update the printing (Part 8)
    37. Fix a memory leak (Part 9)
    38. Add packet age (Part 9)
    39. Fix the printing, again (Part 9)
    40. Fix the add packet function (Part 9)
    41. Update the database structure for sort and purge (Part 10)
    42. Add the sort and purge commands (Part 10)
    43. Add the sort functionality (Part 10)
    44. Add the purge functionality (Part 10)
    45. The End & Commentary (Part 10)

    All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git

    There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.

    Create an Advertising Data Database Task

    We need to create the file advertisingDatabase.h which will hold the task prototype (so that main can get going).

    Then create the advertisingDatabase.c to hold the actual database code.  It will start with the definition of messages which can be sent to the task.  For now just “ADB_ADD”.  To make things a little bit simpler these command can have two data elements (which I call data0 and data1).  Then the main part of the task just

    1. Creates the queue to manage the messages
    2. Process the message until the end of time

    To start the task, you need to add it to main.c.

    When I build and program this, you can now see the new task.  Good that working.

    Update the Advertising Database to Accept Submitted ADV Packets

    If you recall our original setup was to take advertising packets in the Bluetooth Manager thread and print out the data.  The first thing that we want to fix up is the ability of the advertising database task to accept advertising packets which are pushed to its command queue.   To prepare for this I create two local variables to hold the data.

    Then I update the ADB_ADD command.  My first, and really simple fix, is to grab the printing code from the Bluetooth Manager task.  Obviously this won’t be an improvement from the original program as far as the users goes, but it will verify that the tasks are working properly together.

    Then I add a command to the advertisingDatabase.h which the Bluetooth Manager task can call to submit advertising packets

    The actual command in advertisingDatabase.c just takes the advertising information, puts it in a command message, then submits it to the command queue.

    Update the Bluetooth Manager to Submit Adv Packets

    Now I go and edit the bluetoothManager. c to submit packets rather than print them.  To do this I greatly simplify the callback.  There is one VERY important issue to deal with, which is one of those potential religious war issues.  Memory.

    When you get the callback from the stack, it gives you POINTERS to data for the advertising packet that reside inside of buffers inside of the stack.  As soon as this callback returns this memory is purged.  To prevent this data from getting cleaned up by the stack I

    1. Malloc some memory for the wiced_bt_ble_scan_results
    2. Malloc some memory for the advertising data
    3. Make a copy of the data
    4. Submit it to the Advertising Database

    I KNOW from the spec that the largest data packet is 31-bytes (actually it is 31-bytes + one more field with length 0).  So I know the maximum length is 32-bytes  This means that in many situations I will be copying GARBAGE into my buffer if the packet is less than 32 bytes long.  I think that this is simpler than calculating the length and then only copying that much data.

    When I run this updated program I should get the same stream of data coming out on the serial port.  Sure enough the new thread is working.

    Create an Advertising Data Database

    Now, lets create an actual database.  To simplify things my database is just an array of structures.  One structure per bluetooth device.  The structure will contain a pointer to the information about the device it just saw and the actual raw data.

    Then I will create several helper functions to work with the database

    1. Find devices in the database given a mac address
    2. Print an entry in the database
    3. Add entries to the database

    First, find an entry in the database.  This function will search through the database and compare the mac address against the mac address in the database.  When the memcmp ==0 meaning it found a match, it will return that entry.

    The print function will make sure that you asked for a legal entry (much must be greater than 0… and less than the max).  Then it will print out the mac address and the raw data.  In a future post I will add a smarter print out.

    To add an entry to the database, first make sure that it isn’t already in the database.  Then when you are sure that it isn’t the database, you just add the pointers to your table.  You need to make sure and not go beyond the end of the table, and if you did, you will have effectively blown away the last entry in the table.  Oh well.

    Add a Command to Print the Database

    Now we want to add the ability to print from the command line.  So add a new command message to the list of legal commands.

    Then create a new function to print.  If you send in a “-1” it will print the whole table.  Otherwise just print the individual entry.

    Now edit usercmd.c to have the new command line.  Notice that I use “sscanf” which obviously has some issues.  Too bad.

    When I program the project it immediately prints out a bunch of devices that are at my house.  Then you can see I run the “print” command which prints the table.  Finally P do a print 0 to just print the first entry.

    In the next article I will add smarter diagnostics to the advertising packets.

    AnyCloud Bluetooth Advertising Scanner (Part 4)

    Summary

    In this article I update the AnyCloud BLE advertising scanner to use the btutil library that was created in the previous post.  In addition, I add a command queue to the bluetoothManger and enable a new command to turn on and off scanning.

    Story

    If you have been following along until now, which I imagine that you have if you are reading this,  you will have gotten a vomit of device data blasting out onto your serial console.  This isn’t very helpful.  So now what?  I am going to divide this problem into two parts

    1. Creating a new user command to turn on and off scanning (this article)
    2. Creating a database to manage the data + a set of commands to dump it (next article)

    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. Explain BLE Advertising - Scanner/Observer (Part 3)
      6. Explain BLE Advertising - Advertiser (Part 3)
      7. How does scanning work in the AnyCloud Bluetooth Stack? (Part 3)
      8. Add Observing to our Project (Part 3)
      9. Program and Test the Project (Part 3)
      10. Add the IoT Expert Bluetooth Utility Library (Part 4)
      11. Mulithreading Dangers (Part 4)
      12. Add a Queue to the Bluetooth Manager Thread (Part 4)
      13. Add a Timer to Process the Queue (Part 4)
      14. A Potential Threading Bug (Part 4)
      15. Add a Scan Off & On Command (Part 4)
      16. Create an Advertising Data Database Task (Part 5)
      17. Update the Advertising Database to Accept Submitted ADV Packets (Part 5)
      18. Update the Bluetooth Manager to Submit Adv Packets (Part 5)
      19. Create an Advertising Data Database (Part 5)
      20. Add a Command to Print the Database (Part 5)
      21. Refactor a silly duplication (Part 6)
      22. Update the print (Part 6)
      23. Add the "decode" command (Part 6)
      24. Add the decode packets functionality (Part 6)
      25. Program and test (Part 6)
      26. Design a new advertising database (Part 7)
      27. Update to the new database (Part 7)
      28. Update printing (Part 7)
      29. Update the advertising add (Part 7)
      30. Create a watch command (Part 7)
      31. Create a record command (Part 7)
      32. Create an erase command (Part 7)
      33. Update the filter data structure (Part 8)
      34. Fix the Add function (Part 8)
      35. Add the filter command (Part 8)
      36. Update the printing (Part 8)
      37. Fix a memory leak (Part 9)
      38. Add packet age (Part 9)
      39. Fix the printing, again (Part 9)
      40. Fix the add packet function (Part 9)
      41. Update the database structure for sort and purge (Part 10)
      42. Add the sort and purge commands (Part 10)
      43. Add the sort functionality (Part 10)
      44. Add the purge functionality (Part 10)
      45. The End & Commentary (Part 10)

      All of the code can be found at git@github.com:iotexpert/AnyCloudBLEScanner.git and https://github.com/iotexpert/AnyCloudBLEScanner.git

      There are git tags in place starting at part 5 so that you can look at just that version of the code.  "git tag" to list the tags.  And "git checkout part6" to look at the part 6 version of the code.

      Add the IoT Expert “btutil” Library

      Before we actually start all of the command queue stuff, lets move to the btutil library that I talked about in the previous post.  To do this, add the library using the library manager.

      Then delete bt_platform_cfg_settings.h and bt_platform_cfg_settings.c from your project.  Finally Rebuild and make sure that everything still works.  That is it.

      Multithreading

      Id like to explain that there is now some danger.  That danger comes from the fact that we have multiple tasks which are all accessing data plus functions that are talking to each other ASYNCHRONOUSLY.  Specifically we have:

      1. The Bluetooth Stack task – running the Bluetooth stack and management callback
      2. The Bluetooth Stack APIs – e.g. wiced_bt_ble_observe
      3. The usrcmd task – which is interacting with the user on the serial port and talking to the other tasks
      4. A timer_svc task – which runs software timers
      5. The advertising data (which I will start saving in the next article)

      When faced with this situation what I typically like to do is provide thread safe public functions for each of the tasks.  Then any other task can call these functions and know that things are not going to get corrupted by a race condition.

      To make the design thread safe, I typically like to put an RTOS Queue between the tasks.  These queues are a safe place to send and receive data in a “thread safe” way.  There are two basic design patterns that can be used

      1. Define a message structure (that gets pushed into the queue) and make it global (via a dot-h).  Define a queue handle and make it global (via a dot-h).  Then let any task build messages and push them into the queue to be received in the task that owns the queue.
      2. Define the message structure and queue.  Then define functions which are global (via a dot-h) which know how to interact with the queue.

      I typically think that the 2nd method is better, so that is what I am going to do here.

      1. In BluetoothManager.h I will provide a function called “btm_cmdScan”
      2. The usrcmd task will call the btm_cmdScan function which will
      3. Create a btm_cmdMsg_t with the “scan” command and data of true/false
      4. Then push it into the Bluetooth Manager Command Queue
      5. Where a timer callback in the Bluetooth Manager Task will take it out of the queue
      6. Figure out that it is a “scan” command
      7. Then will either turn on or off scanning

      Add a Queue to the Bluetooth Manager Thread

      So we need two things a message to push into a queue (just a structure) and we need a queue to push it into.  First the message which is just a structure with two elements.  The first element is a command and the second element is some data of type void.  The meaning of the void *data will be different based on the command.

      But how about the command?  The command is just an enumerate list of commands which will now start with just one command.

      And know we need to define the queue.

      Before you can use the queue you need to initialize it.  The best place to initialize this queue is in the management callback right after the stack gets going.  You can see that I tell FreeRTOS that there is a queue which can hold up to 10 commands.  I also tell it that each command is the sizeof the command message.

      Now we need to create a way for other tasks to create these command messages.  They will do this by calling a function which we will define in the bluetoothManager.h

      This function will live in bluetoothManager.c and it simply

      1. Creates a command
      2. Set the actual command to scan
      3. Sets the void* data to be enable … in other words start or stop scanning.  Remember that a void * can be anything.  See I cast a bool to a void *
      4. Finally push the data into the command queue

      Add a Timer to Process the Queue

      So now we have a method to push items into the queue.  How do we get them out of the queue?  To do that I will use a Bluetooth Stack timer that will run every 50ms.

      First, define the timer in bluetoothManager.c

      Then define a function which the timer will call.  This function will

      1. Try to get a message out of the queue
      2. IF there is a message it will use a big switch to look at the possible messages
      3. If the message is a scan
      4. Then call the wiced function to either start “observing” or stop “observing”

      The last thing you need to do is start the timer.  The best place to start the timer is in the management callback where you need to

      1. Create the timer
      2. Tell it to start and run every 50ms

      A Potential Threading Bug

      When I did the implementation originally I created what I thought was a threading bug.  Specifically I used the FreeRTOS timer to process the queue.  In other words instead of using a wiced_timer_ext_t I used a TimerHandle_t.  So what?

      The wiced_timer_ext_t is run INSIDE of the BluetoothStack task where the TimerHandle_t is run inside of the Timer_SVC task.

      So what?  I was afraid that the call to wiced_bt_ble_obsere was NOT thread safe and needed to be called inside of the same task as the stack.

      After some digging I found out that the Bluetooth Stack is threadsafe, so I worried for no reason.  Well, actually, you can never worry enough about making these kinds of threading bugs because they are viscously difficult to debug.

      Add a Scan Off & On Command

      The last thing that you need to do is add an actual command to the usercmd task to call the bluetooth manager function to turn on and off scanning.

      First, add a new prototype for your new command in usercmd.c.  Then add it to the list of legal commands.

      Then create the function to process the command line input and call the btm_scan function.

      Now build it and run it.  You should still get adv packets barfing all over your screen.  But now you can turn on and off the scanning with “scan on” and “scan off”.  In the next article we will create a database to hold the scan packets.

      AnyCloud Bluetooth Utilities Library

      Summary

      This article is a discussion of a library of utilities functions that support AnyCloud Bluetooth development.  It includes settings to configure the hardware, functions to decode stack events, functions to decode advertising packets etc.

      Story

      The Cypress, now Infineon, Modus Toolbox team has been working to bring the WICED Bluetooth devices to be closer and more compatible with the PSoC 6 tools.  One of the important enablement things we have done is turn on the WICED Bluetooth Host stack on the PSoC 6 so that it can effectively talk to the CYW43XXX Bluetooth / WiFi combo chips.

      As I have been using all of the new stuff I found myself adding my own custom functionality…. and after a while I realized (finally) that I should put all of those little helper things into a library, specifically an IoT Expert library.  For now this library contains:

      • The Bluetooth Platform Configuration Settings
      • Functions to decode stack events
      • Functions to decode advertising packets

      but imagine with time I will add more functions and templates.

      bt_platform_cfg_settings

      As I discussed in the article AnyCloud Bluetooth Advertising Scanner (Part 1), every single AnyCloud BLE Stack project will require a structure of type wiced_bt_cfg_settings_t.  This structure is used to setup the hardware before getting the stack going.  Remember you need to make a call like this to initialize the Bluetooth hardware.

      At some point this file will be included automatically for you by the Modus Toolbox team, but for now I have added this to my library.  This file look like this.  Basically a bunch of pin definitions which are set for you automatically by the BSP.  Obviously you can make your own, but this should work on all of the Cypress development kits (I think)

      btutil_stack

      When you startup the Bluetooth Host stack you are responsible for providing a “management callback” which has the function prototype

      The first parameter is an “event” which is  just an enumerated list of possible events by the Bluetooth Host Stack.  Here is the actual list.

      While you are trying to figure out what is going on during the development, it is very useful to be able to print out the name of the events (instead of the numbers).  In other words instead of doing

      it is way better to do

      While I was looking at an example project I found this function which I thought was awesome.

      And then I learned something new when I looked at the “function” CASE_RETURN_STR which used compiler trick to turn an enumerated value into a string.

      This allows you to do this in your management callback (notice line 16 where the string is printed out)

      It turns out that there are several other places where the stack gives you an event-ish thing.  So these functions were created as well

      btutil_adv_decode

      In AnyCloud Bluetooth Advertising Scanner (Part 3) I discussed the format of the advertising packet.  So I created functions which will decode the data in the advertising packets.  More on the future article AnyCloud Bluetooth Advertising Scanner (Part 4 or maybe 5 or maybe 6).  Here are the functions:

      btutil

      And because I like to have just one include to get access to all of the function I created “btutil.h” which just includes all of the headers in one place.

      Add to the IoT Expert Manifest

      In order to set it up for my library to live in the library manager I updated the IoT Expert Manifest file to have a link to the GitHub repository

      And now the library manager has the IoT Expert Bluetooth Utilities.

       

       

      AnyCloud – Wireless Connection Manager (Part 2)

      Summary

      Part 2 of the 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 last article I walked you through creating a project using the wireless connection manager (WCM) which is one of the libraries that is part of the Infineon/Cypress AnyCloud SDK.  I introduced the wifi-mw-core, wifi-connection-manager and ntshell libraries.  In this article I will update the program to include commands to

      • connect (to an Access Point)
      • disconnect (from an Access Point)
      • print (mac address and ip address)

      Add the Connect

      I want to add a command that will let me issue a command line like

      • connect SSID (if it doesn’t have a passphrase)
      • connect SSID passphrase

      In order to connect to an Access Point you need to call the WCM API, cy_wcm_connect_ap.  Here is the function prototype:

      This function requires that you give it two arguments

      1. A pointer for a place to store the IP address (that comes from the DHCP server)
      2. A pointer to a structure of connection parameters.  That structure is as follows:

      Typically you would setup the “ap_credentials” part of the structure (unless you happen to know the MAC address of the AP you want to connect to).  Those credentials include the SSID and password as well as the security (WPA2 PSK etc…)

      Security is an enumeration of possible security types.

      Having to know the security of the AP is a total pain in the neck.  Where do you find the security from?  It turns out that when an AP beacons, the security of that SSID is one of the things that is broadcast.  What this means is that my program will need to

      1. When the connect command is called it should scan for the SSID that is part of the connect command & wait
      2. When the scan finds that SSID it will put the security type into the correct datastructure
      3. Then call the connect.

      The way that I will do this is to

      1. Build a filter (that looks only for the user specified SSID)
      2. Provides a pointer for a place to store the security type.

      I use the cy_wcm_scan function to do this.  Here is the function prototype:

      The scan filter is just a structure that specified

      1. A mode (which type of filter you want)
      2. The specific thing that you are looking for.

      The mode is simply an enumeration of the types of filters:

      What I want to do is start the scan and then wait for a semaphore.  To do this I will create a semaphore variable at the top of the netTask.c

      Inside of the switch I will

      1. Create a connection parameters structure (line 226-227)
      2. setup the scan filter (line 231-232)
      3. create the semaphore (line 235)
      4. run the scan (line 236)
      5. wait for the semaphore to be set or timeout (line 239) notice that I hardcoded it to 10 seconds

      In the scan callback I will check to see if I have real data (in other words the scan is not complete).  In the setup above I made the user data be a pointer to the place to store the security.  On line 54 I will store the security type that came back from the scan in the place pointed to by the user data pointer.  Then I will stop the scan and give the semaphore.

      Now back in the switch statement you can actually connect because you know the security type (line 244)  The else clause on line 253 handles the case where the timeout of the semaphore occurred, meaning that the scan didn’t find the AP.

      With all of the connection work done, you can add the scan command to “usrcmd.c”.  It just looks at the number of arguments (either 2 or 3), then sets up the message to send to the network task, the queues the message.

      Add the Disconnect Command

      The disconnect command is trivial.  Just call the disconnect api.

      Which you also need to add to the usercmd.c

      Add the Print Command

      The print command will have two optional parameters, IP (to print the current IP address) and MAC (to print our MAC address).  The first command is print ip.

      The MAC address command is also simple:

      And you need to add the print command to usrcmd.c

      All of this code is available on github at

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

      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

      Mouser Bluetooth Mesh: L1 Developer Resources

      How To Design With Bluetooth Mesh


      You can "git" a workspace will all of these files at https://github.com/iotexpert/MouserVTWBluetoothMesh or git@github.com:iotexpert/MouserVTWBluetoothMesh.git

      Summary

      This lesson has a bunch of links to useful documentation about Bluetooth Mesh.  It includes links to all of the Cypress software and application notes.  It also includes links to the Bluetooth Special Interest Group website for the BLE Mesh Specs.

      Cypress Resources

      1. Cypress Bluetooth Mesh Landing Page
      2. AN227069 – Getting Started with Bluetooth Mesh
      3. EZ-BT Mesh Evaluation Kit Landing Page
      4. EZ-BT Mesh Evaluation Kit QuickStart
      5. Modus Toolbox
      6. Cypress Bluetooth Community
      7. Bluetooth SDK 1.2
      8. Modus Toolbox Bluetooth SDK Examples @ github
      9. Cypress WICED Bluetooth 101 – Class
      10. Mesh Client
      11. Mesh Client Documentation

      Bluetooth Sig Resources

      1. Bluetooth SIG Mesh Specs
      2. Bluetooth SIG Mesh Profile Spec
      3. Bluetooth SIG Mesh Model Spec
      4. Bluetooth SIG Mesh Device Properties
      5. Introducing Bluetooth Mesh Networking
      6. Intro Bluetooth Mesh Part 1
      7. Intro Bluetooth Mesh Part 2
      8. Bluetooth Mesh Fundamental Concepts of BT Mesh Networking Part1
      9. Bluetooth Mesh Fundamental Concepts of BT Mesh Networking Part2
      10. Bluetooth Mesh Networking: Friendship
      11. Management of Devices in a Bluetooth Mesh Network
      12. In-Market Bluetooth Low Energy Devices and Bluetooth Mesh Networking
      13. Bluetooth Mesh Security Overview
      14. Provisioning a Bluetooth Mesh Network Part 1
      15. Provisioning a Bluetooth Mesh Network Part 2

      Other Useful Links

      1. Wikipedia Bluetooth Mesh

      Cypress Bluetooth Mesh Landing Page

      AN227069 – Getting Started with Bluetooth Mesh

      EZ-BT Mesh Evaluation Kit Landing Page

      EZ-BT Mesh Evaluation Kit QuickStart

      Modus Toolbox

      Cypress Bluetooth Community

      Bluetooth SDK 1.2

      Modus Toolbox Bluetooth SDK Examples @ github

      Cypress WICED Bluetooth 101 – Class

      Mesh Client

      Mesh Client Documentation

      Bluetooth SIG Mesh Specs

      Bluetooth SIG Mesh Profile Spec

      Bluetooth SIG Mesh Model Spec

      Bluetooth SIG Mesh Device Properties

      Introducing Bluetooth Mesh Networking

      Intro Bluetooth Mesh Part 1

      Intro Bluetooth Mesh Part 2

      Bluetooth Mesh Fundamental Concepts of BT Mesh Networking Part1

      Bluetooth Mesh Fundamental Concepts of BT Mesh Networking Part2

      Bluetooth Mesh Networking: Friendship

      Management of Devices in a Bluetooth Mesh Network

      In-Market Bluetooth Low Energy Devices and Bluetooth Mesh Networking

      Bluetooth Mesh Security Overview

      Provisioning a Bluetooth Mesh Network Part 1

      Provisioning a Bluetooth Mesh Network Part 2

      MBEDOS Little File System & CY8CPROTO_62_4343W

      Summary

      This is the first article in a series that will discuss how to use the MBED OS file systems with Cypress SPI Nor Flash chips and PSoC 6.

      Title
      The Back Story & Making the LittleFS Work with the CY8CKIT_062_4343W
      The Architecture of Filesystems in MBEDOS
      SPI Nor Flash
      SFDP
      The MBED OS Quad SPI Driver
      LittleFS
      FATFS
      MBED OS and POSIX Files

       

      The Back Story

      On a bunch of our development kits there is a SPI NOR Flash sitting right next to the PSoC 6.  Which exact SPI flash depends on the exact generation of development kit.  I have always wanted to use these chips, but had never had time to sort out how they work.  And quite frankly we never made it very easy to use them because although they were connected, we didn’t provide much in the way of software support.  However, with the advent of MBED OS at Cypress we were suddenly gifted with two file systems to use, LittleFS and FATFS.

      This journey starts with an email note to the Applications manager in India (an awesome woman named Jaya)… “Hey, can you get someone to send me an example of the MBED OS flash file system on the CY8CPROTO_062_4343W.”  A day or so later I got an email with an attached project and a “memo” that explained what to do.  This exchange happened right before Embedded World in February and I was really busy.  Finally, a couple of weeks ago I read the email and the instructions which started with “Break off the NOR Flash wing and solder….”  If you look in the picture below you can see that at the top of the kit there is a breakaway wing (circled in green) that has a SPI Flash chip on it (circled in red).

      Honestly, I didn’t read any further than “.. break off the wing…”.  So, I sent another note … “Uh… how about no.  Why can’t I use the development kit without soldering?”… And these two emails were my first steps down the Embedded FileSystem & NOR Flash Rabbit Hole which is the subject of this series of articles.

      Making the LittleFS Work with the CY8CKIT_062_4343W

      I am going to start by giving you the step by step instructions to make the LittleFS work … and these instruction will only include a little bit of commentary on how it works.  I will expand on the “how” in all of the follow on articles.  To make it work you need to follow these steps:

      1. Clone the MBEDOS FileSystem Example
      2. Clone my QSPI driver path
      3. Then patch MBEDOS with the updated QSPI driver.
      4. Test
      5. Examine the Project

      The first step in the process of running the example is to clone the MBED OS Example Project for Filesystems.  To do this, run “mbed import mbed-os-example-filesystem”.  As I noted above, the default MBED does not have the required drivers for the Quad SPI interface.  Fortunately another excellent Applications engineer in India named Vaira built me a QSPI driver in advance of the actual official release from Cypress.  I have put these drivers on the iotexpert github repository and you can get them with a “git clone git@github.com:iotexpert/MBED_QSPI_PATCHES.git”.  Once you have them you can apply the patch by

      1. cd mbed-os-example-filesystem
      2. ../MBED_QSPI_PATCHES/patch-qspi-mbed.sh

      The shell script is simple program that copies the driver files into the correct locations in your mbed-os directory in your current project.  I will talk in detail about these files in a later article.

      Here is what my terminal looks like after I run the import, clone and apply patches.

      Next I will build the project “as-is” using “mbed compile -t GCC_ARM -m CY8CPROTO_062_4343W”

      OK, the project looks like it builds with no problems (other than a very annoying boatload of warnings – I really wish people weren’t slobs).  Running the compile also has the nice side effect of setting the default target and toolchain.  You can see this by either looking at the “.mbed” file or by running “mbed config target” or “mbed config toolchain”.  Here is what my terminal window looks like

      Test

      I generally like to test a project before I start making changes to it.  I already compiled, so now, I program it into the board with either the Cypress Programmer or by running “mbed compile -f”.  When you attach a serial program to the development kit you will get something like this:

      So, the project seems to work.  When I run the project again (by pressing the reset button on the board), here is what I get:

      But what is it doing?  First, lets get the code into an editor where we can see what is happening:

      Visual Studio Code

      Recently, I have been using Visual Studio Code to view and edit my projects.  To make that experience better, it is a good idea to “export” the project from the MBED CLI.  This doesn’t change anything in your project, but it does create the files to make VSCODE work better.  To do this run “mbed export -i vscode_gcc_arm -m CY8CPROTO_062_4343W –profile mbed-os/tools/profiles/debug.json”

      When you start VSCODE it will look something like this:

      When I open the directory with my project with the “File -> Open …” menu

      It will look like this:

      Examine the Project

      Now click on main.cpp and your screen should look like this:

      To make any of the MBED OS Filesystems work, they need to have a “BlockDevice” to read and write the media, meaning the SPI Flash or SD Card or … The project as it comes from ARM creates the BlockDevice on line 23 where it asks for the “default_instance”.  Those configuration files which we patched MBED with earlier sets up the default instance to be the QSPI flash on the development kit (which I will explain in great detail in a later article).

      After you have a BlockDevice, the next thing that you need is a FileSystem object.  In this case on line 31-33 you can see that this project uses a LittleFileSystem.  The argument to the LittleFileSystem object creation is the mount point (think Unix “/fs/”).  The mount point is used by all of the POSIX APIs (open, close, read etc).  I will talk more about POSIX in later article.

      Near the start of main, the first real thing that happens is that you need to “mount” the Filesystem onto the BlockDevice.  This is done on line 80.  The mount will return an non-zero error code if there is nothing on the SPI Flash or the SPI Flash is corrupted.  If the mount fails, the program will try to create a filesystem by calling “reformat” on line 87.  If that fails the “error” will halt the whole thing and blink the red light on the board.

      Once we have a Filesystem (object) and it is formatted, the project will try to open the file “/fs/numbers.txt” using the POSIX API “open” on line 97.  The open specifics that it is to open the file for “read” and that it will append the “+”.  If that operation fails, it will try to create the file on line 103.

      If the file was opened for the first time, it will write the numbers 0-9 into the file using the loop (109) and fprintf (line 112).  The file will have lines with 4 spaces followed by a number then a “\n”.  This format was chosen to make the parsing easier later on in the program.

      Once the file is initialized, you want the put the file point back to the start which is done with the “fseek” on line 122.

      The main part of the program will start at the top,  read the numbers and increment them, and write them back into the file.  I am not really in love with this block of code… but I suppose that it is functional.

      Once all of the numbers are incremented and written back into the file, the last step is closing the file on line 156.

      The next phase of the program is to do a directory listing using the POSIX directory APIs (opendir, readdir,closedir).  This little block of code will print out all of the files in the “/fs” directory.

      Then they demonstrate opening the numbers.txt file and printing out the data.

      And finally closing things up by unmounting the filesystem.

      Super Annoying Hard Code

      All through this example program the number “10” is hardcoded.  This is called a MAGIC NUMBER and in this particular case is not at all a good thing.  Moreover, lines of code like this represent absolute insanity.

      Really… just don’t do this.  Friends don’t let friends use magic numbers.

      Erasing the FileSystem

      Near the top of main you can see that they register an interrupt to create an event when the button on the development kit is pressed.

      The erase function simply initializes the block device, calls erase and then de-inits the block device.  This will cause the whole thing to begin anew when the kit is reset.

      The first time I ran the erase, I thought that there was something wrong… and I ended up going through a big debug loop.  The final step in the debug loop was being patient… which isn’t really in my wheelhouse.  I added this little block of code which timed the erase operation.

      And it turns out the answer is 115.06 seconds.  I am going to have to figure out why it takes so long.

      The last thing to notice is that if you press the erase button while it is writing the files, Im pretty sure that something bad happens.

      In the next articles I will examine this system in much much more detail.  Again thanks to Jaya and Vaira for their excellent work.

       

      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.