extern crate clerk; extern crate itertools; use std::cell::RefCell; use std::collections::VecDeque; use clerk::{DefaultLines, Delay, Display, DisplayControlBuilder, EntryModeBuilder, FunctionSetBuilder, SeekFrom, ShiftTo, Send, Receive, Init, WriteMode, ReadMode}; struct ConnectionMock { init_calls: RefCell, send_bytes: RefCell>, receivable_bytes: RefCell>, } impl Default for ConnectionMock { fn default() -> Self { ConnectionMock { init_calls: RefCell::new(0), send_bytes: RefCell::new(vec![]), receivable_bytes: RefCell::new(VecDeque::new()), } } } impl ConnectionMock { fn set_read_value(&self, value: u8) { self.receivable_bytes.borrow_mut().push_back(value) } } impl Init for ConnectionMock { fn init(&self) { let mut init_calls = self.init_calls.borrow_mut(); *init_calls += 1; } } impl Send for ConnectionMock { fn send(&self, mode: WriteMode) { let mut send_bytes = self.send_bytes.borrow_mut(); send_bytes.push(mode); } } impl Receive for ConnectionMock { fn receive(&self, _: ReadMode) -> u8 { self.receivable_bytes.borrow_mut().pop_front().unwrap() } } pub struct CustomDelayMock; impl Delay for CustomDelayMock { fn delay_ns(_: u16) { // mhh } } fn setup_display() -> Display { Display::new(ConnectionMock::default()) } #[test] fn init() { let lcd = setup_display(); lcd.init(&FunctionSetBuilder::default()); let connection = lcd.get_connection(); let init_calls = connection.init_calls.borrow_mut(); assert_eq!(*init_calls, 1); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0x33)); assert_eq!(send_bytes[1], WriteMode::Command(0x32)); assert_eq!(send_bytes[2], WriteMode::Command(0x20)); assert_eq!(send_bytes[3], WriteMode::Command(0x01)); } #[test] fn set_entry_mode() { let lcd = setup_display(); lcd.set_entry_mode(&EntryModeBuilder::default()); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0000_0110)); } #[test] fn test_set_display_control() { let lcd = setup_display(); lcd.set_display_control(&DisplayControlBuilder::default()); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0000_1100)); } #[test] fn test_shift_cursor_left() { let mut lcd = setup_display(); lcd.shift_cursor(ShiftTo::Left(1)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0000)); } #[test] fn test_shift_cursor_left_with_zero_offset() { let mut lcd = setup_display(); lcd.shift_cursor(ShiftTo::Left(0)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes.len(), 0); } #[test] fn test_shift_cursor_right() { let mut lcd = setup_display(); lcd.shift_cursor(ShiftTo::Right(1)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0100)); } #[test] fn test_shift_cursor_right_multiple() { let mut lcd = setup_display(); lcd.shift_cursor(ShiftTo::Right(2)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0001_0100)); assert_eq!(send_bytes[1], WriteMode::Command(0b0001_0100)); } #[test] fn test_shift_cursor_right_with_zero_offset() { let mut lcd = setup_display(); lcd.shift_cursor(ShiftTo::Right(0)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes.len(), 0); } #[test] fn test_shift_left() { let lcd = setup_display(); lcd.shift(ShiftTo::Left(1)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0001_1000)); } #[test] fn test_shift_right() { let lcd = setup_display(); lcd.shift(ShiftTo::Right(1)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0001_1100)); } #[test] fn test_clear() { let lcd = setup_display(); lcd.clear(); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0x01)); } #[test] fn test_seek_from_home() { let mut lcd = setup_display(); lcd.seek(SeekFrom::Home(3)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0011)); } #[test] fn test_seek_from_current() { let mut lcd = setup_display(); lcd.seek(SeekFrom::Home(2)); lcd.seek(SeekFrom::Current(1)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0010)); assert_eq!(send_bytes[1], WriteMode::Command(0b1000_0011)); } #[test] fn test_seek_from_line() { let mut lcd = setup_display(); lcd.seek(SeekFrom::Line { line: DefaultLines::Two, bytes: 3, }); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b1100_0011)); } #[test] fn test_seek_cgram_from_home() { let mut lcd = setup_display(); lcd.seek_cgram(SeekFrom::Home(3)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0011)); } #[test] fn test_seek_cgram_from_current() { let mut lcd = setup_display(); lcd.seek_cgram(SeekFrom::Home(2)); lcd.seek_cgram(SeekFrom::Current(1)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0010)); assert_eq!(send_bytes[1], WriteMode::Command(0b0100_0011)); } #[test] #[ignore] // TODO: needs clarification: line does not make sense here, For 5×8 dots, eight character // patterns can be written, and for 5×10 dots, four character patterns can be written fn test_seek_cgram_from_line() { let mut lcd = setup_display(); lcd.seek_cgram(SeekFrom::Home(2)); lcd.seek_cgram(SeekFrom::Current(1)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b0100_0010)); assert_eq!(send_bytes[1], WriteMode::Command(0b0100_0011)); } #[test] fn test_write() { let mut lcd = setup_display(); lcd.write(123); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Data(123)); } #[test] fn test_write_updates_address_counter() { let mut lcd = setup_display(); lcd.seek(SeekFrom::Home(0)); lcd.write(12); lcd.write(34); lcd.seek(SeekFrom::Current(0)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[3], WriteMode::Command(0b1000_0010)); } #[test] fn test_write_message() { let mut lcd = setup_display(); lcd.write_message("Hi"); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Data(b'H')); assert_eq!(send_bytes[1], WriteMode::Data(b'i')); } #[test] fn test_write_message_increments_address_counter() { let mut lcd = setup_display(); lcd.write_message("Hi"); lcd.seek(SeekFrom::Current(0)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[2], WriteMode::Command(0b1000_0010)); } #[test] fn test_read() { let expected = 42; let connection = ConnectionMock::default(); connection.set_read_value(expected); let mut lcd: Display = Display::new(connection); let input = lcd.read_byte(); assert_eq!(input, expected); } #[test] fn test_read_increments_address_counter() { let connection = ConnectionMock::default(); connection.set_read_value(4); connection.set_read_value(2); let mut lcd: Display = Display::new(connection); lcd.read_byte(); lcd.seek(SeekFrom::Current(0)); lcd.read_byte(); lcd.seek(SeekFrom::Current(0)); let connection = lcd.get_connection(); let send_bytes = connection.send_bytes.borrow_mut(); assert_eq!(send_bytes[0], WriteMode::Command(0b1000_0001)); assert_eq!(send_bytes[1], WriteMode::Command(0b1000_0010)); }