-
Notifications
You must be signed in to change notification settings - Fork 1.1k
add pico_status_led #2501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
peterharperuk
wants to merge
6
commits into
raspberrypi:develop
Choose a base branch
from
peterharperuk:status_led
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
add pico_status_led #2501
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
1836660
Fix dependency issue with pico_cyw43_driver
peterharperuk 95e7529
Fix build warnings in cyw43_driver.c
peterharperuk 5490b1a
Allow LwIP to be disabled by default
peterharperuk 282fe5a
Status led library
peterharperuk e156d2e
Add status led library to the build
peterharperuk f83483a
Add status led to kitchen sink
peterharperuk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
load("//bazel:defs.bzl", "compatible_with_rp2", "pico_generate_pio_header") | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
cc_library( | ||
name = "pico_status_led", | ||
srcs = ["status_led.c"], | ||
hdrs = ["include/pico/status_led.h"], | ||
includes = ["include"], | ||
target_compatible_with = compatible_with_rp2(), | ||
deps = [ | ||
"//src/rp2_common/hardware_gpio", | ||
"//src/rp2_common/hardware_pio", | ||
] + select({ | ||
"//bazel/constraint:is_pico_w": [ | ||
"//src/rp2_common/pico_cyw43_driver", | ||
], | ||
"//bazel/constraint:is_pico2_w": [ | ||
"//src/rp2_common/pico_cyw43_driver" | ||
], | ||
"//conditions:default": [], | ||
}), | ||
) | ||
|
||
pico_generate_pio_header( | ||
name = "ws2812", | ||
srcs = ["ws2812.pio"], | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
pico_add_library(pico_status_led) | ||
target_sources(pico_status_led INTERFACE | ||
${CMAKE_CURRENT_LIST_DIR}/status_led.c | ||
) | ||
target_include_directories(pico_status_led_headers SYSTEM INTERFACE | ||
${CMAKE_CURRENT_LIST_DIR}/include | ||
) | ||
pico_mirrored_target_link_libraries(pico_status_led INTERFACE | ||
hardware_gpio | ||
hardware_pio | ||
) | ||
if (PICO_CYW43_SUPPORTED) | ||
pico_mirrored_target_link_libraries(pico_status_led INTERFACE | ||
pico_cyw43_driver cyw43_driver_picow pico_async_context_threadsafe_background | ||
) | ||
target_compile_definitions(pico_status_led INTERFACE | ||
CYW43_LWIP_DEFAULT=0 # Disable LwIP by default. Can be overridden if LwIP is needed. | ||
) | ||
endif() | ||
pico_generate_pio_header(pico_status_led ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio) | ||
|
||
get_target_property(OUT pico_status_led LINK_LIBRARIES) |
133 changes: 133 additions & 0 deletions
133
src/rp2_common/pico_status_led/include/pico/status_led.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/* | ||
* Copyright (c) 2025 Raspberry Pi (Trading) Ltd. | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
/** \file pico/status_led.h | ||
* \defgroup pico_status_led pico_status_led | ||
* | ||
* \brief Enables access to the on-board status leds | ||
* | ||
* 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) | ||
* This library hides the details so you can use the status leds for all boards without changing your code. | ||
*/ | ||
|
||
#ifndef _PICO_STATUS_LED_H | ||
#define _PICO_STATUS_LED_H | ||
|
||
#include "hardware/gpio.h" | ||
|
||
#if defined(CYW43_WL_GPIO_LED_PIN) | ||
#include "cyw43.h" | ||
#endif | ||
|
||
struct async_context; | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
// PICO_CONFIG: PICO_STATUS_LED_WS2812_WRGB, Inidicate if the colored status led supports WRGB, type=bool, default=false group=pico_status_led | ||
#ifndef PICO_STATUS_LED_WS2812_WRGB | ||
#define PICO_STATUS_LED_WS2812_WRGB 0 | ||
#endif | ||
|
||
/*! \brief Initialise the status leds | ||
* \ingroup pico_status_led | ||
* | ||
* Initialise the status leds and the resources they need before use. | ||
* | ||
* \param context The hardware for some devices (e.g. Pico W) requires an async context. | ||
* You can usually only have one of these. Pass the async context into the function or pass NULL to get the function to just create a context for it's own use if needed . | ||
* \return Returns true if the led was initialised successfully, otherwise an error occurred | ||
*/ | ||
bool pico_status_led_init(struct async_context *context); | ||
|
||
/*! \brief Set the status led on or off | ||
* \ingroup pico_status_led | ||
* | ||
* \note: If your hardware does not support a status led (\see PICO_DEFAULT_LED_PIN), this function does nothing and returns false. | ||
* | ||
* \param led_on True to turn the led on. Pass False to turn the led off | ||
* \param True if the status led could be set, otherwise false | ||
*/ | ||
static inline bool pico_status_led_set(bool led_on) { | ||
#if defined PICO_DEFAULT_LED_PIN | ||
gpio_put(PICO_DEFAULT_LED_PIN, led_on); | ||
return true; | ||
#elif defined CYW43_WL_GPIO_LED_PIN | ||
cyw43_gpio_set(&cyw43_state, CYW43_WL_GPIO_LED_PIN, led_on); | ||
return true; | ||
peterharperuk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#else | ||
return false; | ||
#endif | ||
} | ||
|
||
/*! \brief Get the state of the status led | ||
* \ingroup pico_status_led | ||
* | ||
* \note: If your hardware does not support a status led (\see PICO_DEFAULT_LED_PIN), this function always returns false. | ||
* | ||
* \return True if the led is on, or False if the led is off | ||
*/ | ||
static inline bool pico_status_led_get(void) { | ||
#if defined PICO_DEFAULT_LED_PIN | ||
return gpio_get(PICO_DEFAULT_LED_PIN); | ||
#elif defined CYW43_WL_GPIO_LED_PIN | ||
bool value = false; | ||
cyw43_gpio_get(&cyw43_state, CYW43_WL_GPIO_LED_PIN, &value); | ||
return value; | ||
#else | ||
return false; | ||
#endif | ||
} | ||
|
||
/*! \brief Set the colored status led value | ||
* \ingroup pico_status_led | ||
* | ||
* The colored status led defaults to off. Use this function to change its color. | ||
* | ||
* \note: If your hardware does not support a colored status led (\see PICO_DEFAULT_WS2812_PIN), this function does nothing and returns false. | ||
* | ||
* \param value The color of the colored status led in 0xWWRRGGBB format. | ||
* \param True if the coloured status led could be set, otherwise false on failure | ||
*/ | ||
bool pico_status_led_color_set(uint32_t value); | ||
|
||
/*! \brief Get the colored status led value | ||
* \ingroup pico_status_led | ||
* | ||
* \note: If your hardware does not support a colored status led (\see PICO_DEFAULT_WS2812_PIN), this function always returns 0x0. | ||
* | ||
* \return The color of the colored status led in 0xWWRRGGBB format. | ||
*/ | ||
uint32_t pico_status_led_color_get(void); | ||
|
||
/*! \brief Generate an RGB colour value for /ref pico_status_led_color_set | ||
* \ingroup pico_status_led | ||
*/ | ||
#define PICO_STATUS_LED_RGB(R, G, B) (((R) << 16) | ((G) << 8) | (B)) | ||
|
||
/*! \brief Generate an WRGB colour value for \ref pico_status_led_color_set | ||
* | ||
* \note: If your hardware does not support a white pixel, the white component is ignored | ||
* | ||
* \ingroup pico_status_led | ||
*/ | ||
#define PICO_STATUS_LED_WRGB(W, R, G, B) (((W) << 24) | ((R) << 16) | ((G) << 8) | (B)) | ||
|
||
/*! \brief Deinitialise the status leds | ||
* \ingroup pico_status_led | ||
* | ||
* Deinitialises the status leds when they are no longer needed. | ||
* | ||
* \param context The async context to be used. This should be the same as the value passed into pico_status_led_init | ||
*/ | ||
void pico_status_led_deinit(struct async_context *context); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
* Copyright (c) 2025 Raspberry Pi (Trading) Ltd. | ||
* | ||
* SPDX-License-Identifier: BSD-3-Clause | ||
*/ | ||
|
||
#include "pico/status_led.h" | ||
|
||
#if defined(CYW43_WL_GPIO_LED_PIN) | ||
#include "pico/cyw43_driver.h" | ||
#include "pico/async_context_threadsafe_background.h" | ||
#endif | ||
|
||
#ifdef PICO_DEFAULT_WS2812_PIN | ||
#include <hardware/pio.h> | ||
#include "ws2812.pio.h" | ||
|
||
// PICO_CONFIG: PICO_STATUS_LED_WS2812_FREQ, Frequency per bit for the WS2812 status led pio, type=int, default=800000, group=pico_status_led | ||
#ifndef PICO_STATUS_LED_WS2812_FREQ | ||
#define PICO_STATUS_LED_WS2812_FREQ 800000 | ||
#endif | ||
|
||
static PIO pio; | ||
static uint sm; | ||
static int offset = -1; | ||
static uint32_t ws2812_value; | ||
|
||
// Extract from 0xWWRRGGBB | ||
#define RED(C) ((C >> 16) & 0xff) | ||
#define GREEN(C) ((C >> 8) & 0xff) | ||
#define BLUE(C) ((C >> 0) & 0xff) | ||
#define WHITE(C) ((C >> 24) && 0xff) | ||
#endif // PICO_STATUS_LED_WS2812_PIN | ||
|
||
bool pico_status_led_color_set(uint32_t value) { | ||
#ifdef PICO_DEFAULT_WS2812_PIN | ||
ws2812_value = value; | ||
if (offset > -1) { | ||
#if PICO_STATUS_LED_WS2812_WRGB | ||
// Convert to 0xWWGGRRBB | ||
pio_sm_put_blocking(pio, sm, WHITE(ws2812_value) << 24 | GREEN(ws2812_value) << 16 | RED(ws2812_value) << 8 | BLUE(ws2812_value)); | ||
#else | ||
// Convert to 0xGGRRBB00 | ||
pio_sm_put_blocking(pio, sm, GREEN(ws2812_value) << 24 | RED(ws2812_value) << 16 | BLUE(ws2812_value) << 8); | ||
#endif //P ICO_STATUS_LED_WS2812_WRGB | ||
return true; | ||
} | ||
#else | ||
(void)value; | ||
#endif // PICO_DEFAULT_WS2812_PIN | ||
return false; | ||
} | ||
|
||
uint32_t pico_status_led_color_get(void) { | ||
#ifdef PICO_DEFAULT_WS2812_PIN | ||
return ws2812_value; | ||
#else | ||
return 0x0; | ||
#endif | ||
} | ||
|
||
#if defined(CYW43_WL_GPIO_LED_PIN) | ||
static async_context_threadsafe_background_t status_led_context; | ||
#endif | ||
|
||
bool pico_status_led_init(struct async_context *context) { | ||
#if defined(PICO_DEFAULT_LED_PIN) | ||
gpio_init(PICO_DEFAULT_LED_PIN); | ||
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); | ||
#elif defined(CYW43_WL_GPIO_LED_PIN) | ||
assert(!status_led_context.core.type); | ||
if (!context) { | ||
async_context_threadsafe_background_config_t config = async_context_threadsafe_background_default_config(); | ||
if (!async_context_threadsafe_background_init(&status_led_context, &config)) { | ||
return false; | ||
} | ||
if (!cyw43_driver_init(&status_led_context.core)) { | ||
async_context_deinit(&status_led_context.core); | ||
return false; | ||
} | ||
} | ||
#endif | ||
#if PICO_DEFAULT_WS2812_PIN | ||
if (pio_claim_free_sm_and_add_program_for_gpio_range(&ws2812_program, &pio, &sm, &offset, PICO_DEFAULT_WS2812_PIN, 1, true)) { | ||
ws2812_program_init(pio, sm, offset, PICO_DEFAULT_WS2812_PIN, PICO_STATUS_LED_WS2812_FREQ, PICO_STATUS_LED_WS2812_WRGB); | ||
} else { | ||
pico_status_led_deinit(context); | ||
return false; | ||
} | ||
#endif | ||
(void)context; | ||
return true; | ||
} | ||
|
||
void pico_status_led_deinit(struct async_context *context) { | ||
// Note: We cannot deinit cyw43 in case it has other users | ||
#if defined(PICO_DEFAULT_LED_PIN) | ||
gpio_deinit(PICO_DEFAULT_LED_PIN); | ||
#elif defined(CYW43_WL_GPIO_LED_PIN) | ||
assert((context && !status_led_context.core.type) || (!context && status_led_context.core.type)); | ||
if (!context) { | ||
cyw43_driver_deinit(&status_led_context.core); | ||
async_context_deinit(&status_led_context.core); | ||
} | ||
#endif | ||
#if PICO_DEFAULT_WS2812_PIN | ||
if (offset >= 0) { | ||
pio_remove_program_and_unclaim_sm(&ws2812_program, pio, sm, offset); | ||
offset = -1; | ||
} | ||
#endif | ||
(void)context; | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What colour would you use for on and off? Would it be onfigurable at build time? Would it be configurable at run time?