Pull request for i.a. sensor buffer template

Dependencies:   BLE_API MPU6050 mbed nRF51822

Files at this revision

API Documentation at this revision

Comitter:
JustinAtAlten
Date:
Thu Nov 15 15:13:52 2018 +0000
Parent:
9:e9d6a9758cf7
Child:
11:8c38e284e9f7
Commit message:
added sensor value buffer template, added a temperature bulk request service, and changed how the tickers are handled (to save memory).

Changed in this revision

AppTime.cpp Show annotated file Show diff for this revision Revisions of this file
AppTime.h Show annotated file Show diff for this revision Revisions of this file
IO.cpp Show annotated file Show diff for this revision Revisions of this file
IO.h Show annotated file Show diff for this revision Revisions of this file
MeasurementBufferTemplate.h Show annotated file Show diff for this revision Revisions of this file
ReadIntervals.cpp Show annotated file Show diff for this revision Revisions of this file
ReadIntervals.h Show annotated file Show diff for this revision Revisions of this file
Util.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
mbed_config.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AppTime.cpp	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,15 @@
+#include "AppTime.h"
+
+#include "mbed.h"
+#include "Timer.h"
+
+static Timer runTime;
+
+void AppTime::init(){
+	runTime.start();
+}
+
+float AppTime::getTime(){
+	return runTime;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AppTime.h	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,11 @@
+#ifndef APPTIME_H
+#define APPTIME_H
+
+//AppTime: because time(NULL) always returns -1!
+
+namespace AppTime {
+	extern void init();
+	extern float getTime();
+};
+
+#endif /* APPTIME_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IO.cpp	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,15 @@
+#include "IO.h"
+
+// InterruptIn button(BUTTON_PIN);
+AnalogIn	battery(BATTERY_PIN);
+MPU6050 	mpu(MPU6050_SDA, MPU6050_SCL);
+// InterruptIn motion_probe(p14);
+#ifdef USE_SERIAL
+Serial 		pc(UART_TX, UART_RX);
+#endif /* USE_SERIAL */
+
+DigitalOut blue(LED_BLUE);
+DigitalOut green(LED_GREEN);
+DigitalOut red(LED_RED);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IO.h	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,45 @@
+#ifndef IO_H
+#define IO_H
+
+#include "mbed.h"
+#include "MPU6050.h"
+
+// #define USE_SERIAL
+
+
+//---------------//
+
+
+#define LED_GREEN   p21
+#define LED_RED	 	p22
+#define LED_BLUE	p23
+// #define BUTTON_PIN  p17
+#define BATTERY_PIN p1
+
+#define MPU6050_SDA p12
+#define MPU6050_SCL p13
+
+#define UART_TX	 	p9
+#define UART_RX	 	p11
+#define UART_CTS	p8
+#define UART_RTS	p10
+
+// extern InterruptIn button;
+extern AnalogIn	battery;
+extern MPU6050 mpu;
+#ifdef USE_SERIAL
+extern Serial pc;
+#endif /* USE_SERIAL */
+
+extern DigitalOut blue;
+extern DigitalOut green;
+extern DigitalOut red;
+
+#ifdef USE_SERIAL
+#define LOG(...)	{ pc.printf(__VA_ARGS__); }
+#else /* USE_SERIAL */
+#define LOG(...)	{  }
+#endif  /* USE_SERIAL */
+
+
+#endif /* IO_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MeasurementBufferTemplate.h	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,125 @@
+#ifndef MEASUREMENTBUFFERTEMPLATE_H
+#define MEASUREMENTBUFFERTEMPLATE_H
+
+#include "AppTime.h"
+
+#define IncrementInRange(x, range) (((x+1) >= range) ? 0 : x+1)
+
+
+template<typename T_BufferType, unsigned int T_BufferLength, unsigned int T_ReadingsInUpdate, unsigned int T_ReadInterval, T_BufferType (*T_MeasurementFunction)()>
+class MeasurementBufferTemplate {
+public:
+	struct BulkUpdate {
+		uint32_t requestedTime; 			//intended time of first sensor-reading, specified by request
+		uint32_t initialTime; 				//provided time of first sensor-reading
+		uint32_t sensorReadingInterval; 	// time difference between sensor-readings (seconds)
+		uint32_t numberOfReadings;
+		T_BufferType readings[T_ReadingsInUpdate];
+
+		BulkUpdate(const time_t & requestedTime=0, const time_t & initialTime=0, const time_t & sensorReadingInterval=0) :
+				requestedTime(requestedTime),
+				initialTime(initialTime),
+				sensorReadingInterval(sensorReadingInterval),
+				numberOfReadings(0)
+		{
+
+		}
+	};
+
+public:
+	MeasurementBufferTemplate() : 
+			buffer(new T_BufferType[T_BufferLength]),
+			indexOfNewestReading(T_BufferLength-1),
+			timeOfLastReading(0),
+			nrSensorReadingsPerformed(0)
+	{
+
+	}
+
+	virtual ~MeasurementBufferTemplate(){
+		delete [] buffer;
+	}
+
+	T_BufferType performMeasurement(){
+		//Get data
+		T_BufferType measurementData = T_MeasurementFunction();
+
+		//Update buffer and meta-data
+		indexOfNewestReading = IncrementInRange(indexOfNewestReading, T_BufferLength);
+		timeOfLastReading = AppTime::getTime();
+		buffer[indexOfNewestReading] = measurementData;
+
+		if(nrSensorReadingsPerformed < T_BufferLength){ 	//doesn't matter what the value is past this point, so only increment when relevant to prevent overflow
+			nrSensorReadingsPerformed++;
+		}
+
+		return measurementData;
+	}
+
+	BulkUpdate getBulkUpdate(const time_t & requestedTime){
+		if(timeOfLastReading < requestedTime){
+			//no data available yet for requested time
+			return BulkUpdate(requestedTime);
+		}
+
+		//find sensor-reading from where to start copying data
+		float tDiff = timeOfLastReading - (float)requestedTime;
+		unsigned int periodsPassed = tDiff / T_ReadInterval;
+
+		//if request is made for data that no longer exists (i.e. it was overwritten already), then just present the oldest data we have
+		if(periodsPassed >= T_BufferLength){
+			periodsPassed = T_BufferLength-1;
+		}
+
+		//If more sensor-readings are requested than have been read: adjust request to all readings that have been read
+		if(periodsPassed >= nrSensorReadingsPerformed){
+			periodsPassed = nrSensorReadingsPerformed-1;
+		}
+
+		//set time of initial sensorReading
+		float timePassed = periodsPassed * T_ReadInterval;
+		time_t initialTime = 0;
+		if(timePassed > timeOfLastReading){
+			//Shouldn't happen
+			initialTime = 0;
+		} else {
+			initialTime = timeOfLastReading - timePassed;
+		}
+
+		//find the startIndex of the stored data
+		int startIndex = (int)indexOfNewestReading - periodsPassed; 	// n+1 sensor-readings read for n = periodsPassed
+		if(startIndex < 0){
+		 	//count backwards
+			startIndex = T_BufferLength - abs(startIndex);
+				//startIndex should now be >= 0, because (abs(startIndex) + 1) <= T_BufferLength
+		}
+
+		//copy data to BulkUpdate
+		BulkUpdate ret(requestedTime, initialTime, T_ReadInterval);
+		unsigned int readIndex = startIndex;
+		for(unsigned int i=0; i < T_ReadingsInUpdate; i++){
+			//Copy reading
+			ret.readings[i] = buffer[readIndex];
+			ret.numberOfReadings++;
+
+			//increment read index
+			readIndex = IncrementInRange(readIndex, T_BufferLength);
+			
+			if(readIndex == IncrementInRange(indexOfNewestReading, T_BufferLength)){
+				//if this iteration just read the newest temperature-sensor-reading: stop
+				break;
+			}
+		}
+
+		return ret;
+	}
+
+private:
+	T_BufferType * buffer;
+	unsigned int indexOfNewestReading;
+	float timeOfLastReading;
+	uint16_t nrSensorReadingsPerformed;
+};
+
+
+#endif /* MEASUREMENTBUFFERTEMPLATE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ReadIntervals.cpp	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,36 @@
+#include "ReadIntervals.h"
+#include <algorithm>
+
+int ReadIntervals::temperatureSensorPeriod_timeLeft = 0;
+int ReadIntervals::batteryMonitorPeriod_timeLeft = 0;
+
+
+
+void ReadIntervals::updateTimeLeft(const int & tickerSleptTime){
+	temperatureSensorPeriod_timeLeft -= tickerSleptTime;
+	batteryMonitorPeriod_timeLeft -= tickerSleptTime;
+}
+
+int ReadIntervals::getTickerSleepTime(){
+	if(temperatureSensorPeriod_timeLeft <= 0){
+		temperatureSensorPeriod_timeLeft += TemperatureSensorPeriod;
+	}
+	if(batteryMonitorPeriod_timeLeft <= 0){
+		batteryMonitorPeriod_timeLeft += BatteryMonitorPeriod;
+	}
+
+	int ret = temperatureSensorPeriod_timeLeft;
+	ret = std::min<int>(ret, batteryMonitorPeriod_timeLeft);
+	
+	ret = std::max<int>(ret, 1); 	//assert that ret != 0 or lower
+
+	return ret;
+}
+
+bool ReadIntervals::temperatureSensorPeriodPassed(){
+	return (temperatureSensorPeriod_timeLeft <= 0);
+}
+bool ReadIntervals::batteryMonitorPeriodPassed(){
+	return (batteryMonitorPeriod_timeLeft <= 0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ReadIntervals.h	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,22 @@
+#ifndef READINTERVALS_H
+#define READINTERVALS_H
+
+namespace ReadIntervals {
+	//                                                  //
+	//      All time-variables here are in seconds      //
+	//                                                  //
+
+	const unsigned int TemperatureSensorPeriod = 1;
+	const unsigned int BatteryMonitorPeriod = 60;
+
+	extern int temperatureSensorPeriod_timeLeft;
+	extern int batteryMonitorPeriod_timeLeft;
+
+	extern bool temperatureSensorPeriodPassed();
+	extern bool batteryMonitorPeriodPassed();
+
+	extern void updateTimeLeft(const int & tickerSleptTime);
+	extern int getTickerSleepTime();
+};
+
+#endif /* READINTERVALS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Util.h	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,82 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <string>
+// #include <vector>
+
+template<typename T_FromType, typename T_ToType>
+inline void castArray(T_FromType * fromArray, T_ToType * toArray, const unsigned int & length){
+	for(unsigned int i=0; i < length; i++){
+		toArray[i] = fromArray[i];
+	}
+}
+
+// inline std::vector<std::string> split(std::string receivedMessage, const char & delimiter = ' '){
+// 	std::vector<std::string> ret;
+// 	size_t wordEnd = receivedMessage.find_first_of(delimiter);
+// 	while(wordEnd != std::string::npos){
+// 		std::string word = receivedMessage.substr(0, wordEnd);
+// 		if(!word.empty()){
+// 			ret.push_back(word);
+// 		}
+// 		receivedMessage = receivedMessage.substr(wordEnd+1);
+// 		wordEnd = receivedMessage.find_first_of(delimiter);
+// 	}
+// 	if(!receivedMessage.empty()){
+// 		ret.push_back(receivedMessage);
+// 	}
+
+// 	return ret;
+// }
+
+
+inline char digitToChar(uint8_t digit){
+	return ('0' + digit); //ascii value + digit value = ascii value
+}
+
+inline std::string floatToString(float value, int maximumNumberOfDecimals = 5){	//Temporary solution to solve logging of float values
+	//First make sure buffer is big enough
+	std::string ret;
+	int integersLength = 0;
+	int valueInt = static_cast<int>(value);
+
+	//integer part
+	if(valueInt){
+		integersLength = 1;
+	}
+	while(valueInt /= 10){   //assuming decimal system
+		integersLength++;
+		value /= 10.0f;
+	}
+	
+	for(int i=0; i < integersLength; i++){
+		uint8_t digit = (uint8_t) value;
+		ret += digitToChar(digit);
+		value -= digit;
+		value *= 10.0f;
+	}
+
+	//decimal point
+	ret += ".";
+	
+	//decimal part
+	int decimalLength = 0;
+	while((value != 0.0f) && (decimalLength < maximumNumberOfDecimals)){
+		uint8_t digit = (uint8_t) value;
+		ret += digitToChar(digit);
+		decimalLength++;
+		value -= digit;
+		value *= 10.0f;
+	}
+	
+	if((decimalLength == 0) && (decimalLength < maximumNumberOfDecimals)){
+		ret += "0";
+	}
+	ret += "f";
+	
+	return ret;
+}
+
+#define floatToCharArray(...) floatToString(__VA_ARGS__).c_str()
+
+#endif /* UTIL_H */
--- a/main.cpp	Tue Oct 16 22:29:07 2018 +0200
+++ b/main.cpp	Thu Nov 15 15:13:52 2018 +0000
@@ -1,5 +1,5 @@
-
 #include "mbed.h"
+#include "mbed_mem_trace.h"
 #include "nrf51.h"
 #include "nrf51_bitfields.h"
 #include "MPU6050.h"
@@ -12,27 +12,26 @@
 #include "TemperatureService.h"
 #include "AccelerationService.h"
 
-
-#define LOG(...)    { pc.printf(__VA_ARGS__); }
-
-#define LED_GREEN   p21
-#define LED_RED     p22
-#define LED_BLUE    p23
-#define BUTTON_PIN  p17
-#define BATTERY_PIN p1
+#include "ReadIntervals.h"
+#include "Util.h"
+#include "IO.h"
+#include "MeasurementBufferTemplate.h"
 
-#define MPU6050_SDA p12
-#define MPU6050_SCL p13
+//https://os.mbed.com/handbook/SDFileSystem
+// http://os.mbed.com/users/mbed_official/code/SDFileSystem/
+// needs: https://os.mbed.com/teams/mbed-official/code/FATFileSystem/pull-request/4
+// #include "SDFileSystem.h"
+//https://os.mbed.com/cookbook/SD-Card-File-System
 
-#define UART_TX     p9
-#define UART_RX     p11
-#define UART_CTS    p8
-#define UART_RTS    p10
 
-/* Starting sampling rate. */
+///////////////////////////////////////
+//              DEFINES              //
+///////////////////////////////////////
+
+// Starting sampling rate.
 #define DEFAULT_MPU_HZ  (100)
 
-
+// --- Device Information --- //
 #define MANUFACTURER "PM @ ALTEN"
 #define MODELNUMBER "IoT BLE"
 #define SERIALNUMBER "123456"
@@ -40,178 +39,271 @@
 #define FIRMWAREREVISION "1.0"
 #define SOFTWAREREVISION "1.0"
 
-DigitalOut blue(LED_BLUE);
-DigitalOut green(LED_GREEN);
-DigitalOut red(LED_RED);
+/////////////////////////////////////////
+//              CONSTANTS              //
+/////////////////////////////////////////
+
+// --- UUIDs --- //
+const char acceleration128bitUUIDlist[] = { 0x53, 0xF8, 0x0E, 0x12, 0xAD, 0xBB, 0xF1, 0x38, 0xAC, 0x07, 0xD2, 0x3D, 0xF0, 0xE2, 0x34, 0x5D };
+const UUID uuidTempBulkService("11111111-1000-2222-3333-444455556666");
+const UUID uuidTempBulkCharRead("11111111-1001-2222-3333-444455556666");
 
-InterruptIn button(BUTTON_PIN);
-AnalogIn    battery(BATTERY_PIN);
-Serial pc(UART_TX, UART_RX);
-MPU6050 mpu(MPU6050_SDA, MPU6050_SCL);
+// --- Temperature Buffer Data --- //
+const unsigned int TemperatureBufferSize = 100;
+const unsigned int TemperatureBulkUpdateSize = 6;
+	// https://devzone.nordicsemi.com/f/nordic-q-a/519/reading-a-subset-of-data-on-a-ble-server
+	//  characteristic data max 512 bytes
+	//	https://github.com/pieterm/bledemo#step-8-add-callback-function-on-data-written-event
+	//  	GattWriteCallbackParams
+
 
-InterruptIn motion_probe(p14);
+/////////////////////////////////////////////////////
+//              FUNCTION DECLARATIONS              //
+/////////////////////////////////////////////////////
+
+uint16_t readTemperature();
 
-int read_none_count = 0;
+////////////////////////////////////////
+//              TYPEDEFS              //
+////////////////////////////////////////
+
+typedef MeasurementBufferTemplate<uint16_t, TemperatureBufferSize, TemperatureBulkUpdateSize, ReadIntervals::TemperatureSensorPeriod, readTemperature> TemperatureBuffer;
 
-BLEDevice  ble;
-UARTService *uartServicePtr;
+/////////////////////////////////////////
+//              VARIABLES              //
+/////////////////////////////////////////
 
-// variables to monitor the battery voltage
-volatile float  batteryVoltage = 100.0f;
-volatile bool   batteryVoltageChanged = false;
+// --- Buffers --- //
+TemperatureBuffer temperatureBuffer;
+TemperatureBuffer::BulkUpdate tempUpdate;
 
-volatile bool   startMeasure = false;
+// --- Timing --- //
+Ticker ticker;
+
+// --- BLE --- //
+GattCharacteristic * tempBulkUpdateCharacteristic;
 
-volatile bool bleIsConnected = false;
-volatile uint8_t tick_event = 0;
+// --- Flags --- //
+volatile bool batteryVoltageChanged = false;
+volatile bool tempUpdateFlag = false;
+volatile bool startMeasure = false;
+
+/////////////////////////////////////////
+//              FUNCTIONS              //
+/////////////////////////////////////////
+
 
-int16_t ax, ay, az;
-int16_t gx, gy, gz;
+uint16_t readTemperature(){
+	//read temperature (raw)
+	int16_t tempRaw = mpu.getTempRaw();
+	// convert into 0.1 degrees Celsius
+	tempRaw *= 10;
+	tempRaw += 5210;
+	tempRaw /= 340;
+	tempRaw += 350;
 
-//char acceleration128bitUUIDlist[] = {0x5D,0x34,0xE2,0xF0 ,0x3D,0xD2 ,0x07,0xAC ,0x38,0xF1 ,0xBB,0xAD,0x12,0x0E,0xF8,0x53};
-char acceleration128bitUUIDlist[] = { 0x53, 0xF8, 0x0E, 0x12, 0xAD, 0xBB, 0xF1, 0x38, 0xAC, 0x07, 0xD2, 0x3D, 0xF0, 0xE2, 0x34, 0x5D };
+	return tempRaw;
+}
 
 
 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
 {
-    LOG("Connected!\n");
-    bleIsConnected = true;
+	LOG("Connected!\n");
+	// bleIsConnected = true;
 }
 
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams)
 {
-    LOG("Disconnected!\n");
-    LOG("Restarting the advertising process\n");
-    ble.startAdvertising();
-    bleIsConnected = false;
+	LOG("Disconnected!\n");
+	LOG("Restarting the advertising process\n");
+	BLE & ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
+	ble.gap().startAdvertising();
+	// bleIsConnected = false;
 }
 
 void tick(void)
 {
-    green = !green;
-    startMeasure = true;    // notify the main-loop to start measuring the MPU6050
+	static int tickerSleepTime=0;
+	blue = !blue;
+
+	//update time
+	ReadIntervals::updateTimeLeft(tickerSleepTime);
+
+	//perform actions
+	if(ReadIntervals::temperatureSensorPeriodPassed()){
+		green = !green;
+		startMeasure = true;	// notify the main-loop to start measuring the MPU6050
+	}
+	if(ReadIntervals::batteryMonitorPeriodPassed()){
+		red = !red;
+		batteryVoltageChanged = true;
+	}
+
+	//prep next ticker-sleep
+	tickerSleepTime = ReadIntervals::getTickerSleepTime();
+	ticker.attach(tick, tickerSleepTime);
 }
 
-// timer callback function to measure the ADC battery level
-void batteryMonitorCallback(void)
-{
-    float sample;
-    
-    sample = battery.read();
-    /* cannot use (uart.)printf() in a ISR like this. */
-    batteryVoltage = sample;
-    batteryVoltageChanged = true;
+// void detect(void)
+// {
+// 	LOG("Button pressed\n");  
+// 	blue = !blue;
+// }
+
+void setAdvertisingPayload(BLE & ble){
+	ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
+	ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+	ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
+									 (const uint8_t *)acceleration128bitUUIDlist, sizeof(acceleration128bitUUIDlist));
 }
 
-void detect(void)
-{
-    LOG("Button pressed\n");  
-    blue = !blue;
+void setScanResponsePayload(BLE & ble){
+	uint8_t name[] = "iot aabbccddeeff";
+	Gap::AddressType_t addr_type;
+	Gap::Address_t address;
+	ble_error_t error = ble.gap().getAddress(&addr_type, address);
+	if(error == BLE_ERROR_NONE){
+		for(int i = 5; i >= 0; i--){
+			char buffer[3];
+			sprintf(buffer, "%02x", address[i]);
+			name[4 + ((5-i)*2)] = buffer[0];
+			name[4 + ((5-i)*2) + 1] = buffer[1];
+		}
+	}
+	
+	ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME,
+									 name, sizeof(name));
 }
 
 
+void onDataWritten(const GattWriteCallbackParams * context)
+{
+	if(context->handle == tempBulkUpdateCharacteristic->getValueHandle()){
+		const time_t & newSelectedTime = *(time_t*)context->data;
+		tempUpdate = temperatureBuffer.getBulkUpdate(newSelectedTime);
+		tempUpdateFlag = true;
+	}
+}
+
 int main(void)
 {
-    blue  = 1;
-    green = 1;
-    red   = 1;
+	///Start global timer
+	AppTime::init();
+
+	///Initialize led values
+	blue  = 0;
+	green = 1;
+	red   = 1;
+
+	wait(1);
 
-    pc.baud(115200);
-    
-    wait(1);
-    
-    LOG("---- Seeed Tiny BLE ----\n");
-    
-    
-    LOG("MPU6050 testConnection \n");
-    bool mpu6050TestResult = mpu.testConnection();
-    if(mpu6050TestResult) {
-        LOG("MPU6050 test passed \n");
-    } else {
-        LOG("MPU6050 test failed \n");
-    }
-    
-    Ticker ticker;
-    ticker.attach(tick, 5);
-    
-    Ticker batteryMonitorTicker;
-    batteryMonitorTicker.attach(batteryMonitorCallback, 60.0f);
+#ifdef USE_SERIAL
+	pc.baud(115200);
+#endif /* USE_SERIAL */
+	
+	LOG("---- Seeed Tiny BLE ----\n");
+	
+	///Initialize MPU6050
+	LOG("MPU6050 testConnection \n");
+	bool mpu6050TestResult = mpu.testConnection();
+	if(mpu6050TestResult) {
+		LOG("MPU6050 test passed \n");
+	} else {
+		LOG("MPU6050 test failed \n");
+	}
+	
+	///Initialize temperature buffer & update
+	uint16_t temperature = temperatureBuffer.performMeasurement();
+	tempUpdate = temperatureBuffer.getBulkUpdate(0);
 
-    button.fall(detect);
+	///Initialize ticker
+	ticker.attach(tick, ReadIntervals::TemperatureSensorPeriod);
+	
+	// button.fall(detect);
+
+	///Initialize BLE
+	LOG("Initialising the nRF51822\n");
+	BLE & ble = BLE::Instance(BLE::DEFAULT_INSTANCE);
+	ble.init();
+	ble.gap().onDisconnection(disconnectionCallback);
+	ble.gap().onConnection(connectionCallback);
 
-    LOG("Initialising the nRF51822\n");
-    ble.init();
-    ble.gap().onDisconnection(disconnectionCallback);
-    ble.gap().onConnection(connectionCallback);
-    
-    uint8_t name[] = "iot aabbccddeeff";
-    
-    Gap::AddressType_t addr_type;
-    Gap::Address_t address;
-    ble_error_t error = ble.gap().getAddress(&addr_type, address);
-    if (error == BLE_ERROR_NONE) {
-        for (int i = 5; i >= 0; i--){
-            char buffer[3];
-            sprintf(buffer, "%02x", address[i]);
-            name[4 + ((5-i)*2)] = buffer[0];
-            name[4 + ((5-i)*2) + 1] = buffer[1];
-        }
-    }
-    LOG("name = %s\n", name);
-    
-    /* setup advertising */
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
-    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
-    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
-                                     (const uint8_t *)acceleration128bitUUIDlist, sizeof(acceleration128bitUUIDlist));
-    ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME,
-                                     name, sizeof(name));
-    
-    DFUService dfu(ble);                                 
-    UARTService uartService(ble);
-    uartServicePtr = &uartService;
-    //uartService.retargetStdout();
-    BatteryService battery(ble);
-    DeviceInformationService deviceInfo(ble, MANUFACTURER, MODELNUMBER, SERIALNUMBER, HARDWAREREVISION, FIRMWAREREVISION, SOFTWAREREVISION);
-    TemperatureService tempService(ble);
-    AccelerationService accelerationService(ble);
+	// -> Initialize BLE - custom services
+	tempBulkUpdateCharacteristic = new GattCharacteristic(uuidTempBulkCharRead, NULL, 1, sizeof(tempUpdate), 
+			GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
+	GattService tempBulkService(uuidTempBulkService, &tempBulkUpdateCharacteristic, 1);
+	ble.gattServer().addService(tempBulkService);
+	ble.gattServer().onDataWritten(onDataWritten);
+	
+	// -> Initialize BLE - advertising and scan payloads
+	setAdvertisingPayload(ble);
+	setScanResponsePayload(ble);
+	
+	// -> Initialize BLE - generic services
+	DFUService dfu(ble);
+	UARTService uartService(ble);
+	BatteryService batteryService(ble);
+	DeviceInformationService deviceInfo(ble, MANUFACTURER, MODELNUMBER, SERIALNUMBER, HARDWAREREVISION, FIRMWAREREVISION, SOFTWAREREVISION);
+	TemperatureService tempService(ble);
+	AccelerationService accelerationService(ble);
+
+	// -> Initialize BLE - start advertising
+	ble.gap().setAdvertisingInterval(160); // 100ms; in multiples of 0.625ms.
+	ble.gap().startAdvertising();
+
+	tempService.updateTemperature(temperature);
+	
+	while(true) {
+		ble.waitForEvent();
+
+		// update battery level after the level is measured
+		if(batteryVoltageChanged == true) {
+			float batteryVoltage = battery.read();
+			// LOG("VBat: %4.3f, ADC: %4.3f, Vadc: %4.3f\n", batteryVoltage*2.0f, batteryVoltage, batteryVoltage*3.3f);
+			LOG("VBat: %s, ADC: %s, Vadc: %s\n", floatToCharArray(batteryVoltage*2.0f), floatToCharArray(batteryVoltage), floatToCharArray(batteryVoltage*3.3f));
+			batteryService.updateBatteryLevel((uint8_t)(batteryVoltage*100.0f));	// input is 0-1.0 of 3.3V -> *100 = percentage of 3.3V
+			batteryVoltageChanged = false;
+		}
 
-    ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
-    ble.gap().startAdvertising();
-    
-    while (true) {
-        ble.waitForEvent();
-    
-        // update battery level after the level is measured
-        if (batteryVoltageChanged == true) {
-            LOG("VBat: %4.3f, ADC: %4.3f, Vadc: %4.3f\n", batteryVoltage*2.0f, batteryVoltage, batteryVoltage*3.3f);
-            battery.updateBatteryLevel((uint8_t)(batteryVoltage*100.0f));    // input is 0-1.0 of 3.3V -> *100 = percentage of 3.3V
-            batteryVoltageChanged = false;
-        }
-        else if (startMeasure == true) {
-            //float a[3];
-            //mpu.getAccelero(a);
-            //LOG("Acceleration %.2f;%.2f;%.2f\n", a[0], a[1], a[2]);
+		if(startMeasure == true) {
+			//uartService.write("test\n", 5);
+			//float a[3];
+			//mpu.getAccelero(a);
+			//LOG("Acceleration %.2f;%.2f;%.2f\n", a[0], a[1], a[2]);
  
-            int a[3];
-            mpu.getAcceleroRaw(a);
-            accelerationService.addAcceleration((int16_t*)a);
-            //LOG("Acceleration %d;%d;%d\n", a[0], a[1], a[2]);
-            LOG("Acceleration 0x%x;0x%x;0x%x\n", a[0], a[1], a[2]);
-            
-            float temp = mpu.getTemp();
-            LOG("Temp = %.01f\n", temp);
-            int16_t tempRaw = mpu.getTempRaw();
-            // convert into 0.1 degrees Celsius
-            tempRaw *= 10;
-            tempRaw += 5210;
-            tempRaw /= 340;
-            tempRaw += 350;
-            // update BLE tmperature
-            tempService.updateTemperature(tempRaw);
-            
-            startMeasure = false;
-        }
-    }
+			///Acceleration
+			//read accelerometer data
+			int a[3];
+			mpu.getAcceleroRaw(a);
+			//convert to format accepted by accelerionService
+			int16_t a_16[3];
+			castArray(a, a_16, 3); 	//cannot simply cast 'a' to int16_t*, memory won't move accordingly
+			// update BLE acceleration
+			accelerationService.addAcceleration(a_16);
+			LOG("Acceleration 0x%x;0x%x;0x%x\n", a[0], a[1], a[2]);
+			
+			///Temperature
+			uint16_t temperature = temperatureBuffer.performMeasurement();
+			tempService.updateTemperature(temperature);
+
+			///Reset measure flag
+			startMeasure = false;
+		}
+
+		if(tempUpdateFlag){
+			ble_error_t err = ble.gattServer().write(tempBulkUpdateCharacteristic->getValueHandle(), (const uint8_t*)&tempUpdate, sizeof(tempUpdate));
+			LOG("err:[%d]\n", err);
+			LOG("rT:[%d]\n", tempUpdate.requestedTime);
+			LOG("iT:[%d]\n", tempUpdate.initialTime);
+			LOG("nR:[%d]\n", tempUpdate.numberOfReadings);
+			LOG("pT:[%s]\n", floatToCharArray(tempUpdate.sensorReadingInterval));
+				// LOG("pT:[%f]\n", tempUpdate.sensorReadingInterval);
+			for(unsigned int i=0; i < tempUpdate.numberOfReadings; i++){
+				LOG("%#010x\n", tempUpdate.readings[i]);
+			}
+			tempUpdateFlag = false;
+		}
+	}
 }
 
+
--- a/mbed.bld	Tue Oct 16 22:29:07 2018 +0200
+++ b/mbed.bld	Thu Nov 15 15:13:52 2018 +0000
@@ -1,1 +1,1 @@
-https://os.mbed.com/users/mbed_official/code/mbed/builds/e95d10626187
\ No newline at end of file
+https://os.mbed.com/users/mbed_official/code/mbed/builds/aa5281ff4a02
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_config.h	Thu Nov 15 15:13:52 2018 +0000
@@ -0,0 +1,36 @@
+/*
+ * mbed SDK
+ * Copyright (c) 2017 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Automatically generated configuration file.
+// DO NOT EDIT, content will be overwritten.
+
+#ifndef __MBED_CONFIG_DATA__
+#define __MBED_CONFIG_DATA__
+
+// Configuration parameters
+#define MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE 9600   // set by library:platform
+#define MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR 0      // set by library:platform
+#define MBED_CONF_PLATFORM_STDIO_BAUD_RATE          115200 // set by application[*]
+#define MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES   1      // set by application[*]
+#define MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT      1      // set by library:platform
+// Macros
+#define MBED_HEAP_STATS_ENABLED                     1      // defined by application
+#define MBED_MEM_TRACING_ENABLED                    1      // defined by application
+#define MBED_STACK_STATS_ENABLED                    1      // defined by application
+
+#endif
+