Associate driver with address, writeback to file
This commit is contained in:
parent
b7784dfe49
commit
f13a706d93
6 changed files with 189 additions and 88 deletions
19
src/Wippersnapper_demo.ino.cpp
Normal file
19
src/Wippersnapper_demo.ino.cpp
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpjqartfsv"
|
||||||
|
#include <Arduino.h>
|
||||||
|
# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino"
|
||||||
|
# 11 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino"
|
||||||
|
#include "ws_adapters.h"
|
||||||
|
|
||||||
|
|
||||||
|
ws_adapter_offline wipper;
|
||||||
|
#define WS_DEBUG
|
||||||
|
void setup();
|
||||||
|
void loop();
|
||||||
|
#line 17 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino"
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
wipper.provision();
|
||||||
|
wipper.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() { wipper.run(); }
|
||||||
|
|
@ -626,42 +626,56 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) {
|
||||||
|
|
||||||
drvBase *drv = nullptr;
|
drvBase *drv = nullptr;
|
||||||
if (strcmp(device_name, SCAN_DEVICE) == 0) {
|
if (strcmp(device_name, SCAN_DEVICE) == 0) {
|
||||||
|
WS_DEBUG_PRINTLN("Attempting to autoconfig device found in scan...");
|
||||||
// Get all possible driver candidates for this address
|
// Get all possible driver candidates for this address
|
||||||
WS_DEBUG_PRINT("Getting drivers for address: ");
|
WS_DEBUG_PRINT("Getting drivers for address: ");
|
||||||
WS_DEBUG_PRINTLN(device_descriptor.i2c_device_address);
|
WS_DEBUG_PRINTLN(device_descriptor.i2c_device_address);
|
||||||
std::vector<const char *> candidate_drivers =
|
std::vector<const char *> candidate_drivers =
|
||||||
getDriversForAddress(device_descriptor.i2c_device_address);
|
getDriversForAddress(device_descriptor.i2c_device_address);
|
||||||
|
|
||||||
// Print out all the candidates
|
// Probe each candidate to see if it communicates
|
||||||
for (const char *driverName : candidate_drivers) {
|
for (const char *driverName : candidate_drivers) {
|
||||||
WS_DEBUG_PRINT("[i2c] Found a candidate driver: ");
|
WS_DEBUG_PRINT("[i2c] Attempting to initialize driver: ");
|
||||||
WS_DEBUG_PRINTLN(driverName);
|
WS_DEBUG_PRINTLN(driverName);
|
||||||
}
|
|
||||||
|
|
||||||
// Check/probe each candidate to see if it communicates
|
|
||||||
for (const char *driverName : candidate_drivers) {
|
|
||||||
drv = CreateI2CDriverByName(
|
drv = CreateI2CDriverByName(
|
||||||
driverName, bus, device_descriptor.i2c_device_address,
|
driverName, bus, device_descriptor.i2c_device_address,
|
||||||
device_descriptor.i2c_mux_channel, device_status);
|
device_descriptor.i2c_mux_channel, device_status);
|
||||||
|
// Probe the driver to check if it communicates its init. sequence
|
||||||
|
// properly
|
||||||
if (!drv->begin()) {
|
if (!drv->begin()) {
|
||||||
delete drv;
|
delete drv;
|
||||||
drv = nullptr;
|
drv = nullptr;
|
||||||
} else {
|
} else {
|
||||||
WS_DEBUG_PRINT("[i2c] Device initialized: ");
|
WS_DEBUG_PRINT("[i2c] Driver successfully initialized: ");
|
||||||
WS_DEBUG_PRINTLN(driverName);
|
WS_DEBUG_PRINTLN(driverName);
|
||||||
// TOdO: NOTE THAT WE MAY DOUBLE_INIT BELOW!!! AND CRASH
|
drv->SetSensorTypes(true);
|
||||||
|
drv->SetPeriod(0);
|
||||||
|
// TODO: Add driver information to FS
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS_DEBUG_PRINTLN("Device was defined in config file, initializing...");
|
WS_DEBUG_PRINTLN("Device was defined in config file, initializing...");
|
||||||
// TODO: Add more debug window here
|
if (did_set_mux_ch) {
|
||||||
drv = CreateI2CDriverByName(
|
drv->SetMuxAddress(device_descriptor.i2c_mux_address);
|
||||||
device_name, bus, device_descriptor.i2c_device_address,
|
WS_DEBUG_PRINTLN("[i2c] Set driver to use MUX");
|
||||||
device_descriptor.i2c_mux_channel, device_status);
|
}
|
||||||
if (drv == nullptr) {
|
if (use_alt_bus) {
|
||||||
WS_DEBUG_PRINTLN(
|
drv->EnableAltI2CBus(_i2c_model->GetI2cDeviceAddOrReplaceMsg()
|
||||||
"[i2c] ERROR: I2C driver type not found or unsupported!");
|
->i2c_device_description.i2c_bus_scl,
|
||||||
|
_i2c_model->GetI2cDeviceAddOrReplaceMsg()
|
||||||
|
->i2c_device_description.i2c_bus_sda);
|
||||||
|
WS_DEBUG_PRINTLN("[i2c] Set driver to use Alt I2C bus");
|
||||||
|
}
|
||||||
|
// Configure the driver
|
||||||
|
drv->SetSensorTypes(
|
||||||
|
false,
|
||||||
|
_i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_sensor_types,
|
||||||
|
_i2c_model->GetI2cDeviceAddOrReplaceMsg()
|
||||||
|
->i2c_device_sensor_types_count);
|
||||||
|
drv->SetPeriod(
|
||||||
|
_i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_period);
|
||||||
|
if (!drv->begin()) {
|
||||||
if (WsV2._sdCardV2->isModeOffline()) {
|
if (WsV2._sdCardV2->isModeOffline()) {
|
||||||
WsV2.haltErrorV2("[i2c] Driver failed to initialize!\n\tDid you set "
|
WsV2.haltErrorV2("[i2c] Driver failed to initialize!\n\tDid you set "
|
||||||
"the correct value for i2cDeviceName?\n\tDid you set "
|
"the correct value for i2cDeviceName?\n\tDid you set "
|
||||||
|
|
@ -671,35 +685,6 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to initialize the driver
|
|
||||||
if (did_set_mux_ch) {
|
|
||||||
drv->SetMuxAddress(device_descriptor.i2c_mux_address);
|
|
||||||
WS_DEBUG_PRINTLN("[i2c] Set driver to use MUX");
|
|
||||||
}
|
|
||||||
if (use_alt_bus) {
|
|
||||||
drv->EnableAltI2CBus(_i2c_model->GetI2cDeviceAddOrReplaceMsg()
|
|
||||||
->i2c_device_description.i2c_bus_scl,
|
|
||||||
_i2c_model->GetI2cDeviceAddOrReplaceMsg()
|
|
||||||
->i2c_device_description.i2c_bus_sda);
|
|
||||||
WS_DEBUG_PRINTLN("[i2c] Set driver to use Alt I2C bus");
|
|
||||||
}
|
|
||||||
// Configure the driver
|
|
||||||
drv->EnableSensorReads(
|
|
||||||
_i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_sensor_types,
|
|
||||||
_i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_sensor_types_count);
|
|
||||||
drv->SetSensorPeriod(
|
|
||||||
_i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_period);
|
|
||||||
if (!drv->begin()) {
|
|
||||||
if (WsV2._sdCardV2->isModeOffline()) {
|
|
||||||
WsV2.haltErrorV2("[i2c] Driver failed to initialize!\n\tDid you set "
|
|
||||||
"the correct value for i2cDeviceName?\n\tDid you set "
|
|
||||||
"the correct value for"
|
|
||||||
"i2cDeviceAddress?",
|
|
||||||
WS_LED_STATUS_ERROR_RUNTIME, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_i2c_drivers.push_back(drv);
|
_i2c_drivers.push_back(drv);
|
||||||
WS_DEBUG_PRINTLN("[i2c] Driver initialized and added to controller: ");
|
WS_DEBUG_PRINTLN("[i2c] Driver initialized and added to controller: ");
|
||||||
WS_DEBUG_PRINTLN(device_name);
|
WS_DEBUG_PRINTLN(device_name);
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,12 @@ protected:
|
||||||
NULL; ///< Holds data for the AHTX0's temperature sensor
|
NULL; ///< Holds data for the AHTX0's temperature sensor
|
||||||
Adafruit_Sensor *_aht_humidity =
|
Adafruit_Sensor *_aht_humidity =
|
||||||
NULL; ///< Holds data for the AHTX0's humidity sensor
|
NULL; ///< Holds data for the AHTX0's humidity sensor
|
||||||
|
wippersnapper_sensor_SensorType _default_sensor_types[3] = {
|
||||||
|
wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE,
|
||||||
|
wippersnapper_sensor_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT,
|
||||||
|
wippersnapper_sensor_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY}; ///< Default
|
||||||
|
///< sensor
|
||||||
|
///< types
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // drvAhtx0
|
#endif // drvAhtx0
|
||||||
|
|
@ -19,7 +19,8 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <protos/i2c.pb.h>
|
#include <protos/i2c.pb.h>
|
||||||
|
|
||||||
#define NO_MUX_CH 0xFFFF; ///< No MUX channel specified
|
#define NO_MUX_CH 0xFFFF; ///< No MUX channel specified
|
||||||
|
#define DEFAULT_SENSOR_PERIOD 30.0 ///< Default sensor period, in seconds
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -161,8 +162,15 @@ public:
|
||||||
The number of active sensors to read from the device.
|
The number of active sensors to read from the device.
|
||||||
*/
|
*/
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
void EnableSensorReads(wippersnapper_sensor_SensorType *sensor_types,
|
void SetSensorTypes(bool use_default_types = false,
|
||||||
size_t sensor_types_count) {
|
wippersnapper_sensor_SensorType *sensor_types = nullptr,
|
||||||
|
size_t sensor_types_count = 0) {
|
||||||
|
if (use_default_types) {
|
||||||
|
sensor_types = _default_sensor_types;
|
||||||
|
// set sensor_types_count to # of elements within _default_sensor_types
|
||||||
|
sensor_types_count =
|
||||||
|
sizeof(_default_sensor_types) / sizeof(_default_sensor_types[0]);
|
||||||
|
}
|
||||||
_sensors_count = sensor_types_count;
|
_sensors_count = sensor_types_count;
|
||||||
for (size_t i = 0; i < _sensors_count; i++) {
|
for (size_t i = 0; i < _sensors_count; i++) {
|
||||||
_sensors[i] = sensor_types[i];
|
_sensors[i] = sensor_types[i];
|
||||||
|
|
@ -193,11 +201,10 @@ public:
|
||||||
seconds.
|
seconds.
|
||||||
*/
|
*/
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
void SetSensorPeriod(float period) {
|
void SetPeriod(float period = DEFAULT_SENSOR_PERIOD) {
|
||||||
if (period < 0) {
|
if (period < 0)
|
||||||
_sensor_period = 0;
|
_sensor_period = DEFAULT_SENSOR_PERIOD;
|
||||||
return;
|
|
||||||
}
|
|
||||||
_sensor_period = (unsigned long)(period * 1000.0f);
|
_sensor_period = (unsigned long)(period * 1000.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,6 +226,14 @@ public:
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
ulong GetSensorPeriod() { return _sensor_period; }
|
ulong GetSensorPeriod() { return _sensor_period; }
|
||||||
|
|
||||||
|
/*******************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Gets the sensor's types
|
||||||
|
@returns A pointer to an array of SensorTypes.
|
||||||
|
*/
|
||||||
|
/*******************************************************************************/
|
||||||
|
wippersnapper_sensor_SensorType *GetSensorTypes() { return _sensors; }
|
||||||
|
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Gets the sensor's previous period.
|
@brief Gets the sensor's previous period.
|
||||||
|
|
@ -591,26 +606,6 @@ public:
|
||||||
return it->second(sensors_event);
|
return it->second(sensors_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************/
|
|
||||||
/*!
|
|
||||||
@brief Checks if an address found during an i2c scan belongs to the
|
|
||||||
sensor.
|
|
||||||
@param scan_address
|
|
||||||
The desired address to check, from an i2c scan
|
|
||||||
@returns True if the address belongs to the sensor, False otherwise
|
|
||||||
*/
|
|
||||||
/*******************************************************************************/
|
|
||||||
bool IsPotentialAddress(uint16_t scan_address) {
|
|
||||||
for (uint8_t i = 0;
|
|
||||||
i < sizeof(_potential_addresses) / sizeof(_potential_addresses[0]);
|
|
||||||
i++) {
|
|
||||||
if (scan_address == _potential_addresses[i]) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false; // nothing found
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************************************/
|
/*******************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Function type for sensor event handlers
|
@brief Function type for sensor event handlers
|
||||||
|
|
@ -732,18 +727,18 @@ public:
|
||||||
_sensors[15]; ///< Sensors attached to the device.
|
_sensors[15]; ///< Sensors attached to the device.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TwoWire *_i2c; ///< Pointer to the I2C bus
|
TwoWire *_i2c; ///< Pointer to the I2C bus
|
||||||
bool _has_alt_i2c_bus; ///< True if the device is on an alternate I2C bus
|
bool _has_alt_i2c_bus; ///< True if the device is on an alternate I2C bus
|
||||||
uint16_t _address; ///< The device's I2C address.
|
uint16_t _address; ///< The device's I2C address.
|
||||||
uint16_t _potential_addresses[2]; ///< Potential I2C addresses for the device,
|
uint32_t _i2c_mux_addr; ///< The I2C MUX address, if applicable.
|
||||||
///< stored on the device driver
|
uint32_t _i2c_mux_channel; ///< The I2C MUX channel, if applicable.
|
||||||
uint32_t _i2c_mux_addr; ///< The I2C MUX address, if applicable.
|
char _name[15]; ///< The device's name.
|
||||||
uint32_t _i2c_mux_channel; ///< The I2C MUX channel, if applicable.
|
char _pin_scl[8]; ///< The device's SCL pin.
|
||||||
char _name[15]; ///< The device's name.
|
char _pin_sda[8]; ///< The device's SDA pin.
|
||||||
char _pin_scl[8]; ///< The device's SCL pin.
|
ulong _sensor_period; ///< The sensor's period, in milliseconds.
|
||||||
char _pin_sda[8]; ///< The device's SDA pin.
|
ulong _sensor_period_prv; ///< The sensor's previous period, in milliseconds.
|
||||||
ulong _sensor_period; ///< The sensor's period, in milliseconds.
|
size_t _sensors_count; ///< Number of sensors on the device.
|
||||||
ulong _sensor_period_prv; ///< The sensor's previous period, in milliseconds.
|
wippersnapper_sensor_SensorType
|
||||||
size_t _sensors_count; ///< Number of sensors on the device.
|
_default_sensor_types[1]; ///< Default sensor types
|
||||||
};
|
};
|
||||||
#endif // DRV_BASE_H
|
#endif // DRV_BASE_H
|
||||||
|
|
@ -473,8 +473,104 @@ bool Wippersnapper_FS::AddSDCSPinToFileConfig(uint8_t pin) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wippersnapper_FS::AddI2CDeviceToConfig(uint32_t address) { return true; }
|
// TODO: Add an inclusion for "i2cDeviceSensorTypes"
|
||||||
|
/********************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Adds an I2C device to the `config.json` file.
|
||||||
|
@param address
|
||||||
|
The I2C device's address.
|
||||||
|
@param period
|
||||||
|
The period at which the device should be polled.
|
||||||
|
@param driver_name
|
||||||
|
The name of the driver.
|
||||||
|
@returns True if the device was successfully added, False otherwise.
|
||||||
|
*/
|
||||||
|
/********************************************************************************/
|
||||||
|
bool Wippersnapper_FS::AddI2cDeviceToFileConfig(uint32_t address, float period,
|
||||||
|
char *driver_name) {
|
||||||
|
if (!wipperFatFs_v2.exists("/config.json")) {
|
||||||
|
HaltFilesystem("ERROR: Could not find expected config.json file on the "
|
||||||
|
"WIPPER volume!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
File32 file_cfg = wipperFatFs_v2.open("/config.json", FILE_READ);
|
||||||
|
if (!file_cfg) {
|
||||||
|
WS_DEBUG_PRINTLN("ERROR: Could not open the config.json file for reading!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the JSON document
|
||||||
|
JsonDocument doc;
|
||||||
|
DeserializationError error = deserializeJson(doc, file_cfg);
|
||||||
|
file_cfg.close();
|
||||||
|
if (error) {
|
||||||
|
WS_DEBUG_PRINT("JSON parse error: ");
|
||||||
|
WS_DEBUG_PRINTLN(error.c_str());
|
||||||
|
WS_DEBUG_PRINTLN(
|
||||||
|
"ERROR: Unable to parse config.json file - deserializeJson() failed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject new_component = doc["components"].add<JsonObject>();
|
||||||
|
new_component["name"] = driver_name;
|
||||||
|
new_component["componentAPI"] = "i2c";
|
||||||
|
new_component["i2cdevicei2cDeviceName"] = driver_name;
|
||||||
|
new_component["period"] = period;
|
||||||
|
// convert address to string
|
||||||
|
char address_str[10];
|
||||||
|
sprintf(address_str, "0x%02X", address);
|
||||||
|
new_component["i2cDeviceAddress"] = address_str;
|
||||||
|
|
||||||
|
// Handle the sensor types
|
||||||
|
// TODO: This is un-implemented because I'm unsure how to go from type->string
|
||||||
|
// representation without adding significant overhead...
|
||||||
|
/*
|
||||||
|
JsonArray new_component_types =
|
||||||
|
new_component["i2cDeviceSensorTypes"].to<JsonArray>();
|
||||||
|
new_component_types[0]["type"] = "relative-humidity";
|
||||||
|
new_component_types[1]["type"] = "ambient-temp";
|
||||||
|
new_component_types[2]["type"] = "ambient-temp-fahrenheit";
|
||||||
|
new_component_types[3]["type"] = "pressure";
|
||||||
|
new_component_types[4]["type"] = "altitude";
|
||||||
|
*/
|
||||||
|
|
||||||
|
doc.shrinkToFit();
|
||||||
|
|
||||||
|
// Remove the existing config.json file
|
||||||
|
wipperFatFs_v2.remove("/config.json");
|
||||||
|
flash_v2.syncBlocks();
|
||||||
|
wipperFatFs_v2.cacheClear();
|
||||||
|
|
||||||
|
// Write the updated doc back to new config.json file
|
||||||
|
file_cfg = wipperFatFs_v2.open("/config.json", FILE_WRITE);
|
||||||
|
if (!file_cfg) {
|
||||||
|
HaltFilesystem("ERROR: Could not open the config.json file for writing!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
serializeJsonPretty(doc, file_cfg);
|
||||||
|
|
||||||
|
// Flush and sync file
|
||||||
|
// TODO: Not sure if this is actually doing anything on RP2040, need to test
|
||||||
|
// in isolation
|
||||||
|
file_cfg.flush();
|
||||||
|
flash_v2.syncBlocks();
|
||||||
|
file_cfg.close();
|
||||||
|
|
||||||
|
// Force cache clear and sync
|
||||||
|
// TODO: Not sure if this is actually doing anything on RP2040, need to test
|
||||||
|
// in isolation
|
||||||
|
flash_v2.syncBlocks();
|
||||||
|
wipperFatFs_v2.cacheClear();
|
||||||
|
refreshMassStorage();
|
||||||
|
|
||||||
|
TinyUSBDevice.detach();
|
||||||
|
delay(150);
|
||||||
|
TinyUSBDevice.attach();
|
||||||
|
delay(1500);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@brief Checks if secrets.json file exists on the flash filesystem.
|
@brief Checks if secrets.json file exists on the flash filesystem.
|
||||||
|
|
|
||||||
|
|
@ -64,9 +64,9 @@ public:
|
||||||
#endif
|
#endif
|
||||||
// config.json
|
// config.json
|
||||||
void CreateFileConfig();
|
void CreateFileConfig();
|
||||||
bool AddSDCSPinToFileConfig(uint8_t pin);
|
|
||||||
void GetPinSDCS();
|
void GetPinSDCS();
|
||||||
bool AddI2CDeviceToConfig(uint32_t address);
|
bool AddSDCSPinToFileConfig(uint8_t pin);
|
||||||
|
bool AddI2cDeviceToFileConfig(uint32_t address, float period, char *driver_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _is_secrets_file_empty = false;
|
bool _is_secrets_file_empty = false;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue