+71
.clang-format
+71
.clang-format
···
1
+
---
2
+
Language: Cpp
3
+
BasedOnStyle: Google
4
+
IndentWidth: 2
5
+
TabWidth: 2
6
+
UseTab: Never
7
+
ColumnLimit: 100
8
+
AlignAfterOpenBracket: Align
9
+
AlignConsecutiveAssignments: false
10
+
AlignConsecutiveDeclarations: false
11
+
AlignEscapedNewlines: Left
12
+
AlignOperands: true
13
+
AlignTrailingComments: true
14
+
AllowAllParametersOfDeclarationOnNextLine: false
15
+
AllowShortBlocksOnASingleLine: false
16
+
AllowShortCaseLabelsOnASingleLine: false
17
+
AllowShortFunctionsOnASingleLine: Inline
18
+
AllowShortIfStatementsOnASingleLine: false
19
+
AllowShortLoopsOnASingleLine: false
20
+
AlwaysBreakAfterReturnType: None
21
+
AlwaysBreakBeforeMultilineStrings: true
22
+
AlwaysBreakTemplateDeclarations: Yes
23
+
BinPackArguments: true
24
+
BinPackParameters: true
25
+
BreakBeforeBinaryOperators: None
26
+
BreakBeforeBraces: Attach
27
+
BreakBeforeTernaryOperators: true
28
+
BreakConstructorInitializers: BeforeColon
29
+
BreakInheritanceList: BeforeColon
30
+
BreakStringLiterals: true
31
+
CompactNamespaces: false
32
+
ConstructorInitializerAllOnOneLineOrOnePerLine: true
33
+
ConstructorInitializerIndentWidth: 4
34
+
ContinuationIndentWidth: 4
35
+
Cpp11BracedListStyle: true
36
+
DerivePointerAlignment: false
37
+
FixNamespaceComments: true
38
+
IncludeBlocks: Regroup
39
+
IncludeCategories:
40
+
- Regex: '^<.*\.h>'
41
+
Priority: 1
42
+
- Regex: '^<.*'
43
+
Priority: 2
44
+
- Regex: '.*'
45
+
Priority: 3
46
+
IndentCaseLabels: true
47
+
IndentPPDirectives: None
48
+
IndentWrappedFunctionNames: false
49
+
KeepEmptyLinesAtTheStartOfBlocks: false
50
+
MaxEmptyLinesToKeep: 1
51
+
NamespaceIndentation: None
52
+
PointerAlignment: Left
53
+
ReflowComments: true
54
+
SortIncludes: true
55
+
SortUsingDeclarations: true
56
+
SpaceAfterCStyleCast: false
57
+
SpaceAfterTemplateKeyword: true
58
+
SpaceBeforeAssignmentOperators: true
59
+
SpaceBeforeCpp11BracedList: false
60
+
SpaceBeforeCtorInitializerColon: true
61
+
SpaceBeforeInheritanceColon: true
62
+
SpaceBeforeParens: ControlStatements
63
+
SpaceBeforeRangeBasedForLoopColon: true
64
+
SpaceInEmptyParentheses: false
65
+
SpacesBeforeTrailingComments: 2
66
+
SpacesInAngles: false
67
+
SpacesInContainerLiterals: false
68
+
SpacesInCStyleCastParentheses: false
69
+
SpacesInParentheses: false
70
+
SpacesInSquareBrackets: false
71
+
Standard: Cpp11
+1
.envrc
+1
.envrc
···
1
+
use flake
+69
CRUSH.md
+69
CRUSH.md
···
1
+
# CRUSH.md - Daedalus Project Guidelines
2
+
3
+
## Build Commands
4
+
- Setup environment: `direnv allow`
5
+
- Build firmware: `cd firmware && make`
6
+
- Flash to RP2350: `cd firmware && make flash`
7
+
- Disassemble: `cd firmware && make disasm`
8
+
- Clean build: `cd firmware && make clean`
9
+
- Format code: `clang-format -i firmware/src/*.cpp firmware/src/*.h`
10
+
- Lint code: `cppcheck --enable=all firmware/src/`
11
+
12
+
## Test Commands
13
+
- Run all tests: `ctest -S build`
14
+
- Run single test: `ctest -R <test_name> -V`
15
+
16
+
## Code Style Guidelines
17
+
18
+
### General
19
+
- Use 2-space indentation
20
+
- Max line length: 100 characters
21
+
- UTF-8 encoding for all files
22
+
- Follow Google C++ Style Guide with modifications in .clang-format
23
+
24
+
### Naming Conventions
25
+
- Classes: PascalCase (e.g., `LedController`)
26
+
- Functions: camelCase (e.g., `initializeHardware()`)
27
+
- Variables: camelCase (e.g., `ledPin`)
28
+
- Constants: UPPER_SNAKE_CASE (e.g., `MAX_BUFFER_SIZE`)
29
+
- Files: snake_case.ext (e.g., `led_controller.cpp`)
30
+
31
+
### Error Handling
32
+
- Use return codes for error reporting
33
+
- Check return values from SDK functions
34
+
- Use assertions for invariants
35
+
- Avoid dynamic memory allocation when possible
36
+
37
+
### Nix Development
38
+
- Pico SDK is provided via nixpkgs with withSubmodules override
39
+
- All tools are managed through Nix
40
+
- Use `nix flake update` to update dependencies
41
+
42
+
## Code Style Guidelines
43
+
44
+
### General
45
+
- Use 2-space indentation
46
+
- Max line length: 100 characters
47
+
- UTF-8 encoding for all files
48
+
49
+
### Naming Conventions
50
+
- Functions/methods: camelCase
51
+
- Variables: camelCase
52
+
- Constants: UPPER_SNAKE_CASE
53
+
- Classes: PascalCase
54
+
- Files: kebab-case.ext
55
+
56
+
### Error Handling
57
+
- Use explicit error handling (no silent failures)
58
+
- Log errors with appropriate context
59
+
- Return meaningful error messages
60
+
61
+
### Comments
62
+
- Use JSDoc-style comments for functions
63
+
- Keep comments current with code changes
64
+
- Explain "why" not "what" in comments
65
+
66
+
### Git Practices
67
+
- Commit messages: Start with verb in present tense
68
+
- Keep commits focused on single changes
69
+
- Reference issues in commit messages when applicable
+36
firmware/CMakeLists.txt
+36
firmware/CMakeLists.txt
···
1
+
cmake_minimum_required(VERSION 3.25)
2
+
3
+
# Need to include pico-sdk cmake support. Must happen before project.
4
+
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
5
+
6
+
project(daedalus_firmware
7
+
LANGUAGES C CXX ASM
8
+
VERSION 1.0
9
+
)
10
+
11
+
set(CMAKE_C_STANDARD 11)
12
+
set(CMAKE_CXX_STANDARD 17)
13
+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Get compilation DB
14
+
15
+
# initialize the Raspberry Pi Pico SDK
16
+
pico_sdk_init()
17
+
18
+
# Tell CMake where to find the executable source file
19
+
add_executable(${PROJECT_NAME}
20
+
src/main.cpp
21
+
)
22
+
23
+
# Create map/bin/hex/uf2 files
24
+
pico_add_extra_outputs(${PROJECT_NAME})
25
+
26
+
# Link to pico_stdlib (gpio, time, etc. functions)
27
+
target_link_libraries(${PROJECT_NAME}
28
+
pico_stdlib
29
+
hardware_gpio
30
+
hardware_uart
31
+
pico_multicore
32
+
)
33
+
34
+
# Choice of available stdio outputs
35
+
pico_enable_stdio_usb(${PROJECT_NAME} 1) # ~13880 extra bytes
36
+
pico_enable_stdio_uart(${PROJECT_NAME} 0) # ~1176 extra bytes
+30
firmware/Makefile
+30
firmware/Makefile
···
1
+
# Little driver makefile to make the complicated bootloader less of a hassle.
2
+
3
+
PROJECT=daedalus_firmware
4
+
5
+
TOOLCHAIN_PREFIX=arm-none-eabi-
6
+
7
+
# Check if FORCE_FLASH is set
8
+
PICOTOOL_OPTS = $(if $(FORCE_FLASH),-f,)
9
+
10
+
build/$(PROJECT).uf2:
11
+
12
+
flash : build/$(PROJECT).uf2
13
+
picotool load $(PICOTOOL_OPTS) $<
14
+
picotool reboot
15
+
16
+
build/$(PROJECT).uf2 build/$(PROJECT).elf: build FORCE
17
+
$(MAKE) -C build
18
+
$(TOOLCHAIN_PREFIX)size build/$(PROJECT).elf
19
+
$(TOOLCHAIN_PREFIX)nm --print-size --size-sort --radix=d build/$(PROJECT).elf | awk '{printf("%5d %s\n", $$2, $$4);}' | sort -nr | head -20
20
+
21
+
disasm: build/$(PROJECT).elf
22
+
$(TOOLCHAIN_PREFIX)objdump -C -S build/$(PROJECT).elf
23
+
24
+
build:
25
+
cmake -B build -DCMAKE_VERBOSE_MAKEFILE=ON -DPICO_BOARD=pico2
26
+
27
+
clean:
28
+
rm -rf build
29
+
30
+
FORCE:
+33
firmware/README.md
+33
firmware/README.md
···
1
+
# Daedalus Firmware
2
+
3
+
This directory contains the firmware for the RP2350 board.
4
+
5
+
## Building
6
+
7
+
1. Make sure you have the Pico SDK set up (automatically handled by the Nix flake)
8
+
2. Configure the build:
9
+
```
10
+
cmake -B build -S .
11
+
```
12
+
3. Build the firmware:
13
+
```
14
+
cmake --build build
15
+
```
16
+
4. The output files will be in the `build` directory:
17
+
- `daedalus_firmware.uf2`: UF2 file for drag-and-drop programming
18
+
- `daedalus_firmware.elf`: ELF file for debugging
19
+
- `daedalus_firmware.hex`: HEX file for programming with external tools
20
+
21
+
## Flashing
22
+
23
+
Connect the RP2350 board in bootloader mode (hold BOOTSEL while connecting USB) and copy the UF2 file:
24
+
25
+
```
26
+
cp build/daedalus_firmware.uf2 /path/to/rp2350/
27
+
```
28
+
29
+
Or use picotool:
30
+
31
+
```
32
+
picotool load -x build/daedalus_firmware.uf2
33
+
```
+30
firmware/STYLE.md
+30
firmware/STYLE.md
···
1
+
# C++ style guide for Daedalus firmware
2
+
3
+
## Formatting
4
+
- Use clang-format with the provided .clang-format file
5
+
- Run before committing: `clang-format -i firmware/src/*.cpp firmware/src/*.h`
6
+
7
+
## Naming
8
+
- Classes: PascalCase (e.g., `LedController`)
9
+
- Functions: camelCase (e.g., `initializeHardware()`)
10
+
- Variables: camelCase (e.g., `ledPin`)
11
+
- Constants: UPPER_SNAKE_CASE (e.g., `MAX_BUFFER_SIZE`)
12
+
- Macros: UPPER_SNAKE_CASE (e.g., `DEBUG_ENABLE`)
13
+
- Files: snake_case (e.g., `led_controller.cpp`)
14
+
15
+
## Headers
16
+
- Use `#pragma once` for header guards
17
+
- Order includes: standard library, Pico SDK, project headers
18
+
19
+
## Comments
20
+
- Use Doxygen-style comments for functions and classes
21
+
- Comment complex algorithms and non-obvious code
22
+
23
+
## Error handling
24
+
- Use return codes for error reporting
25
+
- Check return values from SDK functions
26
+
- Use assertions for invariants
27
+
28
+
## Memory management
29
+
- Avoid dynamic memory allocation when possible
30
+
- If needed, use RAII principles with smart pointers
+65
firmware/pico_sdk_import.cmake
+65
firmware/pico_sdk_import.cmake
···
1
+
# This file is copied from the Pico SDK
2
+
# It allows the CMake project to find the Pico SDK
3
+
4
+
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
5
+
6
+
# This can be dropped into an external project to help locate the Pico SDK
7
+
# It should be included prior to project()
8
+
9
+
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
10
+
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
11
+
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
12
+
endif ()
13
+
14
+
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
15
+
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
16
+
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
17
+
endif ()
18
+
19
+
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
20
+
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
21
+
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
22
+
endif ()
23
+
24
+
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
25
+
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
26
+
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
27
+
28
+
if (NOT PICO_SDK_PATH)
29
+
if (PICO_SDK_FETCH_FROM_GIT)
30
+
include(FetchContent)
31
+
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
32
+
if (PICO_SDK_FETCH_FROM_GIT_PATH)
33
+
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
34
+
endif ()
35
+
FetchContent_Declare(
36
+
pico_sdk
37
+
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
38
+
GIT_TAG master
39
+
)
40
+
if (NOT pico_sdk)
41
+
message("Downloading Raspberry Pi Pico SDK")
42
+
FetchContent_Populate(pico_sdk)
43
+
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
44
+
endif ()
45
+
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
46
+
else ()
47
+
message(FATAL_ERROR
48
+
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
49
+
)
50
+
endif ()
51
+
endif ()
52
+
53
+
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
54
+
if (NOT EXISTS ${PICO_SDK_PATH})
55
+
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
56
+
endif ()
57
+
58
+
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
59
+
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
60
+
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
61
+
endif ()
62
+
63
+
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
64
+
65
+
include(${PICO_SDK_INIT_CMAKE_FILE})
+122
firmware/src/main.cpp
+122
firmware/src/main.cpp
···
1
+
#include <stdlib.h>
2
+
3
+
#include <cstring>
4
+
5
+
#include "pico/multicore.h"
6
+
#include "pico/stdlib.h"
7
+
8
+
// Define GPIO pins for rows and columns
9
+
const uint ROW_PINS[4] = {12, 13, 14, 15};
10
+
const uint COL_PINS[6] = {17, 18, 19, 20, 21, 22};
11
+
12
+
#define ROWS 4
13
+
#define COLS 6
14
+
15
+
// LED state matrix
16
+
uint8_t led_states[ROWS][COLS] = {0};
17
+
18
+
void setup_pins() {
19
+
// Set up row pins
20
+
for (int i = 0; i < ROWS; i++) {
21
+
gpio_init(ROW_PINS[i]);
22
+
gpio_set_dir(ROW_PINS[i], GPIO_OUT);
23
+
gpio_put(ROW_PINS[i], 0); // Start with LEDs off
24
+
}
25
+
26
+
// Set up column pins
27
+
for (int j = 0; j < COLS; j++) {
28
+
gpio_init(COL_PINS[j]);
29
+
gpio_set_dir(COL_PINS[j], GPIO_OUT);
30
+
gpio_put(COL_PINS[j], 1); // Start with LEDs off
31
+
}
32
+
}
33
+
34
+
// Function to update the display at variable frequencies
35
+
void update_led_display(uint32_t refresh_rate_hz) {
36
+
static uint32_t last_update = 0;
37
+
uint32_t current_time = to_ms_since_boot(get_absolute_time());
38
+
uint32_t update_interval = 1000 / refresh_rate_hz;
39
+
40
+
// Only update at the specified frequency
41
+
if (current_time - last_update < update_interval) {
42
+
return;
43
+
}
44
+
45
+
last_update = current_time;
46
+
47
+
// Display the current state
48
+
for (int row = 0; row < ROWS; row++) {
49
+
// Set row active
50
+
gpio_put(ROW_PINS[row], 1);
51
+
52
+
// Set column states for this row
53
+
for (int col = 0; col < COLS; col++) {
54
+
// LED on = column LOW, LED off = column HIGH
55
+
gpio_put(COL_PINS[col], led_states[row][col] ? 0 : 1);
56
+
}
57
+
58
+
// Small delay for this row to be visible
59
+
sleep_us(100);
60
+
61
+
// Deactivate row
62
+
gpio_put(ROW_PINS[row], 0);
63
+
}
64
+
}
65
+
66
+
// Function to set a specific LED state
67
+
void set_led(int row, int col, bool state) {
68
+
if (row >= 0 && row < ROWS && col >= 0 && col < COLS) {
69
+
led_states[row][col] = state ? 1 : 0;
70
+
}
71
+
}
72
+
73
+
// Function to set the entire matrix state
74
+
void set_matrix_state(const uint8_t new_state[ROWS][COLS]) {
75
+
memcpy(led_states, new_state, sizeof(led_states));
76
+
}
77
+
78
+
void random_state(float density) {
79
+
// clamp
80
+
if (density > 1.0f)
81
+
density = 1.0f;
82
+
if (density < 0.0f)
83
+
density = 0.0f;
84
+
85
+
for (int row = 0; row < ROWS; row++) {
86
+
for (int col = 0; col < COLS; col++) {
87
+
float r = (float)rand() / (float)RAND_MAX;
88
+
led_states[row][col] = (r < density) ? 1 : 0;
89
+
}
90
+
}
91
+
}
92
+
93
+
const uint8_t ALL_ON[ROWS][COLS] = {{1, 1, 1, 1, 1, 1},
94
+
{1, 1, 1, 1, 1, 1},
95
+
{1, 1, 1, 1, 1, 1},
96
+
{1, 1, 1, 1, 1, 1}};
97
+
98
+
const uint8_t ALL_OFF[ROWS][COLS] = {{0, 0, 0, 0, 0, 0},
99
+
{0, 0, 0, 0, 0, 0},
100
+
{0, 0, 0, 0, 0, 0},
101
+
{0, 0, 0, 0, 0, 0}};
102
+
103
+
void core1_main() {
104
+
while (true) {
105
+
update_led_display(1000);
106
+
}
107
+
}
108
+
109
+
int main() {
110
+
stdio_init_all();
111
+
setup_pins();
112
+
113
+
multicore_launch_core1(core1_main);
114
+
115
+
while (true) {
116
+
random_state(0.5); // Turn random LEDs ON
117
+
// set_matrix_state(ALL_ON);
118
+
sleep_ms(200);
119
+
// set_matrix_state(ALL_OFF);
120
+
// sleep_ms(500);
121
+
}
122
+
}
+61
flake.lock
+61
flake.lock
···
1
+
{
2
+
"nodes": {
3
+
"flake-utils": {
4
+
"inputs": {
5
+
"systems": "systems"
6
+
},
7
+
"locked": {
8
+
"lastModified": 1731533236,
9
+
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
10
+
"owner": "numtide",
11
+
"repo": "flake-utils",
12
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
13
+
"type": "github"
14
+
},
15
+
"original": {
16
+
"owner": "numtide",
17
+
"repo": "flake-utils",
18
+
"type": "github"
19
+
}
20
+
},
21
+
"nixpkgs": {
22
+
"locked": {
23
+
"lastModified": 1756542300,
24
+
"narHash": "sha256-tlOn88coG5fzdyqz6R93SQL5Gpq+m/DsWpekNFhqPQk=",
25
+
"owner": "NixOS",
26
+
"repo": "nixpkgs",
27
+
"rev": "d7600c775f877cd87b4f5a831c28aa94137377aa",
28
+
"type": "github"
29
+
},
30
+
"original": {
31
+
"owner": "NixOS",
32
+
"ref": "nixos-unstable",
33
+
"repo": "nixpkgs",
34
+
"type": "github"
35
+
}
36
+
},
37
+
"root": {
38
+
"inputs": {
39
+
"flake-utils": "flake-utils",
40
+
"nixpkgs": "nixpkgs"
41
+
}
42
+
},
43
+
"systems": {
44
+
"locked": {
45
+
"lastModified": 1681028828,
46
+
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
47
+
"owner": "nix-systems",
48
+
"repo": "default",
49
+
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
50
+
"type": "github"
51
+
},
52
+
"original": {
53
+
"owner": "nix-systems",
54
+
"repo": "default",
55
+
"type": "github"
56
+
}
57
+
}
58
+
},
59
+
"root": "root",
60
+
"version": 7
61
+
}
+66
flake.nix
+66
flake.nix
···
1
+
{
2
+
description = "Daedalus - RP2350 firmware and Vim plugin";
3
+
4
+
inputs = {
5
+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
6
+
flake-utils.url = "github:numtide/flake-utils";
7
+
};
8
+
9
+
outputs =
10
+
{
11
+
nixpkgs,
12
+
flake-utils,
13
+
...
14
+
}:
15
+
flake-utils.lib.eachDefaultSystem (
16
+
system:
17
+
let
18
+
pkgs = import nixpkgs {
19
+
inherit system;
20
+
};
21
+
22
+
# Needs to be synced past
23
+
# https://github.com/NixOS/nixpkgs/pull/321786
24
+
local-pico-sdk = pkgs.pico-sdk.override {
25
+
withSubmodules = true;
26
+
};
27
+
in
28
+
{
29
+
devShells.default = pkgs.mkShell {
30
+
buildInputs = with pkgs; [
31
+
# C/C++ development
32
+
gcc
33
+
gcc-arm-embedded
34
+
cmake
35
+
gnumake
36
+
37
+
# Pico SDK dependencies
38
+
git
39
+
python3
40
+
python3Packages.pip
41
+
python3Packages.setuptools
42
+
picotool
43
+
44
+
# Debugging tools
45
+
gdb
46
+
openocd
47
+
48
+
# Utilities
49
+
pkg-config
50
+
minicom
51
+
52
+
# Code quality
53
+
clang-tools # clang-format, clang-tidy
54
+
cppcheck
55
+
];
56
+
57
+
shellHook = ''
58
+
# Set environment variables
59
+
export PICO_SDK_PATH="${local-pico-sdk}/lib/pico-sdk"
60
+
61
+
echo "Daedalus development environment ready!"
62
+
'';
63
+
};
64
+
}
65
+
);
66
+
}