A BLE HID controller implementation with communication over SPI

Dependencies:   BLE_API BLE_HID mbed nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "mbed.h"
00018 
00019 #include "ble/BLE.h"
00020 #include "ControllerService.h"
00021 #include "common.h"
00022 
00023 /**
00024  * This program implements a complete HID-over-Gatt Profile:
00025  *  - HID is provided by ControllerServices
00026  *  - Battery Service
00027  *  - Device Information Service
00028  *
00029  */
00030 
00031 DigitalOut waiting_led(LED1);
00032 DigitalOut connected_led(LED2);
00033 
00034 
00035 SPISlave arduino(p23, p22, p21, p24);  // mosi, miso, sck, ssel
00036 DigitalOut arduino_int(p25);
00037 
00038 BLE ble;
00039 ControllerService *contServicePtr;
00040 
00041 static const char DEVICE_NAME[] = "puppeteerPro";
00042 static const char SHORT_DEVICE_NAME[] = "pptPro";
00043 
00044 static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params)
00045 {
00046     HID_DEBUG("disconnected\r\n");
00047     connected_led = 0;
00048 
00049     ble.gap().startAdvertising(); // restart advertising
00050 }
00051 
00052 static void onConnect(const Gap::ConnectionCallbackParams_t *params)
00053 {
00054     HID_DEBUG("connected\r\n");
00055     waiting_led = false;
00056 }
00057 
00058 static void waiting() {
00059     if (!contServicePtr->isConnected()) {
00060         //connected_led = !connected_led;
00061     }
00062     else {
00063         //connected_led = 1;
00064     }
00065 }
00066 
00067 // Current system
00068 // arduino does slave select & interrupt
00069 // arduino transfers
00070 // ble hits isr & records current report
00071 void spi_receive() {
00072     static uint8_t byte_count = 0;
00073     static uint8_t current_report[6] = {0};
00074 
00075     if(arduino.receive()) {
00076         waiting_led = !waiting_led;
00077         uint8_t resp = arduino.read();
00078     
00079         if (resp == 0xFF) {
00080             byte_count = 0;
00081             memset(current_report, 0, sizeof(current_report));
00082         } else {
00083             current_report[byte_count] = resp;
00084             byte_count++;
00085         
00086             if (byte_count == 6) {
00087                 connected_led = !connected_led;
00088                 contServicePtr->setReport(current_report);
00089                 byte_count = 0;
00090             }
00091         }
00092         arduino.reply(0xAA);
00093 
00094         // finally trigger interrupt to signal receiving
00095         arduino_int = 0;
00096         wait_us(100);
00097         arduino_int = 1;
00098         wait_us(100);
00099         arduino_int = 0;
00100     }
00101 }
00102 
00103 int main()
00104 {
00105     Ticker heartbeat;
00106 
00107     HID_DEBUG("initialising ticker\r\n");
00108 
00109     heartbeat.attach(waiting, 1);
00110 
00111     HID_DEBUG("initialising ble\r\n");
00112     ble.init();
00113 
00114     ble.gap().onDisconnection(onDisconnect);
00115     ble.gap().onConnection(onConnect);
00116 
00117     initializeSecurity(ble);
00118 
00119     HID_DEBUG("adding hid service\r\n");
00120     ControllerService contService(ble);
00121     contServicePtr = &contService;
00122 
00123     HID_DEBUG("adding device info and battery service\r\n");
00124     initializeHOGP(ble);
00125 
00126     HID_DEBUG("setting up gap\r\n");
00127     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GAMEPAD);
00128     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME,
00129                                            (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00130     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
00131                                            (const uint8_t *)SHORT_DEVICE_NAME, sizeof(SHORT_DEVICE_NAME));
00132 
00133     ble.gap().setDeviceName((const uint8_t *)DEVICE_NAME);
00134 
00135     HID_DEBUG("advertising\r\n");
00136     ble.gap().startAdvertising();
00137     
00138     // Start interrupt sequence for SPI with Arduino
00139     Ticker spi_thread;
00140     connected_led = 1;
00141     arduino_int = 0;
00142     arduino.reply(0xAA);
00143     spi_thread.attach(spi_receive, 0.020); // 5ms ticker sequence
00144 
00145     
00146     while (true) {
00147         ble.waitForEvent();
00148     }
00149 }