sn3218-hal 0.2.0

Embedded Rust driver for SN3218 18-channel LED controller with gamma correction
Documentation
# SN3218 LED Driver

A Rust `embedded-hal` driver for the SN3218 6-channel LED driver chip, commonly used in the Raspberry Pi GFX HAT by Pimoroni.

## Overview

The SN3218 is an 18-channel LED driver with PWM control, arranged as 6 RGB channels. This driver provides a simple interface to control LED brightness with automatic gamma correction for smoother brightness transitions.

## Features

- **18-channel PWM control** (6 RGB LEDs)
- **Automatic gamma correction** for natural brightness curves
- **Simple API** for enabling/disabling outputs
- **Mask-based LED control** for selective channel enabling
- **Built on embedded-hal** for platform independence

## Hardware

This driver is designed for the SN3218 LED driver chip, which communicates over I2C at address `0x54`. It's commonly found on:

- Pimoroni GFX HAT
- Other SN3218-based LED boards

## Usage

Add this crate to your `Cargo.toml`:

```toml
[dependencies]
sn3218 = "0.2.0"
embedded-hal = "1.0"
```

### Basic Example

```rust
use sn3218::SN3218;
// Your I2C implementation
use your_hal::I2c;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let i2c = I2c::new(/* your I2C config */)?;
    let mut led_driver = SN3218::new(i2c);
    
    // Enable the output
    led_driver.enable()?;
    
    // Enable all LEDs (18 channels)
    led_driver.enable_leds(0x3FFFF)?; // All 18 bits set
    
    // Set LED values (18 channels: R,G,B for each of 6 LEDs)
    let led_values = [
        255, 0, 0,     // LED 0: Red
        0, 255, 0,     // LED 1: Green  
        0, 0, 255,     // LED 2: Blue
        255, 255, 0,   // LED 3: Yellow
        255, 0, 255,   // LED 4: Magenta
        0, 255, 255,   // LED 5: Cyan
    ];
    
    led_driver.output(&led_values)?;
    
    Ok(())
}
```

### Raspberry Pi Example

```rust
use sn3218::SN3218;
use rppal::i2c::I2c;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let i2c = I2c::new()?;
    let mut gfx_hat = SN3218::new(i2c);
    
    // Initialize
    gfx_hat.reset()?;
    gfx_hat.enable()?;
    
    // Create a rainbow effect
    let mut led_values = [0u8; 18];
    for i in 0..6 {
        let hue = i as f32 * 60.0; // 60 degrees apart
        let (r, g, b) = hsv_to_rgb(hue, 1.0, 1.0);
        led_values[i * 3] = (r * 255.0) as u8;
        led_values[i * 3 + 1] = (g * 255.0) as u8;
        led_values[i * 3 + 2] = (b * 255.0) as u8;
    }
    
    gfx_hat.enable_leds(0x3FFFF)?;
    gfx_hat.output(&led_values)?;
    
    Ok(())
}
```

## API Reference

### `SN3218<T: I2c>`

The main driver struct that wraps your I2C implementation.

#### Methods

- **`new(i2c: T) -> Self`**
  
  Creates a new SN3218 driver instance with automatic gamma correction table generation.

- **`enable(&mut self) -> Result<(), T::Error>`**
  
  Enables the LED driver output.

- **`disable(&mut self) -> Result<(), T::Error>`**
  
  Disables the LED driver output.

- **`reset(&mut self) -> Result<(), T::Error>`**
  
  Resets the LED driver to its default state.

- **`enable_leds(&mut self, mask: u32) -> Result<(), T::Error>`**
  
  Enables specific LED channels using a bitmask. Each bit corresponds to one of the 18 channels.
  
  Example: `0x3FFFF` enables all 18 channels, `0x07` enables only the first 3 channels.

- **`output(&mut self, values: &[u8]) -> Result<(), T::Error>`**
  
  Sets the PWM values for all 18 channels. The array must be exactly 18 elements long.
  Values are automatically gamma-corrected for natural brightness perception.

## Channel Mapping

The 18 channels are organized as 6 RGB LEDs:

| LED | Red Channel | Green Channel | Blue Channel |
|-----|------------|---------------|--------------|
| 0   | 0          | 1             | 2            |
| 1   | 3          | 4             | 5            |
| 2   | 6          | 7             | 8            |
| 3   | 9          | 10            | 11           |
| 4   | 12         | 13            | 14           |
| 5   | 15         | 16            | 17           |

## Gamma Correction

This driver automatically applies gamma correction to all output values using the formula:
```
corrected_value = 255^(input_value / 255)
```

This provides more natural brightness transitions, especially important for LED displays.

## Error Handling

All methods return `Result<(), T::Error>` where `T::Error` is the error type from your I2C implementation. Handle these appropriately for your platform.

## Platform Support

This crate works with any platform that implements the `embedded-hal` I2C traits, including:

- Raspberry Pi (via `rppal`)
- STM32 microcontrollers
- ESP32/ESP8266
- Arduino-compatible boards
- Linux-based systems

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request. This crate aims to provide a simple, safe interface to the SN3218 chip while maintaining compatibility with the embedded-hal ecosystem.

## References

- [SN3218 Datasheet]http://www.si-en.com/uploadfile/2017/0227/20170227110058_158.pdf
- [Pimoroni GFX HAT]https://shop.pimoroni.com/products/gfx-hat
- [Original Python Implementation]https://github.com/pimoroni/sn3218

## License

Licensed under either of

 * Apache License, Version 2.0
   ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license
   ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.