0
# Character/Text Displays
1
2
Text-oriented OLED displays that support both graphical rendering and character-based text display with embedded fonts. These displays combine the flexibility of graphics with the convenience of character addressing.
3
4
## Capabilities
5
6
### WS0010 Display
7
8
Serial interface to a monochrome Winstar WS0010 OLED display with character support, embedded fonts, and both graphical and text modes.
9
10
```python { .api }
11
class ws0010:
12
def __init__(self, serial_interface=None, width=100, height=16, undefined='_', font=None, selected_font=0, exec_time=1e-6 * 50, rotate=0, framebuffer=None, **kwargs):
13
"""
14
Initialize WS0010 OLED character display.
15
16
Parameters:
17
- serial_interface: Parallel interface (luma.core.interface.serial.parallel)
18
- width: Number of horizontal pixels (default: 100)
19
- height: Number of vertical pixels (default: 16)
20
- undefined: Character to display for missing glyphs (default: '_')
21
- font: Override internal font with PIL.ImageFont (optional)
22
- selected_font: Select embedded font table by name/number (default: 0)
23
- exec_time: Command execution time in seconds (default: 50µs)
24
- rotate: Rotation value 0-3 (0°, 90°, 180°, 270°) (default: 0)
25
- framebuffer: Framebuffering strategy (diff_to_previous or full_frame)
26
"""
27
28
def display(self, image):
29
"""
30
Display a 1-bit PIL Image on the WS0010 OLED.
31
32
Parameters:
33
- image: PIL.Image in mode "1" (1-bit monochrome)
34
"""
35
36
def get_font(self, ft):
37
"""
38
Load embedded font by index or name.
39
40
Parameters:
41
- ft: Font index (int) or name (str)
42
43
Returns:
44
Font object for the specified embedded font
45
"""
46
47
@property
48
def text(self) -> str:
49
"""Get the current text content displayed on screen."""
50
51
@text.setter
52
def text(self, value: str):
53
"""
54
Set text content to display on screen.
55
56
Parameters:
57
- value: Text string to display, supports newlines
58
"""
59
```
60
61
**Supported Resolutions**: (40,8), (40,16), (60,8), (60,16), (80,8), (80,16), (100,8), (100,16)
62
63
**Available Embedded Fonts**:
64
65
| Number | Name | Font | Size |
66
|--------|----------|----------------------|------|
67
| 0 | FT00 | English Japanese | 5x8 |
68
| 1 | FT01 | Western European I | 5x8 |
69
| 2 | FT10 | English Russian | 5x8 |
70
| 3 | FT11 | Western European II | 5x8 |
71
| 4 | FT00_10 | English Japanese | 5x10 |
72
| 5 | FT01_10 | Western European I | 5x10 |
73
| 6 | FT10_10 | English Russian | 5x10 |
74
| 7 | FT11_10 | Western European II | 5x10 |
75
76
Usage example:
77
78
```python
79
from luma.core.interface.serial import parallel
80
from luma.oled.device import ws0010
81
82
# Initialize with parallel interface
83
serial = parallel(RS=7, E=8, PINS=[25, 24, 23, 18])
84
device = ws0010(serial, width=100, height=16, selected_font='FT01')
85
86
# Display text using character interface
87
device.text = "WS0010 Display\nLine 2 Text"
88
89
# Or use graphical interface
90
with canvas(device) as draw:
91
draw.text((0, 0), "Graphics Mode", fill="white")
92
draw.rectangle((0, 8, 100, 16), outline="white")
93
94
# Load and use different fonts
95
font = device.get_font('FT11') # Western European II
96
device.text = "Çafé naïve résumé"
97
```
98
99
### Winstar WEH Display
100
101
Character-based Winstar WEH OLED display using the WS0010 controller with grid-optimized font rendering.
102
103
```python { .api }
104
class winstar_weh(ws0010):
105
def __init__(self, serial_interface=None, width=16, height=2, **kwargs):
106
"""
107
Initialize Winstar WEH character OLED display.
108
109
Parameters:
110
- serial_interface: Parallel interface (luma.core.interface.serial.parallel)
111
- width: Number of characters per line (default: 16)
112
- height: Number of lines (default: 2)
113
- undefined: Character to display for missing glyphs (default: '_')
114
- font: Override internal font with PIL.ImageFont (optional)
115
- default_table: Select embedded font table (optional)
116
- embedded_font: Select font size "5x8" or "5x10" (default: "5x8")
117
- exec_time: Command execution time in seconds (default: 50µs)
118
- rotate: Rotation value 0-3 (0°, 90°, 180°, 270°) (default: 0)
119
- framebuffer: Framebuffering strategy (diff_to_previous or full_frame)
120
121
Note: Width/height specified in characters, not pixels.
122
Internal pixel dimensions are width*5 x height*8.
123
"""
124
```
125
126
Usage example:
127
128
```python
129
from luma.core.interface.serial import parallel
130
from luma.oled.device import winstar_weh
131
132
# Initialize 16x2 character display
133
serial = parallel(RS=7, E=8, PINS=[25, 24, 23, 18])
134
device = winstar_weh(serial, width=16, height=2)
135
136
# Display character-based text
137
device.text = "Line 1 Text\nLine 2 Text"
138
139
# Text automatically wraps at character boundaries
140
device.text = "This is a long line of text that will wrap"
141
```
142
143
## Character vs Graphical Modes
144
145
### Character Mode
146
147
Character mode uses the text property for simple text display:
148
149
```python
150
# Character mode - automatic font rendering
151
device.text = "Hello World!\nSecond Line"
152
153
# Supports basic formatting
154
device.text = "Temperature: 23°C\nHumidity: 65%"
155
156
# Unicode characters (if font supports them)
157
device.text = "Café naïve résumé"
158
```
159
160
### Graphical Mode
161
162
Graphical mode provides full drawing capabilities:
163
164
```python
165
# Graphical mode - full PIL drawing
166
with canvas(device) as draw:
167
draw.text((0, 0), "Custom Graphics", fill="white")
168
draw.line([(0, 8), (100, 8)], fill="white")
169
draw.rectangle((10, 10, 90, 15), outline="white")
170
draw.point([(5, 5), (95, 5)], fill="white")
171
```
172
173
## Font Management
174
175
### Using Embedded Fonts
176
177
```python
178
# Select font during initialization
179
device = ws0010(serial, selected_font='FT01') # Western European
180
181
# Or load font dynamically
182
font_obj = device.get_font(2) # English Russian (FT10)
183
184
# Access font by name or number
185
font1 = device.get_font('FT11_10') # 5x10 Western European II
186
font2 = device.get_font(7) # Same font by number
187
```
188
189
### Custom Fonts
190
191
```python
192
from PIL import ImageFont
193
194
# Use custom PIL font instead of embedded fonts
195
custom_font = ImageFont.load("custom.pil")
196
device = ws0010(serial, font=custom_font)
197
198
# Embedded fonts are bypassed when custom font is provided
199
device.text = "Custom Font Text"
200
```
201
202
## Interface Configuration
203
204
Character displays typically use parallel interfaces:
205
206
```python
207
from luma.core.interface.serial import parallel
208
209
# Standard parallel configuration
210
serial = parallel(
211
RS=7, # Register Select pin
212
E=8, # Enable pin
213
PINS=[25, 24, 23, 18] # Data pins (D4-D7 for 4-bit mode)
214
)
215
216
# 8-bit mode (if supported)
217
serial = parallel(
218
RS=7, E=8,
219
PINS=[25, 24, 23, 18, 17, 16, 15, 14] # D0-D7 for 8-bit mode
220
)
221
```
222
223
## Common Patterns
224
225
### Error Handling
226
227
```python
228
import luma.core.error
229
230
try:
231
device = ws0010(serial, width=200, height=200)
232
except luma.core.error.DeviceDisplayModeError as e:
233
print(f"Unsupported display mode: {e}")
234
```
235
236
### Display Initialization
237
238
Character displays have longer initialization times:
239
240
```python
241
from time import sleep
242
243
# Initialize device
244
device = ws0010(serial)
245
246
# Device automatically sleeps 0.5s during initialization
247
# Additional delays may be needed for complex setups
248
sleep(0.1)
249
250
device.text = "Ready!"
251
```
252
253
### Grid Considerations for WEH Displays
254
255
WEH displays have 1-pixel gaps every 5th column:
256
257
```python
258
# WEH displays have grid structure
259
device = winstar_weh(serial, width=16, height=2)
260
261
# Text interface automatically handles grid
262
device.text = "Grid Aligned"
263
264
# For graphics, be aware of grid gaps
265
with canvas(device) as draw:
266
# Gaps occur at x = 5, 10, 15, 20, etc.
267
draw.text((0, 0), "Account for gaps in graphics")
268
```
269
270
### Performance Tips
271
272
```python
273
# Use appropriate framebuffer for usage pattern
274
from luma.core.framebuffer import diff_to_previous, full_frame
275
276
# For frequently changing text
277
device = ws0010(serial, framebuffer=diff_to_previous())
278
279
# For static or infrequent updates
280
device = ws0010(serial, framebuffer=full_frame())
281
282
# Reset display if needed (4-bit mode only)
283
# Device automatically resets when in 4-bit mode for synchronization
284
```