Skip to content

Commit

Permalink
Merge pull request #212 from aabadie/drv_rgbled_pwm
Browse files Browse the repository at this point in the history
drv: add library to support rgbled via 3 pwm pins
  • Loading branch information
aabadie authored Sep 6, 2023
2 parents f0f9853 + e25fea1 commit ff73d86
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 34 deletions.
12 changes: 12 additions & 0 deletions bsp/conf/dotbot_v2_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,16 @@
#define DB_LIS2MDL_INT_PIN DB_DEBUG3_PIN
/** @} */

/**
* @name RGB LED pwm pins definitions
* @{
*/
#define DB_RGB_LED_PWM_RED_PORT 1
#define DB_RGB_LED_PWM_RED_PIN 7
#define DB_RGB_LED_PWM_GREEN_PORT 0
#define DB_RGB_LED_PWM_GREEN_PIN 10
#define DB_RGB_LED_PWM_BLUE_PORT 1
#define DB_RGB_LED_PWM_BLUE_PIN 6
/** @} */

#endif
12 changes: 12 additions & 0 deletions bsp/conf/nrf52833dk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,16 @@
#define DB_LIS2MDL_INT_PIN DB_DEBUG3_PIN
/** @} */

/**
* @name RGB LED pwm pins definitions
* @{
*/
#define DB_RGB_LED_PWM_RED_PORT DB_DEBUG1_PORT
#define DB_RGB_LED_PWM_RED_PIN DB_DEBUG1_PIN
#define DB_RGB_LED_PWM_GREEN_PORT DB_DEBUG2_PORT
#define DB_RGB_LED_PWM_GREEN_PIN DB_DEBUG2_PIN
#define DB_RGB_LED_PWM_BLUE_PORT DB_DEBUG3_PORT
#define DB_RGB_LED_PWM_BLUE_PIN DB_DEBUG3_PIN
/** @} */

#endif
12 changes: 12 additions & 0 deletions bsp/conf/nrf52840dk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,16 @@
#define DB_LIS2MDL_INT_PIN DB_DEBUG3_PIN
/** @} */

/**
* @name RGB LED pwm pins definitions
* @{
*/
#define DB_RGB_LED_PWM_RED_PORT DB_DEBUG1_PORT
#define DB_RGB_LED_PWM_RED_PIN DB_DEBUG1_PIN
#define DB_RGB_LED_PWM_GREEN_PORT DB_DEBUG2_PORT
#define DB_RGB_LED_PWM_GREEN_PIN DB_DEBUG2_PIN
#define DB_RGB_LED_PWM_BLUE_PORT DB_DEBUG3_PORT
#define DB_RGB_LED_PWM_BLUE_PIN DB_DEBUG3_PIN
/** @} */

#endif
12 changes: 12 additions & 0 deletions bsp/conf/nrf5340dk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,16 @@
#define DB_LIS2MDL_INT_PIN DB_DEBUG3_PIN
/** @} */

/**
* @name RGB LED pwm pins definitions
* @{
*/
#define DB_RGB_LED_PWM_RED_PORT DB_DEBUG1_PORT
#define DB_RGB_LED_PWM_RED_PIN DB_DEBUG1_PIN
#define DB_RGB_LED_PWM_GREEN_PORT DB_DEBUG2_PORT
#define DB_RGB_LED_PWM_GREEN_PIN DB_DEBUG2_PIN
#define DB_RGB_LED_PWM_BLUE_PORT DB_DEBUG3_PORT
#define DB_RGB_LED_PWM_BLUE_PIN DB_DEBUG3_PIN
/** @} */

#endif
4 changes: 2 additions & 2 deletions bsp/nrf/motors.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
//=========================== public ==========================================

void db_motors_init(void) {
db_pwm_init(db_motors_pins, PWM_CHANNELS, M_TOP);
db_pwm_init(0, db_motors_pins, PWM_CHANNELS, M_TOP);
}

void db_motors_set_speed(int16_t l_speed, int16_t r_speed) {
Expand Down Expand Up @@ -74,5 +74,5 @@ void db_motors_set_speed(int16_t l_speed, int16_t r_speed) {
}

// Update PWM values
db_pwm_channels_set(pwm_seq);
db_pwm_channels_set(0, pwm_seq);
}
59 changes: 34 additions & 25 deletions bsp/nrf/pwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,13 @@
#include <stdlib.h>
#include <string.h>
#include <nrf.h>
#include <nrf_peripherals.h>

#include "gpio.h"
#include "pwm.h"

//=========================== defines ==========================================

#if defined(NRF5340_XXAA) && defined(NRF_APPLICATION)
#define DB_PWM (NRF_PWM0_S)
#else
#define DB_PWM (NRF_PWM0)
#endif
#define DB_PWM_MAX_CHANNELS (4)

// Variable that stores the PWM duty cycle for all four PWM channels
Expand All @@ -35,43 +31,56 @@ typedef struct {

//=========================== variables ========================================

static NRF_PWM_Type *_pwm_devs[PWM_COUNT] = {
#if defined(NRF5340_XXAA) && defined(NRF_APPLICATION)
NRF_PWM0_S,
NRF_PWM1_S,
NRF_PWM2_S,
NRF_PWM3_S,
#else
NRF_PWM0,
NRF_PWM1,
NRF_PWM2,
NRF_PWM3,
#endif
};
static pwm_vars_t pwm_vars;

//=========================== public ===========================================

void db_pwm_init(const gpio_t *pins, size_t num_channels, uint16_t mtop) {
void db_pwm_init(pwm_t pwm, const gpio_t *pins, size_t num_channels, uint16_t mtop) {

// configure PWM channel pins;
for (uint8_t channel = 0; channel < num_channels; channel++) {
// Configure the PWM pins as output.
db_gpio_init(&pins[channel], DB_GPIO_OUT);
DB_PWM->PSEL.OUT[channel] = (pins[channel].port << PWM_PSEL_OUT_PORT_Pos) |
(pins[channel].pin << PWM_PSEL_OUT_PIN_Pos) |
(PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos);
_pwm_devs[pwm]->PSEL.OUT[channel] = (pins[channel].port << PWM_PSEL_OUT_PORT_Pos) |
(pins[channel].pin << PWM_PSEL_OUT_PIN_Pos) |
(PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos);
}

// Enable the PWM peripheral
DB_PWM->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
_pwm_devs[pwm]->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);

// Configure PWM frequency and counting mode
DB_PWM->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_16; // 1MHz clock
DB_PWM->COUNTERTOP = mtop; // for example 100us period for the PWM signal means 10kHz
DB_PWM->MODE = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos); // UP counting mode
DB_PWM->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos); // Disable single sequence looping feature
_pwm_devs[pwm]->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_16; // 1MHz clock
_pwm_devs[pwm]->COUNTERTOP = mtop; // for example 100us period for the PWM signal means 10kHz
_pwm_devs[pwm]->MODE = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos); // UP counting mode
_pwm_devs[pwm]->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos); // Disable single sequence looping feature

// Configure how many, and how the PWM dutycycles are loaded from memory
DB_PWM->DECODER = (PWM_DECODER_LOAD_Individual << PWM_DECODER_LOAD_Pos) | // Have a different duty cycle value for each channel.
(PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos); // Reload the duty cycle values after every period, no delay
_pwm_devs[pwm]->DECODER = (PWM_DECODER_LOAD_Individual << PWM_DECODER_LOAD_Pos) | // Have a different duty cycle value for each channel.
(PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos); // Reload the duty cycle values after every period, no delay

// Configure the EasyDMA variables for loading the duty cycle values.
DB_PWM->SEQ[0].PTR = ((uint32_t)(pwm_vars.seq) << PWM_SEQ_PTR_PTR_Pos);
DB_PWM->SEQ[0].CNT = (DB_PWM_MAX_CHANNELS << PWM_SEQ_CNT_CNT_Pos);
_pwm_devs[pwm]->SEQ[0].PTR = ((uint32_t)(pwm_vars.seq) << PWM_SEQ_PTR_PTR_Pos);
_pwm_devs[pwm]->SEQ[0].CNT = (DB_PWM_MAX_CHANNELS << PWM_SEQ_CNT_CNT_Pos);

DB_PWM->SEQ[0].REFRESH = 0UL;
DB_PWM->SEQ[0].ENDDELAY = 0UL;
_pwm_devs[pwm]->SEQ[0].REFRESH = 0UL;
_pwm_devs[pwm]->SEQ[0].ENDDELAY = 0UL;

// Activate the automatic looping of the PWM duty cycle sequence.
DB_PWM->SHORTS = (PWM_SHORTS_LOOPSDONE_SEQSTART0_Enabled << PWM_SHORTS_LOOPSDONE_SEQSTART0_Pos);
_pwm_devs[pwm]->SHORTS = (PWM_SHORTS_LOOPSDONE_SEQSTART0_Enabled << PWM_SHORTS_LOOPSDONE_SEQSTART0_Pos);

// For safety, initialize all PWMs to zero.
for (uint8_t channel = 0; channel < DB_PWM_MAX_CHANNELS; channel++) {
Expand All @@ -81,20 +90,20 @@ void db_pwm_init(const gpio_t *pins, size_t num_channels, uint16_t mtop) {
}
}

void db_pwm_channel_set(uint8_t channel, uint16_t value) {
void db_pwm_channel_set(pwm_t pwm, uint8_t channel, uint16_t value) {
assert(channel < DB_PWM_MAX_CHANNELS);

pwm_vars.seq[channel] = value | 1 << 15;
// Update PWM values
DB_PWM->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger;
_pwm_devs[pwm]->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger;
}

void db_pwm_channels_set(uint16_t *values) {
void db_pwm_channels_set(pwm_t pwm, uint16_t *values) {
assert(sizeof(values) == DB_PWM_MAX_CHANNELS);

for (uint8_t channel = 0; channel < DB_PWM_MAX_CHANNELS; channel++) {
pwm_vars.seq[channel] = values[channel] | 1 << 15;
}
// Update PWM values
DB_PWM->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger;
_pwm_devs[pwm]->TASKS_SEQSTART[0] = PWM_TASKS_SEQSTART_TASKS_SEQSTART_Trigger;
}
14 changes: 11 additions & 3 deletions bsp/pwm.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
#include <stdint.h>
#include <stdlib.h>
#include "gpio.h"
#include "nrf.h"

//=========================== defines ==========================================

typedef uint8_t pwm_t;

//=========================== public ===========================================

Expand All @@ -27,29 +32,32 @@
* The number of channels must not exceed the size of the array containing
* the pins.
*
* @param[in] pwm index of the PWM peripheral to initialize
* @param[in] pins pointer to array of pointer to GPIO pins
* @param[in] num_channels number of channels to configure
* @param[in] mtop max value of the PWM counter register
*/
void db_pwm_init(const gpio_t *pins, size_t num_channels, uint16_t mtop);
void db_pwm_init(pwm_t pwm, const gpio_t *pins, size_t num_channels, uint16_t mtop);

/**
* @brief Set the value of a PWM channel
*
* The channel value must be lower or equal to 3.
*
* @param[in] pwm index of the PWM peripheral
* @param[in] channel index of channel to set
* @param[in] value value to set to the channel
*/
void db_pwm_channel_set(uint8_t channel, uint16_t value);
void db_pwm_channel_set(pwm_t pwm, uint8_t channel, uint16_t value);

/**
* @brief Set the values of all PWM channels
*
* The array of values must be 4 bytes long exactly.
*
* @param[in] pwm index of the PWM peripheral
* @param[in] values pointer to the array containing the values to set
*/
void db_pwm_channels_set(uint16_t *values);
void db_pwm_channels_set(pwm_t pwm, uint16_t *values);

#endif
9 changes: 9 additions & 0 deletions drv/drv.emProject
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,13 @@
<file file_name="pid/pid.c" />
<file file_name="pid.h" />
</project>
<project Name="00drv_rgbled_pwm">
<configuration
Name="Common"
project_dependencies="00bsp_pwm(bsp)"
project_directory="rgbled_pwm"
project_type="Library" />
<file file_name="rgbled_pwm.c" />
<file file_name="../rgbled_pwm.h" />
</project>
</solution>
43 changes: 43 additions & 0 deletions drv/rgbled_pwm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#ifndef __RGBLED_PWM_H
#define __RGBLED_PWM_H

/**
* @file rgbled_pwm.h
* @addtogroup DRV
*
* @brief Cross-platform declaration "rgbled pwm" driver module.
*
* @author Alexandre Abadie <[email protected]>
*
* @copyright Inria, 2023
*/

#include <stdlib.h>
#include <stdint.h>

#include "gpio.h"
#include "pwm.h"

//=========================== definitions ======================================

typedef struct {
const gpio_t pins[3]; // red: 0, green: 1, blue: 2
} db_rgbled_pwm_conf_t;

//=========================== public ===========================================

/**
* @brief Initialize the RGB LED pins
*
* @param[in] conf Configuration for the RGB LED pins
*/
void db_rgbled_pwm_init(const db_rgbled_pwm_conf_t *conf);

/**
* @brief Set the color of the RGB LED
*
* @param[output] payload Decoded payload contained in the input buffer
*/
void db_rgbled_pwm_set_color(uint8_t red, uint8_t green, uint8_t blue);

#endif
33 changes: 33 additions & 0 deletions drv/rgbled_pwm/rgbled_pwm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @file rgbled_pwm.c
* @addtogroup DRV
*
* @brief Implementation of the "rgbled pwm" driver module.
*
* @author Alexandre Abadie <[email protected]>
*
* @copyright Inria, 2023
*/

#include <stdbool.h>
#include <stdint.h>
#include <string.h>

#include "rgbled_pwm.h"
#include "pwm.h"

//=========================== definitions ======================================

#define PWM_CHANNELS (3)
#define PWM_MAX_VALUE (UINT8_MAX)

//=========================== public ===========================================

void db_rgbled_pwm_init(const db_rgbled_pwm_conf_t *conf) {
db_pwm_init(1, conf->pins, PWM_CHANNELS, PWM_MAX_VALUE);
}

void db_rgbled_pwm_set_color(uint8_t red, uint8_t green, uint8_t blue) {
uint16_t pwm_seq[PWM_CHANNELS] = { red, green, blue };
db_pwm_channels_set(1, pwm_seq);
}
Loading

0 comments on commit ff73d86

Please sign in to comment.