[tocstart]: # (toc start) * [Rebuild Fonts](#rebuild-fonts) * [LCD and ePaper](#lcd-and-epaper) * [Powersave Mode](#powersave-mode) * [Refresh](#refresh) * [New Displays](#new-displays) * [Display Procedure](#display-procedure) * [Update u8x8.h](#update-u8x8h) * [Rebuild Code](#rebuild-code) * [Release](#release) * [PDF Generation](#pdf-generation) * [Arduino IDE](#arduino-ide) * [Library ](#library-) * [Test Devices](#test-devices) * [Digispark ATTiny Model A (LED at Pin 1)](#digispark-attiny-model-a-led-at-pin-1) * [Images](#images) * [Defines](#defines) * [GCC](#gcc) * [`F_CPU`](#`f_cpu`) * [Identify Environment](#identify-environment) * [Upload to Arduino Due on Linux](#upload-to-arduino-due-on-linux) * [reset arduino board](#reset-arduino-board) * [wait for it...](#wait-for-it) * [https://stackoverflow.com/questions/43016993/how-can-i-force-a-leonardo-to-reset-with-avrdude](#httpsstackoverflowcomquestions43016993howcaniforcealeonardotoresetwithavrdude) * [TTF to BDF](#ttf-to-bdf) * [External Lib Refs](#external-lib-refs) * [MUI Gif Animations](#mui-gif-animations) [tocend]: # (toc end) # Rebuild Fonts Rebuilding a all font c code, font pictures and all font related md (Github markdown) files: ``` tools/font/build$ make clean tools/font/build$ make build1 tools/font/build$ ./build1 tools/font/build$ make clean tools/font/build$ make build2 tools/font/build$ ./build2 ``` The font pictures must be copied manually to the wiki: ``` tools/font/build$ cp *.png ~/git/u8g2.wiki/fntpic/. ``` Some pictures are too large for the build processor. These pictures have to be generated with bdfconv. After this, overwrite the incomplete pictures. ``` tools/font/bdfconv$ make chinese tools/font/bdfconv$ cp u8g2_font_*.png ~/git/u8g2.wiki/fntpic/. ``` The updated font md files will clear the TOC. This has to be rebuild also: ``` tools/mdtoc$ make wiki ``` The makefile target "wiki" will update all markdown files in the wiki. All modified markdown files will get a generated table of content. Labels are inserted before and after the TOC. Do not delete these labels. To update the examples, call the .ino updater: ``` tools/inoupdate$ make ino ``` This will the constructor list for the examples. # LCD and ePaper ## Powersave Mode LCD: Powersave mode will make the content of the display invisible. e-Paper: Powersave mode will try to lower the power consumption, however the display content will not be affected. In both cases the RAM content is not affected and can still be written. This means, that the RAM can be written during power down mode. After enabling power up, the new display content will be visible (for e-Paper devices an additional refresh is required). ## Refresh E-Paper devices have to handle the `U8X8_MSG_DISPLAY_REFRESH` message. LCDs must ignore this message. `U8X8_MSG_DISPLAY_REFRESH` is sent to the device via call to [refreshDisplay](u8x8reference#refreshdisplay). For the u8x8-API this call must be done by the user. For the u8g2-API this call is automatically performed by the [sendBuffer](u8g2reference#sendbuffer) and [nextPage](u8g2reference#nextPage) calls. The refresh message **must** be sent only during power up mode of the e-Paper/e-Ink device. This leads to the following problem: The C++ begin() sequence looks like this: 1. [initDisplay](u8g2reference#initdisplay) 2. [clearDisplay](u8g2reference#cleardisplay) 3. [setPowerSave(0)](u8g2reference#setpowersave) While this is fine for LCDs, the problem for e-Paper/e-Ink is, that a refresh message is sent during step 2, but the power save might still be enabled. To solve this, the procedures above behave differently for LCDs and e-Paper/e-Ink devices: | Procedure | Result for LCD | Result for e-Paper/e-Ink | |----------|-------|------------| | initDisplay | Power Save enabled, display RAM undefined, empty display screen | Power Save disabled, display RAM cleared, empty display screen | | clearDisplay | Display RAM cleared | Display RAM cleared (redundant, because it is already empty) | | setPowerSave(0) | Display RAM is visible on the screen | Disable Power Save (redundant, because it is already disabled) | # New Displays ## Display Procedure Every display has its own display procedure. All display specific communication happens through this procedure. The procedure should be located in a c file with the prefix `u8x8_d_` and the function name *must* have the following form: `u8x8_d__()` Example: ``` uint8_t u8x8_d__(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { uint8_t x, c; uint8_t *ptr; switch(msg) { case U8X8_MSG_DISPLAY_SETUP_MEMORY: // make a call to u8x8_d_helper_display_setup_memory // do NOT communicate with the display u8x8_d_helper_display_setup_memory(u8x8, ); break; case U8X8_MSG_DISPLAY_INIT: // setup the communication interface // init the display by sending an init sequence u8x8_d_helper_display_init(u8x8); u8x8_cad_SendSequence(u8x8, ); // LCD: Put controller in power safe mode and do not clear // the controller RAM (will be done later) // e-paper/e-Ink: Leave the controller in normal mode (activated charge pump, etc) // ensure, that the controller RAM and the display content are cleared break; case U8X8_MSG_DISPLAY_SET_POWER_SAVE: // arg_int == 0: wakeup, normal mode // arg_int == 1: power safe // Power save mode means, that power is reduced, but still the controller RAM // is valid. Sometimes a controller might have several power modes (normal, // sleep, deep sleep, etc). As long as the RAM can be written, any power down // mode is fine. Do not switch to a power down mode, where the controller RAM // gets invalid. ... break; #ifdef U8X8_WITH_SET_FLIP_MODE case U8X8_MSG_DISPLAY_SET_FLIP_MODE: // This case should be compiled only with U8X8_WITH_SET_FLIP_MODE // arg_int == 0: normal, native orientation // arg_int == 1: 180 degree rotation ... break; #endif #ifdef U8X8_WITH_SET_CONTRAST case U8X8_MSG_DISPLAY_SET_CONTRAST: // This case should be compiled only with U8X8_WITH_SET_CONTRAST // arg_int: 0 (no contrast/brightness) to 255 (max contrast/brightness) ... break; #endif case U8X8_MSG_DISPLAY_DRAW_TILE: /* arg_ptr: (u8x8_tile_t *) */ /* arg_int: How often u8x8_tile_t should be repeated */ ... break; case U8X8_MSG_DISPLAY_REFRESH: // LCD: Do nothing // e-Paper/e-Ink: Make controller RAM visible on the display. // It can be assumed, that the controler is NOT in power save mode. break; default: return 0; } return 1; } ``` In most cases each display includes a display-informations stucture (which must be set if U8X8_MSG_DISPLAY_SETUP_MEMORY is received) and a display init sequence (which must be set if U8X8_MSG_DISPLAY_INIT) is received. ## Update u8x8.h The prototype of the display procedure ``` uint8_t u8x8_d__(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) ``` has to be added to u8x8.h ## Rebuild Code Locate ``` tools/codebuild$ ``` Update codebuild.c file with the new controller/display: Usually this is done by copying an existing display structure. The structure usually looks like this: ``` { "sh1106", 8, 4, "u8g2_ll_hvline_vertical_top_lsb", "u8x8_cad_001", "", COM_4WSPI|COM_3WSPI|COM_6800|COM_8080, "Not tested", /* is_generate_u8g2_class= */ 1, { { "64x32" }, { NULL } } }, { "sh1106", 8, 4, "u8g2_ll_hvline_vertical_top_lsb", "u8x8_cad_ssd13xx_i2c", "i2c", COM_I2C, "Not tested", /* is_generate_u8g2_class= */ 1, { { "64x32" }, { NULL } } }, ``` From left to right: | Example | Description | |---|---| | "sh1106" | The name of the controller in your procedure: | | 8 | The tile width (=8 pixel) of the display: In this case 8x8 = 64 pixel width | | 4 | The tile height (=8 pixel) of the display: Here: 4*8 = 32 pixel height | | "u8g2_ll_hvline_vertical_top_lsb" | The U8g2 memory vs display memory mapping procedure (see also u8g2.h) | | "u8x8_cad_001" | The command Argument Data mapping procedure. This might depend on the COM procedure. | | COM_4WSPI | The communication protocols, supported by the display. Can be or'ed | | "Not tested" | Unused comment | | /* is_generate_u8g2_class= */ 1 | Whether the u8g2 Arduino class should be generated (usually 1) | | display list | At the end there must be a NULL terminated list of display names. This must match the part of the function name | Then rebuild the code with ``` tools/codebuild$ make build ``` Finally execute codebuild: ``` tools/codebuild$ ./codebuild ``` This will update U8g2 and add the new constructors for the display # Release ## PDF Generation ``` sudo apt install texlive-latex-base texlive-fonts-recommended texlive-latex-extra pandoc -f gfm fntlistallpic.md -t latex -o ~/git/u8g2/doc/u8g2fntlistallpic.pdf ``` # Arduino IDE ## Library A library, which has been installed via local zip file, is located in the "Arduino/libraries" folder. # Test Devices ## Digispark ATTiny Model A (LED at Pin 1) * Github: https://github.com/digistump/DigistumpArduino * Boards Manager URL: http://digistump.com/package_digistump_index.json * Board: Digispark Default 16.5 MHz * Product Specification: https://digistump.com/wiki/digispark/tutorials/digispark * Defines: `__AVR_ATtiny85__` * Test Environment: Arduino 1.6.5 on Linux Desktop * Display: SSD1306 I2C OLED, Pin 0: Data, Pin 2: Clock # Images * LED light, white background * ISO 200, Cloud, 1/60 (A), +3/10 EV, S-Prog # Defines ## GCC * Show gcc buildin macros: `gcc -dM -E - < /dev/null` ## `F_CPU` * F\_CPU must be defined and must expand to the CPU frequency in hertz (e.g. -DF\_CPU=16000000L) ## Identify Environment * `ARDUINO`: Version number of the Arduino Environment. 100 for 1.00, 10600 for 1.6.0, 10800 for 1.8.0 * `__AVR__`: Atmel AVR * `__18CXX`: MPLAB C18 (PIC) * `__PIC32MX`: PIC32 * `__XC8` MPLAB XC8 Compiler (Microchip) * `__PIC18` MPLAB XC8 Compiler with selected PIC18 device * `__arm__`: GCC ARM (Arduino Due) * `__SAM3X8E__`: Arduino Due * `__AVR_ARCH__`: Values 2 and 25 are ATTiny * `__XTENSA__`, `__xtensa__`: gcc predefined for xtensa architecture (ESP8266) * `XTENSA_EL`, `XTENSA`, `xtensa`: gcc predefined for ESP32 * `ARDUINO_ARCH_ESP8266`, `ESP8266`: Defined by the esp8266 Arduino board file * `ARDUINO_ARCH_ESP32`, `ESP_PLATFORM`: Defined by Arduino IDE for ESP32 boards * `__AVR_ARCH__`: Build-in macro that resolves to a decimal number that identifies the architecture. Possible values are: * 2: avr2, ATTiny * 25: avr25, ATTiny with MOVW instruction * 3: avr3 * 31: avr31 * 35: avr35 (ata5505, ata6617c, ata664251, atmega16u2, atmega32u2, atmega8u2, attiny1634, attiny167, at90usb162, at90usb82) * 4: avr4 (ATMega with 8KB) * 5: avr5 (ATMega with 16KB to 64KB) * 51: avr51 (ATMega with 128KB) * 6: avr6 (ATMega with > 128KB) for mcu=avr2, avr25, avr3, avr31, avr35, avr4, avr5, avr51, avr6, # Upload to Arduino Due on Linux Often the following code seems to be required (enter on terminal): ``` stty -F /dev/ttyACM0 speed 1200 cs8 -cstopb -parenb ``` The following code will reset and wait for the board: ``` # reset arduino board stty -F /dev/ttyACM0 speed 1200 cs8 # wait for it... # https://stackoverflow.com/questions/43016993/how-can-i-force-a-leonardo-to-reset-with-avrdude while :; do sleep 0.5 [ -c /dev/ttyACM0 ] && break done ``` # TTF to BDF Usually, the following options should be used 8x8 Fonts: ``` otf2bdf -r 72 -p 8 -o ``` 16x16 Fonts: ``` otf2bdf -r 72 -p 16 -o ``` # External Lib Refs * http://platformio.org/lib/show/942/U8g2/ * http://www.arduinolibraries.info/libraries/u8g2 ## MUI Gif Animations ``` convert -delay 20 -loop 0 *.png mui_animation.gif ```