chirimenBLE for TY51822

Dependencies:   mbed BLE_API nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Chirimen BLE farmware
00003  * copylight KDDI Technorogy
00004  *
00005  * change log
00006  * 2018/11/28 初回リリース
00007  * 2018/12/03 GPIO端子の初期値不定を修正
00008  * 2018/12/19 GPIO ドライブ能力変更 (0.5mA -> 5mA)
00009  * 2018/12/20 nRF51ライブラリのバグ対策 -- RTS/CTSの割り当て禁止
00010  *            送信出力を +4dBmに規定
00011  */
00012 
00013 
00014 #include "mbed.h"
00015 #include "BLE.h"
00016 
00017 #include "board.h"
00018 
00019 #define VERSION_NUM 1 // 2018-11-28
00020 const static char  DEVICE_NAME[] = "btGPIO2";
00021 
00022 #define NEED_CONSOLE_OUTPUT 1 
00023 /* Set this if you need debug messages on the console;
00024  * it will have an impact on code-size and power consumption. */
00025 
00026 #if NEED_CONSOLE_OUTPUT
00027 Serial  pc(DBG_TX, DBG_RX); // TX,RX default 9600bps
00028 #define DEBUG(...) { pc.printf(__VA_ARGS__); }
00029 #else
00030 #define DEBUG(...) /* nothing */
00031 #endif /* #if NEED_CONSOLE_OUTPUT */
00032 
00033 #ifdef MICROBIT
00034 // micro:bit matrix-led
00035 DigitalOut col0(P0_4, 0);
00036 #endif
00037 DigitalOut LED_CONNECT(GPIO_LED_CONNECT);
00038 
00039 #define CMD_EXPORT      0x10
00040 #define CMD_GPIO_WRITE  0x11
00041 #define CMD_GPIO_READ   0x12
00042 #define CMD_UNEXPORT    0x13
00043 #define CMD_GPIO_EVENT  0x14
00044 #define CMD_I2C_INIT    0x20
00045 #define CMD_I2C_WRITE   0x21
00046 #define CMD_I2C_RDBYTE  0x22
00047 #define CMD_I2C_READ    0x23
00048 #define CMD_ADC_INPUT   0x30
00049 #define CMD_ADC_READ    0x31
00050 
00051 // Bluetooth Low Energy
00052 BLE ble;
00053 static Gap::ConnectionParams_t connectionParams;
00054 
00055 // I2C 2-waire
00056 I2C i2c(I2C_SDA,I2C_SCL);
00057 #define MAX_I2C_TRANSFAR_SIZE 10
00058 
00059 // Timer
00060 Ticker timerTask;
00061 
00062 /*
00063  * gpio bridge used UUID
00064  * ServiceUUID:    928a3d40-e8bf-4b2b-b443-66d2569aed50
00065  * NotifyDataUUID: 928a3d41-e8bf-4b2b-b443-66d2569aed50
00066  * WriteDataUUID:  928a3d42-e8bf-4b2b-b443-66d2569aed50
00067  */
00068 static const uint8_t UUID_GPIO_SERVICE[]  = {0x92,0x8a,0x3d,0x40,0xe8,0xbf,0x4b,0x2b,0xb4,0x43,0x66,0xd2,0x56,0x9a,0xed,0x50};
00069 static const uint8_t UUID_ADV_SERVICE[]   = {0x50,0xed,0x9a,0x56,0xd2,0x66,0x43,0xb4,0x2b,0x4b,0xbf,0xe8,0x40,0x3d,0x8a,0x92};
00070 static const uint8_t UUID_NOTIFY_DATA[]   = {0x92,0x8a,0x3d,0x41,0xe8,0xbf,0x4b,0x2b,0xb4,0x43,0x66,0xd2,0x56,0x9a,0xed,0x50};
00071 static const uint8_t UUID_WRITE_DATA[]    = {0x92,0x8a,0x3d,0x42,0xe8,0xbf,0x4b,0x2b,0xb4,0x43,0x66,0xd2,0x56,0x9a,0xed,0x50};
00072 static const uint8_t UUID_STAT_DATA[]     = {0x92,0x8a,0x3d,0x43,0xe8,0xbf,0x4b,0x2b,0xb4,0x43,0x66,0xd2,0x56,0x9a,0xed,0x50};
00073 
00074 uint8_t wrtData[20] = {0,};
00075 GattCharacteristic  gWrtCharacteristic (UUID_WRITE_DATA, wrtData, sizeof(wrtData), sizeof(wrtData),
00076         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
00077 
00078 uint8_t notifyData[20] = {0,};
00079 GattCharacteristic  gNotifyCharacteristic (UUID_NOTIFY_DATA, notifyData, sizeof(notifyData), sizeof(notifyData),
00080         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
00081 
00082 uint8_t statData[20] = {0,0};
00083 GattCharacteristic  gStatCharacteristic (UUID_STAT_DATA, statData, sizeof(statData), sizeof(statData),
00084         GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
00085 
00086 GattCharacteristic *gGpioChars[] = {&gNotifyCharacteristic,&gWrtCharacteristic,&gStatCharacteristic};
00087 GattService gGpioService = GattService(UUID_GPIO_SERVICE, gGpioChars, sizeof(gGpioChars) / sizeof(GattCharacteristic *));
00088 
00089 int gConnect = 0;
00090 
00091 int gCmdLen = 0;
00092 uint8_t gCmdData[20] = {0,};
00093 
00094 int gNotifyLen = 0;
00095 uint8_t gNotifyData[6] = {0x2,0x0,0x0,0x14,0,0};
00096 int gScanGPIO = 0;
00097 
00098 /* ----GPIO Task----------------------------------------------------------------------- */
00099 void gpioTask() {
00100             
00101 //    LED_CONNECT = !LED_CONNECT;
00102     
00103     if (gNotifyLen >0) {  // busy
00104         return;
00105     }
00106 
00107     for (int i=0; i<sizeof(validGpioPins); i++) {
00108         if (eventGpioPins[gScanGPIO] != 0) { // is event pins
00109             uint8_t rdGpio = gports[gScanGPIO];
00110             if ( currentGpioLevel[gScanGPIO] != rdGpio) {
00111                 DEBUG("GPIO status chenged port%d:%d\r\n",validGpioPins[gScanGPIO],rdGpio);
00112                 currentGpioLevel[gScanGPIO] = rdGpio;
00113                 gNotifyData[4] = gScanGPIO;
00114                 gNotifyData[5] = rdGpio;
00115                 gNotifyLen = 6;
00116                 continue;
00117             }
00118         }
00119         gScanGPIO++;
00120         if (gScanGPIO > sizeof(validGpioPins)) {
00121             gScanGPIO = 0;
00122         }
00123     }
00124 }
00125 
00126 void reloadGpioCondition() {
00127     for (int i=0; i<sizeof(validGpioPins); i++) {
00128         if (eventGpioPins[i] != 0) { // is event pins
00129             uint8_t rdGpio = gports[i];
00130             currentGpioLevel[i] = rdGpio;
00131         }
00132     }
00133 }
00134 
00135 void clearEventLists() {
00136     for (int i=0; i<sizeof(validGpioPins); i++) {
00137         eventGpioPins[i] = 0;
00138     }
00139 }
00140 
00141 void initGpio() {
00142     for (int i=0; i<sizeof(validGpioPins); i++) {
00143         int gpioNum = validGpioPins[i];
00144         DEBUG("initGpio() 0x%x\r\n", gpioNum);
00145         gports[gpioNum].input();        // 端子を入力モード
00146         gports[gpioNum].mode(PullNone); // pullアップ/ダウンなし
00147         eventGpioPins[gpioNum] = 0;     // イベント監視対象外
00148         reloadGpioCondition(); // 設定を更新
00149     }
00150     
00151     // nRF51ライブラリのバグ対策 -- RTS/CTSの割り当て禁止
00152     NRF_UART0->PSELRTS = 0xFFFFFFFF;
00153     NRF_UART0->PSELCTS = 0xFFFFFFFF;
00154 }
00155 
00156 // set high drive (Low/High 5mA)
00157 void hiDriveGpio(int gpioNum) {
00158     NRF_GPIO->PIN_CNF[gpioNum] =
00159         (NRF_GPIO->PIN_CNF[gpioNum] & ~GPIO_PIN_CNF_DRIVE_Msk) |
00160         (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos);
00161 }
00162 /* --- BLE callbacks ------------------------------------------------------------------- */
00163 void onDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)    // Mod
00164 {
00165     DEBUG("Disconnected handle %u, reason %u\r\n", params->handle, params->reason);
00166     DEBUG("Restarting the advertising process\r\n");
00167     DEBUG("Disconnected!\n\r");
00168     timerTask.detach(); // stop timer
00169     gConnect = 0;
00170     clearEventLists();
00171     
00172     LED_CONNECT = 0;
00173     ble.startAdvertising();
00174 }
00175 
00176 #define BLE_INTERVAL_10MS   8
00177 #define BLE_INTERVAL_12MS   10
00178 #define BLE_INTERVAL_20MS   15
00179 #define BLE_INTERVAL_30MS   23
00180 #define BLE_INTERVAL_50MS   39
00181 #define BLE_INTERVAL_62MS   50
00182 #define BLE_INTERVAL_100MS  78
00183 #define BLE_INTERVAL_125MS  100
00184 
00185 void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params)   //Mod
00186 {
00187     DEBUG("Connected!\n\r");
00188     LED_CONNECT = 1;
00189     ble.getPreferredConnectionParams(&connectionParams);
00190 //    connectionParams.minConnectionInterval        = BLE_INTERVAL_10MS;
00191     connectionParams.minConnectionInterval        = BLE_INTERVAL_50MS;
00192 //    connectionParams.minConnectionInterval        = INTERVAL_100MS;
00193 
00194 //    connectionParams.maxConnectionInterval        = BLE_INTERVAL_12MS;
00195     connectionParams.maxConnectionInterval        = BLE_INTERVAL_62MS;
00196 //    connectionParams.maxConnectionInterval        = BLE_INTERVAL_125MS;
00197     if (ble.updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE) {
00198         DEBUG("failed to update connection paramter\r\n");
00199     }
00200     gConnect = 1;
00201     timerTask.attach(&gpioTask, 0.1f); // start interval 100mS timer 
00202     
00203     // set ready flag
00204     statData[0] = 0;
00205     statData[1] = VERSION_NUM;
00206     ble.gattServer().write(gStatCharacteristic.getValueAttribute().getHandle(), statData, 4);
00207 }
00208 
00209 void ConnectTimeoutCallback(Gap::TimeoutSource_t source)
00210 {
00211     ble.setAdvertisingTimeout(0); /* 0 is disable the advertising timeout. */
00212     ble.startAdvertising();
00213 }
00214 
00215 void DataWrittenCallback(const GattWriteCallbackParams *params)
00216 {
00217     uint8_t *wrtData = (uint8_t *)params->data;
00218     uint16_t wrtLen = params->len;
00219         
00220     memcpy(gCmdData,wrtData,wrtLen);
00221     gCmdLen = wrtLen;
00222     LED_CONNECT = 0; // busy condition
00223 
00224     DEBUG("rcv\r\n");
00225 //    DEBUG("DataWrittenCallback() len=%u data=", wrtLen);
00226 //    for (int i=0; i< wrtLen; i++) {
00227 //        DEBUG("0x%x,", *wrtData++);
00228 //    }
00229 //    DEBUG("\r\n");
00230 
00231 }
00232 
00233 void UpdatesEnabledCallBack(Gap::Handle_t handle)
00234 {
00235     DEBUG("UpdatesEnabled\n\r");
00236     // ユーザ処理コード
00237 }
00238  
00239 void UpdatesDisabledCallBack(Gap::Handle_t handle)
00240 {
00241     DEBUG("UpdatesDisabled\n\r");
00242     // ユーザ処理コード
00243 }
00244  
00245 void DataSentCallback(unsigned count)
00246 {
00247 //    DEBUG("DataSentCallback\n\r");
00248     // ユーザ処理コード
00249 }
00250 
00251 /* --- test code ----------------------------------------------------------------------- */
00252 int tako() {
00253     i2c.frequency(I2C_SPEED);
00254     char wReg[2] = {0x0,0x0};
00255     char rReg[2] = {0,0};
00256     
00257     i2c.start();
00258     int val = i2c.write(0x48<<1);
00259     i2c.stop();
00260     DEBUG("write val %d\r\n",val);
00261     
00262 #if 1
00263     if (i2c.write(0x48<<1, wReg, 0) == 0) {
00264         DEBUG("write ok\r\n");
00265     } else {
00266         DEBUG("write NG\r\n");
00267     }
00268 #endif    
00269 //    i2c.write(0x48, wReg, 1);
00270 #if 1
00271     if (i2c.read(0x48<<1, rReg, 2) == 0) {
00272         DEBUG("read ok\r\n");
00273     } else {
00274         DEBUG("read ng\r\n");
00275     }
00276 
00277     DEBUG("read sensor data=");
00278     for (int i=0; i< 2; i++) {
00279       DEBUG("0x%x,", rReg[i]);
00280     }
00281     DEBUG("\r\n");
00282 #endif
00283     return 0;
00284 }
00285 
00286 /* --- user task ----------------------------------------------------------------------- */
00287 int checkGPIO(int gpioNum) {
00288     for (int i=0; i<sizeof(validGpioPins); i++) {
00289         if (validGpioPins[i] == gpioNum) {
00290             return i;
00291         }
00292     }
00293     DEBUG("Invalid GPIO number %d\r\n",gpioNum);
00294     return -1;    
00295 }
00296 
00297 // ホストからのコマンドを処理
00298 void commandTask() {
00299     uint8_t response[20] = {1,2,3,4};
00300     int responseSize = 5;
00301     int gpioNum = -1;
00302     char i2cWrBuf[MAX_I2C_TRANSFAR_SIZE] = {0,};
00303     char i2cRdBuf[MAX_I2C_TRANSFAR_SIZE] = {0,};
00304 
00305     memcpy(response,gCmdData,4); // コマンドヘッダ部分をレスポンスデータにコピー
00306 
00307     switch (gCmdData[3]) {
00308       case CMD_EXPORT: // use GPIO port
00309         // input:
00310         //  gCmdData[4] : target port number
00311         //  gCmdData[5] : 0=outpt 1=input
00312         // output:
00313         //  response[4] : 1=accept 1=reject
00314         gpioNum = checkGPIO(gCmdData[4]);
00315         if (gpioNum < 0) {
00316             response[4] = 0; // error
00317         } else {
00318             if (gCmdData[5] == 0) {
00319                 DEBUG("set GPIO output  %d\r\n",gCmdData[4]);
00320                 gports[gpioNum] = 0; // inital state low
00321                 gports[gpioNum].output();
00322                 hiDriveGpio(gpioNum); // set high drive (Low/High 5mA)
00323 
00324 
00325             } else {
00326                 DEBUG("set GPIO input %d\r\n",gCmdData[4]);
00327                 gports[gpioNum].input();
00328                 gports[gpioNum].mode(PullUp);  // 内蔵プルアップを使う
00329                 // gports[gpioNum].mode( PullDown );    /  内蔵プルダウンを使う
00330                 eventGpioPins[gpioNum] = 1; // イベント監視対象
00331                 reloadGpioCondition();
00332             }
00333             response[4] = 1; // OK
00334         }
00335         break;
00336 
00337       case CMD_UNEXPORT: // GPIO port input
00338         // input:
00339         //  gCmdData[4] : target port number
00340         // output:
00341         //  response[4] : 1=accept 1=reject
00342         gpioNum = checkGPIO(gCmdData[4]);
00343         if (gpioNum < 0) {
00344             response[4] = 0; // error
00345         } else {
00346             gports[gpioNum].input(); // 端子を入力として解放
00347             gports[gpioNum].mode(PullNone);
00348             eventGpioPins[gpioNum] = 0; // イベント監視対象外
00349             reloadGpioCondition();
00350             response[4] = 1; // OK
00351         }
00352         break;
00353 
00354       case CMD_GPIO_WRITE: // GPIO port write
00355         // input:
00356         //  gCmdData[4] : target port number
00357         //  gCmdData[5] : 0=low 1=high
00358         // output:
00359         //  response[4] : 1=accept 0=reject
00360         gpioNum = checkGPIO(gCmdData[4]);
00361         if (gpioNum < 0) {
00362             response[4] = 0; // error
00363         } else {
00364             gports[gpioNum] = gCmdData[5];
00365             response[4] = 1; // OK
00366         }                
00367         break;
00368 
00369       case CMD_GPIO_READ: // GPIO port write
00370         // input:
00371         //  gCmdData[4] : target port number
00372         // output:
00373         //  response[4] : 1=accept 0=reject
00374         //  response[5] : port condition 0=low 1=high
00375         gpioNum = checkGPIO(gCmdData[4]);
00376         if (gpioNum < 0) {
00377             response[4] = 0; // error
00378         } else {
00379             gports[gpioNum] = gCmdData[5];
00380             if (gports[gpioNum] ==0) {
00381                 response[5] = 0; // Low
00382             } else {
00383                 response[5] = 1; // High
00384             }
00385             response[4] = 1; // OK
00386             responseSize += 1;
00387         }                
00388         break;
00389 
00390       case CMD_I2C_INIT: // I2C test access
00391         // input:
00392         //  gCmdData[4] : slave I2C address
00393         // output:
00394         //  response[4] : 1=accept 1=reject
00395         i2cWrBuf[0] =0;
00396         if (i2c.write(gCmdData[4]<<1, i2cWrBuf, 0) == 0) {
00397             response[4] = 1; // OK
00398         } else {
00399             DEBUG("I2C write error address=%x\r\n",gCmdData[4]);
00400             response[4] = 0; // error
00401         }
00402         break;
00403 
00404       case CMD_I2C_READ: // I2C read
00405         // input:
00406         //  gCmdData[4] : slave I2C address
00407         //  gCmdData[5] : sub-address
00408         //  gCmdData[6] : length
00409         // output:
00410         //  response[4] : read data length / 0=reject
00411         //  response[5] : read data
00412         if ((gCmdData[6] > MAX_I2C_TRANSFAR_SIZE) || (gCmdData[6] < 1)) {
00413             DEBUG("I2C write error invalid length=%d\r\n",gCmdData[6]);
00414             response[4] = 0; // error
00415             break;
00416         }
00417         i2cWrBuf[0] = gCmdData[5];
00418         if (i2c.write(gCmdData[4]<<1, i2cWrBuf, 1, true) != 0) { // Repeat condision
00419             DEBUG("I2C write error address=%x\r\n",gCmdData[4]);
00420             response[4] = 0; // error
00421             break;
00422         }
00423         if (i2c.read(gCmdData[4]<<1, i2cRdBuf, gCmdData[6]) != 0) {
00424             DEBUG("I2C read error address=%x\r\n",gCmdData[4]);
00425             response[4] = 0; // error
00426             break;
00427         }
00428 //        DEBUG("I2C read ok\r\n");
00429         memcpy(&response[5],i2cRdBuf,gCmdData[6]);
00430         response[4] = gCmdData[6]; // read size
00431         responseSize += gCmdData[6];
00432         break;
00433 
00434       case CMD_I2C_RDBYTE:
00435         // input:
00436         //  gCmdData[4] : slave I2C address
00437         //  gCmdData[5] : length
00438         // output:
00439         //  response[4] : read data length / 0=reject
00440         //  response[5] : read data
00441         if ((gCmdData[5] > MAX_I2C_TRANSFAR_SIZE) || (gCmdData[5] < 1)) {
00442             DEBUG("I2C write error invalid length=%d\r\n",gCmdData[5]);
00443             response[4] = 0; // error
00444             break;
00445         }
00446         if (i2c.read(gCmdData[4]<<1, i2cRdBuf, gCmdData[5]) != 0) {
00447             DEBUG("I2C read error address=%x\r\n",gCmdData[4]);
00448             response[4] = 0; // error
00449             break;
00450         }
00451 //        DEBUG("read ok\r\n");
00452         memcpy(&response[5],i2cRdBuf,gCmdData[5]);
00453         response[4] = gCmdData[5]; // read size
00454         responseSize += gCmdData[5];
00455         break;
00456 
00457       case CMD_I2C_WRITE: // I2C write
00458         // input:
00459         //  gCmdData[4] : slave I2C address
00460         //  gCmdData[5] : length
00461         //  gCmdData[6] : write data
00462         //  gCmdData[7] ...
00463         // output:
00464         //  response[4] : 1=accept 1=reject
00465         if ((gCmdData[5] > MAX_I2C_TRANSFAR_SIZE) || (gCmdData[5] < 1)) {
00466             DEBUG("I2C write error invalid length=%d\r\n",gCmdData[5]);
00467             response[4] = 0; // error
00468             break;
00469         }
00470         memcpy(i2cWrBuf,&gCmdData[6],gCmdData[5]);
00471         if (i2c.write(gCmdData[4]<<1, i2cWrBuf, gCmdData[5]) != 0) { // Repeat condision
00472             DEBUG("I2C write error address=%x\r\n",gCmdData[4]);
00473             response[4] = 0; // error
00474             break;
00475         }
00476 
00477         response[4] = gCmdData[5]; // return complite transfar size
00478         break;
00479 
00480 #if 0
00481       case CMD_ADC_INPUT:
00482         // input:
00483         //  gCmdData[4] : target port number
00484         // output:
00485         //  response[4] : 1=accept 1=reject
00486         gpioNum = checkGPIO(gCmdData[4]);
00487         if ((gpioNum < 1) || (gpioNum > 6)) {
00488             response[4] = 0; // error
00489         } else {
00490             gports[gpioNum].input(); // 端子を入力として解放
00491             gports[gpioNum].mode(PullNone);
00492             eventGpioPins[gpioNum] = 0; // イベント監視対象外
00493             reloadGpioCondition();
00494             
00495             // ADC setting
00496             // 10bit Reference internal Bandcap(1.2V)
00497             NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
00498                 (ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
00499                 (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) |
00500                 (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
00501             response[4] = 1; // OK
00502         }
00503         break;
00504         
00505       case CMD_ADC_READ:
00506         // input:
00507         //  gCmdData[4] : target port number
00508         // output:
00509         //  response[4] : read data length(fixed 2) / 0=reject
00510         //  response[5] : read data(MSB)
00511         //  response[6] : read data(LSB)
00512         gpioNum = gCmdData[4];
00513         if ((gpioNum < 1) || (gpioNum > 6)) {
00514             response[4] = 0; // error
00515         } else {
00516             NRF_ADC->CONFIG     &= ~ADC_CONFIG_PSEL_Msk;
00517             NRF_ADC->CONFIG     |= (4 << gpioNum) << ADC_CONFIG_PSEL_Pos;
00518             NRF_ADC->TASKS_START = 1;
00519             while (((NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) >> ADC_BUSY_BUSY_Pos) == ADC_BUSY_BUSY_Busy) {
00520             }
00521             uint16_t advalue = (uint16_t)NRF_ADC->RESULT; // 10 bit
00522             DEBUG("read adc %d =%x\r\n",gpioNum, advalue);
00523             response[5] = advalue >> 8;
00524             response[6] = advalue && 0xff;
00525             responseSize += 2;
00526         }
00527         break;
00528 #endif
00529               
00530       default:
00531         DEBUG("unknonwn command =%x\r\n",gCmdData[3]);
00532         response[4] = 0; // error
00533         break;    
00534                 
00535     }
00536 
00537     DEBUG("reply\r\n");
00538 //    DEBUG("send Notify len=%u data=", responseSize);
00539 //    for (int i=0; i< responseSize; i++) {
00540 //        DEBUG("0x%x,", response[i]);
00541 //    }
00542 //    DEBUG("\r\n");
00543 
00544     // send response (notify)
00545     ble.gattServer().write(gNotifyCharacteristic.getValueAttribute().getHandle(), response, responseSize);
00546     LED_CONNECT = 1; // ready
00547 
00548 }
00549 
00550 /* --- main code ----------------------------------------------------------------------- */
00551 int main() {
00552     LED_CONNECT = 1;
00553     gCmdLen = 0;
00554     gConnect = 0;
00555     gScanGPIO = 0;
00556 
00557     initGpio();
00558     hiDriveGpio(GPIO_LED_CONNECT);
00559     DEBUG("PowerON version %d\n\r",VERSION_NUM);
00560     
00561     /* Initialise the nRF51822 */
00562     ble.init();
00563 
00564     /* Setup The event handlers */
00565     ble.onConnection(onConnectionCallback);
00566     ble.onDisconnection(onDisconnectionCallback);
00567     ble.onTimeout(ConnectTimeoutCallback);
00568 
00569     ble.onDataWritten(DataWrittenCallback);
00570     ble.onDataSent(DataSentCallback);
00571     ble.onUpdatesEnabled(UpdatesEnabledCallBack);
00572     ble.onUpdatesDisabled(UpdatesDisabledCallBack);
00573     
00574     // set TX power
00575     // Valid values are -40, -20, -16, -12, -8, -4, 0, 4)
00576     ble.setTxPower(4);
00577 
00578     /* setup advertising */
00579     ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00580     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00581 
00582     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
00583                                      (const uint8_t *)UUID_ADV_SERVICE, sizeof(UUID_ADV_SERVICE));
00584     ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME,
00585                                      (const uint8_t *)DEVICE_NAME,
00586                                      strlen(DEVICE_NAME));
00587     ble.gap().setAdvertisingInterval(80); /* 50ms; in multiples of 0.625ms. */
00588     ble.gap().startAdvertising();
00589     DEBUG("Start Advertising\r\n");
00590 
00591     ble.addService(gGpioService);
00592 
00593     LED_CONNECT = 0;
00594     for (;; ) {
00595         ble.waitForEvent();
00596         if (gCmdLen > 0) {
00597             commandTask();
00598             gCmdLen =0;
00599         } else if (gNotifyLen > 0) {
00600             ble.gattServer().write(gNotifyCharacteristic.getValueAttribute().getHandle(), gNotifyData, gNotifyLen);
00601             gNotifyLen = 0;
00602         }
00603     }
00604 
00605 }