Skip to content

Commit 6f8fc64

Browse files
committed
[I2S] Setup basic I2S driver template package
1 parent 4826ca8 commit 6f8fc64

File tree

6 files changed

+368
-0
lines changed

6 files changed

+368
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2009-2012, Fabian Greif
3+
* Copyright (c) 2010, Martin Rosekeit
4+
* Copyright (c) 2012-2015, Niklas Hauser
5+
* Copyright (c) 2013, Sascha Schade
6+
* Copyright (c) 2021, Marton Ledneczki
7+
*
8+
* This file is part of the modm project.
9+
*
10+
* This Source Code Form is subject to the terms of the Mozilla Public
11+
* License, v. 2.0. If a copy of the MPL was not distributed with this
12+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
13+
*/
14+
// ----------------------------------------------------------------------------
15+
16+
#ifndef MODM_INTERFACE_I2S_HPP
17+
#define MODM_INTERFACE_I2S_HPP
18+
19+
#include <modm/architecture/interface/peripheral.hpp>
20+
21+
namespace modm
22+
{
23+
24+
/// @ingroup modm_architecture_i2s
25+
struct I2s
26+
{
27+
/// The signature of the configuration function.
28+
using ConfigurationHandler = void(*)();
29+
};
30+
31+
} // namespace modm
32+
33+
#endif // MODM_INTERFACE_I2S_HPP
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
* Copyright (c) 2009-2012, Fabian Greif
3+
* Copyright (c) 2010, Martin Rosekeit
4+
* Copyright (c) 2012-2017, Niklas Hauser
5+
* Copyright (c) 2013, Sascha Schade
6+
* Copyright (c) 2021, Marton Lednczki
7+
*
8+
* This file is part of the modm project.
9+
*
10+
* This Source Code Form is subject to the terms of the Mozilla Public
11+
* License, v. 2.0. If a copy of the MPL was not distributed with this
12+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
13+
*/
14+
// ----------------------------------------------------------------------------
15+
16+
#ifndef MODM_INTERFACE_I2S_MASTER_HPP
17+
#define MODM_INTERFACE_I2S_MASTER_HPP
18+
19+
#include <modm/processing/resumable.hpp>
20+
#include "i2s.hpp"
21+
22+
namespace modm
23+
{
24+
25+
/**
26+
* Interface for a I2S Master
27+
*
28+
* @author Marton Ledneczki
29+
* @ingroup modm_architecture_i2s
30+
*/
31+
class I2sMaster : public ::modm::PeripheralDriver, public I2s
32+
{
33+
#ifdef __DOXYGEN__
34+
public:
35+
/**
36+
* Connect GPIOs to the peripheral and configure them.
37+
*
38+
* This configures the CK (serial clock), MCK (master clock),
39+
* SD (serial data) and WS (word select) signals and connects them.
40+
*
41+
* @tparam Signals
42+
* One CK, SD and WS signal are required
43+
* and can be passed out-of-order.
44+
*/
45+
template< class... Signals >
46+
static void
47+
connect();
48+
49+
/**
50+
* Initializes the hardware and sets the baudrate.
51+
*
52+
* @tparam SystemClock
53+
* the currently active system clock
54+
* @tparam baudrate
55+
* the desired baudrate in Hz
56+
* @tparam tolerance
57+
* the allowed relative tolerance for the resulting baudrate
58+
*/
59+
template< class SystemClock, baudrate_t baudrate, percent_t tolerance=5_pct >
60+
static void
61+
initialize();
62+
63+
/// Sets a new data mode.
64+
static void
65+
setDataMode(DataMode mode);
66+
67+
/// Sets a new data order.
68+
static void
69+
setDataOrder(DataOrder order);
70+
71+
/**
72+
* Request access to the spi master within a context.
73+
* You may acquire the spi master multiple times within the same context.
74+
*
75+
* The configuration handler will only be called when aquiring the spi
76+
* master for the first time (if it is not a `nullptr`).
77+
*
78+
* @warning Aquires must be balanced with releases of the **same** context!
79+
* @warning Aquires are persistent even after calling `initialize()`!
80+
*
81+
* @return `0` if another context is using the spi master, otherwise
82+
* `>0` as the number of times this context acquired the master.
83+
*/
84+
static uint8_t
85+
acquire(void *ctx, ConfigurationHandler handler = nullptr);
86+
87+
/**
88+
* Release access to the spi master within a context.
89+
*
90+
* @warning Releases must be balanced with acquires of the **same** context!
91+
* @warning Releases are persistent even after calling `initialize()`!
92+
*
93+
* @return `0` if nothing can be released anymore (for any context)
94+
* `>0` as the number of times this context can still release the master.
95+
*/
96+
static uint8_t
97+
release(void *ctx);
98+
99+
/**
100+
* Swap a single byte and wait for completion.
101+
*
102+
* @param data
103+
* data to be sent
104+
* @return received data
105+
*/
106+
static uint8_t
107+
transferBlocking(uint8_t data);
108+
109+
/**
110+
* Set the data buffers and length with options and starts a transfer.
111+
* This may be hardware accelerated (DMA or Interrupt), but not guaranteed.
112+
*
113+
* @param[in] tx
114+
* pointer to transmit buffer, set to `nullptr` to send dummy bytes
115+
* @param[out] rx
116+
* pointer to receive buffer, set to `nullptr` to discard received bytes
117+
* @param length
118+
* number of bytes to be shifted out
119+
*/
120+
static void
121+
transferBlocking(const uint8_t *tx, uint8_t *rx, std::size_t length);
122+
123+
/**
124+
* Swap a single byte and wait for completion non-blocking!.
125+
*
126+
* You must call this inside a Protothread or Resumable
127+
* using `PT_CALL` or `RF_CALL` respectively.
128+
* @warning These methods differ from Resumables by lacking context protection!
129+
* You must ensure that only one driver is accessing this resumable function
130+
* by using `acquire(ctx)` and `release(ctx)`.
131+
*
132+
* @param data
133+
* data to be sent
134+
* @return received data
135+
*/
136+
static modm::ResumableResult<uint8_t>
137+
transfer(uint8_t data);
138+
139+
/**
140+
* Set the data buffers and length with options and
141+
* starts a non-blocking transfer.
142+
* This may be hardware accelerated (DMA or Interrupt), but not guaranteed.
143+
*
144+
* You must call this inside a Protothread or Resumable
145+
* using `PT_CALL` or `RF_CALL` respectively.
146+
* @warning These methods differ from Resumables by lacking context protection!
147+
* You must ensure that only one driver is accessing this resumable function
148+
* by using `acquire(ctx)` and `release(ctx)`.
149+
*
150+
* @param[in] tx
151+
* pointer to transmit buffer, set to `nullptr` to send dummy bytes
152+
* @param[out] rx
153+
* pointer to receive buffer, set to `nullptr` to discard received bytes
154+
* @param length
155+
* number of bytes to be shifted out
156+
*/
157+
static modm::ResumableResult<void>
158+
transfer(const uint8_t *tx, uint8_t *rx, std::size_t length);
159+
#endif
160+
};
161+
162+
} // namespace modm
163+
164+
#endif // MODM_INTERFACE_SPI_MASTER_HPP

src/modm/architecture/module.lb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,21 @@ class I2cMultiplexer(Module):
230230
env.copy("interface/i2c_multiplexer.hpp")
231231
# -----------------------------------------------------------------------------
232232

233+
class I2s(Module):
234+
def init(self, module):
235+
module.name = "i2s"
236+
module.description = "Inter-IC Sound (I2S)"
237+
238+
def prepare(self, module, options):
239+
module.depends(":processing:resumable")
240+
return True
241+
242+
def build(self, env):
243+
env.outbasepath = "modm/src/modm/architecture"
244+
env.copy("interface/i2s.hpp")
245+
env.copy("interface/i2s_master.hpp")
246+
# -----------------------------------------------------------------------------
247+
233248
class Interrupt(Module):
234249
def init(self, module):
235250
module.name = "interrupt"
@@ -381,6 +396,7 @@ def prepare(module, options):
381396
module.add_submodule(I2c())
382397
module.add_submodule(I2cDevice())
383398
module.add_submodule(I2cMultiplexer())
399+
module.add_submodule(I2s())
384400
module.add_submodule(Interrupt())
385401
module.add_submodule(Memory())
386402
module.add_submodule(OneWire())

src/modm/board/disco_f407vg/module.lb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def prepare(module, options):
3131
":platform:gpio",
3232
":platform:i2c:1",
3333
":platform:spi:1",
34+
":platform:i2s:3",
3435
":platform:usb:fs")
3536
return True
3637

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (c) 2009-2011, Fabian Greif
3+
* Copyright (c) 2010, Martin Rosekeit
4+
* Copyright (c) 2011-2017, Niklas Hauser
5+
* Copyright (c) 2012, Georgi Grinshpun
6+
* Copyright (c) 2013, Kevin Läufer
7+
* Copyright (c) 2014, Sascha Schade
8+
* Copyright (C) 2021, Marton Ledneczki
9+
*
10+
* This file is part of the modm project.
11+
*
12+
* This Source Code Form is subject to the terms of the Mozilla Public
13+
* License, v. 2.0. If a copy of the MPL was not distributed with this
14+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
15+
*/
16+
// ----------------------------------------------------------------------------
17+
18+
#ifndef MODM_STM32_I2S_MASTER{{ id }}_HPP
19+
#define MODM_STM32_I2S_MASTER{{ id }}_HPP
20+
21+
#include <modm/architecture/interface/i2s_master.hpp>
22+
#include <modm/platform/gpio/connector.hpp>
23+
#include <modm/math/algorithm/prescaler.hpp>
24+
//#include "i2s_hal_{{ id }}.hpp" TODO
25+
26+
namespace modm
27+
{
28+
29+
namespace platform
30+
{
31+
32+
/**
33+
* Inter-IC Sound (I2C{{ id }}).
34+
*
35+
* TODO: say something about the nature of implementation
36+
*
37+
* @author Marton Ledneczki
38+
* @ingroup modm_platform_i2s modm_platform_i2s_{{id}}
39+
*/
40+
class I2sMaster{{ id }} : public modm::I2sMaster
41+
{
42+
public:
43+
//using Hal = I2sHal{{ id }}; TODO
44+
45+
//using DataSize = Hal::DataSize; TODO
46+
47+
public:
48+
template< template<Peripheral _> class... Signals >
49+
static void
50+
connect()
51+
{
52+
using Connector = GpioConnector<Peripheral::I2s{{ id }}, Signals...>;
53+
using Ck = typename Connector::template GetSignal<Gpio::Signal::Ck>;
54+
using Mck = typename Connector::template GetSignal<Gpio::Signal::Mck>;
55+
using Sd = typename Connector::template GetSignal<Gpio::Signal::Sd>;
56+
using Ws = typename Connector::template GetSignal<Gpio::Signal::Ws>;
57+
58+
// Connector::disconnect();
59+
Ck::setOutput(Gpio::OutputType::PushPull);
60+
Mck::setOutput(Gpio::OutputType::PushPull);
61+
Sd::setOutput(Gpio::OutputType::PushPull);
62+
Ws::setOutput(Gpio::OutputType::PushPull);
63+
Connector::connect();
64+
}
65+
66+
67+
// end documentation inherited
68+
};
69+
70+
} // namespace platform
71+
72+
} // namespace modm
73+
74+
#endif // MODM_STM32_I2S_MASTER{{ id }}_HPP
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright (c) 2016-2018, Niklas Hauser
5+
# Copyright (c) 2017, Fabian Greif
6+
# Copyright (c) 2021, Marton Ledneczki
7+
#
8+
# This file is part of the modm project.
9+
#
10+
# This Source Code Form is subject to the terms of the Mozilla Public
11+
# License, v. 2.0. If a copy of the MPL was not distributed with this
12+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
13+
# -----------------------------------------------------------------------------
14+
15+
def get_properties(env):
16+
device = env[":target"]
17+
driver = device.get_driver("i2s")
18+
properties = {}
19+
properties["target"] = device.identifier
20+
properties["features"] = driver["feature"] if "feature" in driver else []
21+
return properties
22+
23+
class Instance(Module):
24+
def __init__(self, driver, instance):
25+
self.instance = int(instance)
26+
self.driver = driver
27+
28+
def init(self, module):
29+
module.name = str(self.instance)
30+
module.description = "Instance {}".format(self.instance)
31+
32+
def prepare(self, module, options):
33+
module.depends(":platform:i2s")
34+
return True
35+
36+
def build(self, env):
37+
properties = get_properties(env)
38+
properties["id"] = self.instance
39+
40+
env.substitutions = properties
41+
env.outbasepath = "modm/src/modm/platform/i2s"
42+
43+
#env.template("i2s_hal.hpp.in", "i2s_hal_{}.hpp".format(self.instance))
44+
#env.template("i2s_hal_impl.hpp.in", "i2s_hal_{}_impl.hpp".format(self.instance))
45+
env.template("i2s_master.hpp.in", "i2s_master_{}.hpp".format(self.instance))
46+
#env.template("i2s_master.cpp.in", "i2s_master_{}.cpp".format(self.instance))
47+
if env.has_module(":platform:dma"):
48+
pass
49+
#env.template("i2s_master_dma.hpp.in", "i2s_master_{}_dma.hpp".format(self.instance))
50+
#env.template("i2s_master_dma_impl.hpp.in", "i2s_master_{}_dma_impl.hpp".format(self.instance))
51+
52+
53+
def init(module):
54+
module.name = ":platform:i2s"
55+
module.description = "Inter-IC Sound (I2S)"
56+
57+
def prepare(module, options):
58+
device = options[":target"]
59+
if not device.has_driver("i2s:stm32*"):
60+
return False
61+
62+
module.depends(
63+
":architecture:register",
64+
":architecture:i2s",
65+
":cmsis:device",
66+
":math:algorithm",
67+
":platform:gpio",
68+
":platform:rcc")
69+
70+
for driver in device.get_all_drivers("i2s:stm32*"):
71+
for instance in driver["instance"]:
72+
module.add_submodule(Instance(driver, instance))
73+
74+
return True
75+
76+
def build(env):
77+
env.substitutions = get_properties(env)
78+
env.outbasepath = "modm/src/modm/platform/i2s"
79+
80+
#env.template("i2s_base.hpp.in")

0 commit comments

Comments
 (0)