Prusa-MMU-Private
PrusaMultiMaterialUpgradev3firmwareforMK3SMK4
gpio.h
Go to the documentation of this file.
1 #pragma once
3 #include <inttypes.h>
4 
5 #ifdef __AVR__
6 #include <avr/io.h>
7 #include <util/atomic.h>
8 #else
9 #define ATOMIC_BLOCK(x)
10 #endif
11 
12 namespace hal {
13 
15 namespace gpio {
16 
17 struct GPIO_TypeDef {
18  volatile uint8_t PINx;
19  volatile uint8_t DDRx;
20  volatile uint8_t PORTx;
21 };
22 
23 enum class Mode : uint8_t {
24  input = 0,
25  output,
26 };
27 
28 enum class Pull : uint8_t {
29  none = 0,
30  up,
31  down, // not available on the AVR
32 };
33 
34 enum class Level : uint8_t {
35  low = 0,
36  high,
37 };
38 
40  Mode mode;
41  Pull pull;
42  Level level;
43  inline GPIO_InitTypeDef(Mode mode, Pull pull)
44  : mode(mode)
45  , pull(pull) {};
46  inline GPIO_InitTypeDef(Mode mode, Level level)
47  : mode(mode)
48  , level(level) {};
49 };
50 
51 struct GPIO_pin {
52  // No constructor here in order to allow brace-initialization in old
53  // gcc versions/standards
54  GPIO_TypeDef *const port;
55  const uint8_t pin;
56 };
57 
58 __attribute__((always_inline)) inline void WritePin(const GPIO_pin portPin, Level level) {
59  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
60  if (level == Level::high)
61  portPin.port->PORTx |= (1 << portPin.pin);
62  else
63  portPin.port->PORTx &= ~(1 << portPin.pin);
64  }
65 }
66 
67 __attribute__((always_inline)) inline Level ReadPin(const GPIO_pin portPin) {
68 #ifdef __AVR__
69  return (Level)((portPin.port->PINx & (1 << portPin.pin)) != 0);
70 #else
71  // Return the value modified by WritePin
72  return (Level)((portPin.port->PORTx & (1 << portPin.pin)) != 0);
73 #endif
74 }
75 
76 __attribute__((always_inline)) inline void TogglePin(const GPIO_pin portPin) {
77 #ifdef __AVR__
78  // Optimized path for AVR, resulting in a pin toggle
79  portPin.port->PINx = (1 << portPin.pin);
80 #else
81  WritePin(portPin, (Level)(ReadPin(portPin) != Level::high));
82 #endif
83 }
84 
85 __attribute__((always_inline)) inline void Init(const GPIO_pin portPin, GPIO_InitTypeDef GPIO_Init) {
86  if (GPIO_Init.mode == Mode::output) {
87  WritePin(portPin, GPIO_Init.level);
88  portPin.port->DDRx |= (1 << portPin.pin);
89  } else {
90  portPin.port->DDRx &= ~(1 << portPin.pin);
91  WritePin(portPin, (Level)GPIO_Init.pull);
92  }
93 }
94 
95 }
96 }
97 
98 #ifdef __AVR__
99 #define GPIOA ((hal::gpio::GPIO_TypeDef *)&PINA)
100 #define GPIOB ((hal::gpio::GPIO_TypeDef *)&PINB)
101 #define GPIOC ((hal::gpio::GPIO_TypeDef *)&PINC)
102 #define GPIOD ((hal::gpio::GPIO_TypeDef *)&PIND)
103 #define GPIOE ((hal::gpio::GPIO_TypeDef *)&PINE)
104 #define GPIOF ((hal::gpio::GPIO_TypeDef *)&PINF)
105 #define GPIOG ((hal::gpio::GPIO_TypeDef *)&PING)
106 #define GPIOH ((hal::gpio::GPIO_TypeDef *)&PINH)
107 #define GPIOJ ((hal::gpio::GPIO_TypeDef *)&PINJ)
108 #define GPIOK ((hal::gpio::GPIO_TypeDef *)&PINK)
109 #define GPIOL ((hal::gpio::GPIO_TypeDef *)&PINL)
110 #else
111 
112 // stub entries
113 extern hal::gpio::GPIO_TypeDef _GPIOA;
114 extern hal::gpio::GPIO_TypeDef _GPIOB;
115 extern hal::gpio::GPIO_TypeDef _GPIOC;
116 extern hal::gpio::GPIO_TypeDef _GPIOD;
117 extern hal::gpio::GPIO_TypeDef _GPIOE;
118 extern hal::gpio::GPIO_TypeDef _GPIOF;
119 extern hal::gpio::GPIO_TypeDef _GPIOG;
120 extern hal::gpio::GPIO_TypeDef _GPIOH;
121 extern hal::gpio::GPIO_TypeDef _GPIOJ;
122 extern hal::gpio::GPIO_TypeDef _GPIOK;
123 extern hal::gpio::GPIO_TypeDef _GPIOL;
124 
125 #define GPIOA (&::_GPIOA)
126 #define GPIOB (&::_GPIOB)
127 #define GPIOC (&::_GPIOC)
128 #define GPIOD (&::_GPIOD)
129 #define GPIOE (&::_GPIOE)
130 #define GPIOF (&::_GPIOF)
131 #define GPIOG (&::_GPIOG)
132 #define GPIOH (&::_GPIOH)
133 #define GPIOJ (&::_GPIOJ)
134 #define GPIOK (&::_GPIOK)
135 #define GPIOL (&::_GPIOL)
136 
137 #endif
void Init()
ADC access routines.
Definition: adc.cpp:8
Definition: gpio.h:39
Definition: gpio.h:17
Definition: gpio.h:51