diff options
author | Clyne Sullivan <tullivan99@gmail.com> | 2019-02-28 17:04:22 -0500 |
---|---|---|
committer | Clyne Sullivan <tullivan99@gmail.com> | 2019-02-28 17:04:22 -0500 |
commit | d6869d1ec4bd24cd2c3eafa534f0849b25ec5607 (patch) | |
tree | 79e54ed27b39c31864895535d11399708d5a45c0 /arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm | |
parent | 614ee97bf3a2270c413527a7f35c54cbecd9e601 (diff) |
added basic code
Diffstat (limited to 'arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm')
3 files changed, 414 insertions, 0 deletions
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.cpp b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.cpp new file mode 100755 index 0000000..6b372bd --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.cpp @@ -0,0 +1,106 @@ +/**************************************************************************/ +/*! + @file IEEE11073float.h +*/ +/**************************************************************************/ + +/** + * \file bytelib.c + * \brief Byte manipulation module implementation. + * Copyright (C) 2010 Signove Tecnologia Corporation. + * All rights reserved. + * Contact: Signove Tecnologia Corporation (contact@signove.com) + * + * $LICENSE_TEXT:BEGIN$ + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation and appearing + * in the file LICENSE included in the packaging of this file; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $LICENSE_TEXT:END$ + * + * \author Walter Guerra, Mateus Lima + * \date Jun 14, 2010 + */ + +#include <Arduino.h> +#include "IEEE11073float.h" + +uint32_t float2IEEE11073(double data, uint8_t output[4]) +{ + uint32_t result = MDER_NaN; + + + if (isnan(data)) { + goto finally; + }/* else if (data > MDER_FLOAT_MAX) { + result = MDER_POSITIVE_INFINITY; + goto finally; + } else if (data < MDER_FLOAT_MIN) { + result = MDER_NEGATIVE_INFINITY; + goto finally; + } else if (data >= -MDER_FLOAT_EPSILON && + data <= MDER_FLOAT_EPSILON) { + result = 0; + goto finally; + }*/ + + double sgn; sgn = data > 0 ? +1 : -1; + double mantissa; mantissa = fabs(data); + int32_t exponent; exponent = 0; // Note: 10**x exponent, not 2**x + + // scale up if number is too big + while (mantissa > MDER_FLOAT_MANTISSA_MAX) { + mantissa /= 10.0; + ++exponent; + if (exponent > MDER_FLOAT_EXPONENT_MAX) { + // argh, should not happen + if (sgn > 0) { + result = MDER_POSITIVE_INFINITY; + } else { + result = MDER_NEGATIVE_INFINITY; + } + goto finally; + } + } + + // scale down if number is too small + while (mantissa < 1) { + mantissa *= 10; + --exponent; + if (exponent < MDER_FLOAT_EXPONENT_MIN) { + // argh, should not happen + result = 0; + goto finally; + } + } + + // scale down if number needs more precision + double smantissa; smantissa = round(mantissa * MDER_FLOAT_PRECISION); + double rmantissa; rmantissa = round(mantissa) * MDER_FLOAT_PRECISION; + double mdiff; mdiff = abs(smantissa - rmantissa); + while (mdiff > 0.5 && exponent > MDER_FLOAT_EXPONENT_MIN && + (mantissa * 10) <= MDER_FLOAT_MANTISSA_MAX) { + mantissa *= 10; + --exponent; + smantissa = round(mantissa * MDER_FLOAT_PRECISION); + rmantissa = round(mantissa) * MDER_FLOAT_PRECISION; + mdiff = abs(smantissa - rmantissa); + } + + uint32_t int_mantissa; int_mantissa = (int) round(sgn * mantissa); + result = (exponent << 24) | (int_mantissa & 0xFFFFFF); + +finally: + if ( output ) memcpy(output, &result, 4); + return result; +}
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.h b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.h new file mode 100755 index 0000000..b5dec8f --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/IEEE11073float.h @@ -0,0 +1,89 @@ +/**************************************************************************/ +/*! + @file IEEE11073float.h +*/ +/**************************************************************************/ + +/** + * \file bytelib.c + * \brief Byte manipulation module implementation. + * Copyright (C) 2010 Signove Tecnologia Corporation. + * All rights reserved. + * Contact: Signove Tecnologia Corporation (contact@signove.com) + * + * $LICENSE_TEXT:BEGIN$ + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation and appearing + * in the file LICENSE included in the packaging of this file; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * $LICENSE_TEXT:END$ + * + * \author Walter Guerra, Mateus Lima + * \date Jun 14, 2010 + */ + +#ifndef _IEEE11073FLOAT_H_ +#define _IEEE11073FLOAT_H_ + +#include <stdint.h> + +typedef enum { + MDER_POSITIVE_INFINITY = 0x007FFFFE, + MDER_NaN = 0x007FFFFF, + MDER_NRes = 0x00800000, + MDER_RESERVED_VALUE = 0x00800001, + MDER_NEGATIVE_INFINITY = 0x00800002 +} ReservedFloatValues; +static const int32_t FIRST_RESERVED_VALUE = MDER_POSITIVE_INFINITY; + +// (2 ** 23 - 3) +#define MDER_FLOAT_MANTISSA_MAX 0x007FFFFD +// 2 ** 7 - 1 +#define MDER_FLOAT_EXPONENT_MAX 127 +#define MDER_FLOAT_EXPONENT_MIN -128 +// (2 ** 23 - 3) * 10 ** 127 +#define MDER_FLOAT_MAX 8.388604999999999e+133 +// -(2 ** 23 - 3) * 10 ** 127 +#define MDER_FLOAT_MIN (-MDER_FLOAT_MAX) +// 10 ** -128 +#define MDER_FLOAT_EPSILON 1e-128 +// 10 ** upper(23 * log(2) / log(10)) +// precision for a number 1.0000xxx +#define MDER_FLOAT_PRECISION 10000000 + +typedef enum { + MDER_S_POSITIVE_INFINITY = 0x07FE, + MDER_S_NaN = 0x07FF, + MDER_S_NRes = 0x0800, + MDER_S_RESERVED_VALUE = 0x0801, + MDER_S_NEGATIVE_INFINITY = 0x0802 +} ReservedSFloatValues; +static const uint32_t FIRST_S_RESERVED_VALUE = MDER_S_POSITIVE_INFINITY; + +// (2 ** 11 - 3) +#define MDER_SFLOAT_MANTISSA_MAX 0x07FD +// 2 ** 3 - 1 +#define MDER_SFLOAT_EXPONENT_MAX 7 +#define MDER_SFLOAT_EXPONENT_MIN -8 +// (2 ** 11 - 3) * 10 ** 7 +#define MDER_SFLOAT_MAX 20450000000.0 +// -(2 ** 11 - 3) * 10 ** 7 +#define MDER_SFLOAT_MIN (-MDER_SFLOAT_MAX) +// 10 ** -8 +#define MDER_SFLOAT_EPSILON 1e-8 +// 10 ** upper(11 * log(2) / log(10)) +#define MDER_SFLOAT_PRECISION 10000 + +uint32_t float2IEEE11073(double data, uint8_t output[4]); + +#endif /* _IEEE11073FLOAT_H_ */
diff --git a/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/custom_htm.ino b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/custom_htm.ino new file mode 100755 index 0000000..ba360fc --- /dev/null +++ b/arduino/libraries/Bluefruit52Lib/examples/Peripheral/custom_htm/custom_htm.ino @@ -0,0 +1,219 @@ +/********************************************************************* + This is an example for our nRF52 based Bluefruit LE modules + + Pick one up today in the adafruit shop! + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + MIT license, check LICENSE for more information + All text above, and the splash screen below must be included in + any redistribution +*********************************************************************/ +#include <bluefruit.h> +#include "IEEE11073float.h" + +/* Health Thermometer Service Definitions + * Health Thermometer Service: 0x1809 + * Temperature Measurement Char: 0x2A1C + */ +BLEService htms = BLEService(UUID16_SVC_HEALTH_THERMOMETER); +BLECharacteristic htmc = BLECharacteristic(UUID16_CHR_TEMPERATURE_MEASUREMENT); + +BLEDis bledis; // DIS (Device Information Service) helper class instance + +double tempvalue = 0; + +// Advanced function prototypes +void startAdv(void); +void setupHTM(void); +void connect_callback(uint16_t conn_handle); +void disconnect_callback(uint16_t conn_handle, uint8_t reason); + +void setup() +{ + Serial.begin(115200); + while ( !Serial ) delay(10); // for nrf52840 with native usb + + Serial.println("Bluefruit52 Heath Thermometer Example"); + Serial.println("-------------------------------------\n"); + + // Initialise the Bluefruit module + Serial.println("Initialise the Bluefruit nRF52 module"); + Bluefruit.begin(); + Bluefruit.setName("Bluefruit52"); + + // Set the connect/disconnect callback handlers + Bluefruit.setConnectCallback(connect_callback); + Bluefruit.setDisconnectCallback(disconnect_callback); + + // Configure and Start the Device Information Service + Serial.println("Configuring the Device Information Service"); + bledis.setManufacturer("Adafruit Industries"); + bledis.setModel("Bluefruit Feather52"); + bledis.begin();; + + // Setup the Heath Thermometer service using + // BLEService and BLECharacteristic classes + Serial.println("Configuring the Heath Thermometer Service"); + setupHTM(); + + // Setup the advertising packet(s) + Serial.println("Setting up the advertising payload(s)"); + startAdv(); + + Serial.println("Ready Player One!!!"); + Serial.println("\nAdvertising"); +} + +void startAdv(void) +{ + // Advertising packet + Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); + Bluefruit.Advertising.addTxPower(); + + // Include HTM Service UUID + Bluefruit.Advertising.addService(htms); + + // Include Name + Bluefruit.Advertising.addName(); + + /* Start Advertising + * - Enable auto advertising if disconnected + * - Interval: fast mode = 20 ms, slow mode = 152.5 ms + * - Timeout for fast mode is 30 seconds + * - Start(timeout) with timeout = 0 will advertise forever (until connected) + * + * For recommended advertising interval + * https://developer.apple.com/library/content/qa/qa1931/_index.html + */ + Bluefruit.Advertising.restartOnDisconnect(true); + Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms + Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode + Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds +} + +void setupHTM(void) +{ + // Configure the Health Thermometer service + // See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.service.health_thermometer.xml + // Supported Characteristics: + // Name UUID Requirement Properties + // ---------------------------- ------ ----------- ---------- + // Temperature Measurement 0x2A1C Mandatory Indicate + // + // Temperature Type 0x2A1D Optional Read <-- Not used here + // Intermediate Temperature 0x2A1E Optional Read, Notify <-- Not used here + // Measurement Interval 0x2A21 Optional Read, Write, Indicate <-- Not used here + htms.begin(); + + // Note: You must call .begin() on the BLEService before calling .begin() on + // any characteristic(s) within that service definition.. Calling .begin() on + // a BLECharacteristic will cause it to be added to the last BLEService that + // was 'begin()'ed! + + // Configure the Temperature Measurement characteristic + // See:https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.temperature_measurement.xml + // Properties = Indicte + // Min Len = 6 + // Max Len = 6 + // B0 = UINT8 - Flag (MANDATORY) + // b3:7 = Reserved + // b2 = Temperature Type Flag (0 = Not present, 1 = Present) + // b1 = Timestamp Flag (0 = Not present, 1 = Present) + // b0 = Unit Flag (0 = Celsius, 1 = Fahrenheit) + // B4:1 = FLOAT - IEEE-11073 32-bit FLOAT measurement value + // B5 = Temperature Type + htmc.setProperties(CHR_PROPS_INDICATE); + htmc.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS); + htmc.setFixedLen(6); + htmc.setCccdWriteCallback(cccd_callback); // Optionally capture CCCD updates + htmc.begin(); + uint8_t htmdata[6] = { 0b00000101, 0, 0 ,0 ,0, 2 }; // Set the characteristic to use Fahrenheit, with type (body) but no timestamp field + htmc.write(htmdata, sizeof(htmdata)); // Use .write for init data + + // Temperature Type Value + // See: https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.temperature_type.xml + // B0 = UINT8 - Temperature Type + // 0 = Reserved + // 1 = Armpit + // 2 = Body (general) + // 3 = Ear (usually ear lobe) + // 4 = Finger + // 5 = Gastro-intestinal Tract + // 6 = Mouth + // 7 = Rectum + // 8 = Toe + // 9 = Tympanum (ear drum) + // 10:255 = Reserved +} + +void connect_callback(uint16_t conn_handle) +{ + char central_name[32] = { 0 }; + Bluefruit.Gap.getPeerName(conn_handle, central_name, sizeof(central_name)); + + Serial.print("Connected to "); + Serial.println(central_name); +} + +/** + * Callback invoked when a connection is dropped + * @param conn_handle connection where this event happens + * @param reason is a BLE_HCI_STATUS_CODE which can be found in ble_hci.h + * https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/nordic/softdevice/s140_nrf52_6.1.1_API/include/ble_hci.h + */ +void disconnect_callback(uint16_t conn_handle, uint8_t reason) +{ + (void) conn_handle; + (void) reason; + + Serial.println("Disconnected"); + Serial.println("Advertising!"); +} + +void cccd_callback(BLECharacteristic& chr, uint16_t cccd_value) +{ + // Display the raw request packet + Serial.print("CCCD Updated: "); + //Serial.printBuffer(request->data, request->len); + Serial.print(cccd_value); + Serial.println(""); + + // Check the characteristic this CCCD update is associated with in case + // this handler is used for multiple CCCD records. + if (chr.uuid == htmc.uuid) { + if (chr.indicateEnabled()) { + Serial.println("Temperature Measurement 'Indicate' enabled"); + } else { + Serial.println("Temperature Measurement 'Indicate' disabled"); + } + } +} + +void loop() +{ + digitalToggle(LED_RED); + + if ( Bluefruit.connected() ) { + uint8_t htmdata[6] = { 0b00000101, 0,0,0,0, 2 }; // Fahrenheit unit, temperature type = body (2) + + float2IEEE11073(tempvalue, &htmdata[1]); + + // Note: We use .indicate instead of .write! + // If it is connected but CCCD is not enabled + // The characteristic's value is still updated although notification is not sent + if ( htmc.indicate(htmdata, sizeof(htmdata)) ){ + Serial.print("Temperature Measurement updated to: "); Serial.println(tempvalue); + }else{ + Serial.println("ERROR: Indicate not set in the CCCD or not connected!"); + } + + tempvalue += 0.5F; + } + + // Only send update once per second + delay(1000); +} + |