Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822
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 }
Generated on Sun Jul 31 2022 03:59:08 by
1.7.2