nRF51822 serves as the bridge between BLE central and MCU, which makes cental able to fetch photos from serial camera.
Dependencies: BLE_API mbed nRF51822
Fork of nRF51822_blinky by
main.cpp
00001 #ifndef DEVICE_SERIAL_FC 00002 #define DEVICE_SERIAL_FC 1 00003 #endif 00004 00005 #define APPLICATION_TIMEOUT 00006 #define LOW_POWER_CONSTRAINT 00007 00008 #include "mbed.h" 00009 #include "ble/BLE.h" 00010 #include "ble/Gap.h" 00011 #include "ringBuffer.h" 00012 #include "application.h" 00013 00014 #define DEVICE_NAME "ket_045" 00015 #define CODE_VERSION 8 00016 00017 #define SDA_PIN P0_8 00018 #define SCL_PIN P0_9 00019 #define UARTTX_PIN P0_18 00020 #define UARTRX_PIN P0_17 00021 #define POWER_LED_PIN P0_11 00022 #define INSERTION_LED_PIN P0_10 00023 #define ANI_BATTERY_VOLTAGE_PIN P0_2 00024 #define ANI_USB_CHARGE_PIN P0_3 00025 #define BTN_POWER_ON_PIN P0_4 00026 #define ANI_SALIVA_VOLTAGE_PIN P0_5 00027 #define STM32_ENABLE_PIN P0_12 00028 #define CHECK_BUTTON_TIMES 2 00029 #define CHECK_BUTTON_VOLTAGE_LEVEL 0.05f 00030 00031 #ifdef LOW_POWER_CONSTRAINT 00032 #define LOW_POWER_THERS 103 // changed 5/21 00033 #define LOW_POWER_THERS_MARGIN 2 00034 #define MAXIMUM_LOW_POWER_COUNTER 30 00035 #endif 00036 00037 #define UART_BAUDRATE 14400 00038 #define MINIMUM_TICKER_PERIOD 2500 00039 00040 #define BLE_UUID_TXRX_SERVICE 0x0000 /**< The UUID of the Nordic UART Service. */ 00041 #define BLE_UUID_TX_CHARACTERISTIC 0x0002 /**< The UUID of the TX Characteristic. */ 00042 #define BLE_UUIDS_RX_CHARACTERISTIC 0x0003 /**< The UUID of the RX Characteristic. */ 00043 00044 #define BLE_GAP_CP_MIN_CONN_INTVL_MIN 0x0006 //Lowest mimimum connection interval permitted, in units of 1.25 ms, i.e. 7.5 ms. 00045 #define BLE_GAP_CP_MAX_CONN_INTVL_MAX 0x0C80 //Highest maximum connection interval permitted, in units of 1.25 ms, i.e. 4 s. 00046 #define BLE_GAP_CP_SLAVE_LATENCY_MAX 0x01F3 //Highest slave latency permitted, in connection events. 00047 #define BLE_GAP_CP_CONN_SUP_TIMEOUT_MIN 0x000A //Lowest supervision timeout permitted, in units of 10 ms, i.e. 100 ms. 00048 #define BLE_GAP_CP_CONN_SUP_TIMEOUT_MAX 0x0C80 //Highest supervision timeout permitted, in units of 10 ms, i.e. 32 s. 00049 00050 #define BLE_BUF_LEN 20 00051 #define BLE_RETRANSMISSION_BUF 18 00052 #define MONITORING_PAYLOAD 5 00053 #define SINGLE_UINT16_PAYLOAD 3 00054 #define UART_DATA_PACKET_PAYLOAD 1 00055 #define UART_PACKET_SIZE 111 00056 00057 typedef enum { 00058 SYS_POWERSAVING = 0, 00059 SYS_RELAXING_BUTTON, 00060 SYS_LOCKING_BUTTON 00061 }SystemStateTypeDef; 00062 00063 typedef enum { 00064 BTN_IDLE = 0, 00065 BTN_CHANGE_ANALOG, 00066 BTN_CHECK_LONG_PRESS 00067 }ButtonStateTypeDef; 00068 00069 typedef enum { 00070 STM32_IDLE = 0, //Cannot receive any byte from UARTRX 00071 STM32_CHECK_HEADER, //Check incoming header and forward to the client 00072 STM32_IMAGE_FORWARDING //Forward image data to the client 00073 }STM32StateTypeDef; 00074 00075 typedef enum { 00076 SYS_HEADER_IMAGE_INFO = 0, 00077 SYS_HEADER_SALIVA_VOLTAGE, // Not used (for debug purpose) 00078 SYS_HEADER_MONITORING, // Not used (for debug purpose) 00079 SYS_HEADER_IMAGE_PACKET, 00080 SYS_HEADER_DEVICE_INFO, 00081 SYS_HEADER_NO_SPECIFIC 00082 }HeaderTypeDef; 00083 00084 typedef enum { 00085 UARTRX_CHECK_FIRST_PREAMBLE = 0, 00086 UARTRX_CHECK_SECOND_PREAMBLE, 00087 UARTRX_TRANSFERING_DATA 00088 }UARTRxStateTypeDef; 00089 00090 typedef enum { 00091 BLE_TURNON_MONITORING = 0, // Enable/Disable device monitoring 00092 BLE_CHANGE_CASSETTE_ID, // Write ID to saliva cassette 00093 BLE_REQUEST_SALIVA_VOLTAGE, // Turn on saliva sampling periodically 00094 BLE_REQUEST_IMAGE_INFO, // Request image header 00095 BLE_REQUEST_IMAGE_BY_INDEX, // Request image data by uart packet IDs 00096 BLE_END_IMAGE_TRANSFER, // Directly terminate image transferring 00097 BLE_DEREQUEST_SALIVA_VOLTAGE, // Turn off saliva sampling periodically 00098 BLE_SHUTDOWN, // Shutdown device 00099 BLE_UNLOCK_BUTTON, // Unlock Button 00100 BLE_UART_DEBUG, // Reserved for debug Value: 0x09 00101 BLE_REQUEST_DEVICE_INFO, // Request code version 00102 BLE_CLOSE_MONITORING 00103 }BLECommandTypeDef; 00104 00105 /* BLE Callback functions */ 00106 void bleInitCompleteCB(struct BLE::InitializationCompleteCallbackContext *context); 00107 void bleOnConnectionCB(const Gap::ConnectionCallbackParams_t *p_conn_param); 00108 void bleDisconnectionCB(const Gap::DisconnectionCallbackParams_t *params); 00109 void bleCharacteristicWrittenCB(const GattWriteCallbackParams *Handler); 00110 void bleReduceConnInterval(void); 00111 00112 void timerPeriodicalCB(void); 00113 void timerFlashPowerLed(void); 00114 void timerFlashInsertionLed(void); 00115 void timerCheckBuffer(void); 00116 void timerRoutineTasks(void); 00117 00118 void uartTxTransmit(uint8_t* buf, uint16_t length); 00119 void uartRxCB(void); 00120 00121 void buttonInterruptServiceRoutine(void); 00122 void buttonCheckLongPress(uint8_t counter); 00123 void buttonLongPressVerified(void); 00124 void changeButtonPinToAnalogIn(void); 00125 void changeButtonPinToInterrupt(void); 00126 void shutdownDevice(void); 00127 00128 void resetSTM32StateType(void); 00129 void requestSalivaVoltage(void); 00130 void requestForImagePacket(uint16_t packetId); 00131 00132 BLE ble; 00133 Gap::Handle_t mHandle = 0; 00134 Ticker ticker; 00135 Serial pc(UARTTX_PIN, UARTRX_PIN); 00136 I2C *pI2C = NULL; 00137 DigitalOut ledPower(POWER_LED_PIN); //P0_11 00138 DigitalOut *pLedInsertion = NULL; //P0_10 Must be changed 00139 DigitalOut uartEnable(STM32_ENABLE_PIN); //P0_12 00140 InterruptIn *pButton = NULL; //P0_4 00141 AnalogIn *pButtonAnalogIn = NULL; //P0_4 00142 AnalogIn aniSalivaVolt(ANI_SALIVA_VOLTAGE_PIN); //P0_5 00143 AnalogIn aniUSBChargeVolt(ANI_USB_CHARGE_PIN); 00144 AnalogIn aniBatterVolt(ANI_BATTERY_VOLTAGE_PIN); //P0_2 00145 00146 static const uint16_t codeVersion = CODE_VERSION; 00147 00148 /* State variables for application status, UARTRX data parsing status, 00149 waiting header type and main loop trigger */ 00150 static SystemStateTypeDef systemState = SYS_RELAXING_BUTTON; 00151 static ButtonStateTypeDef buttonState = BTN_IDLE; 00152 static STM32StateTypeDef stm32State = STM32_IDLE; 00153 static UARTRxStateTypeDef uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00154 static HeaderTypeDef waitHeader = SYS_HEADER_NO_SPECIFIC; 00155 00156 /* Variables to handle data transferring. */ 00157 static uint8_t packetNum = 0; 00158 static uint8_t lastPacketSize = 0; 00159 static uint8_t currentPacketIndex = 0; 00160 static uint8_t targetPayload = 0; 00161 static uint8_t alreadyTransferred = 0; 00162 static uint8_t waitCamera = 0; 00163 static const uint8_t MAX_WAIT_TARGET_PAYLOAD = 2; 00164 static bool isRetransmit = false; 00165 static uint8_t retransmitIndex = 0; 00166 static uint8_t retransmitSize = 0; 00167 static bool setImgPktPayloadByID = false; 00168 static bool directForward = false; 00169 00170 static bool isCheckBuf = false; 00171 static bool isRoutine = false; 00172 static bool isInserted = false; 00173 static bool isEnterMainLoop = false; 00174 static bool isMonitoring = false; 00175 static bool salivaPeriodically = false; 00176 00177 static uint8_t checkButtonCounter = 0; 00178 00179 #ifdef LOW_POWER_CONSTRAINT 00180 static bool isLowPower = false; 00181 static uint8_t lowPowerCounter = 0; 00182 #endif 00183 00184 #ifdef APPLICATION_TIMEOUT 00185 static uint16_t disConnIdleCnt = 0; 00186 static uint16_t connIdleCnt = 0; 00187 static const uint16_t MAX_DISCONN_IDLE = 300; 00188 static const uint16_t MAX_CONN_IDLE = 300; 00189 #endif 00190 00191 static RingBuffer ringBuffer; 00192 static const uint8_t preamble[] = {0xFF, 0x7F}; 00193 uint8_t uartTxPayload[BLE_BUF_LEN] = {0,}; 00194 uint8_t uartRxPayload[BLE_BUF_LEN] = {0,}; 00195 uint8_t retransmitIndices[BLE_RETRANSMISSION_BUF] = {0,}; 00196 00197 // The Nordic UART Service 00198 static const uint8_t uart_base_uuid[] = {0x71, 0x3D, 0, 0, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; 00199 static const uint8_t uart_tx_uuid[] = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; 00200 static const uint8_t uart_rx_uuid[] = {0x71, 0x3D, 0, 2, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E}; 00201 static const uint8_t uart_base_uuid_rev[] = {0x1E, 0x94, 0x8D, 0xF1, 0x48, 0x31, 0x94, 0xBA, 0x75, 0x4C, 0x3E, 0x50, 0, 0, 0x3D, 0x71}; 00202 00203 /* GATTs */ 00204 GattCharacteristic txCharacteristic (uart_tx_uuid, uartTxPayload, 1, BLE_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE); 00205 GattCharacteristic rxCharacteristic (uart_rx_uuid, uartRxPayload, 1, BLE_BUF_LEN, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); 00206 GattCharacteristic *uartChars[] = {&txCharacteristic, &rxCharacteristic}; 00207 GattService uartService(uart_base_uuid, uartChars, sizeof(uartChars) / sizeof(GattCharacteristic *)); 00208 00209 int main() 00210 { 00211 pc.baud(UART_BAUDRATE); 00212 pc.attach(uartRxCB , pc.RxIrq); 00213 pc.set_flow_control(pc.Disabled); 00214 RingBuffer_init(&ringBuffer); 00215 uartEnable = 1; 00216 00217 pI2C = new I2C(SDA_PIN, SCL_PIN); 00218 pLedInsertion = new DigitalOut(INSERTION_LED_PIN); 00219 pLedInsertion->write(1); 00220 ledPower = 0; 00221 00222 ticker.attach_us(timerPeriodicalCB, MINIMUM_TICKER_PERIOD); 00223 pButton = new InterruptIn(BTN_POWER_ON_PIN); 00224 pButton->fall(buttonInterruptServiceRoutine); 00225 00226 ble.init(bleInitCompleteCB); 00227 ble.onConnection(bleOnConnectionCB); 00228 ble.onDisconnection(bleDisconnectionCB); 00229 ble.onDataWritten(bleCharacteristicWrittenCB); 00230 00231 // Adjust interrupt priority 00232 // NVIC_SetPriority(RADIO_IRQn, 0); 00233 // NVIC_SetPriority(UART0_IRQn, 1); 00234 // NVIC_SetPriority(RTC1_IRQn, 2); 00235 00236 // setup advertising // Restricted to 31 bytes 00237 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); 00238 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); 00239 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, (const uint8_t *)"BLETest", sizeof("BLETest") - 1); 00240 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (const uint8_t *)uart_base_uuid_rev, sizeof(uart_base_uuid)); 00241 ble.gap().setDeviceName("BLETest"); 00242 00243 ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) - 1); 00244 ble.setAdvertisingInterval(160); // 100ms; in multiples of 0.625ms. 00245 ble.addService(uartService); 00246 00247 ble.startAdvertising(); 00248 00249 while(true){ 00250 00251 #ifdef LOW_POWER_CONSTRAINT 00252 if(lowPowerCounter > MAXIMUM_LOW_POWER_COUNTER){ 00253 shutdownDevice(); 00254 } 00255 #endif 00256 00257 #ifdef APPLICATION_TIMEOUT 00258 if(disConnIdleCnt >= MAX_DISCONN_IDLE && systemState == SYS_RELAXING_BUTTON){ 00259 shutdownDevice(); 00260 } 00261 else if(connIdleCnt >= MAX_CONN_IDLE){ 00262 if(mHandle != 0) 00263 ble.disconnect(mHandle, Gap::CONNECTION_TIMEOUT); 00264 systemState = SYS_RELAXING_BUTTON; 00265 } 00266 #endif 00267 00268 switch (systemState) { 00269 case SYS_POWERSAVING: 00270 case SYS_RELAXING_BUTTON: 00271 switch (buttonState) { 00272 case BTN_CHANGE_ANALOG: 00273 changeButtonPinToAnalogIn(); 00274 break; 00275 case BTN_CHECK_LONG_PRESS: 00276 buttonCheckLongPress(checkButtonCounter); 00277 break; 00278 case BTN_IDLE: 00279 default: 00280 break; 00281 } 00282 break; 00283 case SYS_LOCKING_BUTTON: 00284 buttonState = BTN_IDLE; 00285 break; 00286 } 00287 00288 if(isCheckBuf){ 00289 isCheckBuf = false; 00290 timerCheckBuffer(); 00291 } 00292 00293 if(isRoutine){ 00294 isRoutine = false; 00295 timerRoutineTasks(); 00296 } 00297 00298 if( isEnterMainLoop ){ 00299 switch (stm32State){ 00300 case STM32_IMAGE_FORWARDING: 00301 { 00302 if (setImgPktPayloadByID == false){ 00303 uint8_t check = 0; 00304 RingBuffer_read(&ringBuffer, &check, 1); 00305 HeaderTypeDef header = static_cast<HeaderTypeDef>(check); 00306 if (header == SYS_HEADER_IMAGE_PACKET){ 00307 if (currentPacketIndex != (packetNum-1)) 00308 targetPayload = UART_PACKET_SIZE + 3; 00309 else 00310 targetPayload = lastPacketSize + 3; 00311 00312 alreadyTransferred = 0; 00313 setImgPktPayloadByID = true; 00314 waitCamera = 0; 00315 } 00316 } 00317 else { 00318 uint16_t numBytes = RingBuffer_availableDataAmount(&ringBuffer); 00319 while((numBytes >= (BLE_BUF_LEN-1)) || (directForward == true)){ 00320 waitCamera = 0; 00321 uint16_t diff = numBytes; 00322 if(diff > (BLE_BUF_LEN-1)) 00323 diff = (BLE_BUF_LEN-1); 00324 uartRxPayload[0] = static_cast<uint8_t>(SYS_HEADER_IMAGE_PACKET); 00325 00326 RingBuffer_read(&ringBuffer, uartRxPayload+1, diff); 00327 00328 if(mHandle != 0){ 00329 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), uartRxPayload, diff+1); 00330 alreadyTransferred += diff; 00331 numBytes -= diff; 00332 } 00333 00334 if(directForward == true || alreadyTransferred >= targetPayload){ 00335 __disable_irq(); // Disable Interrupts 00336 setImgPktPayloadByID = false; 00337 __enable_irq(); 00338 directForward = false; 00339 RingBuffer_init(&ringBuffer); 00340 00341 if(isRetransmit == false){ 00342 currentPacketIndex++; 00343 } 00344 else{ 00345 retransmitIndex++; 00346 if(retransmitIndex >= retransmitSize){ 00347 retransmitSize = 0; 00348 resetSTM32StateType(); 00349 break; 00350 } 00351 else{ 00352 currentPacketIndex = retransmitIndices[retransmitIndex]; 00353 } 00354 } 00355 00356 if(currentPacketIndex == packetNum && isRetransmit == false){ 00357 /* TODO retransmission */ 00358 isRetransmit = true; 00359 if(retransmitSize > 0){ 00360 uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00361 retransmitIndex = 0; 00362 currentPacketIndex = retransmitIndices[retransmitIndex]; 00363 requestForImagePacket(currentPacketIndex); 00364 } 00365 else{ 00366 resetSTM32StateType(); 00367 } 00368 } 00369 else{ 00370 uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00371 requestForImagePacket(currentPacketIndex); 00372 } 00373 break; 00374 } 00375 } 00376 } 00377 break; 00378 } 00379 case STM32_CHECK_HEADER: 00380 { 00381 uint8_t buf[BLE_BUF_LEN] = {0,}; 00382 HeaderTypeDef header; 00383 switch (waitHeader) { 00384 /* Image info */ 00385 case SYS_HEADER_IMAGE_INFO: 00386 { 00387 RingBuffer_read(&ringBuffer, buf, 1); 00388 header = static_cast<HeaderTypeDef>(buf[0]); 00389 if (header == SYS_HEADER_IMAGE_INFO){ 00390 RingBuffer_read(&ringBuffer, buf+1, SINGLE_UINT16_PAYLOAD-1); 00391 if(mHandle != 0) 00392 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, SINGLE_UINT16_PAYLOAD); 00393 00394 uint16_t totalDataLength = buf[1]*256 + buf[2]; 00395 packetNum = totalDataLength/UART_PACKET_SIZE; 00396 lastPacketSize = totalDataLength%UART_PACKET_SIZE; 00397 if(totalDataLength%UART_PACKET_SIZE != 0) 00398 packetNum++; 00399 else 00400 lastPacketSize = UART_PACKET_SIZE; 00401 00402 currentPacketIndex = 0; 00403 resetSTM32StateType(); 00404 } 00405 break; 00406 } 00407 case SYS_HEADER_SALIVA_VOLTAGE: 00408 // { 00409 // RingBuffer_read(&ringBuffer, buf, 1); 00410 // header = static_cast<HeaderTypeDef>(buf[0]); 00411 // if (header == SYS_HEADER_SALIVA_VOLTAGE){ 00412 // RingBuffer_read(&ringBuffer, buf+1, SINGLE_UINT16_PAYLOAD-1); 00413 // if(mHandle != 0) 00414 // ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, SINGLE_UINT16_PAYLOAD); 00415 // 00416 // stm32State = STM32_CHECK_HEADER; 00417 // uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00418 // } 00419 // break; 00420 // } 00421 case SYS_HEADER_NO_SPECIFIC: 00422 default: 00423 break; 00424 } 00425 break; 00426 } 00427 case STM32_IDLE: 00428 default: 00429 break; 00430 } 00431 isEnterMainLoop = false; 00432 } 00433 ble.waitForEvent(); 00434 } 00435 } 00436 00437 void bleInitCompleteCB(struct BLE::InitializationCompleteCallbackContext *context){ 00438 if (context->error != BLE_ERROR_NONE) 00439 return; 00440 00441 if (context->ble.getInstanceID() == BLE::DEFAULT_INSTANCE){ 00442 /* use the BLE instance */ 00443 return; 00444 } 00445 } 00446 00447 void bleOnConnectionCB(const Gap::ConnectionCallbackParams_t *p_conn_param){ 00448 mHandle = p_conn_param->handle; 00449 #ifdef APPLICATION_TIMEOUT 00450 connIdleCnt = 0; 00451 #endif 00452 bleReduceConnInterval(); 00453 } 00454 00455 void bleDisconnectionCB(const Gap::DisconnectionCallbackParams_t *params){ 00456 mHandle = 0; 00457 if(systemState != SYS_POWERSAVING){ 00458 #ifdef APPLICATION_TIMEOUT 00459 disConnIdleCnt = 0; 00460 #endif 00461 ble.startAdvertising(); 00462 } 00463 } 00464 00465 void bleCharacteristicWrittenCB(const GattWriteCallbackParams *Handler){ 00466 uint16_t bleBytesRead; 00467 if (Handler->handle == txCharacteristic.getValueAttribute().getHandle()) 00468 { 00469 #ifdef APPLICATION_TIMEOUT 00470 connIdleCnt = 0; 00471 #endif 00472 ble.readCharacteristicValue(txCharacteristic.getValueAttribute().getHandle(), uartTxPayload, &bleBytesRead); 00473 if(bleBytesRead == 0) 00474 return; 00475 00476 BLECommandTypeDef command = static_cast<BLECommandTypeDef>(uartTxPayload[0]); 00477 bool isUARTCommand = false; 00478 switch(command){ 00479 case BLE_TURNON_MONITORING: 00480 isMonitoring = true; 00481 break; 00482 case BLE_CLOSE_MONITORING: 00483 isMonitoring = false; 00484 break; 00485 case BLE_REQUEST_SALIVA_VOLTAGE: 00486 waitHeader = SYS_HEADER_SALIVA_VOLTAGE; 00487 salivaPeriodically = true; 00488 systemState = SYS_LOCKING_BUTTON; // Lock Begin 00489 break; 00490 case BLE_DEREQUEST_SALIVA_VOLTAGE: 00491 salivaPeriodically = false; 00492 break; 00493 case BLE_REQUEST_IMAGE_INFO: 00494 waitHeader = SYS_HEADER_IMAGE_INFO; 00495 isUARTCommand = true; 00496 salivaPeriodically = false; 00497 break; 00498 case BLE_END_IMAGE_TRANSFER: 00499 isRetransmit = false; 00500 packetNum = 0; 00501 resetSTM32StateType(); 00502 break; 00503 case BLE_SHUTDOWN: 00504 changeButtonPinToInterrupt(); 00505 shutdownDevice(); 00506 break; 00507 case BLE_UNLOCK_BUTTON: 00508 { 00509 systemState = SYS_RELAXING_BUTTON; 00510 buttonState = BTN_IDLE; 00511 break; 00512 } 00513 case BLE_UART_DEBUG: 00514 { 00515 uint8_t debugHeader = 0xF1; 00516 uartTxTransmit(&debugHeader, 1); 00517 break; 00518 } 00519 case BLE_REQUEST_IMAGE_BY_INDEX: 00520 if(bleBytesRead >= 2){ 00521 uint8_t check = uartTxPayload[1]; 00522 if(check == 0){ 00523 if(packetNum > 0){ 00524 setImgPktPayloadByID = false; 00525 directForward = false; 00526 RingBuffer_init(&ringBuffer); 00527 currentPacketIndex = 0; 00528 isRetransmit = false; 00529 retransmitSize = 0; 00530 stm32State = STM32_IMAGE_FORWARDING; 00531 uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00532 requestForImagePacket(currentPacketIndex); 00533 } 00534 } 00535 else if(check <= 18){ 00536 if(bleBytesRead < check+2) 00537 break; 00538 retransmitSize = check; 00539 memcpy(retransmitIndices, uartTxPayload+2, retransmitSize); 00540 if(isRetransmit == true){ 00541 stm32State = STM32_IMAGE_FORWARDING; 00542 uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00543 retransmitIndex = 0; 00544 currentPacketIndex = retransmitIndices[retransmitIndex]; 00545 requestForImagePacket(currentPacketIndex); 00546 } 00547 else{ 00548 uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00549 requestForImagePacket(currentPacketIndex); 00550 } 00551 } 00552 else{ 00553 /* Invalid check number */ 00554 } 00555 } 00556 break; 00557 case BLE_CHANGE_CASSETTE_ID: 00558 if(bleBytesRead >= 3) 00559 writeAT24EEPROMBuffer(*pI2C, 0, (char*)uartTxPayload+1, 2); 00560 break; 00561 case BLE_REQUEST_DEVICE_INFO: 00562 { 00563 uint8_t buf[SINGLE_UINT16_PAYLOAD] = {0,}; 00564 buf[0] = SYS_HEADER_DEVICE_INFO; 00565 buf[1] = (codeVersion >> 8) & 0xFF; 00566 buf[2] = codeVersion & 0xFF; 00567 if(mHandle != 0) 00568 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, SINGLE_UINT16_PAYLOAD); 00569 00570 break; 00571 } 00572 default: 00573 break; 00574 } 00575 if(isUARTCommand){ 00576 stm32State = STM32_CHECK_HEADER; 00577 uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00578 uartTxTransmit(uartTxPayload, 1); 00579 } 00580 } 00581 } 00582 00583 void bleReduceConnInterval(void){ 00584 Gap::ConnectionParams_t bleGapConnParamInitStruct; 00585 bleGapConnParamInitStruct.minConnectionInterval = BLE_GAP_CP_MIN_CONN_INTVL_MIN; /*Minimum Connection Interval in 1.25 ms*/ 00586 bleGapConnParamInitStruct.maxConnectionInterval = BLE_GAP_CP_MIN_CONN_INTVL_MIN; /*Minimum Connection Interval in 1.25 ms*/ 00587 bleGapConnParamInitStruct.slaveLatency = 0; /*Slave Latency in number of connection events*/ 00588 bleGapConnParamInitStruct.connectionSupervisionTimeout = BLE_GAP_CP_CONN_SUP_TIMEOUT_MIN; /*Connection Supervision Timeout in 10 ms*/ 00589 00590 ble.gap().updateConnectionParams(mHandle, &bleGapConnParamInitStruct); 00591 } 00592 00593 void timerPeriodicalCB(void){ 00594 static uint32_t time = 0; 00595 time++; 00596 00597 if ( time % 100 == 2 ) { // 250ms 00598 if(buttonState == BTN_CHECK_LONG_PRESS) 00599 checkButtonCounter++; 00600 } 00601 00602 if(systemState != SYS_POWERSAVING){ 00603 if ( time % 3 == 1 ) { // 7.5ms 00604 isCheckBuf = true; 00605 } 00606 00607 // if ( time % 50 == 2 ) { // 250ms 00608 // if(isInserted) 00609 // timerFlashPowerLed(); 00610 // } 00611 00612 if ( time % 200 == 3 ) { // 500ms 00613 #ifdef LOW_POWER_CONSTRAINT 00614 if(isLowPower){ 00615 timerFlashPowerLed(); 00616 lowPowerCounter++; 00617 } 00618 #endif 00619 00620 if(isInserted && systemState == SYS_LOCKING_BUTTON){ 00621 timerFlashInsertionLed(); 00622 } 00623 } 00624 00625 if ( time % 400 == 4 ) { // 1s 00626 isRoutine = true; 00627 #ifdef APPLICATION_TIMEOUT 00628 if(mHandle == 0) 00629 disConnIdleCnt++; 00630 else 00631 connIdleCnt++; 00632 #endif 00633 } 00634 00635 if ( time % 800 == 5 ) { 00636 if(salivaPeriodically == true) 00637 requestSalivaVoltage(); 00638 } 00639 } 00640 } 00641 00642 void timerFlashPowerLed(void){ 00643 ledPower = !ledPower; 00644 } 00645 00646 void timerFlashInsertionLed(void){ 00647 int tmp = pLedInsertion->read(); 00648 pLedInsertion->write(!tmp); 00649 } 00650 00651 void timerRoutineTasks(void){ 00652 uint8_t buf[BLE_BUF_LEN] = {0,}; 00653 buf[0] = SYS_HEADER_MONITORING; 00654 bool result = readAT24EEPROMBuffer(*pI2C, 0, (char*)buf+1, 2); 00655 00656 if(result == false){ 00657 pLedInsertion->write(1); 00658 isInserted = false; 00659 buf[1] = 0xFF; 00660 buf[2] = 0xFF; 00661 00662 // If no ID detected, system will unlock button automatically. 5/17 00663 if(systemState == SYS_LOCKING_BUTTON){ 00664 systemState = SYS_RELAXING_BUTTON; 00665 buttonState = BTN_IDLE; 00666 } 00667 } 00668 else{ 00669 isInserted = true; 00670 if(systemState != SYS_LOCKING_BUTTON){ 00671 pLedInsertion->write(0); 00672 } 00673 00674 if(systemState == SYS_POWERSAVING){ 00675 pLedInsertion->write(1); 00676 } 00677 } 00678 00679 float fvalue = (float)aniBatterVolt.read()*3.3*100; 00680 uint16_t ivalue = (uint16_t)fvalue; 00681 buf[3] = (ivalue >> 8) & 0xFF; 00682 buf[4] = ivalue & 0xFF; 00683 00684 #ifdef LOW_POWER_CONSTRAINT 00685 if(!isLowPower && ivalue < (LOW_POWER_THERS-LOW_POWER_THERS_MARGIN)){ 00686 isLowPower = true; 00687 lowPowerCounter = 0; 00688 } 00689 else if(isLowPower && ivalue > (LOW_POWER_THERS+LOW_POWER_THERS_MARGIN)){ 00690 isLowPower = false; 00691 } 00692 #endif 00693 00694 if(mHandle != 0 && isMonitoring == true){ 00695 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, MONITORING_PAYLOAD); 00696 } 00697 } 00698 00699 void uartTxTransmit(uint8_t* buf, uint16_t length){ 00700 uint16_t index; 00701 pc.putc(preamble[0]); 00702 pc.putc(preamble[1]); 00703 for(index = 0; index < length; index++) 00704 { 00705 pc.putc(buf[index]); 00706 } 00707 } 00708 00709 // UARTRX Callback function 00710 void uartRxCB(void){ 00711 while(pc.readable()) 00712 { 00713 uint8_t byteIn = pc.getc(); 00714 if(stm32State == STM32_IDLE) 00715 continue; 00716 00717 if(uartRxState == UARTRX_TRANSFERING_DATA){ 00718 RingBuffer_writebyte(&ringBuffer, byteIn); 00719 } 00720 else if(uartRxState == UARTRX_CHECK_FIRST_PREAMBLE && byteIn == preamble[0]){ 00721 uartRxState = UARTRX_CHECK_SECOND_PREAMBLE; 00722 } 00723 else if(uartRxState == UARTRX_CHECK_SECOND_PREAMBLE && byteIn == preamble[1]){ 00724 uartRxState = UARTRX_TRANSFERING_DATA; 00725 } 00726 } 00727 } 00728 00729 void buttonInterruptServiceRoutine(void){ 00730 if(buttonState == BTN_IDLE) 00731 buttonState = BTN_CHANGE_ANALOG; 00732 00733 if(systemState == SYS_POWERSAVING) 00734 ticker.attach_us(timerPeriodicalCB, MINIMUM_TICKER_PERIOD); 00735 } 00736 00737 void buttonCheckLongPress(uint8_t counter){ 00738 if(counter < CHECK_BUTTON_TIMES){ 00739 if(pButtonAnalogIn != NULL && (float)pButtonAnalogIn->read() < CHECK_BUTTON_VOLTAGE_LEVEL){ 00740 return; 00741 } 00742 else if(systemState == SYS_POWERSAVING){ 00743 ticker.detach(); 00744 } 00745 } 00746 else{ 00747 buttonLongPressVerified(); 00748 } 00749 changeButtonPinToInterrupt(); 00750 } 00751 00752 void buttonLongPressVerified(void){ 00753 checkButtonCounter = 0; 00754 if(systemState == SYS_POWERSAVING){ 00755 systemState = SYS_RELAXING_BUTTON; 00756 ble.startAdvertising(); 00757 #ifdef APPLICATION_TIMEOUT 00758 disConnIdleCnt = 0; 00759 #endif 00760 ticker.attach_us(timerPeriodicalCB, MINIMUM_TICKER_PERIOD); 00761 ledPower = 0; 00762 uartEnable = 1; 00763 resetSTM32StateType(); 00764 } 00765 else if(systemState == SYS_RELAXING_BUTTON){ 00766 shutdownDevice(); 00767 } 00768 } 00769 00770 void changeButtonPinToAnalogIn(void){ 00771 pButton->fall(NULL); 00772 delete pButton; 00773 checkButtonCounter = 0; 00774 pButtonAnalogIn = new AnalogIn(BTN_POWER_ON_PIN); 00775 buttonState = BTN_CHECK_LONG_PRESS; 00776 } 00777 00778 void changeButtonPinToInterrupt(void){ 00779 delete pButtonAnalogIn; 00780 pButton = new InterruptIn(BTN_POWER_ON_PIN); 00781 pButton->fall(buttonInterruptServiceRoutine); 00782 float dummy = (float)pButtonAnalogIn->read(); 00783 buttonState = BTN_IDLE; 00784 } 00785 00786 void shutdownDevice(void){ 00787 systemState = SYS_POWERSAVING; 00788 if(mHandle != 0) 00789 ble.disconnect(mHandle, Gap::REMOTE_USER_TERMINATED_CONNECTION); 00790 pLedInsertion->write(1); 00791 ticker.detach(); 00792 ble.gap().stopAdvertising(); 00793 ledPower = 1; 00794 uartEnable = 0; 00795 isMonitoring = false; 00796 salivaPeriodically = false; 00797 #ifdef LOW_POWER_CONSTRAINT 00798 lowPowerCounter = 0; 00799 #endif 00800 deepsleep(); 00801 } 00802 00803 void resetSTM32StateType(void){ 00804 stm32State = STM32_IDLE; 00805 uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00806 waitHeader = SYS_HEADER_NO_SPECIFIC; 00807 } 00808 00809 void requestSalivaVoltage(void){ 00810 uint8_t buf[BLE_BUF_LEN] = {0,}; 00811 float fvalue = aniSalivaVolt.read()*3.3*100; 00812 uint16_t ivalue = (uint16_t)fvalue; 00813 00814 buf[0] = SYS_HEADER_SALIVA_VOLTAGE; 00815 buf[1] = (ivalue >> 8) & 0xFF; 00816 buf[2] = ivalue & 0xFF; 00817 00818 if(mHandle != 0) 00819 ble.updateCharacteristicValue(rxCharacteristic.getValueAttribute().getHandle(), buf, SINGLE_UINT16_PAYLOAD); 00820 } 00821 00822 void timerCheckBuffer(void){ 00823 uint16_t numBytes = RingBuffer_availableDataAmount(&ringBuffer); 00824 switch (stm32State) { 00825 case STM32_CHECK_HEADER:{ 00826 if (numBytes >= SINGLE_UINT16_PAYLOAD){ 00827 isEnterMainLoop = true; 00828 } 00829 break; 00830 } 00831 case STM32_IMAGE_FORWARDING: 00832 { 00833 if(setImgPktPayloadByID == false){ 00834 if(numBytes >= UART_DATA_PACKET_PAYLOAD){ 00835 isEnterMainLoop = true; 00836 } 00837 else{ 00838 if (waitCamera > MAX_WAIT_TARGET_PAYLOAD){ 00839 setImgPktPayloadByID = false; 00840 directForward = false; 00841 RingBuffer_init(&ringBuffer); 00842 requestForImagePacket(currentPacketIndex); 00843 waitCamera = 0; 00844 } 00845 } 00846 } 00847 else { 00848 if((targetPayload-alreadyTransferred) <= (BLE_BUF_LEN-1)){ 00849 if(numBytes+alreadyTransferred == targetPayload) 00850 directForward = true; 00851 } 00852 00853 if (numBytes > 0){ 00854 isEnterMainLoop = true; 00855 } 00856 00857 else if (waitCamera > MAX_WAIT_TARGET_PAYLOAD){ 00858 uartRxState = UARTRX_CHECK_FIRST_PREAMBLE; 00859 requestForImagePacket(currentPacketIndex); 00860 waitCamera = 0; 00861 } 00862 00863 } 00864 break; 00865 } 00866 default: 00867 break; 00868 } 00869 } 00870 00871 void requestForImagePacket(uint16_t packetId){ 00872 uint8_t tempBuf[3]; 00873 tempBuf[0] = static_cast<uint8_t>(BLE_REQUEST_IMAGE_BY_INDEX); 00874 tempBuf[1] = (packetId >> 8) & 0xFF; 00875 tempBuf[2] = packetId & 0xFF; 00876 uartTxTransmit(tempBuf, 3); 00877 } 00878 00879 void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) { 00880 FlowControl flow_type = (FlowControl)type; 00881 switch(type) { 00882 case RTS: 00883 serial_set_flow_control(&_serial, flow_type, flow1, NC); 00884 break; 00885 00886 case CTS: 00887 serial_set_flow_control(&_serial, flow_type, NC, flow1); 00888 break; 00889 00890 case RTSCTS: 00891 case Disabled: 00892 serial_set_flow_control(&_serial, flow_type, flow1, flow2); 00893 break; 00894 00895 default: 00896 break; 00897 } 00898 }
Generated on Sun Jul 24 2022 10:29:02 by 1.7.2