espressif: group boards using target name as a family
`hw\bsp` separate one family folder to esp32s2, esp32s3 add board specific board.cmake file to override board specific options(features) fix examples and test scripts to use new family approach
This commit is contained in:
8
hw/bsp/esp32s3/components/led_strip/CMakeLists.txt
Normal file
8
hw/bsp/esp32s3/components/led_strip/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(component_srcs "src/led_strip_rmt_ws2812.c")
|
||||
|
||||
idf_component_register(SRCS "${component_srcs}"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_INCLUDE_DIRS ""
|
||||
PRIV_REQUIRES "driver"
|
||||
REQUIRES "")
|
||||
|
126
hw/bsp/esp32s3/components/led_strip/include/led_strip.h
Normal file
126
hw/bsp/esp32s3/components/led_strip/include/led_strip.h
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief LED Strip Type
|
||||
*
|
||||
*/
|
||||
typedef struct led_strip_s led_strip_t;
|
||||
|
||||
/**
|
||||
* @brief LED Strip Device Type
|
||||
*
|
||||
*/
|
||||
typedef void *led_strip_dev_t;
|
||||
|
||||
/**
|
||||
* @brief Declare of LED Strip Type
|
||||
*
|
||||
*/
|
||||
struct led_strip_s {
|
||||
/**
|
||||
* @brief Set RGB for a specific pixel
|
||||
*
|
||||
* @param strip: LED strip
|
||||
* @param index: index of pixel to set
|
||||
* @param red: red part of color
|
||||
* @param green: green part of color
|
||||
* @param blue: blue part of color
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Set RGB for a specific pixel successfully
|
||||
* - ESP_ERR_INVALID_ARG: Set RGB for a specific pixel failed because of invalid parameters
|
||||
* - ESP_FAIL: Set RGB for a specific pixel failed because other error occurred
|
||||
*/
|
||||
esp_err_t (*set_pixel)(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue);
|
||||
|
||||
/**
|
||||
* @brief Refresh memory colors to LEDs
|
||||
*
|
||||
* @param strip: LED strip
|
||||
* @param timeout_ms: timeout value for refreshing task
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Refresh successfully
|
||||
* - ESP_ERR_TIMEOUT: Refresh failed because of timeout
|
||||
* - ESP_FAIL: Refresh failed because some other error occurred
|
||||
*
|
||||
* @note:
|
||||
* After updating the LED colors in the memory, a following invocation of this API is needed to flush colors to strip.
|
||||
*/
|
||||
esp_err_t (*refresh)(led_strip_t *strip, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Clear LED strip (turn off all LEDs)
|
||||
*
|
||||
* @param strip: LED strip
|
||||
* @param timeout_ms: timeout value for clearing task
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Clear LEDs successfully
|
||||
* - ESP_ERR_TIMEOUT: Clear LEDs failed because of timeout
|
||||
* - ESP_FAIL: Clear LEDs failed because some other error occurred
|
||||
*/
|
||||
esp_err_t (*clear)(led_strip_t *strip, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Free LED strip resources
|
||||
*
|
||||
* @param strip: LED strip
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Free resources successfully
|
||||
* - ESP_FAIL: Free resources failed because error occurred
|
||||
*/
|
||||
esp_err_t (*del)(led_strip_t *strip);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief LED Strip Configuration Type
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t max_leds; /*!< Maximum LEDs in a single strip */
|
||||
led_strip_dev_t dev; /*!< LED strip device (e.g. RMT channel, PWM channel, etc) */
|
||||
} led_strip_config_t;
|
||||
|
||||
/**
|
||||
* @brief Default configuration for LED strip
|
||||
*
|
||||
*/
|
||||
#define LED_STRIP_DEFAULT_CONFIG(number, dev_hdl) \
|
||||
{ \
|
||||
.max_leds = number, \
|
||||
.dev = dev_hdl, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Install a new ws2812 driver (based on RMT peripheral)
|
||||
*
|
||||
* @param config: LED strip configuration
|
||||
* @return
|
||||
* LED strip instance or NULL
|
||||
*/
|
||||
led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
171
hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c
Normal file
171
hw/bsp/esp32s3/components/led_strip/src/led_strip_rmt_ws2812.c
Normal file
@@ -0,0 +1,171 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_attr.h"
|
||||
#include "led_strip.h"
|
||||
#include "driver/rmt.h"
|
||||
|
||||
static const char *TAG = "ws2812";
|
||||
#define STRIP_CHECK(a, str, goto_tag, ret_value, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(a)) \
|
||||
{ \
|
||||
ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
ret = ret_value; \
|
||||
goto goto_tag; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WS2812_T0H_NS (350)
|
||||
#define WS2812_T0L_NS (1000)
|
||||
#define WS2812_T1H_NS (1000)
|
||||
#define WS2812_T1L_NS (350)
|
||||
#define WS2812_RESET_US (280)
|
||||
|
||||
static uint32_t ws2812_t0h_ticks = 0;
|
||||
static uint32_t ws2812_t1h_ticks = 0;
|
||||
static uint32_t ws2812_t0l_ticks = 0;
|
||||
static uint32_t ws2812_t1l_ticks = 0;
|
||||
|
||||
typedef struct {
|
||||
led_strip_t parent;
|
||||
rmt_channel_t rmt_channel;
|
||||
uint32_t strip_len;
|
||||
uint8_t buffer[0];
|
||||
} ws2812_t;
|
||||
|
||||
/**
|
||||
* @brief Conver RGB data to RMT format.
|
||||
*
|
||||
* @note For WS2812, R,G,B each contains 256 different choices (i.e. uint8_t)
|
||||
*
|
||||
* @param[in] src: source data, to converted to RMT format
|
||||
* @param[in] dest: place where to store the convert result
|
||||
* @param[in] src_size: size of source data
|
||||
* @param[in] wanted_num: number of RMT items that want to get
|
||||
* @param[out] translated_size: number of source data that got converted
|
||||
* @param[out] item_num: number of RMT items which are converted from source data
|
||||
*/
|
||||
static void IRAM_ATTR ws2812_rmt_adapter(const void *src, rmt_item32_t *dest, size_t src_size,
|
||||
size_t wanted_num, size_t *translated_size, size_t *item_num)
|
||||
{
|
||||
if (src == NULL || dest == NULL) {
|
||||
*translated_size = 0;
|
||||
*item_num = 0;
|
||||
return;
|
||||
}
|
||||
const rmt_item32_t bit0 = {{{ ws2812_t0h_ticks, 1, ws2812_t0l_ticks, 0 }}}; //Logical 0
|
||||
const rmt_item32_t bit1 = {{{ ws2812_t1h_ticks, 1, ws2812_t1l_ticks, 0 }}}; //Logical 1
|
||||
size_t size = 0;
|
||||
size_t num = 0;
|
||||
uint8_t *psrc = (uint8_t *)src;
|
||||
rmt_item32_t *pdest = dest;
|
||||
while (size < src_size && num < wanted_num) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// MSB first
|
||||
if (*psrc & (1 << (7 - i))) {
|
||||
pdest->val = bit1.val;
|
||||
} else {
|
||||
pdest->val = bit0.val;
|
||||
}
|
||||
num++;
|
||||
pdest++;
|
||||
}
|
||||
size++;
|
||||
psrc++;
|
||||
}
|
||||
*translated_size = size;
|
||||
*item_num = num;
|
||||
}
|
||||
|
||||
static esp_err_t ws2812_set_pixel(led_strip_t *strip, uint32_t index, uint32_t red, uint32_t green, uint32_t blue)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
|
||||
STRIP_CHECK(index < ws2812->strip_len, "index out of the maximum number of leds", err, ESP_ERR_INVALID_ARG);
|
||||
uint32_t start = index * 3;
|
||||
// In thr order of GRB
|
||||
ws2812->buffer[start + 0] = green & 0xFF;
|
||||
ws2812->buffer[start + 1] = red & 0xFF;
|
||||
ws2812->buffer[start + 2] = blue & 0xFF;
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t ws2812_refresh(led_strip_t *strip, uint32_t timeout_ms)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
|
||||
STRIP_CHECK(rmt_write_sample(ws2812->rmt_channel, ws2812->buffer, ws2812->strip_len * 3, true) == ESP_OK,
|
||||
"transmit RMT samples failed", err, ESP_FAIL);
|
||||
return rmt_wait_tx_done(ws2812->rmt_channel, pdMS_TO_TICKS(timeout_ms));
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static esp_err_t ws2812_clear(led_strip_t *strip, uint32_t timeout_ms)
|
||||
{
|
||||
ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
|
||||
// Write zero to turn off all leds
|
||||
memset(ws2812->buffer, 0, ws2812->strip_len * 3);
|
||||
return ws2812_refresh(strip, timeout_ms);
|
||||
}
|
||||
|
||||
static esp_err_t ws2812_del(led_strip_t *strip)
|
||||
{
|
||||
ws2812_t *ws2812 = __containerof(strip, ws2812_t, parent);
|
||||
free(ws2812);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
led_strip_t *led_strip_new_rmt_ws2812(const led_strip_config_t *config)
|
||||
{
|
||||
led_strip_t *ret = NULL;
|
||||
STRIP_CHECK(config, "configuration can't be null", err, NULL);
|
||||
|
||||
// 24 bits per led
|
||||
uint32_t ws2812_size = sizeof(ws2812_t) + config->max_leds * 3;
|
||||
ws2812_t *ws2812 = calloc(1, ws2812_size);
|
||||
STRIP_CHECK(ws2812, "request memory for ws2812 failed", err, NULL);
|
||||
|
||||
uint32_t counter_clk_hz = 0;
|
||||
STRIP_CHECK(rmt_get_counter_clock((rmt_channel_t)config->dev, &counter_clk_hz) == ESP_OK,
|
||||
"get rmt counter clock failed", err, NULL);
|
||||
// ns -> ticks
|
||||
float ratio = (float)counter_clk_hz / 1e9;
|
||||
ws2812_t0h_ticks = (uint32_t)(ratio * WS2812_T0H_NS);
|
||||
ws2812_t0l_ticks = (uint32_t)(ratio * WS2812_T0L_NS);
|
||||
ws2812_t1h_ticks = (uint32_t)(ratio * WS2812_T1H_NS);
|
||||
ws2812_t1l_ticks = (uint32_t)(ratio * WS2812_T1L_NS);
|
||||
|
||||
// set ws2812 to rmt adapter
|
||||
rmt_translator_init((rmt_channel_t)config->dev, ws2812_rmt_adapter);
|
||||
|
||||
ws2812->rmt_channel = (rmt_channel_t)config->dev;
|
||||
ws2812->strip_len = config->max_leds;
|
||||
|
||||
ws2812->parent.set_pixel = ws2812_set_pixel;
|
||||
ws2812->parent.refresh = ws2812_refresh;
|
||||
ws2812->parent.clear = ws2812_clear;
|
||||
ws2812->parent.del = ws2812_del;
|
||||
|
||||
return &ws2812->parent;
|
||||
err:
|
||||
return ret;
|
||||
}
|
Reference in New Issue
Block a user