BLE switch interface with GROVE joystic for micro:bit http://mahoro-ba.net/e2073.html

Dependencies:   microbit

Committer:
masakjm
Date:
Tue Apr 09 19:37:57 2019 +0000
Revision:
21:961da341b755
Parent:
0:28fb3e9ef81a
Added setting function of installation direction.

Who changed what in which revision?

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