Skip to content

Commit 39e1502

Browse files
committed
WIP
1 parent 87bca70 commit 39e1502

File tree

8 files changed

+13382
-0
lines changed

8 files changed

+13382
-0
lines changed

ext/etlcpp/deps.dot

Lines changed: 1330 additions & 0 deletions
Large diffs are not rendered by default.

ext/etlcpp/deps.svg

Lines changed: 9853 additions & 0 deletions
Loading

ext/etlcpp/plot_deps.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from pathlib import Path
2+
import re
3+
import graphviz as gv
4+
5+
dependencies = {}
6+
7+
for file in Path("etl/include").glob("**/*.h"):
8+
key = str(file).replace("etl/include/etl/", "")
9+
includes = [i.replace("../", "") for i in re.findall(r"#include +\"(.*?)\"", file.read_text())]
10+
dependencies[key] = includes
11+
# print(key, includes)
12+
13+
graph = gv.Digraph(name="deps",
14+
format="svg",
15+
graph_attr={"rankdir": "BT", "bgcolor": "transparent", "class": "deps"},
16+
node_attr={"style": "filled,solid", "shape": "box"})
17+
18+
def clean_name(name):
19+
return name.replace("/", "_").replace(".", "_")
20+
21+
for file, includes in dependencies.items():
22+
graph.node(clean_name(file), file, style="filled")
23+
for include in includes:
24+
graph.edge(clean_name(file), clean_name(include), style="solid")
25+
26+
svg = graph.pipe().decode("utf-8")
27+
print(svg)

src/modm/platform/gpio/pio/module.lb

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright (c) 2023, Niklas Hauser
5+
#
6+
# This file is part of the modm project.
7+
#
8+
# This Source Code Form is subject to the terms of the Mozilla Public
9+
# License, v. 2.0. If a copy of the MPL was not distributed with this
10+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
11+
# -----------------------------------------------------------------------------
12+
13+
class Instance(Module):
14+
def __init__(self, instance):
15+
self.instance = instance
16+
17+
def init(self, module):
18+
module.name = str(self.instance)
19+
module.description = "Instance {}".format(self.instance)
20+
21+
def prepare(self, module, options):
22+
return True
23+
24+
def build(self, env):
25+
env.substitutions = {"id": self.instance}
26+
env.outbasepath = "modm/src/modm/platform/pio"
27+
env.template("pio.hpp.in", "pio_{}.hpp".format(self.instance))
28+
29+
30+
def init(module):
31+
module.name = ":platform:pio"
32+
module.description = "Programmable I/O (PIO)"
33+
34+
35+
def prepare(module, options):
36+
module.depends(":platform:gpio")
37+
return options[":target"].has_driver("pio:rp*")
38+
39+
40+
def build(env):
41+
env.substitutions = {
42+
"target": env[":target"].identifier,
43+
"multicore_enabled": env.has_module(":platform:multicore"),
44+
}
45+
env.outbasepath = "modm/src/modm/platform/pio"
46+
env.copy("base.hpp")
47+

src/modm/platform/gpio/pio/module.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# General Purpose I/O (GPIO)
2+
3+
This module provides register access to GPIO and connect their signals to the
4+
respective peripherals in a compile-time verified way.
5+
6+
Each GPIO is represented as its own class with only static methods, which
7+
implement the `modm::GpioIO` interface and provide additional platform-specific
8+
methods.
9+
10+
```cpp
11+
using namespace modm::platform;
12+
13+
using Button = GpioInput0;
14+
Button::setInput(Gpio::InputType::PullUp);
15+
bool input = Button::read();
16+
17+
using Led = GpioInverted<GpioOuput3>; // inverts the IO logic of the pin
18+
19+
Led::setOutput(Gpio::OutputType::PushPull, Gpio::OutputSpeed::Fast);
20+
Led::set(input);
21+
22+
using Signal = Gpio4;
23+
Signal::setFunction(4); // For func id see datasheet
24+
Signal::disconnect(); // Switch back to floating input
25+
26+
using OpenDrain = GpioOpenDrain<Gpio5>;
27+
OpenDrain::setInput(Gpio::InputType::PullUp);
28+
OpenDrain::set(); // Input with Pullup
29+
OpenDrain::reset(); // Output with PushPull Low
30+
```
31+
32+
You can also use an unordered set of GPIOs, which is useful when configuring a
33+
large number of pins, since the register accesses will be bundled and thus less
34+
code is generated.
35+
36+
```cpp
37+
using Set = GpioSet<Gpio0, Gpio27, Gpio12, Gpio4>;
38+
Set::setInput();
39+
```
40+
41+
To write and read a set of GPIOs, you need to use an ordered implementation,
42+
which defines the pins from MSB to LSB, left-to-right. You can also check the
43+
number of ports in case your use-case requires atomic reads/writes.
44+
45+
```cpp
46+
using Port = SoftwareGpioPort<Gpio10, Gpio2, Gpio6, Gpio14>;
47+
static_assert(Port::number_of_ports == 1, "Read/write needs to be atomic");
48+
Port::setInput(Gpio::InputType::PullUp);
49+
uint8_t nibble = Port::read();
50+
Port::setOutput();
51+
Port::write(nibble);
52+
```
53+
54+
For efficient access you can use a strictly-ordered implementation with a start
55+
pin and width. Note that you can reverse the data order with a negative width.
56+
57+
```cpp
58+
using Port = GpioPort<Gpio0, 8>;
59+
Port::setOutput();
60+
Port::write(data);
61+
62+
using ReversePort = GpioPort<Gpio7, -8>;
63+
ReversePort::setInput();
64+
uint8_t data = ReversePort::read();
65+
```
66+
67+
Finally, you can use an empty GPIO implementation in cases where the API
68+
requires a GPIO, but you don't need one, for example, a bit-banged SPI without
69+
MISO pin:
70+
71+
```cpp
72+
// write only SPI
73+
using SPI = modm::platform::BitBangSpiMaster<Gpio0, Gpio1, GpioUnused>;
74+
```
75+
76+
77+
## Function Signals
78+
79+
To make it easier to connect pins with peripherals, this module implements a
80+
compile-time map of (pin, signal, peripheral) to Function ID (func).
81+
Note that you must provide both peripherals and signals to be unambiguous.
82+
83+
```cpp
84+
GpioConnector<Peripheral::Uart1, Gpio0::Tx, Gpio1::Rx>::connect();
85+
```
86+
87+
However, it is recommended to wrap this functionality into a separate function
88+
`Driver::connect<Signals...>(config)`, so that additional driver specific pin
89+
configuration can be done:
90+
91+
```cpp
92+
template< class... Signals >
93+
void Uart1::connect()
94+
{
95+
Connector = GpioConnector<Peripheral::Uart1, Signals...>;
96+
Connector::disconnect(); // reset to floating input
97+
98+
// extract pins from signals
99+
using Rx = Connector::GetSignal<Gpio::Signal::Rx>;
100+
using Tx = Connector::GetSignal<Gpio::Signal::Tx>;
101+
// if not found, returns GpioUnused, you can check for this case
102+
static_assert(not Connector::isValid<Tx>,
103+
"This UART driver requires the Tx signal");
104+
105+
// configure both pins
106+
Rx::configure(Gpio::InputType::PullUp);
107+
Tx::configure(Gpio::OutputType::PushPull);
108+
109+
// connect both pins to alternate functions
110+
// This will static assert if signals do not make sense
111+
Connector::connect();
112+
}
113+
// Connect these pin signals to Uart1
114+
Uart1::connect<Gpio0::Tx, Gpio1::Rx>();
115+
```
116+
117+
Note that you may pass a *variable* number of signals to this connect function,
118+
leaving out signals you don't need and adding signals that are not required.
119+
120+
```cpp
121+
// Connect only one signal
122+
Uart1::connect<Gpio0::Tx>();
123+
// Connect more signals than required
124+
Uart1::connect<Gpio0::Tx, Gpio2::Cts>();
125+
```
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2022, Andrey Kunitsyn
3+
* Copyright (c) 2022, Niklas Hauser
4+
*
5+
* This file is part of the modm project.
6+
*
7+
* This Source Code Form is subject to the terms of the Mozilla Public
8+
* License, v. 2.0. If a copy of the MPL was not distributed with this
9+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
10+
*/
11+
// ----------------------------------------------------------------------------
12+
13+
#pragma once
14+
15+
#include <cstdint>
16+
#include <span>
17+
#include <hardware/structs/pio.h>
18+
#include <modm/architecture/interface/register.hpp>
19+
20+
namespace modm::platform
21+
{
22+
23+
struct PioBase
24+
{
25+
26+
/// @ingroup modm_platform_platform
27+
struct Program
28+
{
29+
std::span<uint16_t> instructions;
30+
uint8_t wrap_target;
31+
uint8_t wrap;
32+
uint8_t side_set_count;
33+
bool side_set_optional;
34+
bool side_set_pindir;
35+
};
36+
37+
38+
39+
};
40+
41+
} // namespace modm::platform

0 commit comments

Comments
 (0)