A BLE HID controller implementation with communication over SPI

Dependencies:   BLE_API BLE_HID mbed nRF51822

Committer:
mrhannah
Date:
Wed Dec 13 05:34:15 2017 +0000
Revision:
0:f21dc3a04d62
Initial/(final) changes for project

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mrhannah 0:f21dc3a04d62 1 /* mbed Microcontroller Library
mrhannah 0:f21dc3a04d62 2 * Copyright (c) 2015 ARM Limited
mrhannah 0:f21dc3a04d62 3 *
mrhannah 0:f21dc3a04d62 4 * Licensed under the Apache License, Version 2.0 (the "License");
mrhannah 0:f21dc3a04d62 5 * you may not use this file except in compliance with the License.
mrhannah 0:f21dc3a04d62 6 * You may obtain a copy of the License at
mrhannah 0:f21dc3a04d62 7 *
mrhannah 0:f21dc3a04d62 8 * http://www.apache.org/licenses/LICENSE-2.0
mrhannah 0:f21dc3a04d62 9 *
mrhannah 0:f21dc3a04d62 10 * Unless required by applicable law or agreed to in writing, software
mrhannah 0:f21dc3a04d62 11 * distributed under the License is distributed on an "AS IS" BASIS,
mrhannah 0:f21dc3a04d62 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mrhannah 0:f21dc3a04d62 13 * See the License for the specific language governing permissions and
mrhannah 0:f21dc3a04d62 14 * limitations under the License.
mrhannah 0:f21dc3a04d62 15 */
mrhannah 0:f21dc3a04d62 16
mrhannah 0:f21dc3a04d62 17 #include "mbed.h"
mrhannah 0:f21dc3a04d62 18
mrhannah 0:f21dc3a04d62 19 #include "ble/BLE.h"
mrhannah 0:f21dc3a04d62 20 #include "ControllerService.h"
mrhannah 0:f21dc3a04d62 21 #include "common.h"
mrhannah 0:f21dc3a04d62 22
mrhannah 0:f21dc3a04d62 23 /**
mrhannah 0:f21dc3a04d62 24 * This program implements a complete HID-over-Gatt Profile:
mrhannah 0:f21dc3a04d62 25 * - HID is provided by ControllerServices
mrhannah 0:f21dc3a04d62 26 * - Battery Service
mrhannah 0:f21dc3a04d62 27 * - Device Information Service
mrhannah 0:f21dc3a04d62 28 *
mrhannah 0:f21dc3a04d62 29 */
mrhannah 0:f21dc3a04d62 30
mrhannah 0:f21dc3a04d62 31 DigitalOut waiting_led(LED1);
mrhannah 0:f21dc3a04d62 32 DigitalOut connected_led(LED2);
mrhannah 0:f21dc3a04d62 33
mrhannah 0:f21dc3a04d62 34
mrhannah 0:f21dc3a04d62 35 SPISlave arduino(p23, p22, p21, p24); // mosi, miso, sck, ssel
mrhannah 0:f21dc3a04d62 36 DigitalOut arduino_int(p25);
mrhannah 0:f21dc3a04d62 37
mrhannah 0:f21dc3a04d62 38 BLE ble;
mrhannah 0:f21dc3a04d62 39 ControllerService *contServicePtr;
mrhannah 0:f21dc3a04d62 40
mrhannah 0:f21dc3a04d62 41 static const char DEVICE_NAME[] = "puppeteerPro";
mrhannah 0:f21dc3a04d62 42 static const char SHORT_DEVICE_NAME[] = "pptPro";
mrhannah 0:f21dc3a04d62 43
mrhannah 0:f21dc3a04d62 44 static void onDisconnect(const Gap::DisconnectionCallbackParams_t *params)
mrhannah 0:f21dc3a04d62 45 {
mrhannah 0:f21dc3a04d62 46 HID_DEBUG("disconnected\r\n");
mrhannah 0:f21dc3a04d62 47 connected_led = 0;
mrhannah 0:f21dc3a04d62 48
mrhannah 0:f21dc3a04d62 49 ble.gap().startAdvertising(); // restart advertising
mrhannah 0:f21dc3a04d62 50 }
mrhannah 0:f21dc3a04d62 51
mrhannah 0:f21dc3a04d62 52 static void onConnect(const Gap::ConnectionCallbackParams_t *params)
mrhannah 0:f21dc3a04d62 53 {
mrhannah 0:f21dc3a04d62 54 HID_DEBUG("connected\r\n");
mrhannah 0:f21dc3a04d62 55 waiting_led = false;
mrhannah 0:f21dc3a04d62 56 }
mrhannah 0:f21dc3a04d62 57
mrhannah 0:f21dc3a04d62 58 static void waiting() {
mrhannah 0:f21dc3a04d62 59 if (!contServicePtr->isConnected()) {
mrhannah 0:f21dc3a04d62 60 //connected_led = !connected_led;
mrhannah 0:f21dc3a04d62 61 }
mrhannah 0:f21dc3a04d62 62 else {
mrhannah 0:f21dc3a04d62 63 //connected_led = 1;
mrhannah 0:f21dc3a04d62 64 }
mrhannah 0:f21dc3a04d62 65 }
mrhannah 0:f21dc3a04d62 66
mrhannah 0:f21dc3a04d62 67 // Current system
mrhannah 0:f21dc3a04d62 68 // arduino does slave select & interrupt
mrhannah 0:f21dc3a04d62 69 // arduino transfers
mrhannah 0:f21dc3a04d62 70 // ble hits isr & records current report
mrhannah 0:f21dc3a04d62 71 void spi_receive() {
mrhannah 0:f21dc3a04d62 72 static uint8_t byte_count = 0;
mrhannah 0:f21dc3a04d62 73 static uint8_t current_report[6] = {0};
mrhannah 0:f21dc3a04d62 74
mrhannah 0:f21dc3a04d62 75 if(arduino.receive()) {
mrhannah 0:f21dc3a04d62 76 waiting_led = !waiting_led;
mrhannah 0:f21dc3a04d62 77 uint8_t resp = arduino.read();
mrhannah 0:f21dc3a04d62 78
mrhannah 0:f21dc3a04d62 79 if (resp == 0xFF) {
mrhannah 0:f21dc3a04d62 80 byte_count = 0;
mrhannah 0:f21dc3a04d62 81 memset(current_report, 0, sizeof(current_report));
mrhannah 0:f21dc3a04d62 82 } else {
mrhannah 0:f21dc3a04d62 83 current_report[byte_count] = resp;
mrhannah 0:f21dc3a04d62 84 byte_count++;
mrhannah 0:f21dc3a04d62 85
mrhannah 0:f21dc3a04d62 86 if (byte_count == 6) {
mrhannah 0:f21dc3a04d62 87 connected_led = !connected_led;
mrhannah 0:f21dc3a04d62 88 contServicePtr->setReport(current_report);
mrhannah 0:f21dc3a04d62 89 byte_count = 0;
mrhannah 0:f21dc3a04d62 90 }
mrhannah 0:f21dc3a04d62 91 }
mrhannah 0:f21dc3a04d62 92 arduino.reply(0xAA);
mrhannah 0:f21dc3a04d62 93
mrhannah 0:f21dc3a04d62 94 // finally trigger interrupt to signal receiving
mrhannah 0:f21dc3a04d62 95 arduino_int = 0;
mrhannah 0:f21dc3a04d62 96 wait_us(100);
mrhannah 0:f21dc3a04d62 97 arduino_int = 1;
mrhannah 0:f21dc3a04d62 98 wait_us(100);
mrhannah 0:f21dc3a04d62 99 arduino_int = 0;
mrhannah 0:f21dc3a04d62 100 }
mrhannah 0:f21dc3a04d62 101 }
mrhannah 0:f21dc3a04d62 102
mrhannah 0:f21dc3a04d62 103 int main()
mrhannah 0:f21dc3a04d62 104 {
mrhannah 0:f21dc3a04d62 105 Ticker heartbeat;
mrhannah 0:f21dc3a04d62 106
mrhannah 0:f21dc3a04d62 107 HID_DEBUG("initialising ticker\r\n");
mrhannah 0:f21dc3a04d62 108
mrhannah 0:f21dc3a04d62 109 heartbeat.attach(waiting, 1);
mrhannah 0:f21dc3a04d62 110
mrhannah 0:f21dc3a04d62 111 HID_DEBUG("initialising ble\r\n");
mrhannah 0:f21dc3a04d62 112 ble.init();
mrhannah 0:f21dc3a04d62 113
mrhannah 0:f21dc3a04d62 114 ble.gap().onDisconnection(onDisconnect);
mrhannah 0:f21dc3a04d62 115 ble.gap().onConnection(onConnect);
mrhannah 0:f21dc3a04d62 116
mrhannah 0:f21dc3a04d62 117 initializeSecurity(ble);
mrhannah 0:f21dc3a04d62 118
mrhannah 0:f21dc3a04d62 119 HID_DEBUG("adding hid service\r\n");
mrhannah 0:f21dc3a04d62 120 ControllerService contService(ble);
mrhannah 0:f21dc3a04d62 121 contServicePtr = &contService;
mrhannah 0:f21dc3a04d62 122
mrhannah 0:f21dc3a04d62 123 HID_DEBUG("adding device info and battery service\r\n");
mrhannah 0:f21dc3a04d62 124 initializeHOGP(ble);
mrhannah 0:f21dc3a04d62 125
mrhannah 0:f21dc3a04d62 126 HID_DEBUG("setting up gap\r\n");
mrhannah 0:f21dc3a04d62 127 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GAMEPAD);
mrhannah 0:f21dc3a04d62 128 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME,
mrhannah 0:f21dc3a04d62 129 (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
mrhannah 0:f21dc3a04d62 130 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
mrhannah 0:f21dc3a04d62 131 (const uint8_t *)SHORT_DEVICE_NAME, sizeof(SHORT_DEVICE_NAME));
mrhannah 0:f21dc3a04d62 132
mrhannah 0:f21dc3a04d62 133 ble.gap().setDeviceName((const uint8_t *)DEVICE_NAME);
mrhannah 0:f21dc3a04d62 134
mrhannah 0:f21dc3a04d62 135 HID_DEBUG("advertising\r\n");
mrhannah 0:f21dc3a04d62 136 ble.gap().startAdvertising();
mrhannah 0:f21dc3a04d62 137
mrhannah 0:f21dc3a04d62 138 // Start interrupt sequence for SPI with Arduino
mrhannah 0:f21dc3a04d62 139 Ticker spi_thread;
mrhannah 0:f21dc3a04d62 140 connected_led = 1;
mrhannah 0:f21dc3a04d62 141 arduino_int = 0;
mrhannah 0:f21dc3a04d62 142 arduino.reply(0xAA);
mrhannah 0:f21dc3a04d62 143 spi_thread.attach(spi_receive, 0.020); // 5ms ticker sequence
mrhannah 0:f21dc3a04d62 144
mrhannah 0:f21dc3a04d62 145
mrhannah 0:f21dc3a04d62 146 while (true) {
mrhannah 0:f21dc3a04d62 147 ble.waitForEvent();
mrhannah 0:f21dc3a04d62 148 }
mrhannah 0:f21dc3a04d62 149 }