lcd1602rs 0.3.0

A tiny package to write to a LCD1602 via I2C (e.g. on a Raspberry Pi)
Documentation
extern "C" {
    // LCD 1602

    // Opens a file system handle to the I2C device
    // Turns on the LCD, sets the 4-bit mode and clears the memory
    // Returns 0 for success, 1 for failure
    fn lcd1602Init(iChannel: i32, iAddr: i32) -> i32;

    // Set the cursor position on the LCD
    fn lcd1602SetCursor(x: i32, y: i32) -> i32;

    // Control the backlight, cursor, and blink
    fn lcd1602Control(bBacklight: i32, bCursor: i32, bBlink: i32) -> i32;

    // Print a zero-terminated character string
    // Only 1 line at a time can be accessed
    fn lcd1602WriteString(szText: *const std::ffi::c_char) -> i32;

    // Clear the characters from the LCD
    fn lcd1602Clear() -> i32;

    // Turn off the LCD and backlight
    // close the I2C file handle
    fn lcd1602Shutdown();


    // LCD 2004

    // Opens a file system handle to the I2C device
    // Turns on the LCD, sets the 4-bit mode and clears the memory
    // Returns 0 for success, 1 for failure
    fn lcd2004Init(iChannel: i32, iAddr: i32) -> i32;

    // Set the cursor position on the LCD
    fn lcd2004SetCursor(x: i32, y: i32) -> i32;

    // Control the backlight, cursor, and blink
    fn lcd2004Control(bBacklight: i32, bCursor: i32, bBlink: i32) -> i32;

    // Print a zero-terminated character string
    // Only 1 line at a time can be accessed
    fn lcd2004WriteString(szText: *const std::ffi::c_char) -> i32;

    // Clear the characters from the LCD
    fn lcd2004Clear() -> i32;

    // Turn off the LCD and backlight
    // close the I2C file handle
    fn lcd2004Shutdown();
}

pub trait Lcd {
    fn new(channel: i32, addr: i32) -> Option<Self>
        where Self: Sized;

    fn set_cursor(&self, x: i32, y: i32);

    fn control(&self, backlight: bool, cursor: bool, blink: bool);

    fn write(&self, text: &str);

    fn clear(&self);

    fn lines() -> i32;

    fn columns() -> i32;
}

pub struct Lcd1602 {}

impl Lcd for Lcd1602 {
    fn new(channel: i32, addr: i32) -> Option<Lcd1602> {
        let result = unsafe {
            lcd1602Init(channel, addr)
        };
        match result {
            0 => Some(Lcd1602 {}),
            _ => None
        }
    }

    fn set_cursor(&self, x: i32, y: i32) {
        unsafe {
            lcd1602SetCursor(x, y);
        }
    }

    fn control(&self, backlight: bool, cursor: bool, blink: bool) {
        unsafe {
            lcd1602Control(if backlight {1} else {0}, if cursor {1} else {0}, if blink {1} else {0});
        }
    }

    fn write(&self, text: &str) {
        let cstr = std::ffi::CString::new(text.chars().map(|c| {
            // '\' and '~' are not available
            if c >= ' ' && c < '~' && c != '\\' {
                return c as u8
            }

            match c {
                '¥' => 0x5C,

                '' => 0x7E,
                '' => 0x7F,

                '°' => 0xDF,

                'α' => 0xE0,
                'ä' | 'Ä' => 0xE1,
                'β' | 'ß' | '' => 0xE2,
                'ε' => 0xE3,
                'μ' => 0xE4,
                'σ' => 0xE5,
                'ρ' => 0xE6,
                '' => 0xE8,
                'ö' | 'Ö' => 0xEF,

                'θ' => 0xF2,
                'Ω' => 0xF3,
                '' => 0xF4,
                'ü' | 'Ü' => 0xF5,
                'Σ' | '' => 0xF6,
                'π' => 0xF7,
                '÷' => 0xFD,

                _ => 0xDB // use box as default for unprintable characters
            }
        }).collect::<Vec<u8>>()).expect("CString::new failed");
        let ptr = cstr.into_raw();

        unsafe {
            lcd1602WriteString(ptr);

            // retake pointer to free memory
            let _ = std::ffi::CString::from_raw(ptr);
        }
    }

    fn clear(&self) {
        unsafe {
            lcd1602Clear();
        }
    }

    fn lines() -> i32 {2}
    fn columns() -> i32 {16}
}

impl Drop for Lcd1602 {
    fn drop(&mut self) {
        unsafe {
            lcd1602Shutdown();
        }
    }
}

pub struct Lcd2004 {}

impl Lcd for Lcd2004 {
    fn new(channel: i32, addr: i32) -> Option<Lcd2004> {
        let result = unsafe {
            lcd2004Init(channel, addr)
        };
        match result {
            0 => Some(Lcd2004 {}),
            _ => None
        }
    }

    fn set_cursor(&self, x: i32, y: i32) {
        unsafe {
            lcd2004SetCursor(x, y);
        }
    }

    fn control(&self, backlight: bool, cursor: bool, blink: bool) {
        unsafe {
            lcd2004Control(if backlight {1} else {0}, if cursor {1} else {0}, if blink {1} else {0});
        }
    }

    fn write(&self, text: &str) {
        let cstr = std::ffi::CString::new(text.chars().map(|c| {
            // '\' and '~' are not available
            if c >= ' ' && c < '~' && c != '\\' {
                return c as u8
            }

            match c {
                '¥' => 0x5C,

                '' => 0x7E,
                '' => 0x7F,

                '°' => 0xDF,

                'α' => 0xE0,
                'ä' | 'Ä' => 0xE1,
                'β' | 'ß' | '' => 0xE2,
                'ε' => 0xE3,
                'μ' => 0xE4,
                'σ' => 0xE5,
                'ρ' => 0xE6,
                '' => 0xE8,
                'ö' | 'Ö' => 0xEF,

                'θ' => 0xF2,
                'Ω' => 0xF3,
                '' => 0xF4,
                'ü' | 'Ü' => 0xF5,
                'Σ' | '' => 0xF6,
                'π' => 0xF7,
                '÷' => 0xFD,

                _ => 0xDB // use box as default for unprintable characters
            }
        }).collect::<Vec<u8>>()).expect("CString::new failed");
        let ptr = cstr.into_raw();

        unsafe {
            lcd2004WriteString(ptr);

            // retake pointer to free memory
            let _ = std::ffi::CString::from_raw(ptr);
        }
    }

    fn clear(&self) {
        unsafe {
            lcd2004Clear();
        }
    }

    fn lines() -> i32 {4}
    fn columns() -> i32 {20}
}

impl Drop for Lcd2004 {
    fn drop(&mut self) {
        unsafe {
            lcd2004Shutdown();
        }
    }
}