|
| 1 | +# Changing module behavior |
| 2 | + |
| 3 | +If you want to change the behavior of a module that doesn't have any options within vial you will need to change the code in the `users/halcyon_modules/splitkb/<module_name>` folder. Within this folder you can change the `.c`, `.h`, `config.h` or `rules.mk` files to your liking. For the actual configuration options, check out the QMK documentation. |
| 4 | + |
| 5 | +If you want to add any custom `.c` files you can do so by adding a `SRC += <file>.c` to your keymaps `rules.mk` or `SRC += $(CURRENT_DIR)/<file>.c` to the modules `rules.mk` |
| 6 | + |
| 7 | +For the modules we added some extra hooks. Mainly the following: |
| 8 | + |
| 9 | +* `void module_post_init_kb(void)` |
| 10 | +* `void module_post_init_user(void)` |
| 11 | +* `void module_housekeeping_task_kb(void)` |
| 12 | +* `void module_housekeeping_task_user(void)` |
| 13 | + |
| 14 | +These four are added because we already use the `keyboard_post_init_kb` and `housekeeping_task_kb` in the main halcyon code. Any module can then use the other hooks to do anything else. |
| 15 | + |
| 16 | +* `void display_module_housekeeping_task_kb(bool second_display)` |
| 17 | +* `void display_module_housekeeping_task_user(bool second_display)` |
| 18 | + |
| 19 | +Finally we added a display housekeeping task. We added the feature where the keyboard can detect if there are one or two displays connected. Because we always want to show information about layers if we only have one display, where it doesn't matter where the display is located. We use this to determine if the keyboard with display module is the second display or not and draw the content accordingly. |
| 20 | + |
| 21 | +## Display |
| 22 | + |
| 23 | +To customize your display you will need to add some files to your keymap. A complete example can be found in the `examples` directory in our `qmk_userspace` fork. The files in this example can be added to your keymap folder. Some more simple examples can be found below. |
| 24 | + |
| 25 | +Within the example you can see how a display code should be built up. The functions used here are more thoroughly explained in the [Quantum Painter API documentation from QMK](https://docs.qmk.fm/quantum_painter#quantum-painter-api). Because we added some extra hooks which you can read more about [here](#changing-module-behavior), any actual display initialization is already done so you don't have to worry about that. We make use of the surface feature of quantum painter. This makes it so it only draws changed parts of the display. Which is why we use the `qp_surface_draw` feature at the end of the code. |
| 26 | + |
| 27 | +There are some quirks when using Quantum Painter which we noticed while creating our firmware which can help if you want to create your own display behavior. |
| 28 | +* Font size is determined when generating the file using the CLI. |
| 29 | +* You need to generate mono2 fonts if you want to recolor the font but this pretty much breaks any aliased font. So a pixel font is recommended. |
| 30 | +* Using pixel fonts you can scale them 2 or 4 times larger but somehow they break at a certain point when going too large. We fixed this by just creating images of the fonts and using that. |
| 31 | +* If you want to wrap around text, you'll need to create a custom function for that. |
| 32 | +* Drawing a full screen image can give the keyboard noticeable lag. For startup this is okay but switching images every couple of seconds could become annoying. |
| 33 | +* This also applies for animations. Smaller size animations are fine, from testing the animations could take up around 30% of the screen and still have the keyboard be responsive but when having animations on the entire screen it can slow down the entire keyboard. |
| 34 | +* Using large images or animations can eat up the firmware size very quickly so be aware of that. |
| 35 | +* Our displays are 240*135 pixels. |
| 36 | + |
| 37 | +You can also look in the `users/halcyon_modules/hlc_tft_display/` folder to see how we implemented the display code. |
| 38 | + |
| 39 | +To load new fonts or images you will need to convert them using the [Quantum Painter CLI tools.](https://docs.qmk.fm/quantum_painter#quantum-painter-cli) |
| 40 | + |
| 41 | + |
| 42 | +### Example: draw a picture on the second display |
| 43 | + |
| 44 | +First convert your 240*135 image to a QGF file: |
| 45 | +`qmk painter-convert-graphics -f rgb565 -i my_image.png` |
| 46 | + |
| 47 | +Copy the generated files to your keymap. |
| 48 | + |
| 49 | +In your `rules.mk` add |
| 50 | + |
| 51 | +```makefile |
| 52 | +SRC += my_image.qgf.c |
| 53 | +``` |
| 54 | + |
| 55 | +And in your keymap.c add: |
| 56 | + |
| 57 | +```c |
| 58 | +#include "hlc_tft_display/hlc_tft_display.h" |
| 59 | +#include "qp_surface.h" |
| 60 | +#include "my_image.qgf.h" |
| 61 | + |
| 62 | +static painter_image_handle_t my_image; |
| 63 | + |
| 64 | +painter_device_t lcd; |
| 65 | +painter_device_t lcd_surface; |
| 66 | + |
| 67 | +bool module_post_init_user(void) { |
| 68 | + return false; |
| 69 | +} |
| 70 | + |
| 71 | +bool display_module_housekeeping_task_user(bool second_display) { |
| 72 | + static bool display_set = false; |
| 73 | + |
| 74 | + if(second_display) { |
| 75 | + if (!display_set) { |
| 76 | + my_image = qp_load_image_mem(gfx_my_image); // Get the `gfx_my_image` from the `my_image.qgf.h` file |
| 77 | + qp_drawimage(lcd_surface, 0, 0, my_image); |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + if(!second_display) { |
| 82 | + // Re-use the function to display layers and status |
| 83 | + update_display(); |
| 84 | + } |
| 85 | + |
| 86 | + qp_surface_draw(lcd_surface, lcd, 0, 0, 0); |
| 87 | + |
| 88 | + return false; |
| 89 | +} |
| 90 | +``` |
| 91 | +
|
| 92 | +
|
| 93 | +### Example: write some colorful text on the display |
| 94 | +
|
| 95 | +First convert your font to an image file: |
| 96 | +
|
| 97 | +```bash |
| 98 | +qmk painter-make-font-image -s size_of_font -o ./ -f my_font.ttf |
| 99 | +``` |
| 100 | + |
| 101 | +Now convert the generated font image |
| 102 | + |
| 103 | +```bash |
| 104 | +qmk painter-convert-font-image -f mono2 -i my_font.png |
| 105 | +``` |
| 106 | + |
| 107 | +In your `rules.mk` add |
| 108 | + |
| 109 | +```makefile |
| 110 | +SRC += my_font.qff.c |
| 111 | +``` |
| 112 | + |
| 113 | +And in your keymap.c add: |
| 114 | + |
| 115 | +```c |
| 116 | +#include "hlc_tft_display/hlc_tft_display.h" |
| 117 | +#include "qp_surface.h" |
| 118 | +#include "my_font.qff.h" |
| 119 | + |
| 120 | +static painter_font_handle_t my_font; |
| 121 | + |
| 122 | +painter_device_t lcd; |
| 123 | +painter_device_t lcd_surface; |
| 124 | + |
| 125 | +bool module_post_init_user(void) { |
| 126 | + my_font = qp_load_font_mem(font_my_font); |
| 127 | + static const char *text = "Hello from SplitKB!"; |
| 128 | + int16_t width = qp_textwidth(my_font, text); |
| 129 | + qp_drawtext_recolor(lcd_surface, (LCD_WIDTH - width), (LCD_HEIGHT - my_font->line_height), my_font, text, HSV_BLUE, HSV_BLACK); |
| 130 | + qp_surface_draw(lcd_surface, lcd, 0, 0, 0); |
| 131 | + return false; |
| 132 | +} |
| 133 | + |
| 134 | +bool display_module_housekeeping_task_user(bool second_display) { |
| 135 | + return false; |
| 136 | +} |
| 137 | +``` |
| 138 | +
|
| 139 | +## Encoder |
| 140 | +
|
| 141 | +Look at the [QMK documentation for the encoders feature](https://docs.qmk.fm/features/encoders) to see what options are available. |
| 142 | +
|
| 143 | +## Cirque |
| 144 | +
|
| 145 | +Look at the [QMK documentation for the cirque trackpad](https://docs.qmk.fm/features/pointing_device#cirque-trackpad) to see what options are available. |
0 commit comments