@typecad/framework-zephyr 1.0.0-alpha.18 → 1.0.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audit.d.ts +111 -0
- package/dist/audit.js +416 -0
- package/dist/boardgen.js +63 -5
- package/dist/chips/resolve.js +20 -0
- package/dist/chips/types.d.ts +21 -0
- package/dist/display/bindings.d.ts +55 -0
- package/dist/display/bindings.js +316 -0
- package/dist/display/gfx.d.ts +2 -3
- package/dist/display/gfx.js +166 -154
- package/dist/display/index.js +20 -1
- package/dist/display/mipi-dbi-host.d.ts +9 -0
- package/dist/display/mipi-dbi-host.js +174 -0
- package/dist/display/profiles.d.ts +109 -4
- package/dist/display/profiles.js +270 -7
- package/dist/display/touch-adapter.js +118 -48
- package/dist/display/ui-adapter-eink.d.ts +2 -0
- package/dist/display/ui-adapter-eink.js +4 -0
- package/dist/display/ui-adapter-gray.d.ts +8 -0
- package/dist/display/ui-adapter-gray.js +170 -0
- package/dist/display/ui-adapter-mono.d.ts +13 -0
- package/dist/display/ui-adapter-mono.js +230 -0
- package/dist/display/ui-adapter-native.d.ts +10 -0
- package/dist/display/ui-adapter-native.js +295 -0
- package/dist/display/ui-adapter-shared.d.ts +11 -0
- package/dist/display/ui-adapter-shared.js +122 -0
- package/dist/display/ui-adapter.js +53 -101
- package/dist/dt-config/kconfig.d.ts +62 -1
- package/dist/dt-config/kconfig.js +123 -26
- package/dist/dt-config/overlay.d.ts +13 -0
- package/dist/dt-config/overlay.js +431 -16
- package/dist/framework.manifest.d.ts +9 -3
- package/dist/framework.manifest.js +123 -10
- package/dist/index.d.ts +2 -0
- package/dist/index.js +9 -1
- package/dist/licenses.js +5 -84
- package/dist/lowering/can.d.ts +25 -0
- package/dist/lowering/can.js +97 -0
- package/dist/lowering/clock.d.ts +17 -0
- package/dist/lowering/clock.js +58 -0
- package/dist/lowering/hid.d.ts +27 -0
- package/dist/lowering/hid.js +244 -0
- package/dist/lowering/i2c.d.ts +8 -0
- package/dist/lowering/i2c.js +140 -0
- package/dist/lowering/i2s.d.ts +27 -0
- package/dist/lowering/i2s.js +98 -0
- package/dist/lowering/index.d.ts +9 -1
- package/dist/lowering/index.js +25 -1
- package/dist/lowering/matrix.d.ts +15 -0
- package/dist/lowering/matrix.js +63 -0
- package/dist/lowering/power.d.ts +10 -0
- package/dist/lowering/power.js +35 -0
- package/dist/lowering/pwm.js +25 -0
- package/dist/lowering/sensor.d.ts +2 -2
- package/dist/lowering/sensor.js +8 -4
- package/dist/lowering/strip.d.ts +16 -0
- package/dist/lowering/strip.js +70 -0
- package/dist/lowering/thread.js +5 -1
- package/dist/lowering/trace.d.ts +44 -0
- package/dist/lowering/trace.js +239 -0
- package/dist/lowering/uart.js +6 -1
- package/dist/lowering/usb.d.ts +3 -1
- package/dist/lowering/usb.js +6 -3
- package/dist/sbom.d.ts +181 -0
- package/dist/sbom.js +901 -0
- package/dist/strategy.d.ts +60 -2
- package/dist/strategy.js +485 -25
- package/dist/toolchain/index.d.ts +12 -1
- package/dist/toolchain/index.js +115 -27
- package/dist/toolchain/scaffold.d.ts +4 -1
- package/dist/toolchain/scaffold.js +67 -3
- package/dist/west-inventory.d.ts +25 -0
- package/dist/west-inventory.js +97 -0
- package/package.json +3 -3
- package/src/audit.ts +529 -0
- package/src/boardgen.ts +54 -5
- package/src/chips/resolve.ts +21 -0
- package/src/chips/types.ts +576 -567
- package/src/display/bindings.ts +347 -0
- package/src/display/gfx.ts +318 -306
- package/src/display/index.ts +87 -70
- package/src/display/mipi-dbi-host.ts +183 -0
- package/src/display/profiles.ts +458 -139
- package/src/display/touch-adapter.ts +274 -204
- package/src/display/ui-adapter-eink.ts +13 -0
- package/src/display/ui-adapter-gray.ts +178 -0
- package/src/display/ui-adapter-mono.ts +238 -0
- package/src/display/ui-adapter-native.ts +304 -0
- package/src/display/ui-adapter-shared.ts +125 -0
- package/src/display/ui-adapter.ts +51 -100
- package/src/dt-config/kconfig.ts +647 -511
- package/src/dt-config/overlay.ts +433 -16
- package/src/framework.manifest.ts +131 -10
- package/src/index.ts +11 -1
- package/src/licenses.ts +5 -84
- package/src/lowering/can.ts +140 -0
- package/src/lowering/clock.ts +91 -0
- package/src/lowering/hid.ts +261 -0
- package/src/lowering/i2c.ts +146 -0
- package/src/lowering/i2s.ts +143 -0
- package/src/lowering/index.ts +18 -1
- package/src/lowering/matrix.ts +70 -0
- package/src/lowering/power.ts +41 -0
- package/src/lowering/pwm.ts +192 -167
- package/src/lowering/sensor.ts +159 -155
- package/src/lowering/strip.ts +81 -0
- package/src/lowering/thread.ts +5 -1
- package/src/lowering/trace.ts +270 -0
- package/src/lowering/uart.ts +6 -1
- package/src/lowering/usb.ts +224 -221
- package/src/sbom.ts +1117 -0
- package/src/strategy.ts +440 -25
- package/src/toolchain/index.ts +117 -28
- package/src/toolchain/scaffold.ts +62 -3
- package/src/west-inventory.ts +102 -0
package/src/display/gfx.ts
CHANGED
|
@@ -1,306 +1,318 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Zephyr display GFX runtime — generic display_write + ported GFX primitives
|
|
3
|
-
//
|
|
4
|
-
// Emits C++ that resolves a DT-bound display device, keeps a one-row line
|
|
5
|
-
// buffer (no full framebuffer — see AGENTS.md rendering guardrails), and
|
|
6
|
-
// implements fill_rect / draw_rect / draw_text / flush on top of display_write.
|
|
7
|
-
// Text uses a minimal 5x7 bitmap font covering digits 0-9 and uppercase A-Z
|
|
8
|
-
// only; unknown characters render as a space.
|
|
9
|
-
//
|
|
10
|
-
// EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
|
|
11
|
-
// Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
|
|
14
|
-
import type { ZephyrDisplayProfile } from './profiles.js';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
39
|
-
'
|
|
40
|
-
'
|
|
41
|
-
'
|
|
42
|
-
'
|
|
43
|
-
'
|
|
44
|
-
'
|
|
45
|
-
'
|
|
46
|
-
'
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
'
|
|
50
|
-
'
|
|
51
|
-
'
|
|
52
|
-
'
|
|
53
|
-
'
|
|
54
|
-
'
|
|
55
|
-
'
|
|
56
|
-
'
|
|
57
|
-
'
|
|
58
|
-
'
|
|
59
|
-
'
|
|
60
|
-
'
|
|
61
|
-
'
|
|
62
|
-
'
|
|
63
|
-
'
|
|
64
|
-
'
|
|
65
|
-
'
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
'//
|
|
73
|
-
'
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*/
|
|
102
|
-
export function buildDisplayRuntime(profile: ZephyrDisplayProfile): DisplayRuntimeResult {
|
|
103
|
-
const w = profile.width;
|
|
104
|
-
const h = profile.height;
|
|
105
|
-
const isMono = profile.colorFormat === 'mono';
|
|
106
|
-
|
|
107
|
-
// Backlight is optional: the overlay emits the DT alias only when a backlight
|
|
108
|
-
// GPIO is configured. Guard with DT_HAS_ALIAS so this compiles whether or not
|
|
109
|
-
// the alias exists (DT_NODE_HAS_STATUS(DT_ALIAS(...)) is version-dependent
|
|
110
|
-
// when the alias is missing).
|
|
111
|
-
const blInit = profile.backlight
|
|
112
|
-
? `#if DT_HAS_ALIAS(${profile.backlight})\n const struct device* __bl = DEVICE_DT_GET(DT_ALIAS(${profile.backlight}));\n gpio_pin_configure(__bl, 0, GPIO_OUTPUT); gpio_pin_set(__bl, 0, 1);\n#endif`
|
|
113
|
-
: '';
|
|
114
|
-
|
|
115
|
-
const stateLines = isMono
|
|
116
|
-
? [
|
|
117
|
-
'// CUTTLEFISH_DISPLAY_BEGIN',
|
|
118
|
-
`static const struct device* __tc_display = DEVICE_DT_GET(DT_NODELABEL(${profile.dtLabel}));`,
|
|
119
|
-
`// Mono framebuffer
|
|
120
|
-
|
|
121
|
-
'
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
for (uint16_t row =
|
|
269
|
-
__tc_display_line[
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
uint16_t
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Zephyr display GFX runtime — generic display_write + ported GFX primitives
|
|
3
|
+
//
|
|
4
|
+
// Emits C++ that resolves a DT-bound display device, keeps a one-row line
|
|
5
|
+
// buffer (no full framebuffer — see AGENTS.md rendering guardrails), and
|
|
6
|
+
// implements fill_rect / draw_rect / draw_text / flush on top of display_write.
|
|
7
|
+
// Text uses a minimal 5x7 bitmap font covering digits 0-9 and uppercase A-Z
|
|
8
|
+
// only; unknown characters render as a space.
|
|
9
|
+
//
|
|
10
|
+
// EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
|
|
11
|
+
// Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
import type { ZephyrDisplayProfile } from './profiles.js';
|
|
15
|
+
import { displayFactsLine } from './profiles.js';
|
|
16
|
+
|
|
17
|
+
export interface DisplayRuntimeResult {
|
|
18
|
+
/** #include lines to force when the display is used. */
|
|
19
|
+
readonly includes: string[];
|
|
20
|
+
/** File-scope C++ declarations (device handle + line buffer). */
|
|
21
|
+
readonly stateLines: string[];
|
|
22
|
+
/** The C++ helper functions (display_init/fill_rect/draw_rect/draw_text/flush). */
|
|
23
|
+
readonly helpers: string;
|
|
24
|
+
/** The C++ font-table source (exposed for testing). */
|
|
25
|
+
readonly fontTable: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 5x7 bitmap glyphs for 0-9 and A-Z. Each glyph is 5 bytes (columns), MSB=top.
|
|
29
|
+
// Unknown characters fall back to the space (all-zero columns).
|
|
30
|
+
// (Compact hand-authored bitmaps; the test asserts presence of '0'..'9','A'..'Z'.)
|
|
31
|
+
function fontTableCpp(): string {
|
|
32
|
+
// A flat map: char -> 5 bytes. Built so the test sees '0'..'9' and 'A'..'Z'.
|
|
33
|
+
const glyphs: Record<string, number[]> = {
|
|
34
|
+
'0': [0x3e, 0x51, 0x49, 0x45, 0x3e],
|
|
35
|
+
'1': [0x00, 0x42, 0x7f, 0x40, 0x00],
|
|
36
|
+
'2': [0x42, 0x61, 0x51, 0x49, 0x46],
|
|
37
|
+
'3': [0x21, 0x41, 0x45, 0x4b, 0x31],
|
|
38
|
+
'4': [0x18, 0x14, 0x12, 0x7f, 0x10],
|
|
39
|
+
'5': [0x27, 0x45, 0x45, 0x45, 0x39],
|
|
40
|
+
'6': [0x3c, 0x4a, 0x49, 0x49, 0x30],
|
|
41
|
+
'7': [0x01, 0x71, 0x09, 0x05, 0x03],
|
|
42
|
+
'8': [0x36, 0x49, 0x49, 0x49, 0x36],
|
|
43
|
+
'9': [0x06, 0x49, 0x49, 0x29, 0x1e],
|
|
44
|
+
'A': [0x7e, 0x11, 0x11, 0x11, 0x7e],
|
|
45
|
+
'B': [0x7f, 0x49, 0x49, 0x49, 0x36],
|
|
46
|
+
'C': [0x3e, 0x41, 0x41, 0x41, 0x22],
|
|
47
|
+
'D': [0x7f, 0x41, 0x41, 0x22, 0x1c],
|
|
48
|
+
'E': [0x7f, 0x49, 0x49, 0x49, 0x41],
|
|
49
|
+
'F': [0x7f, 0x09, 0x09, 0x09, 0x01],
|
|
50
|
+
'G': [0x3e, 0x41, 0x49, 0x49, 0x7a],
|
|
51
|
+
'H': [0x7f, 0x08, 0x08, 0x08, 0x7f],
|
|
52
|
+
'I': [0x00, 0x41, 0x7f, 0x41, 0x00],
|
|
53
|
+
'J': [0x20, 0x40, 0x41, 0x3f, 0x01],
|
|
54
|
+
'K': [0x7f, 0x08, 0x14, 0x22, 0x41],
|
|
55
|
+
'L': [0x7f, 0x40, 0x40, 0x40, 0x40],
|
|
56
|
+
'M': [0x7f, 0x02, 0x0c, 0x02, 0x7f],
|
|
57
|
+
'N': [0x7f, 0x04, 0x08, 0x10, 0x7f],
|
|
58
|
+
'O': [0x3e, 0x41, 0x41, 0x41, 0x3e],
|
|
59
|
+
'P': [0x7f, 0x09, 0x09, 0x09, 0x06],
|
|
60
|
+
'Q': [0x3e, 0x41, 0x51, 0x21, 0x5e],
|
|
61
|
+
'R': [0x7f, 0x09, 0x19, 0x29, 0x46],
|
|
62
|
+
'S': [0x46, 0x49, 0x49, 0x49, 0x31],
|
|
63
|
+
'T': [0x01, 0x01, 0x7f, 0x01, 0x01],
|
|
64
|
+
'U': [0x3f, 0x40, 0x40, 0x40, 0x3f],
|
|
65
|
+
'V': [0x1f, 0x20, 0x40, 0x20, 0x1f],
|
|
66
|
+
'W': [0x3f, 0x40, 0x38, 0x40, 0x3f],
|
|
67
|
+
'X': [0x63, 0x14, 0x08, 0x14, 0x63],
|
|
68
|
+
'Y': [0x07, 0x08, 0x70, 0x08, 0x07],
|
|
69
|
+
'Z': [0x61, 0x51, 0x49, 0x45, 0x43],
|
|
70
|
+
};
|
|
71
|
+
const lines: string[] = [
|
|
72
|
+
'// Minimal 5x7 font: digits 0-9 and uppercase A-Z. Unknown chars → space.',
|
|
73
|
+
'// (Rows for other codes are all-zero — the table is indexed by char code.)',
|
|
74
|
+
'static const uint8_t __tc_font5x7[128][5] = {',
|
|
75
|
+
];
|
|
76
|
+
for (let c = 0; c < 128; c++) {
|
|
77
|
+
const ch = String.fromCharCode(c);
|
|
78
|
+
const known = Object.prototype.hasOwnProperty.call(glyphs, ch);
|
|
79
|
+
const g = glyphs[ch] ?? [0x00, 0x00, 0x00, 0x00, 0x00];
|
|
80
|
+
// Annotate known glyphs (0-9, A-Z) with their char literal; other rows use
|
|
81
|
+
// only the code point so the table carries no stray char literals.
|
|
82
|
+
const label = known ? ` '${ch}'` : ` ${c}`;
|
|
83
|
+
lines.push(` {0x${g[0].toString(16).padStart(2, '0')}, 0x${g[1].toString(16).padStart(2, '0')}, 0x${g[2].toString(16).padStart(2, '0')}, 0x${g[3].toString(16).padStart(2, '0')}, 0x${g[4].toString(16).padStart(2, '0')}}, //${label}`);
|
|
84
|
+
}
|
|
85
|
+
lines.push('};');
|
|
86
|
+
return lines.join('\n');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Build the display runtime C++ for a profile.
|
|
91
|
+
*
|
|
92
|
+
* Two rendering models, selected by `profile.colorFormat`:
|
|
93
|
+
* - `'rgb565'` (TFT): a one-row line buffer (no full framebuffer — see
|
|
94
|
+
* AGENTS.md rendering guardrails); fill_rect/draw_rect/draw_text stream
|
|
95
|
+
* each row via display_write.
|
|
96
|
+
* - `'mono'` (OLED, e.g. SSD1306): a full framebuffer — the standard model
|
|
97
|
+
* for page-buffered monochrome panels (the AGENTS.md "no full framebuffer"
|
|
98
|
+
* guardrail targets RGB SPI TFTs, not mono OLEDs). draw ops set bits;
|
|
99
|
+
* display_flush pushes the whole framebuffer as VTILED MONO01 (the layout
|
|
100
|
+
* the driver consumes; see monoHelpers).
|
|
101
|
+
*/
|
|
102
|
+
export function buildDisplayRuntime(profile: ZephyrDisplayProfile): DisplayRuntimeResult {
|
|
103
|
+
const w = profile.width;
|
|
104
|
+
const h = profile.height;
|
|
105
|
+
const isMono = profile.colorFormat === 'mono';
|
|
106
|
+
|
|
107
|
+
// Backlight is optional: the overlay emits the DT alias only when a backlight
|
|
108
|
+
// GPIO is configured. Guard with DT_HAS_ALIAS so this compiles whether or not
|
|
109
|
+
// the alias exists (DT_NODE_HAS_STATUS(DT_ALIAS(...)) is version-dependent
|
|
110
|
+
// when the alias is missing).
|
|
111
|
+
const blInit = profile.backlight
|
|
112
|
+
? `#if DT_HAS_ALIAS(${profile.backlight})\n const struct device* __bl = DEVICE_DT_GET(DT_ALIAS(${profile.backlight}));\n gpio_pin_configure(__bl, 0, GPIO_OUTPUT); gpio_pin_set(__bl, 0, 1);\n#endif`
|
|
113
|
+
: '';
|
|
114
|
+
|
|
115
|
+
const stateLines = isMono
|
|
116
|
+
? [
|
|
117
|
+
'// CUTTLEFISH_DISPLAY_BEGIN',
|
|
118
|
+
`static const struct device* __tc_display = DEVICE_DT_GET(DT_NODELABEL(${profile.dtLabel}));`,
|
|
119
|
+
`// Mono framebuffer, vtiled MONO01 — the layout Zephyr's ssd1306-class`,
|
|
120
|
+
`// drivers expect from display_write (SCREEN_INFO_MONO_VTILED, matching`,
|
|
121
|
+
`// cfb's draw_point): byte = fb[(y>>3)*${w} + x], bit = 1<<(y&7).`,
|
|
122
|
+
`// pitch must equal width and (y, height) must be multiples of 8 — the`,
|
|
123
|
+
`// full-frame flush satisfies both by construction.`,
|
|
124
|
+
`static uint8_t __tc_display_fb[(${w} * ${h} + 7) / 8];`,
|
|
125
|
+
'// CUTTLEFISH_DISPLAY_END',
|
|
126
|
+
]
|
|
127
|
+
: [
|
|
128
|
+
'// CUTTLEFISH_DISPLAY_BEGIN',
|
|
129
|
+
`static const struct device* __tc_display = DEVICE_DT_GET(DT_NODELABEL(${profile.dtLabel}));`,
|
|
130
|
+
`static uint16_t __tc_display_line[${w}]; // one-row line buffer (rgb565)`,
|
|
131
|
+
'// CUTTLEFISH_DISPLAY_END',
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
const helpers = isMono
|
|
135
|
+
? monoHelpers(w, h, blInit)
|
|
136
|
+
: rgb565Helpers(w, blInit);
|
|
137
|
+
|
|
138
|
+
const fontTable = fontTableCpp();
|
|
139
|
+
|
|
140
|
+
return {
|
|
141
|
+
includes: ['<zephyr/drivers/display.h>'],
|
|
142
|
+
// Profile marker: lets the toolchain recover which profile emitted this
|
|
143
|
+
// runtime (profileFromEmittedSource in profiles.ts) instead of re-deriving
|
|
144
|
+
// geometry from the emitted C.
|
|
145
|
+
stateLines: [`// typecad-display-profile: ${profile.driver}`, displayFactsLine(profile), ...stateLines],
|
|
146
|
+
helpers,
|
|
147
|
+
fontTable,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Mono (OLED) helpers: a full framebuffer + bit-packing. SSD1306-class panels
|
|
153
|
+
* are page-buffered, so draw ops set bits in the framebuffer and display_flush
|
|
154
|
+
* pushes the whole buffer. color != 0 ⇒ lit. The packing is VTILED MONO01
|
|
155
|
+
* (byte = 8 vertical pixels, fb[(y>>3)*W + x], bit = 1<<(y&7)) because that
|
|
156
|
+
* is what the driver's display_write consumes — a horizontal-packed buffer
|
|
157
|
+
* with pitch = rowBytes fails the driver's pitch==width check (-EINVAL) and
|
|
158
|
+
* nothing reaches the panel.
|
|
159
|
+
*/
|
|
160
|
+
function monoHelpers(w: number, h: number, blInit: string): string {
|
|
161
|
+
return `
|
|
162
|
+
// VTILED MONO01 pixel packing: byte = fb[(y>>3)*${w}] + x, bit = 1<<(y&7).
|
|
163
|
+
static inline void __tc_set_pixel(uint16_t x, uint16_t y, uint8_t on) {
|
|
164
|
+
if ((x >= ${w}U) || (y >= ${h}U)) { return; }
|
|
165
|
+
uint16_t idx = static_cast<uint16_t>((static_cast<uint32_t>(y) >> 3) * ${w}U + x);
|
|
166
|
+
uint8_t mask = static_cast<uint8_t>(1U << (y & 7U));
|
|
167
|
+
if (on != 0U) {
|
|
168
|
+
__tc_display_fb[idx] = static_cast<uint8_t>(__tc_display_fb[idx] | mask);
|
|
169
|
+
} else {
|
|
170
|
+
__tc_display_fb[idx] = static_cast<uint8_t>(__tc_display_fb[idx] & static_cast<uint8_t>(~mask));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
static inline void display_init(void) {
|
|
175
|
+
if (!device_is_ready(__tc_display)) { for (;;) { k_msleep(1000); } }
|
|
176
|
+
${blInit}
|
|
177
|
+
for (uint16_t i = 0; i < static_cast<uint16_t>(sizeof(__tc_display_fb)); i++) { __tc_display_fb[i] = 0U; }
|
|
178
|
+
display_blanking_off(__tc_display);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
static inline void display_fill_rect(uint16_t x, uint16_t y, uint16_t rw, uint16_t rh, uint16_t color) {
|
|
182
|
+
uint8_t on = (color != 0U) ? 1U : 0U;
|
|
183
|
+
for (uint16_t row = 0; row < rh; row++) {
|
|
184
|
+
for (uint16_t i = 0; i < rw; i++) {
|
|
185
|
+
__tc_set_pixel(static_cast<uint16_t>(x + i), static_cast<uint16_t>(y + row), on);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
static inline void display_draw_rect(uint16_t x, uint16_t y, uint16_t rw, uint16_t rh, uint16_t color) {
|
|
191
|
+
uint8_t on = (color != 0U) ? 1U : 0U;
|
|
192
|
+
for (uint16_t i = 0; i < rw; i++) {
|
|
193
|
+
__tc_set_pixel(static_cast<uint16_t>(x + i), y, on);
|
|
194
|
+
__tc_set_pixel(static_cast<uint16_t>(x + i), static_cast<uint16_t>(y + rh - 1U), on);
|
|
195
|
+
}
|
|
196
|
+
for (uint16_t row = 1U; row < rh - 1U; row++) {
|
|
197
|
+
__tc_set_pixel(x, static_cast<uint16_t>(y + row), on);
|
|
198
|
+
__tc_set_pixel(static_cast<uint16_t>(x + rw - 1U), static_cast<uint16_t>(y + row), on);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
static inline void display_draw_text(uint16_t x, uint16_t y, const char* text, uint16_t color) {
|
|
203
|
+
uint8_t on = (color != 0U) ? 1U : 0U;
|
|
204
|
+
uint16_t cx = x;
|
|
205
|
+
for (const char* p = text; *p != 0; p++) {
|
|
206
|
+
uint8_t uc = static_cast<uint8_t>(*p);
|
|
207
|
+
if (uc >= 128U) { uc = static_cast<uint8_t>(' '); }
|
|
208
|
+
const uint8_t* glyph = &__tc_font5x7[uc][0];
|
|
209
|
+
if (uc >= static_cast<uint8_t>('a') && uc <= static_cast<uint8_t>('z')) {
|
|
210
|
+
glyph = &__tc_font5x7[uc - 32U][0];
|
|
211
|
+
} else if (uc < static_cast<uint8_t>('0')
|
|
212
|
+
|| (uc > static_cast<uint8_t>('9') && uc < static_cast<uint8_t>('A'))
|
|
213
|
+
|| uc > static_cast<uint8_t>('Z')) {
|
|
214
|
+
glyph = &__tc_font5x7[static_cast<uint8_t>(' ')][0];
|
|
215
|
+
}
|
|
216
|
+
for (uint16_t col = 0; col < 5U; col++) {
|
|
217
|
+
uint8_t bits = glyph[col];
|
|
218
|
+
for (uint16_t row = 0; row < 7U; row++) {
|
|
219
|
+
if ((bits & static_cast<uint8_t>(1U << row)) != 0U) {
|
|
220
|
+
__tc_set_pixel(static_cast<uint16_t>(cx + col), static_cast<uint16_t>(y + row), on);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
cx = static_cast<uint16_t>(cx + 6U);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
static inline void display_flush(void) {
|
|
229
|
+
// Full-frame push. pitch = width and height a multiple of 8 are the
|
|
230
|
+
// ssd1306 driver's hard requirements — the full frame satisfies both.
|
|
231
|
+
struct display_buffer_descriptor __desc;
|
|
232
|
+
__desc.buf_size = sizeof(__tc_display_fb); // ${w} * ${h} / 8 bytes
|
|
233
|
+
__desc.width = ${w}U;
|
|
234
|
+
__desc.height = ${h}U;
|
|
235
|
+
__desc.pitch = ${w}U; // vtiled: bytes per 8-pixel page row == width
|
|
236
|
+
__desc.frame_incomplete = false;
|
|
237
|
+
(void)display_write(__tc_display, 0, 0, &__desc, __tc_display_fb);
|
|
238
|
+
}
|
|
239
|
+
`;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* RGB565 (TFT) helpers: a one-row line buffer; each op streams rows via
|
|
244
|
+
* display_write. No full framebuffer (AGENTS.md rendering guardrails).
|
|
245
|
+
*/
|
|
246
|
+
function rgb565Helpers(w: number, blInit: string): string {
|
|
247
|
+
return `
|
|
248
|
+
// Write a single row of \`rw\` rgb565 pixels at (x,y). Builds the
|
|
249
|
+
// display_buffer_descriptor the Zephyr display_write API requires (rgb565 =
|
|
250
|
+
// 2 bytes/pixel) and pushes the one-row line buffer.
|
|
251
|
+
static inline void __tc_display_write_row(uint16_t x, uint16_t y, uint16_t rw) {
|
|
252
|
+
struct display_buffer_descriptor __desc;
|
|
253
|
+
__desc.buf_size = static_cast<uint32_t>(rw) * 2U; // 2 bytes per rgb565 pixel
|
|
254
|
+
__desc.width = rw;
|
|
255
|
+
__desc.height = 1U;
|
|
256
|
+
__desc.pitch = rw;
|
|
257
|
+
__desc.frame_incomplete = false;
|
|
258
|
+
(void)display_write(__tc_display, x, y, &__desc, __tc_display_line);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static inline void display_init(void) {
|
|
262
|
+
if (!device_is_ready(__tc_display)) { for (;;) { k_msleep(1000); } }
|
|
263
|
+
${blInit}
|
|
264
|
+
display_blanking_off(__tc_display);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
static inline void display_fill_rect(uint16_t x, uint16_t y, uint16_t rw, uint16_t h, uint16_t color) {
|
|
268
|
+
for (uint16_t row = 0; row < h; row++) {
|
|
269
|
+
for (uint16_t i = 0; i < rw; i++) { __tc_display_line[i] = color; }
|
|
270
|
+
__tc_display_write_row(x, static_cast<uint16_t>(y + row), rw);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
static inline void display_draw_rect(uint16_t x, uint16_t y, uint16_t rw, uint16_t h, uint16_t color) {
|
|
275
|
+
// Top + bottom edges.
|
|
276
|
+
for (uint16_t i = 0; i < rw; i++) { __tc_display_line[i] = color; }
|
|
277
|
+
__tc_display_write_row(x, y, rw);
|
|
278
|
+
__tc_display_write_row(x, static_cast<uint16_t>(y + h - 1U), rw);
|
|
279
|
+
// Left + right edges.
|
|
280
|
+
for (uint16_t row = 1U; row < h - 1U; row++) {
|
|
281
|
+
__tc_display_line[0] = color;
|
|
282
|
+
if (rw > 1U) { __tc_display_line[rw - 1U] = color; }
|
|
283
|
+
__tc_display_write_row(x, static_cast<uint16_t>(y + row), rw);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
static inline void display_draw_text(uint16_t x, uint16_t y, const char* text, uint16_t color) {
|
|
288
|
+
uint16_t cx = x;
|
|
289
|
+
for (const char* p = text; *p != 0; p++) {
|
|
290
|
+
// Read the byte UNSIGNED so bytes >= 0x80 don't index the 128-entry
|
|
291
|
+
// font table negatively (signed char would make 0x80 == -128).
|
|
292
|
+
uint8_t uc = static_cast<uint8_t>(*p);
|
|
293
|
+
if (uc >= 128U) { uc = static_cast<uint8_t>(' '); } // unknown → space
|
|
294
|
+
const uint8_t* glyph = &__tc_font5x7[uc][0];
|
|
295
|
+
// Lowercase → uppercase; anything outside 0-9/A-Z → space glyph.
|
|
296
|
+
if (uc >= static_cast<uint8_t>('a') && uc <= static_cast<uint8_t>('z')) {
|
|
297
|
+
glyph = &__tc_font5x7[uc - 32U][0];
|
|
298
|
+
} else if (uc < static_cast<uint8_t>('0')
|
|
299
|
+
|| (uc > static_cast<uint8_t>('9') && uc < static_cast<uint8_t>('A'))
|
|
300
|
+
|| uc > static_cast<uint8_t>('Z')) {
|
|
301
|
+
glyph = &__tc_font5x7[static_cast<uint8_t>(' ')][0];
|
|
302
|
+
}
|
|
303
|
+
for (uint16_t col = 0; col < 5U; col++) {
|
|
304
|
+
uint8_t bits = glyph[col];
|
|
305
|
+
for (uint16_t row = 0; row < 7U; row++) {
|
|
306
|
+
__tc_display_line[0] = ((bits & static_cast<uint8_t>(1U << row)) != 0U) ? color : 0U;
|
|
307
|
+
__tc_display_write_row(static_cast<uint16_t>(cx + col), static_cast<uint16_t>(y + row), 1U);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
cx = static_cast<uint16_t>(cx + 6U); // 5 cols + 1 space
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
static inline void display_flush(void) {
|
|
315
|
+
// No-op: writes are immediate via display_write; there is no framebuffer to push.
|
|
316
|
+
}
|
|
317
|
+
`;
|
|
318
|
+
}
|