qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

st7565.md (13130B)


      1 # ST7565 LCD Driver
      2 
      3 ## Supported Hardware
      4 
      5 LCD modules using ST7565 driver IC, communicating over SPI.
      6 
      7 |Module                        |IC     |Size  |Notes                                                     |
      8 |------------------------------|-------|------|----------------------------------------------------------|
      9 |Newhaven Display NHD-C12832A1Z|ST7565R|128x32|Used by Ergodox Infinity; primary consumer of this feature|
     10 |Zolentech ZLE12864B           |ST7565P|128x64|Requires contrast adjustment                              |
     11 
     12 ## Usage
     13 
     14 To enable the feature, there are three steps. First, when compiling your keyboard, you'll need to add the following to your `rules.mk`:
     15 
     16 ```make
     17 ST7565_ENABLE = yes
     18 ```
     19 
     20 Then in your `keymap.c` file, implement the ST7565 task call. This example assumes your keymap has three layers named `_QWERTY`, `_FN` and `_ADJ`:
     21 
     22 ```c
     23 #ifdef ST7565_ENABLE
     24 void st7565_task_user(void) {
     25     // Host Keyboard Layer Status
     26     st7565_write_P(PSTR("Layer: "), false);
     27 
     28     switch (get_highest_layer(layer_state)) {
     29         case _QWERTY:
     30             st7565_write_P(PSTR("Default\n"), false);
     31             break;
     32         case _FN:
     33             st7565_write_P(PSTR("FN\n"), false);
     34             break;
     35         case _ADJ:
     36             st7565_write_P(PSTR("ADJ\n"), false);
     37             break;
     38         default:
     39             // Or use the write_ln shortcut over adding '\n' to the end of your string
     40             st7565_write_ln_P(PSTR("Undefined"), false);
     41     }
     42 
     43     // Host Keyboard LED Status
     44     led_t led_state = host_keyboard_led_state();
     45     st7565_write_P(led_state.num_lock ? PSTR("NUM ") : PSTR("    "), false);
     46     st7565_write_P(led_state.caps_lock ? PSTR("CAP ") : PSTR("    "), false);
     47     st7565_write_P(led_state.scroll_lock ? PSTR("SCR ") : PSTR("    "), false);
     48 }
     49 #endif
     50 ```
     51 
     52 ## Logo Example
     53 
     54 In the default font, certain ranges of characters are reserved for a QMK logo. To render this logo to the screen, use the following code example:
     55 
     56 ```c
     57 static void render_logo(void) {
     58     static const char PROGMEM qmk_logo[] = {
     59         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94,
     60         0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, 0xB4,
     61         0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0x00
     62     };
     63 
     64     st7565_write_P(qmk_logo, false);
     65 }
     66 ```
     67 
     68 ## Buffer Read Example
     69 For some purposes, you may need to read the current state of the display buffer. The `st7565_read_raw` function can be used to safely read bytes from the buffer.
     70 
     71 In this example, calling `fade_display` in the `st7565_task_user` function will slowly fade away whatever is on the screen by turning random pixels off over time.
     72 ```c
     73 //Setup some mask which can be or'd with bytes to turn off pixels
     74 const uint8_t single_bit_masks[8] = {127, 191, 223, 239, 247, 251, 253, 254};
     75 
     76 static void fade_display(void) {
     77     //Define the reader structure
     78     display_buffer_reader_t reader;
     79     uint8_t buff_char;
     80     if (random() % 30 == 0) {
     81         srand(timer_read());
     82         // Fetch a pointer for the buffer byte at index 0. The return structure
     83         // will have the pointer and the number of bytes remaining from this
     84         // index position if we want to perform a sequential read by
     85         // incrementing the buffer pointer
     86         reader = st7565_read_raw(0);
     87         //Loop over the remaining buffer and erase pixels as we go
     88         for (uint16_t i = 0; i < reader.remaining_element_count; i++) {
     89             //Get the actual byte in the buffer by dereferencing the pointer
     90             buff_char = *reader.current_element;
     91             if (buff_char != 0) {
     92                 st7565_write_raw_byte(buff_char & single_bit_masks[rand() % 8], i);
     93             }
     94             //increment the pointer to fetch a new byte during the next loop
     95             reader.current_element++;
     96         }
     97     }
     98 }
     99 ```
    100 
    101 ## Other Examples
    102 
    103 In split keyboards, it is very common to have two displays that each render different content and are oriented or flipped differently. You can do this by switching which content to render by using the return value from `is_keyboard_master()` or `is_keyboard_left()` found in `split_util.h`, e.g:
    104 
    105 ```c
    106 #ifdef ST7565_ENABLE
    107 display_rotation_t st7565_init_user(display_rotation_t rotation) {
    108     if (!is_keyboard_master()) {
    109         return DISPLAY_ROTATION_180;  // flips the display 180 degrees if offhand
    110     }
    111 
    112     return rotation;
    113 }
    114 
    115 void st7565_task_user(void) {
    116     if (is_keyboard_master()) {
    117         render_status();  // Renders the current keyboard state (layer, lock, caps, scroll, etc)
    118     } else {
    119         render_logo();  // Renders a static logo
    120     }
    121 }
    122 #endif
    123 ```
    124 
    125 ## Basic Configuration
    126 
    127 |Define                  |Default       |Description                                                                                          |
    128 |------------------------|--------------|-----------------------------------------------------------------------------------------------------|
    129 |`ST7565_A0_PIN`         |*Not defined* |(Required) The GPIO connected to the display's A0 (data/command) pin                                 |
    130 |`ST7565_RST_PIN`        |*Not defined* |(Required) The GPIO connected to the display's reset pin                                             |
    131 |`ST7565_SS_PIN`         |*Not defined* |(Required) The GPIO connected to the display's slave select pin                                      |
    132 |`ST7565_SPI_CLK_DIVISOR`|`4`           |The SPI clock divisor to use                                                                         |
    133 |`ST7565_FONT_H`         |`"glcdfont.c"`|The font code file to use for custom fonts                                                           |
    134 |`ST7565_FONT_START`     |`0`           |The starting character index for custom fonts                                                        |
    135 |`ST7565_FONT_END`       |`223`         |The ending character index for custom fonts                                                          |
    136 |`ST7565_FONT_WIDTH`     |`6`           |The font width                                                                                       |
    137 |`ST7565_FONT_HEIGHT`    |`8`           |The font height (untested)                                                                           |
    138 |`ST7565_TIMEOUT`        |`60000`       |Turns off the screen after 60000ms of keyboard inactivity. Helps reduce burn-in. Set to 0 to disable.|
    139 |`ST7565_COLUMN_OFFSET`  |`0`           |Shift output to the right this many pixels.                                                          |
    140 |`ST7565_CONTRAST`       |`32`          |The default contrast level of the display, from 0 to 255.                                            |
    141 |`ST7565_UPDATE_INTERVAL`|`0`           |Set the time interval for updating the display in ms. This will improve the matrix scan rate.        |
    142 
    143 ## Custom sized displays
    144 
    145 The default display size for this feature is 128x32 and all necessary defines are precalculated with that in mind.
    146 
    147 |Define                 |Default   |Description                                                                                                |
    148 |-----------------------|----------|-----------------------------------------------------------------------------------------------------------|
    149 |`ST7565_DISPLAY_WIDTH` |`128`     |The width of the display.                                                                                  |
    150 |`ST7565_DISPLAY_HEIGHT`|`32`      |The height of the display.                                                                                 |
    151 |`ST7565_MATRIX_SIZE`   |`512`     |The local buffer size to allocate.<br>`(ST7565_DISPLAY_HEIGHT / 8 * ST7565_DISPLAY_WIDTH)`.                |
    152 |`ST7565_BLOCK_TYPE`    |`uint16_t`|The unsigned integer type to use for dirty rendering.                                                      |
    153 |`ST7565_BLOCK_COUNT`   |`16`      |The number of blocks the display is divided into for dirty rendering.<br>`(sizeof(ST7565_BLOCK_TYPE) * 8)`.|
    154 |`ST7565_BLOCK_SIZE`    |`32`      |The size of each block for dirty rendering<br>`(ST7565_MATRIX_SIZE / ST7565_BLOCK_COUNT)`.                 |
    155 
    156 ## API
    157 
    158 ```c
    159 // Rotation enum values are flags
    160 typedef enum {
    161     DISPLAY_ROTATION_0,
    162     DISPLAY_ROTATION_180
    163 } display_rotation_t;
    164 
    165 // Initialize the display, rotating the rendered output based on the define passed in.
    166 // Returns true if the was initialized successfully
    167 bool st7565_init(display_rotation_t rotation);
    168 
    169 // Called at the start of st7565_init, weak function overridable by the user
    170 // rotation - the value passed into st7565_init
    171 // Return new display_rotation_t if you want to override default rotation
    172 display_rotation_t st7565_init_user(display_rotation_t rotation);
    173 
    174 // Clears the display buffer, resets cursor position to 0, and sets the buffer to dirty for rendering
    175 void st7565_clear(void);
    176 
    177 // Renders the dirty chunks of the buffer to display
    178 void st7565_render(void);
    179 
    180 // Moves cursor to character position indicated by column and line, wraps if out of bounds
    181 // Max column denoted by 'st7565_max_chars()' and max lines by 'st7565_max_lines()' functions
    182 void st7565_set_cursor(uint8_t col, uint8_t line);
    183 
    184 // Advances the cursor to the next page, writing ' ' if true
    185 // Wraps to the beginning when out of bounds
    186 void st7565_advance_page(bool clearPageRemainder);
    187 
    188 // Moves the cursor forward 1 character length
    189 // Advance page if there is not enough room for the next character
    190 // Wraps to the beginning when out of bounds
    191 void st7565_advance_char(void);
    192 
    193 // Writes a single character to the buffer at current cursor position
    194 // Advances the cursor while writing, inverts the pixels if true
    195 // Main handler that writes character data to the display buffer
    196 void st7565_write_char(const char data, bool invert);
    197 
    198 // Writes a string to the buffer at current cursor position
    199 // Advances the cursor while writing, inverts the pixels if true
    200 void st7565_write(const char *data, bool invert);
    201 
    202 // Writes a string to the buffer at current cursor position
    203 // Advances the cursor while writing, inverts the pixels if true
    204 // Advances the cursor to the next page, wiring ' ' to the remainder of the current page
    205 void st7565_write_ln(const char *data, bool invert);
    206 
    207 // Pans the buffer to the right (or left by passing true) by moving contents of the buffer
    208 // Useful for moving the screen in preparation for new drawing
    209 void st7565_pan(bool left);
    210 
    211 // Returns a pointer to the requested start index in the buffer plus remaining
    212 // buffer length as struct
    213 display_buffer_reader_t st7565_read_raw(uint16_t start_index);
    214 
    215 // Writes a string to the buffer at current cursor position
    216 void st7565_write_raw(const char *data, uint16_t size);
    217 
    218 // Writes a single byte into the buffer at the specified index
    219 void st7565_write_raw_byte(const char data, uint16_t index);
    220 
    221 // Sets a specific pixel on or off
    222 // Coordinates start at top-left and go right and down for positive x and y
    223 void st7565_write_pixel(uint8_t x, uint8_t y, bool on);
    224 
    225 // Writes a PROGMEM string to the buffer at current cursor position
    226 // Advances the cursor while writing, inverts the pixels if true
    227 // Remapped to call 'void st7565_write(const char *data, bool invert);' on ARM
    228 void st7565_write_P(const char *data, bool invert);
    229 
    230 // Writes a PROGMEM string to the buffer at current cursor position
    231 // Advances the cursor while writing, inverts the pixels if true
    232 // Advances the cursor to the next page, wiring ' ' to the remainder of the current page
    233 // Remapped to call 'void st7565_write_ln(const char *data, bool invert);' on ARM
    234 void st7565_write_ln_P(const char *data, bool invert);
    235 
    236 // Writes a PROGMEM string to the buffer at current cursor position
    237 void st7565_write_raw_P(const char *data, uint16_t size);
    238 
    239 // Can be used to manually turn on the screen if it is off
    240 // Returns true if the screen was on or turns on
    241 bool st7565_on(void);
    242 
    243 // Called when st7565_on() turns on the screen, weak function overridable by the user
    244 // Not called if the screen is already on
    245 void st7565_on_user(void);
    246 
    247 // Can be used to manually turn off the screen if it is on
    248 // Returns true if the screen was off or turns off
    249 bool st7565_off(void);
    250 
    251 // Called when st7565_off() turns off the screen, weak function overridable by the user
    252 // Not called if the screen is already off
    253 void st7565_off_user(void);
    254 
    255 // Returns true if the screen is currently on, false if it is
    256 // not
    257 bool st7565_is_on(void);
    258 
    259 // Basically it's st7565_render, but with timeout management and st7565_task_user calling!
    260 void st7565_task(void);
    261 
    262 // Called at the start of st7565_task, weak function overridable by the user
    263 void st7565_task_user(void);
    264 
    265 // Inverts the display
    266 // Returns true if the screen was or is inverted
    267 bool st7565_invert(bool invert);
    268 
    269 // Returns the maximum number of characters that will fit on a line
    270 uint8_t st7565_max_chars(void);
    271 
    272 // Returns the maximum number of lines that will fit on the display
    273 uint8_t st7565_max_lines(void);
    274 ```