{"id":26115532,"url":"https://github.com/neurosity/ti-lp55231","last_synced_at":"2026-04-22T06:03:50.551Z","repository":{"id":198606207,"uuid":"701097405","full_name":"neurosity/ti-lp55231","owner":"neurosity","description":"Linux Rust driver for Texas Instruments LP55231.","archived":false,"fork":false,"pushed_at":"2023-10-06T03:50:21.000Z","size":24,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-19T14:38:44.703Z","etag":null,"topics":["embedded","hardware-support","lp55231"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neurosity.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-10-05T23:05:16.000Z","updated_at":"2025-04-15T20:04:47.000Z","dependencies_parsed_at":null,"dependency_job_id":"d9ea88cc-27bd-4371-85bc-2b5b7dad3f59","html_url":"https://github.com/neurosity/ti-lp55231","commit_stats":null,"previous_names":["neurosity/ti-lp55231"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/neurosity/ti-lp55231","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neurosity%2Fti-lp55231","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neurosity%2Fti-lp55231/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neurosity%2Fti-lp55231/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neurosity%2Fti-lp55231/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neurosity","download_url":"https://codeload.github.com/neurosity/ti-lp55231/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neurosity%2Fti-lp55231/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32123605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T00:31:26.853Z","status":"online","status_checked_at":"2026-04-22T02:00:05.693Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["embedded","hardware-support","lp55231"],"created_at":"2025-03-10T07:45:40.632Z","updated_at":"2026-04-22T06:03:50.546Z","avatar_url":"https://github.com/neurosity.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"LP55231 Linux Rust Driver\n-------------------------\n\n[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers\u0026message=Open\u0026color=blue\u0026logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/neurosity/ti-lp55231)\n\nLinux driver for [Texas Instruments LP55231](https://www.ti.com/product/LP55231),\na 9 channel RGB/White LED controller with internal program memory and integrated\ncharge Pump.\n\n**Features:**\n- Full implementation of I2C control interface in [datasheet](https://www.ti.com/lit/ds/symlink/lp55231.pdf)\n- Ergonomic API to leverage the [programming engine](#example-effect-blinking)\n- Easy to debug with optional features:\n    - [read-after-write checks](#read-after-write-verifications) to validate register writes\n    - [debug output](#debug-output) to see the value in a register before and after a write\n\n## Initialization, setup, and preparing animations\n\nThis example covers a typical initialization of the driver, preparing three\nLEDs (R, G, B) for animated effects.\n\n```rust\nuse ti_lp55231::{\n  Channel,\n  ChargePumpMode,\n  ClockSelection,\n  Direction,\n  Engine,\n  EngineExec,\n  EngineMode,\n  Instruction,\n  LP55231,\n  PreScale,\n}\n\n// Create the driver\nlet path = \"/dev/i2c-2\";\nlet i2c_addr = 0x32;\nlet ic = LP55231::create(path, i2c_addr)?;\n\n// Power and configure the driver.\nic.set_enabled(true)?;\nic.set_misc_settings(Misc {\n  auto_increment_enabled: true,\n  powersave_enabled: true,\n  charge_pump_mode: ChargePumpMode::Auto,\n  pwm_powersave_enabled: true,\n  clock_selection: ClockSelection::ForceInternal,\n})?;\n\n// Channel assignment.\nlet (r, g, b) = (Channel::D7, Channel::D1, Channel::D2);\n\n// Enable logarithmic brightness for a smoother ramp up effect.\nic.set_log_brightness(r, true)?;\nic.set_log_brightness(g, true)?;\nic.set_log_brightness(b, true)?;\n\n// Enable ratiometric dimming to preserve the ratio between the\n// RGB components of all mapped channels during animations\nic.set_ratiometric_dimming(r, true)?;\nic.set_ratiometric_dimming(g, true)?;\nic.set_ratiometric_dimming(b, true)?;\n\n// Set color to orange\nic.set_channel_pwm(r, 255)?;\nic.set_channel_pwm(g, 128)?;\nic.set_channel_pwm(b, 0)?;\n\n// Program the IC (see other example for implementations of `create_program`)\nlet instructions = create_program(\u0026[r, g, b])?;\nic.load_program(\u0026instructions)?;\n\n// Wait for the ENGINE_BUSY bit to clear,\n// indicating that all instructions have been loaded.\nic.wait_while_engine_busy(Duration::from_millis(10))?;\n\n// Set up one of the programming engines to Halt \u0026 Hold (ready to execute).\nlet engine = Engine::E1;\nic.set_engine_exec(engine, EngineExec::Hold)?;\nic.set_engine_mode(engine, EngineMode::Halt)?;\n\n// Run the effect\nic.set_engine_exec(engine, EngineExec::Free)?;\nic.set_engine_mode(engine, EngineMode::RunProgram)?;\n```\n\n## Example effect: blinking\n\nThis example is an implementation of `create_program` that prepares a blinking\neffect to run in an endless loop.\n\n```rust\nfn create_program(channels_to_control: \u0026[Channel]) -\u003e [Instruction; 8] {\n  [\n    // ----- LED-to-Engine mapping table\n    // 00. Map all target output channels to the programming engine for control.\n    Instruction::map_channels(channels_to_control),\n\n    // ----- blink effect start\n    // 01-02. Set LED mapping table start/end index + activation.\n    Instruction::mux_map_start(0),\n    Instruction::mux_ld_end(0),\n    // 03. Power all mapped LEDs off.\n    Instruction::set_pwm(0),\n    // 04. Wait ~0.5 seconds (15.625ms * 30).\n    Instruction::wait(PreScale::CT15_625, 30),\n    // 05. Set all LEDs to max brightness.\n    Instruction::set_pwm(255),\n    // 06. Wait ~0.5 seconds (15.625ms * 30).\n    Instruction::wait(PreScale::CT15_625, 30),\n    // 07. Loop back to beginning of blink effect index.\n    Instruction::branch(1, 0),\n  ]\n}\n```\n\n## Example effect: glow\n\n```rust\nfn create_program(channels_to_control: \u0026[Channel]) -\u003e [Instruction; 9] {\n  [\n    // ----- LED-to-Engine mapping table\n    // 00. Map all target output channels to the programming engine for control.\n    Instruction::map_channels(channels_to_control),\n\n    // ----- glow effect start\n    // 01-02. Set LED mapping table start/end index + activation.\n    Instruction::mux_map_start(0),\n    Instruction::mux_ld_end(0),\n    // 03. Quickly ramp up to max brightness.\n    Instruction::ramp(PreScale::CT0_488, 4, Direction::Up, 255),\n    // 04. Wait ~0.5 seconds (15.625ms * 30 = 468.75ms).\n    Instruction::wait(PreScale::CT15_625, 30),\n    // 05. Begin ramping brightness down to half (255 - 127 = 128).\n    Instruction::ramp(PreScale::CT15_625, 4, Direction::Down, 127),\n    // 06. Wait ~0.5 seconds (15.625ms * 30 = 468.75ms).\n    Instruction::wait(PreScale::CT15_625, 30),\n    // 07. Begin ramping brightness up to max (128 + 127 = 255).\n    Instruction::ramp(PreScale::CT15_625, 4, Direction::Up, 127),\n    // 08. Loop back to first step of effect.\n    Instruction::branch(1, 0),\n  ]\n}\n```\n\n## Switching between effects\n\nThe programming engine supports up to 96 instructions, which gives you plenty of\nroom to set up multiple effects. To switch between effects:\n\n- pause the programming engine\n- update the program counter to first index of next effect\n- unpause the programming engine.\n\nExample:\n\n```rust\n// Pause engine execution.\nic.set_engine_exec(Engine::E1, EngineExec::Hold)?;\nic.wait_while_engine_busy(Duration::from_millis(1))?;\n\n// Update the program counter to the starting instruction of the desired effect\n// This example assumes we're jumping to instruction 42, of the possible 96\n// programming memory addresses.\nic.set_engine_program_counter(Engine::E1, 42)?;\n\n// Unpause the engine and begin the new animation.\nic.set_engine_exec(Engine::E1, EngineExec::Free)?;\nic.set_engine_mode(Engine::E1, EngineMode::RunProgram)?;\n```\n\n# Debugging\n\n## Read-after-write verifications\n\nRead-after-write checks can be enabled with:\n\n```rust\nlet ic = LP55231::create(...)?;\nic.verify_writes = true;\n```\n\nThis will cause the driver to perform a read after every I2C write instruction\nto compare the value in the register. It will throw an exception if the read\nvalue does not match the written value.\n\n\u003e [!NOTE]\n\u003e This is useful during development, especially around using the programming\n\u003e engines which must be in the correct internal state in order to allow changes.\n\n## Debug output\n\nWhen enabled via `debug_enabled` property, the driver will emit useful (but\nrather verbose) output to help you understand the state of registers with every\nread and write operation. Example:\n\n```rust\nlet ic = LP55231::create(...)?;\nic.debug_enabled = true;\nic.set_enabled(true)?;\n```\n\nWill produce output:\n\n```\nset_enabled(true) {\n  00000000 \u003c\u003c 0x00 ENABLE_ENGINE_CNTRL1\n  00100000 \u003e\u003e 0x00 ENABLE_ENGINE_CNTRL1\n}\n```\n\n### Scoping debug output for multiple I2C calls\n\nScope for multiple debug calls can be combined with the `debug::scope!` macro:\n\n```rust\nfn multiple_i2c_calls(\n  ic: \u0026mut LP55231,\n  value: bool,\n) -\u003e Result\u003c(), LinuxI2CError\u003e {\n  debug::scope!(ic, \"example({})\", value);\n  ic.set_enabled(value)?;\n  ic.set_enabled(!value)?;\n  Ok(())\n}\n\nmultiple_i2_calls(true)?;\n```\n\nWould result in the following output:\n```\nexample(true) {\n  set_enabled(true) {\n    00000000 \u003c\u003c 0x00 ENABLE_ENGINE_CNTRL1\n    00100000 \u003e\u003e 0x00 ENABLE_ENGINE_CNTRL1\n  }\n  set_enabled(false) {\n    00100000 \u003c\u003c 0x00 ENABLE_ENGINE_CNTRL1\n    00000000 \u003e\u003e 0x00 ENABLE_ENGINE_CNTRL1\n  }\n}\n```\n\nSee [debug.rs](src/debug.rs) docs for more details.\n\n## Getting started with development\n\n1. Clone the project and open the folder in VS Code\n2. Accept plugin suggestions (dev container required in non-linux envs)\n3. Re-open in dev container\n\n\u003e [!NOTE]\n\u003e This project uses [hermit](https://cashapp.github.io/hermit/) to manage the\n\u003e Rust toolchain for this project. No prior installation of Rust required.\n\n## TODO\n\n- [ ] Read/write pages in blocks (`at_once` param in `read/write_program_page`)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneurosity%2Fti-lp55231","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneurosity%2Fti-lp55231","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneurosity%2Fti-lp55231/lists"}