htr

Dependencies:   mbed AdafruitST7735 BLE_API Adafruit_GFX nRF51822

main.cpp

Committer:
tekasijimo
Date:
2019-08-11
Revision:
19:02bb67cb303c
Parent:
18:0cbeb28ce4f6

File content as of revision 19:02bb67cb303c:

#include "mbed.h"
#include "ble/BLE.h"
#include "Adafruit_GFX/Adafruit_GFX.h"
#include "AdafruitST7735/Adafruit_ST7735.h"

// Конфигурация BLE
const static uint16_t SERVICE_UUID          = 0xA000;
const static char     DEVICE_NAME[] = "HPSP BT-Lite";

// Настройка выводов
DigitalOut led1(P0_21);
DigitalOut DISP_LED (P0_16);
DigitalIn key1 (P0_8);
DigitalIn key2 (P0_17);
DigitalOut OSC (P0_6);

#define TFT_MISO P0_4   // NC(NC)      //Не подключен так как отсутсвует на дисплее
#define TFT_RST P0_9    // RST(5)
#define TFT_DC P0_10     // D/C(6)      // не работает на 10
#define TFT_MOSI P0_11   // DIN(7)
#define TFT_SCK P0_12   // CLK(8)
#define TFT_SS P0_13     // CS(11)

//
Adafruit_ST7735 tft(TFT_MOSI, TFT_MISO, TFT_SCK, TFT_SS, TFT_DC, TFT_RST); // MOSI, MISO, SCLK, SSEL, TFT_DC, TFT_RST

// Назначение цветов
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
int COLOR = WHITE;

Timeout KEY_TIME;                                           // Счетчик для таймера работы программы
short FLAG = 0;                                           // Флаг старта программы
unsigned int HOUR = 0;                                           // Часы
unsigned int MIN = 0;                                            // Минуты
unsigned int SEC = 0;                                            // Секунды
unsigned int TIME_PROGRAMM = 5400;                                  // Время работы программы
int START = 0;
// Переменные типа char для дисплея
char HOUR_CHAR[2] = {'0', '0'};
char MIN_CHAR[2] = {'0', '0'};
char SEC_CHAR[2] = {'0', '0'};
int r = 20;

//static UARTService* uartService;

//static EventQueue eventQueue(
//  /* event count */ 16 * /* event size */ 32
//);

Ticker ticker;

char freq_storage[900] = {0}; //резервируем блок памяти в EEPROM для хранения частот
char timer_storage[100] = {0}; //резервируем блок памяти в EEPROM для хранения таймеров

char* freq_storage_pos = freq_storage;
char* timer_storage_pos = timer_storage;

void generate()
{
  char* freq_storage_pos = freq_storage;
  unsigned short freq;
  unsigned short duration = 180; // длительность

  memcpy( &freq, freq_storage_pos, sizeof(freq) );
  freq_storage_pos += sizeof(freq);

  while ( freq != 0 )
  {
    memcpy( &duration, freq_storage_pos, sizeof(duration) );
    freq_storage_pos += sizeof(duration);

    // распаковываем частоту
    float real_freq;
    if ( freq <= 1000 )
    {
      real_freq = (float)freq / 100;
    }
    else if ( freq <= 11000 )
    {
      real_freq = (float)(freq - 1000) / 10;
    }
    else
    {
      real_freq = freq - 10000;
    }

    float real_duration = (float)duration * 1000;

    OSC = 1;
    wait_ms(real_duration);
    OSC = 0;

    /*
      digitalWrite(led, HIGH);
      tone(ant, real_freq);
      customDelay(real_duration);
      noTone(ant);
      digitalWrite(led, LOW);
    */

    memcpy( &freq, freq_storage_pos, sizeof(freq) );
    freq_storage_pos += sizeof(freq);
  }
}

int frequencies_scan_mode = 1;

int parse_bt_data( char *buffer // буфер, в котором уже лежат принятые данные в виде стандартной C строки
                 )
{
  if ( buffer == NULL) // проверяем корректность входных данных
  {
    return 0;
  }

  // вспомогательные переменные
  char *current = buffer; // указатель на текущий символ

  // сканируем частоты
  while ( frequencies_scan_mode != 0 && *current != 0 )
  {
    if ( *current == ':' )
    {
      break; // выходим, так как частоты закончились
    }

    unsigned long freq; // частота в сотых долях герца
    unsigned long duration; // длительность в секундах
    char separator[2]; // разделитель

    int symbols_read;
    int values_read = sscanf( current, "%ld %ld%1[,:]%n", &freq, &duration, separator, &symbols_read); // считываем частоту и длительность

    if ( values_read != 3 )
    {
      // закончился буффер
      // копируем оставшиеся данные в начало буффера
      int rest_len = strlen( current ); // длина остатка в буффере
      memmove( buffer, current, rest_len );
      return rest_len;
    }

    // кодируем частоту для умещения в память
    unsigned short packed_freq;
    if ( freq <= 10 * 100 ) // 10Гц
    {
      packed_freq = freq;
    }
    else if ( freq <= 1000 * 100 ) // 1кГц
    {
      packed_freq = 1000 + freq / 10;
    }
    else
    {
      packed_freq = 10000 + freq / 100;
    }

    // сохраняем данные в EEPROM
    memcpy( freq_storage_pos, &packed_freq, sizeof(packed_freq) );
    freq_storage_pos += sizeof(packed_freq);
    memcpy( freq_storage_pos, &duration, sizeof(duration) );
    freq_storage_pos += sizeof(duration);

    // моргаем после каждых данных
    //led2 = !led2;

    current += symbols_read; //переходим к следующей паре

    if ( *separator == ':' )
    {
      // пишем признак конца данных
      unsigned short end = 0;
      memcpy( freq_storage_pos, &end, sizeof(end) );

      frequencies_scan_mode = 0; // загрузка частот завершена
      break;
    }
  }

  // сканируем таймеры
  while ( *current != 0 )
  {
    if ( *current == '.' )
    {
      break; // выходим, так как таймеры закончились
    }

    unsigned int timer_start;

    int symbols_read;
    char separator[2]; //разделитель
    int values_read = sscanf( current, "%d%1[,.]%n", &timer_start, separator, &symbols_read); //считываем время до запуска таймера

    if ( values_read != 2 )
    {
      // закончился буффер
      // копируем оставшиеся данные в начало буффера
      int rest_len = strlen( current ); // длина остатка в буффере
      memmove( buffer, current, rest_len );
      return rest_len;
    }

    // сохраняем данные в EEPROM
    //eeprom_write_block( timer_start, timer_storage_pos, sizeof(timer_start) );
    //timer_storage_pos += sizeof(timer_start);

    current += symbols_read; //переходим к следующей паре

    if ( *separator == '.' )
    {
      // пишем признак конца данных
      unsigned short end = 0;
      memcpy( timer_storage_pos, &end, sizeof(end) );
      break; // конец данных
    }
  }

  return 0;
}

void updateSensorValue()
{

}

void periodicCallback(void)
{
  OSC = !OSC; /* Do blinky on LED1 to indicate system aliveness. */
  TIME_PROGRAMM--;
  r = r + 2;
      if (r >= 60){
          r = 30;
          if(COLOR == WHITE){
              COLOR = BLACK;
              }
              else (COLOR = WHITE);
          };
  if (BLE::Instance().getGapState().connected) {
//    eventQueue.call(updateSensorValue);
  }
}

void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
  tft.fillScreen(ST7735_BLACK);
  FLAG = 1;
  r= 30;
}

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
  BLE::Instance().gap().startAdvertising();
  tft.fillScreen(ST7735_BLACK);
  FLAG = 1;
  r= 30;
}

#define INPUT_BUFFER_SIZE 50
char buffer[INPUT_BUFFER_SIZE + 1]; //приемный буффер
static int config_complete = 0;

void onDataWrittenCallback(const GattWriteCallbackParams *params) {
  if ( params != NULL )
  {
    //led2 = 0;
    unsigned int buffer_pos = 0; //текущая позиция в буффере

    //если есть данные - читаем
    while ( buffer_pos < params->len )
    {
      //загоняем прочитанное в буфер
      char symbol = params->data[buffer_pos++];
      buffer[buffer_pos] = symbol;
      if ( symbol == '.')
      {
        buffer[buffer_pos] = 0; // закрываем строку
        parse_bt_data(buffer); // обрабатываем полученный кусок данных

        // конец данных, прекращаем чтение
        // данные получены, надо выставить флаг и больше из BT не читать
        config_complete = 1;
        break;
      }

      if ( buffer_pos == INPUT_BUFFER_SIZE )
      {
        buffer[INPUT_BUFFER_SIZE] = 0; //символ конца строки для полностью заполненного буффера
        buffer_pos = parse_bt_data(buffer); // обрабатываем полученный кусок данных
      }
    }
    //led2 = 1;
  }
}

// GATT service and characteristic UUIDs
const uint8_t  nRF51ServiceUUID[UUID::LENGTH_OF_LONG_UUID] = {
  0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00,
  0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB
};
const uint8_t  nRF51ServiceUUIDreversed[UUID::LENGTH_OF_LONG_UUID] = {
  0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
  0x00, 0x10, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00
};
const UUID nRF51_GATT_SERVICE = UUID("00001101-0000-1000-8000-00805F9B34FB");
//const UUID nRF51_GATT_CHAR_BUTTON = UUID((uint8_t *)"nRF51-DK button ");
const UUID nRF51_GATT_CHAR_LED    = UUID("00001102-0000-1000-8000-00805F9B34FB");

//#define CHARACTERISTIC_BUTTON 0
#define CHARACTERISTIC_LED    0
#define CHARACTERISTIC_COUNT  1

// our bluetooth smart objects
GattService        *gatt_service;
GattCharacteristic *gatt_characteristics[CHARACTERISTIC_COUNT];
uint8_t             gatt_char_value[CHARACTERISTIC_COUNT];

/**
   Callback triggered when the ble initialization process has finished
*/
void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
  BLE&        ble   = params->ble;
  ble_error_t error = params->error;

  if (error != BLE_ERROR_NONE) {
    /* In case of error, forward the error handling to onBleInitError */
    //onBleInitError(ble, error);
    return;
  }

  /* Ensure that it is the default instance of BLE */
  if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
    return;
  }

  ble.gap().onDisconnection(disconnectionCallback);
  ble.gattServer().onDataWritten(onDataWrittenCallback);

//  bool initialValueForLEDCharacteristic = false;

  /* Setup primary service. */
  //uartService = new UARTService(ble);

  /* Setup advertising. */
  ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
  ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
  ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *)nRF51ServiceUUIDreversed, sizeof(nRF51ServiceUUIDreversed));
  ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
  ble.gap().setAdvertisingInterval(100); /* 100ms. */

  // add our gatt service with two characteristics
  ble.addService(*gatt_service);

  ble.gap().startAdvertising();
}

void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
  BLE &ble = BLE::Instance();
//  eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
  led2 = !led2;
}

void BUTTON () {
    if (!key1){
        START = 0;
    }
}

// Основной цикл
int main(void)
{
      DISP_LED = 0;                        // Инициализация дисплея
      tft.initR(INITR_144GREENTAB);
      //tft.invertDisplay(true);                            // Инвертирование цветов дисплея для корректного отображения цветов
      tft.fillScreen(ST7735_BLACK);                       // Заливка черным цветом
      tft.setTextColor(WHITE);                            // Установка цвета текста
      tft.setCursor(40, 48);
      tft.setTextSize(2);
      tft.printf("HPSP");
      tft.setCursor(22, 64);
      tft.printf("BT-Lite");
      wait(1);
      tft.setTextSize(1);
      tft.setCursor(2, 110);
      tft.printf("HPSP BT-Lite V:pre0.2");
      tft.setCursor(2, 120);
      tft.printf("NOT FOR SALE");
      wait(2);
      tft.fillScreen(ST7735_BLACK);
        tft.setTextSize(2);
        tft.setCursor(10, 57);
        tft.printf("Wait Data");
  // tft.drawRect(100, 0, 20, 30, WHITE);

  ticker.attach(periodicCallback, 0.8); /* Blink LED every 3 seconds */

  // create our button characteristic (read, notify)
  /*gatt_characteristics[CHARACTERISTIC_BUTTON] =
    new GattCharacteristic(
          nRF51_GATT_CHAR_BUTTON,
          &gatt_char_value[CHARACTERISTIC_BUTTON], 1, 1,
          GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ |
          GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);*/

  // create our LED characteristic (read, write)
  gatt_characteristics[CHARACTERISTIC_LED] =
    new GattCharacteristic(
    nRF51ServiceUUID,
    &gatt_char_value[CHARACTERISTIC_LED], 1, 1,
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ |
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE |
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE |
    GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY );

  // create our service, with both characteristics
  gatt_service =
    new GattService(nRF51_GATT_SERVICE,
                    gatt_characteristics, CHARACTERISTIC_COUNT);

  BLE &ble = BLE::Instance();
//  ble.onEventsToProcess(scheduleBleEventsProcessing);
  ble.init(bleInitComplete);

  /* SpinWait for initialization to complete. This is necessary because the
     BLE object is used in the main loop below. */
  while (ble.hasInitialized()  == false)
  {
    /* spin loop */
  }

  // Основной цикл
  while (true)
  {
      if ( !key1 || !key2) {
        DISP_LED = !DISP_LED;
        KEY_TIME.attach(BUTTON, 5);
        wait(0.2);

      }

      //BACKLIGTH.attach(&TFT_LED, 30);

      // Проверка флага на старт программы и отоброжение таймера  ( TODO вынести в отдельную функцию и обновлять по прерыванию )
      if ( FLAG == 1 ) {

        // переводим время в другой формат ЧЧ:ММ:СС
        HOUR = TIME_PROGRAMM / 60 / 60;
        MIN = (TIME_PROGRAMM / 60) % 60;
        SEC = TIME_PROGRAMM % 60;
        // Тут надо добавить конвертацию типов пока вижу это как разделение на десятки и еденицы и далее по формуле i + '0' записывать их в массив.
        // конвертацию то я сделал но как то не так. сыпет муссором на дисплей вида 00:0000:000000 и это в лучшем случае...
        // Часы
        HOUR_CHAR[0] = ((HOUR / 10) % 10) + '0';
        HOUR_CHAR[1] = (HOUR % 10) + '0';
        // Минуты
        MIN_CHAR[0] = ((MIN / 10) % 10) + '0';
        MIN_CHAR[1] = (MIN % 10) + '0';
        // Секунды
        SEC_CHAR[0] = ((SEC / 10) % 10) + '0';
        SEC_CHAR[1] = (SEC % 10) + '0';
        // Так как библиотека принимает только char пришлось посимвольно выводить время...
        tft.drawChar(52, 48, HOUR_CHAR[0], WHITE, BLACK, 2);
        tft.drawChar(64, 48, HOUR_CHAR[1], WHITE, BLACK, 2);
        tft.drawChar(52, 64, MIN_CHAR[0], WHITE, BLACK, 2);
        tft.drawChar(64, 64, MIN_CHAR[1], WHITE, BLACK, 2);

        if (r >= 30) {
          r = 20;
          if (COLOR == WHITE) {
            COLOR = BLACK;
          }
          else (COLOR = WHITE);
        };

        tft.drawCircle(63, 62, r, COLOR);
        if (TIME_PROGRAMM < 1) {
          FLAG = 0;
        }
      }

      else {
        ble.waitForEvent();
    
      }
  }
}