diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 00000000..0ddd68f5 --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,19 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpjqartfsv" +#include +# 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(); } \ No newline at end of file diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index 7fa2ae53..28a5af1f 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -626,42 +626,56 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { drvBase *drv = nullptr; 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 WS_DEBUG_PRINT("Getting drivers for address: "); WS_DEBUG_PRINTLN(device_descriptor.i2c_device_address); std::vector candidate_drivers = 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) { - WS_DEBUG_PRINT("[i2c] Found a candidate driver: "); + WS_DEBUG_PRINT("[i2c] Attempting to initialize driver: "); WS_DEBUG_PRINTLN(driverName); - } - - // Check/probe each candidate to see if it communicates - for (const char *driverName : candidate_drivers) { drv = CreateI2CDriverByName( driverName, bus, device_descriptor.i2c_device_address, device_descriptor.i2c_mux_channel, device_status); + // Probe the driver to check if it communicates its init. sequence + // properly if (!drv->begin()) { delete drv; drv = nullptr; } else { - WS_DEBUG_PRINT("[i2c] Device initialized: "); + WS_DEBUG_PRINT("[i2c] Driver successfully initialized: "); 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; } } } else { WS_DEBUG_PRINTLN("Device was defined in config file, initializing..."); - // TODO: Add more debug window here - drv = CreateI2CDriverByName( - device_name, bus, device_descriptor.i2c_device_address, - device_descriptor.i2c_mux_channel, device_status); - if (drv == nullptr) { - WS_DEBUG_PRINTLN( - "[i2c] ERROR: I2C driver type not found or unsupported!"); + 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->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()) { WsV2.haltErrorV2("[i2c] Driver failed to initialize!\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); WS_DEBUG_PRINTLN("[i2c] Driver initialized and added to controller: "); WS_DEBUG_PRINTLN(device_name); diff --git a/src/components/i2c/drivers/drvAhtx0.h b/src/components/i2c/drivers/drvAhtx0.h index e0822681..4ecaf211 100644 --- a/src/components/i2c/drivers/drvAhtx0.h +++ b/src/components/i2c/drivers/drvAhtx0.h @@ -112,6 +112,12 @@ protected: NULL; ///< Holds data for the AHTX0's temperature sensor Adafruit_Sensor *_aht_humidity = 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 \ No newline at end of file diff --git a/src/components/i2c/drivers/drvBase.h b/src/components/i2c/drivers/drvBase.h index e1b082a0..ab03194d 100644 --- a/src/components/i2c/drivers/drvBase.h +++ b/src/components/i2c/drivers/drvBase.h @@ -19,7 +19,8 @@ #include #include -#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. */ /*******************************************************************************/ - void EnableSensorReads(wippersnapper_sensor_SensorType *sensor_types, - size_t sensor_types_count) { + void SetSensorTypes(bool use_default_types = false, + 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; for (size_t i = 0; i < _sensors_count; i++) { _sensors[i] = sensor_types[i]; @@ -193,11 +201,10 @@ public: seconds. */ /*******************************************************************************/ - void SetSensorPeriod(float period) { - if (period < 0) { - _sensor_period = 0; - return; - } + void SetPeriod(float period = DEFAULT_SENSOR_PERIOD) { + if (period < 0) + _sensor_period = DEFAULT_SENSOR_PERIOD; + _sensor_period = (unsigned long)(period * 1000.0f); } @@ -219,6 +226,14 @@ public: /*******************************************************************************/ 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. @@ -591,26 +606,6 @@ public: 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 @@ -732,18 +727,18 @@ public: _sensors[15]; ///< Sensors attached to the device. protected: - TwoWire *_i2c; ///< Pointer to the 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 _potential_addresses[2]; ///< Potential I2C addresses for the device, - ///< stored on the device driver - uint32_t _i2c_mux_addr; ///< The I2C MUX address, if applicable. - uint32_t _i2c_mux_channel; ///< The I2C MUX channel, if applicable. - char _name[15]; ///< The device's name. - char _pin_scl[8]; ///< The device's SCL pin. - char _pin_sda[8]; ///< The device's SDA pin. - ulong _sensor_period; ///< The sensor's period, in milliseconds. - ulong _sensor_period_prv; ///< The sensor's previous period, in milliseconds. - size_t _sensors_count; ///< Number of sensors on the device. + TwoWire *_i2c; ///< Pointer to the 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. + uint32_t _i2c_mux_addr; ///< The I2C MUX address, if applicable. + uint32_t _i2c_mux_channel; ///< The I2C MUX channel, if applicable. + char _name[15]; ///< The device's name. + char _pin_scl[8]; ///< The device's SCL pin. + char _pin_sda[8]; ///< The device's SDA pin. + ulong _sensor_period; ///< The sensor's period, in milliseconds. + ulong _sensor_period_prv; ///< The sensor's previous period, in milliseconds. + size_t _sensors_count; ///< Number of sensors on the device. + wippersnapper_sensor_SensorType + _default_sensor_types[1]; ///< Default sensor types }; #endif // DRV_BASE_H \ No newline at end of file diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index d9ce8d68..fd6d6d25 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -473,8 +473,104 @@ bool Wippersnapper_FS::AddSDCSPinToFileConfig(uint8_t pin) { 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(); + 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(); + 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. diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.h b/src/provisioning/tinyusb/Wippersnapper_FS.h index 891199e9..62a02294 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.h +++ b/src/provisioning/tinyusb/Wippersnapper_FS.h @@ -64,9 +64,9 @@ public: #endif // config.json void CreateFileConfig(); - bool AddSDCSPinToFileConfig(uint8_t pin); void GetPinSDCS(); - bool AddI2CDeviceToConfig(uint32_t address); + bool AddSDCSPinToFileConfig(uint8_t pin); + bool AddI2cDeviceToFileConfig(uint32_t address, float period, char *driver_name); private: bool _is_secrets_file_empty = false;