Jules Thuillier / Mbed 2 deprecated OldRemote

Dependencies:   BLE_API mbed nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "BLEDevice.h"
00003 
00004 #include "DFUService.h"
00005 
00006 //UART Primary Service
00007 #include "UARTService.h"
00008  
00009 //Battery and DeviceInformation Auxilary Services
00010 #include "BatteryService.h"
00011 #include "DeviceInformationService.h"
00012 
00013 #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console;
00014                                * it will have an impact on code-size and power consumption. */
00015 #if NEED_CONSOLE_OUTPUT
00016 #define DEBUG(...) { printf(__VA_ARGS__);}
00017 #else
00018 #define DEBUG(...) /* nothing */
00019 #endif /* #if NEED_CONSOLE_OUTPUT */ 
00020 
00021 #define RECORD_OFF_TIMER 12000
00022 #define ADV_INTERVAL 1600 /* 1000ms; in multiples of 0.625ms. */
00023 #define ADV_TIMEOUT 30 /* in seconds */
00024 #define BUTTON_SHUTDOWN_DELAY 4
00025 
00026 #define NRF51822 0
00027 
00028     /* Initialisation des entrées sorties */
00029 
00030 PinName ir = P0_6;
00031 PwmOut irled(P0_12); 
00032 
00033 static char const DEVICE_NAME[] = "OldRemote";
00034 
00035 BLEDevice ble;
00036 UARTService *uartServicePtr;
00037 BatteryService *battServicePtr;
00038 
00039 enum States {DISCONNECTED, OFF, ADVERTISING, CONNECTED};
00040 States currentState = DISCONNECTED;
00041 
00042 // Timer pour connaitre la duree de l'enfoncement
00043 Timer timer;
00044 Timer timerUp;
00045 Timer timerDown;
00046 Timeout recordOffTimer;
00047 
00048 // Ticker pour un reveil toutes ls 1 secondes
00049 Ticker ticker;
00050 bool startPeriodick = false;
00051 // Turn the device off
00052 
00053 uint16_t recordBuffers [3][100];
00054 uint8_t indexi = 0, indexj = 0;
00055 
00056 uint16_t sendBuffer [100];
00057 uint8_t sendBufferIndex = 0;
00058 
00059 bool receivingDatas = false;
00060 bool recording = false;
00061 
00062 // Convertit un tableau de char en int
00063 int char_to_int(char *data)
00064 {
00065     int i;
00066     sscanf(data, "%d", &i);
00067     return i;
00068 }
00069 
00070 
00071 /* Envoi en infrarouge les données passées en parametre
00072  * PROTOCOL :
00073  * first data : array size - 1 (number of HIGH - LOW datas)
00074  * every odd index : duration of HIGH
00075  * every even index : duration of LOW
00076  */
00077 void sendIR(uint16_t *data)
00078 {
00079     uint8_t size = data[0];
00080     // Start at index 1, as index 0 is buffer length
00081     for(int i=1; i<size; i++)
00082     {
00083             // HIGH 
00084             if((i%2)==1)
00085             {
00086                 irled.write(0.33f);
00087             }    
00088             // LOW 
00089             else
00090             {
00091                 irled.write(0);
00092             }
00093             
00094             wait_us(data[i]);   
00095     }
00096     irled.write(0);
00097 }
00098 
00099 
00100 /* 
00101  * Renvoie le dernier signal IR
00102  */
00103 void repeat()
00104 {
00105     if(sendBuffer[0] != 0)
00106     {
00107         sendIR(sendBuffer); 
00108     }   
00109 }
00110 
00111 void prepareForReception()
00112 {
00113     for(int i=0; i<100; i++)
00114     {
00115      sendBuffer[i] = 0;   
00116     }    
00117 }
00118 
00119 
00120 /* Set the IR frequency 
00121  * Param : frequency in Kilohertz
00122  */
00123 void setFrequency(int freq)
00124 {
00125     DEBUG("Frequency : %d\r\n", freq);
00126     uint8_t period = 1000/freq;
00127     irled.period_us(period);
00128 }
00129 
00130 
00131 // Vide le buffer dont l'index est passe en parametre
00132 void clearBuffer(int index)
00133 {
00134     for(int j=0; j<100;j++){
00135         recordBuffers[index][j] = 0;
00136     }
00137 }
00138 
00139 
00140 // Vide tous les buffers
00141 void clearBuffers()
00142 {
00143     for(int j=0; j<3;j++){
00144         clearBuffer(j);
00145     }
00146 }
00147 
00148 
00149 void disconnect()
00150 {
00151     DEBUG("Shutting down\r\n");
00152     
00153     // Arrete le timer
00154     timer.stop();
00155     
00156 
00157     // Supprime l'appel toutes les 1 secondes
00158     ticker.detach();
00159   
00160     Gap::DisconnectionReason_t myreason;
00161     ble.disconnect(myreason);
00162     
00163     currentState = OFF;
00164 }
00165 
00166 uint8_t getBattery()
00167 {
00168  // Configure ADC
00169     NRF_ADC->CONFIG     = (ADC_CONFIG_RES_8bit                        << ADC_CONFIG_RES_Pos)     |
00170                           (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos)  |
00171                           (ADC_CONFIG_REFSEL_VBG                      << ADC_CONFIG_REFSEL_Pos)  |
00172                           (ADC_CONFIG_PSEL_Disabled                   << ADC_CONFIG_PSEL_Pos)    |
00173                           (ADC_CONFIG_EXTREFSEL_None                  << ADC_CONFIG_EXTREFSEL_Pos);
00174     NRF_ADC->EVENTS_END = 0;
00175     NRF_ADC->ENABLE     = ADC_ENABLE_ENABLE_Enabled;
00176 
00177     NRF_ADC->EVENTS_END  = 0;    // Stop any running conversions.
00178     NRF_ADC->TASKS_START = 1;
00179     
00180     while (!NRF_ADC->EVENTS_END)
00181     {
00182     }
00183     
00184     uint16_t vbg_in_mv = 1200;
00185     uint8_t adc_max = 255;
00186     uint16_t vbat_current_in_mv = (NRF_ADC->RESULT * 3 * vbg_in_mv) / adc_max;
00187     
00188     NRF_ADC->EVENTS_END     = 0;
00189     NRF_ADC->TASKS_STOP     = 1;
00190     
00191     return (uint8_t) ((vbat_current_in_mv * 100) / 3700);   
00192  
00193  //   return 12;   
00194 }
00195 
00196 
00197 // Fontion appelé toutes les 1 secondes lorsque le telephoen est connecté
00198 void periodicCallback(void)
00199 {
00200   //  uint8_t batt = getBattery();
00201  //   uint8_t batt = 42;
00202    // DEBUG("Periodic Callback \n\r");
00203     //if (battServicePtr != NULL)
00204    //     battServicePtr->updateBatteryLevel(batt);
00205    // DEBUG("Battery : %d \n\r", batt);
00206 
00207 }
00208 // Callback appelé en cas de deconnection
00209 void onDisconnection(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
00210 {
00211     DEBUG("Disconnected \n\r");
00212 
00213     if(currentState != OFF)
00214     {
00215          //   printf("Restarting the advertising process\n\r");
00216         ble.startAdvertising();
00217         currentState = DISCONNECTED;
00218     }
00219     
00220     switch (reason) {
00221     case Gap::REMOTE_USER_TERMINATED_CONNECTION:
00222         DEBUG("Disconnected (REMOTE_USER_TERMINATED_CONNECTION)\n\r");
00223         break;
00224     case Gap::LOCAL_HOST_TERMINATED_CONNECTION:
00225         DEBUG("Disconnected (LOCAL_HOST_TERMINATED_CONNECTION)\n\r");
00226         break;
00227     case Gap::CONN_INTERVAL_UNACCEPTABLE:
00228         DEBUG("Disconnected (CONN_INTERVAL_UNACCEPTABLE)\n\r");
00229         break;
00230     }
00231 
00232 }
00233 
00234 // Callback appelé lorsque la connection est etablie
00235 void onConnection(Gap::Handle_t handle, Gap::addr_type_t peerAddrType, const Gap::address_t peerAddr, const Gap::ConnectionParams_t *param)
00236 {
00237     DEBUG("Connected\n\r"); 
00238     currentState = CONNECTED;
00239 }
00240 
00241 
00242 // Callback appelé lorsque l'advertising arrive a son timeout avant que la connexion ait été établie
00243 void onTimeout()
00244 {
00245     DEBUG("Timeout \n\r");
00246     disconnect();
00247 }
00248 
00249 
00250 void sendUART(char *data, int size)
00251 {
00252     uint8_t  buf[size];
00253     for(int i=0; i< size; i++)
00254         {
00255            buf[i] = (uint8_t)data[i];
00256         }
00257     ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), buf, size);
00258 }
00259 
00260 
00261 // Callback appelé lorsque le service uart recoit des données
00262 void receiveUART(const GattCharacteristicWriteCBParams *params)
00263 {
00264     if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) {
00265         uint16_t bytesRead = params->len;
00266 
00267         DEBUG("Data received : %*s\n\r", params->len, params->data);
00268         DEBUG("Data length : %d\n\r", bytesRead);
00269         
00270         // get all the data in one array
00271         uint8_t  buf[bytesRead];
00272         uint16_t split = bytesRead;
00273         for(int i=0; i< bytesRead; i++)
00274         {
00275            buf[i] = params->data[i];
00276            if((char)buf[i] == ':' )
00277            {
00278             DEBUG("Split at %u\n\r", i);
00279             split = i;
00280            } 
00281         }
00282         char  option[split];
00283         char  arg[bytesRead - (split+1)];
00284         
00285         // split array to get option
00286         for(int i=0; i< split; i++)
00287         {
00288            option[i] = buf[i];
00289         }
00290 
00291         // split array to get argument
00292         if(split<bytesRead)
00293         {
00294             for(int i=split+1; i < bytesRead; i++)
00295             {
00296                arg[i-(split+1)] = buf[i];
00297             }
00298             
00299         }
00300         
00301         // Get ready to receive the datas to send
00302         if(strncmp(option, "send", split) == 0)
00303         {   
00304             
00305             prepareForReception();
00306             sendBuffer[0] = char_to_int(arg); 
00307             receivingDatas = true;  
00308             DEBUG("Receiving datas\r\n");
00309         }
00310         
00311         
00312         // Set the frequency
00313         else if(strncmp(option, "setfreq", split) == 0)
00314         {   
00315             setFrequency(char_to_int(arg));    
00316         }
00317         
00318         // Repeat the last emission
00319         else if(strncmp(option, "repeat", split) == 0)
00320         {   
00321             repeat();    
00322         }
00323         
00324         // Start recording
00325         else if(strncmp(option, "record", split) == 0)
00326         {   
00327              
00328         }
00329         
00330         
00331         else if(receivingDatas)
00332         {  
00333             int duration = char_to_int(option);
00334             DEBUG("data : %u\r\n", duration);
00335             
00336             if(duration != 0)
00337             {
00338                 sendBufferIndex++;
00339                 sendBuffer[sendBufferIndex] = duration;
00340                 
00341                 if(sendBufferIndex == sendBuffer[0])
00342                 {
00343                     DEBUG("Reception Over\r\n"); 
00344                     receivingDatas = false;   
00345                     sendIR(sendBuffer); 
00346                 }
00347             }   
00348             else {
00349                 sendUART("FAIL:send", 9);
00350                 DEBUG("FAIL:send\r\n"); 
00351                 receivingDatas = false;   
00352  
00353             }
00354         }
00355         else
00356         {
00357             DEBUG("UNPARSED : %s\r\n", option);
00358         }
00359     }    
00360 }
00361 
00362 
00363 
00364 void recordFinished()
00365 {
00366     if(recording){
00367         timerUp.reset();
00368         timerDown.reset();
00369         indexi = 0;
00370         indexj = 0;
00371         DEBUG("Record is over\r\n"); 
00372         for(int i=0; i<100; i++)
00373             DEBUG("%d - ",recordBuffers[0][i]);  
00374         DEBUG("\r\n");
00375         for(int i=0; i<100; i++)
00376             DEBUG("%d - ",recordBuffers[1][i]);  
00377         DEBUG("\r\n");
00378     }
00379     
00380 }
00381 
00382 void irFall()
00383 {
00384     if(recording){
00385         // Arrete le timer
00386         timerUp.stop();
00387         
00388         timerDown.reset();
00389         timerDown.start();
00390         
00391         // Demarrage du timer de shutdown;
00392         recordOffTimer.attach_us(&recordFinished, RECORD_OFF_TIMER);
00393         if(indexj<100 && indexi <3)
00394             recordBuffers[indexi][indexj] = timerUp.read_us();
00395         indexj++;
00396     }
00397 }
00398 
00399 void irRise()
00400 {
00401     if(recording){
00402         timerDown.stop();
00403         
00404         timerUp.reset();
00405         timerUp.start();
00406         
00407         // Supprime le shutdown timer
00408         recordOffTimer.detach();
00409         if(indexj<100 && indexi <3)
00410             recordBuffers[indexi][indexj] = timerDown.read_us();
00411         indexj++;
00412     }
00413 }
00414 
00415 
00416 void initIRInterrupt(PinName pin)
00417 {
00418     // Interruption sur le bouton
00419     InterruptIn *interruption;
00420 
00421     // Initalize interruption
00422     interruption = new InterruptIn(pin);
00423     
00424     if(NRF51822)
00425     {
00426         interruption->rise(irRise);
00427         interruption->fall(irFall);
00428     }
00429     else
00430     {    
00431         interruption->fall(irRise);
00432         interruption->rise(irFall);
00433     }
00434 }
00435 
00436 
00437 int main() {
00438     /*
00439     NRF_CLOCK->TASKS_LFCLKSTOP = 1;
00440     NRF_CLOCK->LFCLKSRC = 2;    // 0 = RC, 1 = XTAL, 2 = SYNTH
00441     NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
00442     NRF_CLOCK->TASKS_LFCLKSTART = 1;
00443     while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0){}
00444     NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; 
00445  */
00446 
00447     irled.period_us(26);
00448 //    irled.write(0.33f);
00449     
00450     DEBUG("Hello world\r\n");
00451     
00452     // Demarre l'appel periodique toutes les 1 seconde
00453     ticker.attach(periodicCallback, 1.0f);
00454 
00455     initIRInterrupt(ir);
00456     
00457     DEBUG("Fin interrupt Set\r\n");
00458      // Initialisation et set des callback
00459     ble.init();
00460     ble.reset();
00461     ble.onDisconnection(onDisconnection);
00462     ble.onDataWritten(receiveUART);
00463     ble.onConnection(onConnection);
00464     ble.onTimeout(onTimeout);
00465  
00466  /*****************************************
00467  ********** AJOUT DES SERVICES ************
00468  *****************************************/
00469   
00470     // Creation du service UART
00471     UARTService uartService(ble);
00472     uartServicePtr = &uartService;
00473   //  uartService.retargetStdout(); // renvoie la sortie printf sur l'UART
00474     // Creation du battery service
00475     BatteryService battery(ble);
00476     battServicePtr = &battery;
00477    
00478    // Creation du DFU service 
00479     DFUService dfu(ble); 
00480     
00481     // Creation du device information service
00482     DeviceInformationService deviceInfo(ble, DEVICE_NAME, "OldRemote", "SN1", "hw-rev1", "fw-rev1", "soft-rev1");
00483  
00484 
00485     // Setup advertising
00486     static const uint16_t uuid16_list[] = {GattService::UUID_BATTERY_SERVICE, GattService::UUID_DEVICE_INFORMATION_SERVICE};
00487 
00488     ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00489     ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00490     ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,(const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) - 1);
00491     ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
00492     ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));                               
00493     ble.setAdvertisingInterval(ADV_INTERVAL); /* 100ms; in multiples of 0.625ms. */
00494 //    ble.setAdvertisingTimeout(ADV_TIMEOUT); /* in seconds */
00495     ble.startAdvertising();
00496  
00497     currentState = ADVERTISING;   
00498     
00499     DEBUG("Initialisation done\r\n");
00500 
00501     while (true) { 
00502         ble.waitForEvent();
00503         
00504     }
00505 }