Bare Metal Programming Tool Kit
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
ports.h
Go to the documentation of this file.
1 //***************************************************************************
2 //
3 // file : bmptk/hardware/ports.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 // port interface classes
39 //
40 // ==========================================================================
41 
43 //
50 struct port_in {
51 
53  enum { type = type_port_in };
54 
56  enum { features = has_none };
57 
59  //
63  static void init();
64 
66  static int n_pins();
67 
69  //
80  static unsigned int get();
81 };
82 
84 //
91 struct port_out {
92 
94  enum { type = type_port_out };
95 
97  enum { features = has_none };
98 
100  //
104  static void init();
105 
107  static int n_pins();
108 
110  //
120  static void set( unsigned int d );
121 };
122 
124 //
132 struct port_in_out {
133 
135  enum { type = type_port_in_out };
136 
138  enum { features = has_none };
139 
141  //
145  static void init();
146 
148  static int n_pins();
149 
151  //
154  static void direction_set_input();
155 
157  //
160  static void direction_set_output();
161 
166  static void set( unsigned int d );
167 
173  static unsigned int get();
174 };
175 
177 //
185 struct port_oc {
186 
188  enum { type = type_port_oc };
189 
191  enum { features = has_none };
192 
194  static void init();
195 
197  static int n_pins();
198 
203  static void set( unsigned int d );
204 
210  static unsigned int get();
211 };
212 
213 
214 // ==========================================================================
215 //
216 // combine pins into a port_out
217 //
218 // ==========================================================================
219 
221 //
230 template< typename... > class port_out_from_pins : public port_out {};
231 
232 #ifndef DOXYDOC
233 
234 template<> class port_out_from_pins<> : public port_out {
235 public:
236  static void init(){}
237  static void set( unsigned int x ){}
238  static int n_pins(){ return 0; }
239 };
240 
241 template< typename arg_pin, typename... tail_args >
242 struct port_out_from_pins< arg_pin, tail_args... > : public port_out {
243 
244  static_assert(
245  ( (int)arg_pin::type == bmptk::type_pin_out )
246  | ( (int)arg_pin::type == bmptk::type_pin_in_out )
247  | ( (int)arg_pin::type == bmptk::type_pin_oc ),
248  "port_out_from_pins requires pin_out, pin_in_out or a pin_oc"
249  );
250 
251  typedef port_out_from_pins< tail_args... > tail;
252  typedef pin_out_from< arg_pin > pin;
253 
254  static void init(){
255  pin::init();
256  tail::init();
257  }
258 
259  static void set( unsigned int x ){
260  pin::set( x & 0x01 );
261  tail::set( x >> 1 );
262  }
263 
264  static int n_pins(){
265  return tail::n_pins() + 1;
266  }
267 };
268 
269 #endif
270 
271 
273 //
279 template< typename... > class port_in_from_pins : public port_in {};
280 
281 #ifndef DOXYDOC
282 
283 template<> class port_in_from_pins<> : public port_in {
284 public:
285  static void init(){}
286  static unsigned int get(){ return 0; }
287  static int n_pins(){ return 0; }
288 };
289 
290 template< typename arg_pin, typename... tail_args >
291 class port_in_from_pins< arg_pin, tail_args... > : public port_in {
292 public:
293 
294  typedef port_in_from_pins< tail_args... > tail;
295  typedef pin_in_from< arg_pin > pin;
296 
297  static void init(){
298  pin::init();
299  tail::init();
300  }
301 
302  static unsigned int get(){
303  return
304  ( tail::get() << 1 )
305  | pin::get() ? 0x01 : 0x00;
306  }
307 
308  static int n_pins(){
309  return tail::n_pins() + 1;
310  }
311 };
312 
313 #endif
314 
315 
317 //
323 template< typename... > class port_in_out_from_pins : public port_in_out {};
324 
325 #ifndef DOXYDOC
326 
327 template<> class port_in_out_from_pins<> : public port_in_out {
328 public:
329  static void init(){}
330  static unsigned int get(){ return 0; }
331  static void set( unsigned int x ){}
332  static int n_pins(){ return 0; }
333  static void direction_set_input() {}
334  static void direction_set_output() {}
335 };
336 
337 template< typename arg_pin, typename... tail_args >
338 class port_in_out_from_pins< arg_pin, tail_args... > : public port_in_out {
339 public:
340 
341  typedef port_in_out_from_pins< tail_args... > tail;
342  typedef pin_in_out_from< arg_pin > pin;
343 
344  static void init(){
345  pin::init();
346  tail::init();
347  }
348 
349  static void set( unsigned int x ){
350  pin::set( x & 0x01 );
351  tail::set( x >> 1 );
352  }
353 
354  static unsigned int get(){
355  return
356  ( tail::get() << 1 )
357  | pin::get() ? 0x01 : 0x00;
358  }
359 
360  static void direction_set_input() {
361  pin::direction_set_input();
362  tail::direction_set_input();
363  }
364 
365  static void direction_set_output() {
366  pin::direction_set_output();
367  tail::direction_set_output();
368  }
369 
370  static int n_pins(){
371  return tail::n_pins() + 1;
372  }
373 };
374 
375 #endif
376 
377 
379 //
385 template< typename... > class port_oc_from_pins : public port_oc {};
386 
387 #ifndef DOXYDOC
388 
389 template<> class port_oc_from_pins<> : public port_oc {
390 public:
391  static void init(){}
392  static unsigned int get(){ return 0; }
393  static void set( unsigned int x ){}
394  static int n_pins(){ return 0; }
395 };
396 
397 template< typename arg_pin, typename... tail_args >
398 class port_oc_from_pins< arg_pin, tail_args... > : public port_oc {
399 public:
400 
401  typedef port_oc_from_pins< tail_args... > tail;
402  typedef pin_oc_from< arg_pin > pin;
403 
404  static void init(){
405  pin::init();
406  tail::init();
407  }
408 
409  static void set( unsigned int x ){
410  pin::set( x & 0x01 );
411  tail::set( x >> 1 );
412  }
413 
414  static unsigned int get(){
415  return
416  ( tail::get() << 1 )
417  | pin::get() ? 0x01 : 0x00;
418  }
419 
420  static int n_pins(){
421  return tail::n_pins() + 1;
422  }
423 };
424 
425 #endif
426 
427 template< typename port >
428 class port_out_from : public port {};
429 
430 // ==========================================================================
431 //
432 // 8-bit buffered ports
433 //
434 // ==========================================================================
435 
438 
440  static void init();
441 
443  static void set( unsigned int x );
444 };
445 
447 //
450 template< typename channel >
451 class port_buffer_out : public port_out {
452 
453  static unsigned int port_out_buffer;
454 
455  static void port_out_flush(){
456  channel::set( port_out_buffer );
457  }
458 
459  template< int p >
460  class single_pin : public bmptk::hardware::pin_out {
461  public:
462 
463  static void init(){
464  channel::init();
465  }
466 
467  static void set( bool x ){
468  if( x ){
469  port_out_buffer |= ( 0x01 << p );
470  } else {
471  port_out_buffer &= ~ ( 0x01 << p );
472  }
473  port_out_flush();
474  }
475  };
476 
477 public:
478 
480  static void init(){
481  channel::init();
482  }
483 
485  static void set( unsigned int x ){
486  port_out_buffer = x;
487  port_out_flush();
488  }
489 
491  static int n_pins(){
492  return 8;
493  }
494 
496  typedef single_pin< 0 > pin_0;
497 
499  typedef single_pin< 1 > pin_1;
500 
502  typedef single_pin< 2 > pin_2;
503 
505  typedef single_pin< 3 > pin_3;
506 
508  typedef single_pin< 4 > pin_4;
509 
511  typedef single_pin< 5 > pin_5;
512 
514  typedef single_pin< 6 > pin_6;
515 
517  typedef single_pin< 7 > pin_7;
518 };
519 
520 template < typename channel >
522 
525 
527  static void init();
528 
530  static void set( unsigned int x );
531 
533  static unsigned int get();
534 };
535 
537 //
540 template< typename channel >
541 class port_buffer_oc : public port_oc {
542 
543  static unsigned int port_in_buffer;
544  static unsigned int port_out_buffer;
545 
546  static void port_out_flush(){
547  channel::set( port_out_buffer );
548  }
549 
550  static void port_in_refresh(){
551  port_in_buffer = channel::get();
552  }
553 
554  template< int p >
555  class single_pin : public bmptk::hardware::pin_oc {
556  public:
557 
558  static void init(){
559  channel::init();
560  }
561 
562  static void set( bool x ){
563  if( x ){
564  port_out_buffer |= ( 0x01 << p );
565  } else {
566  port_out_buffer &= ~ ( 0x01 << p );
567  }
568  port_out_flush();
569  }
570 
571  static bool get(){
572  port_in_refresh();
573  return port_in_buffer &( 0x01 << p );
574  }
575  };
576 
577 public:
578 
580  static void init(){
581  channel::init();
582  }
583 
585  static void set( unsigned int x ){
586  port_out_buffer = x;
587  port_out_flush();
588  }
589 
591  static int n_pins(){
592  return 8;
593  }
594 
596  static unsigned int get(){
597  port_in_refresh();
598  return port_in_buffer;
599  }
600 
602  typedef single_pin< 0 > pin_0;
603 
605  typedef single_pin< 1 > pin_1;
606 
608  typedef single_pin< 2 > pin_2;
609 
611  typedef single_pin< 3 > pin_3;
612 
614  typedef single_pin< 4 > pin_4;
615 
617  typedef single_pin< 5 > pin_5;
618 
620  typedef single_pin< 6 > pin_6;
621 
623  typedef single_pin< 7 > pin_7;
624 };
625 
626 template < typename channel >
628 template < typename channel >
630 
633 
635  static void init();
636 
638  static unsigned int get();
639 };
640 
642 //
645 template< typename channel >
646 class port_buffer_in : public port_in {
647 
648  static unsigned int port_in_buffer;
649 
650  static void port_in_refresh(){
651  port_in_buffer = channel::get();
652  }
653 
654  template< int p >
655  class single_pin : public bmptk::hardware::pin_in {
656  public:
657 
658  static void init(){
659  channel::init();
660  }
661 
662  static bool get(){
663  port_in_refresh();
664  return port_in_buffer &( 0x01 << p );
665  }
666  };
667 
668 public:
669 
671  static void init(){
672  channel::init();
673  }
674 
676  static int n_pins(){
677  return 8;
678  }
679 
681  static unsigned int get(){
682  port_in_refresh();
683  return port_in_buffer;
684  }
685 
687  typedef single_pin< 0 > pin_0;
688 
690  typedef single_pin< 1 > pin_1;
691 
693  typedef single_pin< 2 > pin_2;
694 
696  typedef single_pin< 3 > pin_3;
697 
699  typedef single_pin< 4 > pin_4;
700 
702  typedef single_pin< 5 > pin_5;
703 
705  typedef single_pin< 6 > pin_6;
706 
708  typedef single_pin< 7 > pin_7;
709 };
710 
711 template < typename channel >
713 
716 
718  static void init();
719 
721  static void set( unsigned int x );
722 
724  static unsigned int get();
725 
727  //
730  static unsigned direction( unsigned int x );
731 };
732 
734 //
737 template< typename channel >
739 
740  static unsigned int port_in_buffer;
741  static unsigned int port_out_buffer;
742  static unsigned int port_direction_buffer;
743 
744  static void port_out_flush(){
745  channel::set( port_out_buffer );
746  }
747 
748  static void port_in_refresh(){
749  port_in_buffer = channel::get();
750  }
751 
752  static void port_direction_flush(){
753  channel::direction( port_direction_buffer );
754  }
755 
756  template< int p >
757  class single_pin : public bmptk::hardware::pin_in_out {
758  public:
759 
760  static void init(){
761  channel::init();
762  }
763 
764  static void set( bool x ){
765  if( x ){
766  port_out_buffer |= ( 0x01 << p );
767  } else {
768  port_out_buffer &= ~ ( 0x01 << p );
769  }
770  port_out_flush();
771  }
772 
773  static bool get(){
774  port_in_refresh();
775  return port_in_buffer &( 0x01 << p );
776  }
777 
778  static void direction_set_input(){
779  port_direction_buffer &= ( 0x01 << p ) ^ -1;
780  port_direction_flush();
781  }
782 
783  static void direction_set_output(){
784  port_direction_buffer |= ( 0x01 << p );
785  port_direction_flush();
786  }
787  };
788 
789 public:
790 
792  static void init(){
793  channel::init();
794  }
795 
797  static void set( unsigned int x ){
798  port_out_buffer = x;
799  port_out_flush();
800  }
801 
803  static int n_pins(){
804  return 8;
805  }
806 
808  static unsigned int get(){
809  port_in_refresh();
810  return port_in_buffer;
811  }
812 
814  static void direction_set_input(){
815  port_direction_buffer = 0;
816  port_direction_flush();
817  }
818 
820  static void direction_set_output(){
821  port_direction_buffer = 0 ^ -1;
822  port_direction_flush();
823  }
824 
826  typedef single_pin< 0 > pin_0;
827 
829  typedef single_pin< 1 > pin_1;
830 
832  typedef single_pin< 2 > pin_2;
833 
835  typedef single_pin< 3 > pin_3;
836 
838  typedef single_pin< 4 > pin_4;
839 
841  typedef single_pin< 5 > pin_5;
842 
844  typedef single_pin< 6 > pin_6;
845 
847  typedef single_pin< 7 > pin_7;
848 };
849 
850 template < typename channel >
852 template < typename channel >
854 template < typename channel >
856 
857 
858 // ==========================================================================
859 //
860 // invert a port
861 //
862 // ==========================================================================
863 
864 #ifndef DOXYDOC
865 
866 template< class port >
867 struct invert< port, type_port_out > : public port {
868  static void set( unsigned int x ){ port::set( x ^ -1 ); }
869 };
870 
871 template< class port >
872 struct invert< port, type_port_in > : public port {
873  static unsigned int get(){ return port::get() ^ -1; }
874 };
875 
876 template< class port >
877 struct invert< port, type_port_in_out > : public port {
878  static void set( unsigned int x ){ port::set( x ^ -1 ); }
879  static unsigned int get(){ return port::get() ^ -1; }
880 };
881 template< class port >
882 
883 struct invert< port, type_port_oc > : public port {
884  static void set( unsigned int x ){ port::set( x ^ -1 ); }
885  static unsigned int get(){ return port::get() ^ -1; }
886 };
887 
888 #endif
889 
890 
891 }; // namespace hardware
892 }; // namespace bmptk;