Skip to content

Conversation

@nehalkpatel
Copy link
Owner

This commit adds a complete I2C driver implementation following the same patterns used for Pin and UART drivers. The implementation includes:

C++ Changes:

  • Added I2C message types (I2CEmulatorRequest/Response) to support Send and Receive operations with I2C device addresses
  • Updated HostI2CController to use ZMQ transport instead of local buffers
  • Added JSON encoding/decoding support for I2C messages
  • Integrated I2C controller into HostBoard with proper transport wiring
  • I2C operations are synchronous and always initiated by the application

Python Emulator Changes:

  • Added I2C class to emulate I2C peripherals at different addresses
  • Implemented device buffer storage per I2C address (address -> bytearray)
  • Added Send/Receive operation handlers in the emulator message loop
  • Provided helper methods for testing (write_to_device, read_from_device)

Key Design Decisions:

  • I2C uses int error codes (as defined in i2c.hpp interface) instead of common::Error, with a helper function to convert between them
  • All I2C operations are blocking and synchronous
  • Data buffers are maintained per I2C address (up to 256 bytes each)
  • Interrupt and DMA variants delegate to blocking implementations for now

The implementation enables I2C communication testing through the host emulation environment without requiring actual hardware.

This commit adds a complete I2C driver implementation following the same
patterns used for Pin and UART drivers. The implementation includes:

C++ Changes:
- Added I2C message types (I2CEmulatorRequest/Response) to support Send
  and Receive operations with I2C device addresses
- Updated HostI2CController to use ZMQ transport instead of local buffers
- Added JSON encoding/decoding support for I2C messages
- Integrated I2C controller into HostBoard with proper transport wiring
- I2C operations are synchronous and always initiated by the application

Python Emulator Changes:
- Added I2C class to emulate I2C peripherals at different addresses
- Implemented device buffer storage per I2C address (address -> bytearray)
- Added Send/Receive operation handlers in the emulator message loop
- Provided helper methods for testing (write_to_device, read_from_device)

Key Design Decisions:
- I2C uses int error codes (as defined in i2c.hpp interface) instead of
  common::Error, with a helper function to convert between them
- All I2C operations are blocking and synchronous
- Data buffers are maintained per I2C address (up to 256 bytes each)
- Interrupt and DMA variants delegate to blocking implementations for now

The implementation enables I2C communication testing through the host
emulation environment without requiring actual hardware.
Created comprehensive unit tests for HostI2CController following the same
pattern as the existing UART tests. The tests cover:

- Basic Send/Receive operations
- Multiple I2C device addresses
- Partial data reception
- Receive from uninitialized devices
- Interrupt-based operations (SendDataInterrupt, ReceiveDataInterrupt)
- DMA-based operations (SendDataDma, ReceiveDataDma)

The test fixture sets up a ZMQ-based emulator that simulates I2C device
buffers, allowing thorough testing of the I2C driver without hardware.

Test coverage includes:
- HostI2CTest.SendData
- HostI2CTest.SendReceiveData
- HostI2CTest.MultipleAddresses
- HostI2CTest.ReceiveWithoutSend
- HostI2CTest.ReceivePartialData
- HostI2CTest.SendDataInterrupt
- HostI2CTest.ReceiveDataInterrupt
- HostI2CTest.SendDataDma
- HostI2CTest.ReceiveDataDma
Lambdas with captures cannot be converted to function pointers, which was
causing compilation errors in the unit tests. Changed the I2C interface to
use std::function instead, matching the pattern used in UART.

This allows tests to use lambdas with captures for callback verification.
Created a complete I2C test application that demonstrates I2C driver usage
and comprehensive Python integration tests.

C++ Application (i2c_test):
- Writes a test pattern (0xDE, 0xAD, 0xBE, 0xEF) to I2C device at 0x50
- Reads the data back and verifies it matches
- Toggles LED1 when data verification succeeds
- Toggles LED2 as a heartbeat indicator
- Handles write/read errors gracefully

Python Integration Tests (test_i2c_test.py):
- test_i2c_test_starts: Verifies app starts successfully
- test_i2c_test_write_read_cycle: Validates I2C write/read operations
- test_i2c_test_toggles_leds: Checks LED toggling behavior
- test_i2c_test_data_mismatch: Tests error handling with wrong data

Updated conftest.py to add i2c_test fixture with --i2c-test CLI option.

The tests use the Python emulator's I2C device buffer simulation to
verify correct I2C communication without requiring hardware.
Changed all references from i2c_test to i2c_demo:
- Renamed src/apps/i2c_test/ directory to src/apps/i2c_demo/
- Renamed source files: i2c_test.hpp/cpp to i2c_demo.hpp/cpp
- Updated class name from I2CTest to I2CDemo
- Renamed test file: test_i2c_test.py to test_i2c_demo.py
- Updated pytest fixture from i2c_test to i2c_demo
- Updated CLI option from --i2c-test to --i2c-demo
- Updated all CMakeLists.txt references
- Implemented ToggleLed() helper function to encapsulate LED toggling
- Replaced manual data comparison loop with std::ranges::equal
- Reduced cognitive complexity from 27 to below threshold of 25
@nehalkpatel nehalkpatel force-pushed the claude/implement-i2c-driver-01D2T8eb5rweSwTxmeqB371A branch 3 times, most recently from df293f5 to 3c30697 Compare November 25, 2025 05:05
- Added Toggle() as a virtual method in OutputPin class
- Implemented Toggle() in HostPin (reads current state, sets opposite)
- Updated i2c_demo to use led.Toggle() instead of helper function
- Removed ToggleLed() helper from I2CDemo class
- This is a more appropriate design as toggle is a pin operation
@nehalkpatel nehalkpatel force-pushed the claude/implement-i2c-driver-01D2T8eb5rweSwTxmeqB371A branch from 3c30697 to 96be525 Compare November 25, 2025 05:40
@nehalkpatel nehalkpatel merged commit 499242e into main Nov 25, 2025
1 check passed
@nehalkpatel nehalkpatel deleted the claude/implement-i2c-driver-01D2T8eb5rweSwTxmeqB371A branch November 25, 2025 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants