Skip to content

Commit 40417de

Browse files
committed
Status led library
Functions for turning a binary led on and off and setting value of a colour status led. Set/get the colour used if the colored led is ON... pico_status_led_color_set_on_value pico_status_led_color_get_on_value Set the coloured led ON or OFF pico_status_led_color_set pico_status_led_color_get pico_status_led_set and pico_status_led_get call these functions if PICO_DEFAULT_LED_PIN is not defined or PICO_STATUS_LED_COLOR_ONLY is true. PICO_DEFAULT_LED_PIN_INVERTED and PICO_DEFAULT_WS2812_POWER_PIN are now used. Fixes #188
1 parent cce86cd commit 40417de

File tree

8 files changed

+458
-2
lines changed

8 files changed

+458
-2
lines changed

src/cmake/rp2_common.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ if (NOT PICO_BARE_METAL)
140140
pico_add_subdirectory(rp2_common/pico_standard_link)
141141

142142
pico_add_subdirectory(rp2_common/pico_fix)
143+
pico_add_subdirectory(rp2_common/pico_status_led)
143144

144145
# at the end as it includes a lot of other stuff
145146
pico_add_subdirectory(rp2_common/pico_runtime_init)

src/rp2_common/pico_lwip/lwip_freertos.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ static void tcpip_init_done(void *param) {
2525
}
2626

2727
bool lwip_freertos_init(async_context_t *context) {
28-
assert(!lwip_context);
29-
lwip_context = context;
28+
assert(!lwip_context || lwip_context == context);
3029
static bool done_lwip_init;
3130
if (!done_lwip_init) {
31+
lwip_context = context;
3232
done_lwip_init = true;
3333
SemaphoreHandle_t init_sem = xSemaphoreCreateBinary();
3434
tcpip_task_blocker = xSemaphoreCreateBinary();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
load("//bazel:defs.bzl", "compatible_with_rp2", "pico_generate_pio_header")
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
cc_library(
6+
name = "pico_status_led",
7+
srcs = ["status_led.c"],
8+
hdrs = ["include/pico/status_led.h"],
9+
includes = ["include"],
10+
target_compatible_with = compatible_with_rp2(),
11+
deps = [
12+
"//src/rp2_common/hardware_gpio",
13+
"//src/rp2_common/hardware_pio",
14+
] + select({
15+
"//bazel/constraint:is_pico_w": [
16+
"//src/rp2_common/pico_cyw43_driver",
17+
],
18+
"//bazel/constraint:is_pico2_w": [
19+
"//src/rp2_common/pico_cyw43_driver"
20+
],
21+
"//conditions:default": [],
22+
}),
23+
)
24+
25+
pico_generate_pio_header(
26+
name = "ws2812",
27+
srcs = ["ws2812.pio"],
28+
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
pico_add_library(pico_status_led)
2+
target_sources(pico_status_led INTERFACE
3+
${CMAKE_CURRENT_LIST_DIR}/status_led.c
4+
)
5+
target_include_directories(pico_status_led_headers SYSTEM INTERFACE
6+
${CMAKE_CURRENT_LIST_DIR}/include
7+
)
8+
pico_mirrored_target_link_libraries(pico_status_led INTERFACE
9+
hardware_gpio
10+
hardware_pio
11+
)
12+
if (PICO_CYW43_SUPPORTED)
13+
pico_mirrored_target_link_libraries(pico_status_led INTERFACE
14+
pico_cyw43_driver cyw43_driver_picow pico_async_context_threadsafe_background
15+
)
16+
target_compile_definitions(pico_status_led INTERFACE
17+
CYW43_LWIP_DEFAULT=0 # Disable LwIP by default. Can be overridden if LwIP is needed.
18+
)
19+
endif()
20+
pico_generate_pio_header(pico_status_led ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio)
21+
22+
get_target_property(OUT pico_status_led LINK_LIBRARIES)
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Copyright (c) 2025 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
/** \file pico/status_led.h
8+
* \defgroup pico_status_led pico_status_led
9+
*
10+
* \brief Enables access to the on-board status leds
11+
*
12+
* Boards usually have access to an on-board status leds which are configured via the board header (\see PICO_DEFAULT_LED_PIN and \see PICO_DEFAULT_WS2812_PIN)
13+
* This library hides the details so you can use the status leds for all boards without changing your code.
14+
*/
15+
16+
#ifndef _PICO_STATUS_LED_H
17+
#define _PICO_STATUS_LED_H
18+
19+
#include "hardware/gpio.h"
20+
21+
#if defined(CYW43_WL_GPIO_LED_PIN)
22+
#include "cyw43.h"
23+
#endif
24+
25+
struct async_context;
26+
27+
#ifdef __cplusplus
28+
extern "C" {
29+
#endif
30+
31+
// PICO_CONFIG: PICO_STATUS_LED_WS2812_WRGB, Indicate if the colored status led supports WRGB, type=bool, default=0, group=pico_status_led
32+
#ifndef PICO_STATUS_LED_WS2812_WRGB
33+
#define PICO_STATUS_LED_WS2812_WRGB 0
34+
#endif
35+
36+
// PICO_CONFIG: PICO_STATUS_LED_COLOR_ONLY, Indicate if only the colored status led should be used. Only true by default if a WS2812 pin is defined and no led pin is defined, type=bool, group=pico_status_led
37+
#ifdef PICO_DEFAULT_WS2812_PIN
38+
#ifndef PICO_STATUS_LED_COLOR_ONLY
39+
#define PICO_STATUS_LED_COLOR_ONLY !(defined PICO_DEFAULT_LED_PIN || defined CYW43_WL_GPIO_LED_PIN)
40+
#endif
41+
#else
42+
// Force this off if PICO_DEFAULT_WS2812_PIN is not defined
43+
#undef PICO_STATUS_LED_COLOR_ONLY
44+
#define PICO_STATUS_LED_COLOR_ONLY 0
45+
#endif
46+
47+
/*! \brief Generate an RGB colour value for /ref pico_status_led_color_set_on_value
48+
* \ingroup pico_status_led
49+
*/
50+
#ifndef PICO_STATUS_LED_RGB
51+
#define PICO_STATUS_LED_RGB(R, G, B) (((R) << 16) | ((G) << 8) | (B))
52+
#endif
53+
54+
/*! \brief Generate an WRGB colour value for \ref pico_status_led_color_set_on_value
55+
*
56+
* \note: If your hardware does not support a white pixel, the white component is ignored
57+
*
58+
* \ingroup pico_status_led
59+
*/
60+
#ifndef PICO_STATUS_LED_WRGB
61+
#define PICO_STATUS_LED_WRGB(W, R, G, B) (((W) << 24) | ((R) << 16) | ((G) << 8) | (B))
62+
#endif
63+
64+
// PICO_CONFIG: PICO_STATUS_LED_COLOR_ON_DEFAULT, the default pixel color value of the coloured status led when it is on. type=int, group=pico_status_led
65+
#ifndef PICO_STATUS_LED_COLOR_ON_DEFAULT
66+
#if PICO_STATUS_LED_WS2812_WRGB
67+
#define PICO_STATUS_LED_COLOR_ON_DEFAULT PICO_STATUS_LED_WRGB(0xaa, 0, 0, 0)
68+
#else
69+
#define PICO_STATUS_LED_COLOR_ON_DEFAULT PICO_STATUS_LED_RGB(0xaa, 0xaa, 0xaa)
70+
#endif
71+
#endif
72+
73+
// PICO_CONFIG: PICO_STATUS_LED_COLOR_OFF, the pixel color value of the coloured status led when it is off. type=int, group=pico_status_led
74+
#ifndef PICO_STATUS_LED_COLOR_OFF
75+
#if PICO_STATUS_LED_WS2812_WRGB
76+
#define PICO_STATUS_LED_COLOR_OFF PICO_STATUS_LED_WRGB(0, 0, 0, 0)
77+
#else
78+
#define PICO_STATUS_LED_COLOR_OFF PICO_STATUS_LED_RGB(0, 0, 0)
79+
#endif
80+
#endif
81+
82+
/*! \brief Initialise the status leds
83+
* \ingroup pico_status_led
84+
*
85+
* Initialise the status leds and the resources they need before use.
86+
*
87+
* \note: You must call this function before using any other status led functions.
88+
*
89+
* \param context An async context is needed to control the led on some devices (e.g. Pico W).
90+
* You can usually only have one async context. Pass your async context into the function or if you don't have one, pass NULL to get the function to just create a context for it's own use as and if required.
91+
* \return Returns true if the led was initialised successfully, otherwise false on failure
92+
*/
93+
bool pico_status_led_init(struct async_context *context);
94+
95+
/*! \brief Set the color used for the status led when it is on
96+
* \ingroup pico_status_led
97+
*
98+
* \note: If your hardware does not support a colored status led (\see PICO_DEFAULT_WS2812_PIN), this function does nothing and returns false.
99+
*
100+
* \param value The color to use for the colored status led when it is on, in 0xWWRRGGBB format
101+
* \param True if the coloured status led could be set, otherwise false on failure
102+
*/
103+
bool pico_status_led_color_set_on_value(uint32_t value);
104+
105+
/*! \brief Get the color used for the status led value when it is on
106+
* \ingroup pico_status_led
107+
*
108+
* \note: If your hardware does not support a colored status led (\see PICO_DEFAULT_WS2812_PIN), this function always returns 0x0.
109+
*
110+
* \return The color used for the colored status led when it is on, in 0xWWRRGGBB format
111+
*/
112+
uint32_t pico_status_led_color_get_on_value(void);
113+
114+
/*! \brief Set the colored status led on or off
115+
* \ingroup pico_status_led
116+
*
117+
* \note: If your hardware does not support a colored status led (\see PICO_DEFAULT_WS2812_PIN), this function does nothing and returns false.
118+
*
119+
* \param led_on True to turn the colored led on. Pass False to turn the colored led off
120+
* \param True if the colored status led could be set, otherwise false
121+
*/
122+
bool pico_status_led_color_set(bool led_on);
123+
124+
/*! \brief Get the state of the colored status led
125+
* \ingroup pico_status_led
126+
*
127+
* \note: If your hardware does not support a colored status led (\see PICO_DEFAULT_WS2812_PIN), this function returns false.
128+
*
129+
* \return True if the colored status led is on, or False if the coloured status led is off
130+
*/
131+
bool pico_status_led_color_get(void);
132+
133+
/*! \brief Set the status led on or off
134+
* \ingroup pico_status_led
135+
*
136+
* \note: If your hardware does not support a status led (\see PICO_DEFAULT_LED_PIN), this function does nothing and returns false.
137+
*
138+
* \param led_on True to turn the led on. Pass False to turn the led off
139+
* \param True if the status led could be set, otherwise false
140+
*/
141+
static inline bool pico_status_led_set(bool led_on) {
142+
#if PICO_STATUS_LED_COLOR_ONLY
143+
return pico_status_led_color_set(led_on);
144+
#elif defined PICO_DEFAULT_LED_PIN
145+
#if defined(PICO_DEFAULT_LED_PIN_INVERTED) && PICO_DEFAULT_LED_PIN_INVERTED
146+
gpio_put(PICO_DEFAULT_LED_PIN, !led_on);
147+
#else
148+
gpio_put(PICO_DEFAULT_LED_PIN, led_on);
149+
#endif
150+
return true;
151+
#elif defined CYW43_WL_GPIO_LED_PIN
152+
cyw43_gpio_set(&cyw43_state, CYW43_WL_GPIO_LED_PIN, led_on);
153+
return true;
154+
#else
155+
return false;
156+
#endif
157+
}
158+
159+
/*! \brief Get the state of the status led
160+
* \ingroup pico_status_led
161+
*
162+
* \note: If your hardware does not support a status led (\see PICO_DEFAULT_LED_PIN), this function always returns false.
163+
*
164+
* \return True if the status led is on, or False if the status led is off
165+
*/
166+
static inline bool pico_status_led_get(void) {
167+
#if PICO_STATUS_LED_COLOR_ONLY
168+
return pico_status_led_color_get();
169+
#elif defined PICO_DEFAULT_LED_PIN
170+
#if defined(PICO_DEFAULT_LED_PIN_INVERTED) && PICO_DEFAULT_LED_PIN_INVERTED
171+
return !gpio_get(PICO_DEFAULT_LED_PIN);
172+
#else
173+
return gpio_get(PICO_DEFAULT_LED_PIN);
174+
#endif
175+
#elif defined CYW43_WL_GPIO_LED_PIN
176+
bool value = false;
177+
cyw43_gpio_get(&cyw43_state, CYW43_WL_GPIO_LED_PIN, &value);
178+
return value;
179+
#else
180+
return false;
181+
#endif
182+
}
183+
184+
/*! \brief Deinitialise the status leds
185+
* \ingroup pico_status_led
186+
*
187+
* Deinitialises the status leds when they are no longer needed.
188+
*
189+
* \param context The async context to be used. This should be the same as the value passed into pico_status_led_init
190+
*/
191+
void pico_status_led_deinit(struct async_context *context);
192+
193+
#ifdef __cplusplus
194+
}
195+
#endif
196+
197+
#endif

0 commit comments

Comments
 (0)