Skip to content

Commit 0de6982

Browse files
authored
Merge pull request #1 from Davang/feature/gpioClass
esp gpio class
2 parents 1e8b6dd + 0065738 commit 0de6982

File tree

9 files changed

+409
-1
lines changed

9 files changed

+409
-1
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,9 @@
3030
*.exe
3131
*.out
3232
*.app
33+
34+
# build
35+
build/
36+
37+
# config
38+
sdkconfig*

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,27 @@
11
# esp-davang
2-
custom esp libraries
2+
3+
Custom classes to wrap around esp-idf. The main idea is not make it faster neither lighter but try to use `c++` features to ease future implementations.
4+
For example compile checking validity of peripherals configurations. Improve memory safety like using `std::string` instead of `char*`.
5+
6+
As with esp-idf an export script is given to ease its use. It exports two variables, `DAVANG_ESP` and `DAVANG_COMPONENT_DIRS`.
7+
8+
* `DAVANG_ESP` : the path to the esp-davang directory base of the repository.
9+
* `DAVANG_COMPONENT_DIRS` : the path to the components directory base of the.
10+
11+
I know writting a warp over an already HAL/BSP libary makes no sense, as for that reason you may use the existing one already.
12+
My classes remove some funciontality, will ad some overhead to the code, and not be as tested as esp-idf.
13+
So why did I do it? beacuase I do not use all the functionlay mos of the time, and run time errors are a pain in the ass.
14+
I used this classes for a few time, and they are helpfull to me, I hope they to you too.
15+
16+
## Components
17+
18+
This directory has all componets, each have a unique folder with _dvng_ as prefix this way they may nor result in conflict with any other component.
19+
Add `list(APPEND EXTRA_COMPONENT_DIRS "${DAVANG_COMPONENT_DIRS}")` to your project.
20+
21+
## Examples
22+
23+
Just what the name says it is, examples.
24+
25+
---
26+
27+
Davang

components/dvng_gpio/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
idf_component_register( SRCS "src/davang_gpio.cpp"
2+
INCLUDE_DIRS "inc"
3+
REQUIRES driver )
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*!
2+
* \file davang_gpio.hpp
3+
* \details GPIO abstraction class declaration for ESP-IDF.
4+
* \author Davang
5+
* \version 1.0.0
6+
* \date 2023/09/25
7+
* \copyright MIT License
8+
*/
9+
10+
#ifndef ESP_DAVANG_COMPONENTS_DVNG_GPIO_DAVANG_GPIO_H
11+
#define ESP_DAVANG_COMPONENTS_DVNG_GPIO_DAVANG_GPIO_H
12+
13+
/* C includes */
14+
#include <cstdint>
15+
16+
/* C++ includes */
17+
#include <utility>
18+
19+
/* 3rd party includes */
20+
#include "driver/gpio.h"
21+
#include "esp_err.h"
22+
23+
/* custom includes*/
24+
25+
26+
27+
/*! Specific davang namespace for gpio data types related. */
28+
namespace dvng::gpio
29+
{
30+
31+
/* data types */
32+
33+
using pin_t = uint32_t; /*! \brief data type representing */
34+
using isr_t = gpio_isr_t; /*! \brief data type representing */
35+
36+
/* isr_t functions are : static void IRAM_ATTR gpio_isr_handler(void* arg); */
37+
38+
/* enumerators */
39+
40+
enum class MODE : uint64_t
41+
{
42+
INPUT = GPIO_MODE_INPUT,
43+
OUTPUT = GPIO_MODE_OUTPUT,
44+
OUTPUT_OPEN_DRAIN = GPIO_MODE_OUTPUT_OD,
45+
TOTAL,
46+
};
47+
48+
49+
enum class PULL_UP : uint32_t
50+
{
51+
NONE = GPIO_PULLUP_DISABLE,
52+
ACTIVE = GPIO_PULLUP_ENABLE,
53+
TOTAL,
54+
};
55+
56+
enum class PULL_DOWN : uint32_t
57+
{
58+
NONE = GPIO_PULLDOWN_DISABLE,
59+
ACTIVE = GPIO_PULLDOWN_ENABLE,
60+
TOTAL,
61+
};
62+
63+
enum class GPIO_INTERRUPT : uint32_t
64+
{
65+
NONE = GPIO_INTR_DISABLE,
66+
RAISE = GPIO_INTR_POSEDGE,
67+
FALL = GPIO_INTR_NEGEDGE,
68+
EDGE = GPIO_INTR_ANYEDGE,
69+
TOTAL,
70+
};
71+
72+
enum class LEVEL : uint32_t
73+
{
74+
LOW = 0,
75+
HIGH = 1,
76+
};
77+
78+
/* constants */
79+
80+
/*!< Specific davang namespace for gpio data types related. */
81+
constexpr pin_t MAX_PIN = GPIO_PIN_COUNT;
82+
83+
/* asssertion structures */
84+
template< gpio::pin_t T_PIN, gpio::MODE T_MODE,
85+
gpio::PULL_UP T_PULL_UP = gpio::PULL_UP::NONE,
86+
gpio::PULL_DOWN T_PULL_DOWN = gpio::PULL_DOWN::NONE,
87+
gpio::GPIO_INTERRUPT T_INTERRUPT = gpio::GPIO_INTERRUPT::NONE >
88+
struct s_asserter
89+
{
90+
91+
static constexpr uint64_t OUTPUT_MASK = SOC_GPIO_VALID_OUTPUT_GPIO_MASK;
92+
static constexpr uint64_t GPIO_MASK = SOC_GPIO_VALID_GPIO_MASK;
93+
94+
static constexpr bool IS_OUTPUT_SUPPORTED = ( 0 != ( ( 1ULL << T_PIN ) & OUTPUT_MASK ) );
95+
static constexpr bool IS_MODE_OUTPUT = ( T_MODE == gpio::MODE::OUTPUT );
96+
static constexpr bool IS_MODE_INPUT = ( T_MODE == gpio::MODE::INPUT );
97+
98+
static_assert( ( ( 0 <= T_PIN ) && ( 0 != ( ( 1ULL << T_PIN) & GPIO_MASK ) ) ), "Not a valid gpio pin number, gpio pin should be less than dvng::gpio::MAX_PIN" );
99+
100+
static_assert( ( T_MODE < gpio::MODE::TOTAL ), "Gpio mode not supported" );
101+
102+
static_assert( ( true == IS_MODE_INPUT ) || ( ( true == IS_MODE_OUTPUT ) && ( true == IS_OUTPUT_SUPPORTED ) ) , "Output mode not supported, this pin may only be an input" );
103+
104+
static_assert( ( T_MODE < gpio::MODE::TOTAL ), "Gpio mode not supported" );
105+
static_assert( ( T_PULL_UP < gpio::PULL_UP::TOTAL ), "Gpio pull up not supported" );
106+
static_assert( ( T_PULL_DOWN < gpio::PULL_DOWN::TOTAL ), "Gpio pulldown not supported" );
107+
static_assert( ( T_INTERRUPT < gpio::GPIO_INTERRUPT::TOTAL ), "Gpio interrupt not supported" );
108+
109+
110+
111+
};
112+
113+
114+
} /* namespace dvng::gpio */
115+
116+
/*!< Generic davang namespace */
117+
namespace dvng
118+
{
119+
120+
121+
class c_gpio
122+
{
123+
/* constants */
124+
private:
125+
const gpio_config_t m_gpio_config;
126+
127+
/* data members */
128+
private:
129+
gpio::LEVEL m_level;
130+
gpio::pin_t m_pin;
131+
const gpio::MODE m_mode;
132+
const gpio::GPIO_INTERRUPT m_interrupt;
133+
134+
/* constructors and destructor */
135+
public:
136+
137+
c_gpio( ) = delete;
138+
139+
c_gpio( const c_gpio & ) = delete;
140+
141+
c_gpio( const c_gpio && ) = delete;
142+
143+
/*!
144+
* \ brief c_gpio constructor
145+
*/
146+
template< gpio::pin_t T_PIN, gpio::MODE T_MODE,
147+
gpio::PULL_UP T_PULL_UP = gpio::PULL_UP::NONE,
148+
gpio::PULL_DOWN T_PULL_DOWN = gpio::PULL_DOWN::NONE,
149+
gpio::GPIO_INTERRUPT T_INTERRUPT = gpio::GPIO_INTERRUPT::NONE >
150+
c_gpio( const gpio::s_asserter< T_PIN, T_MODE, T_PULL_UP, T_PULL_DOWN, T_INTERRUPT > ) : m_gpio_config ( /* pin_bit_mask */ 1ULL << T_PIN,
151+
/* mode */ static_cast< gpio_mode_t >( T_MODE ),
152+
/* pull_up_en */ static_cast< gpio_pullup_t >( T_PULL_UP ),
153+
/* pull_down_en */ static_cast< gpio_pulldown_t >( T_PULL_DOWN ),
154+
/* intr_type */ static_cast< gpio_int_type_t >( T_INTERRUPT ) ),
155+
m_level ( gpio::LEVEL::LOW ),
156+
m_pin ( T_PIN ),
157+
m_mode ( T_MODE ),
158+
m_interrupt ( T_INTERRUPT )
159+
{
160+
161+
}
162+
163+
164+
virtual ~c_gpio( );
165+
166+
167+
/* methods */
168+
public:
169+
170+
[[nodiscard("Always ensure valid pin initialization")]]
171+
int init( );
172+
173+
int deinit( );
174+
175+
[[nodiscard("Why get the level of a pin if not using it?")]]
176+
gpio::LEVEL get_level( );
177+
178+
int set_level( const gpio::LEVEL & t_level );
179+
180+
int set_high( ) ;
181+
182+
int set_low( );
183+
184+
int toggle( );
185+
186+
[[nodiscard("Always ensure correct isr registration ")]]
187+
int register_isr( gpio::isr_t t_isr, void * t_arguments );
188+
189+
190+
};
191+
192+
193+
} /* namespace dvng */
194+
195+
#endif /* ESP_DAVANG_COMPONENTS_DVNG_GPIO_DAVANG_GPIO_H */
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*!
2+
* \file davang_gpio.cpp
3+
* \details GPIO abstraction class declaration for ESP-IDF, adds c++ checks at compile time.
4+
* \author Davang
5+
* \version 1.0.0
6+
* \date 09/06/2024
7+
* \copyright MIT License
8+
*/
9+
10+
/* custom includes*/
11+
#include "davang_gpio.hpp"
12+
13+
14+
namespace dvng
15+
{
16+
17+
c_gpio::~c_gpio( )
18+
{
19+
// do nothing you are responsible of deinitialize the pin
20+
}
21+
22+
int c_gpio::deinit( )
23+
{
24+
return gpio_reset_pin( static_cast< gpio_num_t >( m_pin ) );
25+
}
26+
27+
int c_gpio::init( )
28+
{
29+
return gpio_config( &m_gpio_config );
30+
}
31+
32+
gpio::LEVEL c_gpio::get_level( )
33+
{
34+
return static_cast< gpio::LEVEL >( gpio_get_level( static_cast< gpio_num_t >( m_pin ) ) );
35+
}
36+
37+
int c_gpio::set_level( const gpio::LEVEL & t_level )
38+
{
39+
int error = ESP_OK;
40+
41+
if ( gpio::MODE::OUTPUT == m_mode )
42+
{
43+
error = gpio_set_level( static_cast< gpio_num_t >( m_pin ), std::to_underlying( m_level ) );
44+
if( ESP_OK == error )
45+
{
46+
m_level = t_level;
47+
}
48+
}
49+
else
50+
{
51+
error = ESP_ERR_NOT_SUPPORTED;
52+
}
53+
54+
return error;
55+
}
56+
57+
int c_gpio::set_high( )
58+
{
59+
return set_level( gpio::LEVEL::HIGH );
60+
}
61+
62+
int c_gpio::set_low( )
63+
{
64+
return set_level( gpio::LEVEL::LOW );
65+
}
66+
67+
int c_gpio::toggle( )
68+
{
69+
if( gpio::LEVEL::LOW == m_level )
70+
{
71+
return set_high( );
72+
}
73+
else
74+
{
75+
return set_low( );
76+
}
77+
}
78+
79+
int c_gpio::register_isr( gpio::isr_t t_isr, void * t_arguments )
80+
{
81+
if ( gpio::GPIO_INTERRUPT::NONE == m_interrupt )
82+
{
83+
return ESP_ERR_NOT_SUPPORTED;
84+
}
85+
else
86+
{
87+
esp_err_t error = gpio_set_intr_type(static_cast< gpio_num_t >( m_pin ), static_cast< gpio_int_type_t >( m_interrupt ));
88+
89+
if( ESP_OK == error )
90+
{
91+
error = gpio_install_isr_service( ESP_INTR_FLAG_EDGE | ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LOWMED );
92+
}
93+
94+
if( ESP_OK == error )
95+
{
96+
error = gpio_isr_handler_add( static_cast< gpio_num_t >( m_pin ), t_isr, t_arguments );
97+
}
98+
99+
if( ESP_OK != error )
100+
{
101+
error = gpio_isr_handler_remove( static_cast< gpio_num_t >( m_pin ) );
102+
gpio_uninstall_isr_service( );
103+
}
104+
105+
106+
return error;
107+
}
108+
}
109+
110+
}

examples/dvng_gpio/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
cmake_minimum_required(VERSION 3.16)
2+
3+
set(EXTRA_COMPONENT_DIRS $ENV{DAVANG_COMPONENT_DIRS})
4+
5+
set(COMPONENTS main)
6+
7+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
8+
9+
project( davang_blink )
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
idf_component_register(SRCS "davang_blink.cpp"
2+
INCLUDE_DIRS "."
3+
REQUIRES dvng_gpio freertos )

0 commit comments

Comments
 (0)