Advertisement
Guest User

Untitled

a guest
Nov 18th, 2014
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.53 KB | None | 0 0
  1.  
  2.  
  3. namespace gpio {
  4.  
  5.     template< unsigned int port, unsigned int... pins >
  6.     struct port_pins
  7.     {};
  8.  
  9.     using uint32 = unsigned int;
  10.  
  11.     struct pin_settings {
  12.  
  13.         constexpr pin_settings( uint32 mode_, bool hmode_, uint32 type_, bool htype_, uint32 speed_, bool hspeed_, uint32 resis_, bool hresis_ )
  14.             : mode(mode_), has_mode(hmode_), output_type(type_), has_output_type(htype_), output_speed(speed_), has_output_speed(hspeed_), resistors(resis_), has_resistors(hresis_)
  15.         {}
  16.  
  17.         const uint32 mode = 0;
  18.         const bool has_mode = false;
  19.  
  20.         const uint32 output_type = 0;
  21.         const bool has_output_type = false;
  22.  
  23.         const uint32 output_speed = 0;
  24.         const bool has_output_speed = false;
  25.  
  26.         const uint32 resistors = 0;
  27.         const bool has_resistors = false;
  28.     };
  29.  
  30.     constexpr pin_settings operator|( const pin_settings& a, const pin_settings& b )
  31.     {
  32.         return { a.mode | b.mode, a.has_mode || b.has_mode,
  33.                  a.output_type | b.output_type, a.has_output_type || b.has_output_type,
  34.                  a.output_speed | b.output_speed, a.has_output_speed || b.has_output_speed,
  35.                  a.resistors | b.resistors, a.has_resistors || b.has_resistors };
  36.     }
  37.  
  38.     // mode
  39.     struct input : public pin_settings {
  40.         constexpr input() : pin_settings(0, true, 0, false, 0, false, 0, false) {}
  41.     };
  42.  
  43.     struct output : public pin_settings {
  44.         constexpr output() : pin_settings(1, true, 0, false, 0, false, 0, false ) {}
  45.     };
  46.  
  47.     struct alternate : public pin_settings {
  48.         constexpr alternate() : pin_settings(2, true, 0, false, 0, false, 0, false ) {}
  49.     };
  50.  
  51.     struct analog : public pin_settings {
  52.         constexpr analog() : pin_settings(3, true, 0, false, 0, false, 0, false ) {}
  53.     };
  54.  
  55.     // output type
  56.     struct push_pull : public pin_settings {
  57.         constexpr push_pull() : pin_settings(0, false, 0, true, 0, false, 0, false ) {}
  58.     };
  59.  
  60.     struct open_drain : public pin_settings {
  61.         constexpr open_drain() : pin_settings(0, false, 1, true, 0, false, 0, false ) {}
  62.     };
  63.  
  64.     // output_speed
  65.     struct low_speed : public pin_settings {
  66.         constexpr low_speed() : pin_settings(0, false, 0, false, 0, true, 0, false ) {}
  67.     };
  68.  
  69.     struct medium_speed : public pin_settings {
  70.         constexpr medium_speed() : pin_settings(0, false, 0, false, 1, true, 0, false ) {}
  71.     };
  72.  
  73.     struct fast_speed : public pin_settings {
  74.         constexpr fast_speed() : pin_settings(0, false, 0, false, 2, true, 0, false ) {}
  75.     };
  76.  
  77.     struct high_speed : public pin_settings {
  78.         constexpr high_speed() : pin_settings(0, false, 0, false, 3, true, 0, false ) {}
  79.     };
  80.  
  81.     // resistor
  82.     struct pull_up : public pin_settings {
  83.         constexpr pull_up() : pin_settings(0, false, 0, false, 0, false, 1, true ) {}
  84.     };
  85.  
  86.     struct pull_down : public pin_settings {
  87.         constexpr pull_down() : pin_settings(0, false, 0, false, 0, false, 2, true ) {}
  88.     };
  89.  
  90.     template< unsigned int value_in, unsigned int... pins >
  91.     struct replicate_static;
  92.  
  93.     template< unsigned int value_in, unsigned int pin0, unsigned int... pins >
  94.     struct replicate_static< value_in, pin0, pins... > {
  95.         static const unsigned int value = value_in << pin0 | replicate_static< value_in, pins... >::value;
  96.     };
  97.  
  98.     template< unsigned int stride, unsigned int... pins >
  99.     struct replicate_dynamic;
  100.  
  101.     template< unsigned int stride, unsigned int pin0, unsigned int... pins >
  102.     struct replicate_dynamic< stride, pin0, pins... >
  103.     {
  104.         static unsigned int exec( unsigned int value ) {
  105.             return replicate_dynamic<stride, pins...>::exec(value) | (value << (pin0*stride));
  106.         }
  107.     };
  108.  
  109.     template< unsigned int stride >
  110.     struct replicate_dynamic< stride >
  111.     {
  112.         static unsigned int exec( unsigned int value ) {
  113.             (void) value;
  114.             return 0;
  115.         }
  116.     };
  117.  
  118.     template< typename... port_pin_list >
  119.     struct configure_struct;
  120.  
  121.     template< unsigned int port, unsigned int... pins, typename... remainder >
  122.     struct configure_struct< port_pins< port, pins... >, remainder... >
  123.     {
  124.         static void configure( const pin_settings& settings )
  125.         {
  126.             volatile char* const port_base = reinterpret_cast<volatile char*>(0x40020000) + port * 0x400;
  127.  
  128.             if( settings.has_mode ) {
  129.                 volatile uint32* const mode = reinterpret_cast<volatile uint32*>(port_base + 0x00);
  130.                 *mode = replicate_dynamic<2, pins...>::exec(settings.mode);
  131.             }
  132.  
  133.             if(settings.has_output_type) {
  134.                 volatile uint32* const output_type = reinterpret_cast<volatile uint32*>(port_base + 0x04);
  135.                 *output_type = replicate_dynamic<1, pins...>::exec(settings.output_type);
  136.             }
  137.  
  138.             if(settings.has_output_speed) {
  139.                 volatile uint32* const output_speed = reinterpret_cast<volatile uint32*>(port_base + 0x08);
  140.                 *output_speed = replicate_dynamic<2, pins...>::exec(settings.output_speed);
  141.             }
  142.  
  143.             if(settings.has_resistors) {
  144.                 volatile uint32* const resistors = reinterpret_cast<volatile uint32*>(port_base + 0x0c);
  145.                 *resistors = replicate_dynamic<2, pins...>::exec(settings.resistors);
  146.             }
  147.  
  148.             configure_struct< remainder... >::configure( settings );
  149.         }
  150.     };
  151.  
  152.     template< >
  153.     struct configure_struct< >
  154.     {
  155.         static void configure( const pin_settings& settings )
  156.         {
  157.             (void) settings;
  158.         }
  159.     };
  160.  
  161.     template< typename... port_pin_list >
  162.     void configure( const pin_settings& settings )
  163.     {
  164.         configure_struct< port_pin_list... >::configure( settings );
  165.     }
  166.  
  167.     template< unsigned int... pins >
  168.     using pins_a = port_pins< 0, pins... >;
  169.  
  170.     template< unsigned int... pins >
  171.     using pins_b = port_pins< 1, pins... >;
  172.  
  173.     template< unsigned int... pins >
  174.     using pins_c = port_pins< 2, pins... >;
  175. }
  176.  
  177. void playground_main()
  178. {
  179.     gpio::configure< gpio::pins_a< 2, 3, 4, 5 >, gpio::pins_b< 5, 6, 7 > >( gpio::pull_up() | gpio::high_speed() | gpio::output() );
  180. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement