@typecad/framework-zephyr 1.0.0-alpha.16 → 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/LICENSE +202 -21
- package/README.md +49 -87
- package/dist/as-built.d.ts +2 -2
- package/dist/as-built.js +2 -2
- package/dist/audit.d.ts +111 -0
- package/dist/audit.js +416 -0
- package/dist/boardgen.d.ts +1 -9
- package/dist/boardgen.js +288 -47
- package/dist/chips/resolve.js +20 -0
- package/dist/chips/types.d.ts +22 -1
- package/dist/debug-codegen.js +1 -1
- 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 +119 -49
- 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 +510 -558
- package/dist/doctor.js +4 -4
- package/dist/dt-config/custom-board.js +2 -2
- package/dist/dt-config/kconfig.d.ts +62 -1
- package/dist/dt-config/kconfig.js +141 -38
- package/dist/dt-config/overlay.d.ts +15 -2
- package/dist/dt-config/overlay.js +433 -18
- package/dist/framework.manifest.d.ts +10 -4
- package/dist/framework.manifest.js +133 -17
- package/dist/index.d.ts +2 -0
- package/dist/index.js +14 -6
- package/dist/licenses.d.ts +2 -2
- package/dist/licenses.js +13 -92
- 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/fs.js +1 -1
- package/dist/lowering/gpio.js +0 -32
- package/dist/lowering/hid.d.ts +27 -0
- package/dist/lowering/hid.js +244 -0
- package/dist/lowering/http.js +264 -32
- package/dist/lowering/i2c.d.ts +8 -0
- package/dist/lowering/i2c.js +137 -5
- 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/interrupts.js +6 -0
- package/dist/lowering/matrix.d.ts +15 -0
- package/dist/lowering/matrix.js +63 -0
- package/dist/lowering/mqtt.js +110 -8
- package/dist/lowering/power.d.ts +3 -2
- package/dist/lowering/power.js +20 -45
- 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 +16 -13
- package/dist/lowering/wdt.js +2 -29
- package/dist/sbom.d.ts +181 -0
- package/dist/sbom.js +901 -0
- package/dist/sdk/board-catalog-sync.d.ts +1 -3
- package/dist/sdk/board-catalog-sync.js +4 -10
- package/dist/strategy.d.ts +82 -46
- package/dist/strategy.js +639 -182
- package/dist/tmp-probe.d.ts +2 -0
- package/dist/tmp-probe.js +9 -0
- package/dist/toolchain/debug-config.d.ts +50 -90
- package/dist/toolchain/debug-config.js +239 -510
- package/dist/toolchain/env-check.d.ts +1 -3
- package/dist/toolchain/env-check.js +2 -7
- package/dist/toolchain/index.d.ts +28 -3
- package/dist/toolchain/index.js +498 -62
- package/dist/toolchain/runners.d.ts +16 -0
- package/dist/toolchain/runners.js +75 -0
- package/dist/toolchain/scaffold.d.ts +5 -2
- package/dist/toolchain/scaffold.js +79 -15
- package/dist/toolchain/west-discover.d.ts +6 -0
- package/dist/toolchain/west-discover.js +36 -13
- package/dist/toolchain/west-spawn.js +8 -2
- package/dist/west-inventory.d.ts +25 -0
- package/dist/west-inventory.js +97 -0
- package/installer/README.md +328 -328
- package/installer/install.sh +2 -2
- package/installer/templates/project/.typecad/activate-zephyr.ps1 +1 -1
- package/installer/templates/project/.typecad/activate-zephyr.sh +1 -1
- package/installer/templates/project/.vscode/settings.json +1 -1
- package/installer/templates/project/README.md +2 -2
- package/package.json +5 -5
- package/src/as-built.ts +206 -206
- package/src/audit.ts +529 -0
- package/src/boardgen.ts +265 -50
- package/src/chips/resolve.ts +21 -0
- package/src/chips/types.ts +10 -1
- 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 +119 -49
- 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 +732 -781
- package/src/doctor.ts +4 -4
- package/src/dt-config/custom-board.ts +2 -2
- package/src/dt-config/kconfig.ts +647 -505
- package/src/dt-config/overlay.ts +1475 -1058
- package/src/framework.manifest.ts +659 -535
- package/src/index.ts +16 -6
- package/src/licenses.ts +346 -425
- package/src/lowering/can.ts +140 -0
- package/src/lowering/clock.ts +91 -0
- package/src/lowering/fs.ts +135 -135
- package/src/lowering/gpio.ts +0 -33
- package/src/lowering/hid.ts +261 -0
- package/src/lowering/http.ts +264 -32
- package/src/lowering/i2c.ts +142 -5
- package/src/lowering/i2s.ts +143 -0
- package/src/lowering/index.ts +18 -1
- package/src/lowering/interrupts.ts +6 -0
- package/src/lowering/matrix.ts +70 -0
- package/src/lowering/mqtt.ts +109 -8
- 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 +16 -13
- package/src/lowering/wdt.ts +2 -25
- package/src/sbom.ts +1117 -0
- package/src/sdk/board-catalog-sync.ts +4 -25
- package/src/strategy.ts +2680 -2309
- package/src/toolchain/debug-config.ts +262 -522
- package/src/toolchain/env-check.ts +279 -285
- package/src/toolchain/index.ts +1792 -1359
- package/src/toolchain/runners.ts +80 -0
- package/src/toolchain/scaffold.ts +355 -296
- package/src/toolchain/west-discover.ts +35 -13
- package/src/toolchain/west-spawn.ts +174 -168
- package/src/west-inventory.ts +102 -0
- package/dist/async/timer-polyfill.d.ts +0 -10
- package/dist/async/timer-polyfill.js +0 -95
- package/dist/chips/board-overrides.d.ts +0 -7
- package/dist/chips/board-overrides.js +0 -11
- package/dist/chips/esp32.d.ts +0 -2
- package/dist/chips/esp32.js +0 -71
- package/dist/chips/esp32s3.d.ts +0 -2
- package/dist/chips/esp32s3.js +0 -103
- package/dist/chips/soc/.d.ts +0 -2
- package/dist/chips/soc/.js +0 -129
- package/dist/chips/soc/esp32.d.ts +0 -2
- package/dist/chips/soc/esp32.js +0 -120
- package/dist/chips/soc/esp32c3.d.ts +0 -2
- package/dist/chips/soc/esp32c3.js +0 -90
- package/dist/chips/soc/esp32c6.d.ts +0 -2
- package/dist/chips/soc/esp32c6.js +0 -109
- package/dist/chips/soc/esp32s3.d.ts +0 -2
- package/dist/chips/soc/esp32s3.js +0 -189
- package/dist/chips/soc/index.d.ts +0 -2
- package/dist/chips/soc/index.js +0 -23
- package/dist/chips/soc/nrf52840.d.ts +0 -2
- package/dist/chips/soc/nrf52840.js +0 -130
- package/dist/chips/soc/rp2040.d.ts +0 -2
- package/dist/chips/soc/rp2040.js +0 -141
- package/dist/chips/soc/rp2350a.d.ts +0 -2
- package/dist/chips/soc/rp2350a.js +0 -145
- package/dist/chips/soc/samd21g18a.d.ts +0 -2
- package/dist/chips/soc/samd21g18a.js +0 -143
- package/dist/chips/soc/stm32f411xe.d.ts +0 -2
- package/dist/chips/soc/stm32f411xe.js +0 -251
- package/dist/chips/xiao-ble.d.ts +0 -2
- package/dist/chips/xiao-ble.js +0 -100
- package/dist/lowering/pulse.d.ts +0 -7
- package/dist/lowering/pulse.js +0 -51
- package/dist/lowering/tone.d.ts +0 -10
- package/dist/lowering/tone.js +0 -63
- package/dist/lowering/worker-backing.d.ts +0 -14
- package/dist/lowering/worker-backing.js +0 -79
- package/dist/lowering/worker.d.ts +0 -6
- package/dist/lowering/worker.js +0 -14
- package/dist/sdk/board-data.generated.d.ts +0 -2
- package/dist/sdk/board-data.generated.js +0 -4
- package/dist/sdk/catalog-walker.d.ts +0 -90
- package/dist/sdk/catalog-walker.js +0 -682
- package/dist/sdk/dts-reader.d.ts +0 -83
- package/dist/sdk/dts-reader.js +0 -596
- package/src/debug-codegen.ts +0 -207
package/src/display/index.ts
CHANGED
|
@@ -1,70 +1,87 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Zephyr display op resolver — maps DisplayHALOp → GFX runtime calls
|
|
3
|
-
//
|
|
4
|
-
// resolveZephyrDisplayOp is a pure function of (op, state): the strategy holds
|
|
5
|
-
// a DisplayState (mirrors Arduino's _displayCtx) and passes it in. On
|
|
6
|
-
// display.init the state is seeded with the active profile; subsequent ops
|
|
7
|
-
// lower to the helpers in gfx.ts.
|
|
8
|
-
//
|
|
9
|
-
// Validator probes call fill_rect/draw_text/draw_rect/flush WITHOUT a prior
|
|
10
|
-
// init, so when state is uninitialized we seed the DEFAULT profile and lower
|
|
11
|
-
// anyway (the probe only checks code/expression is non-undefined).
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
|
|
14
|
-
import type { DisplayHALOp } from '@typecad/cuttlefish/api/shared';
|
|
15
|
-
import { DEFAULT_ZEPHYR_DISPLAY_PROFILE, type ZephyrDisplayProfile } from './profiles.js';
|
|
16
|
-
|
|
17
|
-
// Re-export the UI display/touch adapters + profile registry so the strategy
|
|
18
|
-
// and consumers can reach them from the package barrel.
|
|
19
|
-
export { zephyrUiDisplayAdapter, zephyrDisplayAdapterGenerator } from './ui-adapter.js';
|
|
20
|
-
export { zephyrTouchAdapter } from './touch-adapter.js';
|
|
21
|
-
export { ZEPHYR_DISPLAY_PROFILES, DEFAULT_ZEPHYR_DISPLAY_PROFILE, BUILT_IN_PROFILES } from './profiles.js';
|
|
22
|
-
export type { ZephyrDisplayProfile } from './profiles.js';
|
|
23
|
-
|
|
24
|
-
export interface DisplayState {
|
|
25
|
-
initialized: boolean;
|
|
26
|
-
profile: ZephyrDisplayProfile;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** Fresh display state (used by the strategy per-build). */
|
|
30
|
-
export function newDisplayState(): DisplayState {
|
|
31
|
-
return { initialized: false, profile: DEFAULT_ZEPHYR_DISPLAY_PROFILE };
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Resolve a display.* op. Returns { code } for statement ops, undefined when
|
|
36
|
-
* the op is not recognized.
|
|
37
|
-
*/
|
|
38
|
-
export function resolveZephyrDisplayOp(
|
|
39
|
-
op: DisplayHALOp,
|
|
40
|
-
state: DisplayState,
|
|
41
|
-
): { code?: string; expression?: string } | undefined {
|
|
42
|
-
const o = op as any;
|
|
43
|
-
|
|
44
|
-
// display.init seeds the state. The probe payload for init has no profile
|
|
45
|
-
// fields, so use the default profile.
|
|
46
|
-
if (op.operation === 'display.init') {
|
|
47
|
-
state.initialized = true;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Zephyr display op resolver — maps DisplayHALOp → GFX runtime calls
|
|
3
|
+
//
|
|
4
|
+
// resolveZephyrDisplayOp is a pure function of (op, state): the strategy holds
|
|
5
|
+
// a DisplayState (mirrors Arduino's _displayCtx) and passes it in. On
|
|
6
|
+
// display.init the state is seeded with the active profile; subsequent ops
|
|
7
|
+
// lower to the helpers in gfx.ts.
|
|
8
|
+
//
|
|
9
|
+
// Validator probes call fill_rect/draw_text/draw_rect/flush WITHOUT a prior
|
|
10
|
+
// init, so when state is uninitialized we seed the DEFAULT profile and lower
|
|
11
|
+
// anyway (the probe only checks code/expression is non-undefined).
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
import type { DisplayHALOp } from '@typecad/cuttlefish/api/shared';
|
|
15
|
+
import { DEFAULT_ZEPHYR_DISPLAY_PROFILE, ZEPHYR_DISPLAY_PROFILES, synthesizeZephyrProfile, type ZephyrDisplayProfile } from './profiles.js';
|
|
16
|
+
|
|
17
|
+
// Re-export the UI display/touch adapters + profile registry so the strategy
|
|
18
|
+
// and consumers can reach them from the package barrel.
|
|
19
|
+
export { zephyrUiDisplayAdapter, zephyrDisplayAdapterGenerator } from './ui-adapter.js';
|
|
20
|
+
export { zephyrTouchAdapter } from './touch-adapter.js';
|
|
21
|
+
export { ZEPHYR_DISPLAY_PROFILES, DEFAULT_ZEPHYR_DISPLAY_PROFILE, BUILT_IN_PROFILES } from './profiles.js';
|
|
22
|
+
export type { ZephyrDisplayProfile } from './profiles.js';
|
|
23
|
+
|
|
24
|
+
export interface DisplayState {
|
|
25
|
+
initialized: boolean;
|
|
26
|
+
profile: ZephyrDisplayProfile;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Fresh display state (used by the strategy per-build). */
|
|
30
|
+
export function newDisplayState(): DisplayState {
|
|
31
|
+
return { initialized: false, profile: DEFAULT_ZEPHYR_DISPLAY_PROFILE };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a display.* op. Returns { code } for statement ops, undefined when
|
|
36
|
+
* the op is not recognized.
|
|
37
|
+
*/
|
|
38
|
+
export function resolveZephyrDisplayOp(
|
|
39
|
+
op: DisplayHALOp,
|
|
40
|
+
state: DisplayState,
|
|
41
|
+
): { code?: string; expression?: string } | undefined {
|
|
42
|
+
const o = op as any;
|
|
43
|
+
|
|
44
|
+
// display.init seeds the state. The probe payload for init has no profile
|
|
45
|
+
// fields, so use the default profile.
|
|
46
|
+
if (op.operation === 'display.init') {
|
|
47
|
+
state.initialized = true;
|
|
48
|
+
// Drop-in panels (driver = DT compatible): seed the synthesized profile
|
|
49
|
+
// so the direct-op GFX runtime sizes itself for THIS panel (the mono
|
|
50
|
+
// framebuffer branch keys off the profile's colorFormat/geometry). The
|
|
51
|
+
// op carries the resolved profile's colorFormat — explicit mono wins;
|
|
52
|
+
// otherwise the compatible table decides (ssd1306-class → mono).
|
|
53
|
+
const registered = ZEPHYR_DISPLAY_PROFILES[o.driver as string];
|
|
54
|
+
if (registered) {
|
|
55
|
+
state.profile = registered;
|
|
56
|
+
} else {
|
|
57
|
+
const synth = synthesizeZephyrProfile({
|
|
58
|
+
driver: o.driver as string,
|
|
59
|
+
width: o.width as number,
|
|
60
|
+
height: o.height as number,
|
|
61
|
+
colorFormat: o.colorFormat as string | undefined,
|
|
62
|
+
});
|
|
63
|
+
if (synth) state.profile = synth;
|
|
64
|
+
}
|
|
65
|
+
return { code: 'display_init();' };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// For non-init ops: if not initialized (validator probe path), seed the
|
|
69
|
+
// default so the op still lowers.
|
|
70
|
+
if (!state.initialized) {
|
|
71
|
+
state.initialized = true;
|
|
72
|
+
state.profile = DEFAULT_ZEPHYR_DISPLAY_PROFILE;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
switch (op.operation) {
|
|
76
|
+
case 'display.fill_rect':
|
|
77
|
+
return { code: `display_fill_rect(${o.x}, ${o.y}, ${o.w}, ${o.h}, ${o.color});` };
|
|
78
|
+
case 'display.draw_rect':
|
|
79
|
+
return { code: `display_draw_rect(${o.x}, ${o.y}, ${o.w}, ${o.h}, ${o.color});` };
|
|
80
|
+
case 'display.draw_text':
|
|
81
|
+
return { code: `display_draw_text(${o.x}, ${o.y}, "${o.text}", ${o.color});` };
|
|
82
|
+
case 'display.flush':
|
|
83
|
+
return { code: 'display_flush();' };
|
|
84
|
+
default:
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// App-local CS-holding MIPI DBI host — the 'local-hold-cs' dbiHost.
|
|
3
|
+
//
|
|
4
|
+
// Implements the mipi-dbi host API for the overlay's zephyr,mipi-dbi-spi node
|
|
5
|
+
// with CS held across each command+data burst (GPIO-managed, DC toggled
|
|
6
|
+
// mid-burst — the Adafruit ST77xx protocol the direct transport verified on
|
|
7
|
+
// the clone-ST7796S rig). The stock mipi-dbi-spi driver issues the command
|
|
8
|
+
// byte and its parameters as two CS-deasserted SPI transactions, which
|
|
9
|
+
// scrambles clone ST77xx panels; the mipi-hold-cs DT knob that would fix it
|
|
10
|
+
// is documented by the binding but unimplemented in Zephyr 4.4.2. This host
|
|
11
|
+
// is that behavior, emitted app-locally — the stock bridge stays compiled
|
|
12
|
+
// out (CONFIG_MIPI_DBI_SPI=n) and the in-tree panel driver (e.g.
|
|
13
|
+
// sitronix,st7796s, CONFIG_ST7796S=y) binds on top unchanged.
|
|
14
|
+
//
|
|
15
|
+
// A bus host is a normal Zephyr extension point (11 ship in-tree); once
|
|
16
|
+
// upstream implements mipi-hold-cs, this section retires and the profile's
|
|
17
|
+
// dbiHost flips back to 'spi-bridge'.
|
|
18
|
+
//
|
|
19
|
+
// EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
|
|
20
|
+
// Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
import type { ZephyrDisplayProfile } from "./profiles.js";
|
|
24
|
+
|
|
25
|
+
/** Build the local CS-holding mipi-dbi host for a profile. Emits a device at
|
|
26
|
+
* the overlay's bridge node (bridgeLabel) implementing
|
|
27
|
+
* struct mipi_dbi_driver_api, plus the includes it needs. The panel driver
|
|
28
|
+
* reaches it via DEVICE_DT_GET(DT_INST_PARENT(display0)). */
|
|
29
|
+
export function localHoldCsDbiHost(profile: ZephyrDisplayProfile): {
|
|
30
|
+
includes: string[];
|
|
31
|
+
functions: string;
|
|
32
|
+
} {
|
|
33
|
+
const bus = profile.busLabel ?? 'spi2';
|
|
34
|
+
const bridge = profile.bridgeLabel ?? 'mipi_dbi';
|
|
35
|
+
|
|
36
|
+
const includes = [
|
|
37
|
+
`#include <zephyr/drivers/mipi_dbi.h>`,
|
|
38
|
+
`#include <zephyr/drivers/spi.h>`,
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const functions = `
|
|
42
|
+
// ── App-local MIPI DBI host (CS held across command+data) ───────────────
|
|
43
|
+
// The mipi-hold-cs behavior the zephyr,mipi-dbi-spi child binding documents:
|
|
44
|
+
// CS asserted by GPIO around each complete command+data burst (or whole
|
|
45
|
+
// display write), DC toggled mid-burst. The spi_config carried in the
|
|
46
|
+
// panel's mipi_dbi_config is used verbatim EXCEPT .cs, which this host
|
|
47
|
+
// nulls so the SPI driver never touches the CS line mid-burst.
|
|
48
|
+
static const struct gpio_dt_spec __tc_dbi_dc = GPIO_DT_SPEC_GET(DT_NODELABEL(${bridge}), dc_gpios);
|
|
49
|
+
static const struct gpio_dt_spec __tc_dbi_rst = GPIO_DT_SPEC_GET(DT_NODELABEL(${bridge}), reset_gpios);
|
|
50
|
+
// CS comes from the SPI bus node's cs-gpios, selected by the panel's
|
|
51
|
+
// dbi config .slave (= reg). The overlay puts the panel at index 0 and an
|
|
52
|
+
// SPI touch controller, if any, at index 1 — each owner drives its own CS.
|
|
53
|
+
static const struct gpio_dt_spec __tc_dbi_cs[] = {
|
|
54
|
+
#if DT_PROP_LEN(DT_NODELABEL(${bus}), cs_gpios) > 0
|
|
55
|
+
GPIO_DT_SPEC_GET_BY_IDX(DT_NODELABEL(${bus}), cs_gpios, 0),
|
|
56
|
+
#endif
|
|
57
|
+
#if DT_PROP_LEN(DT_NODELABEL(${bus}), cs_gpios) > 1
|
|
58
|
+
GPIO_DT_SPEC_GET_BY_IDX(DT_NODELABEL(${bus}), cs_gpios, 1),
|
|
59
|
+
#endif
|
|
60
|
+
};
|
|
61
|
+
#define __TC_DBI_CS_COUNT (sizeof(__tc_dbi_cs) / sizeof(__tc_dbi_cs[0]))
|
|
62
|
+
// Staging buffer for display writes: display_write buffers may live in PSRAM
|
|
63
|
+
// (not DMA-capable on ESP32); chunked SRAM staging is the pattern the direct
|
|
64
|
+
// transport proved on this rig. Reused, never per-frame (AGENTS.md).
|
|
65
|
+
static uint8_t __tc_dbi_bounce[4096];
|
|
66
|
+
|
|
67
|
+
static const struct gpio_dt_spec* __tc_dbi_cs_for(const struct mipi_dbi_config* cfg) {
|
|
68
|
+
if (cfg->config.slave >= __TC_DBI_CS_COUNT) return nullptr;
|
|
69
|
+
return &__tc_dbi_cs[cfg->config.slave];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// One command byte (DC low) + its parameters (DC high) under one CS burst.
|
|
73
|
+
static int __tc_dbi_command_write(const struct device* /*dev*/,
|
|
74
|
+
const struct mipi_dbi_config* cfg,
|
|
75
|
+
uint8_t cmd, const uint8_t* data, size_t len) {
|
|
76
|
+
const struct gpio_dt_spec* cs = __tc_dbi_cs_for(cfg);
|
|
77
|
+
if (cs == nullptr) return -EIO;
|
|
78
|
+
struct spi_config sc = cfg->config;
|
|
79
|
+
// This host owns CS — keep the SPI core off it. Both fields matter in
|
|
80
|
+
// Zephyr 4.4: the core gates on cs.cs_is_gpio (NOT the port pointer), and
|
|
81
|
+
// leaving it set makes spi_context_cs_control deref the port-less spec
|
|
82
|
+
// (EXCCAUSE 28 on the first panel init command — verified on hardware).
|
|
83
|
+
sc.cs.cs_is_gpio = false;
|
|
84
|
+
sc.cs.gpio.port = nullptr;
|
|
85
|
+
struct spi_buf __cb = { &cmd, 1 };
|
|
86
|
+
struct spi_buf_set __csb = { &__cb, 1 };
|
|
87
|
+
gpio_pin_set_dt(cs, 1);
|
|
88
|
+
gpio_pin_set_dt(&__tc_dbi_dc, 0);
|
|
89
|
+
int ret = spi_write(DEVICE_DT_GET(DT_NODELABEL(${bus})), &sc, &__csb);
|
|
90
|
+
if ((ret == 0) && (len > 0)) {
|
|
91
|
+
struct spi_buf __db = { const_cast<uint8_t*>(data), len };
|
|
92
|
+
struct spi_buf_set __dsb = { &__db, 1 };
|
|
93
|
+
gpio_pin_set_dt(&__tc_dbi_dc, 1);
|
|
94
|
+
ret = spi_write(DEVICE_DT_GET(DT_NODELABEL(${bus})), &sc, &__dsb);
|
|
95
|
+
}
|
|
96
|
+
gpio_pin_set_dt(cs, 0);
|
|
97
|
+
return ret;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Write-only host: the bridge node carries 'write-only' (no MISO readback
|
|
101
|
+
// path is wired for these panels).
|
|
102
|
+
static int __tc_dbi_command_read(const struct device* /*dev*/,
|
|
103
|
+
const struct mipi_dbi_config* /*cfg*/,
|
|
104
|
+
uint8_t* /*cmds*/, size_t /*num_cmds*/,
|
|
105
|
+
uint8_t* /*response*/, size_t /*len*/) {
|
|
106
|
+
return -ENOTSUP;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Stream desc->buf_size bytes to the panel (DC high) under one CS assertion,
|
|
110
|
+
// chunked through the SRAM bounce buffer.
|
|
111
|
+
static int __tc_dbi_write_display(const struct device* /*dev*/,
|
|
112
|
+
const struct mipi_dbi_config* cfg,
|
|
113
|
+
const uint8_t* framebuf,
|
|
114
|
+
struct display_buffer_descriptor* desc,
|
|
115
|
+
enum display_pixel_format /*pixfmt*/) {
|
|
116
|
+
const struct gpio_dt_spec* cs = __tc_dbi_cs_for(cfg);
|
|
117
|
+
if (cs == nullptr) return -EIO;
|
|
118
|
+
struct spi_config sc = cfg->config;
|
|
119
|
+
sc.cs.cs_is_gpio = false;
|
|
120
|
+
sc.cs.gpio.port = nullptr;
|
|
121
|
+
gpio_pin_set_dt(cs, 1);
|
|
122
|
+
gpio_pin_set_dt(&__tc_dbi_dc, 1);
|
|
123
|
+
const uint8_t* p = framebuf;
|
|
124
|
+
size_t remaining = desc->buf_size;
|
|
125
|
+
int ret = 0;
|
|
126
|
+
while ((remaining > 0) && (ret == 0)) {
|
|
127
|
+
size_t chunk = (remaining > sizeof(__tc_dbi_bounce)) ? sizeof(__tc_dbi_bounce) : remaining;
|
|
128
|
+
memcpy(__tc_dbi_bounce, p, chunk);
|
|
129
|
+
struct spi_buf __b = { __tc_dbi_bounce, chunk };
|
|
130
|
+
struct spi_buf_set __s = { &__b, 1 };
|
|
131
|
+
ret = spi_write(DEVICE_DT_GET(DT_NODELABEL(${bus})), &sc, &__s);
|
|
132
|
+
p += chunk;
|
|
133
|
+
remaining -= chunk;
|
|
134
|
+
}
|
|
135
|
+
gpio_pin_set_dt(cs, 0);
|
|
136
|
+
return ret;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Assert reset for the requested delay, then release (the stock host's
|
|
140
|
+
// semantics — st7796s calls mipi_dbi_reset(host, 100) at init).
|
|
141
|
+
static int __tc_dbi_reset(const struct device* /*dev*/, k_timeout_t delay) {
|
|
142
|
+
gpio_pin_set_dt(&__tc_dbi_rst, 1);
|
|
143
|
+
k_sleep(delay);
|
|
144
|
+
return gpio_pin_set_dt(&__tc_dbi_rst, 0);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Nothing is locked between calls (no per-panel spi reconfig here).
|
|
148
|
+
static int __tc_dbi_release(const struct device* /*dev*/,
|
|
149
|
+
const struct mipi_dbi_config* /*cfg*/) {
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
static DEVICE_API(mipi_dbi, __tc_dbi_api) = {
|
|
154
|
+
__tc_dbi_command_write,
|
|
155
|
+
__tc_dbi_command_read,
|
|
156
|
+
__tc_dbi_write_display,
|
|
157
|
+
__tc_dbi_reset,
|
|
158
|
+
__tc_dbi_release,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
static int __tc_dbi_host_init(const struct device* /*dev*/) {
|
|
162
|
+
if (!device_is_ready(__tc_dbi_dc.port)) return -ENODEV;
|
|
163
|
+
gpio_pin_configure_dt(&__tc_dbi_dc, GPIO_OUTPUT);
|
|
164
|
+
if (device_is_ready(__tc_dbi_rst.port)) {
|
|
165
|
+
gpio_pin_configure_dt(&__tc_dbi_rst, GPIO_OUTPUT_INACTIVE);
|
|
166
|
+
}
|
|
167
|
+
for (size_t i = 0; i < __TC_DBI_CS_COUNT; i++) {
|
|
168
|
+
if (device_is_ready(__tc_dbi_cs[i].port)) {
|
|
169
|
+
gpio_pin_configure_dt(&__tc_dbi_cs[i], GPIO_OUTPUT_INACTIVE);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Same init level/priority slot the stock bridge uses — panel drivers init
|
|
176
|
+
// later (CONFIG_DISPLAY_INIT_PRIORITY=85 > MIPI_DBI_INIT_PRIORITY=80), so
|
|
177
|
+
// the host's GPIOs are live before the panel's init commands run.
|
|
178
|
+
DEVICE_DT_DEFINE(DT_NODELABEL(${bridge}), __tc_dbi_host_init, NULL, NULL, NULL,
|
|
179
|
+
POST_KERNEL, CONFIG_MIPI_DBI_INIT_PRIORITY, &__tc_dbi_api);
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
return { includes, functions };
|
|
183
|
+
}
|