Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace gpio {
- template< unsigned int port, unsigned int... pins >
- struct port_pins
- {};
- using uint32 = unsigned int;
- struct pin_settings {
- constexpr pin_settings( uint32 mode_, bool hmode_, uint32 type_, bool htype_, uint32 speed_, bool hspeed_, uint32 resis_, bool hresis_ )
- : mode(mode_), has_mode(hmode_), output_type(type_), has_output_type(htype_), output_speed(speed_), has_output_speed(hspeed_), resistors(resis_), has_resistors(hresis_)
- {}
- const uint32 mode = 0;
- const bool has_mode = false;
- const uint32 output_type = 0;
- const bool has_output_type = false;
- const uint32 output_speed = 0;
- const bool has_output_speed = false;
- const uint32 resistors = 0;
- const bool has_resistors = false;
- };
- constexpr pin_settings operator|( const pin_settings& a, const pin_settings& b )
- {
- return { a.mode | b.mode, a.has_mode || b.has_mode,
- a.output_type | b.output_type, a.has_output_type || b.has_output_type,
- a.output_speed | b.output_speed, a.has_output_speed || b.has_output_speed,
- a.resistors | b.resistors, a.has_resistors || b.has_resistors };
- }
- // mode
- struct input : public pin_settings {
- constexpr input() : pin_settings(0, true, 0, false, 0, false, 0, false) {}
- };
- struct output : public pin_settings {
- constexpr output() : pin_settings(1, true, 0, false, 0, false, 0, false ) {}
- };
- struct alternate : public pin_settings {
- constexpr alternate() : pin_settings(2, true, 0, false, 0, false, 0, false ) {}
- };
- struct analog : public pin_settings {
- constexpr analog() : pin_settings(3, true, 0, false, 0, false, 0, false ) {}
- };
- // output type
- struct push_pull : public pin_settings {
- constexpr push_pull() : pin_settings(0, false, 0, true, 0, false, 0, false ) {}
- };
- struct open_drain : public pin_settings {
- constexpr open_drain() : pin_settings(0, false, 1, true, 0, false, 0, false ) {}
- };
- // output_speed
- struct low_speed : public pin_settings {
- constexpr low_speed() : pin_settings(0, false, 0, false, 0, true, 0, false ) {}
- };
- struct medium_speed : public pin_settings {
- constexpr medium_speed() : pin_settings(0, false, 0, false, 1, true, 0, false ) {}
- };
- struct fast_speed : public pin_settings {
- constexpr fast_speed() : pin_settings(0, false, 0, false, 2, true, 0, false ) {}
- };
- struct high_speed : public pin_settings {
- constexpr high_speed() : pin_settings(0, false, 0, false, 3, true, 0, false ) {}
- };
- // resistor
- struct pull_up : public pin_settings {
- constexpr pull_up() : pin_settings(0, false, 0, false, 0, false, 1, true ) {}
- };
- struct pull_down : public pin_settings {
- constexpr pull_down() : pin_settings(0, false, 0, false, 0, false, 2, true ) {}
- };
- template< unsigned int value_in, unsigned int... pins >
- struct replicate_static;
- template< unsigned int value_in, unsigned int pin0, unsigned int... pins >
- struct replicate_static< value_in, pin0, pins... > {
- static const unsigned int value = value_in << pin0 | replicate_static< value_in, pins... >::value;
- };
- template< unsigned int stride, unsigned int... pins >
- struct replicate_dynamic;
- template< unsigned int stride, unsigned int pin0, unsigned int... pins >
- struct replicate_dynamic< stride, pin0, pins... >
- {
- static unsigned int exec( unsigned int value ) {
- return replicate_dynamic<stride, pins...>::exec(value) | (value << (pin0*stride));
- }
- };
- template< unsigned int stride >
- struct replicate_dynamic< stride >
- {
- static unsigned int exec( unsigned int value ) {
- (void) value;
- return 0;
- }
- };
- template< typename... port_pin_list >
- struct configure_struct;
- template< unsigned int port, unsigned int... pins, typename... remainder >
- struct configure_struct< port_pins< port, pins... >, remainder... >
- {
- static void configure( const pin_settings& settings )
- {
- volatile char* const port_base = reinterpret_cast<volatile char*>(0x40020000) + port * 0x400;
- if( settings.has_mode ) {
- volatile uint32* const mode = reinterpret_cast<volatile uint32*>(port_base + 0x00);
- *mode = replicate_dynamic<2, pins...>::exec(settings.mode);
- }
- if(settings.has_output_type) {
- volatile uint32* const output_type = reinterpret_cast<volatile uint32*>(port_base + 0x04);
- *output_type = replicate_dynamic<1, pins...>::exec(settings.output_type);
- }
- if(settings.has_output_speed) {
- volatile uint32* const output_speed = reinterpret_cast<volatile uint32*>(port_base + 0x08);
- *output_speed = replicate_dynamic<2, pins...>::exec(settings.output_speed);
- }
- if(settings.has_resistors) {
- volatile uint32* const resistors = reinterpret_cast<volatile uint32*>(port_base + 0x0c);
- *resistors = replicate_dynamic<2, pins...>::exec(settings.resistors);
- }
- configure_struct< remainder... >::configure( settings );
- }
- };
- template< >
- struct configure_struct< >
- {
- static void configure( const pin_settings& settings )
- {
- (void) settings;
- }
- };
- template< typename... port_pin_list >
- void configure( const pin_settings& settings )
- {
- configure_struct< port_pin_list... >::configure( settings );
- }
- template< unsigned int... pins >
- using pins_a = port_pins< 0, pins... >;
- template< unsigned int... pins >
- using pins_b = port_pins< 1, pins... >;
- template< unsigned int... pins >
- using pins_c = port_pins< 2, pins... >;
- }
- void playground_main()
- {
- gpio::configure< gpio::pins_a< 2, 3, 4, 5 >, gpio::pins_b< 5, 6, 7 > >( gpio::pull_up() | gpio::high_speed() | gpio::output() );
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement