Skip to content

Commit

Permalink
[dac] Add basic STM32F4 driver
Browse files Browse the repository at this point in the history
  • Loading branch information
mcbridejc authored and salkinium committed Jun 19, 2020
1 parent 21af57b commit 78d18f6
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 0 deletions.
123 changes: 123 additions & 0 deletions src/modm/platform/dac/stm32/dac.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#ifndef MODM_STM32_DAC_HPP
#define MODM_STM32_DAC_HPP

#include <stdint.h>
#include "../device.hpp"
#include <modm/platform/gpio/connector.hpp>

namespace modm {

namespace platform {

/**
* Digital-to-Analog Converter (DAC)
*
* Supports simple synchronous access to the 2-channel DAC found on most STM32
* microcontrollers.
*
* @author Jeff McBride
* @ingroup modm_platform_dac
*/
class Dac {
public:
/**
* The DAC has two output channels, Channel1 and Channel2
*/
enum class Channel : uint8_t {
Channel1 = 0,
Channel2 = 1
};

template< template<Peripheral _> class... Signals >
static void
connect()
{
using Connector = GpioConnector<Peripheral::Dac, Signals...>;
Connector::connect();
}

/**
* Initialize the D/A converter.
*
* Enables the RCC clock output for the DAC
*/
static inline void initialize();

/** Enable DAC output for the given channel
*
* @param chan The channel to be enabled
*
* @pre The DAC clock must be enabled with initialize()
*/
static inline void enableChannel(Channel chan);

/**
* Disable DAC output for the given channel
*
* @param chan The channel to be disabled
*
* @pre The DAC clock must be enabled with initialize()
*/
static inline void disableChannel(Channel chan);

/**
* Control the output buffer setting
*
* @param chan The channel to enable/disable the output buffer on
* @param enable true to turn on the output buffer, false to turn it off
*
* @pre The DAC clock must be enabled with initialize()
*/
static inline void enableOutputBuffer(Channel chan, bool enable);

/**
* Set the output voltage for a DAC channel
*
* @param chan The channel to set
* @param value The 12-bit DAC output value, range 0-4095.
*
* @pre The DAC clock must be enabled with initialize()
*/
static inline void setOutput(Channel chan, uint16_t value);

/**
* Set output value for Channel1
*
* Equivalent to setOutput(modm::platform::Dac::Channel1, value)
*
* @param value The 12-bit DAC output value, range 0-4095
*
* @pre The DAC clock must be enabled with initialize()
*/
static inline void setOutput1(uint16_t value);

/**
* Set output value for Channel2
*
* Equivalent to setOutput(modm::platform::Dac::Channel2, value)
*
* @param value The 12-bit DAC output value, range 0-4095
*
* @pre The DAC clock must be enabled with initialize()
*/
static inline void setOutput2(uint16_t value);

/// Get the channel for a Pin
template< class Gpio >
static inline constexpr Channel
getPinChannel()
{
constexpr int8_t channel{Gpio::template DacChannel<Peripheral::Dac>};
static_assert(channel >= 0, "Dac does not have a channel for this pin!");
return Channel(channel);
}

};

} // namespace platform

} // namespace modm

#include "dac_impl.hpp"

#endif // MODM_STM32_DAC_HPP
68 changes: 68 additions & 0 deletions src/modm/platform/dac/stm32/dac_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#ifndef MODM_STM32_DAC_HPP
# error "Don't include this file directly, use 'dac.hpp' instead!"
#endif

#include <modm/platform/clock/rcc.hpp>

void modm::platform::Dac::initialize() {
Rcc::enable<Peripheral::Dac>();
}

void modm::platform::Dac::enableChannel(Channel chan) {
switch(chan) {
case Channel::Channel1:
DAC1->CR |= DAC_CR_EN1_Msk;
break;
case Channel::Channel2:
DAC1->CR |= DAC_CR_EN2_Msk;
break;
}
}

void modm::platform::Dac::disableChannel(Channel chan) {
switch(chan) {
case Channel::Channel1:
DAC1->CR &= ~DAC_CR_EN1_Msk;
break;
case Channel::Channel2:
DAC1->CR &= ~DAC_CR_EN2_Msk;
break;
}
}

void modm::platform::Dac::enableOutputBuffer(Channel chan, bool enable) {
uint32_t chanShift = 0;
switch(chan) {
case Channel::Channel1:
chanShift = 0;
break;
case Channel::Channel2:
chanShift = 16;
break;
};

if(enable) {
DAC1->CR &= ~(DAC_CR_BOFF1_Msk << chanShift);
} else {
DAC1->CR |= DAC_CR_BOFF1_Msk << chanShift;
}
}

void modm::platform::Dac::setOutput(Channel chan, uint16_t value) {
switch(chan) {
case Channel::Channel1:
DAC1->DHR12R1 = value & DAC_DHR12R1_DACC1DHR_Msk;
break;
case Channel::Channel2:
DAC1->DHR12R2 = value & DAC_DHR12R2_DACC2DHR_Msk;
break;
}
}

void modm::platform::Dac::setOutput1(uint16_t value) {
setOutput(Channel::Channel1, value);
}

void modm::platform::Dac::setOutput2(uint16_t value) {
setOutput(Channel::Channel2, value);
}
24 changes: 24 additions & 0 deletions src/modm/platform/dac/stm32/module.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os

def init(module):
module.name = ":platform:dac"
module.description = "Digital-to-Analog Converter (DAC)"

def prepare(module, options):
if not options[":target"].has_driver("dac:stm32"):
return False

if not options[":target"].identifier.family == 'f4':
return False

module.depends(":cmsis:device")

return True

def build(env):
env.outbasepath = "modm/src/modm/platform/dac"
env.copy("dac.hpp")
env.copy("dac_impl.hpp")
9 changes: 9 additions & 0 deletions src/modm/platform/gpio/stm32/pin.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ public:
private:
template< Peripheral peripheral >
static constexpr int8_t AdcChannel = -1;
template< Peripheral peripheral >
static constexpr int8_t DacChannel = -1;
};

/// @cond
Expand Down Expand Up @@ -245,6 +247,13 @@ template<>
constexpr int8_t
Gpio{{ port ~ pin }}::AdcChannel<Peripheral::{{ signal.driver }}> = {{ signal.name | to_adc_channel }};
%% endif

%% if signal.driver.startswith("Dac") and signal.name.startswith("Out")
template<>
constexpr int8_t
Gpio{{ port ~ pin }}::DacChannel<Peripheral::{{ signal.driver }}> = {{ signal.name | to_adc_channel }};
%% endif

%% endfor

%% endfor
Expand Down

0 comments on commit 78d18f6

Please sign in to comment.