Riiiver Sample FW

With this sample firmware, you can learn how Riiiver works on the Qualcomm QCC5100.

The demonstration requires a smartphone(iOS or Android is OK) to install the sample app.


What this firmware does:
  • Start advertising and connect with Smartphone
  • Assign Riiiver function to the button of QCC5100.
  • Send the command to the Smartphone via the button pressed, and QCC5100 receives the result from Riiiver.
  • Display the result of Riiiver feature (called "iiidea").

Qualcomm devices [RiiiverSampleFW for QCC5100, QualComm Development Board (EVB)].
Riiiver device [smartphone, SampleApp for smartphone].
Cloud [Riiiver Server].

Note
- Qualcomm devices [RiiiverSampleFW for QCC5100, QualComm Development Board (EVB)].
- Riiiver device [smartphone, RiiiverSampleApp for smartphone].
- Cloud [Riiiver Server].

slate+demo_oeverview

System Requirements
Softwareversion
windowswindows10
linuxv16.04 long-term support (LTS) or later
Arm compilerv6.14.1 or v6.15
Pythonv3.8.10
LVGLv8.3
Installation

Downloading the project, you will see flash.bin under the /Binary directory. Write that binary file to QCC5100, and you can run the demonstration.

.
└── Binary/Flash.bin

The procedure how for writing the binary is described in QCC5100__Software_User_Guide: 5 Load QCC5100 images to device. It can be operated with Linux or Windows.

Build

Riiiver Sample FW already complexed to the Binary File. So, you can write it without Build.

If you want to change the code of Riiiver Sample FW and to build.
Refer to QCC5100__Software_User_Guide: 4 Build software for QCC5100/QCC5100+.
Use the following commands for build.

Windows:./build.bat   --standalone_dutplus --auo-sod-97706 --enable_disp_hostless 2>&1 | tee build.log

linux: ./build.sh   --standalone_dutplus --auo-sod-97706 --enable_disp_hostless 2>&1 | tee build.log
Usage

Here, you can find a quick guide for the demonstration of Riiiver utilizing the QCC5100 UART serial interface-QCLI.

1.Turn on the QCC5100 after writing the flash.bin, and you can find the Riiiver_Demo is listed in the command list of the QCLI. Select the Riiiver_Demo.

slate+demo_list

2.Run the 4 1 command to start the Riiiver_Demo app.

3.Run the 4 2 command, which initializes the Riiiver_Demo app and starts to advertising after completing the initialization.

slate+initialize

When completing the initialization, the home screen appears on the display of the evaluation board(EVB).

slate+initialize

4.Using the sample app in Smartphone, start scanning the peripheral devices nearby and connect to the EVB.

5.Set up the Riiiver features with the sample app. In details, also refer to the sample app document: How does this sample demonstrate?.

6.Run the 4 3 or 4 4 command, which corresponds to button 1 pressed or button 2 pressed respectively, FW will notify the event to the sample app as the BLE sequence.

slate+scan_list

Once you enter the 4 3 or 4 4 command, In the BLE sequence, While waiting for the response from the smartphone, the running animation appears on the display of the EVB.

Note
Another new command is not accepted while this animation is on.

slate+scan_list

7.You will see the result returned from the sample app on the display of the EVB.

slate+scan_list

Project structures

The Riiiver Sample FW is made based on qcc5100-fr-1-0_ap_standard_oem. The project structure is shown as follows. Most of the files used for the Riiiver demonstration are provided under the riiiver directory.

.
└── apps_proc/
    └── fw/
        └── app/
            └── demo/
                └── QCLI_demo/
                    └── src/
                        └── riiiver
File NameWhat kind of features are implemented
riiiver_bluetoothBluetooth communication.
riiiver_buttonManage the event regarding the physical button.
riiiver_demoThe main() function for the Riiiver demonstration.
riiiver_global_dataDeclare variables globally.
riiiver_guiGraphic features.
riiiver_utilDeclare some functions commonly used.

In addition, other changes have been made to work RiiiverDemo.

See the appendix for details below.

wear_bt_app_domain_interdace.c

BLE Specifications

The Riiiver Sample FW provides an original GATT communication service. This section describes the characteristics that service has.

Here, let the EVB be the Qualcomm device (peripheral device) and the smartphone be the Riiiver device (central device).

The Qualcomm device is the GATT Server Role and the Riiiver device is the GATT Client Role.
The Qualcomm device advertises and the Riiver device scans and connects.
CustomService is a BLE Service that exists on the Qualcomm device side.

Peripheral Riiiver Service

The Peripheral Riiiver Service exposes events and some data related to Qualcomm devices and Riiiver devices.

The service is identified with UUID 0000A000-0000-1000-8000-00805F9B34FB.

This service consists of 2 characteristics, OnBoardUserEvent characteristic and CommandReceiver characteristic.

CharacteristicNameUUIDPropertiesnote
OnBoardUserEvent0000A001-0000-1000-8000-00805F9B34FBIndicateShall be used to send the event that occured on the Qualcomm device.
CommandReceiver0000A002-0000-1000-8000-00805F9B34FBWriteShall be used to recieve the result of an iiidea from Riiiver device.
OnBoardUserEvent

The OnBoardUserEvent is performed to send the event that occurred on the Qualcomm device.

Characteristic behavior

It is configured with the Client characteristic descriptor, If some event would be happens such as pressing the button of QCC5100 EVB, it will indicate the event information to Riiiver Device. The event types are defined as follows:

  • The button 1 on the EVB is pressed
  • The button 2 on the EVB is pressed
  • An operation succeeds
  • An operation fails

The send data value follows the format, which is described on Data format part later.

CommandReceiver

The CommandReceiver is performed to recieve the result of an iiidea from Riiiver device.

Characteristic behavior

When CommandReceiver characteristic value is written by the Riiiver server,
Qualcomm device will interpret the value and display the result on its screen.
The value is required to follow in the Data format below.

Data format

The data sent between the client and the server is required to be formatted following specific rules. The data format is as follows:

The IDs for the OnBoardUserEvent characteristic

slate+dataform

namesizeConstraints / Notes
Data Size2 byteMust be little-endian.
Command1 byteThis ID indicates the event type. This value is selected from the command list described below.
Identification DataX byteFor Command ID 0x2 or 0x3, Button1Event = 0x0, Button2Event = 0x1 is set. Normally, 0x0 is set.
The Data format for the CommandReceiver characteristic

slate+dataform

namesizeConstraints / Notes
Data Size2 byteMust be little-endian.
Command1 byteThis ID indicates the event type. This value is selected from the command list described below.
iiidea ResultX byteThe result of the Riiiver feature(iiidea).
Data Size

Data size describes as followings:
DataSize = Y[Byte], then X = Y-1[Byte]

The length of this data must be 2 bytes and to be in little-endian order.

Command

This ID indicates the event type. The command IDs are different according to the direction of the data, i.e. from the Qualcomm device to the Riiiver device or from the Riiiver device to the Qualcomm device.

The IDs for the OnBoardUserEvent characteristic
Idcommand
0x00The button 1 on the EVB is pressed.
0x01The button 2 on the EVB is pressed.
0x02An operation succeeds.
0x03An operation fails.
The IDs for the CommandReceiver characteristic
Idcommand
0x00The result of the iiidea kicked by pressing the button 1.
0x01The result of the iiidea kicked by pressing the button 2.
0x02Shall be used to send data by taking the Riiiver device as a starting point.
0x03Shall be used to notify that some event succeeded.
0x04Shall be used to notify that some event failed.
Value to Display

The value (iiideea Result) includes the key, tab and String message to display the result on the screen.
The value can include a key that specifies the logo image appearing with the messages. The key and the messages must be separated by a tab character.
If only String message (text message) are present, the messages appear on the screen with the default logo image.

slate+iiideaform

If a non-existent key is specified, "GUI DATA ERROR" will be displayed on the screen.

The format of the string is as follows.
Result key character code: UTF-8
Result string character code: UTF-8
Terminating character (NULL character): None

Keys for Logo
Keyiiidea that is expected to be used withWhat it looks like
w_00weatherSunny
w_01weatherCloudy
w_02weatherRainy
w_03weatherPartly cloudy
w_04weatherPartly rainy
g_00GmailMail envelope
g_10Google CalendarCalendar
f_00Flight InformationAir plane
s_00Sports ScoreAmerican Football
s_10Sports ScoreBasketball
s_20Sports ScoreBaseball
s_30Sports ScoreIce Hockey
Example: Execute an iiidea by pressing button

When the button1 on the EVB is pressed, the value of theOnBoardUserEvent characteristic would be updated to 0x 02 00 00 00.

The server that subscribes theOnBoardUserEvent characteristic descriptor receives the updates and executes the iiidea according to the value.

Riiiver device receives the OnBoardUserEvent characteristic updates and will execute the iiidea according to command ID of the value.

After executing iiidea, Riiiver device writes the result of the iiidea as the value for the CommandReceiver characteristic.

for example,
If the value set 0x 0b 00 00 77 5f 30 30 09 53 75 6e 6e 79,
field allocation would be bellow.

slate+dataform_1

Data architecture is little-endian, So, “0b 00” can be replaced with “0x000b”.
Then, we can find the Data Size that the succeeding data length is 12 bytes.

The Command ID00 respresents that the value is the result of the iiidea kicked by pressing button 1(refer to Table The IDs for the OnBoardUserEvent characteristic).

The value to display 0x 77 5f 30 30 09 53 75 6e 6e 79 is decoded as follows:

decoded = w_00\tSunny

Therefore, in this case, the client shall display the message "Sunny" with the weather icon specified with key w_00 on its screen.

Seaquence

slate+seaquence

License

LVGL (https://lvgl.io/) is used to draw on the screen.
Follow MIT for the LVGL code.
(https://opensource.org/licenses/mit-license.php )

appendix

Riiiver Sample FW code changes for implementation

wear_bt_app_domain_interdace.c
.
└── apps_proc/
    └── fw/
        └── app/
            └── productsw/
                └── wear_bt_app/
                    └── src/
Line: 48
-                               
+ #include "riiiver_bluetooth.h"

Line: 119
- const uint8 btApp_adv_dataExtended[] = {11, 0x09, 'S', 'L', 'A', 'T', 'E', '_', '+' , '_', 'E', '\0'};
+ const uint8 btApp_adv_dataExtended[] = {11, 0x09, 'R', 'i', 'i', 'i', 'v', 'e', 'r' ,'_', 'E', '\0'};

Line: 789
        case QAPI_BT_GATT_SERVER_INIT_COMPLETE:
        {
            WEARBTAPP_LOG("QAPI_BT_GATT_SERVER_INIT_COMPLETE %x", id);
            /* Allocate Database in the stack*/-            qapi_bt_GattServer_DBAllocRequest(&bt_gatt_server_task, 20, 1);
+            qapi_bt_GattServer_DBAllocRequest(&bt_gatt_server_task, 60, 1);
        }

Line: 758 - 781
#ifdef WEAR_BT_ENABLE_EVENT_COUNTER_REPORTING
-    if(NULL != ind->bt_gatt_access_write_ind_message.writeUnit)
-    {
-        WEARBTAPP_LOG("<== QAPI_BT_GATT_SERVER_DB_ACCESS_WRITE_IND Attr hndl %d, value length: %d",
-                ind->bt_gatt_access_write_ind_message.writeUnit[0].attrHandle, ind->bt_gatt_access_write_ind_message.writeUnit[0].valueLength);
-    }
-    else
-    {
-        WEARBTAPP_LOG("<== QAPI_BT_GATT_SERVER_DB_ACCESS_WRITE_IND received write unit as NULL");
-    }

+    boolean is_complete_receive = FALSE;
+    if(NULL != ind->bt_gatt_access_write_ind_message.writeUnit)
+    {
+        if(ind->bt_gatt_access_write_ind_message.attrHandle == 0x1b){
+            WEARBTAPP_LOG("APP_TO_WATCH MESSAGE");
+            is_complete_receive = riiiver_received_data_handler(ind->bt_gatt_access_write_ind_message.writeUnit[0].valueLength,
+                                        ind->bt_gatt_access_write_ind_message.writeUnit[0].value); 
+        }else{
+            WEARBTAPP_LOG("discard message" );
+        }
+    }
+    else
+    {
+        WEARBTAPP_LOG("<== QAPI_BT_GATT_SERVER_DB_ACCESS_WRITE_IND received write unit as NULL");
+    }

Line: 2641-2687
    head = qapi_BT_GATT_Util_Create_Primary_Service_With_16_Bit_Uuid(head,
                                                                     &attrHandle,
                                                                     0xA000, /* Temp UUID */                                                                     FALSE,
                                                                     &tail);

    BT_APP_LOG("Sample GATT service attr hndl :%d",attrHandle);
-    properties     = QAPI_BT_GATT_CHARAC_PROPERTIES_WRITE | QAPI_BT_GATT_CHARAC_PROPERTIES_READ | \
-    QAPI_BT_GATT_CHARAC_PROPERTIES_NOTIFY | QAPI_BT_GATT_CHARAC_PROPERTIES_INDICATE;
+    properties     =  QAPI_BT_GATT_CHARAC_PROPERTIES_READ | QAPI_BT_GATT_CHARAC_PROPERTIES_INDICATE;
    attrValueFlags = (QAPI_BT_GATT_ATTR_FLAGS_IRQ_READ | QAPI_BT_GATT_ATTR_FLAGS_IRQ_WRITE);
    head = qapi_BT_GATT_Util_Create_Charac_Definition_With_16_Bit_Uuid(head,
                                                                       &attrHandle,
                                                                       properties,
                                                                       0xA001, /* Temp UUID */                                                                       attrValueFlags,
                                                                       2,value,
                                                                       &tail);

    BT_APP_LOG("Sample GATT characteristic attr hndl :%d",attrHandle);

    
-    head = qapi_BT_GATT_Util_Create_Client_Charac_Configuration(head,
-                                                                &attrHandle,
-                                                                CSR_BT_GATT_ATTR_FLAGS_IRQ_WRITE,
-                                                                &tail);


+    head = qapi_BT_GATT_Util_Create_Client_Charac_Configuration(head,
+                                                                &attrHandle,
+                                                                CSR_BT_GATT_ATTR_FLAGS_IRQ_WRITE,
+                                                                &tail);

+    BT_APP_LOG("Sample GATT CCCD attr hndl :%d",attrHandle);

+    properties     = QAPI_BT_GATT_CHARAC_PROPERTIES_WRITE;
+    attrValueFlags = (QAPI_BT_GATT_ATTR_FLAGS_IRQ_READ | QAPI_BT_GATT_ATTR_FLAGS_IRQ_WRITE);
+    head = qapi_BT_GATT_Util_Create_Charac_Definition_With_16_Bit_Uuid(head,
+                                                                       &attrHandle,
+                                                                       properties,
+                                                                       0xA002, /* Temp UUID */+                                                                       attrValueFlags,
+                                                                       2,value,
+                                                                       &tail);
+
+    BT_APP_LOG("Sample GATT characteristic attr hndl :%d",attrHandle);
+
+
+    head = qapi_BT_GATT_Util_Create_Client_Charac_Configuration(head,
+                                                                &attrHandle,
+                                                                CSR_BT_GATT_ATTR_FLAGS_IRQ_WRITE,
+                                                                &tail);

Line 2940-2987
        case BT_APP_SEND_GATT_NOTIFICATION:
        {
            /* Hardcoded, to be fetched from database source*/            uint16_t handle = 0x18;
            Wear_Bt_App_Context_t* app_context = BTApp_GetContext();
            qapi_BT_Conn_Id_t activeBtConnId = app_context->cid;

-            uint16_t len = 2;
-            uint8_t *value  = malloc(len);
+            uint16_t len = (((uint8*)(data->params))[0]);
+            uint8_t *value;
+            value = malloc(len+1);
      if(value == NULL)
      {
        /* Error fatal. malloc failure */        WEARBTAPP_ERROR_FATAL_LOG("malloc failure");
      }
      else
      {
-               value[0] = (((uint8*)(data->params))[0]);
-               value[1] = (((uint8*)(data->params))[1]);

+               value[0] = (((uint8*)(data->params))[0]);
+               value[1] = (((uint8*)(data->params))[1]);
+               value[2] = (((uint8*)(data->params))[2]);

              WEARBTAPP_LOG("==> qapi_BT_GATT_Indication_Req");
-            qapi_bt_GattServer_NotificationReq(&bt_gatt_server_task, activeBtConnId, handle, len+1, value);
+               qapi_bt_GattServer_NotificationReq(&bt_gatt_server_task, activeBtConnId, handle, len, value);
      }
            break;
        }
        case BT_APP_SEND_GATT_INDICATION:
        {
            /* Hardcoded, to be fetched from database source*/            uint16_t handle = 0x18;
            Wear_Bt_App_Context_t* app_context = BTApp_GetContext();
            qapi_BT_Conn_Id_t activeBtConnId = app_context->cid;

-            uint16_t len = 2;
-            uint8_t *value  = malloc(len);
+            uint16_t len = (((uint8*)(data->params))[0]);
+            uint8_t *value;
+            value = malloc(len+1);
      if(value == NULL)
      {
        /* Error fatal. malloc failure */        WEARBTAPP_ERROR_FATAL_LOG("malloc failure");
      }
      else
      {
-               value[0] = (((uint8*)(data->params))[0]);
-               value[1] = (((uint8*)(data->params))[1]);

+               value[0] = (((uint8*)(data->params))[0]);
+               value[1] = (((uint8*)(data->params))[1]);
+               value[2] = (((uint8*)(data->params))[2]);

                WEARBTAPP_LOG("==> qapi_BT_GATT_Indication_Req");

-               qapi_bt_GattServer_IndicationReq(&bt_gatt_server_task, activeBtConnId, handle, len, value);
+               qapi_bt_GattServer_IndicationReq(&bt_gatt_server_task, activeBtConnId, handle, len+1, value);

            break;
        }