Bare Metal Programming Tool Kit
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
pins.h
Go to the documentation of this file.
1 //***************************************************************************
2 //
3 // file : bmptk/hardware/pins.h
4 //
5 // LICENSE (MIT expat license, copy of bmptk/license.txt)
6 //
7 // Copyright (c) 2013 Wouter van Ooijen (wouter@voti.nl)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE..
27 //
28 //***************************************************************************
29 
30 // document everything in this file
33 namespace bmptk {
34 namespace hardware {
35 
36 // ==========================================================================
37 //
38 // pin interface classes
39 //
40 // ==========================================================================
41 
43 //
48 struct pin_in {
49 
51  enum { type = type_pin_in };
52 
54  enum { features = has_none };
55 
57  //
61  static void init();
62 
64  //
71  static bool get();
72 };
73 
75 //
80 struct pin_out {
81 
83  enum { type = type_pin_out };
84 
86  enum { features = has_none };
87 
89  //
93  static void init();
94 
96  //
103  static void set( bool x );
104 };
105 
107 //
113 struct pin_in_out {
114 
116  enum { type = type_pin_in_out };
117 
119  enum { features = has_none };
120 
122  //
129  static void init();
130 
132  //
135  static void direction_set_input();
136 
138  //
141  static void direction_set_output();
142 
146  static bool get();
147 
154  static void set( bool x );
155 };
156 
158 //
166 struct pin_oc {
167 
169  enum { type = type_pin_oc };
170 
172  enum { features = has_none };
173 
175  //
184  static void init();
185 
190  static void set( bool x );
191 
196  static bool get();
197 };
198 
199 
201 //
208 public:
209 
211  enum { features = has_pullup };
212 
214  static void pullup_enable();
215 
217  static void pullup_disable();
218 };
219 
221 //
227 class pin_ad {
228 
230  enum { features = has_ad };
231 
233  //
236  static void ad_init();
237 
239  //
243  static unsigned int ad_get();
244 
246  static unsigned int ad_bits();
247 
249  static unsigned int ad_max();
250 };
251 
252 
253 // ==========================================================================
254 //
255 // create a pin from another pin
256 //
257 // ==========================================================================
258 
259 #ifdef DOXYDOC
260 
262  //
269  template< typename pin > struct pin_in_out_from : public pin_in_out {};
270 
271 #else
272 
274 template< typename pin, int flavour = pin::type >
275 struct pin_in_out_from {
276  static_assert(
277  ( flavour == bmptk::type_pin_in_out )
278  | ( flavour == bmptk::type_pin_oc ),
279  "pin_in_out_from requires a pin_in_out or a pin_oc"
280  );
281 };
282 
284 template< typename pin >
285 struct pin_in_out_from< pin, type_pin_in_out > : public pin {};
286 
288 template< typename pin >
289 struct pin_in_out_from< pin, type_pin_oc > : public pin {
290 
292  static void direction_set_input(){
293  // setting an open-collector pin high will
294  // make it float
295  pin::set( 1 );
296  }
297 
299  static void direction_set_output(){
300  // no need to do anything, setting the pin high
301  // or low will do the real work
302  }
303 
304 };
305 
306 #endif
307 
308 #ifdef DOXYDOC
309 
311  //
318  template< typename pin > struct pin_oc_from : public pin_oc {};
319 
320 #else
321 
324 template< typename pin, int flavour = pin::type >
325 struct pin_oc_from {
326  static_assert(
327  ( flavour == bmptk::type_pin_oc )
328  | ( flavour == bmptk::type_pin_in_out ),
329  "pin_oc_from requires a pin_oc or a pin_in_out"
330  );
331 };
333 
336 template< typename pin >
337 class pin_oc_from< pin, type_pin_oc > : public pin {};
339 
342 template< typename pin >
343 struct pin_oc_from< pin, type_pin_in_out > : public pin_oc {
344 
345  // don't inherit from the pin, because that would inherit
346  // direction_set_input and direction_set_output
347 
349  static void set( bool x ){
350  // to make a pin_in_out behave like a pin_oc
351  if( x ){
352 
353  // make it float when it is set high
354  pin::direction_set_input();
355 
356  } else {
357 
358  // make it output and low when it is set low
359  pin::direction_set_output();
360  pin::set( 0 );
361  }
362  }
363 
365  static bool get(){
366  return pin::get();
367  }
368 
369 };
371 
372 
373 #endif
374 
375 #ifdef DOXYDOC
376 
378  //
385  template< typename pin > struct pin_out_from : public pin_out {};
386 
387 #else
388 
390 template< typename pin, int flavour = pin::type >
391 struct pin_out_from {
392  static_assert(
393  ( flavour == bmptk::type_pin_out )
394  | ( flavour == bmptk::type_pin_in_out )
395  | ( flavour == bmptk::type_pin_oc ),
396  "pin_out_from requires a pin_out, pin_in_out or a pin_oc"
397  );
398 };
399 
401 template< class pin >
402 struct pin_out_from< pin, type_pin_out > : public pin {};
403 
405 template< class pin >
406 struct pin_out_from< pin, type_pin_in_out > : public pin_out {
407 
408  // don't inherit from the pin, because that would inherit
409  // get() and direction_set_input and direction_set_output
410 
412  static void init(){
413  pin::init();
414  pin::direction_set_output();
415  }
416 
418  static void set( bool x ){
419  pin::set( x );
420  }
421 };
422 
424 template< class pin >
425 struct pin_out_from< pin, type_pin_oc > : public pin_out {
426 
427  // don't inherit from the pin, because that would inherit get()
428 
430  static void init(){
431  pin::init();
432  }
433 
435  static void set( bool x ){
436  pin::set( x );
437  }
438 };
439 
440 #endif
441 
442 
443 #ifdef DOXYDOC
444 
446  //
453  template< typename pin > struct pin_in_from : public pin_in {};
454 
455 #else
456 
458 template< typename pin, int flavour = pin::type >
459 struct pin_in_from {
460  static_assert(
461  ( flavour == bmptk::type_pin_in )
462  | ( flavour == bmptk::type_pin_in_out )
463  | ( flavour == bmptk::type_pin_oc ),
464  "pin_in_from requires a pin_out, pin_in_out or a pin_oc"
465  );
466 };
467 
469 template< class pin >
470 struct pin_out_from< pin, type_pin_in > : public pin {};
471 
473 template< class pin >
474 struct pin_in_from< pin, type_pin_in_out > : public pin_in {
475 
476  // don't inherit from the pin, because that would inherit
477  // get() and direction_set_input and direction_set_output
478 
480  static void init(){
481  pin::init();
482  pin::direction_set_input();
483  }
484 
486  static bool get(){
487  return pin::get();
488  }
489 };
490 
492 template< class pin >
493 struct pin_in_from< pin, type_pin_oc > : public pin_in {
494 
495  // don't inherit from the pin, because that would inherit set()
496 
498  static void init(){
499  pin::init();
500  pin::set( 1 );
501  }
502 
504  static bool get(){
505  return pin::get();
506  }
507 };
508 
509 #endif
510 
511 
512 // ==========================================================================
513 //
514 // invert a pin (or port, in ports.h)
515 //
516 // ==========================================================================
517 
518 #ifdef DOXYDOC
519 
521  //
540  template< typename pin_or_port > class invert : public pin_or_port {};
541 
542 #else
543 
545 template< class t, int flavour = t::type >
546 struct invert {
547  static_assert(
548  // dummy condition
549  flavour == bmptk::type_pin_in,
550  "invert requires a pin or port"
551  );
552 };
553 
555 template< class pin >
556 struct invert< pin, type_pin_in > : public pin {
557 
559  static bool get(){
560  return ! pin::get();
561  }
562 };
563 
565 template< class pin >
566 struct invert< pin, type_pin_out > : public pin {
567 
569  static void set( bool x ){
570  pin::set( ! x );
571  }
572 };
573 
575 template< class pin >
576 struct invert< pin, type_pin_in_out > : public pin {
577 
579  static void set( bool x ){
580  pin::set( ! x );
581  }
582 
584  static bool get(){
585  return ! pin::get();
586  }
587 };
588 
590 template< class pin >
591 struct invert< pin, type_pin_oc > : public pin {
592 
594  static void set( bool x ){
595  pin::set( ! x );
596  }
597 
599  static bool get(){
600  return ! pin::get();
601  }
602 };
603 
604 #endif
605 
606 // ==========================================================================
607 //
608 // flipable
609 //
610 // ==========================================================================
611 
613 template< class pin, int flavour = pin::type >
614 struct flipable : public pin {
615 private:
616 
617  static_assert(
618  ( flavour == bmptk::type_pin_out )
619  | ( flavour == bmptk::type_pin_in_out )
620  | ( flavour == bmptk::type_pin_oc ),
621  "flipable requires a pin_out, pin_in_out or a pin_oc"
622  );
623 
624  static bool value;
625 
626 public:
627 
629  static void set( bool x ){
630  value = x;
631  pin::set( x );
632  }
633 
635  //
640  static void flip(){
641  value = ! value;
642  pin::set( value );
643  }
644 };
645 
646 template< class pin, int flavour > bool flipable< pin, flavour >::value;
647 
648 
649 // ==========================================================================
650 //
651 // detect a rising_edge
652 //
653 // ==========================================================================
654 
656 template< class arg_pin, int flavour = arg_pin::type >
657 struct rising_edge : public pin_in {
658 private:
659 
660  static_assert(
661  ( flavour == bmptk::type_pin_in )
662  | ( flavour == bmptk::type_pin_in_out )
663  | ( flavour == bmptk::type_pin_oc ),
664  "flipable requires a pin_in, pin_in_out or a pin_oc"
665  );
666 
667  typedef pin_in_from< arg_pin > pin;
668 
669  static bool last;
670 
671 public:
672 
674  static void init(){
675  pin::init();
676  }
677 
679  //
684  static bool get(){
685  if( last ){
686  if( ! pin::get() ){
687  last = false;
688  }
689  } else {
690  if( pin::get() ){
691  last = true;
692  return true;
693  }
694  }
695  return false;
696  }
697 };
698 
699 template< class pin, int flavour > bool rising_edge< pin, flavour >::last = 0;
700 
701 
702 // ==========================================================================
703 //
704 // debounce
705 //
706 // ==========================================================================
707 
709 //
714 template< class arg_pin >
715 struct debounce : public pin_in {
716 private:
717 
718  static_assert(
719  ( (int)arg_pin::type == bmptk::type_pin_in )
720  | ( (int)arg_pin::type == bmptk::type_pin_in_out )
721  | ( (int)arg_pin::type == bmptk::type_pin_oc ),
722  "flipable requires a pin_in, pin_in_out or a pin_oc"
723  );
724 
725  typedef pin_in_from< arg_pin > pin;
726 
727 public:
728 
730  static void init(){
731  pin::init();
732  }
733 
735  //
742  static bool get( bmptk::time interval = 50 * bmptk::ms ){
743  static bool last_value;
744  static bmptk::time last_time = -1 * bmptk::s;
746  if( now >= last_time + interval ){
747  last_value = pin::get();
748  last_time = now;
749  }
750  return last_value;
751  }
752 };
753 
754 
755 // ==========================================================================
756 //
757 // combine pins tee-wise: write to the master to write to them all
758 //
759 // ==========================================================================
760 
761 #ifdef DOXYDOC
762 
764  //
782  template< typename... > class tee : public pin_out {};
783  template< typename port_out > class tee : public pin_out {};
784 
785 #else
786 
787 template< typename... > class tee;
788 
789 template<>
790 class tee<> : public pin_out {
791 public:
792  static void init(){}
793  static void set( bool b ){}
794 };
795 
796 template< typename arg_pin, typename... tail_args >
797 struct tee< arg_pin, tail_args... > : public pin_out {
798 
799  static_assert(
800  ( (int)arg_pin::type == bmptk::type_pin_out )
801  | ( (int)arg_pin::type == bmptk::type_pin_in_out )
802  | ( (int)arg_pin::type == bmptk::type_pin_oc ),
803  "flipable requires a pin_out, pin_in_out or a pin_oc"
804  );
805 
806  typedef pin_out_from< arg_pin > pin;
807 
808  typedef tee< tail_args... > tail;
809 
810  static void init(){
811  pin::init();
812  tail::init();
813  }
814 
815  static void set( bool b ){
816  pin::set( b );
817  tail::set( b );
818  }
819 };
820 
822 //
825 struct pin_in_out_dummy : pin_in_out {
826  static void init(){}
827  static void direction_set_input(){}
828  static void direction_set_output(){}
829  static bool get(){ return 0; }
830  static void set( bool x ){}
831 };
832 
833 
834 /*
835 // ==========================================================================
836 //
837 // combine two pins with a logic function
838 //
839 // ==========================================================================
840 
841 template < typename a, typename b > struct logic_xor : public pin_out {
842  static void init(){ a::init(); b::init(); }
843  static bool get(){ return a::get() ^ b::get(); }
844 };
845 
846 */
847 
848 
849 /*
850 template <
851  typename port
852 > class tee <
853  port,
854  std::enable_if< std::is_base_of< port_out, port >::value, int >
855 > : public pin_out {
856 public:
857 
858  static_assert(
859  std::is_base_of< port_out, port>::value,
860  "port must be a descendant of port_out"
861  );
862 
863  static void init(){
864  port::init();
865  }
866 
867  static void set( bool b ){
868  port::set( b ? -1 : 0 );
869  }
870 
871 };
872 */
873 
874 
875 
876 #endif
877 
878 
879 
880 }; // namespace hardware
881 }; // namespace bmptk;