Skip to main content

Overview

BaseConfig manages dynamic PCF8574 I/O expander configuration with intelligent channel distribution strategies, I2C scanning, and configuration validation.

Quick Start

#define ENABLE_ADDONS_AUTOLIGHT_V3
#include "Kinematrix.h"
using namespace AutoLight;

BaseConfig config;

void setup() {
  // Automatic distribution across 2 PCF8574s
  config.setDynamicConfig(12, 2);
  
  // Validate configuration
  if (config.validateConfiguration()) {
    Serial.println("Configuration valid!");
    config.printDistribution();
  }
}

Constructor

BaseConfig
constructor
Create BaseConfig instance

Initialization

initialize
void
Initialize configuration system
setConfigIndex
void
Set configuration index

Dynamic Configuration

Automatic channel distribution across PCF8574 expanders:
setDynamicConfig
void
Configure channels with automatic distribution

Distribution Strategies

typedef enum {
    DISTRIBUTE_BALANCED = 0,    // Even distribution across all PCFs
    DISTRIBUTE_SEQUENTIAL = 1,  // Fill PCFs sequentially
    DISTRIBUTE_OPTIMIZED = 2,   // Minimize PCF usage
    DISTRIBUTE_CUSTOM = 3       // Manual configuration
} distribution_strategy_t;

Examples

Balanced Distribution

config.setDynamicConfig(24, 3, DISTRIBUTE_BALANCED);
// Result: PCF1=8ch, PCF2=8ch, PCF3=8ch

Sequential Distribution

config.setDynamicConfig(20, 3, DISTRIBUTE_SEQUENTIAL);
// Result: PCF1=8ch, PCF2=8ch, PCF3=4ch

Optimized Distribution

config.setDynamicConfig(20, 5, DISTRIBUTE_OPTIMIZED);
// Result: Uses only 3 PCFs (20 channels)

Custom Configuration

setDynamicWithAddresses
void
Configure with specific addresses and channel counts
setCustomDistribution
void
Set fully custom PCF distribution

Custom Distribution Example

PCFDistribution custom[3] = {
    {0x27, 8, 0, 0, true},   // PCF at 0x27: channels 0-7
    {0x38, 8, 8, 0, true},   // PCF at 0x38: channels 8-15
    {0x45, 4, 16, 0, true}   // PCF at 0x45: channels 16-19
};
config.setCustomDistribution(custom, 3);

Manual Configuration

setSequence
void
Set channel sequence manually
setChannelPin
void
Set channel pin mapping
setAddress
void
Set PCF I2C addresses

EEPROM Operations

setChannel
void
Set and save channel count to EEPROM
readChannel
int
Read channel count from EEPROM
setVersion
void
Set configuration version
readVersion
int
Read configuration version

Getters

getConfigData
ConfigData*
Get configuration data pointer
getConfig
BaseConfig*
Get config instance
getConfigIndex
int
Get current config index
getChannel
int
Get total channel count
getVersion
int
Get configuration version
getIoSize
int
Get number of I/O expanders
getPinList
uint8_t*
Get pin mapping array
getCurrentDistribution
DynamicConfigData*
Get current distribution data

Validation

validateConfiguration
bool
Validate entire configuration
validateDistribution
bool
Validate PCF distribution
getOptimalPCFCount
uint8_t
Calculate optimal PCF count for channels

Debugging

printDistribution
void
Print PCF distribution to Serial
debugConfig
void
Print complete configuration debug info
cleanup
void
Free allocated resources

I2C Scanner

BaseConfig includes an I2C scanner class:
I2CScanner
class
Scan I2C bus for devices
I2CScanner scanner;
scanner.beginTransmission();
scanner.scanI2CAddress();  // Prints found devices
scanner.endTransmission();

PCFDistribution Structure

struct PCFDistribution {
    uint8_t address;         // I2C address (0x20-0x27)
    uint8_t used_pins;       // Number of allocated pins (1-8)
    uint8_t start_channel;   // Starting channel number
    uint8_t pin_offset;      // Pin offset within PCF
    bool is_active;          // PCF active status
};

ConfigData Structure

typedef struct {
    ConfigHeader header;  // Channel count, pin pointers, I2C addresses
    ConfigTable table;    // Address and version tables
} ConfigData;

Complete Example

#define ENABLE_ADDONS_AUTOLIGHT_V3
#include "Kinematrix.h"
using namespace AutoLight;

BaseConfig config;

void setup() {
  Serial.begin(115200);
  
  // Method 1: Simple auto-configuration
  config.setDynamicConfig(12);  // Auto-optimizes PCF count
  
  // Method 2: Specify PCF count and strategy
  config.setDynamicConfig(24, 3, DISTRIBUTE_BALANCED);
  
  // Method 3: Custom addresses and distribution
  uint8_t addresses[] = {0x27, 0x38, 0x45};
  uint8_t channels[] = {8, 8, 8};
  config.setDynamicWithAddresses(24, 3, addresses, channels);
  
  // Method 4: Full custom control
  PCFDistribution custom[2] = {
    {0x27, 6, 0, 0, true},
    {0x38, 6, 6, 0, true}
  };
  config.setCustomDistribution(custom, 2);
  
  // Validate and debug
  if (config.validateConfiguration()) {
    Serial.println("Configuration OK!");
    config.printDistribution();
  } else {
    Serial.println("Configuration error!");
  }
}

void loop() {
  // Configuration is static after setup
}

Best Practices

Auto Distribution

Use setDynamicConfig(channels) for automatic optimization

Validation

Always call validateConfiguration() before use

I2C Scan

Use I2CScanner to verify PCF addresses before configuration

Debug Output

Use printDistribution() to verify channel mapping

Platform Support

ESP32

Full support with hardware I2C

Build docs developers (and LLMs) love