Marco Merlin
Published © CC BY

MIDI rIoT!

Implements a wireless controller that takes signals from sensors and translates them into MIDI to control a software synthesizer.

IntermediateFull instructions provided20 hours1,664

Things used in this project

Hardware components

Rapid IoT Prototyping Kit
NXP Rapid IoT Prototyping Kit
×1
NXP QN9080DK
NXP QN9080DK
×1
100W, Hi-Z Dedicated Input
100W, Hi-Z Dedicated Input
×1

Software apps and online services

NXP Rapid IOT
IAR Embedded workbench
hairless MIDI
loopMIDI
vsthost
TAL bassline
asio4all

Story

Read more

Code

NXP MIDI RioT online IDE code

C/C++
This is the code I wrote on the online IDE editor
#include "callbacks.h"

//HEADER START
#define MIDI_CHANNEL 0
#define MIDI_CHANNEL_FX 1
#define MIDI_CHANNEL_PERCUSSION 10
#define CONTROL_ROTATIONX 34
#define CONTROL_ROTATIONY 35
#define CONTROL_ROTATIONZ 36
#define CONTROL_MAGX 31
#define CONTROL_MAGY 32
#define CONTROL_MAGZ 33
#define CONTROL_ALL 31

//MIDI STATUS HEADERS

#define MIDI_STATUS_NOTE_OFF        0b10000000
#define MIDI_STATUS_NOTE_ON         0b10010000
#define MIDI_STATUS_POLY_KEY_PRESS  0b10100000
#define MIDI_STATUS_CC              0b10110000 // control change
#define MIDI_STATUS_PC              0b10110000 // program change
#define MIDI_STATUS_PRESSURE        0b11010000
#define MIDI_STATUS_PITCH_BEND      0b11100000

// MIDI Notes Pitch
#define MIDI_ALLNOTEOFF 123
#define MIDI_C1 36
#define MIDI_A2 57
#define MIDI_B2 59
#define MIDI_C3 60
#define MIDI_D3 62
#define MIDI_E3 64
#define MIDI_F3 65
#define MIDI_G3 67

static unsigned short int ctrl_select = CONTROL_ALL;
//HEADER END

void ATMO_Setup() {

}


ATMO_Status_t FastSensorPoll_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t FastSensorPoll_setup(ATMO_Value_t *in, ATMO_Value_t *out) {

	ATMO_INTERVAL_Handle_t intervalHandle;
    ATMO_INTERVAL_AddAbilityInterval(
		ATMO_PROPERTY(FastSensorPoll, instance), 
		ATMO_ABILITY(FastSensorPoll, interval), 
		ATMO_PROPERTY(FastSensorPoll, time), 
		&intervalHandle
	);
	
	return ATMO_Status_Success;
	
}


ATMO_Status_t FastSensorPoll_interval(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight_setup(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_TSL2572_Config_t config;
	config.address = ATMO_PROPERTY(TSL2572AmbientLight, i2cAddress);
	config.i2cDriverInstance = ATMO_PROPERTY(TSL2572AmbientLight, i2cInstance);

	return ( ATMO_TSL2572_Init(&config) == ATMO_TSL2572_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;

}


ATMO_Status_t TSL2572AmbientLight_setEnabled(ATMO_Value_t *in, ATMO_Value_t *out) {
ATMO_TSL2572_SetEnabled(true);
return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight_setDisabled(ATMO_Value_t *in, ATMO_Value_t *out) {
ATMO_TSL2572_SetEnabled(false);
return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight_setEnabledDisabled(ATMO_Value_t *in, ATMO_Value_t *out) {
bool enabled = false;
ATMO_GetBool(in, &enabled);
ATMO_TSL2572_SetEnabled(enabled);
return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight_readAmbientLight(ATMO_Value_t *in, ATMO_Value_t *out) {
    float lightLux;
    if(ATMO_TSL2572_GetAmbientLight(&lightLux) != ATMO_TSL2572_Status_Success)
    {
        ATMO_CreateValueVoid(out);
        return ATMO_Status_Fail;
    }
    ATMO_CreateValueInt(out, (int)lightLux);
    return ATMO_Status_Success;
}


ATMO_Status_t EmbeddedIconLinesDisplay_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t EmbeddedIconLinesDisplay_displayPage(ATMO_Value_t *in, ATMO_Value_t *out) {

	ATMO_UI_Page_DisplayPageByCoord(ATMO_PROPERTY(EmbeddedIconLinesDisplay, x), ATMO_PROPERTY(EmbeddedIconLinesDisplay, y), false);
	return ATMO_Status_Success;
	
}


ATMO_Status_t EmbeddedIconLinesDisplay_onDisplayed(ATMO_Value_t *in, ATMO_Value_t *out) {

	return ATMO_Status_Success;
    
}


ATMO_Status_t EmbeddedIconLinesDisplay_onLeave(ATMO_Value_t *in, ATMO_Value_t *out) {

	return ATMO_Status_Success;
	
}


ATMO_Status_t EmbeddedIconLinesDisplay_setIconLabelAndColor(ATMO_Value_t *in, ATMO_Value_t *out) {

    struct {
        char str[32];
        GUI_COLOR color;
    } icon_data;
 
    ATMO_GetBinary(in, &icon_data, sizeof(icon_data));
    ATMO_UI_ICONLINES_SetIconLabelColor(ATMO_VARIABLE(EmbeddedIconLinesDisplay, pageHandle), icon_data.str, icon_data.color);
    return ATMO_Status_Success;
    
}


ATMO_Status_t EmbeddedIconLinesDisplay_setIconLabel(ATMO_Value_t *in, ATMO_Value_t *out) {

    char str[32];
    ATMO_GetString(in, str, 32);
    ATMO_UI_ICONLINES_SetIconLabel(ATMO_VARIABLE(EmbeddedIconLinesDisplay, pageHandle), str);
    return ATMO_Status_Success;
    
}


ATMO_Status_t EmbeddedIconLinesDisplay_setup(ATMO_Value_t *in, ATMO_Value_t *out) {

    ATMO_UI_PAGE_Config_t config;
    config.hidden = ATMO_PROPERTY(EmbeddedIconLinesDisplay, pageHidden);
    config.textColor = ATMO_PROPERTY(EmbeddedIconLinesDisplay, textColor);
    config.activeButtons = ATMO_UI_Page_GetButtonMask(ATMO_PROPERTY(EmbeddedIconLinesDisplay, topRightButtonEnabled),
    ATMO_PROPERTY(EmbeddedIconLinesDisplay,bottomRightButtonEnabled), ATMO_PROPERTY(EmbeddedIconLinesDisplay, topLeftButtonEnabled), ATMO_PROPERTY(EmbeddedIconLinesDisplay, bottomLeftButtonEnabled));
	config.x = ATMO_PROPERTY(EmbeddedIconLinesDisplay, x);
    config.y = ATMO_PROPERTY(EmbeddedIconLinesDisplay, y);
	strncpy(config.topLeftButtonLabel, ATMO_PROPERTY(EmbeddedIconLinesDisplay, topLeftButtonLabel), ATMO_BUTTON_LABEL_MAXLEN);
	strncpy(config.topRightButtonLabel, ATMO_PROPERTY(EmbeddedIconLinesDisplay, topRightButtonLabel), ATMO_BUTTON_LABEL_MAXLEN);
	strncpy(config.bottomLeftButtonLabel, ATMO_PROPERTY(EmbeddedIconLinesDisplay, bottomLeftButtonLabel), ATMO_BUTTON_LABEL_MAXLEN);
	strncpy(config.bottomRightButtonLabel, ATMO_PROPERTY(EmbeddedIconLinesDisplay, bottomRightButtonLabel), ATMO_BUTTON_LABEL_MAXLEN);
    config.spanX = ATMO_PROPERTY(EmbeddedIconLinesDisplay, spanX);
	config.spanY = ATMO_PROPERTY(EmbeddedIconLinesDisplay, spanY);
    config.title = ATMO_PROPERTY(EmbeddedIconLinesDisplay, pageTitle);
    config.titleHidden = ATMO_PROPERTY(EmbeddedIconLinesDisplay, titleHidden);
	ATMO_UI_ICONLINES_Init(&config, ATMO_PROPERTY(EmbeddedIconLinesDisplay, numLines), false);
	ATMO_VARIABLE(EmbeddedIconLinesDisplay, pageHandle) = config.templateInstance;
    ATMO_UI_ICONLINES_SetMainText(config.templateInstance, 0, ATMO_PROPERTY(EmbeddedIconLinesDisplay, line1Text));
    ATMO_UI_ICONLINES_SetMainText(config.templateInstance, 1, ATMO_PROPERTY(EmbeddedIconLinesDisplay, line2Text));
    ATMO_UI_ICONLINES_SetMainText(config.templateInstance, 2, ATMO_PROPERTY(EmbeddedIconLinesDisplay, line3Text));
    ATMO_UI_ICONLINES_SetMainText(config.templateInstance, 3, ATMO_PROPERTY(EmbeddedIconLinesDisplay, line4Text));
    ATMO_UI_ICONLINES_SetIconLabel(config.templateInstance, ATMO_PROPERTY(EmbeddedIconLinesDisplay, iconLabel));
    ATMO_UI_ICONLINES_RegisterButtonAbilityHandle(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), 1, ATMO_ABILITY(EmbeddedIconLinesDisplay, topRightButtonPressed));
	ATMO_UI_ICONLINES_RegisterButtonAbilityHandle(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), 2, ATMO_ABILITY(EmbeddedIconLinesDisplay, bottomRightButtonPressed));
	ATMO_UI_ICONLINES_RegisterButtonAbilityHandle(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), 3, ATMO_ABILITY(EmbeddedIconLinesDisplay, topLeftButtonPressed));
    ATMO_UI_ICONLINES_RegisterButtonAbilityHandle(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), 4, ATMO_ABILITY(EmbeddedIconLinesDisplay, bottomLeftButtonPressed));
    ATMO_UI_ICONLINES_SetIcon(config.templateInstance, ATMO_PROPERTY(EmbeddedIconLinesDisplay, icon));
    ATMO_UI_ICONLINES_RegisterOnDisplayedAbilityHandle(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), ATMO_ABILITY(EmbeddedIconLinesDisplay, onDisplayed));
    ATMO_UI_ICONLINES_RegisterOnLeaveAbilityHandle(config.templateInstance, ATMO_ABILITY(EmbeddedIconLinesDisplay, onLeave));
    return ATMO_Status_Success;
    
}


ATMO_Status_t EmbeddedIconLinesDisplay_setLine1Text(ATMO_Value_t *in, ATMO_Value_t *out) {

    char label[32];
    if(ATMO_GetString(in, label, 32) == ATMO_Status_Success)
    {
        ATMO_UI_ICONLINES_SetMainText(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), 0, label);
    }
    else
    {
        return ATMO_Status_Fail;
    }

    return ATMO_Status_Success;
    
}


ATMO_Status_t EmbeddedIconLinesDisplay_setLine2Text(ATMO_Value_t *in, ATMO_Value_t *out) {

    char label[32];
    if(ATMO_GetString(in, label, 32) == ATMO_Status_Success)
    {
        ATMO_UI_ICONLINES_SetMainText(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), 1, label);
    }
    else
    {
        return ATMO_Status_Fail;
    }

    return ATMO_Status_Success;
    
}


ATMO_Status_t EmbeddedIconLinesDisplay_setLine3Text(ATMO_Value_t *in, ATMO_Value_t *out) {

    char label[32];
    if(ATMO_GetString(in, label, 32) == ATMO_Status_Success)
    {
        ATMO_UI_ICONLINES_SetMainText(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), 2, label);
    }
    else
    {
        return ATMO_Status_Fail;
    }

    return ATMO_Status_Success;
    
}


ATMO_Status_t EmbeddedIconLinesDisplay_setLine4Text(ATMO_Value_t *in, ATMO_Value_t *out) {

    char label[32];
    if(ATMO_GetString(in, label, 32) == ATMO_Status_Success)
    {
        ATMO_UI_ICONLINES_SetMainText(ATMO_VARIABLE(EmbeddedIconLinesDisplay,pageHandle), 3, label);
    }
    else
    {
        return ATMO_Status_Fail;
    }

    return ATMO_Status_Success;
    
}


ATMO_Status_t EmbeddedIconLinesDisplay_topRightButtonPressed(ATMO_Value_t *in, ATMO_Value_t *out) {
    //return FunctionTRbutton2MIdi_trigger(in, out);
    	char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_C3; //0kkkkkkk, k = key (60 = middle C)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
	
}


ATMO_Status_t EmbeddedIconLinesDisplay_bottomRightButtonPressed(ATMO_Value_t *in, ATMO_Value_t *out) {
    // FunctionBRbutton2MIdi_trigger(in, out);
    char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_F3; //0kkkkkkk, k = key (66 = middle F)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
	
}


ATMO_Status_t EmbeddedIconLinesDisplay_topLeftButtonPressed(ATMO_Value_t *in, ATMO_Value_t *out) {
    // FunctionTLbutton2MIdi_trigger(in, out);
    char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_ALLNOTEOFF; //0kkkkkkk, k = key (123 = all note off)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
	
}


ATMO_Status_t EmbeddedIconLinesDisplay_bottomLeftButtonPressed(ATMO_Value_t *in, ATMO_Value_t *out) {
    // FunctionBLbutton2MIdi_trigger(in, out);
    char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_G3; //0kkkkkkk, k = key (68 = middle G)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
	
}


ATMO_Status_t BLEConnection_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t BLEConnection_setup(ATMO_Value_t *in, ATMO_Value_t *out) {

	ATMO_BLE_PairingCfg_t pairingCfg;
	pairingCfg.pairingKey = ATMO_PROPERTY(BLEConnection, pairingKey);
	pairingCfg.type = ATMO_PROPERTY(BLEConnection, pairingType);
	ATMO_BLE_GAPPairingCfg(ATMO_PROPERTY(BLEConnection, instance), &pairingCfg);

	ATMO_BLE_RegisterEventAbilityHandle(ATMO_PROPERTY(BLEConnection, instance), ATMO_BLE_EVENT_Connected, ATMO_ABILITY(BLEConnection, connected));
	ATMO_BLE_RegisterEventAbilityHandle(ATMO_PROPERTY(BLEConnection, instance), ATMO_BLE_EVENT_Disconnected, ATMO_ABILITY(BLEConnection, disconnected));
	ATMO_BLE_RegisterEventAbilityHandle(ATMO_PROPERTY(BLEConnection, instance), ATMO_BLE_EVENT_PairingRequested, ATMO_ABILITY(BLEConnection, pairingRequested));
	ATMO_BLE_RegisterEventAbilityHandle(ATMO_PROPERTY(BLEConnection, instance), ATMO_BLE_EVENT_PairingSuccess, ATMO_ABILITY(BLEConnection, pairingSucceeded));
	ATMO_BLE_RegisterEventAbilityHandle(ATMO_PROPERTY(BLEConnection, instance), ATMO_BLE_EVENT_PairingFailed, ATMO_ABILITY(BLEConnection, pairingFailed));
	
	return ATMO_Status_Success;
	
}


ATMO_Status_t BLEConnection_disconnect(ATMO_Value_t *in, ATMO_Value_t *out) {

	ATMO_BLE_GAPDisconnect(ATMO_PROPERTY(BLEConnection, instance));
	return ATMO_Status_Success;
	
}


ATMO_Status_t BLEConnection_connected(ATMO_Value_t *in, ATMO_Value_t *out) {

	return ATMO_Status_Success;
	
}


ATMO_Status_t BLEConnection_disconnected(ATMO_Value_t *in, ATMO_Value_t *out) {

	return ATMO_Status_Success;
	
}


ATMO_Status_t BLEConnection_pairingRequested(ATMO_Value_t *in, ATMO_Value_t *out) {

	ATMO_CreateValueCopy(out, in);
	return ATMO_Status_Success;
	
}


ATMO_Status_t BLEConnection_pairingSucceeded(ATMO_Value_t *in, ATMO_Value_t *out) {

	return ATMO_Status_Success;
	
}


ATMO_Status_t BLEConnection_pairingFailed(ATMO_Value_t *in, ATMO_Value_t *out) {

	return ATMO_Status_Success;
	
}


ATMO_Status_t TSL2572AmbientLight1_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight1_setup(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_TSL2572_Config_t config;
	config.address = ATMO_PROPERTY(TSL2572AmbientLight1, i2cAddress);
	config.i2cDriverInstance = ATMO_PROPERTY(TSL2572AmbientLight1, i2cInstance);

	return ( ATMO_TSL2572_Init(&config) == ATMO_TSL2572_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;

}


ATMO_Status_t TSL2572AmbientLight1_setEnabled(ATMO_Value_t *in, ATMO_Value_t *out) {
ATMO_TSL2572_SetEnabled(true);
return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight1_setDisabled(ATMO_Value_t *in, ATMO_Value_t *out) {
ATMO_TSL2572_SetEnabled(false);
return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight1_setEnabledDisabled(ATMO_Value_t *in, ATMO_Value_t *out) {
bool enabled = false;
ATMO_GetBool(in, &enabled);
ATMO_TSL2572_SetEnabled(enabled);
return ATMO_Status_Success;
}


ATMO_Status_t TSL2572AmbientLight1_readAmbientLight(ATMO_Value_t *in, ATMO_Value_t *out) {
    float lightLux;
    if(ATMO_TSL2572_GetAmbientLight(&lightLux) != ATMO_TSL2572_Status_Success)
    {
        ATMO_CreateValueVoid(out);
        return ATMO_Status_Fail;
    }
    ATMO_CreateValueInt(out, (int)lightLux);
    return ATMO_Status_Success;
}


ATMO_Status_t DisplaySensorPoll_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t DisplaySensorPoll_setup(ATMO_Value_t *in, ATMO_Value_t *out) {

	ATMO_INTERVAL_Handle_t intervalHandle;
    ATMO_INTERVAL_AddAbilityInterval(
		ATMO_PROPERTY(DisplaySensorPoll, instance), 
		ATMO_ABILITY(DisplaySensorPoll, interval), 
		ATMO_PROPERTY(DisplaySensorPoll, time), 
		&intervalHandle
	);
	
	return ATMO_Status_Success;
	
}


ATMO_Status_t DisplaySensorPoll_interval(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t ENS210TemperatureHumidity_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t ENS210TemperatureHumidity_setup(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_ENS210_Config_t config;
	config.address = ATMO_PROPERTY(ENS210TemperatureHumidity, i2cAddress);
	config.i2cDriverInstance = ATMO_PROPERTY(ENS210TemperatureHumidity, i2cInstance);
	config.tempCalibrationOffset = ATMO_PROPERTY(ENS210TemperatureHumidity, tempCalibrationOffset);

	return ( ATMO_ENS210_Init(&config) == ATMO_ENS210_Status_Success ) ? ATMO_Status_Success : ATMO_Status_Fail;

}


ATMO_Status_t ENS210TemperatureHumidity_setEnabled(ATMO_Value_t *in, ATMO_Value_t *out) {
ATMO_ENS210_SetEnabled(true);
return ATMO_Status_Success;
}


ATMO_Status_t ENS210TemperatureHumidity_setDisabled(ATMO_Value_t *in, ATMO_Value_t *out) {
ATMO_ENS210_SetEnabled(false);
return ATMO_Status_Success;
}


ATMO_Status_t ENS210TemperatureHumidity_setEnabledDisabled(ATMO_Value_t *in, ATMO_Value_t *out) {
bool enabled = false;
ATMO_GetBool(in, &enabled);
ATMO_ENS210_SetEnabled(enabled);
return ATMO_Status_Success;
}


ATMO_Status_t ENS210TemperatureHumidity_readTemperature(ATMO_Value_t *in, ATMO_Value_t *out) {
    float tempC;
    
    if(ATMO_ENS210_GetTemperatureFloat(&tempC) == ATMO_ENS210_Status_Success)
    {
        ATMO_CreateValueFloat(out, tempC);
    }
    else
    {
        ATMO_CreateValueVoid(out);
    }
    
    return ATMO_Status_Success;
}


ATMO_Status_t ENS210TemperatureHumidity_readHumidity(ATMO_Value_t *in, ATMO_Value_t *out) {
    float humidityPct;

    if(ATMO_ENS210_GetHumidityFloat(&humidityPct) == ATMO_ENS210_Status_Success)
    {
        ATMO_CreateValueFloat(out, humidityPct);
    }
    else
    {
        ATMO_CreateValueVoid(out);
    }
    
    return ATMO_Status_Success;
}


ATMO_Status_t GATT_NRF_UART_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t GATT_NRF_UART_setup(ATMO_Value_t *in, ATMO_Value_t *out) {

	ATMO_BLE_GATTSAddService(
		ATMO_PROPERTY(GATT_NRF_UART, instance),
		&ATMO_VARIABLE(GATT_NRF_UART, bleServiceHandle), 
		ATMO_PROPERTY(GATT_NRF_UART, bleServiceUuid));
	
	uint8_t property = 0;
	uint8_t permission = 0;
	
	property |= ATMO_PROPERTY(GATT_NRF_UART, read) ? ATMO_BLE_Property_Read : 0;
	property |= ATMO_PROPERTY(GATT_NRF_UART, write) ? ATMO_BLE_Property_Write : 0;
	property |= ATMO_PROPERTY(GATT_NRF_UART, notify) ? ATMO_BLE_Property_Notify : 0;

	permission |= ATMO_PROPERTY(GATT_NRF_UART, read) ? ATMO_BLE_Permission_Read : 0;
	permission |= ATMO_PROPERTY(GATT_NRF_UART, write) ? ATMO_BLE_Permission_Write : 0;

	ATMO_DATATYPE types[3] = {ATMO_PROPERTY(GATT_NRF_UART, writeDataType), ATMO_PROPERTY(GATT_NRF_UART, readDataType), ATMO_PROPERTY(GATT_NRF_UART, notifyDataType)};
	
	ATMO_BLE_GATTSAddCharacteristic(
		ATMO_PROPERTY(GATT_NRF_UART, instance),
		&ATMO_VARIABLE(GATT_NRF_UART, bleCharacteristicHandle), 
		ATMO_VARIABLE(GATT_NRF_UART, bleServiceHandle), 
		ATMO_PROPERTY(GATT_NRF_UART, bleCharacteristicUuid), 
		property, permission, ATMO_GetMaxValueSize(3, 64, types));
	
	ATMO_BLE_GATTSRegisterCharacteristicAbilityHandle(
		ATMO_PROPERTY(GATT_NRF_UART, instance),
		ATMO_VARIABLE(GATT_NRF_UART, bleCharacteristicHandle), 
		ATMO_BLE_Characteristic_Written, 
		ATMO_ABILITY(GATT_NRF_UART, written));
	
	return ATMO_Status_Success;
	
}


ATMO_Status_t GATT_NRF_UART_setValue(ATMO_Value_t *in, ATMO_Value_t *out) {

	
	// Convert to the desired write data type
	ATMO_Value_t convertedValue;
	ATMO_InitValue(&convertedValue);
	ATMO_CreateValueConverted(&convertedValue, ATMO_PROPERTY(GATT_NRF_UART, readDataType), in);

	ATMO_BLE_GATTSSetCharacteristic(
		ATMO_PROPERTY(GATT_NRF_UART, instance),
		ATMO_VARIABLE(GATT_NRF_UART, bleCharacteristicHandle),
		convertedValue.size, 
		(uint8_t *)convertedValue.data,
		NULL);
	
	ATMO_FreeValue(&convertedValue);
		
	return ATMO_Status_Success;
	
}


ATMO_Status_t GATT_NRF_UART_written(ATMO_Value_t *in, ATMO_Value_t *out) {

	ATMO_CreateValueConverted(out, ATMO_PROPERTY(GATT_NRF_UART, writeDataType), in);
	return ATMO_Status_Success;
	
}


ATMO_Status_t GATT_NRF_UART_subscibed(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t GATT_NRF_UART_unsubscribed(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t FunctionLight2Midi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	char midi_msg[4] = "dea";
    unsigned int light = 0;
    
	ATMO_GetUnsignedInt(in, &light);
	
	midi_msg[0] = MIDI_STATUS_PITCH_BEND | (MIDI_CHANNEL & 0b1111); // 1110nnnn, n = channel. Pitch Bend
	/*midi_msg[1] = light & 0x7F; //0ffffff, f = fine
	midi_msg[2] = (light >> 7 ) & 0x7F; //0ccccccc, c= coarse*/
	
	midi_msg[1] = 0x0; //0ffffff, f = fine
	midi_msg[2] = light & 0x7F; //0ccccccc, c= coarse
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));

	return ATMO_Status_Success;
}


ATMO_Status_t FunctionTRbutton2Midi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_C3; //0kkkkkkk, k = key (60 = middle C)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
}


ATMO_Status_t FunctionTLbutton2MIdi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	
	char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_ALLNOTEOFF; //0kkkkkkk, k = key (123 = all note off)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;

}


ATMO_Status_t FunctionBRbutton2MIdi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_F3; //0kkkkkkk, k = key (66 = middle F)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
}


ATMO_Status_t FunctionBLbutton2Midi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	char midi_msg[4] = "dea";
	
	ctrl_select++;
	if ( ctrl_select > CONTROL_MAGZ) 
	    ctrl_select = CONTROL_ALL;
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_G3; //0kkkkkkk, k = key (68 = middle G)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	
	return ATMO_Status_Success;
}


ATMO_Status_t SX9500TouchUp_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t SX9500TouchUp_setup(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_SX9500_Config_t config;
	config.address = ATMO_PROPERTY(SX9500TouchUp, i2cAddress);
	config.i2cDriverInstance = ATMO_PROPERTY(SX9500TouchUp, i2cInstance);
	config.gpioDriverInstance = ATMO_PROPERTY(SX9500TouchUp, gpioInstance);
	config.interruptEnabled = ATMO_PROPERTY(SX9500TouchUp, interruptEnabled);
	config.interruptPin = ATMO_PROPERTY(SX9500TouchUp, interruptGpio);
	ATMO_SX9500_Init(&config);
	ATMO_SX9500_RegisterTouchedAbilityHandle(SX9500_Touched_Up, ATMO_ABILITY(SX9500TouchUp, pressUp));
	ATMO_SX9500_RegisterTouchedAbilityHandle(SX9500_Touched_Down, ATMO_ABILITY(SX9500TouchUp, pressDown));
	ATMO_SX9500_RegisterTouchedAbilityHandle(SX9500_Touched_Left, ATMO_ABILITY(SX9500TouchUp, pressLeft));
	ATMO_SX9500_RegisterTouchedAbilityHandle(SX9500_Touched_Right, ATMO_ABILITY(SX9500TouchUp, pressRight));
	return ATMO_Status_Success;
}


ATMO_Status_t SX9500TouchUp_getTouchData(ATMO_Value_t *in, ATMO_Value_t *out) {
	return;
}


ATMO_Status_t SX9500TouchUp_pressUp(ATMO_Value_t *in, ATMO_Value_t *out) {
SX9500_TouchState_t touchState;
ATMO_GetBinary(in, &touchState, sizeof(touchState));
ATMO_CreateValueBinary(out, &touchState, sizeof(touchState));
return ATMO_Status_Success;
}


ATMO_Status_t SX9500TouchUp_pressDown(ATMO_Value_t *in, ATMO_Value_t *out) {
SX9500_TouchState_t touchState;
ATMO_GetBinary(in, &touchState, sizeof(touchState));
ATMO_CreateValueBinary(out, &touchState, sizeof(touchState));
return ATMO_Status_Success;
}


ATMO_Status_t SX9500TouchUp_pressLeft(ATMO_Value_t *in, ATMO_Value_t *out) {
SX9500_TouchState_t touchState;
ATMO_GetBinary(in, &touchState, sizeof(touchState));
ATMO_CreateValueBinary(out, &touchState, sizeof(touchState));
return ATMO_Status_Success;
}


ATMO_Status_t SX9500TouchUp_pressRight(ATMO_Value_t *in, ATMO_Value_t *out) {
SX9500_TouchState_t touchState;
ATMO_GetBinary(in, &touchState, sizeof(touchState));
ATMO_CreateValueBinary(out, &touchState, sizeof(touchState));
return ATMO_Status_Success;
}


ATMO_Status_t FunctionTouchUp2Midi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_A2; //0kkkkkkk, k = key (57 = A-1)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
}


ATMO_Status_t FunctionTouchDown2Midi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_E3; //0kkkkkkk, k = key (64 = E0)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
}


ATMO_Status_t FunctionTouchLeft2Midi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_B2; //0kkkkkkk, k = key (59 = B-1)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
}


ATMO_Status_t FunctionTouchRight2Midi_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	char midi_msg[4] = "dea";
	
	midi_msg[0] = MIDI_STATUS_NOTE_ON | (MIDI_CHANNEL & 0b1111); // 1001nnnn, n = channel. Note On
	midi_msg[1] = 0x0fffffff & MIDI_D3; //0kkkkkkk, k = key (62 = D0)
	midi_msg[2] = 0x7F; //0vvvvvvv, v = velocity
	
	ATMO_CreateValueBinary(out, (void*)midi_msg, 3*sizeof(void));
	return ATMO_Status_Success;
}


ATMO_Status_t DetectMotion_trigger(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;
}


ATMO_Status_t DetectMotion_setup(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_FXOS8700_Config_t config;
	config.address = ATMO_PROPERTY(DetectMotion, i2cAddress);
	config.i2cDriverInstance = ATMO_PROPERTY(DetectMotion, i2cInstance);
	config.gpioDriverInstance = ATMO_PROPERTY(DetectMotion, gpioInstance);
	config.int1En = ATMO_PROPERTY(DetectMotion, interrupt1Enabled);
    config.int2En = ATMO_PROPERTY(DetectMotion, interrupt2Enabled);
    config.int1Pin = ATMO_PROPERTY(DetectMotion, interrupt1Gpio);
    config.int2Pin = ATMO_PROPERTY(DetectMotion, interrupt2Gpio);

    switch(ATMO_PROPERTY(DetectMotion, motionDetectType))
    {
        case FXOS8700_NoDetect:
        {
            config.freefallEnabled = false;
            config.motionEnabled = false;
            config.tapDetectionEnabled = false;
            break;
        }
        case FXOS8700_FreefallDetect:
        {
            config.freefallEnabled = true;
            config.motionEnabled = false;
            config.tapDetectionEnabled = false;
            break;
        }
        case FXOS8700_MotionDetect:
        {
            config.freefallEnabled = false;
            config.motionEnabled = true;
            config.tapDetectionEnabled = false;
            break;
        }
        case FXOS8700_TapDetect:
        {
            config.freefallEnabled = false;
            config.motionEnabled = false;
            config.tapDetectionEnabled = true;
            break; 
        }
        default:
        {
            config.freefallEnabled = false;
            config.motionEnabled = false;  
            config.tapDetectionEnabled = false;
            break;
        }
    }

    ATMO_FXOS8700_SetMotionDetectedAbilityHandle(ATMO_ABILITY(DetectMotion, detectMotion));
    ATMO_FXOS8700_SetFreefallDetectedAbilityHandle(ATMO_ABILITY(DetectMotion, detectFreefall));
    ATMO_FXOS8700_SetTapDetectedAbilityHandle(ATMO_ABILITY(DetectMotion, detectTap));
	ATMO_FXOS8700_Init(&config);

    return ATMO_Status_Success;
	
}


ATMO_Status_t DetectMotion_setEnabled(ATMO_Value_t *in, ATMO_Value_t *out) {
ATMO_FXOS8700_SetEnabled(true);
return ATMO_Status_Success;
}


ATMO_Status_t DetectMotion_setDisabled(ATMO_Value_t *in, ATMO_Value_t *out) {
ATMO_FXOS8700_SetEnabled(false);
return ATMO_Status_Success;
}


ATMO_Status_t DetectMotion_setEnabledDisabled(ATMO_Value_t *in, ATMO_Value_t *out) {
bool enabled = false;
ATMO_GetBool(in, &enabled);
ATMO_FXOS8700_SetEnabled(enabled);
return ATMO_Status_Success;
}


ATMO_Status_t DetectMotion_getSensorData(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_FXOS8700_SensorData_t data;

	if(ATMO_FXOS8700_GetSensorData(&data) != ATMO_FXOS8700_Status_Success)
	{
		ATMO_CreateValueVoid(out);
		return ATMO_Status_Fail;
	}

	ATMO_CreateValueBinary(out, &data, sizeof(data));
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_getAccelX(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_FXOS8700_SensorData_t data;

	if(ATMO_FXOS8700_GetSensorData(&data) != ATMO_FXOS8700_Status_Success)
	{
		ATMO_CreateValueVoid(out);
		return ATMO_Status_Fail;
	}

	ATMO_CreateValueFloat(out, data.accelX);
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_getAccelY(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_FXOS8700_SensorData_t data;

	if(ATMO_FXOS8700_GetSensorData(&data) != ATMO_FXOS8700_Status_Success)
	{
		ATMO_CreateValueVoid(out);
		return ATMO_Status_Fail;
	}

	ATMO_CreateValueFloat(out, data.accelY);
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_getAccelZ(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_FXOS8700_SensorData_t data;

	if(ATMO_FXOS8700_GetSensorData(&data) != ATMO_FXOS8700_Status_Success)
	{
		ATMO_CreateValueVoid(out);
		return ATMO_Status_Fail;
	}

	ATMO_CreateValueFloat(out, data.accelZ);
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_getMagX(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_FXOS8700_SensorData_t data;

	if(ATMO_FXOS8700_GetSensorData(&data) != ATMO_FXOS8700_Status_Success)
	{
		ATMO_CreateValueVoid(out);
		return ATMO_Status_Fail;
	}

	ATMO_CreateValueFloat(out, data.magX);
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_getMagY(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_FXOS8700_SensorData_t data;

	if(ATMO_FXOS8700_GetSensorData(&data) != ATMO_FXOS8700_Status_Success)
	{
		ATMO_CreateValueVoid(out);
		return ATMO_Status_Fail;
	}

	ATMO_CreateValueFloat(out, data.magY);
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_getMagZ(ATMO_Value_t *in, ATMO_Value_t *out) {
	ATMO_FXOS8700_SensorData_t data;

	if(ATMO_FXOS8700_GetSensorData(&data) != ATMO_FXOS8700_Status_Success)
	{
		ATMO_CreateValueVoid(out);
		return ATMO_Status_Fail;
	}

	ATMO_CreateValueFloat(out, data.magZ);
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_detectTap(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_detectMotion(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;

}


ATMO_Status_t DetectMotion_detectFreefall(ATMO_Value_t *in, ATMO_Value_t *out) {
	return ATMO_Status_Success;

}
...

This file has been truncated, please download it to see its full contents.

gatt_uuid128.h

C/C++
QN9080 SDK header file found under /source folder
/* 
* Declare all custom 128-bit UUIDs here using the format:
*
*  UUID128(name, bytes)
*
* where: 
*	-name : an unique tag for the newly defined UUID;
		will be used to reference this UUID when defining
		services and characteristics in <<gatt_db.h>>
*	-bytes: 16 bytes representing the 128-bit value
*
* One definition per line. No semicolon required after each definition.
*
* example:
*  UUID128(uuid_service_robot_characteristics, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF)
*  UUID128(uuid_char_robot_direction, 0x12, 0x34, 0x50, 0x00, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF)
*	
*/
/* Services */

/* Temperature */ 
UUID128(uuid_service_temperature, 0xE0, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x00, 0x02, 0xFF, 0x01)

// MIDI-BLE Service: 03B80E5A-EDE8-4B33-A751-6CE34EC4C700
UUID128(uuid_service_midile, 0x00, 0xC7, 0xC4, 0x4E, 0xE3, 0x6C, 0x51, 0xA7, 0x33, 0x4B, 0xE8, 0xED, 0x5A, 0x0E, 0xB8, 0x03)
// MIDI-BLE characteristic: 7772E5DB-3868-4112-A1A9-F2669D106BF3
UUID128(uuid_characteristic_midile, 0xF3, 0x6B, 0x10, 0x9D, 0x66, 0xF2, 0xA9, 0xA1, 0x12, 0x41, 0x68, 0x38, 0xDB, 0xE5, 0x72, 0x77)

// NRF UART Service UUID128: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
UUID128(uuid_service_nrfuart,           0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E)
// NRF UART Rx characteristic UUID128: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E
UUID128(uuid_characteristic_nrfuart_rx, 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x02, 0x00, 0x40, 0x6E)
// NRF UART Tx characteristic UUID128: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E
UUID128(uuid_characteristic_nrfuart_tx, 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x03, 0x00, 0x40, 0x6E)

temperature_collector.c

C/C++
Main updated code of temperature collector example modified to connect to a nRF UART protocol to stream MIDI messages through the debug COM port.
/*! *********************************************************************************
* \addtogroup Temperature Collector
* @{
********************************************************************************** */
/*! *********************************************************************************
* Copyright (c) 2015, Freescale Semiconductor, Inc.
* Copyright 2016-2017 NXP
* All rights reserved.
*
* \file
*
* This file is the source file for the Temperature Collector application
*
* SPDX-License-Identifier: BSD-3-Clause
********************************************************************************** */

/************************************************************************************
*************************************************************************************
* Include
*************************************************************************************
************************************************************************************/
/* Framework / Drivers */
#include "RNG_Interface.h"
#include "Keyboard.h"
#include "LED.h"
#include "Panic.h"
#include "TimersManager.h"
#include "FunctionLib.h"
#include "shell.h"
#if (cPWR_UsePowerDownMode)
#include "PWR_Interface.h"
#include "PWR_Configuration.h"
#endif

/* BLE Host Stack */
#include "gatt_server_interface.h"
#include "gatt_client_interface.h"
#include "gap_interface.h"
#include "gatt_db_app_interface.h"
#include "gatt_db_handles.h"

/* Profile / Services */
#include "temperature_interface.h"

#include "ble_conn_manager.h"
#include "ble_service_discovery.h"

#include "ApplMain.h"
#include "temperature_collector.h"

// mmerlin: for atoi
#include <stdlib.h>

/*************************************************************************************
**************************************************************************************
* Public macros
**************************************************************************************
*************************************************************************************/
const char* mGattStatus[] = {
    "NoError",
    "InvalidHandle",
    "ReadNotPermitted",
    "WriteNotPermitted",
    "InvalidPdu",
    "InsufficientAuthentication",
    "RequestNotSupported",
    "InvalidOffset",
    "InsufficientAuthorization",
    "PrepareQueueFull",
    "AttributeNotFound",
    "AttributeNotLong",
    "InsufficientEncryptionKeySize",
    "InvalidAttributeValueLength",
    "UnlikelyError",
    "InsufficientEncryption",
    "UnsupportedGroupType",
    "InsufficientResources",
};

/************************************************************************************
*************************************************************************************
* Private macros
*************************************************************************************
************************************************************************************/
#define mShellGattCmdsCount_c               6

#define mMaxServicesCount_d                 6
#define mMaxServiceCharCount_d              8
#define mMaxCharDescriptorsCount_d          2
#define mMaxCharValueLength_d               128 // ATMO_STATIC_SIZE

#define mThroughputReportThreshold_c        100
#define hNrfUartTxHandle                    34

/************************************************************************************
*************************************************************************************
* Shell Configuration
*************************************************************************************
************************************************************************************/
#define DEBUG_SHELL 0
#define debug_shell_write(fmt) if(DEBUG_SHELL) shell_write(fmt);
#define debug_shell_writeDec(fmt) if(DEBUG_SHELL) shell_writeDec(fmt);
#define debug_shell_writeLe(fmt) if(DEBUG_SHELL) shell_writeLe(fmt);
#define debug_shell_writeN(fmt,len) if(DEBUG_SHELL) shell_writeN(fmt,len);
#define debug_shell_writeHexLe(fmt,len) if(DEBUG_SHELL) shell_writeHexLe(fmt,len);

#define MIDI_SHELL 1
#define midi_write(fmt,len) if(MIDI_SHELL) shell_writeN(fmt,len);

/************************************************************************************
*************************************************************************************
* Private type definitions
*************************************************************************************
************************************************************************************/

typedef enum appEvent_tag{
    mAppEvt_PeerConnected_c,
    mAppEvt_PairingComplete_c,
    mAppEvt_ServiceDiscoveryComplete_c,
    mAppEvt_ServiceDiscoveryFailed_c,
    mAppEvt_GattProcComplete_c,
    mAppEvt_GattProcError_c
}appEvent_t;

typedef enum appState_tag{
    mAppIdle_c,
    mAppExchangeMtu_c,
    mAppServiceDisc_c,
    mAppReadDescriptor_c,
    mAppRunning_c,
}appState_t;

/*! Temperature Client - Configuration 
typedef struct tmcConfig_tag
{
    uint16_t    hService;
    uint16_t    hTemperature;
    uint16_t    hTempCccd;
    uint16_t    hTempDesc;
    gattDbCharPresFormat_t  tempFormat;
} tmcConfig_t;*/

typedef struct nrfUartConfig_tag
{  uint16_t    hService;
   gattDbCharPresFormat_t  dataFormat;   
   uint16_t    hNrfuart;
} nrfUartConfig_t;

typedef struct appCustomInfo_tag
{
    // tmcConfig_t     tempClientConfig;
    /* Add persistent information here */
    nrfUartConfig_t nrfuartClientConfig;
}appCustomInfo_t;

typedef struct appPeerInfo_tag
{
    deviceId_t      deviceId;
    appCustomInfo_t customInfo;
    bool_t          isBonded;
    appState_t      appState;
}appPeerInfo_t;


/************************************************************************************
*************************************************************************************
* Private memory declarations
*************************************************************************************
************************************************************************************/
static appPeerInfo_t mPeerInformation;

#if gAppUseBonding_d
static bool_t mRestoringBondedLink = FALSE;
#endif

static bool_t   mScanningOn = FALSE;
static bool_t   mFoundDeviceToConnect = FALSE;

/* Buffer used for Characteristic related procedures */
static gattAttribute_t      *mpCharProcBuffer = NULL;

/* Timers */
static tmrTimerID_t mAppTimerId;

/************************************************************************************
*************************************************************************************
* mmerlin: ported from ble_shell
*************************************************************************************
************************************************************************************/

/* Buffer used for Service Discovery */
/*static gattService_t *mpServiceDiscoveryBuffer = NULL;
static uint8_t  mcPrimaryServices = 0;*/

/* Buffer used for Characteristic Discovery */
static gattCharacteristic_t *mpCharBuffer = NULL;
/*static uint8_t mCurrentServiceInDiscoveryIndex;
static uint8_t mCurrentCharInDiscoveryIndex;
static uint8_t mcCharacteristics = 0;*/

/* Buffer used for Characteristic Descriptor Discovery */
/*static gattAttribute_t *mpCharDescriptorBuffer = NULL;*/

/************************************************************************************
*************************************************************************************
* Private functions prototypes
*************************************************************************************
************************************************************************************/

//mmerlin: ported from ble_shell
static int8_t MidiLeGatt_Read(uint8_t CharHandle);
static uint8_t MidiLeGatt_Print(deviceId_t serverDeviceId);

static void BleApp_PrintMidile ( uint8_t *msg, uint16_t msgLen);


/* Host Stack callbacks */
static void BleApp_ScanningCallback
(
    gapScanningEvent_t* pScanningEvent
);

static void BleApp_ConnectionCallback
(
    deviceId_t peerDeviceId,
    gapConnectionEvent_t* pConnectionEvent
);

static void BleApp_GattClientCallback
(
    deviceId_t              serverDeviceId,
    gattProcedureType_t     procedureType,
    gattProcedureResult_t   procedureResult,
    bleResult_t             error
);

static void BleApp_GattNotificationCallback
(
    deviceId_t          serverDeviceId,
    uint16_t characteristicValueHandle,
    uint8_t* aValue,
    uint16_t valueLength
);

static void BleApp_ServiceDiscoveryCallback
(
	deviceId_t deviceId,
	servDiscEvent_t* pEvent
);

static void BleApp_Config(void);

void BleApp_StateMachineHandler
(
    deviceId_t peerDeviceId,
    uint8_t event
);

static bool_t CheckScanEvent(gapScannedDevice_t* pData);

static void BleApp_StoreServiceHandles
(
    gattService_t   *pService
);

static void BleApp_StoreDescValues
(
    gattAttribute_t     *pDesc
);

/*static void BleApp_PrintTemperature
(
    uint16_t temperature
);*/

static bleResult_t BleApp_ConfigureNotifications(void);

static void ScanningTimeoutTimerCallback(void* pParam);
#if (cPWR_UsePowerDownMode)
static void DisconnectTimerCallback(void* pParam);
#endif
/************************************************************************************
*************************************************************************************
* Public functions
*************************************************************************************
************************************************************************************/

/*! *********************************************************************************
* \brief    Initializes application specific functionality before the BLE stack init.
*
********************************************************************************** */
void BleApp_Init(void)
{
    /* UI */
    shell_init("BLE Temp Collector>");
}

/*! *********************************************************************************
* \brief    Starts the BLE application.
*
********************************************************************************** */
void BleApp_Start(void)
{
    if (!mScanningOn)
    {
        App_StartScanning(&gScanParams, BleApp_ScanningCallback, TRUE);
    }
}

/*! *********************************************************************************
* \brief        Handles keyboard events.
*
* \param[in]    events    Key event structure.
********************************************************************************** */
void BleApp_HandleKeys(key_event_t events)
{
#if (cPWR_UsePowerDownMode)
    BleApp_Start();
#else
    switch (events)
    {
        case gKBD_EventPressPB1_c:
        {
            BleApp_Start();
            break;
        }
        case gKBD_EventLongPB1_c:
        {
            if (mPeerInformation.deviceId != gInvalidDeviceId_c)
                Gap_Disconnect(mPeerInformation.deviceId);
            break;
        }
        case gKBD_EventPressPB2_c:
        case gKBD_EventLongPB2_c:
        default:
            break;
    }
#endif
}

/*! *********************************************************************************
* \brief        Handles BLE generic callback.
*
* \param[in]    pGenericEvent    Pointer to gapGenericEvent_t.
********************************************************************************** */
void BleApp_GenericCallback (gapGenericEvent_t* pGenericEvent)
{
    /* Call BLE Conn Manager */
    BleConnManager_GenericEvent(pGenericEvent);

    switch (pGenericEvent->eventType)
    {
        case gInitializationComplete_c:
        {
            BleApp_Config();
        }
        break;
        default:
            break;
    }
}

/************************************************************************************
*************************************************************************************
* Private functions
*************************************************************************************
************************************************************************************/

/*! *********************************************************************************
* \brief        Configures BLE Stack after initialization. Usually used for
*               configuring advertising, scanning, white list, services, et al.
*
********************************************************************************** */
static void BleApp_Config()
{
    /* Configure as GAP Central */
    BleConnManager_GapCentralConfig();

    /* Register for callbacks*/
    App_RegisterGattClientProcedureCallback(BleApp_GattClientCallback);
    App_RegisterGattClientNotificationCallback(BleApp_GattNotificationCallback);
    BleServDisc_RegisterCallback(BleApp_ServiceDiscoveryCallback);
    
    /* Initialize private variables */
    mPeerInformation.appState = mAppIdle_c;
    mScanningOn = FALSE;
    mFoundDeviceToConnect = FALSE;

    /* Allocate scann timeout timer */
    mAppTimerId = TMR_AllocateTimer();

    /* UI */
    debug_shell_write("\r\nPress SCANSW to connect to a Temperature Sensor!\r\n");

#if (cPWR_UsePowerDownMode)
    /* Allow entering sleep mode until any user interaction */
    PWR_AllowDeviceToSleep();
#endif
}


/*! *********************************************************************************
* \brief        Handles BLE Scanning callback from host stack.
*
* \param[in]    pScanningEvent    Pointer to gapScanningEvent_t.
********************************************************************************** */
static void BleApp_ScanningCallback (gapScanningEvent_t* pScanningEvent)
{
    switch (pScanningEvent->eventType)
    {
        case gDeviceScanned_c:
        {
            mFoundDeviceToConnect = CheckScanEvent(&pScanningEvent->eventData.scannedDevice);
            //mFoundDeviceToConnect = TRUE;
            if (mFoundDeviceToConnect)
            {
                gConnReqParams.peerAddressType = pScanningEvent->eventData.scannedDevice.addressType;
                FLib_MemCpy(gConnReqParams.peerAddress, 
                            pScanningEvent->eventData.scannedDevice.aAddress,
                            sizeof(bleDeviceAddress_t));
                
                Gap_StopScanning();
#if gAppUsePrivacy_d
                gConnReqParams.usePeerIdentityAddress = pScanningEvent->eventData.scannedDevice.advertisingAddressResolved;
#endif
                App_Connect(&gConnReqParams, BleApp_ConnectionCallback);
           }
        }
        break;
        case gScanStateChanged_c:
        {
            mScanningOn = !mScanningOn;

            /* Node starts scanning */
            if (mScanningOn)
            {
                mFoundDeviceToConnect = FALSE;

                debug_shell_write("\r\nScanning...\r\n");

                /* Start advertising timer */
                TMR_StartLowPowerTimer(mAppTimerId,
                           gTmrLowPowerSecondTimer_c,
                           TmrSeconds(gScanningTime_c),
                           ScanningTimeoutTimerCallback, NULL);
#if (cPWR_UsePowerDownMode)
                PWR_ChangeDeepSleepMode(1);
                PWR_AllowDeviceToSleep();
                Led1On();
#else
                LED_StopFlashingAllLeds();
                Led1Flashing();
#endif
            }
            /* Node is not scanning */
            else
            {
                TMR_StopTimer(mAppTimerId);

                if (mFoundDeviceToConnect)
                {
                    App_Connect(&gConnReqParams, BleApp_ConnectionCallback);
                }
                else
                {
#if (cPWR_UsePowerDownMode)
                    Led1Off();
                    /* Go to sleep */
                    PWR_ChangeDeepSleepMode(3);
#else
                    LED_StopFlashingAllLeds();
                    Led1Flashing();
                    Led2Flashing();
                    Led3Flashing();
                    Led4Flashing();
#endif
                }
            }
        }
        break;

        case gScanCommandFailed_c:
        {
        }
    default:
      {
      shell_write("Scanning Event: ");
      shell_writeDec(pScanningEvent->eventType);
      break;
      }
    }
}

/*! *********************************************************************************
* \brief        Handles BLE Connection callback from host stack.
*
* \param[in]    peerDeviceId        Peer device ID.
* \param[in]    pConnectionEvent    Pointer to gapConnectionEvent_t.
********************************************************************************** */
static void BleApp_ConnectionCallback (deviceId_t peerDeviceId, gapConnectionEvent_t* pConnectionEvent)
{
	/* Connection Manager to handle Host Stack interactions */
	BleConnManager_GapCentralEvent(peerDeviceId, pConnectionEvent);

    switch (pConnectionEvent->eventType)
    {
        case gConnEvtConnected_c:
        {
            /* UI */
            LED_StopFlashingAllLeds();
            Led1On();
            debug_shell_write("\r\nConnected!\r\n");

            mPeerInformation.deviceId = peerDeviceId;
            mPeerInformation.isBonded = FALSE;

#if (cPWR_UsePowerDownMode)
            PWR_ChangeDeepSleepMode(1);
            PWR_AllowDeviceToSleep();
#endif

            
#if gAppUseBonding_d
            Gap_CheckIfBonded(peerDeviceId, &mPeerInformation.isBonded);

            if ((mPeerInformation.isBonded) &&
                (gBleSuccess_c == Gap_LoadCustomPeerInformation(peerDeviceId,
                    (void*) &mPeerInformation.customInfo, 0, sizeof (appCustomInfo_t))))
            {
                mRestoringBondedLink = TRUE;
                /* Restored custom connection information. Encrypt link */
                Gap_EncryptLink(peerDeviceId);
            }
#endif
            BleApp_StateMachineHandler(mPeerInformation.deviceId, mAppEvt_PeerConnected_c);
        }
        break;

        case gConnEvtDisconnected_c:
        {
            mPeerInformation.deviceId = gInvalidDeviceId_c;
            mPeerInformation.appState = mAppIdle_c;

            /* Reset Service Discovery to be sure*/
            BleServDisc_Stop(peerDeviceId);

            /* UI */
            debug_shell_write("\r\nDisconnected!\r\n");

#if (cPWR_UsePowerDownMode)
            /* Go to sleep */
            PWR_ChangeDeepSleepMode(3);
            Led1Off();
#else
            LED_TurnOffAllLeds();
            LED_StartFlash(LED_ALL);
#endif
        }
        break;

#if gAppUsePairing_d
        case gConnEvtPairingComplete_c:
        {
            if (pConnectionEvent->eventData.pairingCompleteEvent.pairingSuccessful)
            {
                BleApp_StateMachineHandler(mPeerInformation.deviceId, mAppEvt_PairingComplete_c);
            }
        }
        break;

#if gAppUseBonding_d        
        case gConnEvtEncryptionChanged_c:
        {
            if( pConnectionEvent->eventData.encryptionChangedEvent.newEncryptionState )
            {
                if( mRestoringBondedLink )
                {
                    if( gBleSuccess_c != BleApp_ConfigureNotifications() )
                    {
                        Gap_Disconnect(peerDeviceId);
                    }
                    else
                    {
                        mRestoringBondedLink = FALSE;
                    }
                }
            }
        }
        break;
        
        case gConnEvtAuthenticationRejected_c:
        {
            /* Start Pairing Procedure */
            Gap_Pair(peerDeviceId, &gPairingParameters);
        }
        break;
#endif /* gAppUseBonding_d */
#endif /* gAppUsePairing_d */

    default:
        break;
    }
}

static void BleApp_ServiceDiscoveryCallback(deviceId_t peerDeviceId, servDiscEvent_t* pEvent)
{
	switch(pEvent->eventType)
	{
		case gServiceDiscovered_c:
		{
                        debug_shell_write("\n\rService Discovered!\n");
			BleApp_StoreServiceHandles(pEvent->eventData.pService);
		}
		break;

		case gDiscoveryFinished_c:
		{
			if (pEvent->eventData.success)
			{
				BleApp_StateMachineHandler(peerDeviceId, mAppEvt_ServiceDiscoveryComplete_c);
			}
			else
			{
				BleApp_StateMachineHandler(peerDeviceId, mAppEvt_ServiceDiscoveryFailed_c);
			}
		}
		break;

		default:
		break;
	}
}

/*! *********************************************************************************
* \brief        Stores handles for the specified service.
*
* \param[in]    pService    Pointer to gattService_t.
********************************************************************************** */
static void BleApp_StoreServiceHandles
(
    gattService_t   *pService
)
{
    uint8_t i,j;

    debug_shell_write("\n\rService UUID 128: ");
    debug_shell_writeHexLe(pService->uuid.uuid128,16);
    // debug_shell_write("\n\rService UUID 16: ");
    // debug_shell_writeHexLe(&(pService->uuid.uuid16),2);
    
    /*if ((pService->uuidType == gBleUuidType16_c) &&
        FLib_MemCmp(pService->uuid.uuid128, uuid_service_temperature, 16))*/
    if ( FLib_MemCmp(pService->uuid.uuid128, uuid_service_nrfuart, 16))    
    {
        debug_shell_write("\n\r Explore Service Characteristics!");
        /* Found Temperature Service */
        // mPeerInformation.customInfo.tempClientConfig.hService = pService->startHandle;
        mPeerInformation.customInfo.nrfuartClientConfig.hService = pService->startHandle;

        for (i = 0; i < pService->cNumCharacteristics; i++)
        {            
              debug_shell_write("\n\rCharacteristic UUID 128: ");
              debug_shell_writeHexLe(pService->aCharacteristics[i].value.uuid.uuid128,16);
              // debug_shell_write("\n\rCharacteristic UUID 16: ");
              // debug_shell_writeHexLe(&(pService->aCharacteristics[i].value.uuid.uuid16),2);

                /*if ((pService->aCharacteristics[i].value.uuidType == gBleUuidType16_c) &&
                (pService->aCharacteristics[i].value.uuid.uuid16 == gBleSig_Temperature_d))*/
            if (FLib_MemCmp(pService->aCharacteristics[i].value.uuid.uuid128, uuid_characteristic_nrfuart_tx,16))
            {
              debug_shell_write("\n\rFound NRF TX! Handle: ");
              debug_shell_writeDec(pService->aCharacteristics[i].value.handle);
                /* Found Temperature Char */
                // mPeerInformation.customInfo.tempClientConfig.hTemperature = pService->aCharacteristics[i].value.handle;
                mPeerInformation.customInfo.nrfuartClientConfig.hService= pService->aCharacteristics[i].value.handle;

                for (j = 0; j < pService->aCharacteristics[i].cNumDescriptors; j++)
                {
                    if (pService->aCharacteristics[i].aDescriptors[j].uuidType == gBleUuidType16_c)
                    //if (pService->aCharacteristics[i].aDescriptors[j].uuidType == gBleUuidType128_c)
                    {  
                        switch (pService->aCharacteristics[i].aDescriptors[j].uuid.uuid16)
                        //switch (pService->aCharacteristics[i].aDescriptors[j].uuid.uuid128)
                        {
                            /*case gBleSig_CharPresFormatDescriptor_d:
                            {
                                debug_shell_write("\n\rgBleSig_CharPresFormatDescriptor_d!\n");
                                debug_shell_writeDec(pService->aCharacteristics[i].aDescriptors[j].handle);
                                mPeerInformation.customInfo.tempClientConfig.hTempDesc = pService->aCharacteristics[i].aDescriptors[j].handle;
                                break;
                            }*/
                            case gBleSig_CCCD_d:
                            {
                                debug_shell_write("\n\rgBleSig_CCCD_d: ");
                                debug_shell_writeDec(pService->aCharacteristics[i].aDescriptors[j].handle);
                                // mPeerInformation.customInfo.tempClientConfig.hTempCccd = pService->aCharacteristics[i].aDescriptors[j].handle;
                                mPeerInformation.customInfo.nrfuartClientConfig.hNrfuart = pService->aCharacteristics[i].aDescriptors[j].handle;
                                break;
                            }

                            default:
                              debug_shell_write("\n\rUnknown Characteristic Descriptor! \n");
                              debug_shell_writeDec(pService->aCharacteristics[i].aDescriptors[j].uuid.uuid16);
                            break;
                        }
                    }
                }
            }
        }
    }
}


static void BleApp_StoreDescValues
(
    gattAttribute_t     *pDesc
)
{
    debug_shell_write("\n\rBleApp_StoreDescValues \n\r");
    // if (pDesc->handle == mPeerInformation.customInfo.tempClientConfig.hTempDesc)
    if (pDesc->handle == hNrfUartTxHandle)
    {
        /* Store temperature format*/
        // FLib_MemCpy(&mPeerInformation.customInfo.tempClientConfig.tempFormat,
        FLib_MemCpy(&mPeerInformation.customInfo.nrfuartClientConfig.dataFormat,
                    pDesc->paValue,
                    pDesc->valueLength);
    }

}

/*static void BleApp_PrintTemperature
(
    uint16_t temperature
)
{
    debug_shell_write("Temperature: ");
    debug_shell_writeDec(temperature/100);
   //  if (mPeerInformation.customInfo.tempClientConfig.tempFormat.unitUuid16 == 0x272F)
    if (mPeerInformation.customInfo.nrfuartClientConfig.dataFormat.unitUuid16 == 0x272F)
    {
        debug_shell_write(" C\r\n");
    }
    else
    {
        debug_shell_write("\r\n");
    }
}*/

static void BleApp_PrintMidile
(
    uint8_t *msg,
    uint16_t msgLen
)
{
    debug_shell_write("MIDI Message: ");
    debug_shell_writeHexLe(msg,msgLen);
    debug_shell_write("\n\rRAW MIDI Message: ");
    midi_write(msg,msgLen);
}

/*! *********************************************************************************
* \brief        Handles GATT client callback from host stack.
*
* \param[in]    serverDeviceId      GATT Server device ID.
* \param[in]    procedureType    	Procedure type.
* \param[in]    procedureResult    	Procedure result.
* \param[in]    error    			Callback result.
********************************************************************************** */
static void BleApp_GattClientCallback(
    deviceId_t              serverDeviceId,
    gattProcedureType_t     procedureType,
    gattProcedureResult_t   procedureResult,
    bleResult_t             error
)
{
    if (procedureResult == gGattProcError_c)
    {
      debug_shell_write("\r\ngGattProcError_c !\n\r");
      uint8_t lattError = (uint8_t) (error & 0xFF);
      debug_shell_write("\n\r-->  GATT Event: Procedure Error ");
      debug_shell_write((char*)mGattStatus[lattError]);
      // SHELL_NEWLINE();
      
        attErrorCode_t attError = (attErrorCode_t) (error & 0xFF);
        if (attError == gAttErrCodeInsufficientEncryption_c     ||
            attError == gAttErrCodeInsufficientAuthorization_c  ||
            attError == gAttErrCodeInsufficientAuthentication_c 
            )
        {
            /* Start Pairing Procedure */
            Gap_Pair(serverDeviceId, &gPairingParameters);           
        }

        BleApp_StateMachineHandler(serverDeviceId, mAppEvt_GattProcError_c);
    }
    else if (procedureResult == gGattProcSuccess_c)
    {
        switch(procedureType)
        {
            case gGattProcExchangeMtu_c:
              {
              debug_shell_write("\r\ngGattProcExchangeMtu_c\r\n");
              // GattClient_ExchangeMtu(serverDeviceId);
              break; 
              }
            case gGattProcReadCharacteristicDescriptor_c:
            {
                if (mpCharProcBuffer != NULL)
                {
                    debug_shell_write("\r\ngGattProcReadCharacteristicDescriptor_c\r\n");
                    BleApp_StoreDescValues(mpCharProcBuffer);
                }
            break;
            }
            case gGattProcDiscoverAllCharacteristics_c: 
              {
              debug_shell_write("\r\ngGattProcDiscoverAllCharacteristics_c\r\n");
              break; 
              }
  
            case gGattProcDiscoverAllCharacteristicDescriptors_c:               
              {
              debug_shell_write("\r\ngGattProcDiscoverAllCharacteristicDescriptors_c\r\n");
              break; 
              }
           
            case gGattProcDiscoverAllPrimaryServices_c:
              {
              debug_shell_write("\r\ngGattProcDiscoverAllPrimaryServices_c\r\n");
              break; 
              }
           
            case gGattProcDiscoverPrimaryServicesByUuid_c:
            {
            debug_shell_write("\r\ngGattProcDiscoverPrimaryServicesByUuid_c\r\n");
            break;
            }

            
            case gGattProcDiscoverCharacteristicByUuid_c:
            {
            debug_shell_write("\r\ngGattProcDiscoverCharacteristicByUuid_c\r\n");
            break;
            }
            
            case gGattProcReadCharacteristicValue_c:
            {
              
                MidiLeGatt_Print(serverDeviceId);
                /*debug_shell_write("\n\r-->  GATT Event: Characteristic Value Read ");
                debug_shell_write("\n\r     Value: ");
                debug_shell_writeHexLe(mpCharBuffer->value.paValue, mpCharBuffer->value.valueLength);
                // shell_cmd_finished();
                
                // mmerlin: trigger a new read
        	BleApp_StateMachineHandler(serverDeviceId, mAppEvt_ServiceDiscoveryComplete_c);
                
                MEM_BufferFree(mpCharBuffer->value.paValue);
                MEM_BufferFree(mpCharBuffer);
                mpCharBuffer = NULL;*/
                break;
            }

            case gGattProcWriteCharacteristicValue_c:
            {
                debug_shell_write("\n\r-->  GATT Event: Characteristic Value Written!");
                break;            
            }
            
            default:
              {
              debug_shell_write("\n\rUnknown procedure: ");
              debug_shell_writeDec(procedureResult);
              break;
              }
              
        }

    	BleApp_StateMachineHandler(serverDeviceId, mAppEvt_GattProcComplete_c);
    }

    /* Signal Service Discovery Module */
    BleServDisc_SignalGattClientEvent(serverDeviceId, procedureType,procedureResult, error);

}

/*! *********************************************************************************
* \brief        Handles GATT client notification callback from host stack.
*
* \param[in]    serverDeviceId      		GATT Server device ID.
* \param[in]    characteristicValueHandle   Handle.
* \param[in]    aValue    					Pointer to value.
* \param[in]    valueLength    				Value length.
********************************************************************************** */
static void BleApp_GattNotificationCallback
(
    deviceId_t  serverDeviceId,
    uint16_t    characteristicValueHandle,
    uint8_t*    aValue,
    uint16_t    valueLength
)
{
  debug_shell_write("\r\nNotification Callback!\n\r");
  
    //if (characteristicValueHandle == mPeerInformation.customInfo.tempClientConfig.hTemperature)
    if (characteristicValueHandle == hNrfUartTxHandle)
    {
        // BleApp_PrintTemperature(*(uint16_t*)aValue);
        BleApp_PrintMidile(aValue,valueLength);

#if (cPWR_UsePowerDownMode)
        /* Restart Wait For Data timer */
        TMR_StartLowPowerTimer(mAppTimerId,
                       gTmrLowPowerSecondTimer_c,
                       TmrSeconds(gWaitForDataTime_c),
                       DisconnectTimerCallback, NULL);
#endif
    }
}

static bool_t MatchDataInAdvElementList(gapAdStructure_t *pElement, void *pData, uint8_t iDataLen)
{
    uint8_t i;

    for (i=0; i < pElement->length; i+=iDataLen)
    {
        if (FLib_MemCmp(pData, &pElement->aData[i], iDataLen))
        {
            return TRUE;
        }
    }
    return FALSE;
}

uint8_t riot_mac[] = {0xB3, 0xAF , 0x0A , 0x37 , 0x60, 0x00 };
char riot_dname[] = "PAFB3";

static bool_t CheckScanEvent(gapScannedDevice_t* pData)
{
    uint8_t index = 0;
    uint8_t name[10];
    uint8_t nameLength;
    bool_t foundMatch = FALSE;

    while (index < pData->dataLength)
    {
        gapAdStructure_t adElement;

        adElement.length = pData->data[index];
        adElement.adType = (gapAdType_t)pData->data[index + 1];
        adElement.aData = &pData->data[index + 2];

         /* Search for Temperature Custom Service */
        if ((adElement.adType == gAdIncomplete128bitServiceList_c) ||
          (adElement.adType == gAdComplete128bitServiceList_c))
        {
            //foundMatch = MatchDataInAdvElementList(&adElement, &uuid_service_temperature, 16);
        }

        if ((adElement.adType == gAdShortenedLocalName_c) ||
          (adElement.adType == gAdCompleteLocalName_c))
        {
            nameLength = MIN(adElement.length, 10);
            FLib_MemCpy(name, adElement.aData, nameLength);
            
            //mmerlin:  check MAC                
            // foundMatch = FLib_MemCmp(riot_mac, pData->aAddress, 6);
            foundMatch = FLib_MemCmp((uint8_t*)  riot_dname, name, 5);
        }

        /* Move on to the next AD elemnt type */
        index += adElement.length + sizeof(uint8_t);
    }

    if (foundMatch)
    {
        /* UI */
        debug_shell_write("\r\nFound device: \r\n");
        debug_shell_writeN((char*)name, nameLength-1);
        SHELL_NEWLINE();
        debug_shell_writeHexLe(pData->aAddress, 6);
    }
    return foundMatch;
}

void BleApp_StateMachineHandler(deviceId_t peerDeviceId, uint8_t event)
{
    switch (mPeerInformation.appState)
    {
        case mAppIdle_c:
        {
            debug_shell_write("\nState mAppIdle_c\n");

            if (event == mAppEvt_PeerConnected_c)
            {
#if gAppUseBonding_d
                if (mPeerInformation.customInfo.tempClientConfig.hTemperature != gGattDbInvalidHandle_d)
                {
                    /* Moving to Running State */
...

This file has been truncated, please download it to see its full contents.

Credits

Marco Merlin
4 projects • 9 followers
Electronics Engineer, passionate for tech and music, able to "get things done", curious and aspiring to "solve real-life problems".

Comments