Update UniTemp and run fbt format

This commit is contained in:
MX
2023-01-18 22:25:39 +03:00
parent e4aad248cf
commit 5a9da13d84
36 changed files with 1478 additions and 966 deletions
+24 -7
View File
@@ -66,9 +66,14 @@ const Interface ONE_WIRE = {
.allocator = unitemp_onewire_sensor_alloc,
.mem_releaser = unitemp_onewire_sensor_free,
.updater = unitemp_onewire_sensor_update};
const Interface SPI = {
.name = "SPI",
.allocator = unitemp_spi_sensor_alloc,
.mem_releaser = unitemp_spi_sensor_free,
.updater = unitemp_spi_sensor_update};
//Перечень интерфейсов подключения
//static const Interface* interfaces[] = {&SINGLE_WIRE, &I2C, &ONE_WIRE};
//static const Interface* interfaces[] = {&SINGLE_WIRE, &I2C, &ONE_WIRE, &SPI};
//Перечень датчиков
static const SensorType* sensorTypes[] = {
&DHT11,
@@ -87,7 +92,8 @@ static const SensorType* sensorTypes[] = {
&HDC1080,
&BMP180,
&BMP280,
&BME280};
&BME280,
&MAX31855};
const SensorType* unitemp_sensors_getTypeFromInt(uint8_t index) {
if(index > SENSOR_TYPES_COUNT) return NULL;
@@ -166,7 +172,7 @@ uint8_t unitemp_gpio_getAviablePortsCount(const Interface* interface, const GPIO
}
//Проверка для single wire
if(interface == &SINGLE_WIRE) {
if(interface == &SINGLE_WIRE || interface == &SPI) {
if(gpio_interfaces_list[i] == NULL || (unitemp_gpio_getFromIndex(i) == extraport)) {
aviable_ports_count++;
}
@@ -205,6 +211,13 @@ const GPIO*
return NULL;
}
}
if(interface == &SPI) {
if(!((gpio_interfaces_list[0] == NULL || gpio_interfaces_list[0] == &SPI) &&
(gpio_interfaces_list[1] == NULL || gpio_interfaces_list[1] == &SPI) &&
(gpio_interfaces_list[3] == NULL || gpio_interfaces_list[3] == &SPI))) {
return NULL;
}
}
uint8_t aviable_index = 0;
for(uint8_t i = 0; i < GPIO_ITEMS; i++) {
@@ -222,7 +235,7 @@ const GPIO*
}
}
//Проверка для single wire
if(interface == &SINGLE_WIRE) {
if(interface == &SINGLE_WIRE || interface == &SPI) {
if(gpio_interfaces_list[i] == NULL || unitemp_gpio_getFromIndex(i) == extraport) {
if(aviable_index == index) {
return unitemp_gpio_getFromIndex(i);
@@ -435,6 +448,11 @@ bool unitemp_sensors_save(void) {
stream_write_format(
app->file_stream, "%d\n", unitemp_singlewire_sensorGetGPIO(sensor)->num);
}
if(sensor->type->interface == &SPI) {
uint8_t gpio_num = ((SPISensor*)sensor->instance)->CS_pin->num;
stream_write_format(app->file_stream, "%d\n", gpio_num);
}
if(sensor->type->interface == &I2C) {
stream_write_format(
app->file_stream, "%X\n", ((I2CSensor*)sensor->instance)->currentI2CAdr);
@@ -512,7 +530,7 @@ Sensor* unitemp_sensor_alloc(char* name, const SensorType* type, char* args) {
//Выход если датчик успешно развёрнут
if(status) {
FURI_LOG_I(APP_NAME, "Sensor %s allocated", name);
UNITEMP_DEBUG("Sensor %s allocated", name);
return sensor;
}
//Выход с очисткой если память для датчика не была выделена
@@ -545,7 +563,6 @@ void unitemp_sensor_free(Sensor* sensor) {
FURI_LOG_E(APP_NAME, "Sensor %s memory is not released", sensor->name);
}
free(sensor->name);
//free(sensor);
}
void unitemp_sensors_free(void) {
@@ -573,7 +590,7 @@ bool unitemp_sensors_init(void) {
app->sensors[i]->name);
result = false;
}
UNITEMP_DEBUG("Sensor %s successfully initialized", app->sensors[i]->name);
FURI_LOG_I(APP_NAME, "Sensor %s successfully initialized", app->sensors[i]->name);
}
app->sensors_ready = true;
return result;
+2 -1
View File
@@ -136,7 +136,7 @@ typedef struct Sensor {
extern const Interface SINGLE_WIRE; //Собственный однопроводной протокол датчиков DHTXX и AM23XX
extern const Interface ONE_WIRE; //Однопроводной протокол Dallas
extern const Interface I2C; //I2C_2 (PC0, PC1)
//extern const Interface SPI;
extern const Interface SPI; //SPI_1 (MOSI - 2, MISO - 3, CS - 4, SCK - 5)
/* ============================= Датчик(и) ============================= */
/**
@@ -326,4 +326,5 @@ const GPIO*
#include "./sensors/BMP180.h"
#include "./sensors/HTU21x.h"
#include "./sensors/HDC1080.h"
#include "./sensors/MAX31855.h"
#endif
@@ -0,0 +1,89 @@
/*
Unitemp - Universal temperature reader
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <furi.h>
#include <furi_hal.h>
#include "SPISensor.h"
static uint8_t sensors_count = 0;
bool unitemp_spi_sensor_alloc(Sensor* sensor, char* args) {
if(args == NULL) return false;
//Создание инстанса датчика SPI
SPISensor* instance = malloc(sizeof(SPISensor));
if(instance == NULL) {
FURI_LOG_E(APP_NAME, "Sensor %s instance allocation error", sensor->name);
return false;
}
sensor->instance = instance;
//Определение GPIO chip select
int gpio = 255;
sscanf(args, "%d", &gpio);
instance->CS_pin = unitemp_gpio_getFromInt(gpio);
if(instance->CS_pin == NULL) {
FURI_LOG_E(APP_NAME, "Sensor %s GPIO setting error", sensor->name);
free(instance);
return false;
}
instance->spi = malloc(sizeof(FuriHalSpiBusHandle));
memcpy(instance->spi, &furi_hal_spi_bus_handle_external, sizeof(FuriHalSpiBusHandle));
instance->spi->cs = instance->CS_pin->pin;
bool status = sensor->type->allocator(sensor, args);
//Блокировка портов GPIO
sensors_count++;
unitemp_gpio_lock(unitemp_gpio_getFromInt(2), &SPI);
unitemp_gpio_lock(unitemp_gpio_getFromInt(3), &SPI);
unitemp_gpio_lock(unitemp_gpio_getFromInt(5), &SPI);
unitemp_gpio_lock(instance->CS_pin, &SPI);
return status;
}
bool unitemp_spi_sensor_free(Sensor* sensor) {
bool status = sensor->type->mem_releaser(sensor);
unitemp_gpio_unlock(((SPISensor*)sensor->instance)->CS_pin);
free(((SPISensor*)(sensor->instance))->spi);
free(sensor->instance);
if(--sensors_count == 0) {
unitemp_gpio_unlock(unitemp_gpio_getFromInt(2));
unitemp_gpio_unlock(unitemp_gpio_getFromInt(3));
unitemp_gpio_unlock(unitemp_gpio_getFromInt(5));
}
return status;
}
bool unitemp_spi_sensor_init(Sensor* sensor) {
return sensor->type->initializer(sensor);
}
bool unitemp_spi_sensor_deinit(Sensor* sensor) {
UNUSED(sensor);
return true;
}
UnitempStatus unitemp_spi_sensor_update(Sensor* sensor) {
return sensor->type->updater(sensor);
}
@@ -0,0 +1,66 @@
/*
Unitemp - Universal temperature reader
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef UNITEMP_SPI
#define UNITEMP_SPI
#include "../unitemp.h"
#include <furi_hal_spi.h>
//Структура SPI датчика
typedef struct SPISensor {
//Указатель на интерфейс SPI
FuriHalSpiBusHandle* spi;
//Порт подключения CS
const GPIO* CS_pin;
} SPISensor;
/**
* @brief Выделение памяти для датчика с интерфейсом SPI
* @param sensor Указатель на датчик
* @param args Указатель на массив аргументов с параметрами датчика
* @return Истина если всё ок
*/
bool unitemp_spi_sensor_alloc(Sensor* sensor, char* args);
/**
* @brief Высвобождение памяти инстанса датчика
* @param sensor Указатель на датчик
*/
bool unitemp_spi_sensor_free(Sensor* sensor);
/**
* @brief Инициализации датчика с интерфейсом one wire
* @param sensor Указатель на датчик
* @return Истина если инициализация упспешная
*/
bool unitemp_spi_sensor_init(Sensor* sensor);
/**
* @brief Деинициализация датчика
* @param sensor Указатель на датчик
*/
bool unitemp_spi_sensor_deinit(Sensor* sensor);
/**
* @brief Обновить значение с датчка
* @param sensor Указатель на датчик
* @return Статус обновления
*/
UnitempStatus unitemp_spi_sensor_update(Sensor* sensor);
#endif
@@ -0,0 +1,93 @@
/*
Unitemp - Universal temperature reader
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "MAX31855.h"
const SensorType MAX31855 = {
.typename = "MAX31855",
.altname = "MAX31855 (Thermocouple)",
.interface = &SPI,
.datatype = UT_TEMPERATURE,
.pollingInterval = 500,
.allocator = unitemp_MAX31855_alloc,
.mem_releaser = unitemp_MAX31855_free,
.initializer = unitemp_MAX31855_init,
.deinitializer = unitemp_MAX31855_deinit,
.updater = unitemp_MAX31855_update};
bool unitemp_MAX31855_alloc(Sensor* sensor, char* args) {
UNUSED(sensor);
UNUSED(args);
return true;
}
bool unitemp_MAX31855_free(Sensor* sensor) {
UNUSED(sensor);
return true;
}
bool unitemp_MAX31855_init(Sensor* sensor) {
SPISensor* instance = sensor->instance;
furi_hal_spi_bus_handle_init(instance->spi);
UNUSED(instance);
return true;
}
bool unitemp_MAX31855_deinit(Sensor* sensor) {
UNUSED(sensor);
return true;
}
UnitempStatus unitemp_MAX31855_update(Sensor* sensor) {
SPISensor* instance = sensor->instance;
furi_hal_spi_acquire(instance->spi);
furi_hal_gpio_write(instance->CS_pin->pin, false);
uint8_t buff[4] = {0};
furi_hal_spi_bus_rx(instance->spi, buff, 4, 0xFF);
furi_hal_spi_release(instance->spi);
uint32_t raw = (buff[0] << 24) | (buff[1] << 16) | (buff[2] << 8) | buff[3];
if(raw == 0xFFFFFFFF || raw == 0) return UT_SENSORSTATUS_TIMEOUT;
//Определение состояния термопары
uint8_t state = raw & 0b111;
//Обрыв
if(state == 0x01) {
UNITEMP_DEBUG("%s has thermocouple open circuit", sensor->name);
return UT_SENSORSTATUS_ERROR;
}
//Короткое замыкание к земле
if(state == 0x02) {
UNITEMP_DEBUG("%s has thermocouple short to GND", sensor->name);
return UT_SENSORSTATUS_ERROR;
}
//Короткое замыкание к питанию
if(state == 0x04) {
UNITEMP_DEBUG("%s has thermocouple short to VCC", sensor->name);
return UT_SENSORSTATUS_ERROR;
}
raw = (raw >> 16) & 0xFFFC;
sensor->temp = (int16_t)(raw) / 16.0f;
return UT_SENSORSTATUS_OK;
}
@@ -0,0 +1,65 @@
/*
Unitemp - Universal temperature reader
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef UNITEMP_MAX31855
#define UNITEMP_MAX31855
#include "../unitemp.h"
#include "../Sensors.h"
#include "../interfaces/SPISensor.h"
extern const SensorType MAX31855;
/**
* @brief Выделение памяти и установка начальных значений датчика MAX31855
*
* @param sensor Указатель на создаваемый датчик
* @return Истина при успехе
*/
bool unitemp_MAX31855_alloc(Sensor* sensor, char* args);
/**
* @brief Инициализации датчика MAX31855
*
* @param sensor Указатель на датчик
* @return Истина если инициализация упспешная
*/
bool unitemp_MAX31855_init(Sensor* sensor);
/**
* @brief Деинициализация датчика
*
* @param sensor Указатель на датчик
*/
bool unitemp_MAX31855_deinit(Sensor* sensor);
/**
* @brief Обновление значений из датчика
*
* @param sensor Указатель на датчик
* @return Статус обновления
*/
UnitempStatus unitemp_MAX31855_update(Sensor* sensor);
/**
* @brief Высвободить память датчика
*
* @param sensor Указатель на датчик
*/
bool unitemp_MAX31855_free(Sensor* sensor);
#endif
@@ -76,7 +76,7 @@ static void _draw_temperature(Canvas* canvas, Sensor* sensor, uint8_t x, uint8_t
app->buff[0] = '-';
offset = 1;
}
snprintf((char*)(app->buff + offset), BUFF_SIZE, "%d", (int8_t)sensor->temp);
snprintf((char*)(app->buff + offset), BUFF_SIZE, "%d", (int16_t)sensor->temp);
canvas_set_font(canvas, FontBigNumbers);
canvas_draw_str_aligned(
canvas,
@@ -237,6 +237,7 @@ static void _draw_carousel_values(Canvas* canvas) {
canvas_draw_icon(canvas, 34, 23, frames[furi_get_tick() % 2250 / 750]);
canvas_set_font(canvas, FontSecondary);
//TODO: Оптимизировать эту срань
if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &SINGLE_WIRE) {
snprintf(
app->buff,
@@ -256,6 +257,9 @@ static void _draw_carousel_values(Canvas* canvas) {
if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &I2C) {
snprintf(app->buff, BUFF_SIZE, "Waiting for module on I2C pins");
}
if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &SPI) {
snprintf(app->buff, BUFF_SIZE, "Waiting for module on SPI pins");
}
canvas_draw_str_aligned(canvas, 64, 19, AlignCenter, AlignCenter, app->buff);
return;
}
@@ -304,6 +308,8 @@ static void _draw_carousel_values(Canvas* canvas) {
break;
}
}
//TODO: Оптимизировать вывод информации
static void _draw_carousel_info(Canvas* canvas) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 10, 23, "Type:");
@@ -351,6 +357,25 @@ static void _draw_carousel_info(Canvas* canvas) {
->gpio->name);
}
if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &SPI) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 10, 35, "MISO pin:");
canvas_draw_str(canvas, 10, 46, "CS pin:");
canvas_draw_str(canvas, 10, 58, "SCK pin:");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(
canvas, 41, 23, unitemp_sensor_getActive(generalview_sensor_index)->type->typename);
canvas_draw_str(canvas, 60, 35, unitemp_gpio_getFromInt(3)->name);
canvas_draw_str(
canvas,
47,
46,
((SPISensor*)unitemp_sensor_getActive(generalview_sensor_index)->instance)
->CS_pin->name);
canvas_draw_str(canvas, 54, 58, unitemp_gpio_getFromInt(5)->name);
}
if(unitemp_sensor_getActive(generalview_sensor_index)->type->interface == &I2C) {
canvas_set_font(canvas, FontPrimary);
canvas_draw_str(canvas, 10, 35, "I2C addr:");
@@ -193,6 +193,12 @@ static void _gpio_change_callback(VariableItem* item) {
unitemp_gpio_getAviablePort(editable_sensor->type->interface, index, initial_gpio);
variable_item_set_current_value_text(item, instance->gpio->name);
}
if(editable_sensor->type->interface == &SPI) {
SPISensor* instance = editable_sensor->instance;
instance->CS_pin =
unitemp_gpio_getAviablePort(editable_sensor->type->interface, index, initial_gpio);
variable_item_set_current_value_text(item, instance->CS_pin->name);
}
if(editable_sensor->type->interface == &ONE_WIRE) {
OneWireSensor* instance = editable_sensor->instance;
instance->bus->gpio =
@@ -296,12 +302,15 @@ void unitemp_SensorEdit_switch(Sensor* sensor) {
offset_buff, OFFSET_BUFF_SIZE, "%+1.1f", (double)(editable_sensor->temp_offset / 10.0));
variable_item_set_current_value_text(temp_offset_item, offset_buff);
//Порт подключения датчка (для one wire и single wire)
if(sensor->type->interface == &ONE_WIRE || sensor->type->interface == &SINGLE_WIRE) {
//Порт подключения датчка (для one wire, SPI и single wire)
if(sensor->type->interface == &ONE_WIRE || sensor->type->interface == &SINGLE_WIRE ||
sensor->type->interface == &SPI) {
if(sensor->type->interface == &ONE_WIRE) {
initial_gpio = ((OneWireSensor*)editable_sensor->instance)->bus->gpio;
} else {
} else if(sensor->type->interface == &SINGLE_WIRE) {
initial_gpio = ((SingleWireSensor*)editable_sensor->instance)->gpio;
} else if(sensor->type->interface == &SPI) {
initial_gpio = ((SPISensor*)editable_sensor->instance)->CS_pin;
}
uint8_t aviable_gpio_count =
@@ -86,8 +86,8 @@ static void _enter_callback(void* context, uint32_t index) {
return;
}
//Выбор первого доступного порта для датчика single wire
if(type->interface == &SINGLE_WIRE) {
//Выбор первого доступного порта для датчика single wire и SPI
if(type->interface == &SINGLE_WIRE || type->interface == &SPI) {
snprintf(
args,
4,