diff --git a/DRIVERS.md b/DRIVERS.md index 53cbbb1..76d0359 100644 --- a/DRIVERS.md +++ b/DRIVERS.md @@ -446,6 +446,18 @@ This uses `framebuf.GS8` to stand in for 8 bit color in `rrrgggbb` format. To maximise update speed consider using native, viper or assembler for the conversion, typically to RGB565 format. +An alternative is to design for 4-bit color which halves the size of the +framebuffer. This means using `GS4_HMSB` mode. The class must include the class +variable `lut`: +```python +class MY_DRIVER(framebuf.FrameBuffer): + lut = bytearray(32) +``` +This is a lookup table (LUT) mapping a 4-bit index onto a 16-bit color value +acceptable to the hardware. The "on the fly" converter unpacks the values in +the frame buffer and uses them as indices into the `lut` bytearray. See the +various supplied 4-bit drivers. + Color drivers should have a static method converting rgb(255, 255, 255) to a form acceptable to the driver. For 8-bit rrrgggbb this can be: ```python @@ -453,7 +465,12 @@ form acceptable to the driver. For 8-bit rrrgggbb this can be: def rgb(r, g, b): return (r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6) ``` -This should be amended if the hardware uses a different 8-bit format. +This should be amended if the hardware uses a different 8-bit format. If the +hardware expects a 16 bit value, the "on the fly" converter will map the 8-bit +value to 16 bits. In the case of 4-bit drivers the LUT is 16 bits in size, and +`.rgb` is called only when populating the LUT. In this case `.rgb` returns a 16 +bit value in a format compatible with the hardware and the byte order of the +"on the fly" conversion code. The `Writer` (monochrome) or `CWriter` (color) classes and the `nanogui` module should then work automatically. diff --git a/README.md b/README.md index 8a90055..55baf24 100644 --- a/README.md +++ b/README.md @@ -232,6 +232,7 @@ Demos for larger displays. * `asnano_sync.py` Two Pyboard specific demos using the GUI with `uasyncio`. * `asnano.py` Could readily be adapted for other targets. * `tbox.py` Demo `Textbox` class. Cross-platform. + * `scale_ili.py` A special demo of the asychronous mode of the ILI9341 driver. Usage with `uasyncio` is discussed [here](./ASYNC.md). In summary the blocking which occurs during transfer of the framebuffer to the display may affect more @@ -403,7 +404,10 @@ PALE_YELLOW = create_color(12, 150, 150, 0) This creates a color `rgb(150, 150, 0)` assigns it to "spare" color number 12 then sets `PALE_YELLOW` to 12. Any color number in range `0 <= n <= 15` may be used (implying that predefined colors may be reassigned). It is recommended -that `BLACK` (0) and `WHITE` (15) are not changed. +that `BLACK` (0) and `WHITE` (15) are not changed. If code is to be ported +between 4-bit and other drivers, use `create_color()` for all custom colors: +it will produce appropriate behaviour. See the `vari_fields` function in the +demo `color15.py` for an example. ###### [Contents](./README.md#contents) diff --git a/gui/core/colors.py b/gui/core/colors.py index 916619f..a6c3699 100644 --- a/gui/core/colors.py +++ b/gui/core/colors.py @@ -4,16 +4,20 @@ # Copyright (c) 2020 Peter Hinch from color_setup import SSD -if hasattr(SSD, 'lut'): # Colors defined by LUT - def create_color(idx, r, g, b): - if not 0 <= idx <= 15: - raise ValueError('Color nos must be 0..15') - x = idx << 1 - c = SSD.rgb(r, g, b) - SSD.lut[x] = c & 0xff - SSD.lut[x + 1] = c >> 8 - return idx +# Code can be portable between 4-bit and other drivers by calling create_color +def create_color(idx, r, g, b): + c = SSD.rgb(r, g, b) + if not hasattr(SSD, 'lut'): + return c + if not 0 <= idx <= 15: + raise ValueError('Color nos must be 0..15') + x = idx << 1 + SSD.lut[x] = c & 0xff + SSD.lut[x + 1] = c >> 8 + return idx + +if hasattr(SSD, 'lut'): # Colors defined by LUT BLACK = create_color(0, 0, 0, 0) GREEN = create_color(1, 0, 255, 0) RED = create_color(2, 255, 0, 0) diff --git a/gui/demos/color15.py b/gui/demos/color15.py index 48139e7..bf82622 100644 --- a/gui/demos/color15.py +++ b/gui/demos/color15.py @@ -89,6 +89,7 @@ def multi_fields(t): def vari_fields(): print('Variable label styles.') + VIOLET = create_color(12, 255, 0, 255) # Custom color refresh(ssd, True) # Clear any prior image wri_large = CWriter(ssd, freesans20, GREEN, BLACK, verbose=False) wri_large.set_clip(True, True, False) @@ -117,6 +118,11 @@ def vari_fields(): lbl_var.value(fgcolor=YELLOW) refresh(ssd) utime.sleep(2) + lbl_text.value('Violet') + lbl_bord.value('None') + lbl_var.value(fgcolor=VIOLET) + refresh(ssd) + utime.sleep(2) lbl_text.value('Blue') lbl_bord.value('Green') lbl_var.value('18.99', fgcolor=BLUE, bdcolor=GREEN)