OldRemmote allows you to record IR remotes and upload the IR code to your smartphone to replay it later. Check www.julesthuillier.com for more information
Dependencies: BLE_API mbed nRF51822
main.cpp
- Committer:
- JulesThuillier
- Date:
- 2015-02-09
- Revision:
- 4:688a955562ad
- Parent:
- 3:a491b09cfd3b
File content as of revision 4:688a955562ad:
#include "mbed.h" #include "BLEDevice.h" #include "DFUService.h" //UART Primary Service #include "UARTService.h" //Battery and DeviceInformation Auxilary Services #include "BatteryService.h" #include "DeviceInformationService.h" #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console; * it will have an impact on code-size and power consumption. */ #if NEED_CONSOLE_OUTPUT #define DEBUG(...) { printf(__VA_ARGS__);} #else #define DEBUG(...) /* nothing */ #endif /* #if NEED_CONSOLE_OUTPUT */ #define RECORD_OFF_TIMER 12000 #define ADV_INTERVAL 1600 /* 1000ms; in multiples of 0.625ms. */ #define ADV_TIMEOUT 30 /* in seconds */ #define BUTTON_SHUTDOWN_DELAY 4 #define NRF51822 0 /* Initialisation des entrées sorties */ PinName ir = P0_6; PwmOut irled(P0_12); static char const DEVICE_NAME[] = "OldRemote"; BLEDevice ble; UARTService *uartServicePtr; BatteryService *battServicePtr; enum States {DISCONNECTED, OFF, ADVERTISING, CONNECTED}; States currentState = DISCONNECTED; // Timer pour connaitre la duree de l'enfoncement Timer timer; Timer timerUp; Timer timerDown; Timeout recordOffTimer; // Ticker pour un reveil toutes ls 1 secondes Ticker ticker; bool startPeriodick = false; // Turn the device off uint16_t recordBuffers [3][100]; uint8_t indexi = 0, indexj = 0; uint16_t sendBuffer [100]; uint8_t sendBufferIndex = 0; bool receivingDatas = false; bool recording = false; // Convertit un tableau de char en int int char_to_int(char *data) { int i; sscanf(data, "%d", &i); return i; } /* Envoi en infrarouge les données passées en parametre * PROTOCOL : * first data : array size - 1 (number of HIGH - LOW datas) * every odd index : duration of HIGH * every even index : duration of LOW */ void sendIR(uint16_t *data) { uint8_t size = data[0]; // Start at index 1, as index 0 is buffer length for(int i=1; i<size; i++) { // HIGH if((i%2)==1) { irled.write(0.33f); } // LOW else { irled.write(0); } wait_us(data[i]); } irled.write(0); } /* * Renvoie le dernier signal IR */ void repeat() { if(sendBuffer[0] != 0) { sendIR(sendBuffer); } } void prepareForReception() { for(int i=0; i<100; i++) { sendBuffer[i] = 0; } } /* Set the IR frequency * Param : frequency in Kilohertz */ void setFrequency(int freq) { DEBUG("Frequency : %d\r\n", freq); uint8_t period = 1000/freq; irled.period_us(period); } // Vide le buffer dont l'index est passe en parametre void clearBuffer(int index) { for(int j=0; j<100;j++){ recordBuffers[index][j] = 0; } } // Vide tous les buffers void clearBuffers() { for(int j=0; j<3;j++){ clearBuffer(j); } } void disconnect() { DEBUG("Shutting down\r\n"); // Arrete le timer timer.stop(); // Supprime l'appel toutes les 1 secondes ticker.detach(); Gap::DisconnectionReason_t myreason; ble.disconnect(myreason); currentState = OFF; } uint8_t getBattery() { // Configure ADC NRF_ADC->CONFIG = (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos) | (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) | (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) | (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); NRF_ADC->EVENTS_END = 0; NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled; NRF_ADC->EVENTS_END = 0; // Stop any running conversions. NRF_ADC->TASKS_START = 1; while (!NRF_ADC->EVENTS_END) { } uint16_t vbg_in_mv = 1200; uint8_t adc_max = 255; uint16_t vbat_current_in_mv = (NRF_ADC->RESULT * 3 * vbg_in_mv) / adc_max; NRF_ADC->EVENTS_END = 0; NRF_ADC->TASKS_STOP = 1; return (uint8_t) ((vbat_current_in_mv * 100) / 3700); // return 12; } // Fontion appelé toutes les 1 secondes lorsque le telephoen est connecté void periodicCallback(void) { // uint8_t batt = getBattery(); // uint8_t batt = 42; // DEBUG("Periodic Callback \n\r"); //if (battServicePtr != NULL) // battServicePtr->updateBatteryLevel(batt); // DEBUG("Battery : %d \n\r", batt); } // Callback appelé en cas de deconnection void onDisconnection(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { DEBUG("Disconnected \n\r"); if(currentState != OFF) { // printf("Restarting the advertising process\n\r"); ble.startAdvertising(); currentState = DISCONNECTED; } switch (reason) { case Gap::REMOTE_USER_TERMINATED_CONNECTION: DEBUG("Disconnected (REMOTE_USER_TERMINATED_CONNECTION)\n\r"); break; case Gap::LOCAL_HOST_TERMINATED_CONNECTION: DEBUG("Disconnected (LOCAL_HOST_TERMINATED_CONNECTION)\n\r"); break; case Gap::CONN_INTERVAL_UNACCEPTABLE: DEBUG("Disconnected (CONN_INTERVAL_UNACCEPTABLE)\n\r"); break; } } // Callback appelé lorsque la connection est etablie void onConnection(Gap::Handle_t handle, Gap::addr_type_t peerAddrType, const Gap::address_t peerAddr, const Gap::ConnectionParams_t *param) { DEBUG("Connected\n\r"); currentState = CONNECTED; } // Callback appelé lorsque l'advertising arrive a son timeout avant que la connexion ait été établie void onTimeout() { DEBUG("Timeout \n\r"); disconnect(); } void sendUART(char *data, int size) { uint8_t buf[size]; for(int i=0; i< size; i++) { buf[i] = (uint8_t)data[i]; } ble.updateCharacteristicValue(uartServicePtr->getRXCharacteristicHandle(), buf, size); } // Callback appelé lorsque le service uart recoit des données void receiveUART(const GattCharacteristicWriteCBParams *params) { if ((uartServicePtr != NULL) && (params->charHandle == uartServicePtr->getTXCharacteristicHandle())) { uint16_t bytesRead = params->len; DEBUG("Data received : %*s\n\r", params->len, params->data); DEBUG("Data length : %d\n\r", bytesRead); // get all the data in one array uint8_t buf[bytesRead]; uint16_t split = bytesRead; for(int i=0; i< bytesRead; i++) { buf[i] = params->data[i]; if((char)buf[i] == ':' ) { DEBUG("Split at %u\n\r", i); split = i; } } char option[split]; char arg[bytesRead - (split+1)]; // split array to get option for(int i=0; i< split; i++) { option[i] = buf[i]; } // split array to get argument if(split<bytesRead) { for(int i=split+1; i < bytesRead; i++) { arg[i-(split+1)] = buf[i]; } } // Get ready to receive the datas to send if(strncmp(option, "send", split) == 0) { prepareForReception(); sendBuffer[0] = char_to_int(arg); receivingDatas = true; DEBUG("Receiving datas\r\n"); } // Set the frequency else if(strncmp(option, "setfreq", split) == 0) { setFrequency(char_to_int(arg)); } // Repeat the last emission else if(strncmp(option, "repeat", split) == 0) { repeat(); } // Start recording else if(strncmp(option, "record", split) == 0) { } else if(receivingDatas) { int duration = char_to_int(option); DEBUG("data : %u\r\n", duration); if(duration != 0) { sendBufferIndex++; sendBuffer[sendBufferIndex] = duration; if(sendBufferIndex == sendBuffer[0]) { DEBUG("Reception Over\r\n"); receivingDatas = false; sendIR(sendBuffer); } } else { sendUART("FAIL:send", 9); DEBUG("FAIL:send\r\n"); receivingDatas = false; } } else { DEBUG("UNPARSED : %s\r\n", option); } } } void recordFinished() { if(recording){ timerUp.reset(); timerDown.reset(); indexi = 0; indexj = 0; DEBUG("Record is over\r\n"); for(int i=0; i<100; i++) DEBUG("%d - ",recordBuffers[0][i]); DEBUG("\r\n"); for(int i=0; i<100; i++) DEBUG("%d - ",recordBuffers[1][i]); DEBUG("\r\n"); } } void irFall() { if(recording){ // Arrete le timer timerUp.stop(); timerDown.reset(); timerDown.start(); // Demarrage du timer de shutdown; recordOffTimer.attach_us(&recordFinished, RECORD_OFF_TIMER); if(indexj<100 && indexi <3) recordBuffers[indexi][indexj] = timerUp.read_us(); indexj++; } } void irRise() { if(recording){ timerDown.stop(); timerUp.reset(); timerUp.start(); // Supprime le shutdown timer recordOffTimer.detach(); if(indexj<100 && indexi <3) recordBuffers[indexi][indexj] = timerDown.read_us(); indexj++; } } void initIRInterrupt(PinName pin) { // Interruption sur le bouton InterruptIn *interruption; // Initalize interruption interruption = new InterruptIn(pin); if(NRF51822) { interruption->rise(irRise); interruption->fall(irFall); } else { interruption->fall(irRise); interruption->rise(irFall); } } int main() { /* NRF_CLOCK->TASKS_LFCLKSTOP = 1; NRF_CLOCK->LFCLKSRC = 2; // 0 = RC, 1 = XTAL, 2 = SYNTH NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; NRF_CLOCK->TASKS_LFCLKSTART = 1; while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0){} NRF_CLOCK->EVENTS_LFCLKSTARTED = 0; */ irled.period_us(26); // irled.write(0.33f); DEBUG("Hello world\r\n"); // Demarre l'appel periodique toutes les 1 seconde ticker.attach(periodicCallback, 1.0f); initIRInterrupt(ir); DEBUG("Fin interrupt Set\r\n"); // Initialisation et set des callback ble.init(); ble.reset(); ble.onDisconnection(onDisconnection); ble.onDataWritten(receiveUART); ble.onConnection(onConnection); ble.onTimeout(onTimeout); /***************************************** ********** AJOUT DES SERVICES ************ *****************************************/ // Creation du service UART UARTService uartService(ble); uartServicePtr = &uartService; // uartService.retargetStdout(); // renvoie la sortie printf sur l'UART // Creation du battery service BatteryService battery(ble); battServicePtr = &battery; // Creation du DFU service DFUService dfu(ble); // Creation du device information service DeviceInformationService deviceInfo(ble, DEVICE_NAME, "OldRemote", "SN1", "hw-rev1", "fw-rev1", "soft-rev1"); // Setup advertising static const uint16_t uuid16_list[] = {GattService::UUID_BATTERY_SERVICE, GattService::UUID_DEVICE_INFORMATION_SERVICE}; ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,(const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME) - 1); ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS,(const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); ble.accumulateAdvertisingPayload(GapAdvertisingData::INCOMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); ble.setAdvertisingInterval(ADV_INTERVAL); /* 100ms; in multiples of 0.625ms. */ // ble.setAdvertisingTimeout(ADV_TIMEOUT); /* in seconds */ ble.startAdvertising(); currentState = ADVERTISING; DEBUG("Initialisation done\r\n"); while (true) { ble.waitForEvent(); } }