2018-08-14 16:22:21 +00:00
|
|
|
# Writer and Cwriter classes
|
|
|
|
|
|
|
|
These classes facilitate rendering Python font files to displays where the
|
|
|
|
display driver is subclassed from the `framebuf` class. An example is the
|
|
|
|
official [SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
|
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
Basic support is for scrolling text display using multiple fonts. The
|
|
|
|
`writer_gui` module provides optional extensions for user interface objects
|
|
|
|
displayed at arbitrary locations on screen.
|
|
|
|
|
2018-08-14 16:22:21 +00:00
|
|
|
Example code and images are for 128*64 SSD1306 OLED displays.
|
|
|
|
|
|
|
|
![Image](images/IMG_2866.JPG)
|
|
|
|
Scrolling text, multiple fonts.
|
|
|
|
|
|
|
|
![Image](images/IMG_2861.JPG)
|
|
|
|
A field containing variable length text with a border.
|
|
|
|
|
|
|
|
![Image](images/rjust.JPG)
|
|
|
|
Right justified text.
|
|
|
|
|
|
|
|
![Image](images/mixed.JPG)
|
|
|
|
Mixed text and graphics.
|
|
|
|
|
|
|
|
![Image](images/fields.JPG)
|
2018-08-28 10:37:21 +00:00
|
|
|
Labels and Fields (from writer_gui.py).
|
2018-08-14 16:22:21 +00:00
|
|
|
|
|
|
|
# Contents
|
|
|
|
|
|
|
|
1. [Introduction](./WRITER.md#1-introduction)
|
|
|
|
1.1 [Hardware](./WRITER.md#11-hardware)
|
|
|
|
1.2 [Files](./WRITER.md#11-files)
|
|
|
|
1.3 [Fonts](./WRITER.md#11-fonts)
|
|
|
|
2. [Writer and CWriter classes](./WRITER.md#2-writer-and-cwriter-classes)
|
|
|
|
2.1 [The Writer class](./WRITER.md#21-the-writer-class) For monochrome displays.
|
|
|
|
2.1.1 [Static Method](./WRITER.md#211-static-method)
|
|
|
|
2.1.2.[Constructor](./WRITER.md#212-constructor)
|
|
|
|
2.1.3 [Methods](./WRITER.md#213-methods)
|
|
|
|
2.2 [The CWriter class](./WRITER.md#22-the-cwriter-class) For colour displays
|
|
|
|
and for upside-down rendering.
|
|
|
|
2.2.1 [Static Method](./WRITER.md#221-static-method)
|
|
|
|
2.2.2 [Constructor](./WRITER.md#222-constructor)
|
|
|
|
2.2.3 [Methods](./WRITER.md#223-methods)
|
2018-08-28 10:37:21 +00:00
|
|
|
3. [The writer_gui module](./WRITER.md#3-the-writer_gui-module)
|
2018-08-14 16:22:21 +00:00
|
|
|
3.1 [The Label class](./WRITER.md#31-the-label-class)
|
|
|
|
4. [Notes](./WRITER.md#4-notes)
|
|
|
|
|
|
|
|
###### [Main README](../README.md)
|
|
|
|
|
|
|
|
# 1. Introduction
|
|
|
|
|
|
|
|
The original `Writer` class was a proof of concept intended to demonstrate
|
|
|
|
rendering, on an SSD1306 OLED display, fonts created by`font_to_py.py`.
|
|
|
|
|
|
|
|
This update for practical applications has the following features:
|
|
|
|
* Genarality: capable of working with any `framebuf` derived driver.
|
|
|
|
* Multiple display operation.
|
|
|
|
* Text display of fixed and variable pitch fonts with wrapping and vertical
|
|
|
|
scrolling.
|
|
|
|
* Wrap/clip options: clip, character wrap or word wrap.
|
|
|
|
* Tab support.
|
|
|
|
* String metrics to enable right or centre justification.
|
|
|
|
* Inverse (background color on foreground color) display.
|
|
|
|
* Labels: render static text at a fixed location.
|
|
|
|
* Fields - render dynamically changing text to a fixed rectangular region.
|
|
|
|
* Inverted display option.
|
|
|
|
|
|
|
|
## 1.1 Hardware
|
|
|
|
|
|
|
|
Tests and demos assume a 128*64 SSD1306 OLED display connected via I2C or SPI.
|
|
|
|
Wiring is specified in `ssd1306_setup.py`. Edit this to use a different bus or
|
|
|
|
for a non-Pyboard target. At the time of writing the default of software I2C
|
|
|
|
should be used: the official SSD1306 driver is not compatible with hardware I2C
|
|
|
|
(see [Notes](./WRITER.md#4-notes)).
|
|
|
|
|
|
|
|
## 1.2 Files
|
|
|
|
|
|
|
|
1. `writer.py` Supports `Writer` and `CWriter` classes.
|
2018-08-28 10:37:21 +00:00
|
|
|
2. `writer_gui.py` Provides optional GUI objects.
|
|
|
|
3. `ssd1306_setup.py` Hardware initialisation for SSD1306. Requires the
|
2018-08-14 16:22:21 +00:00
|
|
|
official [SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
|
2018-08-28 10:37:21 +00:00
|
|
|
4. `writer_demo.py` Demo using a 128*64 SSD1306 OLED display. Import to see
|
2018-08-14 16:22:21 +00:00
|
|
|
usage information.
|
2018-08-28 10:37:21 +00:00
|
|
|
5. `writer_tests.py` Test/demo scripts. Import to see usage information.
|
|
|
|
6. `writer_minimal.py` A minimal version for highly resource constrained
|
2018-08-14 16:22:21 +00:00
|
|
|
devices.
|
|
|
|
|
|
|
|
Sample fonts:
|
|
|
|
1. `freesans20.py` Variable pitch font file.
|
|
|
|
2. `courier20.py` Fixed pitch font file.
|
|
|
|
3. `font10.py` Smaller variable pitch fonts.
|
|
|
|
4. `font6.py`
|
|
|
|
|
|
|
|
## 1.3 Fonts
|
|
|
|
|
|
|
|
Python font files should be created using `font-to-py.py` using horizontal
|
|
|
|
mapping (`-x` option). The `-r` option is not required. If RAM is critical
|
|
|
|
fonts may be frozen as bytecode reducing the RAM impact of each font to about
|
|
|
|
340 bytes.
|
|
|
|
|
|
|
|
###### [Contents](./WRITER.md#contents)
|
|
|
|
|
|
|
|
# 2. Writer and CWriter classes
|
|
|
|
|
|
|
|
The `Writer` class provides fast rendering to monochrome displays using bit
|
|
|
|
blitting. Most applications will use this class.
|
|
|
|
|
|
|
|
The `CWriter` class is a subclass of `Writer`. It can optionally support color
|
|
|
|
displays. It provides additional functionality in the form of an upside-down
|
|
|
|
display option. Owing to limitations in the `frmebuf.blit` method the
|
|
|
|
`CWriter` class renders glyphs one pixel at a time; rendering is therefore
|
|
|
|
slower than the `Writer` class.
|
|
|
|
|
|
|
|
Multiple screens are supported. On any screen multiple `Writer` or `CWriter`
|
|
|
|
instances may be used, each using a different font. A class variable holds the
|
|
|
|
state of each screen to ensure that the insertion point is managed across
|
|
|
|
multiple instances/fonts.
|
|
|
|
|
|
|
|
###### [Contents](./WRITER.md#contents)
|
|
|
|
|
|
|
|
## 2.1 The Writer class
|
|
|
|
|
|
|
|
This class facilitates rendering characters from Python font files to a device,
|
|
|
|
assuming the device has a driver subclassed from `framebuf`. It supports three
|
|
|
|
ways of handling text which would overflow the display: clipping, character
|
|
|
|
wrapping and simple word wrapping.
|
|
|
|
|
|
|
|
It handles newline and tab characters, black-on-white inversion, and field
|
|
|
|
blanking to enable variable length contents to be updated at a fixed location.
|
|
|
|
|
|
|
|
Typical use with an SSD1306 display and the official driver is as follows:
|
|
|
|
|
|
|
|
```python
|
|
|
|
from ssd1306_setup import WIDTH, HEIGHT, setup
|
|
|
|
from writer import Writer
|
|
|
|
import freesans20 # Font to use
|
|
|
|
|
|
|
|
use_spi=False # Tested with a 128*64 I2C connected SSD1306 display
|
|
|
|
ssd = setup(use_spi) # Instantiate display: must inherit from framebuf
|
|
|
|
# Demo drawing geometric shpes
|
|
|
|
rhs = WIDTH -1
|
|
|
|
ssd.line(rhs - 20, 0, rhs, 20, 1) # Demo underlying framebuf methods
|
|
|
|
square_side = 10
|
|
|
|
ssd.fill_rect(rhs - square_side, 0, square_side, square_side, 1)
|
|
|
|
# Instantiate a writer for a specific font
|
|
|
|
wri = Writer(ssd, freesans20) # verbose = False to suppress console output
|
|
|
|
Writer.set_textpos(ssd, 0, 0) # In case a previous test has altered this
|
|
|
|
wri.printstring('Sunday\n12 Aug 2018\n10.30am')
|
|
|
|
ssd.show()
|
|
|
|
```
|
|
|
|
|
|
|
|
The file `writer_demo.py` illustrates the use of font files with a 128*64
|
|
|
|
SSD1306 OLED display and the official
|
|
|
|
[SSD1306 driver](https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py).
|
|
|
|
|
|
|
|
### 2.1.1 Static Method
|
|
|
|
|
|
|
|
The `Writer` class exposes the following static method:
|
|
|
|
|
|
|
|
1. `set_textpos` Args: `device`,`row=None`, `col=None`. The `device` is the
|
|
|
|
display instance. This method determines where on screen subsequent text is to
|
|
|
|
be rendered. The initial value is (0, 0) - the top left corner. Arguments are
|
|
|
|
in pixels with positive values representing down and right respectively. The
|
|
|
|
insertion point defines the top left hand corner of the next character to be
|
|
|
|
output.
|
|
|
|
|
|
|
|
Where `None` is passed, the setting is left unchanged.
|
|
|
|
Return: `row`, `col` current settings.
|
|
|
|
|
|
|
|
The insertion point applies to all `Writer` instances having the same device.
|
|
|
|
The insertion point on a given screen is maintained regardless of the font in
|
|
|
|
use.
|
|
|
|
|
|
|
|
### 2.1.2 Constructor
|
|
|
|
|
|
|
|
This takes the following args:
|
|
|
|
1. `device` The hardware device driver instance for the screen in use.
|
|
|
|
2. `font` A Python font instance.
|
|
|
|
3. `verbose=True` If `True` the constructor emits console printout.
|
|
|
|
|
|
|
|
### 2.1.3 Methods
|
|
|
|
|
|
|
|
1. `printstring` Args: `string`, `invert=False`. Outputs a text string at the
|
|
|
|
current insertion point. Newline and Tab characters are honoured. If `invert`
|
|
|
|
is `True` the text is output as black on white.
|
|
|
|
2. `height` No args. Returns the font height in pixels.
|
|
|
|
3. `stringlen` Arg: `string`. Returns the length of a string in pixels. Used
|
|
|
|
for right or centre justification.
|
|
|
|
4. `set_clip` Args: `row_clip=None`, `col_clip=None`, `wrap=None`. If
|
|
|
|
`row_clip` and/or `col_clip` are `True`, characters will be clipped if they
|
|
|
|
extend beyond the boundaries of the physical display. If `col_clip` is
|
|
|
|
`False` characters will wrap onto the next line. If `row_clip` is `False` the
|
|
|
|
display will, where necessary, scroll up to ensure the line is rendered. If
|
|
|
|
`wrap` is `True` word-wrapping will be performed, assuming words are separated
|
|
|
|
by spaces.
|
|
|
|
If any arg is `None`, that value will be left unchanged.
|
|
|
|
Returns the current values of `row_clip`, `col_clip` and `wrap`.
|
|
|
|
5. `tabsize` Arg `value=None`. If `value` is an integer sets the tab size.
|
|
|
|
Returns the current tab size (initial default is 4). Tabs only work properly
|
|
|
|
with fixed pitch fonts.
|
|
|
|
|
|
|
|
###### [Contents](./WRITER.md#contents)
|
|
|
|
|
|
|
|
## 2.2 The CWriter class
|
|
|
|
|
|
|
|
This extends the `Writer` class by adding support for upside-down and/or color
|
2018-08-28 10:37:21 +00:00
|
|
|
displays. A color value is an integer whose interpretation is dependent on the
|
|
|
|
display hardware and device driver.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
|
|
|
### 2.2.1 Static method
|
|
|
|
|
|
|
|
The following static method is added:
|
|
|
|
1. `invert_display` Args `device`, `value=True`. The `device` is the display
|
|
|
|
instance. If `value` is set, causes text to be rendered upside down. The
|
|
|
|
`set_textpos` method should be called to ensure that text is rendered from the
|
|
|
|
bottom right hand corner (viewing the display in its normal orientation).
|
|
|
|
|
|
|
|
If a display is to be run inverted, this method must be called prior to
|
|
|
|
instantiating a `Writer` for this display.
|
|
|
|
|
|
|
|
### 2.2.2 Constructor
|
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
This takes the following args:
|
2018-08-14 16:22:21 +00:00
|
|
|
1. `device` The hardware device driver instance for the screen in use.
|
|
|
|
2. `font` A Python font instance.
|
2018-08-28 10:37:21 +00:00
|
|
|
3. `fgcolor=None` Foreground color. If `None` a monochrome display is assumed.
|
|
|
|
4. `bgcolor=None` Background color. If `None` a monochrome display is assumed.
|
|
|
|
5. `verbose=True` If `True` the constructor emits console printout.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
|
|
|
### 2.2.3 Methods
|
|
|
|
|
|
|
|
All methods of the base class are supported. Additional method:
|
|
|
|
1. `setcolor` Args: `fgcolor=None`, `bgcolor=None`. Sets the foreground and
|
2018-08-28 10:37:21 +00:00
|
|
|
background colors. If one is `None` that value is left unchanged. If both
|
|
|
|
are `None` the constructor defaults are restored. Constructor defaults are
|
|
|
|
1 and 0 for monochrome displays (`Writer`). Returns foreground
|
2018-08-14 16:22:21 +00:00
|
|
|
and background color values.
|
|
|
|
|
|
|
|
The `printstring` method works as per the base class except that the string is
|
|
|
|
rendered in foreground color on background color (or reversed if `invert` is
|
|
|
|
`True`).
|
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
# 3. The writer_gui module
|
2018-08-14 16:22:21 +00:00
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
This supports user interface objects whose text components are drawn using the
|
|
|
|
`Writer` or `CWriter` classes. Upside down rendering is not supported: attempts
|
|
|
|
to specify it will produce unexpected results.
|
|
|
|
|
|
|
|
The objects are drawn at specific locations on screen and are incompatible with
|
|
|
|
the display of scrolling text: they are therefore not intended for use with the
|
|
|
|
writer's `printstring` method.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
|
|
|
## 3.1 The Label class
|
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
This supports applications where text is to be rendered at specific screen
|
|
|
|
locations.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
Text can be static or dynamic. In the case of dynamic text the background is
|
|
|
|
cleared to ensure that short strings can cleanly replace longer ones.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
Labels can be displayed with an optional single pixel border.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
Colors are handled flexibly. By default the colors used are those of the
|
|
|
|
`Writer` instance, however they can be changed dynamically, for example to warn
|
|
|
|
of overrange values.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
Constructor args:
|
2018-08-14 16:22:21 +00:00
|
|
|
1. `writer` The `Writer` instance (font and screen) to use.
|
|
|
|
2. `row` Location on screen.
|
|
|
|
3. `col`
|
2018-08-28 10:37:21 +00:00
|
|
|
4. `text` If a string is passed it is displayed: typically used for static
|
|
|
|
text. If an integer is passed it is interpreted as the maximum text length
|
|
|
|
in pixels; typically obtained from `writer.stringlen('-99.99')`. Nothing is
|
|
|
|
dsplayed until `.value()` is called. Intended for dynamic text fields.
|
|
|
|
5. `invert=False` Display in inverted or normal style.
|
|
|
|
6. `fgcolor=None` Optionally override the `Writer` colors.
|
|
|
|
7. `bgcolor=None`
|
|
|
|
8. `bordercolor=False` If `False` no border is displayed. If `None` a border
|
|
|
|
is shown in the `Writer` forgeround color. If a color is passed, it is used.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
2018-08-28 10:37:21 +00:00
|
|
|
The constructor displays the string at the required location.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
|
|
|
Methods:
|
2018-08-28 10:37:21 +00:00
|
|
|
1. `value` Redraws the label. This takes the following args:
|
|
|
|
1. `text=None` The text to display. If `None` displays last value.
|
|
|
|
2. ` invert=False` If true, show inverse text.
|
|
|
|
3. `fgcolor=None` Foreground color: if `None` the `Writer` default is used.
|
|
|
|
4. `bgcolor=None` Background color, as per foreground.
|
|
|
|
5. `bordercolor=None` As per above except that if `False` is passed, no
|
|
|
|
border is displayed. This clears a previously drawn border.
|
|
|
|
Returns the current text string.
|
|
|
|
2. `show` No args. (Re)draws the label. For future/subclass use.
|
2018-08-14 16:22:21 +00:00
|
|
|
|
|
|
|
# 4. Notes
|
|
|
|
|
|
|
|
Possible future enhancements:
|
|
|
|
1. General rendering to a rectangular area. This may be problematic as the
|
|
|
|
`framebuf` scroll method is only capable of scrolling the entire buffer.
|
|
|
|
2. Extend word wrapping to cases where words are separated by tabs or hyphens.
|
|
|
|
3. An asynchronous version.
|
|
|
|
|
|
|
|
As stated above the official SSD1306 drriver is incompatible with hardware I2C
|
|
|
|
and this problem cannot efficiently be fixed. [PR4020](https://github.com/micropython/micropython/pull/4020)
|
|
|
|
proposes an enhncement which will facilitate an improved SSD1306 driver capable
|
|
|
|
of using hard or soft I2C.
|
|
|
|
|
|
|
|
###### [Contents](./WRITER.md#contents)
|