mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
188 lines
5.8 KiB
C
188 lines
5.8 KiB
C
/*
|
|
* Copyright (C) 2015 Freie Universität Berlin
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* @ingroup sys_auto_init_saul
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Auto initialization of PWM pins directly mapped to SAUL reg
|
|
*
|
|
* @author Christian Amsüss <chrysn@fsfe.org>
|
|
*
|
|
* When this module is used, any PWM device assigned inside the configuration
|
|
* structs inside `pwm_params.h` in the @ref saul_pwm_dimmer_params_t and @ref
|
|
* saul_pwm_rgb_params_t is initialized at startup for 8-bit dimming at about
|
|
* 1kHz, and the indicated channels are exposed via SAUL.
|
|
*
|
|
* @}
|
|
*/
|
|
|
|
#include <inttypes.h>
|
|
#include "log.h"
|
|
#include "saul_reg.h"
|
|
#include "saul/periph.h"
|
|
#include "pwm_params.h"
|
|
#include "periph/pwm.h"
|
|
|
|
#if !defined(SAUL_PWM_FREQ)
|
|
#define SAUL_PWM_FREQ SAUL_PWM_FREQ_DEFAULT
|
|
#endif
|
|
|
|
/**
|
|
* @brief Define the number of configured dimmers
|
|
*/
|
|
#ifndef SAUL_PWM_NO_DIMMER
|
|
#define SAUL_PWM_DIMMER_NUMOF ARRAY_SIZE(saul_pwm_dimmer_params)
|
|
#else
|
|
#define SAUL_PWM_DIMMER_NUMOF 0
|
|
static const saul_pwm_dimmer_params_t saul_pwm_dimmer_params[0];
|
|
#endif
|
|
|
|
/**
|
|
* @brief Define the number of configured RGB LEDs
|
|
*/
|
|
#ifndef SAUL_PWM_NO_RGB
|
|
#define SAUL_PWM_RGB_NUMOF ARRAY_SIZE(saul_pwm_rgb_params)
|
|
#else
|
|
#define SAUL_PWM_RGB_NUMOF 0
|
|
static const saul_pwm_rgb_params_t saul_pwm_rgb_params[0];
|
|
#endif
|
|
|
|
/**
|
|
* @brief Memory for the registry RGB LED entries
|
|
*/
|
|
/* The static variable will be unused in the 0 case and thus not emitted. */
|
|
static saul_reg_t saul_reg_entries_rgb[SAUL_PWM_RGB_NUMOF];
|
|
|
|
/**
|
|
* @brief Memory for the registry dimmer entries
|
|
*/
|
|
/* The static variable will be unused in the 0 case and thus not emitted. */
|
|
static saul_reg_t saul_reg_entries_dimmer[SAUL_PWM_DIMMER_NUMOF];
|
|
|
|
/**
|
|
* @brief Reference to the driver for single-channel dimmers
|
|
*/
|
|
extern saul_driver_t dimmer_saul_driver;
|
|
|
|
/**
|
|
* @brief Reference to the driver for RGB LEDs
|
|
*/
|
|
extern saul_driver_t rgb_saul_driver;
|
|
|
|
/**
|
|
* Configure a PWM driver for LED output (1kHz, 8bit)
|
|
*/
|
|
static int configure(pwm_t dev)
|
|
{
|
|
LOG_DEBUG("[auto_init_saul] initializing PWM %u for LED operation,", dev);
|
|
uint32_t freq = pwm_init(dev, PWM_LEFT, SAUL_PWM_FREQ, saul_pwm_resolution);
|
|
LOG_DEBUG(" actual frequency %" PRIu32 ",\n", freq);
|
|
return freq != 0 ? 0 : -ENOTSUP;
|
|
}
|
|
|
|
/**
|
|
* Configure the PWM driver at the given index (inside saul_pwm_dimmer_params,
|
|
* overflowing into saul_pwm_rgb_params) unless that device came up previously,
|
|
* in which case the function returns without any action.
|
|
* */
|
|
static int configure_on_first_use(pwm_t dev, unsigned index)
|
|
{
|
|
/* Work around -Werror=type-limits that would otherwise trigger */
|
|
unsigned dimmer_numof = SAUL_PWM_DIMMER_NUMOF;
|
|
for (unsigned i = 0; i < dimmer_numof; ++i) {
|
|
pwm_t currentdev = saul_pwm_dimmer_params[i].channel.dev;
|
|
if (currentdev == dev) {
|
|
if (i == index) {
|
|
return configure(dev);
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* Work around -Werror=type-limits that would otherwise trigger */
|
|
unsigned rgb_numof = SAUL_PWM_RGB_NUMOF;
|
|
for (unsigned i = 0; i < rgb_numof; ++i) {
|
|
for (int j = 0; j < 3; ++j) {
|
|
unsigned index = SAUL_PWM_DIMMER_NUMOF + i * 3 + j;
|
|
pwm_t currentdev = saul_pwm_rgb_params[i].channels[j].dev;
|
|
if (currentdev == dev) {
|
|
if (i == index) {
|
|
return configure(dev);
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return -ENOENT;
|
|
}
|
|
|
|
void auto_init_saul_pwm(void)
|
|
{
|
|
/* Work around -Werror=type-limits that would otherwise trigger */
|
|
unsigned dimmer_numof = SAUL_PWM_DIMMER_NUMOF;
|
|
for (unsigned i = 0; i < dimmer_numof; i++) {
|
|
const saul_pwm_dimmer_params_t *p = &saul_pwm_dimmer_params[i];
|
|
|
|
LOG_DEBUG("[auto_init_saul] initializing dimmer #%u\n", i);
|
|
|
|
saul_reg_entries_dimmer[i].dev = (void*)p;
|
|
saul_reg_entries_dimmer[i].name = p->name;
|
|
saul_reg_entries_dimmer[i].driver = &dimmer_saul_driver;
|
|
|
|
int err = configure_on_first_use(p->channel.dev, i);
|
|
if (err != 0) {
|
|
LOG_ERROR(
|
|
"[auto_init_saul] Error initializing device for dimmer #%u\n",
|
|
i);
|
|
/* not `continue`ing: we could run into this on a non-first use and
|
|
* then we couldn't break either */
|
|
}
|
|
/* set initial dark state */
|
|
phydat_t s;
|
|
s.val[0] = 0;
|
|
saul_reg_entries_dimmer[i].driver->write(p, &s);
|
|
/* add to registry */
|
|
saul_reg_add(&(saul_reg_entries_dimmer[i]));
|
|
}
|
|
|
|
/* Work around -Werror=type-limits that would otherwise trigger */
|
|
unsigned rgb_numof = SAUL_PWM_RGB_NUMOF;
|
|
for (unsigned i = 0; i < rgb_numof; i++) {
|
|
const saul_pwm_rgb_params_t *p = &saul_pwm_rgb_params[i];
|
|
|
|
LOG_DEBUG("[auto_init_saul] initializing RGB #%u\n", i);
|
|
|
|
saul_reg_entries_rgb[i].dev = (void*)p;
|
|
saul_reg_entries_rgb[i].name = p->name;
|
|
saul_reg_entries_rgb[i].driver = &rgb_saul_driver;
|
|
|
|
for (int j = 0; j < 3; ++j) {
|
|
unsigned index = SAUL_PWM_DIMMER_NUMOF + i * 3 + j;
|
|
int err = configure_on_first_use(p->channels[j].dev, index);
|
|
if (err != 0) {
|
|
LOG_ERROR(
|
|
"[auto_init_saul] Error initializing device for RGB #%u/%u\n",
|
|
i, j);
|
|
/* not `continue`ing: we could run into this on a non-first use and
|
|
* then we couldn't break either */
|
|
}
|
|
}
|
|
/* set initial dark state */
|
|
phydat_t s;
|
|
s.val[0] = 0;
|
|
s.val[1] = 0;
|
|
s.val[2] = 0;
|
|
saul_reg_entries_rgb[i].driver->write(p, &s);
|
|
/* add to registry */
|
|
saul_reg_add(&(saul_reg_entries_rgb[i]));
|
|
}
|
|
}
|