Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I2cDev_PPmod periodic sensor query #2315

Merged
merged 4 commits into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions firmware/application/ui_navigation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>()},
Expand Down
94 changes: 92 additions & 2 deletions firmware/common/i2cdev_ppmod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

#include "i2cdev_ppmod.hpp"
#include "portapack.hpp"

#include <optional>

namespace i2cdev {
Expand All @@ -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() {
Expand All @@ -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;
}

Expand All @@ -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;
}
Expand Down
24 changes: 20 additions & 4 deletions firmware/common/i2cdev_ppmod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "standalone_app.hpp"
#include "i2cdevmanager.hpp"

#include "i2cdev_ppmod_helper.hpp"

namespace i2cdev {

class I2cDev_PPmod : public I2cDev {
Expand All @@ -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 {
Expand All @@ -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 */
Expand Down
59 changes: 59 additions & 0 deletions firmware/common/i2cdev_ppmod_helper.hpp
Original file line number Diff line number Diff line change
@@ -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
13 changes: 9 additions & 4 deletions firmware/common/i2cdevmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
}
Expand Down
Loading