diff --git a/library.properties b/library.properties index d6840cbca..928523754 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=SdFat - Adafruit Fork, Adafruit SPIFlash, Adafruit NeoPixel, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, RTClib, StreamUtils, Adafruit SHT4x Library +depends=SdFat - Adafruit Fork, Adafruit SPIFlash, Adafruit NeoPixel, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, RTClib, StreamUtils, Adafruit SHT4x Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal diff --git a/platformio.ini b/platformio.ini index ad5932606..fc6394b8c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -78,6 +78,9 @@ lib_deps = adafruit/Adafruit STMPE610 adafruit/Adafruit TouchScreen adafruit/Adafruit MQTT Library + adafruit/Adafruit LED Backpack Library + adafruit/Adafruit LiquidCrystal + adafruit/Adafruit SSD1306 https://github.com/adafruit/Adafruit_SHT4X.git bblanchon/ArduinoJson https://github.com/adafruit/SdFat.git diff --git a/src/Wippersnapper_V2.cpp b/src/Wippersnapper_V2.cpp index 209f7464f..897132427 100644 --- a/src/Wippersnapper_V2.cpp +++ b/src/Wippersnapper_V2.cpp @@ -401,6 +401,12 @@ bool cbDecodeBrokerToDevice(pb_istream_t *stream, const pb_field_t *field, return false; } break; + case wippersnapper_signal_BrokerToDevice_i2c_device_output_write_tag: + WS_DEBUG_PRINTLN("-> I2C Device Output Write Message Type"); + if (!WsV2._i2c_controller->Handle_I2cDeviceOutputWrite(stream)) { + return false; + } + break; case wippersnapper_signal_BrokerToDevice_pixels_add_tag: WS_DEBUG_PRINTLN("-> Pixels Add Message Type"); if (!WsV2._pixels_controller->Handle_Pixels_Add(stream)) { diff --git a/src/components/i2c/controller.cpp b/src/components/i2c/controller.cpp index e14344d91..e47a22a42 100644 --- a/src/components/i2c/controller.cpp +++ b/src/components/i2c/controller.cpp @@ -13,8 +13,9 @@ * */ #include "controller.h" +#include "drivers/drvBase.h" +#include "drivers/drvOutputBase.h" -/*******************************************************************************/ /*! @brief Lambda function to create a drvBase driver instance @param i2c @@ -26,13 +27,12 @@ @param driver_name The i2c driver's name. */ -/*******************************************************************************/ -using FnCreateI2CDriver = +using FnCreateI2CSensorDriver = std::function; -// Factory for creating a new I2C drivers -// NOTE: When you add a new driver, make sure to add it to the factory! -static const std::map I2cFactory = { +// Factory for creating a new I2C SENSOR drivers +// NOTE: When you add a new SENSOR driver, make sure to add it to the factory! +static const std::map I2cFactorySensor = { {"bme280", [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, const char *driver_name) -> drvBase * { @@ -344,7 +344,44 @@ static const std::map I2cFactory = { return new drvVl6180x(i2c, addr, mux_channel, driver_name); }}}; ///< I2C driver factory -/***********************************************************************/ +/*! + @brief Lambda function to create a drvOutputBase instance + @param i2c + The desired I2C interface. + @param addr + The desired i2c device address. + @param mux_channel + The desired I2C multiplexer channel. + @param driver_name + The i2c output driver's name. +*/ +using FnCreateI2cOutputDrv = + std::function; + +// Factory for creating a new i2c OUTPUT driver +// NOTE: When adding a new OUTPUT driver, make sure to add it to the map below! +static const std::map I2cFactoryOutput = { + {"quadalphanum", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvOutputBase * { + return new drvOutQuadAlphaNum(i2c, addr, mux_channel, driver_name); + }}, + {"7seg", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvOutputBase * { + return new drvOut7Seg(i2c, addr, mux_channel, driver_name); + }}, + {"charlcd", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvOutputBase * { + return new drvOutCharLcd(i2c, addr, mux_channel, driver_name); + }}, + {"ssd1306", + [](TwoWire *i2c, uint16_t addr, uint32_t mux_channel, + const char *driver_name) -> drvOutputBase * { + return new drvOutSsd1306(i2c, addr, mux_channel, driver_name); + }}}; ///< I2C output driver factory + /*! @brief Creates an I2C driver by name @param driver_name @@ -359,12 +396,39 @@ static const std::map I2cFactory = { The I2cDeviceStatus message. @returns A pointer to the I2C driver. */ -/***********************************************************************/ -drvBase *CreateI2CDriverByName(const char *driver_name, TwoWire *i2c, - uint16_t addr, uint32_t i2c_mux_channel, - wippersnapper_i2c_I2cDeviceStatus &status) { - auto it = I2cFactory.find(driver_name); - if (it == I2cFactory.end()) { +drvBase *CreateI2cSensorDrv(const char *driver_name, TwoWire *i2c, + uint16_t addr, uint32_t i2c_mux_channel, + wippersnapper_i2c_I2cDeviceStatus &status) { + auto it = I2cFactorySensor.find(driver_name); + if (it == I2cFactorySensor.end()) { + status = + wippersnapper_i2c_I2cDeviceStatus_I2C_DEVICE_STATUS_FAIL_UNSUPPORTED_SENSOR; + return nullptr; + } + + status = wippersnapper_i2c_I2cDeviceStatus_I2C_DEVICE_STATUS_SUCCESS; + return it->second(i2c, addr, i2c_mux_channel, driver_name); +} + +/*! + @brief Creates an I2C driver by name + @param driver_name + The name of the I2C driver. + @param i2c + The I2C bus. + @param addr + The I2C device address. + @param i2c_mux_channel + The I2C MUX channel. + @param status + The I2cDeviceStatus message. + @returns A pointer to the I2C driver. +*/ +drvOutputBase *CreateI2cOutputDrv(const char *driver_name, TwoWire *i2c, + uint16_t addr, uint32_t i2c_mux_channel, + wippersnapper_i2c_I2cDeviceStatus &status) { + auto it = I2cFactoryOutput.find(driver_name); + if (it == I2cFactoryOutput.end()) { status = wippersnapper_i2c_I2cDeviceStatus_I2C_DEVICE_STATUS_FAIL_UNSUPPORTED_SENSOR; return nullptr; @@ -380,8 +444,8 @@ drvBase *CreateI2CDriverByName(const char *driver_name, TwoWire *i2c, */ /***********************************************************************/ I2cController::I2cController() { - _i2c_bus_alt = nullptr; _i2c_model = new I2cModel(); + _i2c_output_model = new I2cOutputModel(); _i2c_bus_default = new I2cHardware(); } @@ -394,6 +458,9 @@ I2cController::~I2cController() { if (_i2c_model) delete _i2c_model; + if (_i2c_output_model) + delete _i2c_output_model; + if (_i2c_bus_default) delete _i2c_bus_default; } @@ -403,24 +470,50 @@ I2cController::~I2cController() { @brief Removes an I2C driver from the controller and frees memory @param address The desired I2C device's address. + @param is_output_device + True if the driver is an output device, False otherwise. @returns True if the driver was removed, False otherwise. */ /***********************************************************************/ -bool I2cController::RemoveDriver(uint32_t address) { - for (drvBase *driver : _i2c_drivers) { - if (driver == nullptr) - continue; +bool I2cController::RemoveDriver(uint32_t address, bool is_output_device) { + if (!is_output_device) { + // Safely remove the i2c sensor driver from the vector and free memory + for (drvBase *driver : _i2c_drivers) { + if (driver == nullptr) + continue; - if (driver->GetAddress() != address) - continue; + if (driver->GetAddress() != address) + continue; - auto it = std::find(_i2c_drivers.begin(), _i2c_drivers.end(), driver); - if (it != _i2c_drivers.end()) { - _i2c_drivers.erase(it); + auto it = std::find(_i2c_drivers.begin(), _i2c_drivers.end(), driver); + if (it != _i2c_drivers.end()) { + _i2c_drivers.erase(it); + } + delete driver; + return true; + } + } else { + // This was an output driver type, safely remove the i2c output driver from + // the vector and free memory + for (drvOutputBase *driver : _i2c_drivers_output) { + if (driver == nullptr) + continue; + + if (driver->GetAddress() != address) + continue; + + auto it = std::find(_i2c_drivers_output.begin(), + _i2c_drivers_output.end(), driver); + if (it != _i2c_drivers_output.end()) { + _i2c_drivers_output.erase(it); + } + delete driver; + return true; } - delete driver; - return true; } + + // We didn't find the driver to remove + WS_DEBUG_PRINTLN("[i2c] ERROR: Unable to find driver to remove!"); return false; } @@ -515,8 +608,8 @@ bool I2cController::Handle_I2cDeviceRemove(pb_istream_t *stream) { strlen(msgRemove->i2c_device_description.i2c_bus_sda) == 0) { WS_DEBUG_PRINTLN("[i2c] Removing device from default bus..."); if (!_i2c_bus_default->HasMux()) { - // TODO: Implement remove, straightforward - if (!RemoveDriver(msgRemove->i2c_device_description.i2c_device_address)) { + if (!RemoveDriver(msgRemove->i2c_device_description.i2c_device_address, + msgRemove->is_output_device)) { WS_DEBUG_PRINTLN( "[i2c] ERROR: Failed to remove i2c device from default bus!"); did_remove = false; @@ -526,11 +619,10 @@ bool I2cController::Handle_I2cDeviceRemove(pb_istream_t *stream) { // Case 1: Is the I2C device connected to a MUX? if (msgRemove->i2c_device_description.i2c_mux_address != 0xFFFF && msgRemove->i2c_device_description.i2c_mux_channel >= 0) { - // TODO: Remove the device from the mux's channel and delete the driver _i2c_bus_default->SelectMuxChannel( msgRemove->i2c_device_description.i2c_mux_channel); - if (!RemoveDriver( - msgRemove->i2c_device_description.i2c_device_address)) { + if (!RemoveDriver(msgRemove->i2c_device_description.i2c_device_address, + msgRemove->is_output_device)) { WS_DEBUG_PRINTLN( "[i2c] ERROR: Failed to remove i2c device from default bus!"); did_remove = false; @@ -539,22 +631,14 @@ bool I2cController::Handle_I2cDeviceRemove(pb_istream_t *stream) { // Case 2: Is the I2C device a MUX? if (msgRemove->i2c_device_description.i2c_device_address == msgRemove->i2c_device_description.i2c_mux_address) { - // TODO: Scan the mux to see what drivers are attached? wippersnapper_i2c_I2cBusScanned scan_results; _i2c_bus_default->ScanMux(&scan_results); - // DEBUG - TODO REMOVE - Print out the scan results for (int i = 0; i < scan_results.i2c_bus_found_devices_count; i++) { - WS_DEBUG_PRINT("[i2c] Found device at address: "); - WS_DEBUG_PRINT( - scan_results.i2c_bus_found_devices[i].i2c_device_address, HEX); - WS_DEBUG_PRINT(" on mux channel #: "); - WS_DEBUG_PRINTLN( - scan_results.i2c_bus_found_devices[i].i2c_mux_channel); // Select the channel and remove the device _i2c_bus_default->SelectMuxChannel( scan_results.i2c_bus_found_devices[i].i2c_mux_channel); - RemoveDriver( - scan_results.i2c_bus_found_devices[i].i2c_device_address); + RemoveDriver(scan_results.i2c_bus_found_devices[i].i2c_device_address, + msgRemove->is_output_device); } _i2c_bus_default->RemoveMux(); } @@ -707,6 +791,80 @@ bool I2cController::Handle_I2cBusScan(pb_istream_t *stream) { return true; } +/*! + @brief Handler for an I2cDeviceOutputWrite message + @param stream + A pointer to the pb_istream_t stream. + @returns True if the callback was successfully executed by the driver, + False otherwise. +*/ +bool I2cController::Handle_I2cDeviceOutputWrite(pb_istream_t *stream) { + WS_DEBUG_PRINTLN("[i2c] Decoding I2cDeviceOutputWrite message..."); + // Attempt to decode an I2cDeviceOutputWrite message + if (!_i2c_model->DecodeI2cDeviceOutputWrite(stream)) { + WS_DEBUG_PRINTLN("[i2c] ERROR: Unable to decode I2cDeviceOutputWrite " + "message!"); + return false; + } + wippersnapper_i2c_I2cDeviceDescriptor descriptor = + _i2c_model->GetI2cDeviceOutputWriteMsg()->i2c_device_description; + + // Attempt to find the driver + drvOutputBase *driver = nullptr; + for (auto *drv : _i2c_drivers_output) { + if (drv == nullptr) + continue; + + if (drv->GetAddress() != descriptor.i2c_device_address) + continue; + + driver = drv; + break; + } + + if (driver == nullptr) { + WS_DEBUG_PRINT("[i2c] ERROR: Unable to find driver for device at addr 0x"); + WS_DEBUG_PRINTLN(descriptor.i2c_device_address, HEX); + return false; + } + + // Optionally configure the I2C MUX + uint32_t mux_channel = driver->GetMuxChannel(); + WS_DEBUG_PRINTLN(mux_channel); + if (driver->HasMux()) { + ConfigureMuxChannel(mux_channel, driver->HasAltI2CBus()); + } + + // Determine which driver cb function to use + if (_i2c_model->GetI2cDeviceOutputWriteMsg()->which_output_msg == + wippersnapper_i2c_I2cDeviceOutputWrite_write_led_backpack_tag) { + WS_DEBUG_PRINTLN("[i2c] Writing to LED backpack..."); + driver->WriteMessage(_i2c_model->GetI2cDeviceOutputWriteMsg() + ->output_msg.write_led_backpack.message); + } else if (_i2c_model->GetI2cDeviceOutputWriteMsg()->which_output_msg == + wippersnapper_i2c_I2cDeviceOutputWrite_write_char_lcd_tag) { + WS_DEBUG_PRINTLN("[i2c] Writing to char LCD..."); + if (!driver->WriteMessageCharLCD(&_i2c_model->GetI2cDeviceOutputWriteMsg() + ->output_msg.write_char_lcd)) { + WS_DEBUG_PRINTLN("[i2c] ERROR: Unable to write to char LCD!"); + return false; + } + } else if (_i2c_model->GetI2cDeviceOutputWriteMsg()->which_output_msg == + wippersnapper_i2c_I2cDeviceOutputWrite_write_oled_tag) { + WS_DEBUG_PRINTLN("[i2c] Writing to SSD1306 OLED..."); + // Note: In the future, we can expand this to support other OLEDs by + // creating and checking a tag within the write oled msg (e.g. SSD1327, + // etc.) + driver->WriteMessageSSD1306(_i2c_model->GetI2cDeviceOutputWriteMsg() + ->output_msg.write_oled.message); + } else { + WS_DEBUG_PRINTLN("[i2c] ERROR: Unable to determine I2C Output Write type!"); + return false; + } + + return true; +} + /***********************************************************************/ /*! @brief Implements handling for a I2cDeviceAddOrReplace message @@ -736,6 +894,9 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { wippersnapper_i2c_I2cDeviceDescriptor device_descriptor = _i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_description; + // Is this an i2c output device? + bool is_output = _i2c_model->GetI2cDeviceAddOrReplaceMsg()->is_output; + // TODO [Online]: Handle Replace messages by implementing the Remove handler // first...then proceed to adding a new device @@ -803,10 +964,29 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { bus = _i2c_bus_default->GetBus(); } - drvBase *drv = CreateI2CDriverByName( - device_name, bus, device_descriptor.i2c_device_address, - device_descriptor.i2c_mux_channel, device_status); - if (drv == nullptr) { + // Attempt to create the driver + bool did_init = false; + drvBase *drv = nullptr; + drvOutputBase *drv_out = nullptr; + if (!is_output) { + drv = CreateI2cSensorDrv(device_name, bus, + device_descriptor.i2c_device_address, + device_descriptor.i2c_mux_channel, device_status); + if (drv != nullptr) { + did_init = true; + } + } else { + WS_DEBUG_PRINT("[i2c] Creating an I2C output driver..."); + drv_out = CreateI2cOutputDrv( + device_name, bus, device_descriptor.i2c_device_address, + device_descriptor.i2c_mux_channel, device_status); + if (drv_out != nullptr) { + did_init = true; + } + WS_DEBUG_PRINTLN("OK!"); + } + + if (!did_init) { WS_DEBUG_PRINTLN("[i2c] ERROR: I2C driver type not found or unsupported!"); if (WsV2._sdCardV2->isModeOffline()) { WsV2.haltErrorV2("[i2c] Driver failed to initialize!\n\tDid you set " @@ -819,33 +999,96 @@ 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); + if (!is_output) { + drv->SetMuxAddress(device_descriptor.i2c_mux_address); + } else { + WS_DEBUG_PRINTLN("[i2c] Setting MUX address for output driver..."); + drv_out->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); + if (!is_output) { + drv->EnableAltI2CBus(_i2c_model->GetI2cDeviceAddOrReplaceMsg() + ->i2c_device_description.i2c_bus_scl, + _i2c_model->GetI2cDeviceAddOrReplaceMsg() + ->i2c_device_description.i2c_bus_sda); + } else { + WS_DEBUG_PRINTLN("[i2c] Setting alt. I2C bus for output driver..."); + drv_out->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); + + if (!is_output) { + // Configure Input-driver settings + 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); + } else { + WS_DEBUG_PRINTLN("[i2c] Configuring output driver..."); + // Configure Output-driver settings + pb_size_t config = + _i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_output_add.which_config; + if (config == + wippersnapper_i2c_output_I2cOutputAdd_led_backpack_config_tag) { + WS_DEBUG_PRINTLN("[i2c] Configuring LED backpack..."); + wippersnapper_i2c_output_LedBackpackConfig cfg = + _i2c_model->GetI2cDeviceAddOrReplaceMsg() + ->i2c_output_add.config.led_backpack_config; + WS_DEBUG_PRINT("[i2c] Got cfg, calling ConfigureI2CBackpack..."); + drv_out->ConfigureI2CBackpack(cfg.brightness, cfg.alignment); + WS_DEBUG_PRINTLN("OK!"); + } else if (config == + wippersnapper_i2c_output_I2cOutputAdd_char_lcd_config_tag) { + WS_DEBUG_PRINTLN("[i2c] Configuring char LCD..."); + } else if (config == + wippersnapper_i2c_output_I2cOutputAdd_oled_config_tag) { + WS_DEBUG_PRINTLN("[i2c] Configuring OLED..."); + wippersnapper_i2c_output_OledConfig cfg = + _i2c_model->GetI2cDeviceAddOrReplaceMsg() + ->i2c_output_add.config.oled_config; + WS_DEBUG_PRINT("[i2c] Got cfg, calling ConfigureOLED..."); + drv_out->ConfigureSSD1306(cfg.width, cfg.height, cfg.font_size); + WS_DEBUG_PRINTLN("OK!"); + } else { + WS_DEBUG_PRINTLN( + "[i2c] ERROR: Unknown config specified for output driver!"); + return false; + } + } + + if (!is_output) { + 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); + } else { + if (!drv_out->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_output.push_back(drv_out); } - _i2c_drivers.push_back(drv); WS_DEBUG_PRINTLN("[i2c] Driver initialized and added to controller: "); WS_DEBUG_PRINTLN(device_name); @@ -863,6 +1106,7 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) { // Create and publish the I2cDeviceAddedorReplaced message to the broker WS_DEBUG_PRINTLN("[i2c] MQTT Publish I2cDeviceAddedorReplaced not yet " "implemented!"); + // TODO! /* if (!PublishI2cDeviceAddedorReplaced(device_descriptor, device_status)) return false; */ } @@ -953,4 +1197,4 @@ void I2cController::update() { cur_time = millis(); drv->SetSensorPeriodPrv(cur_time); } -} \ No newline at end of file +} diff --git a/src/components/i2c/controller.h b/src/components/i2c/controller.h index cb2a9d2ab..201be0a86 100644 --- a/src/components/i2c/controller.h +++ b/src/components/i2c/controller.h @@ -20,7 +20,7 @@ // I2C Drivers #include "drivers/drvAdt7410.h" #include "drivers/drvAhtx0.h" -#include "drivers/drvBase.h" ///< Base driver class +#include "drivers/drvBase.h" ///< Base i2c input driver class #include "drivers/drvBh1750.h" #include "drivers/drvBme280.h" #include "drivers/drvBme680.h" @@ -45,6 +45,11 @@ #include "drivers/drvMprls.h" #include "drivers/drvMs8607.h" #include "drivers/drvNau7802.h" +#include "drivers/drvOut7Seg.h" +#include "drivers/drvOutCharLcd.h" +#include "drivers/drvOutQuadAlphaNum.h" +#include "drivers/drvOutSsd1306.h" +#include "drivers/drvOutputBase.h" ///< Base i2c output driver class #include "drivers/drvPct2075.h" #include "drivers/drvPm25.h" #include "drivers/drvScd30.h" @@ -69,6 +74,7 @@ class Wippersnapper_V2; ///< Forward declaration class I2cModel; ///< Forward declaration +class I2cOutputModel; ///< Forward declaration class I2cHardware; ///< Forward declaration /**************************************************************************/ @@ -84,9 +90,9 @@ class I2cController { void update(); // Routing // bool Handle_I2cDeviceAddOrReplace(pb_istream_t *stream); - // TODO [Online]: These are for Online mode and not yet implemented bool Handle_I2cBusScan(pb_istream_t *stream); bool Handle_I2cDeviceRemove(pb_istream_t *stream); + bool Handle_I2cDeviceOutputWrite(pb_istream_t *stream); // Publishing // bool PublishI2cDeviceAddedorReplaced( const wippersnapper_i2c_I2cDeviceDescriptor &device_descriptor, @@ -95,13 +101,17 @@ class I2cController { bool IsBusStatusOK(bool is_alt_bus = false); bool InitMux(const char *name, uint32_t address, bool is_alt_bus); void ConfigureMuxChannel(uint32_t mux_channel, bool is_alt_bus); - bool RemoveDriver(uint32_t address); + bool RemoveDriver(uint32_t address, bool is_output_device); private: - I2cModel *_i2c_model; ///< Pointer to an I2C model object - I2cHardware *_i2c_bus_default; ///< Pointer to the default I2C bus - I2cHardware *_i2c_bus_alt; ///< Pointer to an alternative I2C bus - std::vector _i2c_drivers; ///< Vector of ptrs to I2C device drivers + I2cModel *_i2c_model = nullptr; ///< Pointer to an I2C model object + I2cOutputModel *_i2c_output_model = + nullptr; ///< Pointer to an I2C output model object + I2cHardware *_i2c_bus_default = nullptr; ///< Pointer to the default I2C bus + I2cHardware *_i2c_bus_alt = nullptr; ///< Pointer to an alternative I2C bus + std::vector _i2c_drivers; ///< Vector of ptrs to I2C input drivers + std::vector + _i2c_drivers_output; ///< Vector of ptrs to I2C output drivers }; extern Wippersnapper_V2 WsV2; ///< Wippersnapper V2 instance #endif // WS_I2C_CONTROLLER_H \ No newline at end of file diff --git a/src/components/i2c/drivers/drvOut7Seg.h b/src/components/i2c/drivers/drvOut7Seg.h new file mode 100644 index 000000000..d70621dab --- /dev/null +++ b/src/components/i2c/drivers/drvOut7Seg.h @@ -0,0 +1,209 @@ +/*! + * @file drvOut7Seg.h + * + * Device driver designed specifically to work with the Adafruit LED 7-Segment + * I2C backpacks: + * ----> http://www.adafruit.com/products/881 + * ----> http://www.adafruit.com/products/880 + * ----> http://www.adafruit.com/products/879 + * ----> http://www.adafruit.com/products/878 + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell for Adafruit Industries 2025 + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef DRV_OUT_7SEG_H +#define DRV_OUT_7SEG_H + +#include "drvOutputBase.h" +#include +#include + +#define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment +#define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment +#define LED_BACKPACK_ALIGNMENT_RIGHT 2 ///< Right alignment +#define LED_BACKPACK_ALIGNMENT_DEFAULT \ + LED_BACKPACK_ALIGNMENT_LEFT ///< Default alignment +#define LED_MAX_CHARS \ + 4 ///< Maximum number of characters to display on the 7-segment display + +/*! + @brief Class that provides a driver for an Adafruit 7-Segment LED matrix + w/I2C backpack. +*/ +class drvOut7Seg : public drvOutputBase { +public: + /*! + @brief Constructor for an Adafruit 7-Segment LED matrix w/I2C backpack. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + drvOut7Seg(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvOutputBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvBase constructor + } + + /*! + @brief Destructor for an Adafruit 7-Segment LED matrix w/I2C backpack. + */ + ~drvOut7Seg() { + if (_matrix) { + delete _matrix; + _matrix = nullptr; + } + } + + /*! + @brief Initializes the 7-segment LED matrix and begins I2C + communication. + @returns True if initialized successfully, False otherwise. + */ + bool begin() override { + _matrix = new Adafruit_7segment(); + bool did_begin = _matrix->begin(0x70, _i2c); + return did_begin; + } + + /*! + @brief Configures the LED matrix's I2C backpack. + @param brightness + The brightness of the i2c backpack (0-15). + @param alignment + The alignment of the i2c backpack's LED matrix (left/right). +*/ + void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { + if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { + _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; + } else { + _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + } + + // Note: Adafruit_LEDBackpack normalizes only > 15, but not < 0, + // so, here we're normalizing < 0 to 8 (median brightness) + if (brightness < 0) { + brightness = 8; // Set to median brightness if out of range + } + } + + /*! + @brief Sets the brightness of the LED backpack. + @param b + The brightness value, from 0 (off) to 15 (full brightness). + */ + void SetLedBackpackBrightness(uint8_t b) { + if (_matrix == nullptr) { + return; + } + _matrix->setBrightness(b); + } + + /*! + @brief Writes the first four characters of a message to the Adafruit + 7-segment LED matrix. + @param message + The message to be displayed. + */ + void WriteMessage(const char *message) { + if (_matrix == nullptr || message == nullptr) { + return; + } + + // Clear before writing + _matrix->clear(); + + // Calculate the number of characters to display + size_t len_display = min(strlen(message), (size_t)LED_MAX_CHARS); + + // Set the starting position based on alignment + int pos_start; + if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) { + pos_start = 0; // start at the leftmost position of the display + } else { + // Exclude decimal points from the character count because those get + // displayed on a "special" segment of the LED display + int seg_chars = 0; + for (size_t i = 0; i < len_display; i++) { + if (message[i] != '.') { + seg_chars++; + } + } + // start at the rightmost position of the display + pos_start = LED_MAX_CHARS - seg_chars; + } + + // Write to the display's buffer + int cur_idx = pos_start; + for (size_t i = 0; i < len_display; i++) { + // skip position 2 + if (cur_idx == 2) { + cur_idx++; + } + // Save the character because if there's a decimal, we need to skip it in + // the buffer + char ch = message[i]; + + // Look-ahead for a decimal point to attach to the current character + bool display_dot = false; + if (i + 1 < len_display && message[i + 1] == '.') { + display_dot = true; + i++; + len_display++; + } + + // Write the character to the display buffer + _matrix->writeDigitAscii(cur_idx, ch, display_dot); + cur_idx++; + } + // Issue the buffered data in RAM to the display + _matrix->writeDisplay(); + } + + /*! + @brief Writes a floating point value to the Adafruit 7-segment LED + matrix. + @param value + The value to be displayed. Only the first four digits are + displayed. + */ + void WriteValue(float value) { + char message[8 + 1]; + snprintf(message, sizeof(message), "%.5f", value); + WriteMessage(message); + } + + /*! + @brief Writes an integer value to the Adafruit 7-segment LED matrix. + @param value + The value to be displayed. Only the first four digits are + displayed. + */ + void WriteValue(int32_t value) { + char message[LED_MAX_CHARS + 1]; + snprintf(message, sizeof(message), "%ld", value); + WriteMessage(message); + } + +protected: + Adafruit_7segment *_matrix = + nullptr; ///< ptr to a 7-segment LED matrix object + int32_t _brightness; ///< Brightness of the LED backpack, from 0 (off) to 15 + ///< (full brightness) + uint32_t _alignment = + LED_BACKPACK_ALIGNMENT_DEFAULT; ///< Determines L/R alignment of the + ///< message displayed +}; + +#endif // DRV_OUT_7SEG_H \ No newline at end of file diff --git a/src/components/i2c/drivers/drvOutCharLcd.h b/src/components/i2c/drivers/drvOutCharLcd.h new file mode 100644 index 000000000..3da962409 --- /dev/null +++ b/src/components/i2c/drivers/drvOutCharLcd.h @@ -0,0 +1,149 @@ +/*! + * @file drvOutCharLcd.h + * + * Device driver for I2C Character LCDs (HD44780) + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell for Adafruit Industries 2025 + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef DRV_OUT_CHAR_LCD +#define DRV_OUT_CHAR_LCD + +#include "drvOutputBase.h" +#include +#include + +/*! + @brief Class that provides a driver interface for a lcd character display. + This class is a wrapper around the Adafruit_LiquidCrystal library. +*/ +class drvOutCharLcd : public drvOutputBase { +public: + /*! + @brief Constructor for a lcd character display. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + drvOutCharLcd(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvOutputBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvOutPutBase constructor + } + + /*! + @brief Destructor for a quad alphanumeric display. + */ + ~drvOutCharLcd() { + if (_lcd) { + delete _lcd; + _lcd = nullptr; + } + } + + /*! + @brief Initializes an I2C character LCD and begins I2C communication. + @returns True if initialized successfully, False otherwise. + */ + bool begin() override { + _lcd = new Adafruit_LiquidCrystal(_address, _i2c); + bool did_begin = _lcd->begin(_cols, _rows); + if (did_begin && _enable_backlight) { + _lcd->setBacklight(HIGH); + } + return did_begin; + } + + /*! + @brief Writes a message to the LCD. + @note MUST be called prior to begin() to configure the LCD's size + @param rows + The number of rows in the LCD. + @param cols + The number of columns in the LCD. + @param enable_backlight + True if the backlight is enabled, False otherwise. + */ + void ConfigureCharLcd(uint8_t rows, uint8_t cols, bool enable_backlight) { + _rows = rows; + _cols = cols; + _enable_backlight = enable_backlight; + } + + /*! + @brief Enables or disables the backlight on a character LCD. + @param enable_backlight + True to enable the backlight, False to disable it. + */ + void EnableBackLightCharLCD(bool enable_backlight) { + if (_lcd == nullptr) + return; + if (_enable_backlight) { + _lcd->setBacklight(HIGH); + } else { + _lcd->setBacklight(LOW); + } + _enable_backlight = enable_backlight; + } + + /*! + @brief Writes a message to the LCD. + @param message + The message to be displayed. + */ + void WriteMessage(const char *message) { + if (_lcd == nullptr) + return; + + // Before writing, let's clear the display + _lcd->clear(); + + size_t message_length = strlen(message); + size_t cur_idx = 0; // Current index in the message + + // Write each row until it hits: \n, or the end of the message, or the last + // column/row position + for (int cur_row = 0; cur_row < _rows && cur_idx < message_length; + cur_row++) { + // Write each row out at the beginning of the row + _lcd->setCursor(0, cur_row); + for (int cur_col = 0; cur_col < _cols && cur_idx < message_length; + cur_col++) { + char c = message[cur_idx]; + if (c == '\\' && cur_idx + 1 < message_length && + message[cur_idx + 1] == 'n') { + cur_idx += 2; // Skip the '\n' character in the buffer + break; // and move to the next row + } else if (c == 194 && cur_idx + 1 < message_length && + message[cur_idx + 1] == 176) { + cur_idx += 2; // Skip the degree symbol sequence in the buffer + _lcd->write(0xDF); // and write the degree symbol + } else { + _lcd->write(c); + cur_idx++; + } + } + } + } + +protected: + Adafruit_LiquidCrystal *_lcd = + nullptr; ///< Pointer to the Adafruit_LiquidCrystal object + uint8_t _rows; ///< Number of rows in the display + uint8_t _cols; ///< Number of columns in the display + bool _enable_backlight; ///< Flag to enable/disable backlight +}; + +#endif // DRV_OUT_CHAR_LCD \ No newline at end of file diff --git a/src/components/i2c/drivers/drvOutQuadAlphaNum.h b/src/components/i2c/drivers/drvOutQuadAlphaNum.h new file mode 100644 index 000000000..18cced030 --- /dev/null +++ b/src/components/i2c/drivers/drvOutQuadAlphaNum.h @@ -0,0 +1,201 @@ +/*! + * @file drvOutQuadAlphaNum.h + * + * Device driver for Quad Alphanumeric Displays w/I2C Backpack + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell for Adafruit Industries 2025 + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef DRV_OUT_QUAD_ALPHANUM_H +#define DRV_OUT_QUAD_ALPHANUM_H + +#include "drvOutputBase.h" +#include +#include + +#define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment +#define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment +#define LED_BACKPACK_ALIGNMENT_RIGHT 2 ///< Right alignment +#define LED_BACKPACK_ALIGNMENT_DEFAULT \ + LED_BACKPACK_ALIGNMENT_LEFT ///< Default alignment +#define LED_MAX_CHARS \ + 4 ///< Maximum number of characters to display on the alphanumeric display + +/*! + @brief Class that provides a driver interface for Quad Alphanumeric + Displays w/I2C Backpack +*/ +class drvOutQuadAlphaNum : public drvOutputBase { +public: + /*! + @brief Constructor for a quad alphanumeric display.. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + drvOutQuadAlphaNum(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvOutputBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvBase constructor + } + + /*! + @brief Destructor for a quad alphanumeric display. + */ + ~drvOutQuadAlphaNum() { + if (_alpha4) { + delete _alpha4; + _alpha4 = nullptr; + } + } + + /*! + @brief Initializes the drvOutQuadAlphaNum sensor and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + bool begin() override { + _alpha4 = new Adafruit_AlphaNum4(); + bool did_begin = _alpha4->begin(_address, _i2c); + _alpha4->setBrightness(_brightness); + return did_begin; + } + + /*! + @brief Configures a LED backpack. + @param brightness + The brightness of the LED backpack. + @param alignment + The alignment of the LED backpack. +*/ + void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { + WS_DEBUG_PRINTLN("[i2c] drvOutQuadAlphaNum::ConfigureI2CBackpack() called"); + if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { + _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; + } else { + _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + } + _brightness = brightness; + WS_DEBUG_PRINTLN("[i2c] drvOutQuadAlphaNum::configured"); + } + + /*! + @brief Sets the brightness of the LED backpack. + @param b + The brightness value, from 0 (off) to 15 (full brightness). + */ + void SetLedBackpackBrightness(uint8_t b) { + if (_alpha4 == nullptr) { + return; + } + _alpha4->setBrightness(b); + } + + /*! + @brief Writes a message to the quad alphanumeric display. + @param message + The message to be displayed. + */ + void WriteMessage(const char *message) { + if (_alpha4 == nullptr || message == nullptr) { + return; + } + // Clear before writing + _alpha4->clear(); + + // Calculate the total message length + size_t msg_len = strlen(message); + + // Count all characters but excluding decimal points as they are part of the + // "segment" + int char_count = 0; + for (size_t i = 0; i < msg_len && char_count < LED_MAX_CHARS; i++) { + if (message[i] != '.') { + char_count++; + } + } + + // Set the starting position based on alignment + int pos_start; + if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) { + pos_start = 0; // start at the leftmost position + } else { + pos_start = LED_MAX_CHARS - char_count; // start at the rightmost position + } + + // Write to the display's buffer + int cur_idx = pos_start; + for (size_t i = 0; i < msg_len && cur_idx < LED_MAX_CHARS; i++) { + char ch = message[i]; + + if (ch == '.') { + // If the previous character has already been processed (or we're at the + // start of the message), we need to show the decimal as a character + if (i == 0 || message[i - 1] == '.') { + _alpha4->writeDigitAscii(cur_idx, ch, false); + cur_idx++; + } else { + // Set decimal on an already written character + _alpha4->writeDigitAscii(cur_idx - 1, message[i - 1], true); + } + continue; + } + + // Perform a look-ahead for the decimal + bool display_dot = (i + 1 < msg_len && message[i + 1] == '.'); + + // Write the character to the display buffer + _alpha4->writeDigitAscii(cur_idx, ch, display_dot); + cur_idx++; + } + + // Issue the buffered data in RAM to the display + _alpha4->writeDisplay(); + } + + /*! + @brief Writes a floating point value to the quad alphanumeric display. + @param value + The value to be displayed. Only the first four digits are + displayed. + */ + void WriteValue(float value) { + char message[8 + 1]; + snprintf(message, sizeof(message), "%.3f", value); + WriteMessage(message); + } + + /*! + @brief Writes an integer value to the quad alphanumeric display. + @param value + The value to be displayed. Only the first four digits are + displayed. + */ + void WriteValue(int32_t value) { + char message[LED_MAX_CHARS + 1]; + snprintf(message, sizeof(message), "%ld", value); + WriteMessage(message); + } + +protected: + Adafruit_AlphaNum4 *_alpha4 = + nullptr; ///< ptr to a 4-digit alphanumeric display object + int32_t _brightness; ///< Brightness of the LED backpack, from 0 (off) to 15 + ///< (full brightness) + uint32_t _alignment = + LED_BACKPACK_ALIGNMENT_DEFAULT; ///< Determines L/R alignment of the + ///< message displayed +}; + +#endif // DRV_OUT_QUAD_ALPHANUM_H \ No newline at end of file diff --git a/src/components/i2c/drivers/drvOutSsd1306.h b/src/components/i2c/drivers/drvOutSsd1306.h new file mode 100644 index 000000000..f02a5c867 --- /dev/null +++ b/src/components/i2c/drivers/drvOutSsd1306.h @@ -0,0 +1,138 @@ +/*! + * @file drvOutSsd1306.h + * + * Device driver for OLED displays with a SSD1306 driver + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell for Adafruit Industries 2025 + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef DRV_OUT_SSD1306_H +#define DRV_OUT_SSD1306_H + +#include "drvOutputBase.h" +#include +#include + +/*! + @brief Class that provides a driver interface for a SSD1306 OLED display. + This class is a wrapper around the Adafruit_SSD1306 library. +*/ +class drvOutSsd1306 : public drvOutputBase { +public: + /*! + @brief Constructor for a lcd character display. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + @param mux_channel + The I2C multiplexer channel. + @param driver_name + The name of the driver. + */ + drvOutSsd1306(TwoWire *i2c, uint16_t sensorAddress, uint32_t mux_channel, + const char *driver_name) + : drvOutputBase(i2c, sensorAddress, mux_channel, driver_name) { + // Initialization handled by drvOutPutBase constructor + } + + /*! + @brief Destructor for a quad alphanumeric display. + */ + ~drvOutSsd1306() { + if (_display != nullptr) { + _display->ssd1306_command(SSD1306_DISPLAYOFF); + delete _display; + _display = nullptr; + } + } + + /*! + @brief Initializes the SSD1306 display and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + bool begin() { + // Attempt to create and allocate a SSD1306 obj. + _display = new Adafruit_SSD1306(_width, _height, _i2c); + if (!_display->begin(SSD1306_SWITCHCAPVCC, _address)) + return false; + // Clear the buffer + _display->clearDisplay(); + // Configure the text size and color + _display->setTextSize(_text_sz); + _display->setTextColor(SSD1306_WHITE); + // Reset the cursor position + _display->setCursor(0, 0); + _display->display(); + return true; + } + + /*! + @brief Configures a SSD1306 OLED display. Must be called before driver + begin() + @param width + The width of the display in pixels. + @param height + The height of the display in pixels. + @param text_size + The magnification factor for the text size. + */ + void ConfigureSSD1306(uint8_t width, uint8_t height, uint8_t text_size) { + _width = width; + _height = height; + _text_sz = text_size; + } + + /*! + @brief Writes a message to the SSD1306 display. + @param message + The message to be displayed. + */ + void WriteMessageSSD1306(const char *message) { + if (_display == nullptr) + return; + + // Start with a fresh display buffer + // and settings + int16_t y_idx = 0; + _display->clearDisplay(); + _display->setTextSize(_text_sz); + _display->setTextColor(SSD1306_WHITE); + _display->setCursor(0, y_idx); + _display->display(); + + // Calculate the line height based on the text size (NOTE: base height is + // 8px) + int16_t line_height = 8 * _text_sz; + uint16_t c_idx = 0; + size_t msg_size = strlen(message); + for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { + if (message[i] == '\\' && i + 1 < msg_size && message[i + 1] == 'n') { + // detected a newline char sequence (\n) + i++; + // Skip to the next possible line + y_idx += line_height; + _display->setCursor(0, y_idx); + } else { + _display->print(message[i]); + _display->display(); + } + } + } + +protected: + Adafruit_SSD1306 *_display = + nullptr; ///< Pointer to the Adafruit_SSD1306 object + uint8_t _width; ///< Width of the display in pixels + uint8_t _height; ///< Height of the display in pixels + uint8_t _text_sz; ///< Text size of the display +}; + +#endif // DRV_OUT_SSD1306_H \ No newline at end of file diff --git a/src/components/i2c/drivers/drvOutputBase.h b/src/components/i2c/drivers/drvOutputBase.h new file mode 100644 index 000000000..ad75e12e3 --- /dev/null +++ b/src/components/i2c/drivers/drvOutputBase.h @@ -0,0 +1,160 @@ +/*! + * @file drvOutputBase.h + * + * Base implementation for I2C output device drivers. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef DRV_OUTPUT_BASE_H +#define DRV_OUTPUT_BASE_H +#include "drvBase.h" +#include +#include + +/*! + @brief Base class for I2C Output Drivers. +*/ +class drvOutputBase : public drvBase { + +public: + /*! + @brief Instantiates an I2C output device. + @param i2c + The I2C hardware interface, default is Wire. + @param address + The I2C device's unique address. + @param mux_channel + An optional channel number used to address a device on a I2C + MUX. + @param driver_name + The name of the driver. + */ + drvOutputBase(TwoWire *i2c, uint16_t address, uint32_t mux_channel, + const char *driver_name) + : drvBase(i2c, address, mux_channel, driver_name) { + // TODO + } + + /*! + @brief Destructor for an I2C output device. + */ + virtual ~drvOutputBase() {} + + /*! + @brief Initializes the I2C output device and begins I2C. + @param message + The message to be displayed. + */ + virtual void WriteMessage(const char *message) { + // noop + } + + /*! + @brief Writes a floating point value to the quad alphanumeric display. + @param value + The value to be displayed. Only the first four digits are + displayed. + */ + virtual void WriteValue(float value) { + // noop + } + + /*! + @brief Writes a floating point value to the quad alphanumeric display. + @param value + The value to be displayed. Only the first four digits are + displayed. + */ + virtual void WriteValue(int32_t value) { + // noop + } + + /*! + @brief Configures a LED backpack. + @param brightness + The brightness of the LED backpack. + @param alignment + The alignment of the LED backpack. + */ + virtual void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { + // noop + } + + /*! + @brief Configures a character LCD. + @param rows + The number of rows in the LCD. + @param cols + The number of columns in the LCD. + @param enable_backlight + True if the backlight is enabled, False otherwise. + */ + virtual void ConfigureCharLcd(uint32_t rows, uint32_t cols, + bool enable_backlight) { + // noop + } + + /*! + @brief Enables or disables the backlight on a character LCD. + @param enable_backlight + True to enable the backlight, False to disable it. + */ + void EnableBackLightCharLCD(bool enable_backlight) { + // noop + } + + /*! + @brief Writes a message to the LCD. + @param write_char_lcd + Pointer to a wippersnapper_i2c_output_CharLCDWrite message. + @returns True if the message was written successfully, False otherwise. + */ + bool + WriteMessageCharLCD(wippersnapper_i2c_output_CharLCDWrite *write_char_lcd) { + EnableBackLightCharLCD(write_char_lcd->enable_backlight); + WriteMessage(write_char_lcd->message); + return true; + } + + /*! + @brief Sets the brightness of the LED backpack. + @param b + The brightness value, from 0 (off) to 15 (full brightness). + */ + virtual void SetLedBackpackBrightness(uint8_t b) { + // noop + } + + /*! + @brief Configures a SSD1306 OLED display. Must be called before driver + begin() + @param width + The width of the display in pixels. + @param height + The height of the display in pixels. + @param text_size + The magnification factor for the text size. + */ + virtual void ConfigureSSD1306(uint8_t width, uint8_t height, + uint8_t text_size) { + // noop + } + + /*! + @brief Writes a message to the SSD1306 display. + @param message + The message to be displayed. + */ + virtual void WriteMessageSSD1306(const char *message) { + // noop + } +}; +#endif // DRV_OUTPUT_BASE_H \ No newline at end of file diff --git a/src/components/i2c/model.cpp b/src/components/i2c/model.cpp index 200148d38..b2fb0264b 100644 --- a/src/components/i2c/model.cpp +++ b/src/components/i2c/model.cpp @@ -1,7 +1,7 @@ /*! * @file src/components/i2c/model.cpp * - * Model for the i2c.proto message. + * Model for the i2c.proto and i2c_output.proto messages. * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing @@ -28,7 +28,8 @@ I2cModel::I2cModel() { memset(&_msg_i2c_device_remove, 0, sizeof(_msg_i2c_device_remove)); memset(&_msg_i2c_device_removed, 0, sizeof(_msg_i2c_device_removed)); memset(&_msg_i2c_device_event, 0, sizeof(_msg_i2c_device_event)); - // no-op + memset(&_msg_i2c_device_output_write, 0, + sizeof(_msg_i2c_device_output_write)); } /***********************************************************************/ @@ -45,6 +46,8 @@ I2cModel::~I2cModel() { memset(&_msg_i2c_device_remove, 0, sizeof(_msg_i2c_device_remove)); memset(&_msg_i2c_device_removed, 0, sizeof(_msg_i2c_device_removed)); memset(&_msg_i2c_device_event, 0, sizeof(_msg_i2c_device_event)); + memset(&_msg_i2c_device_output_write, 0, + sizeof(_msg_i2c_device_output_write)); } /***************************************************************************/ @@ -272,6 +275,14 @@ I2cModel::GetI2cDeviceAddOrReplaceMsg() { return &_msg_i2c_device_add_replace; } +/*! + @brief Returns a pointer to the I2cOutputAdd message. + @returns Pointer to the I2cOutputAdd message. +*/ +wippersnapper_i2c_output_I2cOutputAdd *I2cModel::GetI2cOutputAddMsg() { + return &_msg_i2c_device_add_replace.i2c_output_add; +} + /***************************************************************************/ /*! @brief Encodes a I2cDeviceAddedOrReplaced message. @@ -413,4 +424,85 @@ bool I2cModel::EncodeI2cDeviceEvent() { /**********************************************************************/ wippersnapper_i2c_I2cDeviceEvent *I2cModel::GetI2cDeviceEvent() { return &_msg_i2c_device_event; -} \ No newline at end of file +} + +/*! + @brief Decodes a I2cDeviceOutputWrite message from an input stream. + @param stream + A pointer to the pb_istream_t stream. + @returns True if the I2cDeviceOutputWrite message was decoded successfully, + False otherwise. +*/ +bool I2cModel::DecodeI2cDeviceOutputWrite(pb_istream_t *stream) { + memset(&_msg_i2c_device_output_write, 0, + sizeof(_msg_i2c_device_output_write)); + return pb_decode(stream, wippersnapper_i2c_I2cDeviceOutputWrite_fields, + &_msg_i2c_device_output_write); +} + +/*! + @brief Returns a pointer to the I2cDeviceOutputWrite message. + @returns Pointer to the I2cDeviceOutputWrite message. +*/ +wippersnapper_i2c_I2cDeviceOutputWrite *I2cModel::GetI2cDeviceOutputWriteMsg() { + return &_msg_i2c_device_output_write; +} + +/*! + @brief I2cOutputModel constructor +*/ +I2cOutputModel::I2cOutputModel() { + memset(&_msg_led_backpack_write, 0, sizeof(_msg_led_backpack_write)); + memset(&_msg_char_lcd_write, 0, sizeof(_msg_char_lcd_write)); +} + +/*! + @brief I2cOutputModel destructor +*/ +I2cOutputModel::~I2cOutputModel() { + memset(&_msg_led_backpack_write, 0, sizeof(_msg_led_backpack_write)); + memset(&_msg_char_lcd_write, 0, sizeof(_msg_char_lcd_write)); +} + +/*! + @brief Decodes a LedBackpackWrite message from an input stream. + @param stream + A pointer to the pb_istream_t stream. + @returns True if the LedBackpackWrite message was decoded successfully, + False otherwise. +*/ +bool I2cOutputModel::DecodeLedBackpackWrite(pb_istream_t *stream) { + memset(&_msg_led_backpack_write, 0, sizeof(_msg_led_backpack_write)); + return pb_decode(stream, wippersnapper_i2c_output_LedBackpackWrite_fields, + &_msg_led_backpack_write); +} + +/*! + @brief Decodes a CharLCDWrite message from an input stream. + @param stream + A pointer to the pb_istream_t stream. + @returns True if the CharLCDWrite message was decoded successfully, + False otherwise. +*/ +bool I2cOutputModel::DecodeCharLCDWrite(pb_istream_t *stream) { + memset(&_msg_char_lcd_write, 0, sizeof(_msg_char_lcd_write)); + return pb_decode(stream, wippersnapper_i2c_output_CharLCDWrite_fields, + &_msg_char_lcd_write); +} + +/*! + @brief Returns a pointer to the LedBackpackWrite message. + @returns Pointer to the LedBackpackWrite message. +*/ +wippersnapper_i2c_output_LedBackpackWrite * +I2cOutputModel::GetLedBackpackWriteMsg() { + return &_msg_led_backpack_write; +} + +/*! + @brief Returns a pointer to the CharLCDWrite message. + @returns Pointer to the CharLCDWrite message. +*/ +wippersnapper_i2c_output_CharLCDWrite *I2cOutputModel::GetCharLCDWriteMsg() { + return &_msg_char_lcd_write; +} diff --git a/src/components/i2c/model.h b/src/components/i2c/model.h index 328783b7f..838ce759c 100644 --- a/src/components/i2c/model.h +++ b/src/components/i2c/model.h @@ -1,7 +1,8 @@ /*! * @file src/components/i2c/model.h * - * Provides high-level interfaces for messages within i2c.proto. + * Provides high-level interfaces for messages within i2c.proto and + * i2c_output.proto. * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing @@ -16,6 +17,7 @@ #define WS_I2C_MODEL_H #include "Wippersnapper_V2.h" #include +#include #define MAX_DEVICE_EVENTS \ 15 ///< Maximum number of SensorEvents within I2cDeviceEvent #define MAX_I2C_SCAN_DEVICES 120 ///< Maximum number of devices found on the bus @@ -34,6 +36,7 @@ class I2cModel { bool DecodeI2cDeviceAddReplace(pb_istream_t *stream); bool DecodeI2cDeviceRemove(pb_istream_t *stream); bool DecodeI2cBusScan(pb_istream_t *stream); + bool DecodeI2cDeviceOutputWrite(pb_istream_t *stream); // Encoders bool encodeMsgI2cDeviceAddedorReplaced( wippersnapper_i2c_I2cDeviceDescriptor i2c_device_description, @@ -43,10 +46,12 @@ class I2cModel { // Getters wippersnapper_i2c_I2cDeviceRemove *GetI2cDeviceRemoveMsg(); wippersnapper_i2c_I2cDeviceAddOrReplace *GetI2cDeviceAddOrReplaceMsg(); + wippersnapper_i2c_output_I2cOutputAdd *GetI2cOutputAddMsg(); wippersnapper_i2c_I2cDeviceAddedOrReplaced *GetMsgI2cDeviceAddedOrReplaced(); wippersnapper_i2c_I2cDeviceEvent *GetI2cDeviceEvent(); wippersnapper_i2c_I2cBusScan *GetI2cBusScanMsg(); wippersnapper_i2c_I2cBusScanned *GetI2cBusScannedMsg(); + wippersnapper_i2c_I2cDeviceOutputWrite *GetI2cDeviceOutputWriteMsg(); // I2cBusScanned Message API void ClearI2cBusScanned(); bool AddDeviceToBusScan(const char *bus_scl, const char *bus_sda, @@ -70,5 +75,28 @@ class I2cModel { wippersnapper_i2c_I2cDeviceRemove _msg_i2c_device_remove; wippersnapper_i2c_I2cDeviceRemoved _msg_i2c_device_removed; wippersnapper_i2c_I2cDeviceEvent _msg_i2c_device_event; + wippersnapper_i2c_I2cDeviceOutputWrite _msg_i2c_device_output_write; +}; + +/**************************************************************************/ +/*! + @brief Provides an interface for creating, encoding, and parsing + messages from i2c_output.proto. +*/ +/**************************************************************************/ +class I2cOutputModel { +public: + I2cOutputModel(); + ~I2cOutputModel(); + // Decoders + bool DecodeLedBackpackWrite(pb_istream_t *stream); + bool DecodeCharLCDWrite(pb_istream_t *stream); + // Getters + wippersnapper_i2c_output_LedBackpackWrite *GetLedBackpackWriteMsg(); + wippersnapper_i2c_output_CharLCDWrite *GetCharLCDWriteMsg(); + +private: + wippersnapper_i2c_output_LedBackpackWrite _msg_led_backpack_write; + wippersnapper_i2c_output_CharLCDWrite _msg_char_lcd_write; }; #endif // WS_I2C_MODEL_H \ No newline at end of file diff --git a/src/pb.h b/src/pb.h index f5c9c6f34..fa7e0d893 100644 --- a/src/pb.h +++ b/src/pb.h @@ -16,7 +16,7 @@ /* Define this if your CPU / compiler combination does not support * unaligned memory access to packed structures. Note that packed * structures are only used when requested in .proto options. */ -/* #define PB_NO_PACKED_STRUCTS 1 */ +#define PB_NO_PACKED_STRUCTS 1 /* Increase the number of required fields that are tracked. * A compiler warning will tell if you need this. */ @@ -26,14 +26,14 @@ /* #define PB_FIELD_32BIT 1 */ /* Disable support for error messages in order to save some code space. */ -/* #define PB_NO_ERRMSG 1 */ +#define PB_NO_ERRMSG 1 /* Disable support for custom streams (support only memory buffers). */ -/* #define PB_BUFFER_ONLY 1 */ +#define PB_BUFFER_ONLY 1 /* Disable support for 64-bit datatypes, for compilers without int64_t or to save some code space. */ -/* #define PB_WITHOUT_64BIT 1 */ +#define PB_WITHOUT_64BIT 1 /* Don't encode scalar arrays as packed. This is only to be used when * the decoder on the receiving side cannot process packed scalar arrays. diff --git a/src/protos/i2c.pb.c b/src/protos/i2c.pb.c index 88655b887..6fddefe17 100644 --- a/src/protos/i2c.pb.c +++ b/src/protos/i2c.pb.c @@ -33,6 +33,9 @@ PB_BIND(wippersnapper_i2c_I2cDeviceRemoved, wippersnapper_i2c_I2cDeviceRemoved, PB_BIND(wippersnapper_i2c_I2cDeviceEvent, wippersnapper_i2c_I2cDeviceEvent, 2) +PB_BIND(wippersnapper_i2c_I2cDeviceOutputWrite, wippersnapper_i2c_I2cDeviceOutputWrite, 2) + + diff --git a/src/protos/i2c.pb.h b/src/protos/i2c.pb.h index b344a0029..c6e41a862 100644 --- a/src/protos/i2c.pb.h +++ b/src/protos/i2c.pb.h @@ -4,6 +4,7 @@ #ifndef PB_WIPPERSNAPPER_I2C_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_I2C_PB_H_INCLUDED #include +#include "i2c_output.pb.h" #include "sensor.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -81,6 +82,10 @@ typedef struct _wippersnapper_i2c_I2cDeviceAddOrReplace { float i2c_device_period; /* * The desired period to update the I2c device's sensor(s), in seconds. */ pb_size_t i2c_device_sensor_types_count; wippersnapper_sensor_SensorType i2c_device_sensor_types[15]; /* * SI Types for each sensor on the I2c device. */ + bool is_persistent; /* * Offline-Mode ONLY - True if the device exits in the config file, False otherwise. * */ + bool is_output; /* * Required by the device to determine if the device is an output device.* */ + bool has_i2c_output_add; + wippersnapper_i2c_output_I2cOutputAdd i2c_output_add; /* * Optional - If the I2C device is an output device, fill this field. * */ } wippersnapper_i2c_I2cDeviceAddOrReplace; /* * @@ -97,6 +102,7 @@ typedef struct _wippersnapper_i2c_I2cDeviceAddedOrReplaced { typedef struct _wippersnapper_i2c_I2cDeviceRemove { bool has_i2c_device_description; wippersnapper_i2c_I2cDeviceDescriptor i2c_device_description; /* * The I2c device's address and metadata. */ + bool is_output_device; /* * Determines if the device is an output device.* */ } wippersnapper_i2c_I2cDeviceRemove; /* * @@ -115,9 +121,22 @@ typedef struct _wippersnapper_i2c_I2cDeviceEvent { bool has_i2c_device_description; wippersnapper_i2c_I2cDeviceDescriptor i2c_device_description; /* * The I2c device's address and metadata. */ pb_size_t i2c_device_events_count; - wippersnapper_sensor_SensorEvent i2c_device_events[15]; /* * A, optionally repeated, SensorEvent from a sensor. */ + wippersnapper_sensor_SensorEvent i2c_device_events[15]; /* * Required, but optionally repeated, SensorEvent from a sensor. */ } wippersnapper_i2c_I2cDeviceEvent; +/* * + I2cDeviceOutputWrite represents a request to write to an I2C output device. */ +typedef struct _wippersnapper_i2c_I2cDeviceOutputWrite { + bool has_i2c_device_description; + wippersnapper_i2c_I2cDeviceDescriptor i2c_device_description; /* * Required - The I2c device's address and metadata. */ + pb_size_t which_output_msg; + union { + wippersnapper_i2c_output_LedBackpackWrite write_led_backpack; /* * Optional - If the I2C device is a LED backpack, fill this field. * */ + wippersnapper_i2c_output_CharLCDWrite write_char_lcd; /* * Optional - If the I2C device is a character LCD, fill this field. * */ + wippersnapper_i2c_output_OLEDWrite write_oled; /* * Optional - If the I2C device is an OLED display, fill this field. * */ + } output_msg; +} wippersnapper_i2c_I2cDeviceOutputWrite; + #ifdef __cplusplus extern "C" { @@ -146,25 +165,28 @@ extern "C" { + /* Initializer values for message structs */ #define wippersnapper_i2c_I2cDeviceDescriptor_init_default {"", "", 0, 0, 0} #define wippersnapper_i2c_I2cBusDescriptor_init_default {"", ""} #define wippersnapper_i2c_I2cBusScan_init_default {0, 0, false, wippersnapper_i2c_I2cBusDescriptor_init_default, 0, 0} #define wippersnapper_i2c_I2cBusScanned_init_default {0, {wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default, wippersnapper_i2c_I2cDeviceDescriptor_init_default}, _wippersnapper_i2c_I2cBusStatus_MIN} -#define wippersnapper_i2c_I2cDeviceAddOrReplace_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, "", 0, 0, {_wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN}} +#define wippersnapper_i2c_I2cDeviceAddOrReplace_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, "", 0, 0, {_wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN}, 0, 0, false, wippersnapper_i2c_output_I2cOutputAdd_init_default} #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, _wippersnapper_i2c_I2cBusStatus_MIN, _wippersnapper_i2c_I2cDeviceStatus_MIN} -#define wippersnapper_i2c_I2cDeviceRemove_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default} +#define wippersnapper_i2c_I2cDeviceRemove_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, 0} #define wippersnapper_i2c_I2cDeviceRemoved_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, 0} #define wippersnapper_i2c_I2cDeviceEvent_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, 0, {wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default, wippersnapper_sensor_SensorEvent_init_default}} +#define wippersnapper_i2c_I2cDeviceOutputWrite_init_default {false, wippersnapper_i2c_I2cDeviceDescriptor_init_default, 0, {wippersnapper_i2c_output_LedBackpackWrite_init_default}} #define wippersnapper_i2c_I2cDeviceDescriptor_init_zero {"", "", 0, 0, 0} #define wippersnapper_i2c_I2cBusDescriptor_init_zero {"", ""} #define wippersnapper_i2c_I2cBusScan_init_zero {0, 0, false, wippersnapper_i2c_I2cBusDescriptor_init_zero, 0, 0} #define wippersnapper_i2c_I2cBusScanned_init_zero {0, {wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, wippersnapper_i2c_I2cDeviceDescriptor_init_zero}, _wippersnapper_i2c_I2cBusStatus_MIN} -#define wippersnapper_i2c_I2cDeviceAddOrReplace_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, "", 0, 0, {_wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN}} +#define wippersnapper_i2c_I2cDeviceAddOrReplace_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, "", 0, 0, {_wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN, _wippersnapper_sensor_SensorType_MIN}, 0, 0, false, wippersnapper_i2c_output_I2cOutputAdd_init_zero} #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, _wippersnapper_i2c_I2cBusStatus_MIN, _wippersnapper_i2c_I2cDeviceStatus_MIN} -#define wippersnapper_i2c_I2cDeviceRemove_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero} +#define wippersnapper_i2c_I2cDeviceRemove_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, 0} #define wippersnapper_i2c_I2cDeviceRemoved_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, 0} #define wippersnapper_i2c_I2cDeviceEvent_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, 0, {wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero, wippersnapper_sensor_SensorEvent_init_zero}} +#define wippersnapper_i2c_I2cDeviceOutputWrite_init_zero {false, wippersnapper_i2c_I2cDeviceDescriptor_init_zero, 0, {wippersnapper_i2c_output_LedBackpackWrite_init_zero}} /* Field tags (for use in manual encoding/decoding) */ #define wippersnapper_i2c_I2cDeviceDescriptor_i2c_bus_sda_tag 1 @@ -185,14 +207,22 @@ extern "C" { #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_name_tag 2 #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_period_tag 3 #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_sensor_types_tag 4 +#define wippersnapper_i2c_I2cDeviceAddOrReplace_is_persistent_tag 5 +#define wippersnapper_i2c_I2cDeviceAddOrReplace_is_output_tag 6 +#define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_output_add_tag 7 #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_i2c_device_description_tag 1 #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_i2c_bus_status_tag 2 #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_i2c_device_status_tag 3 #define wippersnapper_i2c_I2cDeviceRemove_i2c_device_description_tag 1 +#define wippersnapper_i2c_I2cDeviceRemove_is_output_device_tag 2 #define wippersnapper_i2c_I2cDeviceRemoved_i2c_device_description_tag 1 #define wippersnapper_i2c_I2cDeviceRemoved_did_remove_tag 2 #define wippersnapper_i2c_I2cDeviceEvent_i2c_device_description_tag 1 #define wippersnapper_i2c_I2cDeviceEvent_i2c_device_events_tag 2 +#define wippersnapper_i2c_I2cDeviceOutputWrite_i2c_device_description_tag 1 +#define wippersnapper_i2c_I2cDeviceOutputWrite_write_led_backpack_tag 2 +#define wippersnapper_i2c_I2cDeviceOutputWrite_write_char_lcd_tag 3 +#define wippersnapper_i2c_I2cDeviceOutputWrite_write_oled_tag 4 /* Struct field encoding specification for nanopb */ #define wippersnapper_i2c_I2cDeviceDescriptor_FIELDLIST(X, a) \ @@ -231,10 +261,14 @@ X(a, STATIC, SINGULAR, UENUM, i2c_bus_status, 2) X(a, STATIC, OPTIONAL, MESSAGE, i2c_device_description, 1) \ X(a, STATIC, SINGULAR, STRING, i2c_device_name, 2) \ X(a, STATIC, SINGULAR, FLOAT, i2c_device_period, 3) \ -X(a, STATIC, REPEATED, UENUM, i2c_device_sensor_types, 4) +X(a, STATIC, REPEATED, UENUM, i2c_device_sensor_types, 4) \ +X(a, STATIC, SINGULAR, BOOL, is_persistent, 5) \ +X(a, STATIC, SINGULAR, BOOL, is_output, 6) \ +X(a, STATIC, OPTIONAL, MESSAGE, i2c_output_add, 7) #define wippersnapper_i2c_I2cDeviceAddOrReplace_CALLBACK NULL #define wippersnapper_i2c_I2cDeviceAddOrReplace_DEFAULT NULL #define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_device_description_MSGTYPE wippersnapper_i2c_I2cDeviceDescriptor +#define wippersnapper_i2c_I2cDeviceAddOrReplace_i2c_output_add_MSGTYPE wippersnapper_i2c_output_I2cOutputAdd #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_FIELDLIST(X, a) \ X(a, STATIC, OPTIONAL, MESSAGE, i2c_device_description, 1) \ @@ -245,7 +279,8 @@ X(a, STATIC, SINGULAR, UENUM, i2c_device_status, 3) #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_i2c_device_description_MSGTYPE wippersnapper_i2c_I2cDeviceDescriptor #define wippersnapper_i2c_I2cDeviceRemove_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, i2c_device_description, 1) +X(a, STATIC, OPTIONAL, MESSAGE, i2c_device_description, 1) \ +X(a, STATIC, SINGULAR, BOOL, is_output_device, 2) #define wippersnapper_i2c_I2cDeviceRemove_CALLBACK NULL #define wippersnapper_i2c_I2cDeviceRemove_DEFAULT NULL #define wippersnapper_i2c_I2cDeviceRemove_i2c_device_description_MSGTYPE wippersnapper_i2c_I2cDeviceDescriptor @@ -265,6 +300,18 @@ X(a, STATIC, REPEATED, MESSAGE, i2c_device_events, 2) #define wippersnapper_i2c_I2cDeviceEvent_i2c_device_description_MSGTYPE wippersnapper_i2c_I2cDeviceDescriptor #define wippersnapper_i2c_I2cDeviceEvent_i2c_device_events_MSGTYPE wippersnapper_sensor_SensorEvent +#define wippersnapper_i2c_I2cDeviceOutputWrite_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, i2c_device_description, 1) \ +X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_led_backpack,output_msg.write_led_backpack), 2) \ +X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_char_lcd,output_msg.write_char_lcd), 3) \ +X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_oled,output_msg.write_oled), 4) +#define wippersnapper_i2c_I2cDeviceOutputWrite_CALLBACK NULL +#define wippersnapper_i2c_I2cDeviceOutputWrite_DEFAULT NULL +#define wippersnapper_i2c_I2cDeviceOutputWrite_i2c_device_description_MSGTYPE wippersnapper_i2c_I2cDeviceDescriptor +#define wippersnapper_i2c_I2cDeviceOutputWrite_output_msg_write_led_backpack_MSGTYPE wippersnapper_i2c_output_LedBackpackWrite +#define wippersnapper_i2c_I2cDeviceOutputWrite_output_msg_write_char_lcd_MSGTYPE wippersnapper_i2c_output_CharLCDWrite +#define wippersnapper_i2c_I2cDeviceOutputWrite_output_msg_write_oled_MSGTYPE wippersnapper_i2c_output_OLEDWrite + extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceDescriptor_msg; extern const pb_msgdesc_t wippersnapper_i2c_I2cBusDescriptor_msg; extern const pb_msgdesc_t wippersnapper_i2c_I2cBusScan_msg; @@ -274,6 +321,7 @@ extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceAddedOrReplaced_msg; extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceRemove_msg; extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceRemoved_msg; extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceEvent_msg; +extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceOutputWrite_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define wippersnapper_i2c_I2cDeviceDescriptor_fields &wippersnapper_i2c_I2cDeviceDescriptor_msg @@ -285,16 +333,18 @@ extern const pb_msgdesc_t wippersnapper_i2c_I2cDeviceEvent_msg; #define wippersnapper_i2c_I2cDeviceRemove_fields &wippersnapper_i2c_I2cDeviceRemove_msg #define wippersnapper_i2c_I2cDeviceRemoved_fields &wippersnapper_i2c_I2cDeviceRemoved_msg #define wippersnapper_i2c_I2cDeviceEvent_fields &wippersnapper_i2c_I2cDeviceEvent_msg +#define wippersnapper_i2c_I2cDeviceOutputWrite_fields &wippersnapper_i2c_I2cDeviceOutputWrite_msg /* Maximum encoded size of messages (where known) */ #define WIPPERSNAPPER_I2C_I2C_PB_H_MAX_SIZE wippersnapper_i2c_I2cBusScanned_size #define wippersnapper_i2c_I2cBusDescriptor_size 32 #define wippersnapper_i2c_I2cBusScan_size 42 #define wippersnapper_i2c_I2cBusScanned_size 6242 -#define wippersnapper_i2c_I2cDeviceAddOrReplace_size 103 +#define wippersnapper_i2c_I2cDeviceAddOrReplace_size 125 #define wippersnapper_i2c_I2cDeviceAddedOrReplaced_size 56 #define wippersnapper_i2c_I2cDeviceDescriptor_size 50 -#define wippersnapper_i2c_I2cDeviceRemove_size 52 +#define wippersnapper_i2c_I2cDeviceOutputWrite_size 569 +#define wippersnapper_i2c_I2cDeviceRemove_size 54 #define wippersnapper_i2c_I2cDeviceRemoved_size 54 #if defined(wippersnapper_sensor_SensorEvent_size) #define wippersnapper_i2c_I2cDeviceEvent_size (142 + 15*wippersnapper_sensor_SensorEvent_size) diff --git a/src/protos/i2c_output.pb.c b/src/protos/i2c_output.pb.c new file mode 100644 index 000000000..d8474b88b --- /dev/null +++ b/src/protos/i2c_output.pb.c @@ -0,0 +1,32 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.8 */ + +#include "i2c_output.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(wippersnapper_i2c_output_LedBackpackConfig, wippersnapper_i2c_output_LedBackpackConfig, AUTO) + + +PB_BIND(wippersnapper_i2c_output_CharLCDConfig, wippersnapper_i2c_output_CharLCDConfig, AUTO) + + +PB_BIND(wippersnapper_i2c_output_OledConfig, wippersnapper_i2c_output_OledConfig, AUTO) + + +PB_BIND(wippersnapper_i2c_output_I2cOutputAdd, wippersnapper_i2c_output_I2cOutputAdd, AUTO) + + +PB_BIND(wippersnapper_i2c_output_LedBackpackWrite, wippersnapper_i2c_output_LedBackpackWrite, AUTO) + + +PB_BIND(wippersnapper_i2c_output_CharLCDWrite, wippersnapper_i2c_output_CharLCDWrite, AUTO) + + +PB_BIND(wippersnapper_i2c_output_OLEDWrite, wippersnapper_i2c_output_OLEDWrite, 2) + + + + + diff --git a/src/protos/i2c_output.pb.h b/src/protos/i2c_output.pb.h new file mode 100644 index 000000000..e14e12dfd --- /dev/null +++ b/src/protos/i2c_output.pb.h @@ -0,0 +1,215 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.8 */ + +#ifndef PB_WIPPERSNAPPER_I2C_OUTPUT_I2C_OUTPUT_PB_H_INCLUDED +#define PB_WIPPERSNAPPER_I2C_OUTPUT_I2C_OUTPUT_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +/* * + LedBackpackAlignment represents all text alignment option for LED backpack displays */ +typedef enum _wippersnapper_i2c_output_LedBackpackAlignment { + wippersnapper_i2c_output_LedBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED = 0, /* * Unspecified alignment option. * */ + wippersnapper_i2c_output_LedBackpackAlignment_LED_BACKPACK_ALIGNMENT_LEFT = 1, /* * (Default) Left-aligned. * */ + wippersnapper_i2c_output_LedBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT = 2 /* * Right-aligned. * */ +} wippersnapper_i2c_output_LedBackpackAlignment; + +/* * + Desired OLED display text 'magnification' size. */ +typedef enum _wippersnapper_i2c_output_OledTextSize { + wippersnapper_i2c_output_OledTextSize_OLED_TEXT_SIZE_UNSPECIFIED = 0, /* * Unspecified text size. * */ + wippersnapper_i2c_output_OledTextSize_OLED_TEXT_SIZE_DEFAULT = 1, /* * Default text size, 6x8px. * */ + wippersnapper_i2c_output_OledTextSize_OLED_TEXT_SIZE_LARGE = 2 /* * Larger text size option, 12x16px. * */ +} wippersnapper_i2c_output_OledTextSize; + +/* Struct definitions */ +/* * + LedBackpackConfig represents the configuration for a LED backpack display. */ +typedef struct _wippersnapper_i2c_output_LedBackpackConfig { + int32_t brightness; /* * Desired brightness of the LED backpack, from 0 (off) to 15 (full brightness). * */ + wippersnapper_i2c_output_LedBackpackAlignment alignment; /* * Desired text alignment for the LED backpack. * */ +} wippersnapper_i2c_output_LedBackpackConfig; + +/* * + CharLCDConfig represents the configuration for a character LCD display. */ +typedef struct _wippersnapper_i2c_output_CharLCDConfig { + uint32_t rows; /* * Number of rows for the character LCD. * */ + uint32_t columns; /* * Number of columns for the character LCD. * */ +} wippersnapper_i2c_output_CharLCDConfig; + +/* * + OledConfig represents the configuration for a OLED display. */ +typedef struct _wippersnapper_i2c_output_OledConfig { + uint32_t width; /* * Width of the OLED display in pixels. * */ + uint32_t height; /* * Height of the OLED display in pixels. * */ + wippersnapper_i2c_output_OledTextSize font_size; /* * Desired font magnification for the OLED display. Defaults to OLED_TEXT_SIZE_DEFAULT. * */ +} wippersnapper_i2c_output_OledConfig; + +/* * + I2cOutputAdd represents a request from the broker to add an I2C output device to a device. */ +typedef struct _wippersnapper_i2c_output_I2cOutputAdd { + pb_size_t which_config; + union { + wippersnapper_i2c_output_LedBackpackConfig led_backpack_config; /* * Configuration for a LED backpack. * */ + wippersnapper_i2c_output_CharLCDConfig char_lcd_config; /* * Configuration for a character LCD. * */ + wippersnapper_i2c_output_OledConfig oled_config; /* * Configuration for an OLED display. * */ + } config; +} wippersnapper_i2c_output_I2cOutputAdd; + +/* * + LedBackpackWrite represents a request from the broker to write a message to a LED backpack. */ +typedef struct _wippersnapper_i2c_output_LedBackpackWrite { + char message[8]; /* * Message to write to the LED backpack. * */ +} wippersnapper_i2c_output_LedBackpackWrite; + +/* * + CharLCDWrite represents a request from the broker to write to a character LCD. */ +typedef struct _wippersnapper_i2c_output_CharLCDWrite { + char message[100]; /* * Message to write to the character LCD. * */ + bool enable_backlight; /* * Whether to enable the backlight. Defaults to True. * */ +} wippersnapper_i2c_output_CharLCDWrite; + +/* * + OLEDWrite represents a request from the broker to write to a OLED display. */ +typedef struct _wippersnapper_i2c_output_OLEDWrite { + char message[512]; /* * Message to write to an OLED display. * */ +} wippersnapper_i2c_output_OLEDWrite; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Helper constants for enums */ +#define _wippersnapper_i2c_output_LedBackpackAlignment_MIN wippersnapper_i2c_output_LedBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED +#define _wippersnapper_i2c_output_LedBackpackAlignment_MAX wippersnapper_i2c_output_LedBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT +#define _wippersnapper_i2c_output_LedBackpackAlignment_ARRAYSIZE ((wippersnapper_i2c_output_LedBackpackAlignment)(wippersnapper_i2c_output_LedBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT+1)) + +#define _wippersnapper_i2c_output_OledTextSize_MIN wippersnapper_i2c_output_OledTextSize_OLED_TEXT_SIZE_UNSPECIFIED +#define _wippersnapper_i2c_output_OledTextSize_MAX wippersnapper_i2c_output_OledTextSize_OLED_TEXT_SIZE_LARGE +#define _wippersnapper_i2c_output_OledTextSize_ARRAYSIZE ((wippersnapper_i2c_output_OledTextSize)(wippersnapper_i2c_output_OledTextSize_OLED_TEXT_SIZE_LARGE+1)) + +#define wippersnapper_i2c_output_LedBackpackConfig_alignment_ENUMTYPE wippersnapper_i2c_output_LedBackpackAlignment + + +#define wippersnapper_i2c_output_OledConfig_font_size_ENUMTYPE wippersnapper_i2c_output_OledTextSize + + + + + + +/* Initializer values for message structs */ +#define wippersnapper_i2c_output_LedBackpackConfig_init_default {0, _wippersnapper_i2c_output_LedBackpackAlignment_MIN} +#define wippersnapper_i2c_output_CharLCDConfig_init_default {0, 0} +#define wippersnapper_i2c_output_OledConfig_init_default {0, 0, _wippersnapper_i2c_output_OledTextSize_MIN} +#define wippersnapper_i2c_output_I2cOutputAdd_init_default {0, {wippersnapper_i2c_output_LedBackpackConfig_init_default}} +#define wippersnapper_i2c_output_LedBackpackWrite_init_default {""} +#define wippersnapper_i2c_output_CharLCDWrite_init_default {"", 0} +#define wippersnapper_i2c_output_OLEDWrite_init_default {""} +#define wippersnapper_i2c_output_LedBackpackConfig_init_zero {0, _wippersnapper_i2c_output_LedBackpackAlignment_MIN} +#define wippersnapper_i2c_output_CharLCDConfig_init_zero {0, 0} +#define wippersnapper_i2c_output_OledConfig_init_zero {0, 0, _wippersnapper_i2c_output_OledTextSize_MIN} +#define wippersnapper_i2c_output_I2cOutputAdd_init_zero {0, {wippersnapper_i2c_output_LedBackpackConfig_init_zero}} +#define wippersnapper_i2c_output_LedBackpackWrite_init_zero {""} +#define wippersnapper_i2c_output_CharLCDWrite_init_zero {"", 0} +#define wippersnapper_i2c_output_OLEDWrite_init_zero {""} + +/* Field tags (for use in manual encoding/decoding) */ +#define wippersnapper_i2c_output_LedBackpackConfig_brightness_tag 1 +#define wippersnapper_i2c_output_LedBackpackConfig_alignment_tag 2 +#define wippersnapper_i2c_output_CharLCDConfig_rows_tag 1 +#define wippersnapper_i2c_output_CharLCDConfig_columns_tag 2 +#define wippersnapper_i2c_output_OledConfig_width_tag 1 +#define wippersnapper_i2c_output_OledConfig_height_tag 2 +#define wippersnapper_i2c_output_OledConfig_font_size_tag 3 +#define wippersnapper_i2c_output_I2cOutputAdd_led_backpack_config_tag 1 +#define wippersnapper_i2c_output_I2cOutputAdd_char_lcd_config_tag 2 +#define wippersnapper_i2c_output_I2cOutputAdd_oled_config_tag 3 +#define wippersnapper_i2c_output_LedBackpackWrite_message_tag 1 +#define wippersnapper_i2c_output_CharLCDWrite_message_tag 1 +#define wippersnapper_i2c_output_CharLCDWrite_enable_backlight_tag 2 +#define wippersnapper_i2c_output_OLEDWrite_message_tag 1 + +/* Struct field encoding specification for nanopb */ +#define wippersnapper_i2c_output_LedBackpackConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, brightness, 1) \ +X(a, STATIC, SINGULAR, UENUM, alignment, 2) +#define wippersnapper_i2c_output_LedBackpackConfig_CALLBACK NULL +#define wippersnapper_i2c_output_LedBackpackConfig_DEFAULT NULL + +#define wippersnapper_i2c_output_CharLCDConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, rows, 1) \ +X(a, STATIC, SINGULAR, UINT32, columns, 2) +#define wippersnapper_i2c_output_CharLCDConfig_CALLBACK NULL +#define wippersnapper_i2c_output_CharLCDConfig_DEFAULT NULL + +#define wippersnapper_i2c_output_OledConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, width, 1) \ +X(a, STATIC, SINGULAR, UINT32, height, 2) \ +X(a, STATIC, SINGULAR, UENUM, font_size, 3) +#define wippersnapper_i2c_output_OledConfig_CALLBACK NULL +#define wippersnapper_i2c_output_OledConfig_DEFAULT NULL + +#define wippersnapper_i2c_output_I2cOutputAdd_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (config,led_backpack_config,config.led_backpack_config), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (config,char_lcd_config,config.char_lcd_config), 2) \ +X(a, STATIC, ONEOF, MESSAGE, (config,oled_config,config.oled_config), 3) +#define wippersnapper_i2c_output_I2cOutputAdd_CALLBACK NULL +#define wippersnapper_i2c_output_I2cOutputAdd_DEFAULT NULL +#define wippersnapper_i2c_output_I2cOutputAdd_config_led_backpack_config_MSGTYPE wippersnapper_i2c_output_LedBackpackConfig +#define wippersnapper_i2c_output_I2cOutputAdd_config_char_lcd_config_MSGTYPE wippersnapper_i2c_output_CharLCDConfig +#define wippersnapper_i2c_output_I2cOutputAdd_config_oled_config_MSGTYPE wippersnapper_i2c_output_OledConfig + +#define wippersnapper_i2c_output_LedBackpackWrite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, message, 1) +#define wippersnapper_i2c_output_LedBackpackWrite_CALLBACK NULL +#define wippersnapper_i2c_output_LedBackpackWrite_DEFAULT NULL + +#define wippersnapper_i2c_output_CharLCDWrite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, message, 1) \ +X(a, STATIC, SINGULAR, BOOL, enable_backlight, 2) +#define wippersnapper_i2c_output_CharLCDWrite_CALLBACK NULL +#define wippersnapper_i2c_output_CharLCDWrite_DEFAULT NULL + +#define wippersnapper_i2c_output_OLEDWrite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, message, 1) +#define wippersnapper_i2c_output_OLEDWrite_CALLBACK NULL +#define wippersnapper_i2c_output_OLEDWrite_DEFAULT NULL + +extern const pb_msgdesc_t wippersnapper_i2c_output_LedBackpackConfig_msg; +extern const pb_msgdesc_t wippersnapper_i2c_output_CharLCDConfig_msg; +extern const pb_msgdesc_t wippersnapper_i2c_output_OledConfig_msg; +extern const pb_msgdesc_t wippersnapper_i2c_output_I2cOutputAdd_msg; +extern const pb_msgdesc_t wippersnapper_i2c_output_LedBackpackWrite_msg; +extern const pb_msgdesc_t wippersnapper_i2c_output_CharLCDWrite_msg; +extern const pb_msgdesc_t wippersnapper_i2c_output_OLEDWrite_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define wippersnapper_i2c_output_LedBackpackConfig_fields &wippersnapper_i2c_output_LedBackpackConfig_msg +#define wippersnapper_i2c_output_CharLCDConfig_fields &wippersnapper_i2c_output_CharLCDConfig_msg +#define wippersnapper_i2c_output_OledConfig_fields &wippersnapper_i2c_output_OledConfig_msg +#define wippersnapper_i2c_output_I2cOutputAdd_fields &wippersnapper_i2c_output_I2cOutputAdd_msg +#define wippersnapper_i2c_output_LedBackpackWrite_fields &wippersnapper_i2c_output_LedBackpackWrite_msg +#define wippersnapper_i2c_output_CharLCDWrite_fields &wippersnapper_i2c_output_CharLCDWrite_msg +#define wippersnapper_i2c_output_OLEDWrite_fields &wippersnapper_i2c_output_OLEDWrite_msg + +/* Maximum encoded size of messages (where known) */ +#define WIPPERSNAPPER_I2C_OUTPUT_I2C_OUTPUT_PB_H_MAX_SIZE wippersnapper_i2c_output_OLEDWrite_size +#define wippersnapper_i2c_output_CharLCDConfig_size 12 +#define wippersnapper_i2c_output_CharLCDWrite_size 103 +#define wippersnapper_i2c_output_I2cOutputAdd_size 16 +#define wippersnapper_i2c_output_LedBackpackConfig_size 13 +#define wippersnapper_i2c_output_LedBackpackWrite_size 9 +#define wippersnapper_i2c_output_OLEDWrite_size 514 +#define wippersnapper_i2c_output_OledConfig_size 14 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/protos/signal.pb.h b/src/protos/signal.pb.h index 3262a6c05..596c42840 100644 --- a/src/protos/signal.pb.h +++ b/src/protos/signal.pb.h @@ -10,6 +10,7 @@ #include "ds18x20.pb.h" #include "error.pb.h" #include "i2c.pb.h" +#include "i2c_output.pb.h" #include "pixels.pb.h" #include "pwm.pb.h" #include "servo.pb.h" @@ -62,6 +63,7 @@ typedef struct _wippersnapper_signal_BrokerToDevice { wippersnapper_i2c_I2cBusScan i2c_bus_scan; wippersnapper_i2c_I2cDeviceAddOrReplace i2c_device_add_replace; wippersnapper_i2c_I2cDeviceRemove i2c_device_remove; + wippersnapper_i2c_I2cDeviceOutputWrite i2c_device_output_write; /* error.proto */ wippersnapper_error_Error error; } payload; @@ -138,6 +140,7 @@ extern "C" { #define wippersnapper_signal_BrokerToDevice_i2c_bus_scan_tag 90 #define wippersnapper_signal_BrokerToDevice_i2c_device_add_replace_tag 91 #define wippersnapper_signal_BrokerToDevice_i2c_device_remove_tag 92 +#define wippersnapper_signal_BrokerToDevice_i2c_device_output_write_tag 93 #define wippersnapper_signal_BrokerToDevice_error_tag 100 #define wippersnapper_signal_DeviceToBroker_digitalio_event_tag 10 #define wippersnapper_signal_DeviceToBroker_analogio_event_tag 20 @@ -181,6 +184,7 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,uart_remove,payload.uart_remove), 8 X(a, STATIC, ONEOF, MSG_W_CB, (payload,i2c_bus_scan,payload.i2c_bus_scan), 90) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,i2c_device_add_replace,payload.i2c_device_add_replace), 91) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,i2c_device_remove,payload.i2c_device_remove), 92) \ +X(a, STATIC, ONEOF, MSG_W_CB, (payload,i2c_device_output_write,payload.i2c_device_output_write), 93) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,error,payload.error), 100) #define wippersnapper_signal_BrokerToDevice_CALLBACK NULL #define wippersnapper_signal_BrokerToDevice_DEFAULT NULL @@ -209,6 +213,7 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,error,payload.error), 100) #define wippersnapper_signal_BrokerToDevice_payload_i2c_bus_scan_MSGTYPE wippersnapper_i2c_I2cBusScan #define wippersnapper_signal_BrokerToDevice_payload_i2c_device_add_replace_MSGTYPE wippersnapper_i2c_I2cDeviceAddOrReplace #define wippersnapper_signal_BrokerToDevice_payload_i2c_device_remove_MSGTYPE wippersnapper_i2c_I2cDeviceRemove +#define wippersnapper_signal_BrokerToDevice_payload_i2c_device_output_write_MSGTYPE wippersnapper_i2c_I2cDeviceOutputWrite #define wippersnapper_signal_BrokerToDevice_payload_error_MSGTYPE wippersnapper_error_Error #define wippersnapper_signal_DeviceToBroker_FIELDLIST(X, a) \ @@ -252,7 +257,7 @@ extern const pb_msgdesc_t wippersnapper_signal_DeviceToBroker_msg; /* Maximum encoded size of messages (where known) */ #if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_digitalio_DigitalIOWrite_size) && defined(wippersnapper_uart_UARTAdd_size) && defined(wippersnapper_uart_UARTRemove_size) -union wippersnapper_signal_BrokerToDevice_payload_size_union {char f12[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f13[(6 + wippersnapper_digitalio_DigitalIOWrite_size)]; char f80[(7 + wippersnapper_uart_UARTAdd_size)]; char f81[(7 + wippersnapper_uart_UARTRemove_size)]; char f0[106];}; +union wippersnapper_signal_BrokerToDevice_payload_size_union {char f12[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f13[(6 + wippersnapper_digitalio_DigitalIOWrite_size)]; char f80[(7 + wippersnapper_uart_UARTAdd_size)]; char f81[(7 + wippersnapper_uart_UARTRemove_size)]; char f0[573];}; #endif #if defined(wippersnapper_digitalio_DigitalIOEvent_size) && defined(wippersnapper_analogio_AnalogIOEvent_size) && defined(wippersnapper_ds18x20_Ds18x20Event_size) && defined(wippersnapper_uart_UARTAdded_size) && defined(wippersnapper_uart_UARTEvent_size) && defined(wippersnapper_i2c_I2cDeviceEvent_size) union wippersnapper_signal_DeviceToBroker_payload_size_union {char f10[(6 + wippersnapper_digitalio_DigitalIOEvent_size)]; char f20[(7 + wippersnapper_analogio_AnalogIOEvent_size)]; char f80[(7 + wippersnapper_ds18x20_Ds18x20Event_size)]; char f90[(7 + wippersnapper_uart_UARTAdded_size)]; char f100[(7 + wippersnapper_uart_UARTEvent_size)]; char f113[(7 + wippersnapper_i2c_I2cDeviceEvent_size)]; char f0[6246];}; diff --git a/src/protos/uart.pb.c b/src/protos/uart.pb.c index 827e9c1d6..435d0c1f2 100644 --- a/src/protos/uart.pb.c +++ b/src/protos/uart.pb.c @@ -22,3 +22,4 @@ PB_BIND(wippersnapper_uart_UARTEvent, wippersnapper_uart_UARTEvent, AUTO) + diff --git a/src/protos/uart.pb.h b/src/protos/uart.pb.h index 6c4e07eaa..e8ec44f22 100644 --- a/src/protos/uart.pb.h +++ b/src/protos/uart.pb.h @@ -10,46 +10,78 @@ #error Regenerate this file with the current version of nanopb generator. #endif +/* Enum definitions */ +/* * + SerialConfig contains the configuration (data, parity, and stop bits) for a serial bus. */ +typedef enum _wippersnapper_uart_SerialConfig { + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_UNSPECIFIED = 0, /* Config was not specified by IO. */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_8N1 = 1, /* 8 data bits, no parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_5N1 = 2, /* 5 data bits, no parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_6N1 = 3, /* 6 data bits, no parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_7N1 = 4, /* 7 data bits, no parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_5N2 = 5, /* 5 data bits, no parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_6N2 = 6, /* 6 data bits, no parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_7N2 = 7, /* 7 data bits, no parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_8N2 = 8, /* 8 data bits, no parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_5E1 = 9, /* 5 data bits, even parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_6E1 = 10, /* 6 data bits, even parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_7E1 = 11, /* 7 data bits, even parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_8E1 = 12, /* 8 data bits, even parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_5E2 = 13, /* 5 data bits, even parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_6E2 = 14, /* 6 data bits, even parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_7E2 = 15, /* 7 data bits, even parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_8E2 = 16, /* 8 data bits, even parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_5O1 = 17, /* 5 data bits, odd parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_6O1 = 18, /* 6 data bits, odd parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_7O1 = 19, /* 7 data bits, odd parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_8O1 = 20, /* 8 data bits, odd parity, 1 stop bit */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_5O2 = 21, /* 5 data bits, odd parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_6O2 = 22, /* 6 data bits, odd parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_7O2 = 23, /* 7 data bits, odd parity, 2 stop bits */ + wippersnapper_uart_SerialConfig_SERIAL_CONFIG_8O2 = 24 /* 8 data bits, odd parity, 2 stop bits */ +} wippersnapper_uart_SerialConfig; + /* Struct definitions */ /* * UARTBusData represents a message to configure a UART bus for communication with a device. NOTE: This message is never sent directly, it is packed inside UARTAdd. */ typedef struct _wippersnapper_uart_UARTBusData { - int32_t baudrate; /* * The baudrate to use for UART communication (may be a common baud rate such as: -1200bps, 2400bps, 4800bps, 19200bps, 38400bps, 57600bps, or 115200bps). */ - char pin_rx[6]; /* * The pin on which to receive UART stream data. */ - char pin_tx[6]; /* * The pin on which to transmit UART stream data. */ - bool is_invert; /* * Inverts the UART signal on RX and TX pins. Defaults to False. */ + pb_callback_t bus_id; /* * The ID of the Serial bus (i.e: Serial, Serial1, "SoftwareSerial"). */ + uint32_t baud_rate; /* * The desired baudrate, in bits per second. */ + wippersnapper_uart_SerialConfig config; /* * Configures the data, parity, and stop bits. */ + pb_callback_t rx_pin; /* * Optional: The pin on which to receive on. */ + pb_callback_t tx_pin; /* * Optional: The pin on which to transmit with. */ + bool invert; /* * Optional: Inverts the UART signal on RX and TX pins. Defaults to False. */ + float timeout; /* * Optional: The timeout, in milliseconds, for the UART bus. */ } wippersnapper_uart_UARTBusData; /* * UARTAdd represents a message sent from IO to a device - to configure the UART bus (if not already configured) and attach a device. */ + to configure a UART bus for communication with a driver. */ typedef struct _wippersnapper_uart_UARTAdd { - bool has_bus_info; - wippersnapper_uart_UARTBusData bus_info; /* * The UART bus configuration. */ - pb_callback_t device_id; /* * The unique identifier of the device to attach to the UART bus, from Adafruit_WipperSnapper_Components. */ - int32_t polling_interval; /* * The polling interval, in milliseconds, to use for the device. */ + bool has_config; + wippersnapper_uart_UARTBusData config; /* * The UART bus configuration. */ + pb_callback_t driver; /* * The unique identifier of the UART driver. */ } wippersnapper_uart_UARTAdd; /* * UARTAdded represents a message sent from a device to IO to confirm that a device has been attached to the UART bus. */ typedef struct _wippersnapper_uart_UARTAdded { - pb_callback_t device_id; /* * The unique identifier of the device to attach to the UART bus, from Adafruit_WipperSnapper_Components. */ - bool is_success; /* * True if the UARTInit was successful, False otherwise. */ + pb_callback_t driver; /* * The unique identifier of the UART driver. */ + bool success; /* * True if the UART bus was successfully initialized, False otherwise. */ } wippersnapper_uart_UARTAdded; /* UARTRemove represents a message sent from IO to a device - to detach a device from the UART bus. */ + to detach a driver from the UART bus and deinitialize the bus. */ typedef struct _wippersnapper_uart_UARTRemove { - pb_callback_t device_id; /* * The unique identifier of the device to detach from the UART bus. */ + pb_callback_t driver; /* * The unique identifier of the UART driver. */ } wippersnapper_uart_UARTRemove; /* * UARTEvent represents incoming data from a UART sensor. */ typedef struct _wippersnapper_uart_UARTEvent { - pb_callback_t device_id; /* * Unique identifier of the device to attach to the UART bus, from Adafruit_WipperSnapper_Components. */ + pb_callback_t driver; /* * The unique identifier of the UART driver. */ pb_callback_t sensor_events; /* * An optionally repeated event from a sensor. */ } wippersnapper_uart_UARTEvent; @@ -58,62 +90,78 @@ typedef struct _wippersnapper_uart_UARTEvent { extern "C" { #endif +/* Helper constants for enums */ +#define _wippersnapper_uart_SerialConfig_MIN wippersnapper_uart_SerialConfig_SERIAL_CONFIG_UNSPECIFIED +#define _wippersnapper_uart_SerialConfig_MAX wippersnapper_uart_SerialConfig_SERIAL_CONFIG_8O2 +#define _wippersnapper_uart_SerialConfig_ARRAYSIZE ((wippersnapper_uart_SerialConfig)(wippersnapper_uart_SerialConfig_SERIAL_CONFIG_8O2+1)) + +#define wippersnapper_uart_UARTBusData_config_ENUMTYPE wippersnapper_uart_SerialConfig + + + + + + /* Initializer values for message structs */ -#define wippersnapper_uart_UARTBusData_init_default {0, "", "", 0} -#define wippersnapper_uart_UARTAdd_init_default {false, wippersnapper_uart_UARTBusData_init_default, {{NULL}, NULL}, 0} +#define wippersnapper_uart_UARTBusData_init_default {{{NULL}, NULL}, 0, _wippersnapper_uart_SerialConfig_MIN, {{NULL}, NULL}, {{NULL}, NULL}, 0, 0} +#define wippersnapper_uart_UARTAdd_init_default {false, wippersnapper_uart_UARTBusData_init_default, {{NULL}, NULL}} #define wippersnapper_uart_UARTAdded_init_default {{{NULL}, NULL}, 0} #define wippersnapper_uart_UARTRemove_init_default {{{NULL}, NULL}} #define wippersnapper_uart_UARTEvent_init_default {{{NULL}, NULL}, {{NULL}, NULL}} -#define wippersnapper_uart_UARTBusData_init_zero {0, "", "", 0} -#define wippersnapper_uart_UARTAdd_init_zero {false, wippersnapper_uart_UARTBusData_init_zero, {{NULL}, NULL}, 0} +#define wippersnapper_uart_UARTBusData_init_zero {{{NULL}, NULL}, 0, _wippersnapper_uart_SerialConfig_MIN, {{NULL}, NULL}, {{NULL}, NULL}, 0, 0} +#define wippersnapper_uart_UARTAdd_init_zero {false, wippersnapper_uart_UARTBusData_init_zero, {{NULL}, NULL}} #define wippersnapper_uart_UARTAdded_init_zero {{{NULL}, NULL}, 0} #define wippersnapper_uart_UARTRemove_init_zero {{{NULL}, NULL}} #define wippersnapper_uart_UARTEvent_init_zero {{{NULL}, NULL}, {{NULL}, NULL}} /* Field tags (for use in manual encoding/decoding) */ -#define wippersnapper_uart_UARTBusData_baudrate_tag 1 -#define wippersnapper_uart_UARTBusData_pin_rx_tag 2 -#define wippersnapper_uart_UARTBusData_pin_tx_tag 3 -#define wippersnapper_uart_UARTBusData_is_invert_tag 4 -#define wippersnapper_uart_UARTAdd_bus_info_tag 1 -#define wippersnapper_uart_UARTAdd_device_id_tag 2 -#define wippersnapper_uart_UARTAdd_polling_interval_tag 3 -#define wippersnapper_uart_UARTAdded_device_id_tag 1 -#define wippersnapper_uart_UARTAdded_is_success_tag 2 -#define wippersnapper_uart_UARTRemove_device_id_tag 1 -#define wippersnapper_uart_UARTEvent_device_id_tag 1 +#define wippersnapper_uart_UARTBusData_bus_id_tag 1 +#define wippersnapper_uart_UARTBusData_baud_rate_tag 2 +#define wippersnapper_uart_UARTBusData_config_tag 3 +#define wippersnapper_uart_UARTBusData_rx_pin_tag 4 +#define wippersnapper_uart_UARTBusData_tx_pin_tag 5 +#define wippersnapper_uart_UARTBusData_invert_tag 6 +#define wippersnapper_uart_UARTBusData_timeout_tag 7 +#define wippersnapper_uart_UARTAdd_config_tag 1 +#define wippersnapper_uart_UARTAdd_driver_tag 2 +#define wippersnapper_uart_UARTAdded_driver_tag 1 +#define wippersnapper_uart_UARTAdded_success_tag 2 +#define wippersnapper_uart_UARTRemove_driver_tag 1 +#define wippersnapper_uart_UARTEvent_driver_tag 1 #define wippersnapper_uart_UARTEvent_sensor_events_tag 2 /* Struct field encoding specification for nanopb */ #define wippersnapper_uart_UARTBusData_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, baudrate, 1) \ -X(a, STATIC, SINGULAR, STRING, pin_rx, 2) \ -X(a, STATIC, SINGULAR, STRING, pin_tx, 3) \ -X(a, STATIC, SINGULAR, BOOL, is_invert, 4) -#define wippersnapper_uart_UARTBusData_CALLBACK NULL +X(a, CALLBACK, SINGULAR, STRING, bus_id, 1) \ +X(a, STATIC, SINGULAR, UINT32, baud_rate, 2) \ +X(a, STATIC, SINGULAR, UENUM, config, 3) \ +X(a, CALLBACK, SINGULAR, STRING, rx_pin, 4) \ +X(a, CALLBACK, SINGULAR, STRING, tx_pin, 5) \ +X(a, STATIC, SINGULAR, BOOL, invert, 6) \ +X(a, STATIC, SINGULAR, FLOAT, timeout, 7) +#define wippersnapper_uart_UARTBusData_CALLBACK pb_default_field_callback #define wippersnapper_uart_UARTBusData_DEFAULT NULL #define wippersnapper_uart_UARTAdd_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, bus_info, 1) \ -X(a, CALLBACK, SINGULAR, STRING, device_id, 2) \ -X(a, STATIC, SINGULAR, INT32, polling_interval, 3) +X(a, STATIC, OPTIONAL, MESSAGE, config, 1) \ +X(a, CALLBACK, SINGULAR, STRING, driver, 2) #define wippersnapper_uart_UARTAdd_CALLBACK pb_default_field_callback #define wippersnapper_uart_UARTAdd_DEFAULT NULL -#define wippersnapper_uart_UARTAdd_bus_info_MSGTYPE wippersnapper_uart_UARTBusData +#define wippersnapper_uart_UARTAdd_config_MSGTYPE wippersnapper_uart_UARTBusData #define wippersnapper_uart_UARTAdded_FIELDLIST(X, a) \ -X(a, CALLBACK, SINGULAR, STRING, device_id, 1) \ -X(a, STATIC, SINGULAR, BOOL, is_success, 2) +X(a, CALLBACK, SINGULAR, STRING, driver, 1) \ +X(a, STATIC, SINGULAR, BOOL, success, 2) #define wippersnapper_uart_UARTAdded_CALLBACK pb_default_field_callback #define wippersnapper_uart_UARTAdded_DEFAULT NULL #define wippersnapper_uart_UARTRemove_FIELDLIST(X, a) \ -X(a, CALLBACK, SINGULAR, STRING, device_id, 1) +X(a, CALLBACK, SINGULAR, STRING, driver, 1) #define wippersnapper_uart_UARTRemove_CALLBACK pb_default_field_callback #define wippersnapper_uart_UARTRemove_DEFAULT NULL #define wippersnapper_uart_UARTEvent_FIELDLIST(X, a) \ -X(a, CALLBACK, SINGULAR, STRING, device_id, 1) \ +X(a, CALLBACK, SINGULAR, STRING, driver, 1) \ X(a, CALLBACK, REPEATED, MESSAGE, sensor_events, 2) #define wippersnapper_uart_UARTEvent_CALLBACK pb_default_field_callback #define wippersnapper_uart_UARTEvent_DEFAULT NULL @@ -133,12 +181,11 @@ extern const pb_msgdesc_t wippersnapper_uart_UARTEvent_msg; #define wippersnapper_uart_UARTEvent_fields &wippersnapper_uart_UARTEvent_msg /* Maximum encoded size of messages (where known) */ +/* wippersnapper_uart_UARTBusData_size depends on runtime parameters */ /* wippersnapper_uart_UARTAdd_size depends on runtime parameters */ /* wippersnapper_uart_UARTAdded_size depends on runtime parameters */ /* wippersnapper_uart_UARTRemove_size depends on runtime parameters */ /* wippersnapper_uart_UARTEvent_size depends on runtime parameters */ -#define WIPPERSNAPPER_UART_UART_PB_H_MAX_SIZE wippersnapper_uart_UARTBusData_size -#define wippersnapper_uart_UARTBusData_size 27 #ifdef __cplusplus } /* extern "C" */