Arduino Pin Library  v4.2.0
An easy to use Arduino library for fast and simultaneous operations on Arduino I/O pins.
Pin.h
Go to the documentation of this file.
1 
8 #include "Arduino.h"
9 
10 
11 #pragma once
12 
13 
14 // ################################# Defines #################################
15 
16 #define DDR_HIGH (*_DDR |= _offset)
17 #define DDR_TOGGLE (*_DDR ^= _offset)
18 #define DDR_LOW (*_DDR &= _ioffset)
19 
20 #define PORT_HIGH (*_PORT |= _offset)
21 #define PORT_TOGGLE (*_PORT ^= _offset)
22 #define PORT_LOW (*_PORT &= _ioffset)
23 
24 #define DDR_ON (*_DDR & _offset)
25 #define DDR_OFF (*_DDR | _ioffset)
26 
27 #define PORT_ON (*_PORT & _offset)
28 #define PORT_OFF (*_PORT | _ioffset)
29 
30 #define PIN_ON (*_PIN & _offset)
31 #define PIN_OFF (*_PIN | _ioffset)
32 
33 
39 class Pin {
40  public:
41  // ################################# Constructors #################################
42 
46  Pin() {
47  _number = 0;
48  _offset = digitalPinToBitMask(_number);
49  _ioffset = ~_offset;
50  _timer = digitalPinToTimer(_number);
51  _PIN = portInputRegister(digitalPinToPort(_number));
52  _PORT = portOutputRegister(digitalPinToPort(_number));
53  _DDR = portModeRegister(digitalPinToPort(_number));
54  }
55 
61  Pin(uint8_t number) {
62  _number = number;
63  _offset = digitalPinToBitMask(_number);
64  _ioffset = ~_offset;
65  _timer = digitalPinToTimer(_number);
66  _PIN = portInputRegister(digitalPinToPort(_number));
67  _PORT = portOutputRegister(digitalPinToPort(_number));
68  _DDR = portModeRegister(digitalPinToPort(_number));
69  }
70 
83  Pin(uint8_t number, uint8_t offset, uint8_t timer, volatile uint8_t* PIN, volatile uint8_t* PORT, volatile uint8_t* DDR) {
84  _number = number;
85  _offset = offset;
86  _ioffset = ~_offset;
87  _timer = timer;
88  _PIN = PIN;
89  _PORT = PORT;
90  _DDR = DDR;
91  }
92 
93 
94  // ################################# Operators #################################
95 
101  operator bool() const {
102  return bool(PIN_ON);
103  }
104 
110  Pin& operator =(uint8_t state) {
111  uint8_t oldSREG = SREG;
112  cli();
113  if (state == LOW) {
114  PORT_LOW;
115  } else {
116  PORT_HIGH;
117  }
118  SREG = oldSREG;
119 
120  return *this;
121  }
122 
123 
124  // ################################# Getters #################################
125 
131  uint8_t getNumber() {
132  return _number;
133  }
134 
140  uint8_t getOffset() {
141  return _offset;
142  }
143 
149  uint8_t getInverseOffset() {
150  return _ioffset;
151  }
152 
158  uint8_t getTimer() {
159  return _timer;
160  }
161 
167  volatile uint8_t* getPIN() {
168  return _PIN;
169  }
170 
176  volatile uint8_t* getPORT() {
177  return _PORT;
178  }
179 
185  volatile uint8_t* getDDR() {
186  return _DDR;
187  }
188 
194  uint8_t getMode() {
195  if (DDR_ON) {
196  return OUTPUT;
197  } else {
198  return INPUT;
199  }
200  }
201 
207  uint8_t getState() {
208  if (PORT_ON) {
209  return HIGH;
210  } else {
211  return LOW;
212  }
213  }
214 
220  uint8_t getValue() {
221  if (PIN_ON) {
222  return HIGH;
223  } else {
224  return LOW;
225  }
226  }
227 
233  uint16_t getAnalogValue() {
234  return analogRead(_number);
235  }
236 
237 
238  // ################################# Setters #################################
239 
240  // #################### Generic ####################
241 
248  void set(uint8_t mode, uint8_t state) {
249  uint8_t oldSREG = SREG;
250  cli();
251  if (mode == INPUT) {
252  DDR_LOW;
253  } else {
254  DDR_HIGH;
255  }
256  if (state == LOW) {
257  PORT_LOW;
258  } else {
259  PORT_HIGH;
260  }
261  SREG = oldSREG;
262  }
263 
269  void setMode(uint8_t mode) {
270  uint8_t oldSREG = SREG;
271  cli();
272  if (mode == INPUT) {
273  DDR_LOW;
274  } else {
275  DDR_HIGH;
276  }
277  SREG = oldSREG;
278  }
279 
285  void setState(uint8_t state) {
286  uint8_t oldSREG = SREG;
287  cli();
288  if (state == LOW) {
289  PORT_LOW;
290  } else {
291  PORT_HIGH;
292  }
293  SREG = oldSREG;
294  }
295 
296  // #################### Input ####################
297 
301  void setInput() {
302  uint8_t oldSREG = SREG;
303  cli();
304  DDR_LOW;
305  SREG = oldSREG;
306  }
307 
311  void setPullupOn() {
312  uint8_t oldSREG = SREG;
313  cli();
314  PORT_HIGH;
315  SREG = oldSREG;
316  }
317 
321  void setPullupOff() {
322  uint8_t oldSREG = SREG;
323  cli();
324  PORT_LOW;
325  SREG = oldSREG;
326  }
327 
332  uint8_t oldSREG = SREG;
333  cli();
334  DDR_LOW;
335  PORT_HIGH;
336  SREG = oldSREG;
337  }
338 
343  uint8_t oldSREG = SREG;
344  cli();
345  DDR_LOW;
346  PORT_LOW;
347  SREG = oldSREG;
348  }
349 
350  // #################### Output ####################
351 
355  void setOutput() {
356  uint8_t oldSREG = SREG;
357  cli();
358  DDR_HIGH;
359  SREG = oldSREG;
360  }
361 
365  void setHigh() {
366  uint8_t oldSREG = SREG;
367  cli();
368  PORT_HIGH;
369  SREG = oldSREG;
370  }
371 
375  void setLow() {
376  uint8_t oldSREG = SREG;
377  cli();
378  PORT_LOW;
379  SREG = oldSREG;
380  }
381 
385  void setOutputHigh() {
386  uint8_t oldSREG = SREG;
387  cli();
388  DDR_HIGH;
389  PORT_HIGH;
390  SREG = oldSREG;
391  }
392 
396  void setOutputLow() {
397  uint8_t oldSREG = SREG;
398  cli();
399  DDR_HIGH;
400  PORT_LOW;
401  SREG = oldSREG;
402  }
403 
409  void setDutyCycle(int value) {
410  analogWrite(_number,value);
411  }
412 
413 
414  // ################################# Utilities #################################
415 
416  // #################### Toggle ####################
417 
421  void toggleMode() {
422  uint8_t oldSREG = SREG;
423  cli();
424  DDR_TOGGLE;
425  SREG = oldSREG;
426  }
427 
431  void toggleState() {
432  uint8_t oldSREG = SREG;
433  cli();
434  PORT_TOGGLE;
435  SREG = oldSREG;
436  }
437 
438 
439  // #################### RC Timer ####################
440 
448  volatile unsigned int rcTimer(volatile unsigned int count) {
449  // ######## C ########
450  /*
451  pin.setInput();
452  for (; count > 0; count--) {
453  if ((pin.getValue() == HIGH) || (count == 0)) {
454  pin.setOutput();
455  return count;
456  }
457  }
458  */
459 
460  // ######## Assembly ########
461  uint8_t status;
462  asm volatile (
463  // Save interupt status and disable interupts
464  "in %[status], __SREG__ \n\t" // Store current interupt status in variable 's'
465  "cli \n\t" // Disable interupts
466 
467  // Set Pin to input mode to start charging capacitor
468  "ld __tmp_reg__, %a[_DDR] \n\t" // Load the DDR register into r0 (__tmp_reg__)
469  "and __tmp_reg__, %[_ioffset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
470  "st %a[_DDR], __tmp_reg__ \n\t" // Store r0 (__tmp_reg__) in the DDR register
471 
472  // Count time before Pin becomes high
473  "loop%=: \n\t" // Label for looping
474  "ld __tmp_reg__,%a[_PIN] \n\t" // Load the PIN register into r0 (__tmp_reg__)
475  "and __tmp_reg__, %[_offset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
476  "brne end%= \n\t" // End the loop if r0 (__tmp_reg__) is not equal to zero by branching to label 'end'
477  "dec %[count] \n\t" // Decrement the value of 'count' by one
478  "brne loop%= \n\t" // If the value of 'count' is not equal to zero continue the loop by branching to label 'loop'
479 
480  // Done counting
481  "end%=: \n\t" // Label for ending loop
482  // Set Pin to output mode to start discharging capacitor
483  "ld __tmp_reg__, %a[_DDR] \n\t" // Load the DDR register into r0 (__tmp_reg__)
484  "or __tmp_reg__, %[_offset] \n\t" // Apply the bit mask (offset) to r0 (__tmp_reg__)
485  "st %a[_DDR], __tmp_reg__ \n\t" // Store r0 (__tmp_reg__) in the PORT register
486 
487  // Restore interupt status
488  "out __SREG__, %[status] \n\t" // Load interupt status from variable 's'
489 
490  // Outputs
491  :
492  [count] "+r" (count), // The value the counter was at when the pin went high
493  [status] "=&r" (status) // The interupt status
494 
495  // Inputs
496  :
497  [_DDR] "e" (_DDR), // The address of the DDR register for the pin
498  [_PIN] "e" (_PIN), // The address of the PIN register for the pin
499  [_offset] "r" (_offset), // The bit mask used to access pin in registers
500  [_ioffset] "r" (_ioffset) // The inverse bit mask used to access pin in registers
501  );
502 
503  return count;
504  }
505 
506  private:
507  // Variables
508  uint8_t _number;
509  uint8_t _offset;
510  uint8_t _ioffset;
511  uint8_t _timer;
512  volatile uint8_t* _PIN;
513  volatile uint8_t* _PORT;
514  volatile uint8_t* _DDR;
515 };
#define PIN
void setInputPullupOff()
Set the pin mode to input and the pin pullup resistor to off.
Definition: Pin.h:342
uint8_t getState()
Get the state of the pin from the PORT register.
Definition: Pin.h:207
uint8_t getNumber()
Get the pin number.
Definition: Pin.h:131
#define DDR_ON
Get the DDR register for the pin (HIGH, LOW) with other pins forced to 0.
Definition: Pin.h:24
void setHigh()
Set the pin output to HIGH.
Definition: Pin.h:365
uint8_t getInverseOffset()
Get the inverse pin offset.
Definition: Pin.h:149
Class for fast operations on Arduino I/O pins.
Definition: Pin.h:39
void setDutyCycle(int value)
Set the PWM duty cycle.
Definition: Pin.h:409
#define PIN_ON
Get the PIN register for the pin (HIGH, LOW) with other pins forced to 0.
Definition: Pin.h:30
volatile uint8_t * getPIN()
Get a pointer to the PIN register.
Definition: Pin.h:167
#define DDR_LOW
Set the DDR register to LOW for the pin.
Definition: Pin.h:18
uint16_t getAnalogValue()
Get the analog value of the pin.
Definition: Pin.h:233
#define PORT_ON
Get the PORT register for the pin (HIGH, LOW) with other pins forced to 0.
Definition: Pin.h:27
void setPullupOff()
Set the pin pullup resistor to off.
Definition: Pin.h:321
void setInputPullupOn()
Set the pin mode to input and the pin pullup resistor to on.
Definition: Pin.h:331
Pin & operator=(uint8_t state)
Set the pin state.
Definition: Pin.h:110
#define PORT_TOGGLE
Set the PORT register to the inverse for the pin.
Definition: Pin.h:21
void setOutput()
Set the pin mode to output.
Definition: Pin.h:355
void setOutputHigh()
Set the pin mode to output and the pin output to HIGH.
Definition: Pin.h:385
void setMode(uint8_t mode)
Set the pin mode.
Definition: Pin.h:269
volatile uint8_t * getPORT()
Get a pointer to the PORT register.
Definition: Pin.h:176
void setLow()
Set the pin output to LOW.
Definition: Pin.h:375
#define DDR_HIGH
Set the DDR register to HIGH for the pin.
Definition: Pin.h:16
#define PORT_HIGH
Set the PORT register to HIGH for the pin.
Definition: Pin.h:20
void setPullupOn()
Set the pin pullup resistor to on.
Definition: Pin.h:311
void setOutputLow()
Set the pin mode to output and the pin output to LOW.
Definition: Pin.h:396
uint8_t getValue()
Get the value of the pin from the PIN register.
Definition: Pin.h:220
void toggleMode()
Toggle the pin mode (OUTPUT -> INPUT, INPUT -> OUTPUT)
Definition: Pin.h:421
void toggleState()
Toggle the pin state (HIGH -> LOW, LOW -> HIGH)
Definition: Pin.h:431
uint8_t getOffset()
Get the pin offset.
Definition: Pin.h:140
Pin()
Default constructor.
Definition: Pin.h:46
#define PORT_LOW
Set the PORT register to LOW for the pin.
Definition: Pin.h:22
volatile uint8_t * getDDR()
Get a pointer to the DDR register.
Definition: Pin.h:185
void setInput()
Set the pin mode to input.
Definition: Pin.h:301
Pin(uint8_t number)
Arduino supported board constructor.
Definition: Pin.h:61
Pin(uint8_t number, uint8_t offset, uint8_t timer, volatile uint8_t *PIN, volatile uint8_t *PORT, volatile uint8_t *DDR)
Custom board constructor.
Definition: Pin.h:83
uint8_t getMode()
Get the mode of the pin from the DDR register.
Definition: Pin.h:194
void setState(uint8_t state)
Set the pin state.
Definition: Pin.h:285
uint8_t getTimer()
Get the pin timer.
Definition: Pin.h:158
#define DDR_TOGGLE
Set the DDR register to the inverse for the pin.
Definition: Pin.h:17
volatile unsigned int rcTimer(volatile unsigned int count)
Set the pin mode to input and decrement a counter until the pin goes HIGH or the counter reaches 0 th...
Definition: Pin.h:448