Petr Vasilev / Mbed 2 deprecated BLE_Evothings_NRF51822-BLE400

Dependencies:   mbed AdafruitST7735 BLE_API Adafruit_GFX nRF51822

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "ble/BLE.h"
00003 #include "Adafruit_GFX/Adafruit_GFX.h"
00004 #include "AdafruitST7735/Adafruit_ST7735.h"
00005 
00006 // Конфигурация BLE
00007 const static uint16_t SERVICE_UUID          = 0xA000;
00008 const static char     DEVICE_NAME[] = "HPSP BT-Lite";
00009 
00010 // Настройка выводов
00011 DigitalOut led1(P0_21);
00012 DigitalOut DISP_LED (P0_16);
00013 DigitalIn key1 (P0_8);
00014 DigitalIn key2 (P0_17);
00015 DigitalOut OSC (P0_6);
00016 
00017 #define TFT_MISO P0_4   // NC(NC)      //Не подключен так как отсутсвует на дисплее
00018 #define TFT_RST P0_9    // RST(5)
00019 #define TFT_DC P0_10     // D/C(6)      // не работает на 10
00020 #define TFT_MOSI P0_11   // DIN(7)
00021 #define TFT_SCK P0_12   // CLK(8)
00022 #define TFT_SS P0_13     // CS(11)
00023 
00024 //
00025 Adafruit_ST7735 tft(TFT_MOSI, TFT_MISO, TFT_SCK, TFT_SS, TFT_DC, TFT_RST); // MOSI, MISO, SCLK, SSEL, TFT_DC, TFT_RST
00026 
00027 // Назначение цветов
00028 #define BLACK 0x0000
00029 #define BLUE 0x001F
00030 #define RED 0xF800
00031 #define GREEN 0x07E0
00032 #define CYAN 0x07FF
00033 #define MAGENTA 0xF81F
00034 #define YELLOW 0xFFE0
00035 #define WHITE 0xFFFF
00036 int COLOR = WHITE;
00037 
00038 Timeout KEY_TIME;                                           // Счетчик для таймера работы программы
00039 short FLAG = 0;                                           // Флаг старта программы
00040 unsigned int HOUR = 0;                                           // Часы
00041 unsigned int MIN = 0;                                            // Минуты
00042 unsigned int SEC = 0;                                            // Секунды
00043 unsigned int TIME_PROGRAMM = 5400;                                  // Время работы программы
00044 int START = 0;
00045 // Переменные типа char для дисплея
00046 char HOUR_CHAR[2] = {'0', '0'};
00047 char MIN_CHAR[2] = {'0', '0'};
00048 char SEC_CHAR[2] = {'0', '0'};
00049 int r = 20;
00050 
00051 //static UARTService* uartService;
00052 
00053 //static EventQueue eventQueue(
00054 //  /* event count */ 16 * /* event size */ 32
00055 //);
00056 
00057 Ticker ticker;
00058 
00059 char freq_storage[900] = {0}; //резервируем блок памяти в EEPROM для хранения частот
00060 char timer_storage[100] = {0}; //резервируем блок памяти в EEPROM для хранения таймеров
00061 
00062 char* freq_storage_pos = freq_storage;
00063 char* timer_storage_pos = timer_storage;
00064 
00065 void generate()
00066 {
00067   char* freq_storage_pos = freq_storage;
00068   unsigned short freq;
00069   unsigned short duration = 180; // длительность
00070 
00071   memcpy( &freq, freq_storage_pos, sizeof(freq) );
00072   freq_storage_pos += sizeof(freq);
00073 
00074   while ( freq != 0 )
00075   {
00076     memcpy( &duration, freq_storage_pos, sizeof(duration) );
00077     freq_storage_pos += sizeof(duration);
00078 
00079     // распаковываем частоту
00080     float real_freq;
00081     if ( freq <= 1000 )
00082     {
00083       real_freq = (float)freq / 100;
00084     }
00085     else if ( freq <= 11000 )
00086     {
00087       real_freq = (float)(freq - 1000) / 10;
00088     }
00089     else
00090     {
00091       real_freq = freq - 10000;
00092     }
00093 
00094     float real_duration = (float)duration * 1000;
00095 
00096     OSC = 1;
00097     wait_ms(real_duration);
00098     OSC = 0;
00099 
00100     /*
00101       digitalWrite(led, HIGH);
00102       tone(ant, real_freq);
00103       customDelay(real_duration);
00104       noTone(ant);
00105       digitalWrite(led, LOW);
00106     */
00107 
00108     memcpy( &freq, freq_storage_pos, sizeof(freq) );
00109     freq_storage_pos += sizeof(freq);
00110   }
00111 }
00112 
00113 int frequencies_scan_mode = 1;
00114 
00115 int parse_bt_data( char *buffer // буфер, в котором уже лежат принятые данные в виде стандартной C строки
00116                  )
00117 {
00118   if ( buffer == NULL) // проверяем корректность входных данных
00119   {
00120     return 0;
00121   }
00122 
00123   // вспомогательные переменные
00124   char *current = buffer; // указатель на текущий символ
00125 
00126   // сканируем частоты
00127   while ( frequencies_scan_mode != 0 && *current != 0 )
00128   {
00129     if ( *current == ':' )
00130     {
00131       break; // выходим, так как частоты закончились
00132     }
00133 
00134     unsigned long freq; // частота в сотых долях герца
00135     unsigned long duration; // длительность в секундах
00136     char separator[2]; // разделитель
00137 
00138     int symbols_read;
00139     int values_read = sscanf( current, "%ld %ld%1[,:]%n", &freq, &duration, separator, &symbols_read); // считываем частоту и длительность
00140 
00141     if ( values_read != 3 )
00142     {
00143       // закончился буффер
00144       // копируем оставшиеся данные в начало буффера
00145       int rest_len = strlen( current ); // длина остатка в буффере
00146       memmove( buffer, current, rest_len );
00147       return rest_len;
00148     }
00149 
00150     // кодируем частоту для умещения в память
00151     unsigned short packed_freq;
00152     if ( freq <= 10 * 100 ) // 10Гц
00153     {
00154       packed_freq = freq;
00155     }
00156     else if ( freq <= 1000 * 100 ) // 1кГц
00157     {
00158       packed_freq = 1000 + freq / 10;
00159     }
00160     else
00161     {
00162       packed_freq = 10000 + freq / 100;
00163     }
00164 
00165     // сохраняем данные в EEPROM
00166     memcpy( freq_storage_pos, &packed_freq, sizeof(packed_freq) );
00167     freq_storage_pos += sizeof(packed_freq);
00168     memcpy( freq_storage_pos, &duration, sizeof(duration) );
00169     freq_storage_pos += sizeof(duration);
00170 
00171     // моргаем после каждых данных
00172     //led2 = !led2;
00173 
00174     current += symbols_read; //переходим к следующей паре
00175 
00176     if ( *separator == ':' )
00177     {
00178       // пишем признак конца данных
00179       unsigned short end = 0;
00180       memcpy( freq_storage_pos, &end, sizeof(end) );
00181 
00182       frequencies_scan_mode = 0; // загрузка частот завершена
00183       break;
00184     }
00185   }
00186 
00187   // сканируем таймеры
00188   while ( *current != 0 )
00189   {
00190     if ( *current == '.' )
00191     {
00192       break; // выходим, так как таймеры закончились
00193     }
00194 
00195     unsigned int timer_start;
00196 
00197     int symbols_read;
00198     char separator[2]; //разделитель
00199     int values_read = sscanf( current, "%d%1[,.]%n", &timer_start, separator, &symbols_read); //считываем время до запуска таймера
00200 
00201     if ( values_read != 2 )
00202     {
00203       // закончился буффер
00204       // копируем оставшиеся данные в начало буффера
00205       int rest_len = strlen( current ); // длина остатка в буффере
00206       memmove( buffer, current, rest_len );
00207       return rest_len;
00208     }
00209 
00210     // сохраняем данные в EEPROM
00211     //eeprom_write_block( timer_start, timer_storage_pos, sizeof(timer_start) );
00212     //timer_storage_pos += sizeof(timer_start);
00213 
00214     current += symbols_read; //переходим к следующей паре
00215 
00216     if ( *separator == '.' )
00217     {
00218       // пишем признак конца данных
00219       unsigned short end = 0;
00220       memcpy( timer_storage_pos, &end, sizeof(end) );
00221       break; // конец данных
00222     }
00223   }
00224 
00225   return 0;
00226 }
00227 
00228 void updateSensorValue()
00229 {
00230 
00231 }
00232 
00233 void periodicCallback(void)
00234 {
00235   OSC = !OSC; /* Do blinky on LED1 to indicate system aliveness. */
00236   TIME_PROGRAMM--;
00237   r = r + 2;
00238       if (r >= 60){
00239           r = 30;
00240           if(COLOR == WHITE){
00241               COLOR = BLACK;
00242               }
00243               else (COLOR = WHITE);
00244           };
00245   if (BLE::Instance().getGapState().connected) {
00246 //    eventQueue.call(updateSensorValue);
00247   }
00248 }
00249 
00250 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
00251 {
00252   tft.fillScreen(ST7735_BLACK);
00253   FLAG = 1;
00254   r= 30;
00255 }
00256 
00257 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
00258 {
00259   BLE::Instance().gap().startAdvertising();
00260   tft.fillScreen(ST7735_BLACK);
00261   FLAG = 1;
00262   r= 30;
00263 }
00264 
00265 #define INPUT_BUFFER_SIZE 50
00266 char buffer[INPUT_BUFFER_SIZE + 1]; //приемный буффер
00267 static int config_complete = 0;
00268 
00269 void onDataWrittenCallback(const GattWriteCallbackParams *params) {
00270   if ( params != NULL )
00271   {
00272     //led2 = 0;
00273     unsigned int buffer_pos = 0; //текущая позиция в буффере
00274 
00275     //если есть данные - читаем
00276     while ( buffer_pos < params->len )
00277     {
00278       //загоняем прочитанное в буфер
00279       char symbol = params->data[buffer_pos++];
00280       buffer[buffer_pos] = symbol;
00281       if ( symbol == '.')
00282       {
00283         buffer[buffer_pos] = 0; // закрываем строку
00284         parse_bt_data(buffer); // обрабатываем полученный кусок данных
00285 
00286         // конец данных, прекращаем чтение
00287         // данные получены, надо выставить флаг и больше из BT не читать
00288         config_complete = 1;
00289         break;
00290       }
00291 
00292       if ( buffer_pos == INPUT_BUFFER_SIZE )
00293       {
00294         buffer[INPUT_BUFFER_SIZE] = 0; //символ конца строки для полностью заполненного буффера
00295         buffer_pos = parse_bt_data(buffer); // обрабатываем полученный кусок данных
00296       }
00297     }
00298     //led2 = 1;
00299   }
00300 }
00301 
00302 // GATT service and characteristic UUIDs
00303 const uint8_t  nRF51ServiceUUID[UUID::LENGTH_OF_LONG_UUID] = {
00304   0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
00305   0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
00306 };
00307 const uint8_t  nRF51ServiceUUIDreversed[UUID::LENGTH_OF_LONG_UUID] = {
00308   0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
00309   0x00, 0x10, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00
00310 };
00311 const UUID nRF51_GATT_SERVICE = UUID("00001101-0000-1000-8000-00805F9B34FB");
00312 //const UUID nRF51_GATT_CHAR_BUTTON = UUID((uint8_t *)"nRF51-DK button ");
00313 const UUID nRF51_GATT_CHAR_LED    = UUID("00001102-0000-1000-8000-00805F9B34FB");
00314 
00315 //#define CHARACTERISTIC_BUTTON 0
00316 #define CHARACTERISTIC_LED    0
00317 #define CHARACTERISTIC_COUNT  1
00318 
00319 // our bluetooth smart objects
00320 GattService        *gatt_service;
00321 GattCharacteristic *gatt_characteristics[CHARACTERISTIC_COUNT];
00322 uint8_t             gatt_char_value[CHARACTERISTIC_COUNT];
00323 
00324 /**
00325    Callback triggered when the ble initialization process has finished
00326 */
00327 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
00328 {
00329   BLE&        ble   = params->ble;
00330   ble_error_t error = params->error;
00331 
00332   if (error != BLE_ERROR_NONE) {
00333     /* In case of error, forward the error handling to onBleInitError */
00334     //onBleInitError(ble, error);
00335     return;
00336   }
00337 
00338   /* Ensure that it is the default instance of BLE */
00339   if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
00340     return;
00341   }
00342 
00343   ble.gap().onDisconnection(disconnectionCallback);
00344   ble.gattServer().onDataWritten(onDataWrittenCallback);
00345 
00346 //  bool initialValueForLEDCharacteristic = false;
00347 
00348   /* Setup primary service. */
00349   //uartService = new UARTService(ble);
00350 
00351   /* Setup advertising. */
00352   ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00353   ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
00354   ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)nRF51ServiceUUIDreversed, sizeof(nRF51ServiceUUIDreversed));
00355   ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00356   ble.gap().setAdvertisingInterval(100); /* 100ms. */
00357 
00358   // add our gatt service with two characteristics
00359   ble.addService(*gatt_service);
00360 
00361   ble.gap().startAdvertising();
00362 }
00363 
00364 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
00365   BLE &ble = BLE::Instance();
00366 //  eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
00367   led2 = !led2;
00368 }
00369 
00370 void BUTTON () {
00371     if (!key1){
00372         START = 0;
00373     }
00374 }
00375 
00376 // Основной цикл
00377 int main(void)
00378 {
00379       DISP_LED = 0;                        // Инициализация дисплея
00380       tft.initR(INITR_144GREENTAB);
00381       //tft.invertDisplay(true);                            // Инвертирование цветов дисплея для корректного отображения цветов
00382       tft.fillScreen(ST7735_BLACK);                       // Заливка черным цветом
00383       tft.setTextColor(WHITE);                            // Установка цвета текста
00384       tft.setCursor(40, 48);
00385       tft.setTextSize(2);
00386       tft.printf("HPSP");
00387       tft.setCursor(22, 64);
00388       tft.printf("BT-Lite");
00389       wait(1);
00390       tft.setTextSize(1);
00391       tft.setCursor(2, 110);
00392       tft.printf("HPSP BT-Lite V:pre0.2");
00393       tft.setCursor(2, 120);
00394       tft.printf("NOT FOR SALE");
00395       wait(2);
00396       tft.fillScreen(ST7735_BLACK);
00397         tft.setTextSize(2);
00398         tft.setCursor(10, 57);
00399         tft.printf("Wait Data");
00400   // tft.drawRect(100, 0, 20, 30, WHITE);
00401 
00402   ticker.attach(periodicCallback, 0.8); /* Blink LED every 3 seconds */
00403 
00404   // create our button characteristic (read, notify)
00405   /*gatt_characteristics[CHARACTERISTIC_BUTTON] =
00406     new GattCharacteristic(
00407           nRF51_GATT_CHAR_BUTTON,
00408           &gatt_char_value[CHARACTERISTIC_BUTTON], 1, 1,
00409           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ |
00410           GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);*/
00411 
00412   // create our LED characteristic (read, write)
00413   gatt_characteristics[CHARACTERISTIC_LED] =
00414     new GattCharacteristic(
00415     nRF51ServiceUUID,
00416     &gatt_char_value[CHARACTERISTIC_LED], 1, 1,
00417     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ |
00418     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE |
00419     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE |
00420     GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY );
00421 
00422   // create our service, with both characteristics
00423   gatt_service =
00424     new GattService(nRF51_GATT_SERVICE,
00425                     gatt_characteristics, CHARACTERISTIC_COUNT);
00426 
00427   BLE &ble = BLE::Instance();
00428 //  ble.onEventsToProcess(scheduleBleEventsProcessing);
00429   ble.init(bleInitComplete);
00430 
00431   /* SpinWait for initialization to complete. This is necessary because the
00432      BLE object is used in the main loop below. */
00433   while (ble.hasInitialized()  == false)
00434   {
00435     /* spin loop */
00436   }
00437 
00438   // Основной цикл
00439   while (true)
00440   {
00441       if ( !key1 || !key2) {
00442         DISP_LED = !DISP_LED;
00443         KEY_TIME.attach(BUTTON, 5);
00444         wait(0.2);
00445 
00446       }
00447 
00448       //BACKLIGTH.attach(&TFT_LED, 30);
00449 
00450       // Проверка флага на старт программы и отоброжение таймера  ( TODO вынести в отдельную функцию и обновлять по прерыванию )
00451       if ( FLAG == 1 ) {
00452 
00453         // переводим время в другой формат ЧЧ:ММ:СС
00454         HOUR = TIME_PROGRAMM / 60 / 60;
00455         MIN = (TIME_PROGRAMM / 60) % 60;
00456         SEC = TIME_PROGRAMM % 60;
00457         // Тут надо добавить конвертацию типов пока вижу это как разделение на десятки и еденицы и далее по формуле i + '0' записывать их в массив.
00458         // конвертацию то я сделал но как то не так. сыпет муссором на дисплей вида 00:0000:000000 и это в лучшем случае...
00459         // Часы
00460         HOUR_CHAR[0] = ((HOUR / 10) % 10) + '0';
00461         HOUR_CHAR[1] = (HOUR % 10) + '0';
00462         // Минуты
00463         MIN_CHAR[0] = ((MIN / 10) % 10) + '0';
00464         MIN_CHAR[1] = (MIN % 10) + '0';
00465         // Секунды
00466         SEC_CHAR[0] = ((SEC / 10) % 10) + '0';
00467         SEC_CHAR[1] = (SEC % 10) + '0';
00468         // Так как библиотека принимает только char пришлось посимвольно выводить время...
00469         tft.drawChar(52, 48, HOUR_CHAR[0], WHITE, BLACK, 2);
00470         tft.drawChar(64, 48, HOUR_CHAR[1], WHITE, BLACK, 2);
00471         tft.drawChar(52, 64, MIN_CHAR[0], WHITE, BLACK, 2);
00472         tft.drawChar(64, 64, MIN_CHAR[1], WHITE, BLACK, 2);
00473 
00474         if (r >= 30) {
00475           r = 20;
00476           if (COLOR == WHITE) {
00477             COLOR = BLACK;
00478           }
00479           else (COLOR = WHITE);
00480         };
00481 
00482         tft.drawCircle(63, 62, r, COLOR);
00483         if (TIME_PROGRAMM < 1) {
00484           FLAG = 0;
00485         }
00486       }
00487 
00488       else {
00489         ble.waitForEvent();
00490     
00491       }
00492   }
00493 }