{"id":24386062,"url":"https://github.com/recursiveerror/liquid_crystal","last_synced_at":"2026-03-12T22:31:05.081Z","repository":{"id":144684136,"uuid":"576802785","full_name":"RecursiveError/liquid_crystal","owner":"RecursiveError","description":"liquid crystal is a modular library for alphanumeric lcd displays compatible with the hd44780 controller, made in Rust with Embedded_hal API","archived":false,"fork":false,"pushed_at":"2024-04-13T19:00:20.000Z","size":71,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-14T08:39:26.552Z","etag":null,"topics":["embedded-hal","embedded-rust","embedded-systems","lcd-display","rust"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/liquid_crystal","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/RecursiveError.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"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}},"created_at":"2022-12-11T02:49:17.000Z","updated_at":"2024-04-11T20:20:58.000Z","dependencies_parsed_at":"2024-04-13T20:20:09.214Z","dependency_job_id":"c3d749df-0b13-4d8d-b03c-33dc8f54a609","html_url":"https://github.com/RecursiveError/liquid_crystal","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RecursiveError%2Fliquid_crystal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RecursiveError%2Fliquid_crystal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RecursiveError%2Fliquid_crystal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RecursiveError%2Fliquid_crystal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RecursiveError","download_url":"https://codeload.github.com/RecursiveError/liquid_crystal/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248333032,"owners_count":21086179,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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-hal","embedded-rust","embedded-systems","lcd-display","rust"],"created_at":"2025-01-19T11:30:46.980Z","updated_at":"2026-03-12T22:31:05.038Z","avatar_url":"https://github.com/RecursiveError.png","language":"Rust","readme":"\n# liquid_crystal\n\n\nliquid crystal is a modular library for alphanumeric lcd displays compatible with the hd44780 controller, made in Rust with Embedded_hal API\n\n## How to use\n\n#### first steps\n\nFirst you must choose a display communication interface, this library provides two built-in interfaces, parallel and I2C\n(you can create your own interfaces [see here](#creating-your-own-interface) )\n\nthen you must choose the number of bits in the communication, that can be: Bus4Bits or Bus8Bits\n\nfinally you must choose a Layout\n(you can create your own layout [see here](#layouts) )\n\n```rust\n    let mut lcd_interface = Parallel::new(D4, D5, D6, D7, rs, en, en2);\n    let mut lcd = LiquidCrystal::new(\u0026mut interface, Bus4Bits, LCD16X2);\n```\n(By default, the LCD implementation uses blocking delay,\nuse the `async` method to create an LCD with async support, remember to enable async in the library features)\n\n\nNot all interfaces support 8Bit communication, but all interfaces that support 8Bit can support 4Bit\n\n#### sending commands and text\n(this may change in the future, [see here](why-this-api) )\n\nfirst you must configure the display.\n\nfor this you must call the \"begin\" function.\n(you can configure directly with the low level \"send\" function, not recommended if you don't know how to configure the HD44780)\n\n```rust\n    lcd.begin(\u0026mut delay);\n```\n\n\nyou can send text and commands by the \"write\" function, this function receives a reference from a delay function and an Enum \"SendType\" which can be Text or Command\n\nto send a text, pass a \u0026str to the \"Text\" variant\n\nto send a command, pass a command from the [command list](#command-list) to the \"Command\" varient\n\n```rust\n    lcd.write(\u0026mut delay,Command(Clear))\n        .write(\u0026mut delay,Text(\"hello World!\"));\n```\n\nyou can send custom characters to variant \"CustomChar\", but first you need to create your custom character by function \"custom_char\", this function receives delay like all others, a reference to an array of u8 with size 8, and the slot that he will occupy\n\n- [how does custom characters work?](https://www.engineersgarage.com/making-custom-characters-on-lcd-using-arduino/)\n- [custom character generator](https://maxpromer.github.io/LCD-Character-Creator/)\n\nHD44780 allows you to create 8 custom characters (slot 0 - 7), you can create and modify these slots at any time, but only 8 different characters can be written at the same time on the display. (creating these characters returns the display to its initial position, then use \"set_cursor\" after creating these characters)\n\nto send use the CustomChar variant with the character slot:\n\n```rust\n    let lightning: [u8; 8] = [0x03, 0x06, 0x0C, 0x1F, 0x1F, 0x03, 0x06, 0x0C];\n\n    lcd.custom_char(\u0026mut delay, \u0026lightning, 0);\n    lcd.write(\u0026mut delay, CustomChar(0));\n```\n\n### Exemple\n[exemple/stm32f1xx/hello.rs](https://github.com/RecursiveError/liquid_crystal/blob/main/exemples/stm32f1xx/hello.rs)\n\n```rust\n#![no_std]\n#![no_main]\n\nuse panic_halt as _;\nuse cortex_m_rt::entry;\nuse stm32f1xx_hal::{pac, prelude::*};\nuse liquid_crystal::{prelude::*};\nuse liquid_crystal::Parallel;\n\n#[entry]\nfn main() -\u003e ! {\n\n    //Rust logo\n    let rust1: [u8; 8] = [0b00001,0b00011,0b00011,0b01110,0b11100,0b11000,0b01000,0b01000];\n    let rust2: [u8; 8] = [0b10001,0b11111,0b00000,0b00000,0b11110,0b10001,0b10001,0b11110];\n    let rust3: [u8; 8] = [0b10000,0b11000,0b11000,0b01110,0b00111,0b00011,0b00010,0b000010];\n\n    let rust4: [u8; 8] = [0b01000,0b01000,0b11000,0b11100,0b01110,0b00011,0b00011,0b00001];\n    let rust5: [u8; 8] = [0b11000,0b10100,0b10010,0b00000,0b00000,0b00000,0b11111,0b10001];\n    let rust6: [u8; 8] = [0b00010,0b00010,0b00011,0b00111,0b01110,0b11000,0b11000,0b10000];\n\n    let cp = cortex_m::Peripherals::take().unwrap();\n    let dp = pac::Peripherals::take().unwrap();\n\n    let mut flash = dp.FLASH.constrain();\n    let rcc = dp.RCC.constrain();\n    let clocks = rcc.cfgr.freeze(\u0026mut flash.acr);\n\n\n    let mut gpioc = dp.GPIOC.split();\n    let mut gpioa = dp.GPIOA.split();\n\n\n    let en = gpioc.pc13.into_push_pull_output(\u0026mut gpioc.crh);\n    let rs = gpioc.pc14.into_push_pull_output(\u0026mut gpioc.crh);\n    let d4 = gpioc.pc15.into_push_pull_output(\u0026mut gpioc.crh);\n    let d5 = gpioa.pa0.into_push_pull_output(\u0026mut gpioa.crl);\n    let d6 = gpioa.pa1.into_push_pull_output(\u0026mut gpioa.crl);\n    let d7 = gpioa.pa2.into_push_pull_output(\u0026mut gpioa.crl);\n\n    let mut delay = cp.SYST.delay(\u0026clocks);\n\n    let mut lcd_interface = Parallel::new(d4, d5, d6, d7, rs, en, lcd_dummy);\n    let mut lcd = LiquidCrystal::new(\u0026mut lcd_interface, Bus4Bits, LCD16X2);\n\n    lcd.begin(\u0026mut delay);\n    lcd.custom_char(\u0026mut delay, \u0026rust1, 0);\n    lcd.custom_char(\u0026mut delay, \u0026rust2, 1);\n    lcd.custom_char(\u0026mut delay, \u0026rust3, 2);\n    lcd.custom_char(\u0026mut delay, \u0026rust4, 3);\n    lcd.custom_char(\u0026mut delay, \u0026rust5, 4);\n    lcd.custom_char(\u0026mut delay, \u0026rust6, 5);\n\n    lcd.write(\u0026mut delay,Text(\"hello World!\"))\n        .write(\u0026mut delay,Command(MoveLine2))\n        .write(\u0026mut delay,Text(\"made in Rust!\"));\n    lcd.set_cursor(\u0026mut delay, 0, 13)\n        .write(\u0026mut delay, CustomChar(0))\n        .write(\u0026mut delay, CustomChar(1))\n        .write(\u0026mut delay, CustomChar(2));\n\n    lcd.set_cursor(\u0026mut delay, 1, 13)\n        .write(\u0026mut delay, CustomChar(3))\n        .write(\u0026mut delay, CustomChar(4))\n        .write(\u0026mut delay, CustomChar(5));\n    loop {}\n}\n\n```\n\n\n## creating your own interface\n\nto create your own interface, you must implement the \"Interface\" Trait which contains the \"send\" function\n\nThe \"send\" function receives two u8 parameters, \"data\" and \"config\", in which their Bits represent:\n\n| BITS | BIT7 | BIT6 |BIT5| BIT4| BIT3| BIT2| BIT1| BIT0|\n| :------ | :------ | :------|  :------| :------| :------| :------| :------| :------|\n| DATA | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |\n| CONFIG | Reserved | Reserved | Reserved | Reserved | EN2 | EN | R/W | RS |\n\n(still no function to read, so keep the R/W pin in pull down)\n(`Reserved`corresponds to the display backlight in the I2C module)\n\nwhere 0 and 1 represent the state of the pin\n1: HIGH\n0: LOW\nconnect the bits to their respective ports, and congratulations you have created your own interface\n\n(to work with PCF8574 you can copy this line ```let package = (config \u0026 0b00000111) | (data \u0026 0xF0) | 0x08; ``` and send it through I2C library of your choice)\n\n\n\n\n## command list\n\n`Clear` Clears the display\n\n`Reset` resets the display's internal variables\n\n`ShiftCursotLeft` Moves the cursor to the left\n\n`ShiftCursotRight` Moves the cursor to the right\n\n`ShiftDisplayLeft` Moves the display left\n\n`ShiftDisplayRight` Moves the display right\n\n`MoveLine1` moves the cursor to the beginning of the first line of the controller\n\n`MoveLine2` moves the cursor to the beginning of the second line of the controller\n\n\n## configuration functions\n\n`echo` enable all displays\n\n`select_lcd` select a display (0 = EN1 | 1 = EN2)\n\n`enable_blink` enable blinking cursor\n\n`enable_cursor` enable cursor\n\n`enable_display` enable display\n\n`enable_autoscroll` enable autoscroll\n\n`disable_blink` disable blinking cursor\n\n`disable_cursor` disable cursor\n\n`disable_display` disable display\n\n`disable_autoscroll` disable autoscroll\n\n`set_autoscroll_increment` autoscroll increments position\n\n`set_autoscroll_decrement` autoscroll decrements position\n\n`update_config` send the configs to the display\n\n## layouts\n\nyou can create custom layouts using the Layout struct.\n\ncreating custom layouts can be very useful if you want to create user interfaces using alphanumeric LCDs.\n\nThe HD44780 supports a total of 2 lines and up to 40 columns, each line has its address.\n\nline 1 = 0x80\nline 2 = 0xC0\n\nmany LCDs rearrange these lines and columns to change the Layout, for example:\n\nfor the 20X4 Display work, the 40 columns of each line are divided into 2 of 20, and to access it, it is necessary to use the line address + offset of 20, so the lines are organized like this:\n\nLine 1 = 0x80\nLine 2 = 0xC0\nLine 3 = 0x80 + 20\nLine 4 = 0xC0 + 20\n\nyou can create using struct Layout!\n\nLayout receives two generic arguments COLUMNS and LINES, inside this struct there is an array of u8 and LINE size\n\neach position represents a line in your Layout, just place the addresses following the example below:\n```rust\nconst LCD16X2: Layout\u003c16,2\u003e = Layout{\n    addrs: [0x80, 0xC0],\n};\n\nconst LCD20X4: Layout\u003c20,4\u003e = Layout{\n    addrs: [0x80, 0xC0, 0x80+20, 0xC0+20],\n};\n```\n(note that you don't have to use all 40 columns if you don't want to)\n\n## why this API?\n\nI use lcd display for a long time, and I always had to rewrite the Drive when I need to use some IO expander, because the current APIs don't provide a simple way to port the communication.\n\nthis API is currently a personal test using embedded_hal, current syntax may change based on users feedback.\n\n- The \"write\" method may be separated into several functions, including new methods for writing data, just like its C++ version: \"omnicrystal\" (Arduino) and UniversalLCD\n\n- support for using reserved \"config\" bits for user customized functions is under review\n(the main idea of ​​this is in use of multi-colored displays)","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frecursiveerror%2Fliquid_crystal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frecursiveerror%2Fliquid_crystal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frecursiveerror%2Fliquid_crystal/lists"}