sketchbook
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
port.h
Go to the documentation of this file.
1 #ifndef PORT_H
2 #define PORT_H
3 
4 #include "dev_data.h"
5 #include "features.h"
6 
7 #if defined(N_PORT)
8 
9 typedef struct {
10  uint8_t adr;
11  uint8_t flags;
12 } port_t;
13 extern port_t ports[];
14 
15 #include "io_regs.h" // defines _P_REGS
16 
17 #define _P_VARS(_port) \
18  uint8_t flg __attribute__((unused)) = _port->flags; \
19  uint8_t adr = _port->adr; \
20  _P_REGS(addr); \
21  adr = 1<<(adr & 0x07);
22 
23 #define _P_GET(_reg) (!!(*_reg & adr))
24 #define _P_SET(_reg,_val) do { \
25  if(_val) \
26  *_reg |= adr; \
27  else \
28  *_reg &=~adr; \
29  } while(0);
30 
31 // the first two bits are used for port_out_t, i.e. PO_* constants. Hardcoded.
32 #define PFLG_ALERT (1<<2) // alert when port changes externally
33 #define PFLG_ALT (1<<3) // switch H/Z and L/pull-up; default: H/L and Z/pull-up
34 #define PFLG_ALT2 (1<<4) // switch H/pullup and L/Z
35 #define PFLG_POLL (1<<5) // change has been reported
36 #define PFLG_CHANGED (1<<6) // pin change
37 #define PFLG_CURRENT (1<<7) // last-seen value. Hardcoded.
38 
39 typedef enum {
40  PI_OFF=0, PI_ON=1
41 } port_in_t;
42 typedef enum { // do not change: bit values are user in port.c
43  PO_OFF=0, PO_ON=1, PO_Z=2, PO_PULLUP=3
44 } port_out_t;
45 
46 // actual port-pin state
47 static inline port_in_t port_get_in(port_t *portp) {
48  _P_VARS(portp)
49  return _P_GET(pin);
50 }
51 
52 // read intended port state from registers
53 static inline port_out_t port_get_out(port_t *portp) {
54  _P_VARS(portp)
55  return _P_GET(port) | (!_P_GET(ddr)<<1) ;
56 }
57 
58 // set intended port state
59 static inline void port_set_out(port_t *portp, port_out_t state) {
60  _P_VARS(portp)
61  _P_SET(port, state&1);
62  _P_SET(ddr,!(state&2));
63  portp->flags = (portp->flags&~PFLG_CURRENT) | (state<<7);
64 }
65 
66 // update flags based on current port state
67 void port_check(port_t *pp);
68 
69 // Set port to 0/1 according to mode (PFLG_ALT*). This is harder than it seems.
70 void port_set(port_t *portp, char val);
71 
72 
73 static inline char port_changed(port_t *portp) {
74  return portp->flags & PFLG_CHANGED;
75 }
76 
77 /* Number of highest port that has a change +1 */
78 extern uint8_t port_changed_cache;
79 
80 /* Note whether a port has changed */
81 static inline char port_has_changed(port_t *portp) {
82  uint8_t flg = portp->flags;
83  if (flg & PFLG_CHANGED) {
84  flg |= PFLG_POLL;
85  flg &=~ PFLG_CHANGED;
86  portp->flags = flg;
87  return 1;
88  }
89  return 0;
90 }
91 
92 static inline void port_pre_send (port_t *portp) {
93  (void)port_has_changed(portp);
94 }
95 
96 static inline void port_post_send (port_t *portp) {
97  uint8_t flg = portp->flags;
98  if(flg & PFLG_POLL) {
99  if (flg & PFLG_CHANGED)
100  flg &=~PFLG_CHANGED;
101  else
102  flg &=~PFLG_POLL;
103  portp->flags = flg;
104  }
105 }
106 
107 #else // no i/o
108 
109 #endif // any inputs or outputs at all
110 #endif // port_h
uint8_t state
Definition: Sensors.cpp:526
return(x >> y)|(x<< (32-y))