
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
This is a BLE Server (Device) program for nRF51.
You can communicate with mbed BLE using "BLE_Uart_Client" program as follows.
/users/kenjiArai/code/BLE_Uart_Client/
Please refer following my notebook.
/users/kenjiArai/notebook/ble-client-and-peripheral-using-switch-sience-ty51/#
Revision 1:9b27a9710d94, committed 2016-04-16
- Comitter:
- kenjiArai
- Date:
- Sat Apr 16 12:12:59 2016 +0000
- Parent:
- 0:6b0eca2bcb7a
- Child:
- 2:2322afea6ecf
- Commit message:
- this is actual main.cpp routine
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/main.cpp Sat Apr 16 08:33:46 2016 +0000 +++ b/main.cpp Sat Apr 16 12:12:59 2016 +0000 @@ -1,12 +1,321 @@ -#include "mbed.h" +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ------- BLE Peripheral UART function -------------------------------- + * --- Tested on Switch Science mbed TY51822r3 --- + * + * http://www.page.sannet.ne.jp/kenjia/index.html + * http://mbed.org/users/kenjiArai/ + * + * Started: March 7th, 2016 + * Revised: April 16th, 2016 + * + * Original program: + * BLE_LoopbackUART + * https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_LoopbackUART/ + * Tested Controller Device: + * BLE_Uart_Client + * https://developer.mbed.org/users/kenjiArai/code/BLE_Uart_Client/ + * + */ -DigitalOut myled(LED1); +// Include --------------------------------------------------------------------------------------- +#include "mbed.h" +#include "BLE.h" +#include "UARTService.h" +#include "nRF51_Vdd.h" +#include "nRF51_WakeUp.h" + +// Definition ------------------------------------------------------------------------------------ +#define GOTO_SLEEP_MODE 0 +#define NEED_CONSOLE_OUTPUT 0 + +#if NEED_CONSOLE_OUTPUT +#define DEBUG(...) { printf(__VA_ARGS__); } +#else +#define DEBUG(...) +#endif + +// Object ---------------------------------------------------------------------------------------- +BLEDevice ble; +DigitalOut connectedLED(LED2); +InterruptIn wake_up_sw(P0_1); +nRF51_WakeUp wakeup(LED1, P0_0); +nRF51_Vdd vdd(3.0f, 2.2f); +Serial pc(USBTX, USBRX); +UARTService *uartServicePtr; +Ticker ticker; + +// ROM / Constant data --------------------------------------------------------------------------- +#warning "You need to confirm your device name." +const char *deviceName = "UART_P"; + +// RAM ------------------------------------------------------------------------------------------- +uint8_t tx_buf[24]; +uint8_t tx_len = 0; +uint8_t rx_buf[24]; +uint8_t rx_len = 0; +volatile bool trigger_transmit = false; +volatile bool trigger_receive = false; +volatile uint8_t command_continue = 0; +uint16_t time_out_cntr = 3600; +volatile bool time_out = false; +bool line_input = false; +uint8_t linebuf_irq[24]; +int linebf_irq_len = 0; +uint8_t linebuf[24]; +int linebf_len = 0; -int main() { - while(1) { - myled = 1; - wait(0.2); - myled = 0; - wait(0.2); +// Function prototypes --------------------------------------------------------------------------- +// BLE +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params); +void onDataWritten(const GattWriteCallbackParams *params); +void periodicCallback(void); +// Application related +void adjust_line(uint8_t *bf); +void action_tx_help(void); +void action_tx_vdd(void); +void action_tx_temperature(void); +void action_tx_pwrup(void); +void action_tx_pwrdwn(void); +void fill_space_n(uint8_t *bf, uint8_t n); +void Update_Values(void); +// Interrupt related +void action_tx_quit(void); +void interrupt_by_sw(void); +void serialRxCallback(void); + +//------------------------------------------------------------------------------------------------- +// Control Program +//------------------------------------------------------------------------------------------------- +int main(void){ + connectedLED = 0; + pc.attach(&serialRxCallback, Serial::RxIrq); + ticker.attach(periodicCallback, 1); + for (int k = 0; k < 20; k++) { pc.printf("\r\n");} // clear terminal output + pc.printf("UART Communication / Peripheral side\r\n"); // opening message + pc.printf(" Client(Central) and Peripheral(device)\r\n"); // opening message + // Interrupt by switch + wake_up_sw.fall(&interrupt_by_sw); + ble.init(); + ble.setDeviceName((const uint8_t *)deviceName); + ble.onDisconnection(disconnectionCallback); + ble.onDataWritten(onDataWritten); + /* setup advertising */ + ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); + ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, + (const uint8_t *)deviceName, + strlen(deviceName) + ); + ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, + (const uint8_t *)UARTServiceUUID_reversed, + sizeof(UARTServiceUUID_reversed) + ); + // Advertize Interval + ble.setAdvertisingInterval(1000); /* 1000ms; in multiples of 0.625ms. */ + // Start + ble.startAdvertising(); + UARTService uartService(ble); + uartServicePtr = &uartService; + while(true){ + if (time_out){ +#if GOTO_SLEEP_MODE + wakeup.set_and_wait(10); + while(true){ // never come here but just in case + deepsleep(); + } +#endif + } + if (line_input){ + line_input = false; + adjust_line(linebuf); + ble.updateCharacteristicValue( + uartServicePtr->getRXCharacteristicHandle(), + linebuf, + 20 + ); + } + if (trigger_transmit){ + trigger_transmit = false; + pc.printf("%s\r\n", rx_buf); + if (rx_buf[0] == '*'){ + switch (rx_buf[1]){ + case 'v': + action_tx_vdd(); + break; + case 't': + action_tx_temperature(); + break; + case 'q': + action_tx_quit(); + break; + case 'h': + case '?': + action_tx_help(); + break; + default: + break; + } + } + } + ble.waitForEvent(); } } + +void serialRxCallback(){ + char c = pc.getc(); + if (c == '\r') { + linebuf_irq[linebf_irq_len++] = c; + pc.printf("\r\n"); + linebf_len = linebf_irq_len; + strcpy((char *)linebuf, (char *)linebuf_irq); + linebf_irq_len = 0; + line_input = true; + } else if ((c == '\b') && linebf_irq_len) { + linebf_irq_len--; + pc.putc(c); + pc.putc(' '); + pc.putc(c); + } else if (((uint8_t)c >= ' ') && (linebf_irq_len < 20)) { + linebuf_irq[linebf_irq_len++] = c; + pc.putc(c); + } else if ( c == 0x1f ){ // Control+? + SCB->AIRCR = 0x05fa0004; // System RESET!! + } + linebuf_irq[linebf_irq_len] = 0; +} + +void adjust_line(uint8_t *bf){ +uint8_t i, c; + + for (i = 0; i <20; bf++, i++){ + c = *bf; + if ( (c == '\r') || (c == '\n') || (c == 0)){ + break; + } + } + for (; i < 20; bf++, i++){ + *bf = ' '; + } + *(bf + 1) = 0; +} + +void onDataWritten(const GattWriteCallbackParams *params){ + if ((uartServicePtr != NULL) && + (params->handle == uartServicePtr->getTXCharacteristicHandle())) + { + strcpy((char *)rx_buf, (const char *)params->data); + rx_len = params->len; + trigger_transmit = true; + DEBUG("RX_data\r\n"); + DEBUG("Length: %d\r\n", rx_len); + DEBUG("Data: "); + DEBUG("%s", rx_buf); + DEBUG("\r\n"); + } +} + +void action_tx_help(){ + // 12345678901234567890 + sprintf((char *)tx_buf,"?:help by JH1PJL"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.2); + // 12345678901234567890 + sprintf((char *)tx_buf,"v:vdd"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.2); + // 12345678901234567890 + sprintf((char *)tx_buf,"t:temperature"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.2); + // 12345678901234567890 + sprintf((char *)tx_buf,"q:quit/sleep"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(0.2); +} + +void action_tx_vdd(){ + sprintf((char *)tx_buf,"Vdd:%3.2fV", vdd.read_real_value()); + tx_len = strlen((const char *)tx_buf); + Update_Values(); +} + +void action_tx_temperature(){ + int32_t p_temp; + float temperature; + + // Update a temperature (inside nRF51822 chip) + sd_temp_get(&p_temp); + // -16.0f is offset vale for chip die temp to ambient temp (depend on your board) + temperature = float(p_temp) / 4; // Original = float(p_temp)/4.0f - 16.0f; + sprintf((char *)tx_buf,"T:%+4.1fdC", temperature); + tx_len = strlen((const char *)tx_buf); + Update_Values(); +} + +void action_tx_quit(){ +#if GOTO_SLEEP_MODE + ticker.detach(); + // 12345678901234567890 + sprintf((char *)tx_buf,"Terminated the BLE"); + tx_len = strlen((const char *)tx_buf); + Update_Values(); + wait(1.0); + wakeup.set_and_wait(120); + while(true){ // never come here but just in case + deepsleep(); + } +#else + SCB->AIRCR = 0x05fa0004; // System RESET!! +#endif +} + +void interrupt_by_sw(){ // Go to sleep + NVIC_SystemReset(); + // Not come here (Just in case) + deepsleep(); +} + +void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params){ + DEBUG("Disconnected!\r\n"); + DEBUG("Restarting the advertising process\r\n"); + ble.startAdvertising(); +} + +void periodicCallback(void){ +#if GOTO_SLEEP_MODE + if (--time_out_cntr == 0){ + time_out = true; + } +#endif +} + +void Update_Values(void){ + ble.updateCharacteristicValue( + uartServicePtr->getRXCharacteristicHandle(), + tx_buf, + tx_len + ); + DEBUG("TX_data: %s\r\n", tx_buf); + DEBUG("Length: %d\r\n", tx_len); + tx_len = 0; +}