@typecad/zephyr-esp32s3-rgb 1.0.0-alpha.13

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/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # @typecad/zephyr-esp32s3-rgb
2
+
3
+ The onboard WS2812 ("NeoPixel") RGB LED of the ESP32-S3 DevKitC, as a
4
+ cuttlefish library package for the **Zephyr RTOS** framework.
5
+
6
+ ```sh
7
+ npm install @typecad/zephyr-esp32s3-rgb
8
+ ```
9
+
10
+ ```ts
11
+ import { rgbLed } from '@typecad/zephyr-esp32s3-rgb';
12
+
13
+ rgbLed.color(0, 255, 0).show(); // green
14
+ rgbLed.color('#ff0000').show(); // red, CSS-style hex
15
+ rgbLed.brightness(64).color('#ffffff').show(); // dim white
16
+ rgbLed.off(); // black + show
17
+ ```
18
+
19
+ `rgbLed` is a preconstructed singleton — import it and chain calls. Colors
20
+ buffer locally; nothing reaches the LED until `show()` (or `off()`).
21
+
22
+ ## What the library carries (so you don't have to)
23
+
24
+ The native Zephyr path for this LED touches devicetree bindings, pinctrl,
25
+ DMA, and Kconfig before the first blink. This package moves that complexity
26
+ into itself, as three declarative artifacts (see `cuttlefish.library.json`):
27
+
28
+ | Artifact | File | What it does |
29
+ |---|---|---|
30
+ | C++ shim | `shims/__tc_rgbled.{h,cpp}` | `class RgbLed` over Zephyr's `led_strip_update_rgb()`; the import resolves to this header |
31
+ | Devicetree overlay | `shims/tc-rgb.overlay` | WS2812 node on GPIO48 through the I2S0 peripheral (`worldsemi,ws2812-i2s`, GRB color-mapping, DMA channel 3) |
32
+ | Kconfig | manifest `kconfig` | `CONFIG_LED_STRIP=y`, `CONFIG_I2S=y`, `CONFIG_DMA=y` |
33
+
34
+ When your program imports the package, the cuttlefish transpiler:
35
+
36
+ 1. registers the import as a library (the package root carries a
37
+ `cuttlefish.library.json`) and skips transpiling its TypeScript — the
38
+ package's own types are the compile-time contract;
39
+ 2. emits `#include "__tc_rgbled.h"` into your `main.cpp` and writes the shim
40
+ files into the generated `src/` (CMake picks the `.cpp` up automatically);
41
+ 3. appends the overlay fragment to the generated `boards/<board>.overlay`;
42
+ 4. appends the Kconfig lines to the generated `prj.conf`.
43
+
44
+ The I2S backend is upstream Zephyr's own configuration for this board
45
+ (`samples/drivers/led/led_strip`), adapted verbatim — it borrows the I2S0
46
+ peripheral and DMA channel 3, which nothing else in a cuttlefish Zephyr
47
+ project uses. The alternative SPI backend would collide with `spi.*` HAL
48
+ usage; the ESP32-S3's dedicated RMT peripheral has no upstream Zephyr driver.
49
+
50
+ ## Requirements
51
+
52
+ - **Framework:** `@typecad/framework-zephyr` (importing under another
53
+ framework fails the transpile with a clear error).
54
+ - **Board target:** `esp32s3_devkitc`.
55
+ - **Hardware revision:** DevKitC **v1.0**, whose RGB LED is on **GPIO48**.
56
+ v1.1 moved it to GPIO38 — on that revision change one line in
57
+ `shims/tc-rgb.overlay` (`I2S0_O_SD_GPIO48` → `I2S0_O_SD_GPIO38`). (The
58
+ mismatch with `boards/board-esp32s3`'s `led: 'GPIO48'` is inherited: the
59
+ Arduino core also pins v1.0's GPIO48 as `RGB_BUILTIN`.)
60
+ - **Validated on hardware:** 2026-08-21, ESP32-S3 DevKitC (GPIO48 revision),
61
+ via demo-shadcn — boot color + tap-counter color cycling through the full
62
+ chain (transpile → shim → overlay → Kconfig → west build → flash).
63
+
64
+ ## Writing a sibling library
65
+
66
+ This package is the template: an npm package with a `cuttlefish.library.json`
67
+ manifest (`module`, `framework`, `targets`, `include`, `gateToken`, `shims`,
68
+ `kconfig`, `overlay`), a types-only TypeScript API, and the native artifacts.
69
+ An Arduino counterpart (`@typecad/arduino-esp32s3-rgb` over `neopixelWrite`)
70
+ would follow the same manifest with a different framework id — the mechanism
71
+ is per-library, not per-framework-matrix.
72
+
73
+ ## Shim compliance
74
+
75
+ The shim sources are AUTOSAR C++14 by construction (fixed-width integers,
76
+ `static_cast` only, no heap, `final` class) and must keep passing
77
+ `--autosar=strict` — the repo's compliance test covers them.
@@ -0,0 +1,18 @@
1
+ {
2
+ "id": "zephyr-esp32s3-rgb",
3
+ "module": "@typecad/zephyr-esp32s3-rgb",
4
+ "framework": "zephyr",
5
+ "targets": ["esp32s3_devkitc"],
6
+ "include": "\"__tc_rgbled.h\"",
7
+ "gateToken": "__tc_rgbled",
8
+ "shims": [
9
+ { "path": "shims/__tc_rgbled.h", "outName": "__tc_rgbled.h" },
10
+ { "path": "shims/__tc_rgbled.cpp", "outName": "__tc_rgbled.cpp" }
11
+ ],
12
+ "kconfig": [
13
+ "CONFIG_LED_STRIP=y",
14
+ "CONFIG_I2S=y",
15
+ "CONFIG_DMA=y"
16
+ ],
17
+ "overlay": "shims/tc-rgb.overlay"
18
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The onboard addressable RGB LED.
3
+ *
4
+ * Buffers color/brightness locally; `show()` pushes one pixel to the strip.
5
+ * All modifiers chain and return the same instance.
6
+ */
7
+ export declare class RgbLed {
8
+ /**
9
+ * Set the LED color from 8-bit components (0–255 each).
10
+ * The LED does not change until `show()` is called.
11
+ */
12
+ color(r: number, g: number, b: number): this;
13
+ /**
14
+ * Set the LED color from a CSS-style hex string
15
+ * (`'#00ff00'` or `'00ff00'`). Invalid input is ignored.
16
+ * The LED does not change until `show()` is called.
17
+ */
18
+ color(hex: string): this;
19
+ /**
20
+ * Scale output brightness (0–255, default 255). Applied at `show()` time,
21
+ * so the buffered full-brightness color is preserved.
22
+ */
23
+ brightness(scale: number): this;
24
+ /** Push the buffered color to the LED. */
25
+ show(): this;
26
+ /** Turn the LED off immediately (black + show). */
27
+ off(): this;
28
+ }
29
+ /**
30
+ * The board's onboard RGB LED — the instance to use. A preconstructed
31
+ * singleton (rather than `new RgbLed()`) so the generated C++ stays a plain
32
+ * static instance with zero heap use.
33
+ */
34
+ export declare const rgbLed: RgbLed;
package/dist/index.js ADDED
@@ -0,0 +1,50 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @typecad/zephyr-esp32s3-rgb — onboard WS2812 RGB LED (ESP32-S3 DevKitC)
3
+ //
4
+ // A cuttlefish *library package*: `npm install @typecad/zephyr-esp32s3-rgb`,
5
+ // then import and use it like any other TypeScript module. The cuttlefish
6
+ // transpiler resolves the import to the native shim header (`__tc_rgbled.h`)
7
+ // and emits the shim + devicetree overlay + Kconfig into the generated Zephyr
8
+ // application — the class below is never executed, it is the typed API
9
+ // contract your editor sees. The C++ class in shims/__tc_rgbled.h is the
10
+ // implementation this type describes.
11
+ //
12
+ // Board facts carried by this library (instead of by you):
13
+ // - WS2812 ("NeoPixel") on GPIO48 (DevKitC v1.0; v1.1 moved it to GPIO38)
14
+ // - driven through the I2S0 peripheral (upstream Zephyr's own configuration
15
+ // for this board — samples/drivers/led/led_strip)
16
+ // - GRB wire order handled by the devicetree color-mapping
17
+ // ---------------------------------------------------------------------------
18
+ /**
19
+ * The onboard addressable RGB LED.
20
+ *
21
+ * Buffers color/brightness locally; `show()` pushes one pixel to the strip.
22
+ * All modifiers chain and return the same instance.
23
+ */
24
+ export class RgbLed {
25
+ color(rOrHex, g, b) {
26
+ // Types-only — lowered to the RgbLed C++ shim by the transpiler.
27
+ return this;
28
+ }
29
+ /**
30
+ * Scale output brightness (0–255, default 255). Applied at `show()` time,
31
+ * so the buffered full-brightness color is preserved.
32
+ */
33
+ brightness(scale) {
34
+ return this;
35
+ }
36
+ /** Push the buffered color to the LED. */
37
+ show() {
38
+ return this;
39
+ }
40
+ /** Turn the LED off immediately (black + show). */
41
+ off() {
42
+ return this;
43
+ }
44
+ }
45
+ /**
46
+ * The board's onboard RGB LED — the instance to use. A preconstructed
47
+ * singleton (rather than `new RgbLed()`) so the generated C++ stays a plain
48
+ * static instance with zero heap use.
49
+ */
50
+ export const rgbLed = new RgbLed();
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@typecad/zephyr-esp32s3-rgb",
3
+ "version": "1.0.0-alpha.13",
4
+ "description": "TypeLED for the ESP32-S3 DevKitC onboard WS2812 RGB LED (Zephyr RTOS) — a cuttlefish library package",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "src",
11
+ "shims",
12
+ "cuttlefish.library.json"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "prepublishOnly": "npm run build"
17
+ },
18
+ "license": "MIT",
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/justind000/typecode.git",
25
+ "directory": "packages/zephyr-esp32s3-rgb"
26
+ },
27
+ "homepage": "https://github.com/justind000/typecode/tree/main/packages/zephyr-esp32s3-rgb",
28
+ "bugs": {
29
+ "url": "https://github.com/justind000/typecode/issues"
30
+ },
31
+ "keywords": [
32
+ "cpp",
33
+ "cuttlefish",
34
+ "cuttlefish-library",
35
+ "cuttlefish-led",
36
+ "embedded",
37
+ "esp32s3",
38
+ "firmware",
39
+ "led",
40
+ "neopixel",
41
+ "rgb",
42
+ "smart-led",
43
+ "typecad",
44
+ "typescript",
45
+ "ws2812",
46
+ "zephyr"
47
+ ],
48
+ "engines": {
49
+ "node": ">=22.11.0"
50
+ },
51
+ "author": "typecad0",
52
+ "sideEffects": false,
53
+ "exports": {
54
+ ".": {
55
+ "types": "./dist/index.d.ts",
56
+ "default": "./dist/index.js"
57
+ },
58
+ "./package.json": "./package.json"
59
+ }
60
+ }
@@ -0,0 +1,103 @@
1
+ // ---------------------------------------------------------------------------
2
+ // __tc_rgbled.cpp — RgbLed shim implementation
3
+ // See __tc_rgbled.h for the contract. AUTOSAR C++14 compliant.
4
+ // ---------------------------------------------------------------------------
5
+
6
+ #include "__tc_rgbled.h"
7
+
8
+ namespace {
9
+
10
+ const std::int32_t kHexDigitCount = 6;
11
+ const std::uint32_t kHexBase = 16U;
12
+ const std::uint32_t kChannelMax = 255U;
13
+
14
+ std::uint8_t channel_scaled(std::uint8_t value, std::uint8_t scale)
15
+ {
16
+ const std::uint32_t product = (static_cast<std::uint32_t>(value) * static_cast<std::uint32_t>(scale)) / kChannelMax;
17
+ return static_cast<std::uint8_t>(product);
18
+ }
19
+
20
+ std::uint8_t hex_digit_value(char c)
21
+ {
22
+ if ((c >= '0') && (c <= '9'))
23
+ {
24
+ return static_cast<std::uint8_t>(c - '0');
25
+ }
26
+ if ((c >= 'a') && (c <= 'f'))
27
+ {
28
+ return static_cast<std::uint8_t>((c - 'a') + 10);
29
+ }
30
+ if ((c >= 'A') && (c <= 'F'))
31
+ {
32
+ return static_cast<std::uint8_t>((c - 'A') + 10);
33
+ }
34
+ return kChannelMax + 1U; // sentinel: not a hex digit
35
+ }
36
+
37
+ } // namespace
38
+
39
+ const struct device* RgbLed::strip_device()
40
+ {
41
+ return DEVICE_DT_GET(DT_ALIAS(led_strip));
42
+ }
43
+
44
+ RgbLed& RgbLed::color(std::uint8_t r, std::uint8_t g, std::uint8_t b)
45
+ {
46
+ pixel_.r = r;
47
+ pixel_.g = g;
48
+ pixel_.b = b;
49
+ return *this;
50
+ }
51
+
52
+ RgbLed& RgbLed::color(const char* hex)
53
+ {
54
+ if (hex == nullptr)
55
+ {
56
+ return *this;
57
+ }
58
+ const char* p = hex;
59
+ if (p[0] == '#')
60
+ {
61
+ p = &p[1];
62
+ }
63
+ std::uint32_t value = 0U;
64
+ for (std::int32_t i = 0; i < kHexDigitCount; ++i)
65
+ {
66
+ const std::uint8_t digit = hex_digit_value(p[i]);
67
+ if (digit > kChannelMax)
68
+ {
69
+ return *this; // invalid input — ignored, buffered color untouched
70
+ }
71
+ value = (value * kHexBase) + static_cast<std::uint32_t>(digit);
72
+ }
73
+ pixel_.r = static_cast<std::uint8_t>((value >> 16) & 0xFFU);
74
+ pixel_.g = static_cast<std::uint8_t>((value >> 8) & 0xFFU);
75
+ pixel_.b = static_cast<std::uint8_t>(value & 0xFFU);
76
+ return *this;
77
+ }
78
+
79
+ RgbLed& RgbLed::brightness(std::uint8_t scale)
80
+ {
81
+ scale_ = scale;
82
+ return *this;
83
+ }
84
+
85
+ RgbLed& RgbLed::show()
86
+ {
87
+ struct led_rgb out{};
88
+ out.r = channel_scaled(pixel_.r, scale_);
89
+ out.g = channel_scaled(pixel_.g, scale_);
90
+ out.b = channel_scaled(pixel_.b, scale_);
91
+ static_cast<void>(led_strip_update_rgb(strip_device(), &out, 1U));
92
+ return *this;
93
+ }
94
+
95
+ RgbLed& RgbLed::off()
96
+ {
97
+ pixel_.r = 0U;
98
+ pixel_.g = 0U;
99
+ pixel_.b = 0U;
100
+ return show();
101
+ }
102
+
103
+ RgbLed rgbLed;
@@ -0,0 +1,42 @@
1
+ // ---------------------------------------------------------------------------
2
+ // __tc_rgbled.h — RgbLed shim for @typecad/zephyr-esp32s3-rgb
3
+ //
4
+ // Emitted into the generated application's src/ by the cuttlefish transpiler
5
+ // when the @typecad/zephyr-esp32s3-rgb import is used. The TypeScript class
6
+ // in the package's src/index.ts is the typed contract; this class is the
7
+ // implementation. Calls render verbatim, so the method names and the global
8
+ // `rgbLed` instance are the API — do not rename one without the other.
9
+ //
10
+ // Targets the devicetree node aliased `led-strip` (contributed by this
11
+ // library's overlay fragment: WS2812 on GPIO48 via the I2S0 peripheral).
12
+ // AUTOSAR C++14 compliant (no heap, no C-style casts, fixed-width ints).
13
+ // ---------------------------------------------------------------------------
14
+
15
+ #ifndef TC_RGBLED_H_
16
+ #define TC_RGBLED_H_
17
+
18
+ #include <cstdint>
19
+ #include <zephyr/device.h>
20
+ #include <zephyr/drivers/led_strip.h>
21
+
22
+ class RgbLed final
23
+ {
24
+ public:
25
+ RgbLed& color(std::uint8_t r, std::uint8_t g, std::uint8_t b);
26
+ RgbLed& color(const char* hex);
27
+ RgbLed& brightness(std::uint8_t scale);
28
+ RgbLed& show();
29
+ RgbLed& off();
30
+
31
+ private:
32
+ static const struct device* strip_device();
33
+
34
+ // Value-initialized: layout-agnostic (led_rgb may carry a leading scratch
35
+ // member under CONFIG_LED_STRIP_RGB_SCRATCH).
36
+ struct led_rgb pixel_{};
37
+ std::uint8_t scale_ = 255U;
38
+ };
39
+
40
+ extern RgbLed rgbLed;
41
+
42
+ #endif // TC_RGBLED_H_
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Onboard WS2812 RGB LED — ESP32-S3 DevKitC, GPIO48, I2S backend.
3
+ *
4
+ * Adapted from Zephyr's in-tree sample overlay for this exact board:
5
+ * samples/drivers/led/led_strip/boards/esp32s3_devkitc_procpu.overlay
6
+ * Copyright (c) 2024-2025 Espressif Systems (Shanghai) Co., Ltd.
7
+ * SPDX-License-Identifier: Apache-2.0
8
+ *
9
+ * Appended to the generated boards/<board>.overlay when the library's
10
+ * __tc_rgbled include token appears in the emitted sources. color-mapping
11
+ * uses raw LED_COLOR_ID values (GREEN=2, RED=1, BLUE=3 — the WS2812 GRB
12
+ * wire order) to keep the fragment include-free.
13
+ */
14
+
15
+ / {
16
+ aliases {
17
+ led-strip = &led_strip;
18
+ };
19
+ };
20
+
21
+ &i2s0_default {
22
+ group1 {
23
+ pinmux = <I2S0_O_SD_GPIO48>;
24
+ };
25
+ };
26
+
27
+ i2s_led: &i2s0 {
28
+ status = "okay";
29
+
30
+ dmas = <&dma 3>;
31
+ dma-names = "tx";
32
+
33
+ led_strip: ws2812@0 {
34
+ compatible = "worldsemi,ws2812-i2s";
35
+
36
+ reg = <0>;
37
+ chain-length = <1>;
38
+ color-mapping = <2 1 3>; /* GRB: LED_COLOR_ID_GREEN, _RED, _BLUE */
39
+ reset-delay = <500>;
40
+ };
41
+ };
42
+
43
+ &dma {
44
+ status = "okay";
45
+ };
package/src/index.ts ADDED
@@ -0,0 +1,68 @@
1
+ // ---------------------------------------------------------------------------
2
+ // @typecad/zephyr-esp32s3-rgb — onboard WS2812 RGB LED (ESP32-S3 DevKitC)
3
+ //
4
+ // A cuttlefish *library package*: `npm install @typecad/zephyr-esp32s3-rgb`,
5
+ // then import and use it like any other TypeScript module. The cuttlefish
6
+ // transpiler resolves the import to the native shim header (`__tc_rgbled.h`)
7
+ // and emits the shim + devicetree overlay + Kconfig into the generated Zephyr
8
+ // application — the class below is never executed, it is the typed API
9
+ // contract your editor sees. The C++ class in shims/__tc_rgbled.h is the
10
+ // implementation this type describes.
11
+ //
12
+ // Board facts carried by this library (instead of by you):
13
+ // - WS2812 ("NeoPixel") on GPIO48 (DevKitC v1.0; v1.1 moved it to GPIO38)
14
+ // - driven through the I2S0 peripheral (upstream Zephyr's own configuration
15
+ // for this board — samples/drivers/led/led_strip)
16
+ // - GRB wire order handled by the devicetree color-mapping
17
+ // ---------------------------------------------------------------------------
18
+
19
+ /**
20
+ * The onboard addressable RGB LED.
21
+ *
22
+ * Buffers color/brightness locally; `show()` pushes one pixel to the strip.
23
+ * All modifiers chain and return the same instance.
24
+ */
25
+ export class RgbLed {
26
+ /**
27
+ * Set the LED color from 8-bit components (0–255 each).
28
+ * The LED does not change until `show()` is called.
29
+ */
30
+ color(r: number, g: number, b: number): this;
31
+
32
+ /**
33
+ * Set the LED color from a CSS-style hex string
34
+ * (`'#00ff00'` or `'00ff00'`). Invalid input is ignored.
35
+ * The LED does not change until `show()` is called.
36
+ */
37
+ color(hex: string): this;
38
+
39
+ color(rOrHex: number | string, g?: number, b?: number): this {
40
+ // Types-only — lowered to the RgbLed C++ shim by the transpiler.
41
+ return this;
42
+ }
43
+
44
+ /**
45
+ * Scale output brightness (0–255, default 255). Applied at `show()` time,
46
+ * so the buffered full-brightness color is preserved.
47
+ */
48
+ brightness(scale: number): this {
49
+ return this;
50
+ }
51
+
52
+ /** Push the buffered color to the LED. */
53
+ show(): this {
54
+ return this;
55
+ }
56
+
57
+ /** Turn the LED off immediately (black + show). */
58
+ off(): this {
59
+ return this;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * The board's onboard RGB LED — the instance to use. A preconstructed
65
+ * singleton (rather than `new RgbLed()`) so the generated C++ stays a plain
66
+ * static instance with zero heap use.
67
+ */
68
+ export const rgbLed: RgbLed = new RgbLed();