Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
Revision 12:8bac5f5d3a3e, committed 2014-12-21
- Comitter:
- prussell
- Date:
- Sun Dec 21 20:44:37 2014 +0000
- Parent:
- 11:7d02fe5ebea5
- Child:
- 13:1c67c03bbf53
- Commit message:
- BLE: Buttons cause Notify, Writes set LED PWM = OK
Changed in this revision
| main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/main.cpp Sun Dec 21 16:26:46 2014 +0000
+++ b/main.cpp Sun Dec 21 20:44:37 2014 +0000
@@ -83,25 +83,23 @@
const bool bPrep = u8_prep_dummy();
//========== IO Hardware: Buttons, LEDs, PWM ==========
-// Inputs:
+// Inputs: (Simultaneous DigitalIn and InteruptIn is OK)
DigitalIn bB1in(BUTTON1); //if(bB1in){}
DigitalIn bB2in(BUTTON2); //if(bB2in){}
InterruptIn B1int(BUTTON1); //B1int.rise(&onB1rise);
InterruptIn B2int(BUTTON2); //B1int.fall(&onB1fall);
// Outputs:
-//DigitalOut bL1out(LED1); // Direct LED1 drive
-//DigitalOut bL2out(LED2); // Direct LED2 drive
-PwmOut fL1pwm(LED1); float fL1level = 0.1; // PWM LED1, brightness=float(0.0~1.0)
-PwmOut fL2pwm(LED2); float fL2level = 0.1; // PWM LED2, brightness=float(0.0~1.0)
+//a DigitalOut bL1out(LED1); // Direct LED1 drive
+//a DigitalOut bL2out(LED2); // Direct LED2 drive
+PwmOut fL1pwm(LED1); float fL1level = 0.1; // PWM LED1, brightness=float(0.0~1.0)
+PwmOut fL2pwm(LED2); float fL2level = 0.1; // PWM LED2, brightness=float(0.0~1.0)
+bool bAppControl = false; //Flag: Host has control of LEDs through BLE
-// onButton Callbacks for InterruptIn
-// *When direct driving hardware consider adjusting drive within the onCallback to reduce response time
-//TODO: Check need of volatile for changes in interrupts affecting variables in non-interrupt code?
-volatile uint8_t uB1rise; void onB1rise(void){ uB1rise++; };// Flag Event, Counter helps detect missed events since last cleared
-volatile uint8_t uB1fall; void onB1fall(void){ uB1fall++; };// Flag Event, Counter helps detect missed events since last cleared
-volatile uint8_t uB2rise; void onB2rise(void){ uB2rise++; };// Flag Event, Counter helps detect missed events since last cleared
-volatile uint8_t uB2fall; void onB2fall(void){ uB2fall++; };// Flag Event, Counter helps detect missed events since last cleared
+//a volatile uint8_t uB1rise; void onB1rise(void){ uB1rise++; };// Flag Event, Counter helps detect missed events since last cleared
+//a volatile uint8_t uB1fall; void onB1fall(void){ uB1fall++; };// Flag Event, Counter helps detect missed events since last cleared
+//a volatile uint8_t uB2rise; void onB2rise(void){ uB2rise++; };// Flag Event, Counter helps detect missed events since last cleared
+//a volatile uint8_t uB2fall; void onB2fall(void){ uB2fall++; };// Flag Event, Counter helps detect missed events since last cleared
//==========BLE==========
const static char pcDeviceName[] = "bleIOv04_pr"; //PR: Why can App nRF-MCP modify this even though flagged as Const, maybe only temporary mod till App restarts?
@@ -198,27 +196,98 @@
*/
// Characteristic Value Storage (with Initial values, should match actual data type transferred, doesn't have to be byte array):
- uint8_t pIOw8[8] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17}; //Value Storage for Characteristic Write8
- uint8_t pIOr4[4] = {0x20,0x21,0x22,0x23}; //Value Storage for Characteristic Read4
- uint8_t pIOn4[4] = {0x30,0x31,0x32,0x33}; //Value Storage for Characteristic Notify4
+ //a uint8_t pIOw8[8] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17}; //Value Storage for Characteristic Write8
+ //a uint8_t pIOr4[4] = {0x20,0x21,0x22,0x23}; //Value Storage for Characteristic Read4
+ //a uint8_t pIOn4[4] = {0x30,0x31,0x32,0x33}; //Value Storage for Characteristic Notify4
+
+ union { // Option: split long setup from short updates to minimize BLE power and traffic
+ struct {// First item in union defines the initializers
+ uint8_t L1pwm100; // LED1 Brightness (0%~100%)
+ uint8_t L2pwm255; // LED2 Brightness (0~255)
+ //float xxxx; //Option: If both smartphone and device use same type of float, else put converter in smartphone code (phone has larger battery and memory)
+ uint16_t px[3]; // Spare 3*16bit (Test: incremented by Ticker1
+ } s;
+ uint8_t pu[]; //Direct Byte access
+ char pc[]; //Character Access (No Terminating Null)
+ } sIOw8 = {100,255,0xA00A, 0xB000, 0xC000}; // Structure/union for Characteristic IOw8
+ // sIOw8.s.L1pwm100, sIOw8.s.L2pwm255, sIOw8.s.px, sIOw8.pu
+
+ union { // Longer maybe OK since only read upon command
+ struct {// First item in union defines the initializers
+ uint8_t bB1p:1,bB2p:1; // Button status, 1/true=Pressed, bit1==Button1, bit2==Button2
+ uint8_t uB1p:6; // Count Button1 Presses (6bit)
+ uint8_t uB1r; // Count Button1 Releases
+ uint8_t uB2p; // Count Button2 Presses
+ uint8_t uB2r; // Count Button2 Releases
+ // // Option: ADC or other inputs or device status
+ } s;
+ uint8_t pu[]; //Direct Byte access
+ char pc[]; //Character Access (No Terminating Null)
+ } sIOr4 = { true, false, 0x3F, 255, 255, 255}; // Structure/union for Characteristic IOr4
+ // sIOr4.s.bB1p, sIOr4.s.bB1p, sIOr4.s.uB1p, sIOr4.s.bB1r, sIOr4.s.uB2p, sIOr4.s.uB2r, sIOr4.pu
+
+ union { // Option: Shorten content to reduce BLE power and traffic
+ struct {// First item in union defines the initializers
+ uint8_t bB1p:1,bB2p:1; // Button status, 1/true=Pressed, bit1==Button1, bit2==Button2
+ uint8_t uB1p:6; // Count Button2 Presses (6bit) *Notify*
+ uint8_t uB2r; // Count Button2 Releases *Notify*
+ int16_t iTempC100; // Temperature in hundreths of 'C (i.e. float = iTempC10/100)
+ // // Option: ADC or other inputs or device status
+ } s;
+ uint8_t pu[]; //Direct Byte access
+ char pc[]; //Character Access (No Terminating Null)
+ } sIOn4 = { false, true, 0x3F, 255, -2345/*=-23.45'C*/}; // Structure/union for Characteristic IOn4
+ // sIOn4.s.bB1p, sIOn4.s.bB2p, sIOn4.s.uB1p, sIOn4.s.uB2r, sIOn4.s.iTempC100, sIOn4.pu
//x GattCharacteristic::GattAttribute *descriptors[]; //How Set Characteristic Descriptors? Maybe in the App is easier?
//IO Characteristics: //GattCharacteristics xx(*UUID, *Payload=*Value, LenInit, LenMax, Properties)
//GattCharacteristic IOw8(puUUID128_IOw8, pIOw8, sizeof(pIOw8), sizeof(pIOw8), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
- GattCharacteristic IOw8(puUUID128_IOw8, pIOw8, sizeof(pIOw8), sizeof(pIOw8), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);// Allow Host to read back last setting
- GattCharacteristic IOr4(puUUID128_IOr4, pIOr4, sizeof(pIOr4), sizeof(pIOr4), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); // Host can manually request
+ GattCharacteristic IOw8(puUUID128_IOw8, sIOw8.pu, sizeof(sIOw8), sizeof(sIOw8), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);// Allow Host to read back last setting
+ GattCharacteristic IOr4(puUUID128_IOr4, sIOr4.pu, sizeof(sIOr4), sizeof(sIOr4), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); // Host can manually request
//GattCharacteristic IOn4(puUUID128_IOn4, pIOn4, sizeof(pIOn4), sizeof(pIOn4), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
- GattCharacteristic IOn4(puUUID128_IOn4, pIOn4, sizeof(pIOn4), sizeof(pIOn4), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); // Host is notified of changes
- GattCharacteristic *pCustomCharacteristics[] = {&IOw8, &IOr4, &IOn4};//Table of Pointers to Characteristics
+ GattCharacteristic IOn4(puUUID128_IOn4, sIOn4.pu, sizeof(sIOn4), sizeof(sIOn4), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); // Host is notified of changes
+ GattCharacteristic *pCustomCharacteristics[] = {&IOw8, &IOr4, &IOn4};//Table of Pointers to GattCharacteristics
//IO Service: //GattService::GattService(*UUID, *GattCharacteristics, (numCharacteristics) ) :
GattService ServiceIO(puUUID128_IOService, pCustomCharacteristics, (sizeof(pCustomCharacteristics)/sizeof(pCustomCharacteristics[0])));
GattService *pServiceIO= &ServiceIO; // Pointer to Service
-//a Option: Allow device to modify its settings and inform host (Some devices may be able to self-modify host written settings)
+//========== Functions for IO Characteristics ========
+void vShowIO(void)
+{ //TODO: For Read Characteristics get data actually written to Characteristic, versus the memory expected to be in characteristic.
+ uint8_t puBuf8[8];
+ uint16_t uLen;
+
+ DEBUG(" ShowIO:\n");
+
+ // IOw8 Write
+ DEBUG(" sIOw8: Handle:%d Len:%d L1:%d L2:%d %04X %04X %04X\n", IOw8.getValueHandle(), uLen, sIOw8.s.L1pwm100, sIOw8.s.L2pwm255, sIOw8.s.px[0], sIOw8.s.px[0], sIOw8.s.px[0]);
+ //DEBUG(" pIOw8: Handle:%d Len:%d [%02X %02X %02X %02X %02X %02X %02X %02X]\n", IOw8.getValueHandle(), sizeof(pIOw8), pIOw8[0], pIOw8[1], pIOw8[2], pIOw8[3],pIOw8[4], pIOw8[5], pIOw8[6], pIOw8[7]);
+ DEBUG(" sIOw8: Handle:%d Len:%d [%02X %02X %02X %02X %02X %02X %02X %02X]\n", IOw8.getValueHandle(), sizeof(sIOw8), sIOw8.pu[0],sIOw8.pu[1],sIOw8.pu[2],sIOw8.pu[3],sIOw8.pu[4],sIOw8.pu[5],sIOw8.pu[6],sIOw8.pu[7]);
+ uLen=sizeof(puBuf8); ble.readCharacteristicValue(IOw8.getValueHandle(), puBuf8, &uLen); // Real Characteristic's Actual Value
+ DEBUG(" cIOw8: Handle:%d Len:%d [%02X %02X %02X %02X %02X %02X %02X %02X]\n", IOw8.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3], puBuf8[4], puBuf8[5], puBuf8[6], puBuf8[7] );
+
+ // IOr4 Read
+ DEBUG("\n sIOr4: Handle:%d Len:%d B1:%d B2:%d B1p:%d B1r:%d B2p:%d B2r:%d\n", IOr4.getValueHandle(), uLen, sIOr4.s.bB1p, sIOr4.s.bB2p, sIOr4.s.uB1p, sIOr4.s.uB1r, sIOr4.s.uB2p, sIOr4.s.uB2r);
+ //DEBUG(" pIOr4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOr4.getValueHandle(), sizeof(pIOr4), pIOr4[0], pIOr4[1], pIOr4[2], pIOr4[3]);
+ //DEBUG(" sIOr4: Handle:%d Len:%d [%02X %02X %02X %02X][%.4s]\n", IOr4.getValueHandle(), sizeof(sIOr4), sIOr4.pu[0], sIOr4.pu[1], sIOr4.pu[2], sIOr4.pu[3], sIOr4.pc );
+ DEBUG(" sIOr4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOr4.getValueHandle(), sizeof(sIOr4), sIOr4.pu[0], sIOr4.pu[1], sIOr4.pu[2], sIOr4.pu[3]);
+ // Read Actual IOr4 Characteristic's data back from Service (i.e. last written to service):
+ uLen=sizeof(puBuf8); ble.readCharacteristicValue(IOr4.getValueHandle(), puBuf8, &uLen); // Real Characteristic's Actual Value
+ DEBUG(" cIOr4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOr4.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3] );
+
+ // IOn4 Notify
+ DEBUG("\n sIOn4: Handle:%d Len:%d B1:%d B2:%d B1p:%d B2r:%d %.2f\n", IOn4.getValueHandle(), uLen, sIOn4.s.bB1p, sIOn4.s.bB2p, sIOn4.s.uB1p, sIOn4.s.uB2r, ((float)sIOn4.s.iTempC100/100.0));
+ //DEBUG("\n pIOn4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOn4.getValueHandle(), sizeof(pIOn4), pIOn4[0], pIOn4[1], pIOn4[2], pIOn4[3]);
+ DEBUG(" sIOn4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOn4.getValueHandle(), sizeof(sIOn4), sIOn4.pu[0], sIOn4.pu[1], sIOn4.pu[2], sIOn4.pu[3]);
+ uLen=sizeof(puBuf8); ble.readCharacteristicValue(IOn4.getValueHandle(), puBuf8, &uLen); // Real Characteristic's Actual Value
+ DEBUG(" cIOn4: Handle:%d Len:%d [%02X %02X %02X %02X]\n", IOn4.getValueHandle(), uLen, puBuf8[0], puBuf8[1], puBuf8[2], puBuf8[3] );
+}
+
+//==== Soft Updates to Characteristics for initial tests: (Most replaced by real buttons/sensors/timers )
/*void vUpdate_IOw8(void) // Handle in device changes to w8 characteristic
-{
+{//a Option: Allow device to modify its settings and inform host (Some devices may be able to self-modify host written settings)
static uint8_t uw8; //Level: 0..2
switch(++uw8){
case 2: memcpy(pIOw8, "w2w2w2wc", sizeof(pIOw8)); DEBUG(" w8c"); break;
@@ -228,34 +297,72 @@
//ble.updateCharacteristicValue(uint16_t handle, const uint8_t *value, uint16_t size, bool localOnly)
ble.updateCharacteristicValue(IOw8.getValueHandle(), pIOw8, sizeof(pIOw8));
//pServiceHRM->updateHeartRate( u8_hrm );// Update Characteristic so sent by BLE
+ vShowIO();
}*/
-void vUpdate_IOr4(void) // Handle device updates r4 characteristics (Without Notify, Host must poll for these)
-{ // For out project this would be: Temperature, Version Info, etc.
- static uint8_t ur4; //Level: 0..2
- switch(++ur4){
- case 2: memcpy(pIOr4, "r2r2", sizeof(pIOr4)); DEBUG(" r4c"); break;
- case 1: memcpy(pIOr4, "r1r1", sizeof(pIOr4)); DEBUG(" r4b"); break;
- default: ur4=0; memcpy(pIOr4, "r0r0", sizeof(pIOr4)); DEBUG(" r4a"); break;
- }
- ble.updateCharacteristicValue(IOr4.getValueHandle(), pIOr4, sizeof(pIOr4));
+//==== Hard Updates to Characteristics: [onButton()] Notify: B1press or B2release
+// *When direct driving hardware consider adjusting drive within the onCallback to reduce response time
+//TODO: Check need of volatile for changes in interrupts affecting variables in non-interrupt code?
+
+volatile uint8_t uB1press; // Events since last handled in main()
+volatile uint8_t uB1release;// Events since last handled in main()
+volatile uint8_t uB2press; // Events since last handled in main()
+volatile uint8_t uB2release;// Events since last handled in main()
+
+void vFillIO(void) // Fill the structures for the Characteristics, but leave any Notify to calling function
+{ //Structures are filled completely so available for BLE read at any time
+ // sIOr4.s.bB1p, sIOr4.s.bB1p, sIOr4.s.uB1p, sIOr4.s.bB1r, sIOr4.s.uB2p, sIOr4.s.uB2r, sIOr4.pu
+ sIOr4.s.bB1p = !bB1in; //Button1 Pressed (nRF51822 mkit: Pressed=Lo)
+ sIOr4.s.bB2p = !bB2in; //Button2 Pressed (nRF51822 mkit: Pressed=Lo)
+ sIOr4.s.uB1p = uB1press;// Button1 Presses (Truncates to size)
+ sIOr4.s.uB1r = uB1release;
+ sIOr4.s.uB2p = uB2press;
+ sIOr4.s.uB2r = uB2release;
+
+ // sIOn4.s.bB1p, sIOn4.s.bB2p, sIOn4.s.uB1p, sIOn4.s.uB2r, sIOn4.s.iTempC100, sIOn4.pu
+ sIOn4.s.bB1p = !bB1in; //Button1 Pressed (nRF51822 mkit: Pressed=Lo)
+ sIOn4.s.bB2p = !bB2in; //Button2 Pressed (nRF51822 mkit: Pressed=Lo)
+ sIOn4.s.uB1p = uB1press;//Button1 Presses (Truncates to size)
+ sIOn4.s.uB2r = uB2release;
+
+ int32_t i32_C_nRF; sd_temp_get(&i32_C_nRF); //Read the nRF Internal Temperature (Die in 0.25'C steps, offset +16'C)
+ sIOn4.s.iTempC100 = (i32_C_nRF*25)-(1600); //Save temperature in hundreths (0.01'C steps relative to 0'C)(.25'C * 25=.01'C steps)
+ //float fTemperature = (float(i32_temp)/4.0) - 16.0; // Scale&Shift (0.25'C from -16'C?)
}
-void vUpdate_IOn4(void) // Handle device updates n4 characteristics (With notify)
-{ // For our Device this would be: Dispenser count changes, Button Activity, Empty warning, Timeouts, etc.
- static uint8_t un4; //Level: 0..2
- switch(++un4){
- case 2: memcpy(pIOn4, "n2n2", sizeof(pIOr4)); DEBUG(" n4c"); break;
- case 1: memcpy(pIOn4, "n1n1", sizeof(pIOr4)); DEBUG(" n4b"); break;
- default: un4=0; memcpy(pIOn4, "n0n0", sizeof(pIOr4)); DEBUG(" n4a"); break;
- }
- ble.updateCharacteristicValue(IOn4.getValueHandle(), pIOn4, sizeof(pIOn4));
-}
+void onB1press(void) // B1 Press == *Notify*
+{ // Update Characteristics that include this button
+ uB1press++; // Flag/Count Events (allows detect any missed processing)
+ vFillIO(); // Prepare IO Characteristic data
+ ble.updateCharacteristicValue(IOn4.getValueHandle(), sIOn4.pu, sizeof(sIOn4));// Notify
+ DEBUG("\n B1p%d", uB1press); vShowIO();
+};
+void onB1release(void) // B1 Release
+{ // Update Characteristics that include this button
+ uB1release++; // Flag/Count Events (allows detect any missed processing)
+ vFillIO(); // Prepare IO Characteristic data
+ ble.updateCharacteristicValue(IOr4.getValueHandle(), sIOr4.pu, sizeof(sIOr4));
+ DEBUG("\n B1r%d", uB1release); vShowIO();
+};
+void onB2press(void) // B2 Press
+{ // Update Characteristics that include this button
+ uB2press++; // Flag/Count Events (allows detect any missed processing)
+ vFillIO(); // Prepare IO Characteristic data
+ ble.updateCharacteristicValue(IOr4.getValueHandle(), sIOr4.pu, sizeof(sIOr4));
+ DEBUG("\n B2p%d", uB2press); vShowIO();
+};
+void onB2release(void) // B2 Release
+{ // Update Characteristics that include this button
+ uB2release++; // Flag/Count Events (allows detect any missed processing)
+ vFillIO(); // Prepare IO Characteristic data
+ ble.updateCharacteristicValue(IOn4.getValueHandle(), sIOn4.pu, sizeof(sIOn4));// Notify
+ DEBUG("\n B2r%d", uB2release); vShowIO();
+};
//==========Functions:BLE==========
void Callback_BLE_onTimeout(void)
{ //PR: Haven't seen this, even when phone moved out of range and events occur like OnDisconnect(Reason0x08) or LinkLoss
- DEBUG("\nBLEi: Callback_BLE_onTimeout()\n" );
+ DEBUG("\n\n\n\n**** BLEi: Callback_BLE_onTimeout() ****\n\n\n\n" );
//DEBUG("\nBLE:Callback_BLE_onTimeout(), Restarting Advertising\n" );
//ble.startAdvertising();
@@ -296,14 +403,13 @@
//x #endif // #if UPDATE_PARAMS_FOR_LONGER_CONNECTION_INTERVAL
}
-static volatile bool bSent = false; //Volatile, don't optimize, changes under interrupt control
-static volatile unsigned uSentBLE;
-void Callback_BLE_onDataSent(unsigned uSent){
- uSentBLE=uSent;
- DEBUG("BLEi: SentI(%u)", uSentBLE); //TODO: PR: Why uSent always "1", expected it to match sent bytes length
- bSent = true;
- //FYI: App nRF-MCP doesn't cause onDataSent(), while App nRF-ToolBox:HRM does cause onDataSent()
- //TBD: onDataSent() maybe only occuring when confirmed receive by phone, as onDataSent() didn't happen when phone moved out of range.
+static volatile bool bNotifySent = false; //Volatile, don't optimize, changes under interrupt control
+static volatile unsigned uNotifyBLE;
+void Callback_BLE_onNotifySent(unsigned uNotify) //TODO: Consider renaming to onNotifySent(uNotified)
+{ // Appears to get called when a Characteristic flagged for Notify is Updated/Sent (not for a characteristic being Read by the app).
+ uNotifyBLE=uNotify;
+ DEBUG(" Senti(%u)", uNotifyBLE); //TODO: PR: Why uSent always "1", expected it to match sent bytes length
+ bNotifySent = true;
}
void Callback_BLE_onDataWritten(const GattCharacteristicWriteCBParams *pParams)
@@ -336,9 +442,16 @@
} else {
uint16_t uLen;
if (tHandle == IOw8.getValueHandle()) { // This occurs from Write by App nRF-MCP since has Write Property set
- ble.readCharacteristicValue(tHandle, pIOw8, &uLen);
- DEBUG(" IOw8[%d]:%02X %02X %02X %02X %02X %02X %02X %02X\n", uLen, pIOw8[0], pIOw8[1], pIOw8[2], pIOw8[3],pIOw8[4], pIOw8[5], pIOw8[6], pIOw8[7]);
+ ble.readCharacteristicValue(tHandle, sIOw8.pu, &uLen); //Update Characteristic with new information (Option: Verify length or a checksum first)
+ vShowIO();
+
+ bAppControl = true; //Host has taken control of LEDs
+ fL1level = (((float)sIOw8.s.L1pwm100)/100.0); if(fL1level>1.0){fL1level=1.0;}; fL1pwm=fL1level; //Set LED1 Level
+ fL2level = (((float)sIOw8.s.L2pwm255)/255.0); if(fL2level>1.0){fL2level=1.0;}; fL2pwm=fL2level; //Set LED1 Level
+ DEBUG(" L1:%d==%f L2:%d==%f\n", sIOw8.s.L1pwm100, fL1level, sIOw8.s.L2pwm255, fL2level);
+
//TODO: Update Outputs and settings: Direct LED Control or Output Control, Or Configuration (Includes flags for: Factory Reset, Enter Test Mode, Enter Demo Mode)
+
//} else if (tHandle == IOr4.getValueHandle()) { // Readonly, shouldn't occur
// ble.readCharacteristicValue(tHandle, pIOr4, &uLen);
// DEBUG(" IOr4[%d]:%02X %02X %02X %02X\n", uLen, pIOr4[0], pIOr4[1], pIOr4[2], pIOr4[3]);
@@ -358,19 +471,19 @@
//x Alert=1: Debug=BLEi: Callback_BLE_onDataWritten(Handle:12, eOp:1, uOffset:0 uLen:1 Data0[0x01]=Data[])
//x Alert=2: Debug=BLEi: Callback_BLE_onDataWritten(Handle:12, eOp:1, uOffset:0 uLen:1 Data0[0x02]=Data[])
- //Characteristic Status:
- DEBUG(" IOw8: Handle:%d Len:%d Initial:[%02X %02X %02X %02X %02X %02X %02X %02X]\n", IOw8.getValueHandle(), sizeof(pIOw8), pIOw8[0], pIOw8[1], pIOw8[2], pIOw8[3],pIOw8[4], pIOw8[5], pIOw8[6], pIOw8[7]);
- DEBUG(" IOr4: Handle:%d Len:%d Initial:[%02X %02X %02X %02X]\n", IOr4.getValueHandle(), sizeof(pIOr4), pIOr4[0], pIOr4[1], pIOr4[2], pIOr4[3]);
- DEBUG(" IOn4: Handle:%d Len:%d Initial:[%02X %02X %02X %02X]\n", IOn4.getValueHandle(), sizeof(pIOn4), pIOn4[0], pIOn4[1], pIOn4[2], pIOn4[3]);
+ //vShowIO(); //Show IO Characteristic Status
}
void Callback_BLE_onUpdatesEnabled(Gap::Handle_t tHandle)
{ //Triggered when click the UpdateContinuousIcon in nRF-MCP(ThreeDownArrows)
- if (tHandle == IOn4.getValueHandle()) { DEBUG(" onUpdates(Handle:%d) Enabled - IOn4\n", tHandle); //This Occurs when selected by App nRF-MCP as has Notify property set
+ if (tHandle == IOn4.getValueHandle()) { DEBUG("\nBLEi: onUpdates(Handle:%d) Enabled - IOn4\n", tHandle); //This Occurs when selected by App nRF-MCP as has Notify property set
//} else if (tHandle == IOr4.getValueHandle()) { DEBUG(" onUpdates(Handle:%d) Enabled - IOr4\n", tHandle); // Notify not enabled on this Characteristic
//} else if (tHandle == IOw8.getValueHandle()) { DEBUG(" onUpdates(Handle:%d) Enabled - IOw8\n", tHandle); // Notify not enabled on this Characteristic
- } else { DEBUG(" onUpdates(Handle:%d) Enabled - Characteristic?\n", tHandle);
+ } else { DEBUG("\nBLEi: onUpdates(Handle:%d) Enabled - Characteristic?\n", tHandle);
}
+
+
+
}
// Adopted 20141213 from http://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LinkLoss/file/440ee5e8595f/main.cpp
@@ -403,7 +516,7 @@
{
//static float fTemperature = 0;//-123.456;
int32_t i32_temp;
- sd_temp_get(&i32_temp); //Read the nRF Internal Temperature (Die in 0.25'C steps, Counting From TBD), TODO:Check Scaling
+ sd_temp_get(&i32_temp); //Read the nRF Internal Temperature (Die in 0.25'C steps, Offset:TBD), TODO:Check Scaling
float fTemperature = (float(i32_temp)/4.0) - 16.0; // Scale&Shift (0.25'C from -16'C?)
//{//Force to IEEE format to match needs of Apps like nRF-HTM and nRF-Toolbox:HTM
@@ -434,36 +547,39 @@
{
static uint32_t u32_Counter; // Counter for checking Timing
DEBUG("\nBLEi: Ticker(%04u) ", ++u32_Counter);
- fL1level+=0.1; if (fL1level>0.5){fL1level = 0.1;}; fL1pwm=fL1level;//PR: Ramp Blink
+ if (!bAppControl) { fL1level+=0.1; if (fL1level>0.5){fL1level = 0.1;}; fL1pwm=fL1level;}//If host not controlling LED then ramp blink to show life
uTicker1++; // Flag event, using counter so can detect missed events
}
//==========main==========
int main(void)
-{
+{
+ vShowIO();
+
fL1level = 1; fL1pwm = fL1level;//Start LED1=OnMax
fL2level = 1; fL2pwm = fL2level;//Start LED2=OnMax
//Restart TeraTerm just before Pressing Reset on mbed, 9600-8N1(No Flow Control)
DEBUG("\nBLE: ___%s___\n", pcDeviceName);
- DEBUG(" Built:[ %s %s ] Compiler:[ %s ]\n", __DATE__, __TIME__, __VERSION__);
+ DEBUG(" Built UTC:[ %s %s ] Compiler:[ %s ]\n", __DATE__, __TIME__, __VERSION__);
DEBUG("BLE: Connect App for Data: nRF-MCP, nRF-Toolbox:HRM/HTM, Android Sample BluetoothLeGatt, etc.\n");
DEBUG("BLE: BluetoothLeGatt: App->mbed: LinkLoss->AlertLevel(UpArrow)\n");
DEBUG("BLE: BluetoothLeGatt: App->mbed: BatteryService->BatteryLevel(DownArrow)\n");
DEBUG("BLE: BluetoothLeGatt: mbed->App: BatteryService->BatteryLevel->EnableNotify(ThreeDownArrows), Also App Acks the send=DEBUG('SentI')\n");
Ticker ticker1; //PR: Timer Object(Structure)
- ticker1.attach(CallbackTicker1, 2.0); //PR: Timer Handler, Float=PeriodSeconds
+ ticker1.attach(CallbackTicker1, 5.0); //PR: Timer Handler, Float=PeriodSeconds (Note BLE default wakes about 50Hz/20msec)
//BLE1: Setup BLE Service (and event actions) //TODO: Check for services declared before main() - Is that OK?
DEBUG("BLE: Setup BLE\n");
ble.init();
- ble.onDisconnection(Callback_BLE_onDisconnect);
- ble.onConnection(Callback_BLE_onConnect); //PR: Not required if no actions enabled, enabled now just for debug printf()
- ble.onDataSent(Callback_BLE_onDataSent);
- ble.onDataWritten(Callback_BLE_onDataWritten);
- ble.onTimeout(Callback_BLE_onTimeout);
- ble.onUpdatesEnabled(Callback_BLE_onUpdatesEnabled);
+ ble.onDisconnection(Callback_BLE_onDisconnect); //PR: Host disconnects, restart advertising, clear any unnecessary functions to save power
+ ble.onConnection(Callback_BLE_onConnect); //PR: Host connects (Not required if no actions enabled, enabled now just for debug)
+ ble.onDataSent(Callback_BLE_onNotifySent); //PR: Occurs when a Notify Characteristic has been updated and sent over BLE
+ ble.onDataWritten(Callback_BLE_onDataWritten); //PR: Occurs when an update to a Characteristic has been received over BLE
+ ble.onTimeout(Callback_BLE_onTimeout); //PR: ??? Hasn't occured, TODO: Monitor and find out what causes this
+ ble.onUpdatesEnabled(Callback_BLE_onUpdatesEnabled);//PR: Occurs when host enables notify on a Characteristic that has Notify property set
+ //ble.onDataRead(Callback_BLE_onDataRead) //TODO: Need a callback for when reading data so can ensure characteristic is fully up to data before it is passed back (For now update periodically)
//BLE2: Setup Services (with their initial values and options)
DEBUG("BLE: Setup Services\n");
@@ -481,12 +597,10 @@
//UARTService ServiceUART(ble);
// pServiceUART = &ServiceUART;
- //Start CustomIO Service:
+ DEBUG("BLE: Setup Custom IO Service\n");
ble.addService(ServiceIO); //Pointer: pServiceIO
- DEBUG(" IOw8: Handle:%d Len:%d Initial:[%02X %02X %02X %02X %02X %02X %02X %02X]\n", IOw8.getValueHandle(), sizeof(pIOw8), pIOw8[0], pIOw8[1], pIOw8[2], pIOw8[3],pIOw8[4], pIOw8[5], pIOw8[6], pIOw8[7]);
- DEBUG(" IOr4: Handle:%d Len:%d Initial:[%02X %02X %02X %02X]\n", IOr4.getValueHandle(), sizeof(pIOr4), pIOr4[0], pIOr4[1], pIOr4[2], pIOr4[3]);
- DEBUG(" IOn4: Handle:%d Len:%d Initial:[%02X %02X %02X %02X]\n", IOn4.getValueHandle(), sizeof(pIOn4), pIOn4[0], pIOn4[1], pIOn4[2], pIOn4[3]);
- //TODO: Ensure outputs in correct Initial state
+ vShowIO();
+ //TODO: Ensure outputs in correct Initial state
//BLE3: Setup advertising
// Note: the Advertising payload is limited to 31bytes, so careful don't overflow this. Multiple UUID16's or a single UUID128 are possible in advertising.
@@ -519,12 +633,12 @@
// = Len07 Type02 Value 0918 0A18 0D18 (UUID16: 1809 180A 180D )
// = LocalName field wasn't appended as insufficient space, so Device won't be named when scanning.
- // Setup InterruptIn for Buttons
+ // Setup InterruptIn for Buttons (coded for nRF51822-mkit polarities on these buttons)
DEBUG("BLE: Enable Button Interrupts\n");
- B1int.fall(&onB1fall);// Button1 Press
- B1int.rise(&onB1rise);// Button1 Release
- B2int.fall(&onB2fall);// Button2 Press
- B2int.rise(&onB2rise);// Button2 Release
+ B1int.fall(&onB1press); // Button1 Press/fall
+ B1int.rise(&onB1release); // Button1 Release/rise
+ B2int.fall(&onB2press); // Button2 Press/fall
+ B2int.rise(&onB2release); // Button2 Release/rise
DEBUG("BLE: Main Loop\n");
uint32_t u32_wakeevents=0, u32_wakelast=0; // Counter&Register for tracking Wake Events (to see monitor their Frequency)
@@ -541,23 +655,23 @@
update_batt();
//a vUpdate_IOw8();
- vUpdate_IOr4();
- vUpdate_IOn4();
+ //a vUpdate_IOr4();
+ //a vUpdate_IOn4();
- DEBUG(" BLE:Wakes:%u,Delta:%u ", u32_wakeevents, u32_wakeevents-u32_wakelast); //For Evaluating Timing
+ DEBUG(" BLE:Wakes:%04u,Delta:%03u ", u32_wakeevents, u32_wakeevents-u32_wakelast); //For Evaluating Timing
u32_wakelast = u32_wakeevents;
} else if (uTicker1) {
uTicker1 = 0; // Clear flag for next Ticker1, see CallbackTicker1(), TODO: log if missed any ticks
- DEBUG("BLE: Tick while unconnected ");
- } else if (bSent){
- bSent=false; //clear flag
- //DEBUG("BLE: Sent %ubytes ", uSentBLE);
+ DEBUG(" BLE: Tick while unconnected ");
+ } else if (bNotifySent){
+ bNotifySent=false; //clear flag Notify Characteristic Transmitted
+ DEBUG(" BLE: Notify(%u) ", uNotifyBLE);
} else {
//DEBUG("BLE: Wait for Event\n\r"); //x Debug output here causes endless wakes from sleep()
- ble.waitForEvent(); //PR: Like sleep() with ble handling. TODO: Handle Error return
- fL2level+=0.25; if (fL2level>0.5){fL2level = 0.0;}; fL2pwm=fL2level;//PR: Ramp Blink
+ ble.waitForEvent(); //PR: Like sleep() with ble handling. TODO: Handle Error return
u32_wakeevents++; //PR: Count events for frequency monitoring (20141207PR: nRF51822 mbed HRM = 50Hz)
- }
+ if (!bAppControl) { fL2level+=0.25; if (fL2level>0.5){fL2level = 0.0;}; fL2pwm=fL2level;} //If host not controling LED then Ramp Blink to show life
+ }
}
}
//========== end of main.cpp ==========