BLE switch interface using micro:bit with 3 tact switches or 3 Makey Makey sensors

Dependencies:   microbit

Committer:
masakjm
Date:
Tue Jun 11 18:08:53 2019 +0000
Revision:
3:d8fd4efb63cc
Parent:
1:9d0e2e5b5d25
Change the usage of timer.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
masakjm 1:9d0e2e5b5d25 1 /* mbed Microcontroller Library
masakjm 1:9d0e2e5b5d25 2 * Copyright (c) 2015 ARM Limited
masakjm 1:9d0e2e5b5d25 3 *
masakjm 1:9d0e2e5b5d25 4 * Licensed under the Apache License, Version 2.0 (the "License");
masakjm 1:9d0e2e5b5d25 5 * you may not use this file except in compliance with the License.
masakjm 1:9d0e2e5b5d25 6 * You may obtain a copy of the License at
masakjm 1:9d0e2e5b5d25 7 *
masakjm 1:9d0e2e5b5d25 8 * http://www.apache.org/licenses/LICENSE-2.0
masakjm 1:9d0e2e5b5d25 9 *
masakjm 1:9d0e2e5b5d25 10 * Unless required by applicable law or agreed to in writing, software
masakjm 1:9d0e2e5b5d25 11 * distributed under the License is distributed on an "AS IS" BASIS,
masakjm 1:9d0e2e5b5d25 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
masakjm 1:9d0e2e5b5d25 13 * See the License for the specific language governing permissions and
masakjm 1:9d0e2e5b5d25 14 * limitations under the License.
masakjm 1:9d0e2e5b5d25 15 */
masakjm 1:9d0e2e5b5d25 16
masakjm 1:9d0e2e5b5d25 17 #include "mbed.h"
masakjm 1:9d0e2e5b5d25 18
masakjm 1:9d0e2e5b5d25 19 #include "HIDServiceBase.h"
masakjm 1:9d0e2e5b5d25 20
masakjm 1:9d0e2e5b5d25 21 enum ButtonState
masakjm 1:9d0e2e5b5d25 22 {
masakjm 1:9d0e2e5b5d25 23 BUTTON_UP,
masakjm 1:9d0e2e5b5d25 24 BUTTON_DOWN
masakjm 1:9d0e2e5b5d25 25 };
masakjm 1:9d0e2e5b5d25 26
masakjm 1:9d0e2e5b5d25 27 enum MouseButton
masakjm 1:9d0e2e5b5d25 28 {
masakjm 1:9d0e2e5b5d25 29 MOUSE_BUTTON_LEFT = 0x1,
masakjm 1:9d0e2e5b5d25 30 MOUSE_BUTTON_RIGHT = 0x2,
masakjm 1:9d0e2e5b5d25 31 MOUSE_BUTTON_MIDDLE = 0x4,
masakjm 1:9d0e2e5b5d25 32 };
masakjm 1:9d0e2e5b5d25 33
masakjm 1:9d0e2e5b5d25 34 /**
masakjm 1:9d0e2e5b5d25 35 * Report descriptor for a standard 3 buttons + wheel mouse with relative X/Y
masakjm 1:9d0e2e5b5d25 36 * moves
masakjm 1:9d0e2e5b5d25 37 */
masakjm 1:9d0e2e5b5d25 38 report_map_t MOUSE_REPORT_MAP = {
masakjm 1:9d0e2e5b5d25 39 USAGE_PAGE(1), 0x01, // Generic Desktop
masakjm 1:9d0e2e5b5d25 40 USAGE(1), 0x02, // Mouse
masakjm 1:9d0e2e5b5d25 41 COLLECTION(1), 0x01, // Application
masakjm 1:9d0e2e5b5d25 42 USAGE(1), 0x01, // Pointer
masakjm 1:9d0e2e5b5d25 43 COLLECTION(1), 0x00, // Physical
masakjm 1:9d0e2e5b5d25 44 USAGE_PAGE(1), 0x09, // Buttons
masakjm 1:9d0e2e5b5d25 45 USAGE_MINIMUM(1), 0x01,
masakjm 1:9d0e2e5b5d25 46 USAGE_MAXIMUM(1), 0x03,
masakjm 1:9d0e2e5b5d25 47 LOGICAL_MINIMUM(1), 0x00,
masakjm 1:9d0e2e5b5d25 48 LOGICAL_MAXIMUM(1), 0x01,
masakjm 1:9d0e2e5b5d25 49 REPORT_COUNT(1), 0x03, // 3 bits (Buttons)
masakjm 1:9d0e2e5b5d25 50 REPORT_SIZE(1), 0x01,
masakjm 1:9d0e2e5b5d25 51 INPUT(1), 0x02, // Data, Variable, Absolute
masakjm 1:9d0e2e5b5d25 52 REPORT_COUNT(1), 0x01, // 5 bits (Padding)
masakjm 1:9d0e2e5b5d25 53 REPORT_SIZE(1), 0x05,
masakjm 1:9d0e2e5b5d25 54 INPUT(1), 0x01, // Constant
masakjm 1:9d0e2e5b5d25 55 USAGE_PAGE(1), 0x01, // Generic Desktop
masakjm 1:9d0e2e5b5d25 56 USAGE(1), 0x30, // X
masakjm 1:9d0e2e5b5d25 57 USAGE(1), 0x31, // Y
masakjm 1:9d0e2e5b5d25 58 USAGE(1), 0x38, // Wheel
masakjm 1:9d0e2e5b5d25 59 LOGICAL_MINIMUM(1), 0x81, // -127
masakjm 1:9d0e2e5b5d25 60 LOGICAL_MAXIMUM(1), 0x7f, // 127
masakjm 1:9d0e2e5b5d25 61 REPORT_SIZE(1), 0x08, // Three bytes
masakjm 1:9d0e2e5b5d25 62 REPORT_COUNT(1), 0x03,
masakjm 1:9d0e2e5b5d25 63 INPUT(1), 0x06, // Data, Variable, Relative
masakjm 1:9d0e2e5b5d25 64 END_COLLECTION(0),
masakjm 1:9d0e2e5b5d25 65 END_COLLECTION(0),
masakjm 1:9d0e2e5b5d25 66 };
masakjm 1:9d0e2e5b5d25 67
masakjm 1:9d0e2e5b5d25 68 uint8_t report[] = { 0, 0, 0, 0 };
masakjm 1:9d0e2e5b5d25 69
masakjm 1:9d0e2e5b5d25 70 /**
masakjm 1:9d0e2e5b5d25 71 * @class MouseService
masakjm 1:9d0e2e5b5d25 72 * @brief HID-over-Gatt mouse service.
masakjm 1:9d0e2e5b5d25 73 *
masakjm 1:9d0e2e5b5d25 74 * Send mouse moves and button informations over BLE.
masakjm 1:9d0e2e5b5d25 75 *
masakjm 1:9d0e2e5b5d25 76 * @code
masakjm 1:9d0e2e5b5d25 77 * BLE ble;
masakjm 1:9d0e2e5b5d25 78 * MouseService mouse(ble);
masakjm 1:9d0e2e5b5d25 79 *
masakjm 1:9d0e2e5b5d25 80 * Timeout timeout;
masakjm 1:9d0e2e5b5d25 81 *
masakjm 1:9d0e2e5b5d25 82 * void stop_mouse_move(void)
masakjm 1:9d0e2e5b5d25 83 * {
masakjm 1:9d0e2e5b5d25 84 * // Set mouse state to immobile
masakjm 1:9d0e2e5b5d25 85 * mouse.setButton(MOUSE_BUTTON_LEFT, MOUSE_UP);
masakjm 1:9d0e2e5b5d25 86 * mouse.setSpeed(0, 0, 0);
masakjm 1:9d0e2e5b5d25 87 * }
masakjm 1:9d0e2e5b5d25 88 *
masakjm 1:9d0e2e5b5d25 89 * void start_mouse_move(void)
masakjm 1:9d0e2e5b5d25 90 * {
masakjm 1:9d0e2e5b5d25 91 * // Move left with a left button down. If the focus is on a drawing
masakjm 1:9d0e2e5b5d25 92 * // software, for instance, this should draw a line.
masakjm 1:9d0e2e5b5d25 93 * mouse.setButton(MOUSE_BUTTON_LEFT, MOUSE_DOWN);
masakjm 1:9d0e2e5b5d25 94 * mouse.setSpeed(1, 0, 0);
masakjm 1:9d0e2e5b5d25 95 *
masakjm 1:9d0e2e5b5d25 96 * timeout.attach(stop_mouse_move, 0.2);
masakjm 1:9d0e2e5b5d25 97 * }
masakjm 1:9d0e2e5b5d25 98 * @endcode
masakjm 1:9d0e2e5b5d25 99 */
masakjm 1:9d0e2e5b5d25 100 class MouseService: public HIDServiceBase
masakjm 1:9d0e2e5b5d25 101 {
masakjm 1:9d0e2e5b5d25 102 public:
masakjm 1:9d0e2e5b5d25 103 MouseService(BLE &_ble) :
masakjm 1:9d0e2e5b5d25 104 HIDServiceBase(_ble,
masakjm 1:9d0e2e5b5d25 105 MOUSE_REPORT_MAP, sizeof(MOUSE_REPORT_MAP),
masakjm 1:9d0e2e5b5d25 106 inputReport = report,
masakjm 1:9d0e2e5b5d25 107 outputReport = NULL,
masakjm 1:9d0e2e5b5d25 108 featureReport = NULL,
masakjm 1:9d0e2e5b5d25 109 inputReportLength = sizeof(inputReport),
masakjm 1:9d0e2e5b5d25 110 outputReportLength = 0,
masakjm 1:9d0e2e5b5d25 111 featureReportLength = 0,
masakjm 1:9d0e2e5b5d25 112 reportTickerDelay = 20),
masakjm 1:9d0e2e5b5d25 113 buttonsState (0),
masakjm 1:9d0e2e5b5d25 114 failedReports (0)
masakjm 1:9d0e2e5b5d25 115 {
masakjm 1:9d0e2e5b5d25 116 speed[0] = 0;
masakjm 1:9d0e2e5b5d25 117 speed[1] = 0;
masakjm 1:9d0e2e5b5d25 118 speed[2] = 0;
masakjm 1:9d0e2e5b5d25 119
masakjm 1:9d0e2e5b5d25 120 startReportTicker();
masakjm 1:9d0e2e5b5d25 121 }
masakjm 1:9d0e2e5b5d25 122
masakjm 1:9d0e2e5b5d25 123 void onConnection(const Gap::ConnectionCallbackParams_t *params)
masakjm 1:9d0e2e5b5d25 124 {
masakjm 1:9d0e2e5b5d25 125 HIDServiceBase::onConnection(params);
masakjm 1:9d0e2e5b5d25 126 startReportTicker();
masakjm 1:9d0e2e5b5d25 127 }
masakjm 1:9d0e2e5b5d25 128
masakjm 1:9d0e2e5b5d25 129 void onDisconnection(const Gap::DisconnectionCallbackParams_t *params)
masakjm 1:9d0e2e5b5d25 130 {
masakjm 1:9d0e2e5b5d25 131 stopReportTicker();
masakjm 1:9d0e2e5b5d25 132 HIDServiceBase::onDisconnection(params);
masakjm 1:9d0e2e5b5d25 133 }
masakjm 1:9d0e2e5b5d25 134
masakjm 1:9d0e2e5b5d25 135 /**
masakjm 1:9d0e2e5b5d25 136 * Set X, Y, Z speed of the mouse. Parameters are sticky and will be
masakjm 1:9d0e2e5b5d25 137 * transmitted on every tick. Users should therefore reset them to 0 when
masakjm 1:9d0e2e5b5d25 138 * the device is immobile.
masakjm 1:9d0e2e5b5d25 139 *
masakjm 1:9d0e2e5b5d25 140 * @param x Speed on hoizontal axis
masakjm 1:9d0e2e5b5d25 141 * @param y Speed on vertical axis
masakjm 1:9d0e2e5b5d25 142 * @param wheel Scroll speed
masakjm 1:9d0e2e5b5d25 143 *
masakjm 1:9d0e2e5b5d25 144 * @returns A status code
masakjm 1:9d0e2e5b5d25 145 *
masakjm 1:9d0e2e5b5d25 146 * @note Directions depend on the operating system's configuration. It is
masakjm 1:9d0e2e5b5d25 147 * customary to increase values on the X axis from left to right, and on the
masakjm 1:9d0e2e5b5d25 148 * Y axis from top to bottom.
masakjm 1:9d0e2e5b5d25 149 * Wheel is less standard, although positive values will usually scroll up.
masakjm 1:9d0e2e5b5d25 150 */
masakjm 1:9d0e2e5b5d25 151 int setSpeed(int8_t x, int8_t y, int8_t wheel)
masakjm 1:9d0e2e5b5d25 152 {
masakjm 1:9d0e2e5b5d25 153 speed[0] = x;
masakjm 1:9d0e2e5b5d25 154 speed[1] = y;
masakjm 1:9d0e2e5b5d25 155 speed[2] = wheel;
masakjm 1:9d0e2e5b5d25 156
masakjm 1:9d0e2e5b5d25 157 startReportTicker();
masakjm 1:9d0e2e5b5d25 158
masakjm 1:9d0e2e5b5d25 159 return 0;
masakjm 1:9d0e2e5b5d25 160 }
masakjm 1:9d0e2e5b5d25 161
masakjm 1:9d0e2e5b5d25 162 /**
masakjm 1:9d0e2e5b5d25 163 * Toggle the state of one button
masakjm 1:9d0e2e5b5d25 164 *
masakjm 1:9d0e2e5b5d25 165 * @returns A status code
masakjm 1:9d0e2e5b5d25 166 */
masakjm 1:9d0e2e5b5d25 167 int setButton(MouseButton button, ButtonState state)
masakjm 1:9d0e2e5b5d25 168 {
masakjm 1:9d0e2e5b5d25 169 if (state == BUTTON_UP)
masakjm 1:9d0e2e5b5d25 170 buttonsState &= ~(button);
masakjm 1:9d0e2e5b5d25 171 else
masakjm 1:9d0e2e5b5d25 172 buttonsState |= button;
masakjm 1:9d0e2e5b5d25 173
masakjm 1:9d0e2e5b5d25 174 startReportTicker();
masakjm 1:9d0e2e5b5d25 175
masakjm 1:9d0e2e5b5d25 176 return 0;
masakjm 1:9d0e2e5b5d25 177 }
masakjm 1:9d0e2e5b5d25 178
masakjm 1:9d0e2e5b5d25 179 /**
masakjm 1:9d0e2e5b5d25 180 * Called by the report ticker
masakjm 1:9d0e2e5b5d25 181 */
masakjm 1:9d0e2e5b5d25 182 virtual void sendCallback(void) {
masakjm 1:9d0e2e5b5d25 183 uint8_t buttons = buttonsState & 0x7;
masakjm 1:9d0e2e5b5d25 184
masakjm 1:9d0e2e5b5d25 185 if (!connected)
masakjm 1:9d0e2e5b5d25 186 return;
masakjm 1:9d0e2e5b5d25 187
masakjm 1:9d0e2e5b5d25 188 bool can_sleep = (report[0] == 0
masakjm 1:9d0e2e5b5d25 189 && report[1] == 0
masakjm 1:9d0e2e5b5d25 190 && report[2] == 0
masakjm 1:9d0e2e5b5d25 191 && report[3] == 0
masakjm 1:9d0e2e5b5d25 192 && report[0] == buttons
masakjm 1:9d0e2e5b5d25 193 && report[1] == speed[0]
masakjm 1:9d0e2e5b5d25 194 && report[2] == speed[1]
masakjm 1:9d0e2e5b5d25 195 && report[3] == speed[2]);
masakjm 1:9d0e2e5b5d25 196
masakjm 1:9d0e2e5b5d25 197 if (can_sleep) {
masakjm 1:9d0e2e5b5d25 198 /* TODO: find out why there always is two more calls to sendCallback after this
masakjm 1:9d0e2e5b5d25 199 * stopReportTicker(). */
masakjm 1:9d0e2e5b5d25 200 stopReportTicker();
masakjm 1:9d0e2e5b5d25 201 return;
masakjm 1:9d0e2e5b5d25 202 }
masakjm 1:9d0e2e5b5d25 203
masakjm 1:9d0e2e5b5d25 204 report[0] = buttons;
masakjm 1:9d0e2e5b5d25 205 report[1] = speed[0];
masakjm 1:9d0e2e5b5d25 206 report[2] = speed[1];
masakjm 1:9d0e2e5b5d25 207 report[3] = speed[2];
masakjm 1:9d0e2e5b5d25 208
masakjm 1:9d0e2e5b5d25 209 if (send(report))
masakjm 1:9d0e2e5b5d25 210 failedReports++;
masakjm 1:9d0e2e5b5d25 211 }
masakjm 1:9d0e2e5b5d25 212
masakjm 1:9d0e2e5b5d25 213 protected:
masakjm 1:9d0e2e5b5d25 214 uint8_t buttonsState;
masakjm 1:9d0e2e5b5d25 215 uint8_t speed[3];
masakjm 1:9d0e2e5b5d25 216
masakjm 1:9d0e2e5b5d25 217 public:
masakjm 1:9d0e2e5b5d25 218 uint32_t failedReports;
masakjm 1:9d0e2e5b5d25 219 };
masakjm 1:9d0e2e5b5d25 220