Skip to content

Commit f702ed5

Browse files
committed
import wiring digital
1 parent 2d5e673 commit f702ed5

File tree

1 file changed

+128
-111
lines changed

1 file changed

+128
-111
lines changed

cores/arduino/wiring_digital.c

+128-111
Original file line numberDiff line numberDiff line change
@@ -28,33 +28,51 @@
2828

2929
void pinMode(uint8_t pin, PinMode mode)
3030
{
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;
5876
}
5977
}
6078

@@ -74,106 +92,105 @@ void pinMode(uint8_t pin, PinMode mode)
7492
//static inline void turnOffPWM(uint8_t timer)
7593
static void turnOffPWM(uint8_t timer)
7694
{
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 */
13796

138-
void digitalWrite(uint8_t pin, PinStatus val)
139-
{
97+
/* Get pin's timer */
14098
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;
144100

145-
if (port == NOT_A_PIN) return;
101+
switch (timer) {
146102

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);
150107

151-
out = portOutputRegister(port);
108+
/* Disable corresponding channel */
109+
TCA0.SINGLE.CTRLB &= ~(1 << (TCA_SINGLE_CMP0EN_bp + bit_pos));
152110

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:
155117

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:
160125
}
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;
161133

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+
// }
163173
}
164174

165175
PinStatus digitalRead(uint8_t pin)
166176
{
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;
172180

173181
// If the pin that support PWM output, we need to turn it off
174182
// 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;
176188

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+
}
178195
return LOW;
179196
}

0 commit comments

Comments
 (0)