mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 05:12:57 +01:00
Merge pull request #14242 from HendrikVE/pr/driver/pca9633
driver/pca9633: add new driver
This commit is contained in:
commit
3665e40726
@ -584,6 +584,10 @@ ifneq (,$(filter opt3001,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter pca9633,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_i2c
|
||||
endif
|
||||
|
||||
ifneq (,$(filter pca9685,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += periph_gpio
|
||||
FEATURES_REQUIRED += periph_i2c
|
||||
|
@ -276,6 +276,10 @@ ifneq (,$(filter opt3001,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/opt3001/include
|
||||
endif
|
||||
|
||||
ifneq (,$(filter pca9633,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/pca9633/include
|
||||
endif
|
||||
|
||||
ifneq (,$(filter pca9685,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/drivers/pca9685/include
|
||||
endif
|
||||
|
337
drivers/include/pca9633.h
Normal file
337
drivers/include/pca9633.h
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_pca9633 PCA9633 I2C PWM controller
|
||||
* @ingroup drivers_actuators
|
||||
* @brief Device driver for the NXP PCA9633
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
|
||||
* @file
|
||||
*/
|
||||
|
||||
#ifndef PCA9633_H
|
||||
#define PCA9633_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "stdbool.h"
|
||||
#include "periph/i2c.h"
|
||||
|
||||
#include "pca9633_regs.h"
|
||||
|
||||
/**
|
||||
* @brief Blinking period with a maximum duration of ~10.73 s
|
||||
*/
|
||||
#define PCA9633_BLINKING_PERIOD_MAX_MS (10625)
|
||||
|
||||
/**
|
||||
* @brief Ration between on/ off in blinking mode is balanced.
|
||||
*
|
||||
* 128 = 255 / 2
|
||||
*/
|
||||
#define PCA9633_BLINKING_RATIO_BALANCED 128
|
||||
|
||||
/**
|
||||
* @brief PCA9633 device initialization parameters
|
||||
*/
|
||||
typedef struct {
|
||||
i2c_t i2c_dev; /**< I2C device */
|
||||
uint16_t i2c_addr; /**< I2C address of device */
|
||||
|
||||
uint8_t reg_pwm_red; /**< Register for red color */
|
||||
uint8_t reg_pwm_green; /**< Register for green color */
|
||||
uint8_t reg_pwm_blue; /**< Register for blue color */
|
||||
uint8_t reg_pwm_amber; /**< Register for amber color */
|
||||
|
||||
bool has_amber_channel; /**< Whether PCA9633 has fourth channel */
|
||||
} pca9633_params_t;
|
||||
|
||||
/**
|
||||
* @brief PCA9633 PWM device data structure type
|
||||
*/
|
||||
typedef struct {
|
||||
pca9633_params_t params; /**< Device initialization parameters */
|
||||
uint8_t stored_reg_ledout; /**< Stored register content of LEDOUT */
|
||||
} pca9633_t;
|
||||
|
||||
/**
|
||||
* @brief PCA9633 driver error codes
|
||||
*/
|
||||
typedef enum {
|
||||
PCA9633_OK = 0, /**< Success */
|
||||
PCA9633_ERROR_I2C = 1, /**< I2C communication error */
|
||||
} pca9685_error_t;
|
||||
|
||||
/**
|
||||
* @brief PCA9633 PWM channel definitions
|
||||
*/
|
||||
typedef enum {
|
||||
PCA9633_PWM_CHANNEL_0 = PCA9633_REG_PWM0, /**< PWM channel 0 */
|
||||
PCA9633_PWM_CHANNEL_1 = PCA9633_REG_PWM1, /**< PWM channel 1 */
|
||||
PCA9633_PWM_CHANNEL_2 = PCA9633_REG_PWM2, /**< PWM channel 2 */
|
||||
PCA9633_PWM_CHANNEL_3 = PCA9633_REG_PWM3, /**< PWM channel 3 */
|
||||
} pca9633_pwm_channel_t;
|
||||
|
||||
/**
|
||||
* @brief LED driver output state, LEDOUT (page 14, below table 13)
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* @brief LED driver x is off
|
||||
*/
|
||||
PCA9633_LDR_STATE_OFF,
|
||||
|
||||
/**
|
||||
* @brief LED driver x is fully on (individual brightness and group
|
||||
* dimming/ blinking not controlled)
|
||||
*/
|
||||
PCA9633_LDR_STATE_ON,
|
||||
|
||||
/**
|
||||
* @brief LED driver x individual brightness can be controlled through its
|
||||
* PWMx register
|
||||
*/
|
||||
PCA9633_LDR_STATE_IND,
|
||||
|
||||
/**
|
||||
* @brief LED driver x individual brightness and group dimming/ blinking can
|
||||
* be controlled through its PWMx register and the GRPPWM registers.
|
||||
* If using PCA9633_LDR_STATE_IND_GRP the controller takes the
|
||||
* minimum value of PWM* and GRPPWM register
|
||||
*/
|
||||
PCA9633_LDR_STATE_IND_GRP,
|
||||
} pca9633_ldr_state_t;
|
||||
|
||||
/**
|
||||
* @brief Auto-Increment options (page 10, table 6)
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* @brief No Auto-Increment
|
||||
*/
|
||||
PCA9633_AI_DISABLED,
|
||||
|
||||
/**
|
||||
* @brief Auto-Increment for all registers. D3, D2, D1, D0 roll over to
|
||||
* ‘0000’ after the last register (1100) is accessed.
|
||||
*/
|
||||
PCA9633_AI_ALL,
|
||||
|
||||
/**
|
||||
* @brief Auto-Increment for individual brightness registers only.
|
||||
* D3, D2, D1, D0 roll over to ‘0010’ after the last register (0101)
|
||||
* is accessed.
|
||||
*/
|
||||
PCA9633_AI_IND,
|
||||
|
||||
/**
|
||||
* @brief Auto-Increment for global control registers only. D3, D2, D1, D0
|
||||
* roll over to ‘0110’ after the last register (0111) is accessed.
|
||||
*/
|
||||
PCA9633_AI_GBL,
|
||||
|
||||
/**
|
||||
* @brief Auto-Increment for individual and global control registers only.
|
||||
* D3, D2, D1, D0 roll over to ‘0010’ after the last register (0111)
|
||||
* is accessed.
|
||||
*/
|
||||
PCA9633_AI_IND_GBL,
|
||||
} pca9633_auto_inc_option_t;
|
||||
|
||||
/**
|
||||
* @brief PCA9633 group control modes
|
||||
*/
|
||||
typedef enum {
|
||||
/**
|
||||
* @brief Control mode for blinking
|
||||
*/
|
||||
PCA9633_GROUP_CONTROL_MODE_BLINKING,
|
||||
|
||||
/**
|
||||
* @brief Control mode for dimming
|
||||
*/
|
||||
PCA9633_GROUP_CONTROL_MODE_DIMMING,
|
||||
} pca9633_group_control_mode_t;
|
||||
|
||||
/**
|
||||
* @brief Initialization.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] params Parameters for device initialization
|
||||
*
|
||||
* @return PCA9633_OK on success
|
||||
* @return -PCA9633_ERROR_I2C if acquiring of I2C bus fails
|
||||
* @return -EIO When slave device doesn't ACK the byte
|
||||
* @return -ENXIO When no devices respond on the address sent on the bus
|
||||
* @return -ETIMEDOUT When timeout occurs before device's response
|
||||
* @return -EINVAL When an invalid argument is given
|
||||
* @return -EOPNOTSUPP When MCU driver doesn't support the flag operation
|
||||
* @return -EAGAIN When a lost bus arbitration occurs
|
||||
*/
|
||||
int pca9633_init(pca9633_t *dev, const pca9633_params_t *params);
|
||||
|
||||
/**
|
||||
* @brief Turn on all LEDs. Restores settings saved at pca9633_turn_off().
|
||||
*
|
||||
* WARNING: If you call pca9633_turn_off() twice, without calling
|
||||
* pca9633_turn_on() in between, then the restored state will be
|
||||
* PCA9633_LDR_STATE_OFF!
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
*/
|
||||
void pca9633_turn_on(pca9633_t* dev);
|
||||
|
||||
/**
|
||||
* @brief Turn off all LEDs. Saves current settings for pca9633_turn_on().
|
||||
* For power saving, see pca9633_sleep().
|
||||
*
|
||||
* WARNING: If you call pca9633_turn_off() twice, without calling
|
||||
* pca9633_turn_on() in between, then the restored state will be
|
||||
* PCA9633_LDR_STATE_OFF!
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
*/
|
||||
void pca9633_turn_off(pca9633_t* dev);
|
||||
|
||||
/**
|
||||
* @brief Switch to normal mode.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
*/
|
||||
void pca9633_wakeup(pca9633_t* dev);
|
||||
|
||||
/**
|
||||
* @brief Switch to low power mode.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
*/
|
||||
void pca9633_sleep(pca9633_t* dev);
|
||||
|
||||
/**
|
||||
* @brief Set individual PWM signal for a given channel.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] pwm_channel PWM channel
|
||||
* @param[in] pwm PWM value
|
||||
*/
|
||||
void pca9633_set_pwm(pca9633_t* dev,
|
||||
pca9633_pwm_channel_t pwm_channel, uint8_t pwm);
|
||||
|
||||
/**
|
||||
* @brief Set global PWM signal.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] pwm PWM value
|
||||
*/
|
||||
void pca9633_set_grp_pwm(pca9633_t* dev, uint8_t pwm);
|
||||
|
||||
/**
|
||||
* @brief Set up values for blinking mode. Blinking mode needs to be activated
|
||||
* manually by calling
|
||||
* pca9633_set_group_control_mode(GROUP_CONTROL_MODE_BLINKING).
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] blink_period_ms Period in ms for one blink (turning off and on).
|
||||
* Maximum period possible is
|
||||
* PCA9633_BLINKING_PERIOD_MAX_MS ≈ 10.73 s. All
|
||||
* values above this maximum will we capped to it.
|
||||
* @param[in] on_off_ratio Value between 0 and 255, where e.g. a value of
|
||||
* 64 (255/4) means 1/4 of the time the LEDs are on
|
||||
* and 3/4 of the time the LEDs are off.
|
||||
*/
|
||||
void pca9633_set_blinking(pca9633_t* dev, uint16_t blink_period_ms,
|
||||
uint8_t on_off_ratio);
|
||||
|
||||
/**
|
||||
* @brief Set PWM values for RGB.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] r Value for red color channel
|
||||
* @param[in] g Value for green color channel
|
||||
* @param[in] b Value for blue color channel
|
||||
*/
|
||||
void pca9633_set_rgb(pca9633_t* dev, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
/**
|
||||
* @brief Set PWM values for RGBA.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] r Value for red color channel
|
||||
* @param[in] g Value for green color channel
|
||||
* @param[in] b Value for blue color channel
|
||||
* @param[in] w Value for amber color channel
|
||||
*/
|
||||
void pca9633_set_rgba(pca9633_t* dev, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
|
||||
|
||||
/**
|
||||
* @brief Set the LED driver output state for a given channel.
|
||||
* There are four states:
|
||||
* - PCA9633_LDR_STATE_OFF
|
||||
* - PCA9633_LDR_STATE_ON
|
||||
* - PCA9633_LDR_STATE_IND
|
||||
* - PCA9633_LDR_STATE_IND_GRP
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] state One of the four possible states
|
||||
* @param[in] pwm_channel PWM channel belonging to LDR
|
||||
*/
|
||||
void pca9633_set_ldr_state(pca9633_t* dev,
|
||||
pca9633_ldr_state_t state,
|
||||
pca9633_pwm_channel_t pwm_channel);
|
||||
|
||||
/**
|
||||
* @brief Set the LED driver output state for all channels.
|
||||
* There are four states:
|
||||
* - PCA9633_LDR_STATE_OFF
|
||||
* - PCA9633_LDR_STATE_ON
|
||||
* - PCA9633_LDR_STATE_IND
|
||||
* - PCA9633_LDR_STATE_IND_GRP
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] state One of the four possible states
|
||||
*/
|
||||
void pca9633_set_ldr_state_all(pca9633_t* dev, pca9633_ldr_state_t state);
|
||||
|
||||
/**
|
||||
* @brief Set an option for auto increment.
|
||||
* There are five options:
|
||||
* - PCA9633_AI_DISABLED
|
||||
* - PCA9633_AI_ALL
|
||||
* - PCA9633_AI_IND
|
||||
* - PCA9633_AI_GBL
|
||||
* - PCA9633_AI_IND_GBL
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] option One of the possible five options
|
||||
*/
|
||||
void pca9633_set_auto_increment(pca9633_t* dev, pca9633_auto_inc_option_t option);
|
||||
|
||||
/**
|
||||
* @brief Set the group control mode.
|
||||
* There are two modes:
|
||||
* - PCA9633_GROUP_CONTROL_MODE_BLINKING
|
||||
* - PCA9633_GROUP_CONTROL_MODE_DIMMING
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] mode One of the two possible modes
|
||||
*/
|
||||
void pca9633_set_group_control_mode(pca9633_t* dev,
|
||||
pca9633_group_control_mode_t mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PCA9633_H */
|
||||
/** @} */
|
1
drivers/pca9633/Makefile
Normal file
1
drivers/pca9633/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
98
drivers/pca9633/include/pca9633_params.h
Normal file
98
drivers/pca9633/include/pca9633_params.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 drivers_actuators
|
||||
* @brief Default configuration for the PCA9633 I2C PWM controller
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
|
||||
* @file
|
||||
*/
|
||||
#ifndef PCA9633_PARAMS_H
|
||||
#define PCA9633_PARAMS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "periph/i2c.h"
|
||||
|
||||
#include "pca9633_regs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Set default configuration parameters
|
||||
* @{
|
||||
*/
|
||||
#ifndef PCA9633_PARAM_I2C_DEV
|
||||
/** I2C device is I2C_DEV(0) */
|
||||
#define PCA9633_PARAM_I2C_DEV I2C_DEV(0)
|
||||
#endif
|
||||
|
||||
#ifndef PCA9633_PARAM_I2C_ADDR
|
||||
/** I2C address of device is (0xc0 >> 1) */
|
||||
#define PCA9633_PARAM_I2C_ADDR (0xc0 >> 1)
|
||||
#endif
|
||||
|
||||
#ifndef PCA9633_PARAM_REG_PWM_RED
|
||||
/** Register for red color is PCA9633_REG_PWM2 */
|
||||
#define PCA9633_PARAM_REG_PWM_RED PCA9633_REG_PWM2
|
||||
#endif
|
||||
|
||||
#ifndef PCA9633_PARAM_REG_PWM_GREEN
|
||||
/** Register for green color is PCA9633_REG_PWM1 */
|
||||
#define PCA9633_PARAM_REG_PWM_GREEN PCA9633_REG_PWM1
|
||||
#endif
|
||||
|
||||
#ifndef PCA9633_PARAM_REG_PWM_BLUE
|
||||
/** Register for blue color is PCA9633_REG_PWM0 */
|
||||
#define PCA9633_PARAM_REG_PWM_BLUE PCA9633_REG_PWM0
|
||||
#endif
|
||||
|
||||
#ifndef PCA9633_PARAM_REG_PWM_AMBER
|
||||
/** Register for amber color is not given (0) */
|
||||
#define PCA9633_PARAM_REG_PWM_AMBER 0
|
||||
#endif
|
||||
|
||||
#ifndef PCA9633_PARAM_HAS_AMBER_CHANNEL
|
||||
/** PCA9633 has no connected channel for amber (false) */
|
||||
#define PCA9633_PARAM_HAS_AMBER_CHANNEL false
|
||||
#endif
|
||||
|
||||
#ifndef PCA9633_PARAMS
|
||||
#define PCA9633_PARAMS \
|
||||
{ \
|
||||
.i2c_dev = PCA9633_PARAM_I2C_DEV, \
|
||||
.i2c_addr = PCA9633_PARAM_I2C_ADDR, \
|
||||
.reg_pwm_red = PCA9633_PARAM_REG_PWM_RED, \
|
||||
.reg_pwm_green = PCA9633_PARAM_REG_PWM_GREEN, \
|
||||
.reg_pwm_blue = PCA9633_PARAM_REG_PWM_BLUE, \
|
||||
.reg_pwm_amber = PCA9633_PARAM_REG_PWM_AMBER, \
|
||||
.has_amber_channel = PCA9633_PARAM_HAS_AMBER_CHANNEL \
|
||||
}
|
||||
#endif /* PCA9633_PARAMS */
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @brief Allocate some memory to store the actual configuration
|
||||
*/
|
||||
static const pca9633_params_t pca9633_params[] =
|
||||
{
|
||||
PCA9633_PARAMS
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PCA9633_PARAMS_H */
|
||||
/** @} */
|
214
drivers/pca9633/include/pca9633_regs.h
Normal file
214
drivers/pca9633/include/pca9633_regs.h
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 drivers_pca9633
|
||||
* @brief Register definitions for the PCA9633 I2C PWM controller
|
||||
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
|
||||
* @file
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef PCA9633_REGS_H
|
||||
#define PCA9633_REGS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Register definitions (page 11, table 7) */
|
||||
|
||||
/**
|
||||
* @brief Mode register 1
|
||||
*/
|
||||
#define PCA9633_REG_MODE1 0x00
|
||||
|
||||
/**
|
||||
* @brief Mode register 2
|
||||
*/
|
||||
#define PCA9633_REG_MODE2 0x01
|
||||
|
||||
/**
|
||||
* @brief Brightness control LED0
|
||||
*/
|
||||
#define PCA9633_REG_PWM0 0x02
|
||||
|
||||
/**
|
||||
* @brief Brightness control LED1
|
||||
*/
|
||||
#define PCA9633_REG_PWM1 0x03
|
||||
|
||||
/**
|
||||
* @brief Brightness control LED2
|
||||
*/
|
||||
#define PCA9633_REG_PWM2 0x04
|
||||
|
||||
/**
|
||||
* @brief Brightness control LED3
|
||||
*/
|
||||
#define PCA9633_REG_PWM3 0x05
|
||||
|
||||
/**
|
||||
* @brief Group duty cycle control
|
||||
*/
|
||||
#define PCA9633_REG_GRPPWM 0x06
|
||||
|
||||
/**
|
||||
* @brief Group frequency
|
||||
*/
|
||||
#define PCA9633_REG_GRPFREQ 0x07
|
||||
|
||||
/**
|
||||
* @brief LED output state
|
||||
*/
|
||||
#define PCA9633_REG_LEDOUT 0x08
|
||||
|
||||
/**
|
||||
* @brief I2C-bus subaddress 1
|
||||
*/
|
||||
#define PCA9633_REG_SUBADR1 0x09
|
||||
|
||||
/**
|
||||
* @brief I2C-bus subaddress 2
|
||||
*/
|
||||
#define PCA9633_REG_SUBADR2 0x0A
|
||||
|
||||
/**
|
||||
* @brief I2C-bus subaddress 3
|
||||
*/
|
||||
#define PCA9633_REG_SUBADR3 0x0B
|
||||
|
||||
/**
|
||||
* @brief LED All Call I2C-bus address
|
||||
*/
|
||||
#define PCA9633_REG_ALLCALLADR 0x0C
|
||||
|
||||
|
||||
|
||||
/* Bits in REG_MODE1 (page 12, table 8) */
|
||||
|
||||
/**
|
||||
* @brief Bit for register Auto-Increment
|
||||
* 0 = disabled
|
||||
* 1 = enabled
|
||||
*/
|
||||
#define PCA9633_BIT_AI2 7
|
||||
|
||||
/**
|
||||
* @brief Bit for Auto-Increment bit1
|
||||
*/
|
||||
#define PCA9633_BIT_AI1 6
|
||||
|
||||
/**
|
||||
* @brief Bit for Auto-Increment bit0
|
||||
*/
|
||||
#define PCA9633_BIT_AI0 5
|
||||
|
||||
/**
|
||||
* @brief 0 = Normal mode
|
||||
* 1 = Low power mode. Oscillator off
|
||||
*/
|
||||
#define PCA9633_BIT_SLEEP 4
|
||||
|
||||
/**
|
||||
* @brief 0 = PCA9633 does not respond to I2C-bus subaddress 1
|
||||
* 1 = PCA9633 responds to I2C-bus subaddress 1
|
||||
*/
|
||||
#define PCA9633_BIT_SUB1 3
|
||||
|
||||
/**
|
||||
* @brief 0 = PCA9633 does not respond to I2C-bus subaddress 2
|
||||
* 1 = PCA9633 responds to I2C-bus subaddress 2
|
||||
*/
|
||||
#define PCA9633_BIT_SUB2 2
|
||||
|
||||
/**
|
||||
* @brief 0 = PCA9633 does not respond to I2C-bus subaddress 3
|
||||
* 1 = PCA9633 responds to I2C-bus subaddress 3
|
||||
*/
|
||||
#define PCA9633_BIT_SUB3 1
|
||||
|
||||
/**
|
||||
* @brief 0 = PCA9633 does not respond to LED All Call I2C-bus address
|
||||
* 1 = PCA9633 responds to LED All Call I2C-bus address
|
||||
*/
|
||||
#define PCA9633_BIT_ALLCALL 0
|
||||
|
||||
|
||||
|
||||
/* Bits in REG_MODE2 (page 12-13, table 9) */
|
||||
|
||||
/**
|
||||
* @brief Bit for group control; 0=dimming, 1=blinking
|
||||
*/
|
||||
#define PCA9633_BIT_DMBLNK 5
|
||||
|
||||
/**
|
||||
* @brief 0 = Output logic state not inverted. Value to use when no external driver used
|
||||
* 1 = Output logic state inverted. Value to use when external driver used
|
||||
*/
|
||||
#define PCA9633_BIT_INVRT 4
|
||||
|
||||
/**
|
||||
* @brief 0 = Outputs change on STOP command
|
||||
* 1 = Outputs change on ACK
|
||||
*/
|
||||
#define PCA9633_BIT_OCH 3
|
||||
|
||||
/**
|
||||
* @brief 0 = The 4 LED outputs are configured with an open-drain structure
|
||||
* 1 = The 4 LED outputs are configured with a totem pole structure
|
||||
*/
|
||||
#define PCA9633_BIT_OUTDRV 2
|
||||
|
||||
/**
|
||||
* @brief See PCA9633_BIT_OUTNE0
|
||||
*/
|
||||
#define PCA9633_BIT_OUTNE1 1
|
||||
|
||||
/**
|
||||
* @brief 00 = When OE = 1 (output drivers not enabled), LEDn = 0.
|
||||
* 01* = When OE = 1 (output drivers not enabled):
|
||||
* LEDn = 1 when OUTDRV = 1
|
||||
* LEDn = high-impedance when OUTDRV = 0 (same as OUTNE[1:0] = 10)
|
||||
* 10 When OE = 1 (output drivers not enabled), LEDn = high-impedance.
|
||||
* 11 reserved
|
||||
*/
|
||||
#define PCA9633_BIT_OUTNE0 0
|
||||
|
||||
|
||||
|
||||
/* Bits in REG_LEDOUT (page 14, table 13) */
|
||||
|
||||
/**
|
||||
* @brief Lower of two bits for LDR3
|
||||
*/
|
||||
#define PCA9633_BIT_LDR3 6
|
||||
|
||||
/**
|
||||
* @brief Lower of two bits for LDR2
|
||||
*/
|
||||
#define PCA9633_BIT_LDR2 4
|
||||
|
||||
/**
|
||||
* @brief Lower of two bits for LDR1
|
||||
*/
|
||||
#define PCA9633_BIT_LDR1 2
|
||||
|
||||
/**
|
||||
* @brief Lower of two bits for LDR0
|
||||
*/
|
||||
#define PCA9633_BIT_LDR0 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PCA9633_REGS_H */
|
||||
/** @} */
|
277
drivers/pca9633/pca9633.c
Normal file
277
drivers/pca9633/pca9633.c
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 drivers_pca9633
|
||||
* @brief Device driver for the PCA9633 I2C PWM controller
|
||||
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
|
||||
* @file
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pca9633.h"
|
||||
#include "pca9633_regs.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief Write data to a register.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] reg Register address to write to
|
||||
* @param[in] data Data to write
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -PCA9633_ERROR_I2C if acquiring of I2C bus fails
|
||||
* @return -EIO When slave device doesn't ACK the byte
|
||||
* @return -ENXIO When no devices respond on the address sent on the bus
|
||||
* @return -ETIMEDOUT When timeout occurs before device's response
|
||||
* @return -EINVAL When an invalid argument is given
|
||||
* @return -EOPNOTSUPP When MCU driver doesn't support the flag operation
|
||||
* @return -EAGAIN When a lost bus arbitration occurs
|
||||
*/
|
||||
static int _write_reg(pca9633_t* dev, uint8_t reg, uint8_t data);
|
||||
|
||||
/**
|
||||
* @brief Read data from a register.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the PCA9633
|
||||
* @param[in] reg Register address to read from
|
||||
* @param[out] data Byte read from given registerAddress
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -PCA9633_ERROR_I2C if acquiring of I2C bus fails
|
||||
* @return -EIO When slave device doesn't ACK the byte
|
||||
* @return -ENXIO When no devices respond on the address sent on the bus
|
||||
* @return -ETIMEDOUT When timeout occurs before device's response
|
||||
* @return -EINVAL When an invalid argument is given
|
||||
* @return -EOPNOTSUPP When MCU driver doesn't support the flag operation
|
||||
* @return -EAGAIN When a lost bus arbitration occurs
|
||||
*/
|
||||
static int _read_reg(pca9633_t* dev, uint8_t reg, uint8_t* data);
|
||||
|
||||
int pca9633_init(pca9633_t *dev, const pca9633_params_t *params)
|
||||
{
|
||||
assert(dev);
|
||||
assert(params);
|
||||
|
||||
dev->params = *params;
|
||||
|
||||
i2c_init(dev->params.i2c_dev);
|
||||
|
||||
int rc = _write_reg(dev, PCA9633_REG_MODE1, 0x0);
|
||||
_write_reg(dev, PCA9633_REG_MODE2, 0x0);
|
||||
|
||||
if (rc != PCA9633_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return PCA9633_OK;
|
||||
}
|
||||
|
||||
void pca9633_wakeup(pca9633_t* dev)
|
||||
{
|
||||
uint8_t reg;
|
||||
_read_reg(dev, PCA9633_REG_MODE1, ®);
|
||||
reg = reg & ~(1 << PCA9633_BIT_SLEEP);
|
||||
|
||||
_write_reg(dev, PCA9633_REG_MODE1, reg);
|
||||
}
|
||||
|
||||
void pca9633_sleep(pca9633_t* dev)
|
||||
{
|
||||
uint8_t reg;
|
||||
_read_reg(dev, PCA9633_REG_MODE1, ®);
|
||||
reg = reg | (1 << PCA9633_BIT_SLEEP);
|
||||
|
||||
_write_reg(dev, PCA9633_REG_MODE1, reg);
|
||||
}
|
||||
|
||||
void pca9633_turn_on(pca9633_t* dev)
|
||||
{
|
||||
_write_reg(dev, PCA9633_REG_LEDOUT, dev->stored_reg_ledout);
|
||||
}
|
||||
|
||||
void pca9633_turn_off(pca9633_t* dev)
|
||||
{
|
||||
_read_reg(dev, PCA9633_REG_LEDOUT, &dev->stored_reg_ledout);
|
||||
_write_reg(dev, PCA9633_REG_LEDOUT, PCA9633_LDR_STATE_OFF);
|
||||
}
|
||||
|
||||
void pca9633_set_pwm(pca9633_t* dev,
|
||||
pca9633_pwm_channel_t pwm_channel, uint8_t pwm)
|
||||
{
|
||||
_write_reg(dev, pwm_channel, pwm);
|
||||
}
|
||||
|
||||
void pca9633_set_grp_pwm(pca9633_t* dev, uint8_t pwm)
|
||||
{
|
||||
_write_reg(dev, PCA9633_REG_GRPPWM, pwm);
|
||||
}
|
||||
|
||||
void pca9633_set_blinking(pca9633_t* dev, uint16_t blink_period_ms,
|
||||
uint8_t on_off_ratio)
|
||||
{
|
||||
/* frequency of 24 Hz is used: */
|
||||
uint16_t blink_period = (24 * blink_period_ms) / 1000;
|
||||
if (blink_period > 255) {
|
||||
blink_period = 255;
|
||||
}
|
||||
|
||||
_write_reg(dev, PCA9633_REG_GRPFREQ, (uint8_t) blink_period);
|
||||
_write_reg(dev, PCA9633_REG_GRPPWM, on_off_ratio);
|
||||
}
|
||||
|
||||
void pca9633_set_rgb(pca9633_t* dev, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
pca9633_set_pwm(dev, dev->params.reg_pwm_red, r);
|
||||
pca9633_set_pwm(dev, dev->params.reg_pwm_green, g);
|
||||
pca9633_set_pwm(dev, dev->params.reg_pwm_blue, b);
|
||||
}
|
||||
|
||||
void pca9633_set_rgba(pca9633_t* dev, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
{
|
||||
pca9633_set_rgb(dev, r, g, b);
|
||||
|
||||
if (dev->params.has_amber_channel) {
|
||||
pca9633_set_pwm(dev, dev->params.reg_pwm_amber, a);
|
||||
}
|
||||
}
|
||||
|
||||
void pca9633_set_ldr_state(pca9633_t* dev,
|
||||
pca9633_ldr_state_t state, pca9633_pwm_channel_t pwm_channel)
|
||||
{
|
||||
uint8_t ldr_bit;
|
||||
switch (pwm_channel) {
|
||||
case PCA9633_PWM_CHANNEL_0:
|
||||
ldr_bit = PCA9633_BIT_LDR0;
|
||||
break;
|
||||
case PCA9633_PWM_CHANNEL_1:
|
||||
ldr_bit = PCA9633_BIT_LDR1;
|
||||
break;
|
||||
case PCA9633_PWM_CHANNEL_2:
|
||||
ldr_bit = PCA9633_BIT_LDR2;
|
||||
break;
|
||||
case PCA9633_PWM_CHANNEL_3:
|
||||
ldr_bit = PCA9633_BIT_LDR3;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t reg;
|
||||
_read_reg(dev, PCA9633_REG_LEDOUT, ®);
|
||||
|
||||
/* first clear both bits of ldr */
|
||||
reg = reg & ~(0b11 << ldr_bit);
|
||||
|
||||
/* second set new state to specified ldr */
|
||||
reg |= (state << ldr_bit);
|
||||
|
||||
_write_reg(dev, PCA9633_REG_LEDOUT, reg);
|
||||
}
|
||||
|
||||
void pca9633_set_ldr_state_all(pca9633_t* dev, pca9633_ldr_state_t state)
|
||||
{
|
||||
uint8_t reg = (state << PCA9633_BIT_LDR3)
|
||||
| (state << PCA9633_BIT_LDR2)
|
||||
| (state << PCA9633_BIT_LDR1)
|
||||
| (state << PCA9633_BIT_LDR0);
|
||||
|
||||
_write_reg(dev, PCA9633_REG_LEDOUT, reg);
|
||||
}
|
||||
|
||||
void pca9633_set_auto_increment(pca9633_t* dev, pca9633_auto_inc_option_t option)
|
||||
{
|
||||
uint8_t new_reg;
|
||||
|
||||
switch (option) {
|
||||
|
||||
case PCA9633_AI_ALL:
|
||||
new_reg = (1 << PCA9633_BIT_AI2)
|
||||
| (0 << PCA9633_BIT_AI1)
|
||||
| (0 << PCA9633_BIT_AI0);
|
||||
break;
|
||||
|
||||
case PCA9633_AI_IND:
|
||||
new_reg = (1 << PCA9633_BIT_AI2)
|
||||
| (1 << PCA9633_BIT_AI1)
|
||||
| (0 << PCA9633_BIT_AI0);
|
||||
break;
|
||||
|
||||
case PCA9633_AI_GBL:
|
||||
new_reg = (1 << PCA9633_BIT_AI2)
|
||||
| (0 << PCA9633_BIT_AI1)
|
||||
| (1 << PCA9633_BIT_AI0);
|
||||
break;
|
||||
|
||||
case PCA9633_AI_IND_GBL:
|
||||
new_reg = (1 << PCA9633_BIT_AI2)
|
||||
| (1 << PCA9633_BIT_AI1)
|
||||
| (1 << PCA9633_BIT_AI0);
|
||||
break;
|
||||
|
||||
case PCA9633_AI_DISABLED:
|
||||
/* fall-thru */
|
||||
default:
|
||||
new_reg = (0 << PCA9633_BIT_AI2)
|
||||
| (0 << PCA9633_BIT_AI1)
|
||||
| (0 << PCA9633_BIT_AI0);
|
||||
break;
|
||||
}
|
||||
|
||||
_write_reg(dev, PCA9633_REG_MODE1, new_reg);
|
||||
}
|
||||
|
||||
void pca9633_set_group_control_mode(pca9633_t* dev,
|
||||
pca9633_group_control_mode_t mode)
|
||||
{
|
||||
uint8_t prev_reg;
|
||||
_read_reg(dev, PCA9633_REG_MODE2, &prev_reg);
|
||||
|
||||
switch (mode) {
|
||||
|
||||
case PCA9633_GROUP_CONTROL_MODE_BLINKING:
|
||||
_write_reg(dev, PCA9633_REG_MODE2, prev_reg | (1 << PCA9633_BIT_DMBLNK));
|
||||
break;
|
||||
|
||||
case PCA9633_GROUP_CONTROL_MODE_DIMMING:
|
||||
default:
|
||||
_write_reg(dev, PCA9633_REG_MODE2, prev_reg & ~(1 << PCA9633_BIT_DMBLNK));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int _write_reg(pca9633_t* dev, uint8_t reg, uint8_t data)
|
||||
{
|
||||
i2c_t i2c_dev = dev->params.i2c_dev;
|
||||
|
||||
if (i2c_acquire(i2c_dev) != 0) {
|
||||
return -PCA9633_ERROR_I2C;
|
||||
}
|
||||
int rc = i2c_write_reg(i2c_dev, dev->params.i2c_addr, reg, data, 0);
|
||||
i2c_release(i2c_dev);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int _read_reg(pca9633_t* dev, uint8_t reg, uint8_t* data)
|
||||
{
|
||||
i2c_t i2c_dev = dev->params.i2c_dev;
|
||||
|
||||
if (i2c_acquire(i2c_dev) != 0) {
|
||||
return -PCA9633_ERROR_I2C;
|
||||
}
|
||||
int rc = i2c_read_reg(i2c_dev, dev->params.i2c_addr, reg, data, 0);
|
||||
i2c_release(i2c_dev);
|
||||
|
||||
return rc;
|
||||
}
|
7
tests/driver_pca9633/Makefile
Normal file
7
tests/driver_pca9633/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
include ../Makefile.tests_common
|
||||
|
||||
USEMODULE += pca9633
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += shell
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
8
tests/driver_pca9633/Makefile.ci
Normal file
8
tests/driver_pca9633/Makefile.ci
Normal file
@ -0,0 +1,8 @@
|
||||
BOARD_INSUFFICIENT_MEMORY := \
|
||||
arduino-duemilanove \
|
||||
arduino-leonardo \
|
||||
arduino-nano \
|
||||
arduino-uno \
|
||||
atmega328p \
|
||||
atmega32u4 \
|
||||
#
|
24
tests/driver_pca9633/README.md
Normal file
24
tests/driver_pca9633/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# PCA9633 I2C PWM controller
|
||||
|
||||
## Overview
|
||||
|
||||
This test application demonstrates the usage of the PCA9633 driver interface
|
||||
and can be used to test a PCA9633 PWM device with shell commands.
|
||||
|
||||
## Usage
|
||||
|
||||
The following shell commands are available:
|
||||
* **turn_on:** Turn on all LEDs.
|
||||
* **turn_off:** Turn off all LEDs.
|
||||
* **wakeup:** Switch to normal mode.
|
||||
* **sleep:** Switch to low power mode.
|
||||
* **pwm:** Set individual PWM signal for a given channel.
|
||||
* **grp_pwm:** Set global PWM signal.
|
||||
* **blinking:** Set up values for blinking mode.
|
||||
* **rgb:** Set PWM values for RGB.
|
||||
* **rgba:** Set PWM values for RGBA.
|
||||
* **ldr_state:** Set the LED driver output state for a given channel.
|
||||
* **ldr_state_all:** Set the LED driver output state for all channels.
|
||||
* **auto_increment:** Set an option for auto increment.
|
||||
* **grp_ctrl_mode:** Set the group control mode.
|
||||
* **run_demo:** Demonstration of all functions.
|
483
tests/driver_pca9633/main.c
Normal file
483
tests/driver_pca9633/main.c
Normal file
@ -0,0 +1,483 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 tests
|
||||
* @brief Test application for the PCA9633 I2C PWM controller
|
||||
* @author Hendrik van Essen <hendrik.ve@fu-berlin.de>
|
||||
* @file
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "xtimer.h"
|
||||
#include "shell.h"
|
||||
|
||||
#include "pca9633.h"
|
||||
#include "pca9633_params.h"
|
||||
|
||||
pca9633_t pca9633_dev;
|
||||
|
||||
int turn_on(int argc, char **argv)
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
pca9633_turn_on(&pca9633_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int turn_off(int argc, char **argv)
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
pca9633_turn_off(&pca9633_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wakeup(int argc, char **argv)
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
pca9633_wakeup(&pca9633_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sleep(int argc, char **argv)
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
pca9633_sleep(&pca9633_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pwm(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
puts("usage: pwm <channel (0-3)> <signal (0-255)>");
|
||||
}
|
||||
else {
|
||||
uint8_t pwm = atoi(argv[2]);
|
||||
|
||||
pca9633_pwm_channel_t pwm_channel;
|
||||
switch (atoi(argv[1])) {
|
||||
case 0:
|
||||
pwm_channel = PCA9633_PWM_CHANNEL_0;
|
||||
break;
|
||||
case 1:
|
||||
pwm_channel = PCA9633_PWM_CHANNEL_1;
|
||||
break;
|
||||
case 2:
|
||||
pwm_channel = PCA9633_PWM_CHANNEL_2;
|
||||
break;
|
||||
case 3:
|
||||
pwm_channel = PCA9633_PWM_CHANNEL_3;
|
||||
break;
|
||||
default:
|
||||
puts("channel needs to be one of [0-3]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pca9633_set_pwm(&pca9633_dev, pwm_channel, pwm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int grp_pwm(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
puts("usage: grp_pwm <signal (0-255)>");
|
||||
}
|
||||
else {
|
||||
uint8_t pwm = atoi(argv[1]);
|
||||
|
||||
pca9633_set_grp_pwm(&pca9633_dev, pwm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blinking(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
puts("usage: blinking <0 or 1>");
|
||||
}
|
||||
else {
|
||||
uint8_t enabled = atoi(argv[1]);
|
||||
|
||||
if (enabled >= 1) {
|
||||
pca9633_set_group_control_mode(&pca9633_dev,
|
||||
PCA9633_GROUP_CONTROL_MODE_BLINKING);
|
||||
|
||||
pca9633_set_blinking(&pca9633_dev,
|
||||
1000,
|
||||
PCA9633_BLINKING_RATIO_BALANCED);
|
||||
}
|
||||
else {
|
||||
pca9633_set_group_control_mode(&pca9633_dev,
|
||||
PCA9633_GROUP_CONTROL_MODE_DIMMING);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rgb(int argc, char **argv)
|
||||
{
|
||||
if (argc != 4) {
|
||||
puts("usage: rgb <red (0-255)> <green (0-255)> <blue (0-255)>");
|
||||
}
|
||||
else {
|
||||
uint8_t r = atoi(argv[1]);
|
||||
uint8_t g = atoi(argv[2]);
|
||||
uint8_t b = atoi(argv[3]);
|
||||
|
||||
pca9633_set_rgb(&pca9633_dev, r, g, b);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rgba(int argc, char **argv)
|
||||
{
|
||||
if (argc != 5) {
|
||||
puts("usage: rgba <red (0-255)> <green (0-255)> <blue (0-255)> <amber (0-255)>");
|
||||
}
|
||||
else {
|
||||
uint8_t r = atoi(argv[1]);
|
||||
uint8_t g = atoi(argv[2]);
|
||||
uint8_t b = atoi(argv[3]);
|
||||
uint8_t w = atoi(argv[4]);
|
||||
|
||||
pca9633_set_rgba(&pca9633_dev, r, g, b, w);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ldr_state(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3) {
|
||||
puts("usage: ldr_state <state (0-3)> pwm <channel (0-3)>");
|
||||
|
||||
puts(" state 0: PCA9633_LDR_STATE_OFF");
|
||||
puts(" state 1: PCA9633_LDR_STATE_ON");
|
||||
puts(" state 2: PCA9633_LDR_STATE_IND");
|
||||
puts(" state 3: PCA9633_LDR_STATE_IND_GRP");
|
||||
|
||||
puts(" channel 0: PCA9633_PWM_CHANNEL_0");
|
||||
puts(" channel 1: PCA9633_PWM_CHANNEL_1");
|
||||
puts(" channel 2: PCA9633_PWM_CHANNEL_2");
|
||||
puts(" channel 3: PCA9633_PWM_CHANNEL_3");
|
||||
}
|
||||
else {
|
||||
pca9633_ldr_state_t state;
|
||||
switch (atoi(argv[1])) {
|
||||
case 0:
|
||||
state = PCA9633_LDR_STATE_OFF;
|
||||
break;
|
||||
case 1:
|
||||
state = PCA9633_LDR_STATE_ON;
|
||||
break;
|
||||
case 2:
|
||||
state = PCA9633_LDR_STATE_IND;
|
||||
break;
|
||||
case 3:
|
||||
state = PCA9633_LDR_STATE_IND_GRP;
|
||||
break;
|
||||
default:
|
||||
puts("state needs to be one of [0-3]");
|
||||
puts(" state 0: PCA9633_LDR_STATE_OFF");
|
||||
puts(" state 1: PCA9633_LDR_STATE_ON");
|
||||
puts(" state 2: PCA9633_LDR_STATE_IND");
|
||||
puts(" state 3: PCA9633_LDR_STATE_IND_GRP");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pca9633_pwm_channel_t pwm_channel;
|
||||
switch (atoi(argv[2])) {
|
||||
case 0:
|
||||
pwm_channel = PCA9633_PWM_CHANNEL_0;
|
||||
break;
|
||||
case 1:
|
||||
pwm_channel = PCA9633_PWM_CHANNEL_1;
|
||||
break;
|
||||
case 2:
|
||||
pwm_channel = PCA9633_PWM_CHANNEL_2;
|
||||
break;
|
||||
case 3:
|
||||
pwm_channel = PCA9633_PWM_CHANNEL_3;
|
||||
break;
|
||||
default:
|
||||
puts("channel needs to be one of [0-3]");
|
||||
puts(" channel 0: PCA9633_PWM_CHANNEL_0");
|
||||
puts(" channel 1: PCA9633_PWM_CHANNEL_1");
|
||||
puts(" channel 2: PCA9633_PWM_CHANNEL_2");
|
||||
puts(" channel 3: PCA9633_PWM_CHANNEL_3");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pca9633_set_ldr_state(&pca9633_dev, state, pwm_channel);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ldr_state_all(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
puts("usage: ldr_state <state (0-3)>");
|
||||
|
||||
puts(" state 0: PCA9633_LDR_STATE_OFF");
|
||||
puts(" state 1: PCA9633_LDR_STATE_ON");
|
||||
puts(" state 2: PCA9633_LDR_STATE_IND");
|
||||
puts(" state 3: PCA9633_LDR_STATE_IND_GRP");
|
||||
}
|
||||
else {
|
||||
pca9633_ldr_state_t state;
|
||||
switch (atoi(argv[1])) {
|
||||
case 0:
|
||||
state = PCA9633_LDR_STATE_OFF;
|
||||
break;
|
||||
case 1:
|
||||
state = PCA9633_LDR_STATE_ON;
|
||||
break;
|
||||
case 2:
|
||||
state = PCA9633_LDR_STATE_IND;
|
||||
break;
|
||||
case 3:
|
||||
state = PCA9633_LDR_STATE_IND_GRP;
|
||||
break;
|
||||
default:
|
||||
puts("state needs to be one of [0-3]");
|
||||
puts(" state 0: PCA9633_LDR_STATE_OFF");
|
||||
puts(" state 1: PCA9633_LDR_STATE_ON");
|
||||
puts(" state 2: PCA9633_LDR_STATE_IND");
|
||||
puts(" state 3: PCA9633_LDR_STATE_IND_GRP");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pca9633_set_ldr_state_all(&pca9633_dev, state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int auto_inc(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
puts("usage: auto_inc <option (0-4)>");
|
||||
|
||||
puts(" option 0: PCA9633_AI_DISABLED");
|
||||
puts(" option 1: PCA9633_AI_ALL");
|
||||
puts(" option 2: PCA9633_AI_IND");
|
||||
puts(" option 3: PCA9633_AI_GBL");
|
||||
puts(" option 4: PCA9633_AI_IND_GBL");
|
||||
}
|
||||
else {
|
||||
pca9633_auto_inc_option_t option;
|
||||
switch (atoi(argv[1])) {
|
||||
case 0:
|
||||
option = PCA9633_AI_DISABLED;
|
||||
break;
|
||||
case 1:
|
||||
option = PCA9633_AI_ALL;
|
||||
break;
|
||||
case 2:
|
||||
option = PCA9633_AI_IND;
|
||||
break;
|
||||
case 3:
|
||||
option = PCA9633_AI_GBL;
|
||||
break;
|
||||
case 4:
|
||||
option = PCA9633_AI_IND_GBL;
|
||||
break;
|
||||
default:
|
||||
puts("option needs to be one of [0-4]");
|
||||
puts(" option 0: PCA9633_AI_DISABLED");
|
||||
puts(" option 1: PCA9633_AI_ALL");
|
||||
puts(" option 2: PCA9633_AI_IND");
|
||||
puts(" option 3: PCA9633_AI_GBL");
|
||||
puts(" option 4: PCA9633_AI_IND_GBL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pca9633_set_auto_increment(&pca9633_dev, option);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int grp_ctrl_mode(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
puts("usage: grp_ctrl_mode <mode (0-1)>");
|
||||
|
||||
puts(" mode 0: PCA9633_GROUP_CONTROL_MODE_BLINKING");
|
||||
puts(" mode 1: PCA9633_GROUP_CONTROL_MODE_DIMMING");
|
||||
}
|
||||
else {
|
||||
pca9633_group_control_mode_t mode;
|
||||
switch (atoi(argv[1])) {
|
||||
case 0:
|
||||
mode = PCA9633_GROUP_CONTROL_MODE_BLINKING;
|
||||
break;
|
||||
case 1:
|
||||
mode = PCA9633_GROUP_CONTROL_MODE_DIMMING;
|
||||
break;
|
||||
default:
|
||||
puts("mode needs to be one of [0-1]");
|
||||
puts(" mode 0: PCA9633_GROUP_CONTROL_MODE_BLINKING");
|
||||
puts(" mode 1: PCA9633_GROUP_CONTROL_MODE_DIMMING");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pca9633_set_group_control_mode(&pca9633_dev, mode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int run_demo(int argc, char **argv)
|
||||
{
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
puts("[DEMO START]");
|
||||
pca9633_set_ldr_state_all(&pca9633_dev, PCA9633_LDR_STATE_IND_GRP);
|
||||
pca9633_set_group_control_mode(&pca9633_dev,
|
||||
PCA9633_GROUP_CONTROL_MODE_DIMMING);
|
||||
pca9633_set_rgb(&pca9633_dev, 255, 255, 255);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
// 1. turn on/off
|
||||
puts("1. turn on/off");
|
||||
pca9633_turn_off(&pca9633_dev);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
pca9633_turn_on(&pca9633_dev);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
// 2. individual dimming (pca9633_set_rgb() uses pca9633_set_pwm() internally)
|
||||
puts("2. individual dimming");
|
||||
pca9633_set_rgb(&pca9633_dev, 255, 255, 255);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
pca9633_set_rgb(&pca9633_dev, 255, 0, 0);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
pca9633_set_rgb(&pca9633_dev, 0, 255, 0);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
pca9633_set_rgb(&pca9633_dev, 0, 0, 255);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
// 3. group dimming
|
||||
puts("3. group dimming");
|
||||
pca9633_set_rgb(&pca9633_dev, 255, 255, 255);
|
||||
pca9633_set_ldr_state_all(&pca9633_dev, PCA9633_LDR_STATE_IND_GRP);
|
||||
|
||||
for (int pwm = 255; pwm >= 0; pwm--) {
|
||||
pca9633_set_grp_pwm(&pca9633_dev, pwm);
|
||||
xtimer_usleep(20 * US_PER_MS);
|
||||
}
|
||||
xtimer_sleep(1);
|
||||
|
||||
// 4. changing ldr state
|
||||
puts("4. changing ldr state");
|
||||
pca9633_set_grp_pwm(&pca9633_dev, 255);
|
||||
pca9633_set_rgb(&pca9633_dev, 255, 255, 255);
|
||||
pca9633_set_ldr_state(&pca9633_dev, PCA9633_LDR_STATE_OFF, PCA9633_BIT_LDR1);
|
||||
// color should be magenta
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
pca9633_set_grp_pwm(&pca9633_dev, 0);
|
||||
pca9633_set_rgb(&pca9633_dev, 0, 0, 0);
|
||||
pca9633_set_ldr_state(&pca9633_dev, PCA9633_LDR_STATE_ON, PCA9633_BIT_LDR1);
|
||||
// color should be green
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
pca9633_set_grp_pwm(&pca9633_dev, 255);
|
||||
pca9633_set_rgb(&pca9633_dev, 255, 128, 0);
|
||||
pca9633_set_ldr_state(&pca9633_dev,PCA9633_LDR_STATE_IND, PCA9633_BIT_LDR1);
|
||||
// color should be orange
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
pca9633_set_grp_pwm(&pca9633_dev, 0);
|
||||
pca9633_set_rgb(&pca9633_dev, 255, 255, 255);
|
||||
pca9633_set_ldr_state(&pca9633_dev, PCA9633_LDR_STATE_IND_GRP, PCA9633_BIT_LDR1);
|
||||
// should be no color at all
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
// 5. test blinking
|
||||
puts("5. test blinking");
|
||||
pca9633_set_grp_pwm(&pca9633_dev, 255);
|
||||
pca9633_set_rgb(&pca9633_dev, 255, 255, 255);
|
||||
pca9633_set_group_control_mode(&pca9633_dev,
|
||||
PCA9633_GROUP_CONTROL_MODE_BLINKING);
|
||||
pca9633_set_blinking(&pca9633_dev,
|
||||
1000,
|
||||
PCA9633_BLINKING_RATIO_BALANCED);
|
||||
xtimer_sleep(10);
|
||||
pca9633_set_group_control_mode(&pca9633_dev,
|
||||
PCA9633_GROUP_CONTROL_MODE_DIMMING);
|
||||
|
||||
// 6. sleep mode
|
||||
puts("6. sleep mode");
|
||||
pca9633_set_rgb(&pca9633_dev, 0, 255, 255);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
pca9633_sleep(&pca9633_dev);
|
||||
xtimer_sleep(2);
|
||||
|
||||
pca9633_wakeup(&pca9633_dev);
|
||||
xtimer_usleep(500 * US_PER_MS);
|
||||
|
||||
puts("[DEMO END]");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const shell_command_t shell_commands[] = {
|
||||
{ "turn_on", "Turn on all LEDs.", turn_on },
|
||||
{ "turn_off", "Turn off all LEDs.", turn_off },
|
||||
{ "wakeup", "Switch to normal mode.", wakeup },
|
||||
{ "sleep", "Switch to low power mode.", sleep },
|
||||
{ "pwm", "Set individual PWM signal for a given channel.", pwm },
|
||||
{ "grp_pwm", "Set global PWM signal.", grp_pwm },
|
||||
{ "blinking", "Set up values for blinking mode.", blinking },
|
||||
{ "rgb", "Set PWM values for RGB.", rgb },
|
||||
{ "rgba", "Set PWM values for RGBA.", rgba },
|
||||
{ "ldr_state", "Set the LED driver output state for a given channel.", ldr_state },
|
||||
{ "ldr_state_all", "Set the LED driver output state for all channels.", ldr_state_all },
|
||||
{ "auto_increment", "Set an option for auto increment.", auto_inc },
|
||||
{ "grp_ctrl_mode", "Set the group control mode.", grp_ctrl_mode },
|
||||
{ "run_demo", "Demonstration of all functions.", run_demo },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
if (pca9633_init(&pca9633_dev, &pca9633_params[0]) != PCA9633_OK) {
|
||||
puts("Initialization failed!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char line_buf[SHELL_DEFAULT_BUFSIZE];
|
||||
shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user