noboru koshinaka
/
BLE_Peripheral_test
ver1.0
main.cpp
- Committer:
- noboruk
- Date:
- 2018-02-07
- Revision:
- 0:7a3c39a4007a
File content as of revision 0:7a3c39a4007a:
/* 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/Server UART function -------------------------------- * communicate with BLE_UART_Client program * --- 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: June 13th, 2016 * Revised: October 22nd, 2017 Run on mbed-OS-5.6.2 * * 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/ */ // 2018/02/07 太陽誘電 EYSGCNZWY 使用の試作機向けに改造 // Include -------------------------------------------------------------------- #include "mbed.h" #include "BLE.h" #include "UARTService.h" #include "RingBuffer.h" // Definition ----------------------------------------------------------------- #define NUM_ONCE 20 #define BFSIZE (NUM_ONCE+4) // If you set 1, you need to connected LED1 and P_0 // Please refer nRF51_WakeUP library #define GOTO_SLEEP_MODE 0 //#define USE_DEBUG_MODE #ifdef USE_DEBUG_MODE #define DEBUG(...) { printf(__VA_ARGS__); } #else #define DEBUG(...) #endif #define LED1_PIN P0_25 #define LED2_PIN P0_23 #define LED3_PIN P0_21 #define EXT_SW_PIN P0_11 #define ROM_CS_PIN P0_12 #define ROM_SCK_PIN P0_13 #define ROM_SDI_PIN P0_15 // Object --------------------------------------------------------------------- DigitalOut alivenessLED(LED1_PIN,1); DigitalOut connectedLED(LED2_PIN,1); DigitalOut out_led(LED3_PIN,1); DigitalIn external_sw(EXT_SW_PIN); // // UARTの端子ははEEPROMの端子を流用 DigitalOut dummy_cs(ROM_CS_PIN,1); //Disable Chip Serial pc(ROM_SDI_PIN,ROM_SCK_PIN, 19200); //SDI=TXD,SCK=RXD // Object BLE ble; UARTService *uartServicePtr; Ticker ticker; Ticker switch_read_ticker; RingBuffer ser_bf(1024); Thread tsk; Mutex bletx_mutex; // ROM / Constant data -------------------------------------------------------- //#warning "You need to confirm your device name." const static char DEVICE_NAME[] = "UART_S"; // RAM ------------------------------------------------------------------------ Gap::Address_t my_mac; uint8_t tx_buf[BFSIZE]; uint8_t tx_len = 0; uint8_t rx_buf[BFSIZE]; 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; uint32_t sleep_time = 30; // unit:second volatile bool rx_isr_busy = false; // bool sw_now; bool sw_old; uint16_t push_cnt = 0; // Function prototypes -------------------------------------------------------- // BLE void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *); void connectionCallback(const Gap::ConnectionCallbackParams_t *params); void onDataWritten_action(const GattWriteCallbackParams *); // Tasks void pc_ser_rx(void); void data_from_ble(void); void Update_Values(void); // Application related void command(uint8_t *cmd); int xatoi (char **, int32_t *); void adjust_line(uint8_t *); // Interrupt related void serialRxCallback(void); void periodicCallback(void); void switch_tickerCallback(void); //------------------------------------------------------------------------------ // Control Program //------------------------------------------------------------------------------ int main(void) { connectedLED = 1; out_led = 1; dummy_cs = 1; sw_now = !external_sw; sw_old = sw_now; pc.attach(&serialRxCallback, Serial::RxIrq); ticker.attach(periodicCallback, 1); switch_read_ticker.attach(switch_tickerCallback, 0.1); tsk.start(pc_ser_rx); // clear terminal output for (int k = 0; k < 5; k++) { pc.printf("\r\n");} // opening message pc.printf("UART Communication / Peripheral side\r\n"); pc.printf(" need Central module (run BLE_Central_EYSGCNZWY program)\r\n"); ble.init(); Gap::AddressType_t my_mac_type; ble.gap().getAddress(&my_mac_type, my_mac); DEBUG( " my_MAC %02x:%02x:%02x:%02x:%02x:%02x (%s)\r\n", my_mac[5], my_mac[4], my_mac[3], my_mac[2], my_mac[1], my_mac[0], (my_mac_type == Gap::ADDR_TYPE_PUBLIC) ? "public" : "random" ); pc.printf( " my_MAC 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x \r\n", my_mac[0], my_mac[1], my_mac[2], my_mac[3], my_mac[4], my_mac[5] ); ble.onDisconnection(disconnectionCallback); ble.onConnection(connectionCallback); ble.onDataWritten(onDataWritten_action); /* setup advertising */ ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.accumulateAdvertisingPayload( GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) ); 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 (trigger_transmit){ static uint8_t cmd_buf[BFSIZE]; static volatile bool flag_continue = 0; trigger_transmit = false; pc.printf((const char*)rx_buf); if (flag_continue == true){ strcat((char *)cmd_buf, (char *)rx_buf); if (strchr((const char*)cmd_buf,(int)'\r') == 0){ flag_continue = true; } else { command(cmd_buf); for(uint8_t i = 0; i < BFSIZE; i++){ cmd_buf[i] = 0;} flag_continue = false; } } if ((rx_buf[0] == '~')){ strcpy((char *)cmd_buf, (char *)rx_buf); if (strchr((const char*)cmd_buf,(int)'\r') == 0){ flag_continue = true; } else { command(cmd_buf); for(uint8_t i = 0; i < BFSIZE; i++){ cmd_buf[i] = 0;} flag_continue = false; } } } ble.waitForEvent(); } } void command(uint8_t *cmd) { uint8_t *p = cmd; while(*p == ' '){ ++p;} // skip space if (*p++ == '~'){ while(*p < '!'){ ++p;} // skip space uint8_t c = *p; //pc.printf("c=%c\r\n", c); switch (c){ default: //pc.printf("\r\nStep(%u)\r\n", __LINE__); break; } } } void periodicCallback(void) { if (rx_isr_busy == true){ rx_isr_busy = false; } else { tsk.signal_set(0x01); } alivenessLED = !alivenessLED; } void switch_tickerCallback(void) { sw_old = sw_now; sw_now = !external_sw; if( sw_now ) { out_led = 0; } else { out_led = 1; } if( ( sw_now != sw_old ) && ( sw_now ) ) { // push triger push_cnt++; sprintf((char *)tx_buf,"%04X\r\n",push_cnt); tx_len = strlen((const char *)tx_buf); Update_Values(); } } void serialRxCallback() { ser_bf.save(pc.getc()); rx_isr_busy = true; tsk.signal_set(0x01); } void pc_ser_rx() { static uint8_t linebf_irq[BFSIZE]; static volatile uint8_t linebf_irq_len = 0; while(true){ Thread::signal_wait(0x01); if (ser_bf.check() == 0){ if (linebf_irq_len != 0){ linebf_irq[linebf_irq_len] = 0; adjust_line(linebf_irq); linebf_irq_len = 0; bletx_mutex.lock(); ble.updateCharacteristicValue( uartServicePtr->getRXCharacteristicHandle(), linebf_irq, NUM_ONCE ); bletx_mutex.unlock(); } } while(ser_bf.check() != 0){ char c = ser_bf.read(); if (c == '\b'){ linebf_irq_len--; pc.putc(c); pc.putc(' '); pc.putc(c); } else if ((c >= ' ') || (c == '\r') || (c == '\n')){ bool overflow = false; if ((c == '\r') || (c == '\n')) { if (linebf_irq_len == NUM_ONCE - 1){// remain only 1 buffer overflow = true; linebf_irq[linebf_irq_len++] = '\r'; pc.putc('\r'); } else { overflow = false; linebf_irq[linebf_irq_len++] = '\r'; linebf_irq[linebf_irq_len++] = '\n'; pc.printf("\r\n"); } } else { linebf_irq[linebf_irq_len++] = c; pc.putc(c); } if (linebf_irq_len >= NUM_ONCE ){ linebf_irq[linebf_irq_len] = 0; adjust_line(linebf_irq); linebf_irq_len = 0; bletx_mutex.lock(); ble.updateCharacteristicValue( uartServicePtr->getRXCharacteristicHandle(), linebf_irq, NUM_ONCE ); bletx_mutex.unlock(); if (overflow == true){ overflow = false; linebf_irq[linebf_irq_len++] = '\n'; pc.putc('\n'); } } } } } } void adjust_line(uint8_t *bf) { uint8_t i, c; for (i = 0; i <NUM_ONCE; bf++, i++){ c = *bf; if (c == 0){ break;} } for (; i < NUM_ONCE; bf++, i++){ *bf = 0x11;} *(bf + 1) = 0; } void onDataWritten_action(const GattWriteCallbackParams *params) { if ((uartServicePtr != NULL) && (params->handle == uartServicePtr->getTXCharacteristicHandle())) { strcpy((char *)rx_buf, (const char *)params->data); trigger_transmit = true; } } void action_tx_wait_time(uint8_t *cmd) { int32_t dt; char *p; p = (char *)(cmd); p += 2; // point to time value if (xatoi(&p, &dt)){ if (dt <= 5){ dt = 5;} sleep_time = dt; // set next wake-up period } else { DEBUG("data is unknown!\r\n"); sleep_time = 30; } DEBUG("slp_t:%d\r\n", sleep_time); //pc.printf("slp_t:%d\r\n", sleep_time); // 12345678901234567890 sprintf((char *)tx_buf, "W: %d sec\r\n", sleep_time); tx_len = strlen((const char *)tx_buf); Update_Values(); } // Change string -> integer int xatoi (char **str, int32_t *res) { unsigned long val; unsigned char c, radix, s = 0; for (;;){ c = **str; if (c == 0){ return 0;} if (c == '-'){ break;} if (c == '+'){ (*str)++; c = **str; } if (c>='0'&& c<='9'){ break; } else { (*str)++; c = **str; } } if (c == '-') { s = 1; c = *(++(*str)); } if (c == '0') { c = *(++(*str)); if (c <= ' ') { *res = 0; return 1; } if (c == 'x') { radix = 16; c = *(++(*str)); } else { if (c == 'b') { radix = 2; c = *(++(*str)); } else { if ((c >= '0')&&(c <= '9')) { radix = 8; } else { return 0; } } } } else { if ((c < '1')||(c > '9')) { return 0; } radix = 10; } val = 0; while (c > ' ') { if (c >= 'a') c -= 0x20; c -= '0'; if (c >= 17) { c -= 7; if (c <= 9) return 0; } if (c >= radix) return 0; val = val * radix + c; c = *(++(*str)); } if (s) val = -val; *res = val; return 1; } void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { DEBUG("Disconnected!\r\n"); DEBUG("Restarting the advertising process\r\n"); ble.startAdvertising(); connectedLED = 1; } void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { DEBUG("Connected!\r\n"); connectedLED = 0; } void Update_Values(void) { bletx_mutex.lock(); ble.updateCharacteristicValue( uartServicePtr->getRXCharacteristicHandle(), tx_buf, tx_len ); bletx_mutex.unlock(); tx_len = 0; }