mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-02-12 04:31:22 -05:00
I2cDev_PPmod periodic sensor query (#2315)
* Add more data tx from esp * command enum rework. +1 for JT * filter 0 query interval * i2c timeouts and sanity check on ppmod
This commit is contained in:
parent
7a38b04192
commit
c90f0944b1
@ -149,6 +149,7 @@ const NavigationView::AppList NavigationView::appList = {
|
||||
{"search", "Search", RX, Color::yellow(), &bitmap_icon_search, new ViewFactory<SearchView>()},
|
||||
{"subghzd", "SubGhzD", RX, Color::yellow(), &bitmap_icon_remote, new ViewFactory<SubGhzDView>()},
|
||||
{"weather", "Weather", RX, Color::green(), &bitmap_icon_thermometer, new ViewFactory<WeatherView>()},
|
||||
//{"fskrx", "FSK RX", RX, Color::yellow(), &bitmap_icon_remote, new ViewFactory<FskxRxMainView>()}, //for JT
|
||||
//{"dmr", "DMR", RX, Color::dark_grey(), &bitmap_icon_dmr, new ViewFactory<NotImplementedView>()},
|
||||
//{"sigfox", "SIGFOX", RX, Color::dark_grey(), &bitmap_icon_fox, new ViewFactory<NotImplementedView>()},
|
||||
//{"lora", "LoRa", RX, Color::dark_grey(), &bitmap_icon_lora, new ViewFactory<NotImplementedView>()},
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include "i2cdev_ppmod.hpp"
|
||||
#include "portapack.hpp"
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace i2cdev {
|
||||
@ -30,11 +29,95 @@ bool I2cDev_PPmod::init(uint8_t addr_) {
|
||||
if (addr_ != I2CDEV_PPMOD_ADDR_1) return false;
|
||||
addr = addr_;
|
||||
model = I2CDECMDL_PPMOD;
|
||||
query_interval = 10;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void I2cDev_PPmod::update() {
|
||||
auto mask = get_features_mask();
|
||||
if (mask & (uint64_t)SupportedFeatures::FEAT_GPS) {
|
||||
auto data = get_gps_data();
|
||||
if (data.has_value()) {
|
||||
GPSPosDataMessage msg{data.value().latitude, data.value().longitude, (int32_t)data.value().altitude, (int32_t)data.value().speed, data.value().sats_in_use};
|
||||
EventDispatcher::send_message(msg);
|
||||
}
|
||||
}
|
||||
if (mask & (uint64_t)SupportedFeatures::FEAT_ORIENTATION) {
|
||||
auto data = get_orientation_data();
|
||||
if (data.has_value()) {
|
||||
OrientationDataMessage msg{(uint16_t)data.value().angle, (int16_t)data.value().tilt};
|
||||
EventDispatcher::send_message(msg);
|
||||
}
|
||||
}
|
||||
if (mask & (uint64_t)SupportedFeatures::FEAT_ENVIRONMENT) {
|
||||
auto data = get_environment_data();
|
||||
if (data.has_value()) {
|
||||
EnvironmentDataMessage msg{data.value().temperature, data.value().humidity, data.value().pressure};
|
||||
EventDispatcher::send_message(msg);
|
||||
}
|
||||
}
|
||||
if (mask & (uint64_t)SupportedFeatures::FEAT_LIGHT) {
|
||||
auto data = get_light_data();
|
||||
if (data.has_value()) {
|
||||
LightDataMessage msg{data.value()};
|
||||
EventDispatcher::send_message(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<orientation_t> I2cDev_PPmod::get_orientation_data() {
|
||||
Command cmd = Command::COMMAND_GETFEAT_DATA_ORIENTATION;
|
||||
orientation_t data;
|
||||
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(orientation_t));
|
||||
if (success == false) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
std::optional<gpssmall_t> I2cDev_PPmod::get_gps_data() {
|
||||
Command cmd = Command::COMMAND_GETFEAT_DATA_GPS;
|
||||
gpssmall_t data;
|
||||
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(gpssmall_t));
|
||||
if (success == false) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
std::optional<environment_t> I2cDev_PPmod::get_environment_data() {
|
||||
Command cmd = Command::COMMAND_GETFEAT_DATA_ENVIRONMENT;
|
||||
environment_t data;
|
||||
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(environment_t));
|
||||
if (success == false) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
std::optional<uint16_t> I2cDev_PPmod::get_light_data() {
|
||||
Command cmd = Command::COMMAND_GETFEAT_DATA_LIGHT;
|
||||
uint16_t data;
|
||||
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&data, sizeof(uint16_t));
|
||||
if (success == false) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
uint64_t I2cDev_PPmod::get_features_mask() {
|
||||
uint64_t mask = 0;
|
||||
Command cmd = Command::COMMAND_GETFEATURE_MASK;
|
||||
bool success = i2c_read((uint8_t*)&cmd, 2, (uint8_t*)&mask, sizeof(mask));
|
||||
if (success == false) {
|
||||
return 0;
|
||||
}
|
||||
// sanity check
|
||||
if (mask == UINT64_MAX) {
|
||||
return 0;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
std::optional<I2cDev_PPmod::device_info> I2cDev_PPmod::readDeviceInfo() {
|
||||
@ -45,7 +128,10 @@ std::optional<I2cDev_PPmod::device_info> I2cDev_PPmod::readDeviceInfo() {
|
||||
if (success == false) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (info.application_count > 1000) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@ -58,6 +144,10 @@ std::optional<I2cDev_PPmod::standalone_app_info> I2cDev_PPmod::getStandaloneAppI
|
||||
if (success == false) {
|
||||
return std::nullopt;
|
||||
}
|
||||
// sanity check
|
||||
if (info.binary_size == UINT32_MAX) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "standalone_app.hpp"
|
||||
#include "i2cdevmanager.hpp"
|
||||
|
||||
#include "i2cdev_ppmod_helper.hpp"
|
||||
|
||||
namespace i2cdev {
|
||||
|
||||
class I2cDev_PPmod : public I2cDev {
|
||||
@ -38,13 +40,22 @@ class I2cDev_PPmod : public I2cDev {
|
||||
COMMAND_NONE = 0,
|
||||
|
||||
// will respond with device_info
|
||||
COMMAND_INFO = 0x18F0,
|
||||
COMMAND_INFO = 1,
|
||||
|
||||
// will respond with info of application
|
||||
COMMAND_APP_INFO = 0xA90B,
|
||||
COMMAND_APP_INFO,
|
||||
|
||||
// will respond with application data
|
||||
COMMAND_APP_TRANSFER = 0x4183,
|
||||
COMMAND_APP_TRANSFER,
|
||||
|
||||
// Feature specific commands
|
||||
COMMAND_GETFEATURE_MASK,
|
||||
// Feature data getter commands
|
||||
COMMAND_GETFEAT_DATA_GPS,
|
||||
COMMAND_GETFEAT_DATA_ORIENTATION,
|
||||
COMMAND_GETFEAT_DATA_ENVIRONMENT,
|
||||
COMMAND_GETFEAT_DATA_LIGHT,
|
||||
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@ -66,9 +77,14 @@ class I2cDev_PPmod : public I2cDev {
|
||||
bool init(uint8_t addr_) override;
|
||||
void update() override;
|
||||
|
||||
std::optional<device_info> readDeviceInfo();
|
||||
std::optional<standalone_app_info> getStandaloneAppInfo(uint32_t index);
|
||||
std::vector<uint8_t> downloadStandaloneApp(uint32_t index, size_t offset);
|
||||
uint64_t get_features_mask();
|
||||
std::optional<device_info> readDeviceInfo();
|
||||
std::optional<gpssmall_t> get_gps_data();
|
||||
std::optional<orientation_t> get_orientation_data();
|
||||
std::optional<environment_t> get_environment_data();
|
||||
std::optional<uint16_t> get_light_data();
|
||||
};
|
||||
|
||||
} /* namespace i2cdev */
|
||||
|
59
firmware/common/i2cdev_ppmod_helper.hpp
Normal file
59
firmware/common/i2cdev_ppmod_helper.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef I2CDEV_PPMOD_HELPER_H
|
||||
#define I2CDEV_PPMOD_HELPER_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
enum class SupportedFeatures : uint64_t {
|
||||
FEAT_NONE = 0,
|
||||
FEAT_EXT_APP = 1 << 0,
|
||||
FEAT_UART = 1 << 1,
|
||||
FEAT_GPS = 1 << 2,
|
||||
FEAT_ORIENTATION = 1 << 3,
|
||||
FEAT_ENVIRONMENT = 1 << 4,
|
||||
FEAT_LIGHT = 1 << 5,
|
||||
FEAT_DISPLAY = 1 << 6
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t hour; /*!< Hour */
|
||||
uint8_t minute; /*!< Minute */
|
||||
uint8_t second; /*!< Second */
|
||||
uint16_t thousand; /*!< Thousand */
|
||||
} gps_time_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t day; /*!< Day (start from 1) */
|
||||
uint8_t month; /*!< Month (start from 1) */
|
||||
uint16_t year; /*!< Year (start from 2000) */
|
||||
} gps_date_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float latitude; /*!< Latitude (degrees) */
|
||||
float longitude; /*!< Longitude (degrees) */
|
||||
float altitude; /*!< Altitude (meters) */
|
||||
uint8_t sats_in_use; /*!< Number of satellites in use */
|
||||
uint8_t sats_in_view; /*!< Number of satellites in view */
|
||||
float speed; /*!< Ground speed, unit: m/s */
|
||||
gps_date_t date; /*!< Fix date */
|
||||
gps_time_t tim; /*!< time in UTC */
|
||||
} gpssmall_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float angle;
|
||||
float tilt;
|
||||
} orientation_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float temperature;
|
||||
float humidity;
|
||||
float pressure;
|
||||
} environment_t;
|
||||
|
||||
// light is uint16_t
|
||||
|
||||
#endif
|
@ -131,8 +131,13 @@ void I2cDev::got_success() {
|
||||
|
||||
bool I2cDev::i2c_read(uint8_t* reg, uint8_t reg_size, uint8_t* data, uint8_t bytes) {
|
||||
if (bytes == 0) return false;
|
||||
if (reg_size > 0 && reg) i2cbus.transmit(addr, reg, reg_size);
|
||||
bool ret = i2cbus.receive(addr, data, bytes);
|
||||
bool ret = true;
|
||||
if (reg_size > 0 && reg) ret = i2cbus.transmit(addr, reg, reg_size, 150);
|
||||
if (!ret) {
|
||||
got_error();
|
||||
return false;
|
||||
}
|
||||
ret = i2cbus.receive(addr, data, bytes, 150);
|
||||
if (!ret)
|
||||
got_error();
|
||||
else
|
||||
@ -153,7 +158,7 @@ bool I2cDev::i2c_write(uint8_t* reg, uint8_t reg_size, uint8_t* data, uint8_t by
|
||||
// Copy the data into the buffer after the register data
|
||||
memcpy(buffer + reg_size, data, bytes);
|
||||
// Transmit the combined data
|
||||
bool result = i2cbus.transmit(addr, buffer, total_size);
|
||||
bool result = i2cbus.transmit(addr, buffer, total_size, 150);
|
||||
// Clean up the dynamically allocated buffer
|
||||
delete[] buffer;
|
||||
if (!result)
|
||||
@ -304,7 +309,7 @@ msg_t I2CDevManager::timer_fn(void* arg) {
|
||||
force_scan = false;
|
||||
}
|
||||
for (size_t i = 0; i < devlist.size(); i++) {
|
||||
if (devlist[i].addr != 0 && devlist[i].dev) {
|
||||
if (devlist[i].addr != 0 && devlist[i].dev && devlist[i].dev->query_interval != 0) {
|
||||
if ((curr_timer % devlist[i].dev->query_interval) == 0) { // only if it is device's interval
|
||||
devlist[i].dev->update(); // updates it's data, and broadcasts it. if there is any error it will handle in it, and later we can remove it
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user