28
28
29
29
void pinMode (uint8_t pin , PinMode mode )
30
30
{
31
- uint8_t bit = digitalPinToBitMask (pin );
32
- uint8_t port = digitalPinToPort (pin );
33
- volatile uint8_t * reg , * out ;
34
-
35
- if (port == NOT_A_PIN ) return ;
36
-
37
- // JWS: can I let the optimizer do this?
38
- reg = portModeRegister (port );
39
- out = portOutputRegister (port );
40
-
41
- if (mode == INPUT ) {
42
- uint8_t oldSREG = SREG ;
43
- cli ();
44
- * reg &= ~bit ;
45
- * out &= ~bit ;
46
- SREG = oldSREG ;
47
- } else if (mode == INPUT_PULLUP ) {
48
- uint8_t oldSREG = SREG ;
49
- cli ();
50
- * reg &= ~bit ;
51
- * out |= bit ;
52
- SREG = oldSREG ;
53
- } else {
54
- uint8_t oldSREG = SREG ;
55
- cli ();
56
- * reg |= bit ;
57
- SREG = oldSREG ;
31
+ uint8_t bit_pos = digitalPinToBitPosition (pin );
32
+
33
+ if ((bit_pos == NOT_A_PIN )|| (mode > INPUT_PULLUP )) return ;
34
+
35
+ PORT_t * port = digitalPinToPortStruct (pin );
36
+ uint8_t bit_mask = (1 << bit_pos );
37
+
38
+ if (mode == OUTPUT ){
39
+
40
+ /* Save state */
41
+ uint8_t status = SREG ;
42
+ cli ();
43
+
44
+ /* Configure direction as output */
45
+ port -> DIRSET = bit_mask ;
46
+
47
+ /* Restore state */
48
+ SREG = status ;
49
+
50
+ } else { /* mode == INPUT or INPUT_PULLUP */
51
+
52
+ /* Calculate where pin control register is */
53
+ uint8_t * pin_ctrl_reg = getPINnCTRLregister (port , bit_pos );
54
+
55
+ /* Save state */
56
+ uint8_t status = SREG ;
57
+ cli ();
58
+
59
+ /* Configure direction as input */
60
+ port -> DIRCLR = bit_mask ;
61
+
62
+ /* Configure pull-up resistor */
63
+ if (mode == INPUT_PULLUP ){
64
+
65
+ /* Enable pull-up */
66
+ * pin_ctrl_reg |= PORT_PULLUPEN_bm ;
67
+
68
+ } else { /* mode == INPUT (no pullup) */
69
+
70
+ /* Disable pull-up */
71
+ * pin_ctrl_reg &= ~(PORT_PULLUPEN_bm );
72
+ }
73
+
74
+ /* Restore state */
75
+ SREG = status ;
58
76
}
59
77
}
60
78
@@ -74,106 +92,105 @@ void pinMode(uint8_t pin, PinMode mode)
74
92
//static inline void turnOffPWM(uint8_t timer)
75
93
static void turnOffPWM (uint8_t timer )
76
94
{
77
- switch (timer )
78
- {
79
- #if defined(TCCR1A ) && defined(COM1A1 )
80
- case TIMER1A : cbi (TCCR1A , COM1A1 ); break ;
81
- #endif
82
- #if defined(TCCR1A ) && defined(COM1B1 )
83
- case TIMER1B : cbi (TCCR1A , COM1B1 ); break ;
84
- #endif
85
- #if defined(TCCR1A ) && defined(COM1C1 )
86
- case TIMER1C : cbi (TCCR1A , COM1C1 ); break ;
87
- #endif
88
-
89
- #if defined(TCCR2 ) && defined(COM21 )
90
- case TIMER2 : cbi (TCCR2 , COM21 ); break ;
91
- #endif
92
-
93
- #if defined(TCCR0A ) && defined(COM0A1 )
94
- case TIMER0A : cbi (TCCR0A , COM0A1 ); break ;
95
- #endif
96
-
97
- #if defined(TCCR0A ) && defined(COM0B1 )
98
- case TIMER0B : cbi (TCCR0A , COM0B1 ); break ;
99
- #endif
100
- #if defined(TCCR2A ) && defined(COM2A1 )
101
- case TIMER2A : cbi (TCCR2A , COM2A1 ); break ;
102
- #endif
103
- #if defined(TCCR2A ) && defined(COM2B1 )
104
- case TIMER2B : cbi (TCCR2A , COM2B1 ); break ;
105
- #endif
106
-
107
- #if defined(TCCR3A ) && defined(COM3A1 )
108
- case TIMER3A : cbi (TCCR3A , COM3A1 ); break ;
109
- #endif
110
- #if defined(TCCR3A ) && defined(COM3B1 )
111
- case TIMER3B : cbi (TCCR3A , COM3B1 ); break ;
112
- #endif
113
- #if defined(TCCR3A ) && defined(COM3C1 )
114
- case TIMER3C : cbi (TCCR3A , COM3C1 ); break ;
115
- #endif
116
-
117
- #if defined(TCCR4A ) && defined(COM4A1 )
118
- case TIMER4A : cbi (TCCR4A , COM4A1 ); break ;
119
- #endif
120
- #if defined(TCCR4A ) && defined(COM4B1 )
121
- case TIMER4B : cbi (TCCR4A , COM4B1 ); break ;
122
- #endif
123
- #if defined(TCCR4A ) && defined(COM4C1 )
124
- case TIMER4C : cbi (TCCR4A , COM4C1 ); break ;
125
- #endif
126
- #if defined(TCCR4C ) && defined(COM4D1 )
127
- case TIMER4D : cbi (TCCR4C , COM4D1 ); break ;
128
- #endif
129
-
130
- #if defined(TCCR5A )
131
- case TIMER5A : cbi (TCCR5A , COM5A1 ); break ;
132
- case TIMER5B : cbi (TCCR5A , COM5B1 ); break ;
133
- case TIMER5C : cbi (TCCR5A , COM5C1 ); break ;
134
- #endif
135
- }
136
- }
95
+ /* Actually turn off compare channel, not the timer */
137
96
138
- void digitalWrite (uint8_t pin , PinStatus val )
139
- {
97
+ /* Get pin's timer */
140
98
uint8_t timer = digitalPinToTimer (pin );
141
- uint8_t bit = digitalPinToBitMask (pin );
142
- uint8_t port = digitalPinToPort (pin );
143
- volatile uint8_t * out ;
99
+ if (timer == NOT_ON_TIMER ) return ;
144
100
145
- if ( port == NOT_A_PIN ) return ;
101
+ switch ( timer ) {
146
102
147
- // If the pin that support PWM output, we need to turn it off
148
- // before doing a digital write.
149
- if (timer != NOT_ON_TIMER ) turnOffPWM (timer );
103
+ /* TCA0 */
104
+ case TIMERA0 :
105
+ /* Bit position will give output channel */
106
+ uint8_t bit_pos = digitalPinToBitPosition (pin );
150
107
151
- out = portOutputRegister (port );
108
+ /* Disable corresponding channel */
109
+ TCA0 .SINGLE .CTRLB &= ~(1 << (TCA_SINGLE_CMP0EN_bp + bit_pos ));
152
110
153
- uint8_t oldSREG = SREG ;
154
- cli ();
111
+ break ;
112
+ /* TCB - only one output */
113
+ case TIMERB0 :
114
+ case TIMERB1 :
115
+ case TIMERB2 :
116
+ case TIMERB3 :
155
117
156
- if (val == LOW ) {
157
- * out &= ~bit ;
158
- } else {
159
- * out |= bit ;
118
+ TCB_t * timerB = (TCB_t * )& TCB0 + (timer - TIMERB0 );
119
+
120
+ /* Disable TCB compare channel */
121
+ timerB -> CTRLB &= ~(TCB_CCMPEN_bm );
122
+
123
+ break ;
124
+ default :
160
125
}
126
+ }
127
+
128
+ void digitalWrite (uint8_t pin , PinStatus val )
129
+ {
130
+ /* Get bit mask for pin */
131
+ uint8_t bit_mask = digitalPinToBitMask (pin );
132
+ if (bit_mask == NOT_A_PIN ) return ;
161
133
162
- SREG = oldSREG ;
134
+ /* Turn off PWM if applicable */
135
+
136
+ // If the pin that support PWM output, we need to turn it off
137
+ // before doing a digital write.
138
+ turnOffPWM (pin );
139
+
140
+ /* Assuming the direction is already output !! */
141
+
142
+ /* Get port */
143
+ PORT_t * port = digitalPinToPortStruct (pin );
144
+ if (port == NULL ) return ;
145
+
146
+ // /* Output direction */
147
+ // if(port->DIR & bit_mask){
148
+
149
+ /* Save system status and disable interrupts */
150
+ uint8_t status = SREG ;
151
+ cli ();
152
+
153
+ /* Set output to value */
154
+ if (val == HIGH ) {
155
+ port -> OUTSET = bit_mask ;
156
+ } else if (val == TOGGLE ) {
157
+ port -> OUTTGL = bit_mask ;
158
+ } else {
159
+ port -> OUTCLR = bit_mask ;
160
+ }
161
+
162
+ /* Restore system status */
163
+ SREG = status ;
164
+
165
+ // } else {
166
+ // /* Old implementation has side effect when pin set as input -
167
+ // pull up is enabled if this function is called.
168
+ // Should we purposely implement this side effect?
169
+ // */
170
+ //
171
+ // /* Enable pull-up ?? */
172
+ // }
163
173
}
164
174
165
175
PinStatus digitalRead (uint8_t pin )
166
176
{
167
- uint8_t timer = digitalPinToTimer (pin );
168
- uint8_t bit = digitalPinToBitMask (pin );
169
- uint8_t port = digitalPinToPort (pin );
170
-
171
- if (port == NOT_A_PIN ) return LOW ;
177
+ /* Get bit mask and check valid pin */
178
+ uint8_t bit_mask = digitalPinToBitMask (pin );
179
+ if (bit_mask == NOT_A_PIN ) return LOW ;
172
180
173
181
// If the pin that support PWM output, we need to turn it off
174
182
// before getting a digital reading.
175
- if (timer != NOT_ON_TIMER ) turnOffPWM (timer );
183
+ turnOffPWM (pin );
184
+
185
+ /* Get port and check valid port */
186
+ PORT_t * port = digitalPinToPortStruct (pin );
187
+ if (port == NULL ) return LOW ;
176
188
177
- if (* portInputRegister (port ) & bit ) return HIGH ;
189
+ /* Read pin value from PORTx.IN register */
190
+ if (port -> IN & bit_mask ){
191
+ return HIGH ;
192
+ } else {
193
+ return LOW ;
194
+ }
178
195
return LOW ;
179
196
}
0 commit comments