|
| 1 | +/********************************************************************* |
| 2 | + This is an example for our nRF52 based Bluefruit LE modules |
| 3 | + Pick one up today in the adafruit shop! |
| 4 | + Adafruit invests time and resources providing this open source code, |
| 5 | + please support Adafruit and open-source hardware by purchasing |
| 6 | + products from Adafruit! |
| 7 | + MIT license, check LICENSE for more information |
| 8 | + All text above, and the splash screen below must be included in |
| 9 | + any redistribution |
| 10 | +*********************************************************************/ |
| 11 | + |
| 12 | +/* This sketch demonstrates the Bluefruit.Advertising API(). When powered up, |
| 13 | + * the Bluefruit module will start advertising a packet compatible with the |
| 14 | + * AdafruitColor class from CircuitPython: |
| 15 | + * https://github.com/adafruit/Adafruit_CircuitPython_BLE/blob/master/adafruit_ble/advertising/adafruit.py |
| 16 | + * In other words, `ble.start_scan(AdafruitColor)` in CircuitPython will hear |
| 17 | + * an advertisement containing the color 0x0F0033 (violet) from this device. |
| 18 | + */ |
| 19 | + |
| 20 | +#include <bluefruit.h> |
| 21 | + |
| 22 | +#define ADV_TIMEOUT 0 // seconds. Set this higher to automatically stop advertising after a time |
| 23 | + |
| 24 | +// The following code is for setting a name based on the actual device MAC address |
| 25 | +// Where to go looking in memory for the MAC |
| 26 | +typedef volatile uint32_t REG32; |
| 27 | +#define pREG32 (REG32 *) |
| 28 | +#define MAC_ADDRESS_HIGH (*(pREG32 (0x100000a8))) |
| 29 | +#define MAC_ADDRESS_LOW (*(pREG32 (0x100000a4))) |
| 30 | + |
| 31 | +void byte_to_str(char* buff, uint8_t val) { // convert an 8-bit byte to a string of 2 hexadecimal characters |
| 32 | + buff[0] = nibble_to_hex(val >> 4); |
| 33 | + buff[1] = nibble_to_hex(val); |
| 34 | +} |
| 35 | + |
| 36 | +char nibble_to_hex(uint8_t nibble) { // convert a 4-bit nibble to a hexadecimal character |
| 37 | + nibble &= 0xF; |
| 38 | + return nibble > 9 ? nibble - 10 + 'A' : nibble + '0'; |
| 39 | +} |
| 40 | + |
| 41 | +void setup() |
| 42 | +{ |
| 43 | + Serial.begin(115200); |
| 44 | + while ( !Serial ) delay(10); // for nrf52840 with native usb |
| 45 | + |
| 46 | + Serial.println("Bluefruit52 Color Advertising Example"); |
| 47 | + Serial.println("----------------------------------------\n"); |
| 48 | + |
| 49 | + Bluefruit.begin(); |
| 50 | + Bluefruit.setTxPower(4); // Check bluefruit.h for supported values |
| 51 | + |
| 52 | + char ble_name[14] = "BluefruitXXXX"; // Null-terminated string must be 1 longer than you set it, for the null |
| 53 | + |
| 54 | + // Replace the XXXX with the lowest two bytes of the MAC Address |
| 55 | + // The commented lines show you how to get the WHOLE MAC address |
| 56 | +// uint32_t addr_high = ((MAC_ADDRESS_HIGH) & 0x0000ffff) | 0x0000c000; |
| 57 | + uint32_t addr_low = MAC_ADDRESS_LOW; |
| 58 | +// Serial.print("MAC Address: "); |
| 59 | +// Serial.print((addr_high >> 8) & 0xFF, HEX); Serial.print(":"); |
| 60 | +// Serial.print((addr_high) & 0xFF, HEX); Serial.print(":"); |
| 61 | +// Serial.print((addr_low >> 24) & 0xFF, HEX); Serial.print(":"); |
| 62 | +// Serial.print((addr_low >> 16) & 0xFF, HEX); Serial.print(":"); |
| 63 | +// Serial.print((addr_low >> 8) & 0xFF, HEX); Serial.print(":"); |
| 64 | +// Serial.print((addr_low) & 0xFF, HEX); Serial.println(""); |
| 65 | + |
| 66 | + // Fill in the XXXX in ble_name |
| 67 | + byte_to_str(&ble_name[9], (addr_low >> 8) & 0xFF); |
| 68 | + byte_to_str(&ble_name[11], addr_low & 0xFF); |
| 69 | + // Set the name we just made |
| 70 | + Bluefruit.setName(ble_name); |
| 71 | + |
| 72 | + // start advertising |
| 73 | + startAdv(); |
| 74 | + Serial.print("Advertising is started: "); |
| 75 | + Serial.println(ble_name); |
| 76 | +} |
| 77 | + |
| 78 | +void startAdv(void) |
| 79 | +{ |
| 80 | + // Advertising packet |
| 81 | + Bluefruit.Advertising.clearData(); |
| 82 | + Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); |
| 83 | + Bluefruit.Advertising.setType(BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED); |
| 84 | + |
| 85 | + // This is the data format that will match CircuitPython's AdafruitColor |
| 86 | + struct ATTR_PACKED |
| 87 | + { |
| 88 | + uint16_t manufacturer; |
| 89 | + uint8_t color_len; |
| 90 | + uint16_t color_type; |
| 91 | + uint8_t color_info[4]; |
| 92 | + } color_data = |
| 93 | + { |
| 94 | + .manufacturer = 0x0822, // Adafruit company ID |
| 95 | + .color_len = sizeof(color_data) - 3, // length of data to follow |
| 96 | + .color_type = 0x0000, // Type specifier of this field, which AdafruitColor defines as 0x0000 |
| 97 | + .color_info = { 0x33, 0x00, 0x0F, 0x00 }, // { 0xBB, 0xGG, 0xRR, 0xIgnore} |
| 98 | + }; |
| 99 | + // BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA is 0xFF |
| 100 | + Bluefruit.Advertising.addData(BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA, &color_data, sizeof(color_data)); |
| 101 | + |
| 102 | + // Tell the BLE device we want to send our name in a ScanResponse if asked. |
| 103 | + Bluefruit.ScanResponse.addName(); |
| 104 | + |
| 105 | + /* Start Advertising |
| 106 | + * - Enable auto advertising if disconnected |
| 107 | + * - Interval: fast mode = 20 ms, slow mode = 152.5 ms |
| 108 | + * - Timeout for fast mode is 30 seconds |
| 109 | + * - Start(timeout) with timeout = 0 will advertise forever (until connected) |
| 110 | + * |
| 111 | + * For recommended advertising interval |
| 112 | + * https://developer.apple.com/library/content/qa/qa1931/_index.html |
| 113 | + */ |
| 114 | + Bluefruit.Advertising.setStopCallback(adv_stop_callback); |
| 115 | + Bluefruit.Advertising.restartOnDisconnect(true); |
| 116 | + Bluefruit.Advertising.setInterval(32, 244); // in units of 0.625 ms |
| 117 | + Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode |
| 118 | + Bluefruit.Advertising.start(ADV_TIMEOUT); // Stop advertising entirely after ADV_TIMEOUT seconds |
| 119 | +} |
| 120 | + |
| 121 | +void loop() |
| 122 | +{ |
| 123 | + |
| 124 | +} |
| 125 | + |
| 126 | +/** |
| 127 | + * Callback invoked when advertising is stopped by timeout |
| 128 | + */ |
| 129 | +void adv_stop_callback(void) |
| 130 | +{ |
| 131 | + Serial.println("Advertising time passed, advertising will now stop."); |
| 132 | +} |
0 commit comments