Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API X_NUCLEO_IDB0XA1 mbed
Fork of BLE_HeartRate_IDB0XA1 by
Revision 29:a6b74dfdd5f2, committed 2017-10-01
- Comitter:
- hux
- Date:
- Sun Oct 01 12:49:25 2017 +0000
- Parent:
- 28:307f58df778a
- Commit message:
- A blue button is always a nice toy ...
Changed in this revision
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/advertise.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/advertise.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,114 @@
+// advertise.h - begin peripheral role and start advertising
+//
+// Synopsis:
+//
+// advertise(O&o);
+// advertise(O&o, const char *mode, int ms = 100);
+//
+// payload(O&o,const char *mode) // set advertising payload
+//
+// Arguments:
+//
+// o: Blob object (to avoid name clashes)
+// mode: String containing a sequence of mode characters defining both
+// advertising type (upper case characters) and advertising flags
+// (lower case characters), some of which have meaning, all others
+// are ignored and can be used for spacing (e.g. ':', ' ', '-', ...)
+// ms: Advertising interval in mili seconds (default 100 ms)
+//
+// Advertising Type
+//
+// C: ADV_CONNECTABLE_UNDIRECTED
+// D: ADV_CONNECTABLE_DIRECTED
+// S: ADV_SCANNABLE_UNDIRECTED
+// N: ADV_NON_CONNECTABLE_UNDIRECTED
+//
+// Advertising Flags:
+//
+// l: LE Limited Discoverable Mode (value: 0x01)
+// g: LE General Discoverable Mode (value: 0x02)
+// n: BR/EDR Not Supported (value: 0x04)
+// c: Controller: simultaneous LE & BR/EDR (value: 0x08)
+// h: Host: Simultaneous LE & BR/EDR (value: 0x10)
+//
+// Examples 1: Start advertising in peripheral role with type 'connectable, uni-
+// directed, and flags 'BR/EDR Not Supported', 'LE General Discoverable Mode'
+//
+// advertise(o,"C:ng",100); // start advertising @ 100 msec interval
+// advertise(o,"Cng",100); // same as above
+// advertise(o,"gCn",100); // same as above
+//
+// Examples 2: Start advertising in peripheral role with type 'connectable,
+// directed, and flags 'LE Limited Discoverable Mode'
+//
+// advertise("D:l",100) // Connectable Directed, limited discoverable
+//
+// Examples 3: A typical peripheral advertising session starts with setup of
+// device name, advertising name and advertising data.
+//
+// device(o,"Smart Button"); // setup device name
+// name(o,"Smart Button #1"); // setup advertising name
+// data(o,"My Home"); // setup advertising data
+// advertise(o,"C:ng",100); // start advertising @ 100 msec interval
+//
+// Example 4: restart advertising based on pre-defined advertising payload
+//
+//
+// See also: SERVICE
+//
+#ifndef _ADVERTISE_H_
+#define _ADVERTISE_H_
+
+#include "bricks/blob.h"
+#include "bricks/trace.h"
+
+#define _GADAT GapAdvertisingData
+#define _GAPAR GapAdvertisingParams
+
+
+ inline void payload(O&o,const char *p) // Set advertising type and flags
+ {
+ _GAPAR::AdvertisingType_t typ = _GAPAR::ADV_CONNECTABLE_UNDIRECTED;
+ uint8_t mask = 0x00;
+
+ for (;*p; p++)
+ {
+ switch (*p)
+ {
+ case 'l': mask = mask | _GADAT::LE_LIMITED_DISCOVERABLE; break;
+ case 'g': mask = mask | _GADAT::LE_GENERAL_DISCOVERABLE; break;
+ case 'n': mask = mask | _GADAT::BREDR_NOT_SUPPORTED; break;
+ case 'c': mask = mask | _GADAT::SIMULTANEOUS_LE_BREDR_C; break;
+ case 'h': mask = mask | _GADAT::SIMULTANEOUS_LE_BREDR_H; break;
+
+ case 'C': typ = _GAPAR::ADV_CONNECTABLE_UNDIRECTED; break;
+ case 'D': typ = _GAPAR::ADV_CONNECTABLE_DIRECTED; break;
+ case 'S': typ = _GAPAR::ADV_SCANNABLE_UNDIRECTED; break;
+ case 'N': typ = _GAPAR::ADV_NON_CONNECTABLE_UNDIRECTED; break;
+ }
+ }
+
+ o.gap().setAdvertisingType(typ);
+ o.gap().accumulateAdvertisingPayload(mask);
+ }
+
+
+ inline void advertise(O&o) // start advertising
+ {
+ o.gap().startAdvertising(); // start advertising
+ trace(o,2,"<advertising>\n");
+ }
+
+ inline void advertise(O&o, int ms) // start advertising (msec: periode)
+ {
+ o.gap().setAdvertisingInterval(ms);
+ advertise(o); // start advertising
+ }
+
+ inline void advertise(Blob &o, const char *mode, int ms = 100)
+ {
+ payload(o,mode); // set advertising payload type & mask
+ advertise(o,ms); // start advertising
+ }
+
+#endif // _ADVERTISE_H_
\ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/callback.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/callback.cpp Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,83 @@
+// callback.cpp - deal with callbacks
+
+#include "bricks/blob.h"
+#include "bricks/callback.h"
+#include "bricks/trace.h"
+
+//==============================================================================
+// Setup Data Written Callback
+//==============================================================================
+
+ static void (*cbWritten)(O&o) = 0; // where we have to follow up
+
+ // default onDataWritten callback
+
+ static void dfWritten(const GattWriteCallbackParams *params)
+ {
+ O o; // setup a blob
+ o.pWritten = params; // store to provide access
+
+ trace(o,2,"<data written>\n");
+
+ if (cbWritten)
+ (*cbWritten)(o); // user callback follow-up
+ }
+
+
+ void onWritten(O&o, void (*fptr)(O&o)) // setup data written callback
+ {
+ cbWritten = fptr; // remember function to follow-up
+ o.gattServer().onDataWritten(dfWritten);// actual calback setup in GATT
+ }
+
+//==============================================================================
+// Setup Connection Callback
+//==============================================================================
+
+ static void (*cbConnect)(Blob&) = 0;// where we have to follow up
+
+ // default connection callback
+
+ static void dfConnect(const Gap::ConnectionCallbackParams_t *params)
+ {
+ O o; // setup a blob object
+ o.pConnect = params; // store to provide access
+
+ trace(o,2,"<connect>\n");
+
+ if (cbConnect)
+ (*cbConnect)(o); // user callback follow-up
+ }
+
+ void onConnect(O&o,void(*fptr)(O&)) // setup connection callback
+ {
+ cbConnect = fptr; // remember function to follow-up
+ o.gap().onConnection(dfConnect); // actual callback setup in GAP
+ }
+
+//==============================================================================
+// Setup Disconnection Callback
+//==============================================================================
+
+ static void (*cbDisconnect)(O&o) = 0; // where we have to follow up
+
+ // default disconnection callback
+
+ static void dfDisconnect(const Gap::DisconnectionCallbackParams_t *params)
+ {
+ Blob o; // setup a blob
+ o.pDisconnect = params; // store to provide access
+
+ trace(o,2,"<disconnected>\n");
+
+ if (cbDisconnect)
+ (*cbDisconnect)(o); // user callback follow-up
+ }
+
+ void onDisconnect(O&o,void(*fptr)(O&o)) // setup disconnection callback
+ {
+ cbDisconnect = fptr; // remember function to follow-up
+
+ o.gap().onDisconnection(dfDisconnect);// actualcallback setup in GAP
+ }
+
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/callback.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/callback.h Sun Oct 01 12:49:25 2017 +0000 @@ -0,0 +1,13 @@ +// callback.h - deal with callbacks +// +// +#ifndef _CALLBACK_H_ +#define _CALLBACK_H_ + +#include "bricks/o.h" + + void onConnect (O&o, void(*fptr)(O&o)); // setup connection callback + void onDisconnect(O&o, void(*fptr)(O&o)); // setup disconnect callback + void onWritten (O&o, void (*fptr)(O&)); // setup data written callback + +#endif // _CALLBACK_H_ \ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/characteristic.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/characteristic.cpp Sun Oct 01 12:49:25 2017 +0000 @@ -0,0 +1,7 @@ +// characteristic.cpp - an easy to use overloaded characteristic class + +#include "bricks/characteristic.h" + + IniBuffer characteristicInidata; // to initialize a characteristic + +// eof \ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/characteristic.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/characteristic.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,247 @@
+// characteristic.h - an easy to use overloaded characteristic class
+//
+// Synopsis:
+//
+// Characteristic<type> myCharacteristic(col,uuid,mode);
+// Characteristic<type> myCharacteristic(col,uuid,mode,name);
+// Characteristic<type> myCharacteristic(col,uuid,mode,name,inidata);
+// Characteristic<type> myCharacteristic(col,uuid,mode,inidata);
+//
+// Declaration of a characteristic, specifying value type, UUID and access mode,
+// optionally providing a name (user descriptor) and initial data.
+//
+// col: Collection, to which the constructed characteristic is automati-
+// cally added. After construction and adding all characteristics to
+// a collection this collection is passed to a service constructor,
+// which gets thus knowledge about all characteristics which have to
+// be involved in the service
+//
+// uuid: A unique universal ID which identifies the characteristic
+//
+// mode: A string comprising zero or more mode characters which
+// define possible properties of the characteristic.
+//
+// "" no properties
+// "b" broadcast
+// "r" read access
+// "s" send & pray (write without response)
+// "w" write access (with feedback)
+// "n" notification (no client confirmation)
+// "i" indication (with client confirmation)
+// "a" authentication signed write
+// "x" extended access
+//
+// name: An optional name provided in terms of a user descriptor. If this
+// argument is omitted the user descriptor is not created.
+//
+// inidata: A pointer to a variable containing initializing data for the
+// characteristic. If the inidata argument is not provided, an
+// implicit initialization is performed which clears the characte-
+// ristic (all bytes set to 0). As a concluding remark it needs to
+// be noted that the implicite initialozation works only for
+// sizeof(Type) <= SIZE_INIBUFFER (defined in "bricks/types.h")
+//
+//
+// Example 1: A protocol might be declared as a class as follows
+//
+// Collection col; // collection used during setup
+//
+// Characteristic<ObjectId> id(col,0x2AC3,"rw","ID");
+// Characteristic<ObjectName> name(col,0x2ABE,"rw","Name");
+// Characteristic<Digital> presence(col,0x2A56,"r","Presence");
+//
+// Service presenceDetection(col,0xA001); // instantiate service
+//
+// onSetup(Blob &blue)
+// {
+// blue.service(presenceDetection); // add service
+// }
+//
+// Example 2: service definition by means of a service definition class
+//
+// class PresenceDetector
+// {
+// public:
+// Collection col; // collection used during setup
+//
+// Characteristic<ObjectId> id; // ID of presence detector
+// Characteristic<ObjectName> name; // name of presence detector
+// Characteristic<Digital> presence; // digital presence value
+// Characteristic<DateTime> timestamp; // last detection change's time
+// Characteristic<ObjectName> layout; // name of model railway layout
+//
+// Service presenceDetection; // the service
+//
+// public:
+// PresenceDetector(Blob &blue, cost UUID uuid) :
+// list; // init service list
+// id(list,0x2AC3,"rw","ID"), // instantiate characteristic
+// name(list,0x2ABE,"rw","Name"), // instantiate characteristic
+// presence(list,0x2A56,"r","Presence"),// instantiate characteristic
+// timestamp(list,0x2A08,"r","Timestamp"),// instantiate characteristic
+// layout(list,0x2ABE,"rw","Layout"), // instantiate characteristic
+// presenceDetection(list,uuid) // instantiate service
+// {
+// blue.service(presenceDetection); // add service
+// }
+// };
+//
+#ifndef _CHARACTERISTIC_H_
+#define _CHARACTERISTIC_H_
+
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "bricks/types.h"
+#include "bricks/collection.h"
+#include "bricks/descriptor.h"
+
+ // the following #define is helpful if characteristics are defined on base
+ // of the BLE API (the tedious way)
+
+#define UserDescriptor(name,attribute,descriptor,text) \
+ static char *name = text; \
+ static GattAttribute attribute(0x2901,(uint8_t*)name,strlen(name),strlen(name)); \
+ static GattAttribute *descriptor[] = {&attribute};
+
+ // the declaration of Characteristics needs the availability of an
+ // initializing buffer in the default case
+
+ extern IniBuffer characteristicInidata; // to initialize a characteristic
+
+ // class definition of a characteristic initializer
+
+ class CharacteristicInitializer // provides pointers to initialized data
+ {
+ private:
+ IniBuffer inibuf; // initialized data
+
+ public:
+ ObjectId *pObjectId() { return (ObjectId*) &inibuf; }
+ ObjectName *pObjectName() { return (ObjectName*) &inibuf; }
+ Bool *pBool() { return (Bool*) &inibuf; }
+ Digital *pDigital() { return (Digital*) &inibuf; }
+ DateTime *pDateTime() { return (DateTime*) &inibuf; }
+ Buffer *pBuffer() { return (Buffer*) &inibuf; }
+
+ public:
+ CharacteristicInitializer() // constructor
+ {
+ memset(inibuf,0,sizeof(IniBuffer));
+
+ // besides of the local inibuf also initialize the global
+ // init buffer characteristicInidata;
+
+ memset(characteristicInidata,0,sizeof(IniBuffer));
+ }
+ };
+
+ // definition of class Characteristic
+
+ class Service;
+
+ template <typename Type>
+ class Characteristic : public GattCharacteristic
+ {
+ private:
+ void init() // initialize inibuffer
+ {
+ static int initialized = 0;
+
+ if (!initialized) // clear init data buffer
+ { initialized = 1;
+ memset(characteristicInidata,0,sizeof(IniBuffer));
+ }
+ }
+
+ private:
+ UserDescriptor descriptor; // characteristic's user descriptor
+
+ uint8_t getmask(const char *pmask)
+ {
+ uint8_t mask = 0;
+
+ for(;*pmask;pmask++)
+ { switch (*pmask)
+ {
+ case 'b': // broad cast
+ mask = mask | BLE_GATT_CHAR_PROPERTIES_BROADCAST;
+ break;
+ case 'r': // read
+ mask = mask | BLE_GATT_CHAR_PROPERTIES_READ;
+ break;
+ case 's': // send (& pray)
+ mask = mask | BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE;
+ break;
+ case 'w': // write
+ mask = mask | BLE_GATT_CHAR_PROPERTIES_WRITE;
+ break;
+ case 'n': // notify
+ mask = mask | BLE_GATT_CHAR_PROPERTIES_NOTIFY;
+ break;
+ case 'i': // indicate
+ mask = mask | BLE_GATT_CHAR_PROPERTIES_INDICATE;
+ break;
+ case 'a': // authenticated signed write
+ mask = mask | BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES;
+ break;
+ case 'x': // extended properties
+ mask = mask | BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES;
+ break;
+ }
+ }
+ return mask;
+ }
+/*
+ public:
+ Characteristic<Type> (Service &service, UUID uuid, const char *mode,
+ Type *valuePtr = (Type*)&characteristicInidata) :
+ GattCharacteristic(uuid,
+ reinterpret_cast<uint8_t*> (valuePtr),
+ sizeof(Type),
+ sizeof(Type),
+ getmask(mode),
+ NULL, // descriptor list
+ 0, // number of descriptors
+ false),
+ descriptor("") // construct descriptor
+ {
+ init(); // assure initializing
+
+ // there is a potential danger that we use implicite initializing
+ // with sizeof(Type) > sizeof(inibuffer). This must be prevented!
+
+ int feasible = (sizeof(Type) <= sizeof(IniBuffer));
+ if (feasible || valuePtr != (Type*)&characteristicInidata)
+ {
+ service.add(this); // add to service
+ } // otherwise just ignore!
+ }
+*/
+ public:
+ Characteristic<Type> (Service &service, UUID uuid, const char *mode,
+ const char *name, Type *valuePtr = (Type*)&characteristicInidata) :
+ GattCharacteristic(uuid,
+ reinterpret_cast<uint8_t*> (valuePtr),
+ sizeof(Type),
+ sizeof(Type),
+ getmask(mode),
+ descriptor.plist, // descriptor list
+ 1, // number of descriptors
+ false),
+ descriptor(name) // construct descriptor
+ {
+ init(); // assure initializing
+
+ // there is a potential danger that we use implicite initializing
+ // with sizeof(Type) > sizeof(inibuffer). This must be prevented!
+
+ int feasible = (sizeof(Type) <= sizeof(IniBuffer));
+ if (feasible || valuePtr != (Type*)&characteristicInidata)
+ {
+ service.add(this); // add to service
+ } // otherwise just ignore!
+ }
+ };
+
+
+#endif // _CHARACTERISTIC_H_
\ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/collection.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/collection.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,93 @@
+// collection.h - used to setup a collection of characteristics in order to
+// setup a service.
+//
+// Description:
+// Collections are used to setup a service comprising a collection of
+// characteristics. The setup sequence starts with declaring a collection
+// (this constructs an empty collection) while passing the collection in-
+// stance repeatedly to a constructor of a characteristic, which auto-adds
+// the new constructed characteristics to the collection. Finally, when the
+// collection instance is passed to a service constructor, the service con-
+// structor is able to access all characteristics which have been collected
+// previously.
+//
+// Example 1: A protocol might be declared as a class as follows
+//
+// Collection col; // collection used during setup
+//
+// Characteristic<ObjectId> id(col,0x2AC3,"rw","ID");
+// Characteristic<ObjectName> name(col,0x2ABE,"rw","Name");
+// Characteristic<Digital> presence(col,0x2A56,"r","Presence");
+//
+// Service presenceDetection(col,0xA001); // instantiate service
+//
+// onSetup(Blob &blue)
+// {
+// blue.service(presenceDetection); // add service
+// }
+//
+// Example 2: service definition by means of a service definition class
+//
+// class PresenceDetector
+// {
+// public:
+// Collection col; // collection used during setup
+//
+// Characteristic<ObjectId> id; // ID of presence detector
+// Characteristic<ObjectName> name; // name of presence detector
+// Characteristic<Digital> presence; // digital presence value
+// Characteristic<DateTime> timestamp; // last detection change's time
+// Characteristic<ObjectName> layout; // name of model railway layout
+//
+// Service presenceDetection; // the service
+//
+// public:
+// PresenceDetector(Blob &blue, cost UUID uuid) :
+// list; // init service list
+// id(list,0x2AC3,"rw","ID"), // instantiate characteristic
+// name(list,0x2ABE,"rw","Name"), // instantiate characteristic
+// presence(list,0x2A56,"r","Presence"),// instantiate characteristic
+// timestamp(list,0x2A08,"r","Timestamp"),// instantiate characteristic
+// layout(list,0x2ABE,"rw","Layout"), // instantiate characteristic
+// presenceDetection(list,uuid) // instantiate service
+// {
+// blue.service(presenceDetection); // add service
+// }
+// };
+//
+#ifndef _COLLECTION_H_
+#define _COLLECTION_H_
+
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+
+ class Collection
+ {
+ private:
+ typedef GattCharacteristic *GattCharPtr;
+
+ public:
+ GattCharacteristic **plist;
+ int count;
+
+ Collection() // construct empty collection
+ {
+ plist = 0; count = 0; // init properties
+ }
+
+ void add(GattCharPtr p)
+ {
+ GattCharPtr *pnew = new GattCharPtr[count+1];
+ pnew[count] = p; // add new characteristic
+
+ if (count > 0)
+ { for (int i=0; i < count; i++)
+ pnew[i] = plist[i];
+ delete plist;
+ }
+ plist = pnew; // update list pointer
+ count++;
+ }
+ };
+
+#endif // _COLLECTION_H_
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/get.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/get.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,52 @@
+// get.h - get data from a characteristics
+//
+// Synopsis:
+//
+// Get data from a 'characteristic' into a 'data' variable
+//
+// get(characteristic,data)
+//
+// The 'get' function (overloaded function family) is implemented for all
+// types defined in "bricks/types.h".
+//
+// See also: CHARACTERISTIC, SET
+//
+#ifndef _GET_H_
+#define _GET_H_
+
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "ble/GattClient.h"
+#include "bricks/o.h"
+#include "bricks/types.h"
+#include "bricks/characteristic.h"
+
+ inline void get(O&o, Characteristic<Bool> &chr, Bool &data)
+ {
+ uint16_t size = sizeof(Bool)/sizeof(uint8_t);
+ o.gattServer().read(chr.getValueHandle(), (uint8_t*)&data,&size);
+ }
+
+ inline void get(O&o, Characteristic<ObjectId> &chr, ObjectId &data)
+ {
+ uint16_t size = sizeof(ObjectId)/sizeof(uint8_t);
+ o.gattServer().read(chr.getValueHandle(), (uint8_t*)&data,&size);
+ }
+
+ inline void get(O&o, Characteristic<Buffer> &chr, Buffer &data)
+ {
+ uint16_t size = sizeof(Buffer)/sizeof(uint8_t);
+ o.gattServer().read(chr.getValueHandle(), (uint8_t*)&data,&size);
+ }
+
+// we provide also some GET methods for GattCharacteristics. However the use
+// of these methods are more dangerous, because a GattCharacteristics can be
+// of any type and the compiler cannot help us to check !!!
+
+ inline void get(O&o,GattCharacteristic &chr, Bool &data)
+ {
+ uint16_t size = sizeof(Bool)/sizeof(uint8_t);
+ o.gattServer().read(chr.getValueHandle(), (uint8_t*)&data, &size);
+ }
+
+#endif // _GET_H_
\ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/init.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/init.cpp Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,71 @@
+// init.cpp - initialize BLE system
+
+#include "bricks/init.h"
+#include "bricks/blinker.h"
+#include "bricks/trace.h"
+
+ static void (*cbSetup)(O&o) = 0; // setup callback
+ static void (*cbError)(O&o) = 0; // error callback
+
+ static void cbDefaultError(O&o) // default error handler
+ {
+ Blinker blink;
+ blink.error(); // 'error' blink sequence
+ }
+
+ static void cbDefaultComplete(O&o) // default error handler
+ {
+ // empty
+ }
+
+ static void initComplete(BLE::InitializationCompleteCallbackContext *params)
+ {
+ Blob o; // setup a blob
+ o.pComplete = params; // store to provide access
+
+ // params->error = (ble_error_t)((int)BLE_ERROR_NONE+1); // uncomment for debug
+
+ trace(o,2,"<initialized>\n");
+
+ if (params->error != BLE_ERROR_NONE)
+ {
+ trace(o,0,"error\n");
+ if (cbError)
+ (*cbError)(o); // handle error in follow-up
+
+ return;
+ }
+
+ // Ensure that it is the default instance of BLE
+
+ if(o.getInstanceID() != BLE::DEFAULT_INSTANCE)
+ {
+ return;
+ }
+
+ (*cbSetup)(o); // followup with setup
+ }
+
+
+ void init(O&o, void (*scb)(O&o),void (*ecb)(O&o)) // init BLE system
+ {
+ cbSetup = scb; // store setup callback
+ cbError = ecb; // store error callback
+ o.init(initComplete);
+ }
+
+
+ void init(O&o, void (*scb)(O&o)) // initialize BLE system
+ {
+ init(o,scb,cbDefaultError); // continue with default error callback
+ }
+
+ void init(O&o) // initialize BLE system
+ {
+ init(o,cbDefaultComplete,cbDefaultError);
+ while (!o.hasInitialized())
+ {
+ trace(o,1,"waiting for initialized BLE!\n");
+ wait_ms(200);
+ }
+ }
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/init.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/init.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,90 @@
+// init.h - initialize BLE system
+//
+// Synopsis:
+//
+// void init(Blob &o, void (*scb)(Blob&),void (*ecb)(Blob&)) // init BLE
+// void init(Blob &o, void (*scb)(Blob&)) // init BLE
+//
+// Arguments:
+//
+// o: Blob object (to avoid name clashes)
+// scb: setup callback
+// ecb: error callback
+//
+// Description:
+//
+// Initialize BLE system, providing a setup callback and optionally an error
+// callback. The actual initializing happens in the setup callback. If an
+// error occurs during initializin, the error callback will be consulted. If
+// no error callback is provided an implicit error callback will be called.
+//
+// Example 1: simple BLE system setup
+//
+// void cbSetup(Blob &o)
+// {
+// device(o,"IoT node"); // setup device name
+// name(o,"Node #1"); // setup advertising name
+// advertise("C:ng"); // start advertising
+// }
+//
+// main(void)
+// {
+// Blob o; // our Blob object
+// init(o,cbSetup); // init BLE base layer, always do first
+// while (true) // Infinite loop waiting for BLE events
+// sleep(o); // low energy waiting
+// }
+//
+// Example 2: Provide also error handler
+//
+// void cbError(Blob &o)
+// {
+// trace(0,"init error!");
+// }
+//
+// void cbSetup(Blob &o)
+// {
+// device(o,"IoT node"); // setup device name
+// name(o,"Node #1"); // setup advertising name
+// advertise("C:ng"); // start advertising
+// }
+//
+// main(void)
+// {
+// Blob o; // our Blob object
+// init(o,cbSetup,cbError); // init BLE base layer, always do first
+// while (true) // Infinite loop waiting for BLE events
+// sleep(o); // low energy waiting
+// }
+//
+// Example 3: Without Callbacks (busy waiting until initialized)
+//
+// main(void)
+// {
+// Blob o; // our Blob object
+// init(o); // init BLE base layer, always do first
+//
+// device(o,"IoT node"); // setup device name
+// name(o,"Node #1"); // setup advertising name
+// advertise("C:ng"); // start advertising
+//
+// while (true) // Infinite loop waiting for BLE events
+// sleep(o); // low energy waiting
+// }
+//
+// See also: BLOB, INIT
+//
+#ifndef _INIT_H_
+#define _INIT_H_
+
+#include "bricks/o.h"
+
+//==============================================================================
+// Initializing
+//==============================================================================
+
+ void init(O&o, void (*scb)(O&o),void (*ecb)(O&o)); // init BLE system
+ void init(O&o, void (*scb)(O&o)); // init BLE system
+ void init(O&o); // init BLE system
+
+#endif // _INIT_H_
\ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/o.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/o.h Sun Oct 01 12:49:25 2017 +0000 @@ -0,0 +1,9 @@ +// o.h - dealing with THE object 'O' +#ifndef _O_H_ +#define _O_H_ + +#define O Blob + +#include "bricks/blob.h" + +#endif // _O_H_ \ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/print.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/print.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,49 @@
+// print.h - print value of a characteristic
+//
+// Synopsis:
+//
+// See also: CHARACTERISTIC, GET, SET
+//
+#ifndef _PRINT_H_
+#define _PRINT_H_
+
+#include <stdio.h>
+#include "ble/Gap.h"
+#include "bricks/o.h"
+#include "bricks/types.h"
+#include "bricks/characteristic.h"
+
+//==============================================================================
+// Some Callbacks
+//==============================================================================
+
+ inline void print(O&o, Characteristic<Buffer> &chr, const char *name)
+ {
+ //Serial out(USBTX, USBRX); // serial port to PC terminal
+
+ Buffer data; uint8_t *p = data;
+ get(o,chr,data);
+
+ printf("%s: %02x-%02x-%02x-%02x-%02x-",name,(int)(p[0]),(int)(p[1]),(int)(p[2]),(int)(p[3]),(int)(p[4]));
+ printf("%02x-%02x-%02x-%02x-%02x\r\n",(int)(p[5]),(int)(p[6]),(int)(p[7]),(int)(p[8]),(int)(p[9]));
+ }
+
+ inline void print(O&o, Characteristic<Bool> &chr, const char *name)
+ {
+ //Serial out(USBTX, USBRX); // serial port to PC terminal
+ Bool data;
+
+ get(o,chr,data);
+ printf("%s: %02x\r\n",name,data);
+ }
+
+// we provide also some PRINT methods for non Characteristics. If the value of
+// a characteristic needs to be printed the value must be fetched before with
+// the GET function.
+
+ inline void print(O&o, Bool data, const char *name)
+ {
+ printf("%s: %02x\r\n",name,(int)data);
+ }
+
+#endif // _PRINT_H_
\ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/service.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/service.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,85 @@
+// service.h - declaring services and definitions
+//
+// Synopsis
+//
+// Example 1: A protocol might be declared as a class as follows
+//
+// Collection col; // collection used during setup
+//
+// Characteristic<ObjectId> id(col,0x2AC3,"rw","ID");
+// Characteristic<ObjectName> name(col,0x2ABE,"rw","Name");
+// Characteristic<Digital> presence(col,0x2A56,"r","Presence");
+//
+// Service presenceDetection(col,0xA001); // instantiate service
+//
+// onSetup(Blob &blue)
+// {
+// blue.service(presenceDetection); // use service
+// }
+//
+// Example 2: service definition by means of a service definition class
+//
+// class PresenceDetector
+// {
+// public:
+// Collection col; // collection used during setup
+//
+// Characteristic<ObjectId> id; // ID of presence detector
+// Characteristic<ObjectName> name; // name of presence detector
+// Characteristic<Digital> presence; // digital presence value
+// Characteristic<DateTime> timestamp; // last detection change's time
+// Characteristic<ObjectName> layout; // name of model railway layout
+//
+// Service presenceDetection; // the service
+//
+// public:
+// PresenceDetector(Blob &blue, cost UUID uuid) :
+// list; // init service list
+// id(list,0x2AC3,"rw","ID"), // instantiate characteristic
+// name(list,0x2ABE,"rw","Name"), // instantiate characteristic
+// presence(list,0x2A56,"r","Presence"),// instantiate characteristic
+// timestamp(list,0x2A08,"r","Timestamp"),// instantiate characteristic
+// layout(list,0x2ABE,"rw","Layout"), // instantiate characteristic
+// presenceDetection(list,uuid) // instantiate service
+// {
+// Blob blue;
+// blue.service(presenceDetection); // use service
+// }
+// };
+//
+#ifndef _SERVICE_H_
+#define _SERVICE_H_
+
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "bricks/blob.h"
+#include "bricks/collection.h"
+
+ // the following #define is helpful if a service is defined on base of the
+ // BLE API (the tedios way)
+
+#define GattListLength(list) (sizeof(list)/sizeof(GattCharacteristic*))
+
+ // Service classs definition
+
+ class Service
+ {
+ public: // public properties
+ Collection collection; // collection of characteristics
+ uint16_t uuid; // UUID of service
+ const char *name; // name of service
+
+ public: // public methods
+ Service(uint16_t _uuid, const char* _name = NULL) : collection()
+ {
+ uuid = _uuid;
+ name = _name;
+ }
+
+ void add(GattCharacteristic *pChr) // add a characteristic to collection
+ {
+ collection.add(pChr);
+ }
+ };
+
+#endif // _SERVICE_H_
\ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/set.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/set.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,46 @@
+// set.h - set data from a characteristics
+//
+// Synopsis:
+//
+// Set data from a 'characteristic' based on 'data' variable
+//
+// set(characteristic,data)
+//
+// The 'set' function (overloaded function family) is implemented for all
+// types defined in "bricks/types.h".
+//
+// See also: CHARACTERISTIC, GET
+//
+#ifndef _SET_H_
+#define _SET_H_
+
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "ble/GattServer.h"
+#include "bricks/o.h"
+#include "bricks/types.h"
+#include "bricks/characteristic.h"
+
+ inline void set(O&o, Characteristic<Bool> &chr, const Bool &data)
+ {
+ uint16_t size = sizeof(Bool)/sizeof(uint8_t);
+ o.gattServer().write(chr.getValueHandle(), (uint8_t*)&data,size);
+ }
+
+ inline void set(O&o, Characteristic<ObjectId> &chr, const ObjectId &data)
+ {
+ uint16_t size = sizeof(ObjectId)/sizeof(uint8_t);
+ o.gattServer().write(chr.getValueHandle(), (uint8_t*)&data,size);
+ }
+
+// we provide also some SET methods for GattCharacteristics. However the use
+// of these methods are more dangerous, because a GattCharacteristics can be
+// of any type and the compiler cannot help us to check !!!
+
+ inline void set(O&o,GattCharacteristic &chr,Bool data)
+ {
+ uint16_t size = sizeof(Bool)/sizeof(uint8_t);
+ o.gattServer().write(chr.getValueHandle(), (uint8_t*)&data,size);
+ }
+
+#endif // _SET_H_
\ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/sleep.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/sleep.h Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,50 @@
+// sleep.h - sleep for some time
+//
+// Synopsis:
+//
+// void sleep(Blob &o) // low energy sleep for some mili seconds
+// void sleep(Blob &o, int ms) // low enery sleep, handle BLE events
+//
+// Arguments:
+//
+// o: Blob object (to avoid name clashes)
+// msec: sleeping interval in miliseconds
+//
+// Description:
+//
+//
+// Example 1: main function body to setup BLE functionality
+//
+// main(void)
+// {
+// Blob o; // our Blob object
+// init(o,onSetup,onError); // init BLE base layer, always do first
+//
+// while (true) // Infinite loop waiting for BLE events
+// sleep(o); // low power waiting for BLE events
+// }
+//
+// Example 2: Turn LED on for 2 seconds miliseconds
+//
+// led = 1; // turn LED on
+// sleep(o,2000); // wait 2000 miliseconds (in LE mode)
+// led = 0; // turn LED off
+//
+// See also: BLOB, INIT
+//
+#ifndef _SLEEP_H_
+#define _SLEEP_H_
+
+#include "bricks/blob.h"
+
+ inline void sleep(Blob &o) // low power waiting for BLE events
+ {
+ o.waitForEvent(); // low power waiting for BLE events
+ }
+
+ inline void sleep(Blob &o, int ms) // low power waiting for BLE events
+ {
+ wait_ms(ms); // low power waiting for some miliseconds
+ }
+
+#endif // _SLEEP_H_
\ No newline at end of file
diff -r 307f58df778a -r a6b74dfdd5f2 bricks/trace.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bricks/trace.cpp Sun Oct 01 12:49:25 2017 +0000
@@ -0,0 +1,54 @@
+// trace.cpp - trace a message depending on verbose level
+//
+
+#include <stdio.h>
+#include "bricks/trace.h"
+
+ static Serial pc(USBTX, USBRX); // serial port to PC terminal
+
+//==============================================================================
+// Managing the Verbose Lewvel
+//==============================================================================
+
+ static int threshold = 0; // verbose threshold, no verbose messages
+
+ void verbose(O&o, int level) // setup verbose level
+ {
+ threshold = level; // update verbose threshold
+ }
+
+//==============================================================================
+// Printing Trace Messages
+//==============================================================================
+
+ void trace(O&o, int level, const char *msg) // trace a message
+ {
+ if (level <= threshold) // update verbose threshold
+ { char buf[2] = " "; // must be terminated
+
+ for (; *msg; msg++)
+ { buf[0] = *msg;
+ printf(buf);
+ if (*msg == '\n')
+ { buf[0] = '\r'; // auto adding carriage return
+ printf(buf);
+ }
+ }
+ }
+ }
+
+ void trace(O&o, int level, const char*format, int value)
+ {
+ char buf[80];
+ if (strlen(format) > 70)
+ trace(o,level," *** buffer overflow *** ");
+ else
+ { sprintf(buf,format,value);
+ trace(o,level,buf);
+ }
+ }
+
+ void traceln(O&o, int level, const char*msg) // trace with CR & LF
+ {
+ trace(o,level,msg); trace(o,level,"\r\n");
+ }
