From: Advaith Menon Date: Thu, 22 Jan 2026 15:05:08 +0000 (-0500) Subject: Finish student guide X-Git-Url: https://git.devinivas.org/?a=commitdiff_plain;h=b715ec6a0a9da1571e0125fd17cf2a8f2f3f01ba;p=4dulcd-nolibrary.git Finish student guide --- diff --git a/GUIDE.adoc b/GUIDE.adoc new file mode 100644 index 0000000..eb2f8f8 --- /dev/null +++ b/GUIDE.adoc @@ -0,0 +1,145 @@ += Writing to the uLCD without a library: Student Guide +Advaith Menon ; Diego Fratta +v0.1.0, 2026-01-20 +:toc: +:link-goldelox: https://github.com/4dsystems/Goldelox-Serial-Linux-Library +:link-spe: https://resources.4dsystems.com.au/manuals/workshop4/serial/goldelox/#text-and-string-commands +:link-repository: https://git.devinivas.org/?p=4dulcd-nolibrary.git;a=summary + +== Abstract +This document details the necessary steps to write to the uLCD without using the +libraries provided by 4D Systems. + +NOTE: Some of this code was written by +reverse-engineering the {link-goldelox}[Linux library] provided by 4D Systems. +This is not necessary - 4D provides {link-spe}[comprehensive +documentation] on the opcodes and how to use them. + +== Copyright +The code is licensed under the MIT License. Students should legally be able to +copy code from this demo into their assignments, as long as the copyright notice +is retained. + +The authors of this document discourage copying code. Instead, they encourage +understanding what the code does and then attempting to rewrite it on their own. + +== Approach +The code uses ESP-IDF as its platform. Since all other platforms, such as +Arduino, run on top of ESP-IDF, this code should be portable. The wiring for the +reset is also done directly to the ESP's reset line, hence there is no code to +reset the uLCD. + +NOTE: To get the code to work with Arduino, rename the `app_main` function to +`setup` and add a new line: `void loop(void) {}`. + +== Code +Code can be found at Advaith's personal Git server. The link is as follows: +{link-repository}. To clone the repository, run `git clone +git://git.devinivas.org/4dulcd-nolibrary.git`. + +== Basic Steps +The steps to initialize UART are not covered here since these depend on the +platform that the user chooses to use. The UART interface has been abstracted to +four functions: + +* `write_tx(const void *data, size_t bufsz)`: Send `bufsz` data from the `data` + buffer via the TX line. Returns number of bytes sent. +* `read_rx(void *data, size_t bufsz, uint32_t tout)`: Read `bufsz` data into the + `data` buffer, and limit to `tout` seconds. If it takes longer, this function + fails. Returns number of bytes read. +* `flush_rx()`: Flush the receiving buffer. +* `flush_tx(uint32_t timeout)`: Flush the transmit buffers. The operation times + out if it exceeds `timeout` seconds. + +By abstracting the UART interface into these four functions, it should be +possible to use this code with any microcontroller that supports UART - these +functions will simply have to be implemented for that specific architecture. + +=== Initialization +The EVE (Extensible Virtual Engine) takes 3 seconds to boot up. This is the +most reliable way to perform the +boot wait - alternate methods will not work. + +NOTE: The official uLCD libraries work by sending a bunch of 'X's until a `0x15` +is received. At least, that is how it's supposed to work in theory, but actually +the read just times out, basically having the same effect as above. + +=== uLCD Default Parameters +By default, the ULCD uses `8N1` UART at a baud rate of 9600. This baud rate can +be changed via a special opcode. + +The uLCD can be treated as a "big-endian" device. This means most significant +bits are sent first. For instance, if you wish to send the data `0xDEADBEEF`, +you would send it as `0xDE`, `0xAD`, `0xBE`, `0xEF`. + +=== uLCD opcodes +uLCD opcodes are 16 bits in length. These opcodes can be found at {link-spe}[the +4D Systems documentation]. For example, the opcode for clearing the screen is +`0xFFD7`, which means you send `0xFF`, then `0xD7`. + +Some opcodes take arguments. Argument values are sent in a big-endian +fashion. + +=== uLCD Acknowledge +After every instruction is set, an acknowledge can be obtained from the uLCD by +reading 1 byte from it. This byte should be `0x06`. Any other value indicates an +error code. + +TIP: The reader is encouraged to create a helper function to perform this +acknowledge since it is a +very commonly used operation. The demo code does not do so to promote learning. + +== Demos + +TIP: The reader is encouraged to attempt writing the code without looking at the +aforementioed repository. Doing so will train one on how to read documentation. + +IMPORTANT: The code must be pulled from the actual repository, and is not +provided here. + +=== Clearing the screen +Per the uLCD documentation, if there is no serial activity after 5 seconds from +EVE initialization, the "flash" screen will be written. To prevent writing on +top of this screen in the event the uLCD has not been reset, the screen must be +cleared. To perform this action, there is the `gfx_Cls` command in GOLDELOX. +This has an opcode of `0xFFD7` and takes no arguments. + +=== Hello, World! +The function `ulcd_txt_demo` demonstrates this process by writing a Hello World +string to the first line and column. This code is in the function +`ulcd_txt_demo`. + +The text cursor first has to be placed at the desired location. +This is done with the `txt_MoveCursor` +function with an opcode of `0xFFE4`. It takes two arguments, the line number and +the column number, both which are 16-bit unsigned integers. Since the uLCD's +number of pixels don't even exceed one byte, it can easily be fit within the +lower byte. The code goes to (0,0). + +Now, the `putstr` command can be used to print a string to the current location +on the LCD. In standard C convention, the string must end with a `0x00` byte to +denote its end. The string "Hello, World" is sent here. + +**Exercise to the reader:** (Not for credit) + +. Make the text bold and change its color to white. + The `txt_Bold` and `txt_FGcolour` commands might help. +. Center the text horizontally and vertically to the screen. + Avoid using trial-and-error, and use the + `charwidth`, `charheight` and `gfx_MoveTo` functions instead. +. Display the text inside a sufficiently big semicircle. + + +=== Changing the baud rate +Unlike other instructions which basically follow the same process, the baud rate +instruction is a bit tricky to implement. It works in three steps: +. Call the `setBaudWait` command +. Change the baud rate +. With the new baud rate, perform the acknowledge procedure. + +To ease understanding of the code, we have abstracted the process of changing +the baud rate to a function called `update_baud`. + +Note that `setBaudWait` doesn't take a baud rate as its argument! It instead +takes a mapping to a number indicating a baud rate. The mapping table can be +found at 4D's website.