@typecad/framework-zephyr 1.0.0-alpha.15 → 1.0.0-alpha.18
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/boardgen.d.ts +1 -9
- package/dist/boardgen.js +228 -45
- package/dist/chips/types.d.ts +1 -1
- package/dist/debug-codegen.js +1 -1
- package/dist/display/touch-adapter.js +1 -1
- package/dist/display/ui-adapter.js +549 -549
- package/dist/doctor.js +4 -4
- package/dist/dt-config/custom-board.js +2 -2
- package/dist/dt-config/kconfig.js +18 -12
- package/dist/dt-config/overlay.d.ts +2 -2
- package/dist/dt-config/overlay.js +2 -2
- package/dist/framework.manifest.d.ts +3 -3
- package/dist/framework.manifest.js +10 -7
- package/dist/index.js +5 -5
- package/dist/licenses.d.ts +2 -2
- package/dist/licenses.js +8 -8
- package/dist/lowering/fs.js +1 -1
- package/dist/lowering/gpio.js +0 -32
- package/dist/lowering/http.js +264 -32
- package/dist/lowering/i2c.js +0 -8
- package/dist/lowering/interrupts.js +6 -0
- package/dist/lowering/mqtt.js +110 -8
- package/dist/lowering/usb.js +11 -11
- package/dist/lowering/wdt.js +2 -29
- package/dist/sdk/board-catalog-sync.d.ts +1 -3
- package/dist/sdk/board-catalog-sync.js +4 -10
- package/dist/strategy.d.ts +22 -44
- package/dist/strategy.js +152 -155
- 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 +241 -502
- package/dist/toolchain/env-check.d.ts +1 -3
- package/dist/toolchain/env-check.js +2 -7
- package/dist/toolchain/index.d.ts +65 -2
- package/dist/toolchain/index.js +432 -55
- package/dist/toolchain/runners.d.ts +16 -0
- package/dist/toolchain/runners.js +75 -0
- package/dist/toolchain/scaffold.d.ts +1 -1
- package/dist/toolchain/scaffold.js +12 -12
- 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/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/boardgen.ts +214 -48
- package/src/chips/types.ts +567 -567
- package/src/display/touch-adapter.ts +204 -204
- package/src/display/ui-adapter.ts +781 -781
- package/src/doctor.ts +4 -4
- package/src/dt-config/custom-board.ts +2 -2
- package/src/dt-config/kconfig.ts +18 -12
- package/src/dt-config/overlay.ts +1058 -1058
- package/src/framework.manifest.ts +538 -535
- package/src/index.ts +5 -5
- package/src/licenses.ts +425 -425
- package/src/lowering/fs.ts +135 -135
- package/src/lowering/gpio.ts +0 -33
- package/src/lowering/http.ts +264 -32
- package/src/lowering/i2c.ts +0 -9
- package/src/lowering/interrupts.ts +6 -0
- package/src/lowering/mqtt.ts +109 -8
- package/src/lowering/usb.ts +221 -221
- package/src/lowering/wdt.ts +2 -25
- package/src/sdk/board-catalog-sync.ts +4 -25
- package/src/strategy.ts +2265 -2309
- package/src/toolchain/debug-config.ts +264 -514
- package/src/toolchain/env-check.ts +279 -285
- package/src/toolchain/index.ts +1703 -1286
- package/src/toolchain/runners.ts +80 -0
- package/src/toolchain/scaffold.ts +296 -296
- package/src/toolchain/west-discover.ts +35 -13
- package/src/toolchain/west-spawn.ts +174 -168
- 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/power.d.ts +0 -9
- package/dist/lowering/power.js +0 -60
- 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
|
@@ -1,204 +1,204 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// Zephyr touch adapters for the
|
|
3
|
-
//
|
|
4
|
-
// Two controllers, both driven directly (polling, no in-tree driver):
|
|
5
|
-
// - FT6336U capacitive over I2C (i2c_write_read_dt)
|
|
6
|
-
// - XPT2046 resistive over SPI (spi_transceive_dt) — the Zephyr analog of
|
|
7
|
-
// Arduino's XPT2046_Touchscreen adapter. The DT node uses the in-tree
|
|
8
|
-
// xptek,xpt2046 binding; CONFIG_INPUT stays off, so the in-tree input
|
|
9
|
-
// driver does not build and this adapter owns the chip.
|
|
10
|
-
//
|
|
11
|
-
// The adapters emit touch_init / touch_isTouched / touch_readRaw — the three
|
|
12
|
-
// symbols the runtime's ui_poll_touch body calls.
|
|
13
|
-
//
|
|
14
|
-
// EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
|
|
15
|
-
// Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
|
|
18
|
-
import type { TouchAdapterCodegen } from "@typecad/cuttlefish/api/shared";
|
|
19
|
-
import type { TouchProfile } from "@typecad/cuttlefish/api/shared";
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Generate a Zephyr touch adapter for the profile's library. Returns
|
|
23
|
-
* undefined for libraries this framework doesn't handle so the strategy can
|
|
24
|
-
* decline and cuttlefish surfaces a clear error.
|
|
25
|
-
*/
|
|
26
|
-
export function zephyrTouchAdapter(touch: TouchProfile): TouchAdapterCodegen | undefined {
|
|
27
|
-
if (touch.library === "XPT2046_Touchscreen") return xpt2046Adapter(touch);
|
|
28
|
-
if (touch.library === "FT6336U") return ft6336uAdapter(touch);
|
|
29
|
-
return undefined;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** XPT2046 control bytes (12-bit differential mode, auto power-down). */
|
|
33
|
-
const XPT2046_CMD_X = 0x90;
|
|
34
|
-
const XPT2046_CMD_Y = 0xd0;
|
|
35
|
-
const XPT2046_CMD_Z1 = 0xb0;
|
|
36
|
-
const hex = (v: number): string => `0x${v.toString(16).toUpperCase()}`;
|
|
37
|
-
|
|
38
|
-
function xpt2046Adapter(touch: TouchProfile): TouchAdapterCodegen {
|
|
39
|
-
// Pen-detect Z1 threshold (raw 12-bit counts). Resistive panels need a few
|
|
40
|
-
// hundred counts above noise; the TouchProfile default (10) is far too low
|
|
41
|
-
// for raw Z1, so the adapter defaults to 400 (the Arduino XPT2046
|
|
42
|
-
// library's Z_THRESHOLD) unless the config sets one explicitly.
|
|
43
|
-
const zThreshold = touch.minPressure ?? 400;
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
includes: [
|
|
47
|
-
`#include <zephyr/kernel.h>`,
|
|
48
|
-
`#include <zephyr/drivers/spi.h>`,
|
|
49
|
-
`#include <zephyr/drivers/gpio.h>`,
|
|
50
|
-
],
|
|
51
|
-
declaration: [
|
|
52
|
-
`// Zephyr XPT2046 resistive touch — SPI device resolved via devicetree.`,
|
|
53
|
-
`// The overlay defines the 'xpt2046' nodelabel on the panel's SPI bus`,
|
|
54
|
-
`// (CS index 1) with the xptek,xpt2046 binding; the bus + CS + 2.5MHz`,
|
|
55
|
-
`// ceiling come from that node. Raw X/Y/Z1 values are reported — the`,
|
|
56
|
-
`// runtime applies the profile calibration + rotation.`,
|
|
57
|
-
`static const struct spi_dt_spec __tc_touch =`,
|
|
58
|
-
` SPI_DT_SPEC_GET(DT_NODELABEL(xpt2046), SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0U);`,
|
|
59
|
-
`static int16_t __tc_touch_cached_x = 0;`,
|
|
60
|
-
`static int16_t __tc_touch_cached_y = 0;`,
|
|
61
|
-
`static int16_t __tc_touch_cached_z = 0;`,
|
|
62
|
-
`static uint8_t __tc_touch_cached_valid = 0;`,
|
|
63
|
-
`#if DT_NODE_HAS_PROP(DT_NODELABEL(xpt2046), int_gpios)`,
|
|
64
|
-
`static const struct gpio_dt_spec __tc_touch_irq = GPIO_DT_SPEC_GET(DT_NODELABEL(xpt2046), int_gpios);`,
|
|
65
|
-
`static uint8_t __tc_touch_irq_ready = 0;`,
|
|
66
|
-
`#endif`,
|
|
67
|
-
].join("\n"),
|
|
68
|
-
functions: [
|
|
69
|
-
`// One XPT2046 conversion: clock out a control byte, read the 12-bit`,
|
|
70
|
-
`// result. The rx byte during the command phase is a dummy; the value is`,
|
|
71
|
-
`// MSB-aligned across the following 16 bits ((b1<<8 | b2) >> 3). The`,
|
|
72
|
-
`// control byte's PD bits are 00 (auto power-down between transactions),`,
|
|
73
|
-
`// so the bus stays shareable with the panel. Touch is polled every frame`,
|
|
74
|
-
`// from ui_poll_touch, so a failed transfer is non-fatal — returns 0 and`,
|
|
75
|
-
`// touch_isTouched() reports false.`,
|
|
76
|
-
`static uint16_t __tc_xpt_read(uint8_t cmd) {`,
|
|
77
|
-
` if (!device_is_ready(__tc_touch.bus)) return 0U;`,
|
|
78
|
-
` uint8_t __tx[3] = { cmd, 0U, 0U };`,
|
|
79
|
-
` uint8_t __rx[3] = { 0U, 0U, 0U };`,
|
|
80
|
-
` struct spi_buf __bt = { __tx, sizeof(__tx) };`,
|
|
81
|
-
` struct spi_buf __br = { __rx, sizeof(__rx) };`,
|
|
82
|
-
` struct spi_buf_set __st = { &__bt, 1 };`,
|
|
83
|
-
` struct spi_buf_set __sr = { &__br, 1 };`,
|
|
84
|
-
` if (spi_transceive_dt(&__tc_touch, &__st, &__sr) != 0) return 0U;`,
|
|
85
|
-
` return static_cast<uint16_t>(((static_cast<uint16_t>(__rx[1]) << 8) | __rx[2]) >> 3);`,
|
|
86
|
-
`}`,
|
|
87
|
-
``,
|
|
88
|
-
`static inline void touch_init() {`,
|
|
89
|
-
` // The SPI bus + CS are configured by devicetree. Configure the pen IRQ`,
|
|
90
|
-
` // input (active low) when the overlay wired it — the cheap detect path.`,
|
|
91
|
-
`#if DT_NODE_HAS_PROP(DT_NODELABEL(xpt2046), int_gpios)`,
|
|
92
|
-
` if (device_is_ready(__tc_touch_irq.port)) {`,
|
|
93
|
-
` gpio_pin_configure_dt(&__tc_touch_irq, GPIO_INPUT);`,
|
|
94
|
-
` __tc_touch_irq_ready = 1U;`,
|
|
95
|
-
` }`,
|
|
96
|
-
`#endif`,
|
|
97
|
-
` (void)device_is_ready(__tc_touch.bus);`,
|
|
98
|
-
`}`,
|
|
99
|
-
``,
|
|
100
|
-
`static inline bool touch_isTouched() {`,
|
|
101
|
-
` __tc_touch_cached_valid = 0;`,
|
|
102
|
-
` __tc_touch_cached_z = 0;`,
|
|
103
|
-
`#if DT_NODE_HAS_PROP(DT_NODELABEL(xpt2046), int_gpios)`,
|
|
104
|
-
` if (__tc_touch_irq_ready != 0U) {`,
|
|
105
|
-
` // PENIRQ asserts (active low) while the panel is pressed — no SPI`,
|
|
106
|
-
` // traffic needed to answer the per-frame poll.`,
|
|
107
|
-
` if (gpio_pin_get_dt(&__tc_touch_irq) <= 0) return false;`,
|
|
108
|
-
` }`,
|
|
109
|
-
`#endif`,
|
|
110
|
-
` // No IRQ (or it fired): confirm via Z1 pressure before reading coords.`,
|
|
111
|
-
` uint16_t __z1 = __tc_xpt_read(${hex(XPT2046_CMD_Z1)});`,
|
|
112
|
-
` if (__z1 <= ${zThreshold}) return false;`,
|
|
113
|
-
` __tc_touch_cached_x = static_cast<int16_t>(__tc_xpt_read(${hex(XPT2046_CMD_X)}));`,
|
|
114
|
-
` __tc_touch_cached_y = static_cast<int16_t>(__tc_xpt_read(${hex(XPT2046_CMD_Y)}));`,
|
|
115
|
-
` __tc_touch_cached_z = static_cast<int16_t>(__z1);`,
|
|
116
|
-
` __tc_touch_cached_valid = 1;`,
|
|
117
|
-
` return true;`,
|
|
118
|
-
`}`,
|
|
119
|
-
``,
|
|
120
|
-
`static inline void touch_readRaw(int16_t* x, int16_t* y, int16_t* z) {`,
|
|
121
|
-
` // touch_isTouched() is polled each frame by ui_poll_touch; the cached`,
|
|
122
|
-
` // values are fresh. If something calls readRaw before isTouched, probe now.`,
|
|
123
|
-
` if (!__tc_touch_cached_valid) {`,
|
|
124
|
-
` (void)touch_isTouched();`,
|
|
125
|
-
` }`,
|
|
126
|
-
` if (x) *x = __tc_touch_cached_x;`,
|
|
127
|
-
` if (y) *y = __tc_touch_cached_y;`,
|
|
128
|
-
` if (z) *z = __tc_touch_cached_z;`,
|
|
129
|
-
` __tc_touch_cached_valid = 0;`,
|
|
130
|
-
`}`,
|
|
131
|
-
].join("\n"),
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function ft6336uAdapter(_touch: TouchProfile): TouchAdapterCodegen {
|
|
136
|
-
return {
|
|
137
|
-
includes: [
|
|
138
|
-
`#include <zephyr/drivers/i2c.h>`,
|
|
139
|
-
],
|
|
140
|
-
declaration: [
|
|
141
|
-
`// Zephyr FT6336U touch — I2C device resolved via devicetree.`,
|
|
142
|
-
`// The board DT must define an 'ft6336u' nodelabel on an I2C bus.`,
|
|
143
|
-
`static const struct i2c_dt_spec __tc_touch = I2C_DT_SPEC_GET(DT_NODELABEL(ft6336u));`,
|
|
144
|
-
`static int16_t __tc_touch_cached_x = 0;`,
|
|
145
|
-
`static int16_t __tc_touch_cached_y = 0;`,
|
|
146
|
-
`static int16_t __tc_touch_cached_z = 0;`,
|
|
147
|
-
`static uint8_t __tc_touch_cached_valid = 0;`,
|
|
148
|
-
].join("\n"),
|
|
149
|
-
functions: [
|
|
150
|
-
`// Read N bytes starting from a register address. Returns 1 on success.`,
|
|
151
|
-
`// Uses i2c_write_read_dt for a combined write-read transaction (register`,
|
|
152
|
-
`// address write, then repeated-start read). The FT6336U is polled every`,
|
|
153
|
-
`// frame from ui_poll_touch, so a failed read (stuck SDA, no controller) is`,
|
|
154
|
-
`// non-fatal — returns 0 and touch_isTreated() returns false.`,
|
|
155
|
-
`static inline uint8_t __tc_touch_read_block(uint8_t reg, uint8_t* buf, uint8_t len) {`,
|
|
156
|
-
` if (!device_is_ready(__tc_touch.bus)) return 0U;`,
|
|
157
|
-
` int rc = i2c_write_read_dt(&__tc_touch, ®, 1U, buf, len);`,
|
|
158
|
-
` return (rc == 0) ? 1U : 0U;`,
|
|
159
|
-
`}`,
|
|
160
|
-
``,
|
|
161
|
-
`static inline void touch_init() {`,
|
|
162
|
-
` // The I2C bus + device are configured by devicetree. The FT6336U needs a`,
|
|
163
|
-
` // hardware reset (reset pin low → high) to enter normal mode after power-on.`,
|
|
164
|
-
`#if DT_NODE_HAS_STATUS(DT_NODELABEL(ft6336u), okay) && DT_NODE_HAS_PROP(DT_NODELABEL(ft6336u), reset_gpios)`,
|
|
165
|
-
` static const struct gpio_dt_spec __tc_touch_rst = GPIO_DT_SPEC_GET(DT_NODELABEL(ft6336u), reset_gpios);`,
|
|
166
|
-
` if (device_is_ready(__tc_touch_rst.port)) {`,
|
|
167
|
-
` gpio_pin_configure_dt(&__tc_touch_rst, GPIO_OUTPUT_ACTIVE); // assert reset (active=low)`,
|
|
168
|
-
` k_msleep(10);`,
|
|
169
|
-
` gpio_pin_set_dt(&__tc_touch_rst, 0); // release reset (inactive=high)`,
|
|
170
|
-
` k_msleep(200); // FT6336U needs ~50ms after reset before responding`,
|
|
171
|
-
` }`,
|
|
172
|
-
`#endif`,
|
|
173
|
-
` (void)device_is_ready(__tc_touch.bus);`,
|
|
174
|
-
`}`,
|
|
175
|
-
``,
|
|
176
|
-
`static inline bool touch_isTouched() {`,
|
|
177
|
-
` __tc_touch_cached_valid = 0;`,
|
|
178
|
-
` __tc_touch_cached_z = 0;`,
|
|
179
|
-
` // Read TD_STATUS (0x02) + P1_XH/XL/YH/YL — 5 bytes in one transaction.`,
|
|
180
|
-
` uint8_t buf[5] = {0, 0, 0, 0, 0};`,
|
|
181
|
-
` if (!__tc_touch_read_block(0x02, buf, 5U)) return false;`,
|
|
182
|
-
` uint8_t count = buf[0] & 0x0F;`,
|
|
183
|
-
` if (count == 0U) return false;`,
|
|
184
|
-
` __tc_touch_cached_x = static_cast<int16_t>((static_cast<uint16_t>(buf[1] & 0x0F) << 8) | buf[2]);`,
|
|
185
|
-
` __tc_touch_cached_y = static_cast<int16_t>((static_cast<uint16_t>(buf[3] & 0x0F) << 8) | buf[4]);`,
|
|
186
|
-
` __tc_touch_cached_z = 255;`,
|
|
187
|
-
` __tc_touch_cached_valid = 1;`,
|
|
188
|
-
` return true;`,
|
|
189
|
-
`}`,
|
|
190
|
-
``,
|
|
191
|
-
`static inline void touch_readRaw(int16_t* x, int16_t* y, int16_t* z) {`,
|
|
192
|
-
` // touch_isTouched() is polled each frame by ui_poll_touch; the cached`,
|
|
193
|
-
` // values are fresh. If something calls readRaw before isTouched, probe now.`,
|
|
194
|
-
` if (!__tc_touch_cached_valid) {`,
|
|
195
|
-
` (void)touch_isTouched();`,
|
|
196
|
-
` }`,
|
|
197
|
-
` if (x) *x = __tc_touch_cached_x;`,
|
|
198
|
-
` if (y) *y = __tc_touch_cached_y;`,
|
|
199
|
-
` if (z) *z = __tc_touch_cached_z;`,
|
|
200
|
-
` __tc_touch_cached_valid = 0;`,
|
|
201
|
-
`}`,
|
|
202
|
-
].join("\n"),
|
|
203
|
-
};
|
|
204
|
-
}
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Zephyr touch adapters for the TypeCAD UI rendering pipeline.
|
|
3
|
+
//
|
|
4
|
+
// Two controllers, both driven directly (polling, no in-tree driver):
|
|
5
|
+
// - FT6336U capacitive over I2C (i2c_write_read_dt)
|
|
6
|
+
// - XPT2046 resistive over SPI (spi_transceive_dt) — the Zephyr analog of
|
|
7
|
+
// Arduino's XPT2046_Touchscreen adapter. The DT node uses the in-tree
|
|
8
|
+
// xptek,xpt2046 binding; CONFIG_INPUT stays off, so the in-tree input
|
|
9
|
+
// driver does not build and this adapter owns the chip.
|
|
10
|
+
//
|
|
11
|
+
// The adapters emit touch_init / touch_isTouched / touch_readRaw — the three
|
|
12
|
+
// symbols the runtime's ui_poll_touch body calls.
|
|
13
|
+
//
|
|
14
|
+
// EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
|
|
15
|
+
// Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
import type { TouchAdapterCodegen } from "@typecad/cuttlefish/api/shared";
|
|
19
|
+
import type { TouchProfile } from "@typecad/cuttlefish/api/shared";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Generate a Zephyr touch adapter for the profile's library. Returns
|
|
23
|
+
* undefined for libraries this framework doesn't handle so the strategy can
|
|
24
|
+
* decline and cuttlefish surfaces a clear error.
|
|
25
|
+
*/
|
|
26
|
+
export function zephyrTouchAdapter(touch: TouchProfile): TouchAdapterCodegen | undefined {
|
|
27
|
+
if (touch.library === "XPT2046_Touchscreen") return xpt2046Adapter(touch);
|
|
28
|
+
if (touch.library === "FT6336U") return ft6336uAdapter(touch);
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** XPT2046 control bytes (12-bit differential mode, auto power-down). */
|
|
33
|
+
const XPT2046_CMD_X = 0x90;
|
|
34
|
+
const XPT2046_CMD_Y = 0xd0;
|
|
35
|
+
const XPT2046_CMD_Z1 = 0xb0;
|
|
36
|
+
const hex = (v: number): string => `0x${v.toString(16).toUpperCase()}`;
|
|
37
|
+
|
|
38
|
+
function xpt2046Adapter(touch: TouchProfile): TouchAdapterCodegen {
|
|
39
|
+
// Pen-detect Z1 threshold (raw 12-bit counts). Resistive panels need a few
|
|
40
|
+
// hundred counts above noise; the TouchProfile default (10) is far too low
|
|
41
|
+
// for raw Z1, so the adapter defaults to 400 (the Arduino XPT2046
|
|
42
|
+
// library's Z_THRESHOLD) unless the config sets one explicitly.
|
|
43
|
+
const zThreshold = touch.minPressure ?? 400;
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
includes: [
|
|
47
|
+
`#include <zephyr/kernel.h>`,
|
|
48
|
+
`#include <zephyr/drivers/spi.h>`,
|
|
49
|
+
`#include <zephyr/drivers/gpio.h>`,
|
|
50
|
+
],
|
|
51
|
+
declaration: [
|
|
52
|
+
`// Zephyr XPT2046 resistive touch — SPI device resolved via devicetree.`,
|
|
53
|
+
`// The overlay defines the 'xpt2046' nodelabel on the panel's SPI bus`,
|
|
54
|
+
`// (CS index 1) with the xptek,xpt2046 binding; the bus + CS + 2.5MHz`,
|
|
55
|
+
`// ceiling come from that node. Raw X/Y/Z1 values are reported — the`,
|
|
56
|
+
`// runtime applies the profile calibration + rotation.`,
|
|
57
|
+
`static const struct spi_dt_spec __tc_touch =`,
|
|
58
|
+
` SPI_DT_SPEC_GET(DT_NODELABEL(xpt2046), SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0U);`,
|
|
59
|
+
`static int16_t __tc_touch_cached_x = 0;`,
|
|
60
|
+
`static int16_t __tc_touch_cached_y = 0;`,
|
|
61
|
+
`static int16_t __tc_touch_cached_z = 0;`,
|
|
62
|
+
`static uint8_t __tc_touch_cached_valid = 0;`,
|
|
63
|
+
`#if DT_NODE_HAS_PROP(DT_NODELABEL(xpt2046), int_gpios)`,
|
|
64
|
+
`static const struct gpio_dt_spec __tc_touch_irq = GPIO_DT_SPEC_GET(DT_NODELABEL(xpt2046), int_gpios);`,
|
|
65
|
+
`static uint8_t __tc_touch_irq_ready = 0;`,
|
|
66
|
+
`#endif`,
|
|
67
|
+
].join("\n"),
|
|
68
|
+
functions: [
|
|
69
|
+
`// One XPT2046 conversion: clock out a control byte, read the 12-bit`,
|
|
70
|
+
`// result. The rx byte during the command phase is a dummy; the value is`,
|
|
71
|
+
`// MSB-aligned across the following 16 bits ((b1<<8 | b2) >> 3). The`,
|
|
72
|
+
`// control byte's PD bits are 00 (auto power-down between transactions),`,
|
|
73
|
+
`// so the bus stays shareable with the panel. Touch is polled every frame`,
|
|
74
|
+
`// from ui_poll_touch, so a failed transfer is non-fatal — returns 0 and`,
|
|
75
|
+
`// touch_isTouched() reports false.`,
|
|
76
|
+
`static uint16_t __tc_xpt_read(uint8_t cmd) {`,
|
|
77
|
+
` if (!device_is_ready(__tc_touch.bus)) return 0U;`,
|
|
78
|
+
` uint8_t __tx[3] = { cmd, 0U, 0U };`,
|
|
79
|
+
` uint8_t __rx[3] = { 0U, 0U, 0U };`,
|
|
80
|
+
` struct spi_buf __bt = { __tx, sizeof(__tx) };`,
|
|
81
|
+
` struct spi_buf __br = { __rx, sizeof(__rx) };`,
|
|
82
|
+
` struct spi_buf_set __st = { &__bt, 1 };`,
|
|
83
|
+
` struct spi_buf_set __sr = { &__br, 1 };`,
|
|
84
|
+
` if (spi_transceive_dt(&__tc_touch, &__st, &__sr) != 0) return 0U;`,
|
|
85
|
+
` return static_cast<uint16_t>(((static_cast<uint16_t>(__rx[1]) << 8) | __rx[2]) >> 3);`,
|
|
86
|
+
`}`,
|
|
87
|
+
``,
|
|
88
|
+
`static inline void touch_init() {`,
|
|
89
|
+
` // The SPI bus + CS are configured by devicetree. Configure the pen IRQ`,
|
|
90
|
+
` // input (active low) when the overlay wired it — the cheap detect path.`,
|
|
91
|
+
`#if DT_NODE_HAS_PROP(DT_NODELABEL(xpt2046), int_gpios)`,
|
|
92
|
+
` if (device_is_ready(__tc_touch_irq.port)) {`,
|
|
93
|
+
` gpio_pin_configure_dt(&__tc_touch_irq, GPIO_INPUT);`,
|
|
94
|
+
` __tc_touch_irq_ready = 1U;`,
|
|
95
|
+
` }`,
|
|
96
|
+
`#endif`,
|
|
97
|
+
` (void)device_is_ready(__tc_touch.bus);`,
|
|
98
|
+
`}`,
|
|
99
|
+
``,
|
|
100
|
+
`static inline bool touch_isTouched() {`,
|
|
101
|
+
` __tc_touch_cached_valid = 0;`,
|
|
102
|
+
` __tc_touch_cached_z = 0;`,
|
|
103
|
+
`#if DT_NODE_HAS_PROP(DT_NODELABEL(xpt2046), int_gpios)`,
|
|
104
|
+
` if (__tc_touch_irq_ready != 0U) {`,
|
|
105
|
+
` // PENIRQ asserts (active low) while the panel is pressed — no SPI`,
|
|
106
|
+
` // traffic needed to answer the per-frame poll.`,
|
|
107
|
+
` if (gpio_pin_get_dt(&__tc_touch_irq) <= 0) return false;`,
|
|
108
|
+
` }`,
|
|
109
|
+
`#endif`,
|
|
110
|
+
` // No IRQ (or it fired): confirm via Z1 pressure before reading coords.`,
|
|
111
|
+
` uint16_t __z1 = __tc_xpt_read(${hex(XPT2046_CMD_Z1)});`,
|
|
112
|
+
` if (__z1 <= ${zThreshold}) return false;`,
|
|
113
|
+
` __tc_touch_cached_x = static_cast<int16_t>(__tc_xpt_read(${hex(XPT2046_CMD_X)}));`,
|
|
114
|
+
` __tc_touch_cached_y = static_cast<int16_t>(__tc_xpt_read(${hex(XPT2046_CMD_Y)}));`,
|
|
115
|
+
` __tc_touch_cached_z = static_cast<int16_t>(__z1);`,
|
|
116
|
+
` __tc_touch_cached_valid = 1;`,
|
|
117
|
+
` return true;`,
|
|
118
|
+
`}`,
|
|
119
|
+
``,
|
|
120
|
+
`static inline void touch_readRaw(int16_t* x, int16_t* y, int16_t* z) {`,
|
|
121
|
+
` // touch_isTouched() is polled each frame by ui_poll_touch; the cached`,
|
|
122
|
+
` // values are fresh. If something calls readRaw before isTouched, probe now.`,
|
|
123
|
+
` if (!__tc_touch_cached_valid) {`,
|
|
124
|
+
` (void)touch_isTouched();`,
|
|
125
|
+
` }`,
|
|
126
|
+
` if (x) *x = __tc_touch_cached_x;`,
|
|
127
|
+
` if (y) *y = __tc_touch_cached_y;`,
|
|
128
|
+
` if (z) *z = __tc_touch_cached_z;`,
|
|
129
|
+
` __tc_touch_cached_valid = 0;`,
|
|
130
|
+
`}`,
|
|
131
|
+
].join("\n"),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function ft6336uAdapter(_touch: TouchProfile): TouchAdapterCodegen {
|
|
136
|
+
return {
|
|
137
|
+
includes: [
|
|
138
|
+
`#include <zephyr/drivers/i2c.h>`,
|
|
139
|
+
],
|
|
140
|
+
declaration: [
|
|
141
|
+
`// Zephyr FT6336U touch — I2C device resolved via devicetree.`,
|
|
142
|
+
`// The board DT must define an 'ft6336u' nodelabel on an I2C bus.`,
|
|
143
|
+
`static const struct i2c_dt_spec __tc_touch = I2C_DT_SPEC_GET(DT_NODELABEL(ft6336u));`,
|
|
144
|
+
`static int16_t __tc_touch_cached_x = 0;`,
|
|
145
|
+
`static int16_t __tc_touch_cached_y = 0;`,
|
|
146
|
+
`static int16_t __tc_touch_cached_z = 0;`,
|
|
147
|
+
`static uint8_t __tc_touch_cached_valid = 0;`,
|
|
148
|
+
].join("\n"),
|
|
149
|
+
functions: [
|
|
150
|
+
`// Read N bytes starting from a register address. Returns 1 on success.`,
|
|
151
|
+
`// Uses i2c_write_read_dt for a combined write-read transaction (register`,
|
|
152
|
+
`// address write, then repeated-start read). The FT6336U is polled every`,
|
|
153
|
+
`// frame from ui_poll_touch, so a failed read (stuck SDA, no controller) is`,
|
|
154
|
+
`// non-fatal — returns 0 and touch_isTreated() returns false.`,
|
|
155
|
+
`static inline uint8_t __tc_touch_read_block(uint8_t reg, uint8_t* buf, uint8_t len) {`,
|
|
156
|
+
` if (!device_is_ready(__tc_touch.bus)) return 0U;`,
|
|
157
|
+
` int rc = i2c_write_read_dt(&__tc_touch, ®, 1U, buf, len);`,
|
|
158
|
+
` return (rc == 0) ? 1U : 0U;`,
|
|
159
|
+
`}`,
|
|
160
|
+
``,
|
|
161
|
+
`static inline void touch_init() {`,
|
|
162
|
+
` // The I2C bus + device are configured by devicetree. The FT6336U needs a`,
|
|
163
|
+
` // hardware reset (reset pin low → high) to enter normal mode after power-on.`,
|
|
164
|
+
`#if DT_NODE_HAS_STATUS(DT_NODELABEL(ft6336u), okay) && DT_NODE_HAS_PROP(DT_NODELABEL(ft6336u), reset_gpios)`,
|
|
165
|
+
` static const struct gpio_dt_spec __tc_touch_rst = GPIO_DT_SPEC_GET(DT_NODELABEL(ft6336u), reset_gpios);`,
|
|
166
|
+
` if (device_is_ready(__tc_touch_rst.port)) {`,
|
|
167
|
+
` gpio_pin_configure_dt(&__tc_touch_rst, GPIO_OUTPUT_ACTIVE); // assert reset (active=low)`,
|
|
168
|
+
` k_msleep(10);`,
|
|
169
|
+
` gpio_pin_set_dt(&__tc_touch_rst, 0); // release reset (inactive=high)`,
|
|
170
|
+
` k_msleep(200); // FT6336U needs ~50ms after reset before responding`,
|
|
171
|
+
` }`,
|
|
172
|
+
`#endif`,
|
|
173
|
+
` (void)device_is_ready(__tc_touch.bus);`,
|
|
174
|
+
`}`,
|
|
175
|
+
``,
|
|
176
|
+
`static inline bool touch_isTouched() {`,
|
|
177
|
+
` __tc_touch_cached_valid = 0;`,
|
|
178
|
+
` __tc_touch_cached_z = 0;`,
|
|
179
|
+
` // Read TD_STATUS (0x02) + P1_XH/XL/YH/YL — 5 bytes in one transaction.`,
|
|
180
|
+
` uint8_t buf[5] = {0, 0, 0, 0, 0};`,
|
|
181
|
+
` if (!__tc_touch_read_block(0x02, buf, 5U)) return false;`,
|
|
182
|
+
` uint8_t count = buf[0] & 0x0F;`,
|
|
183
|
+
` if (count == 0U) return false;`,
|
|
184
|
+
` __tc_touch_cached_x = static_cast<int16_t>((static_cast<uint16_t>(buf[1] & 0x0F) << 8) | buf[2]);`,
|
|
185
|
+
` __tc_touch_cached_y = static_cast<int16_t>((static_cast<uint16_t>(buf[3] & 0x0F) << 8) | buf[4]);`,
|
|
186
|
+
` __tc_touch_cached_z = 255;`,
|
|
187
|
+
` __tc_touch_cached_valid = 1;`,
|
|
188
|
+
` return true;`,
|
|
189
|
+
`}`,
|
|
190
|
+
``,
|
|
191
|
+
`static inline void touch_readRaw(int16_t* x, int16_t* y, int16_t* z) {`,
|
|
192
|
+
` // touch_isTouched() is polled each frame by ui_poll_touch; the cached`,
|
|
193
|
+
` // values are fresh. If something calls readRaw before isTouched, probe now.`,
|
|
194
|
+
` if (!__tc_touch_cached_valid) {`,
|
|
195
|
+
` (void)touch_isTouched();`,
|
|
196
|
+
` }`,
|
|
197
|
+
` if (x) *x = __tc_touch_cached_x;`,
|
|
198
|
+
` if (y) *y = __tc_touch_cached_y;`,
|
|
199
|
+
` if (z) *z = __tc_touch_cached_z;`,
|
|
200
|
+
` __tc_touch_cached_valid = 0;`,
|
|
201
|
+
`}`,
|
|
202
|
+
].join("\n"),
|
|
203
|
+
};
|
|
204
|
+
}
|