this is a new program based on BLE_Uart_Peripheral. Change program name due to relation Client&Peripheral to Client&Server
Dependencies: RingBuffer nRF51_Vdd nRF51_WakeUp
main.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 /* 00018 * ------- BLE Peripheral/Server UART function -------------------------------- 00019 * communicate with BLE_UART_Client program 00020 * --- Tested on Switch Science mbed TY51822r3 --- 00021 * 00022 * http://www.page.sannet.ne.jp/kenjia/index.html 00023 * https://os.mbed.com/users/kenjiArai/ 00024 * 00025 * Started: March 7th, 2016 00026 * Revised: June 13th, 2016 00027 * Revised: Feburary 10th, 2018 Not set mac addr but use device name 00028 * Revised: Feburary 11th, 2018 use mbed-os5.7.4 with CircularBuffer 00029 * 00030 * Original program: 00031 * BLE_LoopbackUART 00032 * https://developer.mbed.org/teams/Bluetooth-Low-Energy/ 00033 * code/BLE_LoopbackUART/ 00034 * Reference program: 00035 * BLE_Peripheral_test by noboru koshinaka 00036 * https://os.mbed.com/users/noboruk/code/BLE_Peripheral_test/ 00037 * Tested Client Device: 00038 * BLE_Uart_Client 00039 * https://os.mbed.com/users/kenjiArai/code/BLE_Uart_Client/ 00040 */ 00041 00042 // Include -------------------------------------------------------------------- 00043 #include "mbed.h" 00044 #include "BLE.h" 00045 #include "UARTService.h" 00046 #include "nRF51_Vdd.h" 00047 #include "nRF51_WakeUp.h" 00048 #include "CircularBuffer.h" 00049 00050 // Definition ----------------------------------------------------------------- 00051 //#define USE_MAC // if you use mac address, please define it 00052 00053 #define NUM_ONCE 20 00054 #define BFSIZE (NUM_ONCE+4) 00055 00056 // Please refer nRF51_WakeUP library 00057 #define GOTO_SLEEP_MODE 0 00058 #if GOTO_SLEEP_MODE 00059 #warning "Make sure!! -> You need to connected P0_21(LED1) and P0_0" 00060 #endif 00061 00062 //#define USE_DEBUG_MODE 00063 #ifdef USE_DEBUG_MODE 00064 #define DEBUG(...) { printf(__VA_ARGS__); } 00065 #else 00066 #define DEBUG(...) 00067 #endif 00068 00069 // Object --------------------------------------------------------------------- 00070 BLE& ble_uart = BLE::Instance(); 00071 DigitalOut connectedLED(LED2); 00072 InterruptIn wake_up_sw(P0_1); 00073 nRF51_WakeUp wakeup(P0_21, P0_0); 00074 nRF51_Vdd vdd(3.0f, 2.2f); 00075 Serial pc(USBTX, USBRX, 115200); 00076 //Serial pc(P0_3, P0_1, 115200); // for another board 00077 UARTService *uartServicePtr; 00078 Ticker ticker; 00079 CircularBuffer<char, 1536> ser_bf; 00080 Thread tsk; 00081 Mutex bletx_mutex; 00082 00083 // ROM / Constant data -------------------------------------------------------- 00084 #warning "You need to confirm your device name." 00085 const static char DEVICE_NAME[] = "UART_PJL"; 00086 00087 // RAM ------------------------------------------------------------------------ 00088 Gap::Address_t my_mac; 00089 uint8_t tx_buf[BFSIZE]; 00090 uint8_t tx_len = 0; 00091 uint8_t rx_buf[BFSIZE]; 00092 volatile bool trigger_transmit = false; 00093 volatile bool trigger_receive = false; 00094 volatile uint8_t command_continue = 0; 00095 uint16_t time_out_cntr = 3600; 00096 volatile bool time_out = false; 00097 uint32_t sleep_time = 30; // unit:second 00098 volatile bool rx_isr_busy = false; 00099 00100 // Function prototypes -------------------------------------------------------- 00101 // BLE 00102 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *); 00103 void onDataWritten_action(const GattWriteCallbackParams *); 00104 // Tasks 00105 void pc_ser_rx(void); 00106 void data_from_ble(void); 00107 void Update_Values(void); 00108 // Application related 00109 void command(uint8_t *cmd); 00110 void action_tx_help(void); 00111 void action_tx_vdd(void); 00112 void action_tx_temperature(void); 00113 void action_tx_wait_time(uint8_t *); 00114 void action_tx_quit(void); 00115 int xatoi (char **, int32_t *); 00116 void adjust_line(uint8_t *); 00117 // Interrupt related 00118 void interrupt_by_sw(void); 00119 void serialRxCallback(void); 00120 void periodicCallback(void); 00121 00122 //------------------------------------------------------------------------------ 00123 // Control Program 00124 //------------------------------------------------------------------------------ 00125 int main(void) 00126 { 00127 connectedLED = 0; 00128 pc.attach(&serialRxCallback, Serial::RxIrq); 00129 ticker.attach(periodicCallback, 1); 00130 tsk.start(pc_ser_rx); 00131 // clear terminal output 00132 for (int k = 0; k < 3; k++) { 00133 pc.printf("\r\n"); 00134 } 00135 // opening message 00136 pc.printf("UART Communication / Server(Peripheral) side\r\n"); 00137 pc.printf(" need Client module (run BLE_Uart_Client program)\r\n"); 00138 // Interrupt by switch 00139 wake_up_sw.fall(&interrupt_by_sw); 00140 ble_uart.init(); 00141 Gap::AddressType_t my_mac_type; 00142 ble_uart.gap().getAddress(&my_mac_type, my_mac); 00143 DEBUG( 00144 " my_MAC %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n", 00145 my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0], 00146 (my_mac_type == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random" 00147 ); 00148 pc.printf( 00149 " My device name : %s\r\n", DEVICE_NAME); 00150 pc.printf( 00151 " My mac data %02x:%02x:%02x:%02x:%02x:%02x\r\n", 00152 my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0] 00153 ); 00154 #ifdef USE_MAC 00155 pc.printf( 00156 " mac_board_x = {0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x};\r\n", 00157 my_mac[0], my_mac[1], my_mac[2], my_mac[3], my_mac[4], my_mac[5] 00158 ); 00159 pc.printf( 00160 " Please write above data(mac_board_x line (x=0,1,2,...))\r\n"); 00161 pc.printf( 00162 " into Client/main.cpp [ROM / Constant data] area\r\n"); 00163 #endif 00164 ble_uart.onDisconnection(disconnectionCallback); 00165 ble_uart.onDataWritten(onDataWritten_action); 00166 /* setup advertising */ 00167 ble_uart.accumulateAdvertisingPayload( 00168 GapAdvertisingData::BREDR_NOT_SUPPORTED); 00169 ble_uart.setAdvertisingType( 00170 GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00171 ble_uart.accumulateAdvertisingPayload( 00172 GapAdvertisingData::COMPLETE_LOCAL_NAME, 00173 (const uint8_t *)DEVICE_NAME, 00174 sizeof(DEVICE_NAME) 00175 ); 00176 ble_uart.accumulateAdvertisingPayload( 00177 GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, 00178 (const uint8_t *)UARTServiceUUID_reversed, 00179 sizeof(UARTServiceUUID_reversed) 00180 ); 00181 // Advertize Interval 00182 ble_uart.setAdvertisingInterval(1000); /* 1000ms;in multiples of 0.625ms.*/ 00183 // Start 00184 ble_uart.startAdvertising(); 00185 UARTService uartService(ble_uart); 00186 uartServicePtr = &uartService; 00187 while(true) { 00188 if (time_out) { 00189 #if GOTO_SLEEP_MODE 00190 wakeup.set_and_wait(sleep_time); 00191 while(true) { // never come here but just in case 00192 deepsleep(); 00193 } 00194 #endif 00195 } 00196 if (trigger_transmit) { 00197 static uint8_t cmd_buf[BFSIZE]; 00198 static volatile bool flag_continue = 0; 00199 trigger_transmit = false; 00200 pc.printf((const char*)rx_buf); 00201 if (flag_continue == true) { 00202 strcat((char *)cmd_buf, (char *)rx_buf); 00203 if (strchr((const char*)cmd_buf,(int)'\r') == 0) { 00204 flag_continue = true; 00205 } else { 00206 command(cmd_buf); 00207 for(uint8_t i = 0; i < BFSIZE; i++) { 00208 cmd_buf[i] = 0; 00209 } 00210 flag_continue = false; 00211 } 00212 } 00213 if ((rx_buf[0] == '~')) { 00214 strcpy((char *)cmd_buf, (char *)rx_buf); 00215 if (strchr((const char*)cmd_buf,(int)'\r') == 0) { 00216 flag_continue = true; 00217 } else { 00218 command(cmd_buf); 00219 for(uint8_t i = 0; i < BFSIZE; i++) { 00220 cmd_buf[i] = 0; 00221 } 00222 flag_continue = false; 00223 } 00224 } 00225 } 00226 ble_uart.waitForEvent(); 00227 } 00228 } 00229 00230 void command(uint8_t *cmd) 00231 { 00232 uint8_t *p = cmd; 00233 00234 while(*p == ' ') { 00235 ++p; // skip space 00236 } 00237 if (*p++ == '~') { 00238 while(*p < '!') { 00239 ++p; // skip space 00240 } 00241 uint8_t c = *p; 00242 //pc.printf("c=%c\r\n", c); 00243 switch (c) { 00244 case 'v': 00245 action_tx_vdd(); 00246 break; 00247 case 't': 00248 action_tx_temperature(); 00249 break; 00250 case 'q': 00251 action_tx_quit(); 00252 break; 00253 case 'w': 00254 action_tx_wait_time(cmd); 00255 break; 00256 case 'h': 00257 case '?': 00258 action_tx_help(); 00259 break; 00260 default: 00261 //pc.printf("\r\nStep(%u)\r\n", __LINE__); 00262 break; 00263 } 00264 } 00265 } 00266 00267 void periodicCallback(void) 00268 { 00269 #if GOTO_SLEEP_MODE 00270 if (--time_out_cntr == 0) { 00271 time_out = true; 00272 } 00273 #endif 00274 if (rx_isr_busy == true) { 00275 rx_isr_busy = false; 00276 } else { 00277 tsk.signal_set(0x01); 00278 } 00279 } 00280 00281 void serialRxCallback() 00282 { 00283 ser_bf.push(pc.getc()); 00284 rx_isr_busy = true; 00285 tsk.signal_set(0x01); 00286 } 00287 00288 void pc_ser_rx() 00289 { 00290 static uint8_t linebf_irq[BFSIZE]; 00291 static volatile uint8_t linebf_irq_len = 0; 00292 00293 while(true) { 00294 Thread::signal_wait(0x01); 00295 if (ser_bf.empty()) { 00296 if (linebf_irq_len != 0) { 00297 linebf_irq[linebf_irq_len] = 0; 00298 adjust_line(linebf_irq); 00299 linebf_irq_len = 0; 00300 bletx_mutex.lock(); 00301 ble_uart.updateCharacteristicValue( 00302 uartServicePtr->getRXCharacteristicHandle(), 00303 linebf_irq, 00304 NUM_ONCE 00305 ); 00306 bletx_mutex.unlock(); 00307 } 00308 } 00309 while(!ser_bf.empty()) { 00310 char c; 00311 ser_bf.pop(c); 00312 if (c == '\b') { 00313 linebf_irq_len--; 00314 pc.putc(c); 00315 pc.putc(' '); 00316 pc.putc(c); 00317 } else if ((c >= ' ') || (c == '\r') || (c == '\n')) { 00318 bool overflow = false; 00319 if ((c == '\r') || (c == '\n')) { 00320 if (linebf_irq_len == NUM_ONCE - 1) { // remain only 1 buffer 00321 overflow = true; 00322 linebf_irq[linebf_irq_len++] = '\r'; 00323 pc.putc('\r'); 00324 } else { 00325 overflow = false; 00326 linebf_irq[linebf_irq_len++] = '\r'; 00327 linebf_irq[linebf_irq_len++] = '\n'; 00328 pc.printf("\r\n"); 00329 } 00330 } else { 00331 linebf_irq[linebf_irq_len++] = c; 00332 pc.putc(c); 00333 } 00334 if (linebf_irq_len >= NUM_ONCE ) { 00335 linebf_irq[linebf_irq_len] = 0; 00336 adjust_line(linebf_irq); 00337 linebf_irq_len = 0; 00338 bletx_mutex.lock(); 00339 ble_uart.updateCharacteristicValue( 00340 uartServicePtr->getRXCharacteristicHandle(), 00341 linebf_irq, 00342 NUM_ONCE 00343 ); 00344 bletx_mutex.unlock(); 00345 if (overflow == true) { 00346 overflow = false; 00347 linebf_irq[linebf_irq_len++] = '\n'; 00348 pc.putc('\n'); 00349 } 00350 } 00351 } 00352 } 00353 } 00354 } 00355 00356 void adjust_line(uint8_t *bf) 00357 { 00358 uint8_t i, c; 00359 00360 for (i = 0; i <NUM_ONCE; bf++, i++) { 00361 c = *bf; 00362 if (c == 0) { 00363 break; 00364 } 00365 } 00366 for (; i < NUM_ONCE; bf++, i++) { 00367 *bf = 0x11; 00368 } 00369 *(bf + 1) = 0; 00370 } 00371 00372 void onDataWritten_action(const GattWriteCallbackParams *params) 00373 { 00374 if ((uartServicePtr != NULL) && 00375 (params->handle == uartServicePtr->getTXCharacteristicHandle())) { 00376 strcpy((char *)rx_buf, (const char *)params->data); 00377 trigger_transmit = true; 00378 } 00379 } 00380 00381 void action_tx_help() 00382 { 00383 // 12345678901234567890 00384 sprintf((char *)tx_buf," ~?:help\r\n"); 00385 tx_len = strlen((const char *)tx_buf); 00386 Update_Values(); 00387 Thread::wait(200); 00388 // 12345678901234567890 00389 sprintf((char *)tx_buf," ~v:vdd\r\n"); 00390 tx_len = strlen((const char *)tx_buf); 00391 Update_Values(); 00392 Thread::wait(200); 00393 // 12345678901234567890 00394 sprintf((char *)tx_buf," ~t:temperature\r\n"); 00395 tx_len = strlen((const char *)tx_buf); 00396 Update_Values(); 00397 Thread::wait(200); 00398 // 12345678901234567890 00399 sprintf((char *)tx_buf," ~w:wait, w 120\r\n"); 00400 tx_len = strlen((const char *)tx_buf); 00401 Update_Values(); 00402 Thread::wait(200); 00403 // 12345678901234567890 00404 sprintf((char *)tx_buf," ~q:quit/sleep\r\n"); 00405 tx_len = strlen((const char *)tx_buf); 00406 Update_Values(); 00407 Thread::wait(200); 00408 } 00409 00410 void action_tx_vdd() 00411 { 00412 sprintf((char *)tx_buf,"Vdd: %3.2f V\r\n", vdd.read_real_value()); 00413 tx_len = strlen((const char *)tx_buf); 00414 Update_Values(); 00415 } 00416 00417 void action_tx_temperature() 00418 { 00419 int32_t p_temp; 00420 float temperature; 00421 00422 // Update a temperature (inside nRF51822 chip) 00423 sd_temp_get(&p_temp); 00424 // -16.0f is offset vale for chip die temp 00425 // to ambient temp (depend on your board) 00426 temperature = float(p_temp) / 4; // Original = float(p_temp)/4.0f - 16.0f; 00427 sprintf((char *)tx_buf,"T: %+4.1f dC\r\n", temperature); 00428 tx_len = strlen((const char *)tx_buf); 00429 Update_Values(); 00430 } 00431 00432 void action_tx_wait_time(uint8_t *cmd) 00433 { 00434 int32_t dt; 00435 char *p; 00436 00437 p = (char *)(cmd); 00438 p += 2; // point to time value 00439 if (xatoi(&p, &dt)) { 00440 if (dt <= 5) { 00441 dt = 5; 00442 } 00443 sleep_time = dt; // set next wake-up period 00444 } else { 00445 DEBUG("data is unknown!\r\n"); 00446 sleep_time = 30; 00447 } 00448 DEBUG("slp_t:%d\r\n", sleep_time); 00449 //pc.printf("slp_t:%d\r\n", sleep_time); 00450 // 12345678901234567890 00451 sprintf((char *)tx_buf, "W: %d sec\r\n", sleep_time); 00452 tx_len = strlen((const char *)tx_buf); 00453 Update_Values(); 00454 } 00455 00456 void action_tx_quit() 00457 { 00458 #if GOTO_SLEEP_MODE 00459 ticker.detach(); 00460 // 12345678901234567890 00461 sprintf((char *)tx_buf,"Terminated the BLE"); 00462 tx_len = strlen((const char *)tx_buf); 00463 Update_Values(); 00464 Thread::wait(1000); 00465 wakeup.set_and_wait(sleep_time); 00466 while(true) { // never come here but just in case 00467 deepsleep(); 00468 } 00469 #else 00470 SCB->AIRCR = 0x05fa0004; // System RESET!! 00471 #endif 00472 } 00473 00474 // Change string -> integer 00475 int xatoi (char **str, int32_t *res) 00476 { 00477 unsigned long val; 00478 unsigned char c, radix, s = 0; 00479 00480 for (;;) { 00481 c = **str; 00482 if (c == 0) { 00483 return 0; 00484 } 00485 if (c == '-') { 00486 break; 00487 } 00488 if (c == '+') { 00489 (*str)++; 00490 c = **str; 00491 } 00492 if (c>='0'&& c<='9') { 00493 break; 00494 } else { 00495 (*str)++; 00496 c = **str; 00497 } 00498 } 00499 if (c == '-') { 00500 s = 1; 00501 c = *(++(*str)); 00502 } 00503 if (c == '0') { 00504 c = *(++(*str)); 00505 if (c <= ' ') { 00506 *res = 0; 00507 return 1; 00508 } 00509 if (c == 'x') { 00510 radix = 16; 00511 c = *(++(*str)); 00512 } else { 00513 if (c == 'b') { 00514 radix = 2; 00515 c = *(++(*str)); 00516 } else { 00517 if ((c >= '0')&&(c <= '9')) { 00518 radix = 8; 00519 } else { 00520 return 0; 00521 } 00522 } 00523 } 00524 } else { 00525 if ((c < '1')||(c > '9')) { 00526 return 0; 00527 } 00528 radix = 10; 00529 } 00530 val = 0; 00531 while (c > ' ') { 00532 if (c >= 'a') c -= 0x20; 00533 c -= '0'; 00534 if (c >= 17) { 00535 c -= 7; 00536 if (c <= 9) return 0; 00537 } 00538 if (c >= radix) return 0; 00539 val = val * radix + c; 00540 c = *(++(*str)); 00541 } 00542 if (s) val = -val; 00543 *res = val; 00544 return 1; 00545 } 00546 00547 void interrupt_by_sw() // Go to sleep 00548 { 00549 NVIC_SystemReset(); 00550 // Not come here (Just in case) 00551 sleep(); 00552 } 00553 00554 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) 00555 { 00556 DEBUG("Disconnected!\r\n"); 00557 DEBUG("Restarting the advertising process\r\n"); 00558 ble_uart.startAdvertising(); 00559 } 00560 00561 void Update_Values(void) 00562 { 00563 bletx_mutex.lock(); 00564 ble_uart.updateCharacteristicValue( 00565 uartServicePtr->getRXCharacteristicHandle(), 00566 tx_buf, 00567 tx_len 00568 ); 00569 bletx_mutex.unlock(); 00570 tx_len = 0; 00571 }
Generated on Tue Jul 12 2022 19:42:45 by 1.7.2