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 RedBearLab

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }