Victor 3 лет назад
Родитель
Сommit
eb31dd66f6
8 измененных файлов с 246 добавлено и 12 удалено
  1. 84 3
      Sensors.c
  2. 15 0
      Sensors.h
  3. 3 0
      interfaces/OneWireSensor.c
  4. 4 2
      interfaces/SingleWireSensor.c
  5. 2 0
      unitemp.c
  6. 118 0
      views/SensorEdit_view.c
  7. 13 7
      views/SensorsList_view.c
  8. 7 0
      views/UnitempViews.h

+ 84 - 3
Sensors.c

@@ -35,6 +35,10 @@ static const GPIO GPIOList[] = {
     {16, "16 (C0)", &gpio_ext_pc0},
     {17, "17 (1W)", &ibutton_gpio}};
 
+//Список интерфейсов, которые прикреплены к GPIO (определяется индексом)
+//NULL - порт свободен, указатель на интерфейс - порт занят этим интерфейсом
+static const Interface* gpio_interfaces_list[GPIO_ITEMS] = {0};
+
 const Interface SINGLE_WIRE = {
     .name = "Single wire",
     .allocator = unitemp_singleWire_alloc,
@@ -86,6 +90,10 @@ const GPIO* unitemp_GPIO_getFromInt(uint8_t name) {
     return NULL;
 }
 
+const GPIO* unitemp_gpio_getFromIndex(uint8_t index) {
+    return &GPIOList[index];
+}
+
 uint8_t unitemp_GPIO_toInt(const GpioPin* gpio) {
     if(gpio == NULL) return 255;
     for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
@@ -96,6 +104,82 @@ uint8_t unitemp_GPIO_toInt(const GpioPin* gpio) {
     return 255;
 }
 
+uint8_t unitemp_gpio_to_index(const GpioPin* gpio) {
+    if(gpio == NULL) return 255;
+    for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
+        if(GPIOList[i].pin->pin == gpio->pin && GPIOList[i].pin->port == gpio->port) {
+            return i;
+        }
+    }
+    return 255;
+}
+
+uint8_t unitemp_gpio_getAviablePortsCount(const Interface* interface) {
+    uint8_t aviable_ports_count = 0;
+    for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
+        //Проверка для one wire
+        if(interface == &ONE_WIRE) {
+            if(gpio_interfaces_list[i] == NULL || gpio_interfaces_list[i] == &ONE_WIRE) {
+                aviable_ports_count++;
+            }
+        }
+
+        //Проверка для single wire
+        if(interface == &SINGLE_WIRE) {
+            if(gpio_interfaces_list[i] == NULL) {
+                aviable_ports_count++;
+            }
+        }
+
+        if(interface == &I2C) {
+            //У I2C два фиксированых порта
+            return 0;
+        }
+    }
+    return aviable_ports_count;
+}
+
+void unitemp_gpio_lock(const GPIO* gpio, const Interface* interface) {
+    uint8_t i = unitemp_gpio_to_index(gpio->pin);
+    if(i == 255) return;
+    gpio_interfaces_list[i] = interface;
+}
+
+void unitemp_gpio_unlock(const GPIO* gpio) {
+    uint8_t i = unitemp_gpio_to_index(gpio->pin);
+    if(i == 255) return;
+    gpio_interfaces_list[i] = NULL;
+}
+
+const GPIO* unitemp_gpio_getAviablePort(const Interface* interface, uint8_t index) {
+    uint8_t aviable_index = 0;
+    uint8_t aviable_port_count = unitemp_gpio_getAviablePortsCount(interface);
+    FURI_LOG_D(APP_NAME, "Aviable ports: %d", aviable_port_count);
+    for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
+        //Проверка для one wire
+        if(interface == &ONE_WIRE) {
+            if(gpio_interfaces_list[i] == NULL || gpio_interfaces_list[i] == &ONE_WIRE) {
+                if(aviable_index == index) {
+                    return unitemp_gpio_getFromIndex(i);
+                } else {
+                    aviable_index++;
+                }
+            }
+        }
+        //Проверка для single wire
+        if(interface == &SINGLE_WIRE) {
+            if(gpio_interfaces_list[i] == NULL) {
+                if(aviable_index == index) {
+                    return unitemp_gpio_getFromIndex(i);
+                } else {
+                    aviable_index++;
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
 bool unitemp_sensors_load() {
     FURI_LOG_D(APP_NAME, "Loading sensors...");
     app->sensors_count = 0;
@@ -177,9 +261,6 @@ bool unitemp_sensors_load() {
         line = strtok((char*)NULL, "\n");
     }
 
-    // uint16_t otherValues[] = {0x76};
-    // unitemp_sensor_alloc("BMP280", BMP280, otherValues);
-
     free(file_buf);
     file_stream_close(app->file_stream);
     stream_free(app->file_stream);

+ 15 - 0
Sensors.h

@@ -180,5 +180,20 @@ void unitemp_sensors_updateValues(void);
  */
 void unitemp_sensors_free(void);
 
+/**
+ * @brief Высвыбождение памяти конкретного датчка
+ * 
+ * @param sensor Указатель на датчик
+ */
+void unitemp_sensor_free(Sensor* sensor);
+
 const SensorType* unitemp_getTypeFromInt(int type);
+
+uint8_t unitemp_gpio_getAviablePortsCount(const Interface* interface);
+
+void unitemp_gpio_lock(const GPIO* gpio, const Interface* interface);
+
+void unitemp_gpio_unlock(const GPIO* gpio);
+
+const GPIO* unitemp_gpio_getAviablePort(const Interface* interface, uint8_t index);
 #endif

+ 3 - 0
interfaces/OneWireSensor.c

@@ -19,6 +19,8 @@ OneWireBus* uintemp_OneWire_bus_alloc(const GPIO* gpio) {
     if(gpio == NULL) {
         return NULL;
     }
+
+    unitemp_gpio_lock(gpio, &ONE_WIRE);
     //Проверка на наличие шины на этом порте
     for(uint8_t i = 0; i < app->sensors_count; i++) {
         if(app->sensors[i]->type == &DS18x2x &&
@@ -290,6 +292,7 @@ bool unitemp_OneWire_sensor_alloc(Sensor* sensor, uint8_t* anotherValues) {
 
 bool unitemp_OneWire_sensor_free(Sensor* sensor) {
     if(((OneWireSensor*)sensor->instance)->bus->device_count == 0) {
+        unitemp_gpio_unlock(((OneWireSensor*)sensor->instance)->bus->gpio);
         free(((OneWireSensor*)sensor->instance)->bus);
     }
     free(sensor->instance);

+ 4 - 2
interfaces/SingleWireSensor.c

@@ -17,7 +17,7 @@ const SensorType DHT11 = {
     .deinitializer = unitemp_singleWire_deinit,
     .updater = unitemp_singleWire_update};
 const SensorType DHT12_SW = {
-    .typename = "DHT12 (single wire)",
+    .typename = "DHT12",
     .interface = &SINGLE_WIRE,
     .pollingInterval = 2000,
     .allocator = unitemp_singleWire_alloc,
@@ -45,7 +45,7 @@ const SensorType DHT22 = {
     .deinitializer = unitemp_singleWire_deinit,
     .updater = unitemp_singleWire_update};
 const SensorType AM2320_SW = {
-    .typename = "AM2320 (single wire)",
+    .typename = "AM2320",
     .interface = &SINGLE_WIRE,
     .pollingInterval = 2000,
     .allocator = unitemp_singleWire_alloc,
@@ -95,6 +95,7 @@ bool unitemp_singleWire_init(Sensor* sensor) {
 bool unitemp_singleWire_deinit(Sensor* sensor) {
     SingleWireSensor* instance = ((Sensor*)sensor)->instance;
     if(instance == NULL || instance->gpio == NULL) return false;
+    unitemp_gpio_unlock(instance->gpio);
     //Низкий уровень по умолчанию
     furi_hal_gpio_write(instance->gpio->pin, false);
     //Режим работы - аналог, подтяжка выключена
@@ -110,6 +111,7 @@ bool unitemp_singleWire_sensorSetGPIO(Sensor* sensor, const GPIO* gpio) {
     if(sensor == NULL || gpio == NULL) return false;
     SingleWireSensor* instance = sensor->instance;
     instance->gpio = gpio;
+    unitemp_gpio_lock(gpio, &SINGLE_WIRE);
     return true;
 }
 const GPIO* unitemp_singleWire_sensorGetGPIO(Sensor* sensor) {

+ 2 - 0
unitemp.c

@@ -182,6 +182,7 @@ static bool unitemp_alloc(void) {
     unitemp_MainMenu_alloc();
     unitemp_Settings_alloc();
     unitemp_SensorsList_alloc();
+    unitemp_SensorEdit_alloc();
 
     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
 
@@ -192,6 +193,7 @@ static bool unitemp_alloc(void) {
  * @brief Освыбождение памяти после работы приложения
  */
 static void unitemp_free(void) {
+    unitemp_SensorEdit_free();
     unitemp_SensorsList_free();
     unitemp_Settings_free();
     unitemp_MainMenu_free();

+ 118 - 0
views/SensorEdit_view.c

@@ -0,0 +1,118 @@
+#include "UnitempViews.h"
+#include <gui/modules/variable_item_list.h>
+
+#include "../interfaces/SingleWireSensor.h"
+#include "../interfaces/OneWireSensor.h"
+
+//Текущий вид
+static View* view;
+//Список
+static VariableItemList* variable_item_list;
+//Текущий редактируемый датчик
+Sensor* editable_sensor;
+
+//Элемент списка - имя датчика
+VariableItem* sensor_name_item;
+#define VIEW_ID SENSOREDIT_VIEW
+
+/**
+ * @brief Функция обработки нажатия кнопки "Назад"
+ *
+ * @param context Указатель на данные приложения
+ * @return ID вида в который нужно переключиться
+ */
+static uint32_t _exit_callback(void* context) {
+    UNUSED(context);
+
+    //Возврат предыдущий вид
+    return MAINMENU_VIEW;
+}
+/**
+ * @brief Функция обработки нажатия средней кнопки
+ *
+ * @param context Указатель на данные приложения
+ * @param index На каком элементе списка была нажата кнопка
+ */
+static void _enter_callback(void* context, uint32_t index) {
+    UNUSED(context);
+    UNUSED(index);
+}
+
+/**
+ * @brief Функция обработки изменения значения GPIO
+ * 
+ * @param item Указатель на элемент списка
+ */
+static void _gpio_change_callback(VariableItem* item) {
+    uint8_t index = variable_item_get_current_value_index(item);
+    if(editable_sensor->type->interface == &SINGLE_WIRE) {
+        SingleWireSensor* instance = editable_sensor->instance;
+        instance->gpio = unitemp_gpio_getAviablePort(editable_sensor->type->interface, index);
+        variable_item_set_current_value_text(item, instance->gpio->name);
+    }
+    if(editable_sensor->type->interface == &ONE_WIRE) {
+        OneWireSensor* instance = editable_sensor->instance;
+        instance->bus->gpio = unitemp_gpio_getAviablePort(editable_sensor->type->interface, index);
+        variable_item_set_current_value_text(item, instance->bus->gpio->name);
+    }
+}
+
+/**
+ * @brief Создание меню редактирования датчка
+ */
+void unitemp_SensorEdit_alloc(void) {
+    variable_item_list = variable_item_list_alloc();
+    //Сброс всех элементов меню
+    variable_item_list_reset(variable_item_list);
+
+    //Добавление колбека на нажатие средней кнопки
+    variable_item_list_set_enter_callback(variable_item_list, _enter_callback, app);
+
+    //Создание вида из списка
+    view = variable_item_list_get_view(variable_item_list);
+    //Добавление колбека на нажатие кнопки "Назад"
+    view_set_previous_callback(view, _exit_callback);
+    //Добавление вида в диспетчер
+    view_dispatcher_add_view(app->view_dispatcher, VIEW_ID, view);
+}
+
+void unitemp_SensorEdit_switch(Sensor* sensor) {
+    editable_sensor = sensor;
+    //Сброс всех элементов меню
+    variable_item_list_reset(variable_item_list);
+    //Обнуление последнего выбранного пункта
+    variable_item_list_set_selected_item(variable_item_list, 0);
+    //Имя датчика
+    sensor_name_item = variable_item_list_add(variable_item_list, "Name", 1, NULL, NULL);
+    variable_item_set_current_value_index(sensor_name_item, 0);
+    variable_item_set_current_value_text(sensor_name_item, sensor->name);
+
+    //Тип датчика (не редактируется)
+    VariableItem* item = variable_item_list_add(variable_item_list, "Type", 1, NULL, NULL);
+    variable_item_set_current_value_index(item, 0);
+    variable_item_set_current_value_text(item, sensor->type->typename);
+
+    //Порт подключения датчка (для one wire и single wire)
+    if(sensor->type->interface == &ONE_WIRE || sensor->type->interface == &SINGLE_WIRE) {
+        uint8_t aviable_gpio_count = unitemp_gpio_getAviablePortsCount(sensor->type->interface);
+        item = variable_item_list_add(
+            variable_item_list, "GPIO", aviable_gpio_count, _gpio_change_callback, app);
+        variable_item_set_current_value_index(item, 0);
+        variable_item_set_current_value_text(
+            item, unitemp_gpio_getAviablePort(sensor->type->interface, 0)->name);
+    }
+
+    //Сохранение
+    variable_item_list_add(variable_item_list, "Save", 1, NULL, NULL);
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID);
+}
+
+void unitemp_SensorEdit_free(void) {
+    //Очистка списка элементов
+    variable_item_list_free(variable_item_list);
+    //Очистка вида
+    view_free(view);
+    //Удаление вида после обработки
+    view_dispatcher_remove_view(app->view_dispatcher, VIEW_ID);
+}

+ 13 - 7
views/SensorsList_view.c

@@ -1,5 +1,6 @@
 #include "UnitempViews.h"
 #include <gui/modules/variable_item_list.h>
+#include <stdio.h>
 
 //Текущий вид
 static View* view;
@@ -28,7 +29,18 @@ static uint32_t _exit_callback(void* context) {
  */
 static void _enter_callback(void* context, uint32_t index) {
     UNUSED(context);
-    UNUSED(index);
+    //Имя датчка
+    char sensor_name[11];
+    snprintf(sensor_name, 11, "Sensor %d", app->sensors_count + 1);
+    const SensorType* st = unitemp_getSensorsTypes()[index];
+    uint8_t anotherValues[1] = {0};
+    //Выбор первого доступного порта для датчиков single wire и one wire
+    if(st->interface == &SINGLE_WIRE || st->interface == &ONE_WIRE) {
+        anotherValues[0] = unitemp_GPIO_toInt(unitemp_gpio_getAviablePort(st->interface, 0)->pin);
+    };
+    //Для I2C адрес выберится автоматически
+
+    unitemp_SensorEdit_switch(unitemp_sensor_alloc(sensor_name, st, anotherValues));
 }
 
 /**
@@ -60,12 +72,6 @@ void unitemp_SensorsList_switch(void) {
     //Обнуление последнего выбранного пункта
     variable_item_list_set_selected_item(variable_item_list, 0);
 
-    // variable_item_set_current_value_index(
-    //     infinity_backlight_item, (uint8_t)app->SensorsList.infinityBacklight);
-    // variable_item_set_current_value_text(
-    //     infinity_backlight_item,
-    //     states[variable_item_get_current_value_index(infinity_backlight_item)]);
-
     view_dispatcher_switch_to_view(app->view_dispatcher, VIEW_ID);
 }
 

+ 7 - 0
views/UnitempViews.h

@@ -9,6 +9,7 @@ typedef enum UnitempViews {
     MAINMENU_VIEW,
     SETTINGS_VIEW,
     SENSORSLIST_VIEW,
+    SENSOREDIT_VIEW,
 
     VIEWS_COUNT
 } UnitempViews;
@@ -31,4 +32,10 @@ void unitemp_Settings_free(void);
 void unitemp_SensorsList_alloc(void);
 void unitemp_SensorsList_switch(void);
 void unitemp_SensorsList_free(void);
+
+/* Редактор датчка */
+void unitemp_SensorEdit_alloc(void);
+//sensor - указатель на редактируемый датчик
+void unitemp_SensorEdit_switch(Sensor* sensor);
+void unitemp_SensorEdit_free(void);
 #endif