Skip to content

Commit

Permalink
[adc] Add STM32F0 support
Browse files Browse the repository at this point in the history
  • Loading branch information
cajt authored and salkinium committed Nov 26, 2018
1 parent 529d28b commit 79b6828
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 33 deletions.
29 changes: 18 additions & 11 deletions src/modm/platform/adc/stm32f0/adc.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/*
* Copyright (c) 2018, Niklas Hauser
* Copyright (c) 2018, Álan Crístoffer
* Copyright (c) 2018, Carl Treudler
*
* This file is part of the modm project.
*
Expand All @@ -15,14 +16,13 @@
#define MODM_STM32F0_ADC_HPP

#include <stdint.h>
#include "../../../type_ids.hpp"
#include "../../../device.hpp"
#include "../device.hpp"
#include <modm/architecture/interface/register.hpp>

#include <modm/platform/gpio/connector.hpp>

namespace modm
{
namespace stm32
namespace platform
{
/**
* Analog/Digital-Converter module (ADC1).
Expand All @@ -46,15 +46,11 @@ public:
* This code was generated using the family datasheet, but not all devices in the
* family have 16 channels.
*/
%% for channel in range(0,16)
/// TypeId used to connect GPIO pins to this adc's Channel{{ channel }}.
static const TypeId::AdcChannel{{ channel }} Channel{{ channel }};
%% endfor

/// Channels, which can be used with this ADC.
enum class Channel : uint8_t
{
%% for channel in range(0,16)
%% for channel in channels
Channel{{ channel }} = {{ channel }},
%% endfor
%#
Expand Down Expand Up @@ -123,6 +119,17 @@ public:
};
MODM_FLAGS32(InterruptFlag);

public:
// start inherited documentation
template< template<Peripheral _> class... Signals >
static void
connect()
{
using Connector = GpioConnector<Peripheral::Adc, Signals...>;
Connector::connect();
}


/**
* Initialize and enable the A/D converter.
*
Expand Down Expand Up @@ -205,8 +212,8 @@ public:
static inline constexpr Channel
getPinChannel()
{
constexpr int8_t channel{Gpio::template AdcChannel<Peripheral::Adc{{ id }}>};
static_assert(channel >= 0, "Adc{{id}} does not have a channel for this pin!");
constexpr int8_t channel{Gpio::template AdcChannel<Peripheral::Adc>};
static_assert(channel >= 0, "Adc does not have a channel for this pin!");
return Channel(channel);
}

Expand Down
43 changes: 21 additions & 22 deletions src/modm/platform/adc/stm32f0/adc_impl.hpp.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// coding: utf-8
/*
* Copyright (c) 2018, Álan Crístoffer
* Copyright (c) 2018, Carl Treudler
*
* This file is part of the modm project.
*
Expand All @@ -11,13 +12,11 @@
// ----------------------------------------------------------------------------

#ifndef MODM_STM32F0_ADC_HPP
# error "Don't include this file directly, use 'adc_{{ id }}.hpp' instead!"
# error "Don't include this file directly, use 'adc.hpp' instead!"
#endif

#include <modm/architecture/driver/delay.hpp> // modm::delayMicroseconds

uint16_t
modm::stm32::Adc::initialize(const ClockMode clk,
modm::platform::Adc::initialize(const ClockMode clk,
const CalibrationMode cal)
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
Expand All @@ -31,7 +30,7 @@ modm::stm32::Adc::initialize(const ClockMode clk,
ADC1->CFGR2 |= static_cast<uint32_t>(clk);
}

uint16_t calibrationResult = modm::stm32::Adc::calibrate(cal);
uint16_t calibrationResult = modm::platform::Adc::calibrate(cal);

ADC1->ISR |= ADC_ISR_ADRDY; // ISR is cleared by setting 1 to the bit
ADC1->CR |= ADC_CR_ADEN;
Expand All @@ -43,15 +42,15 @@ modm::stm32::Adc::initialize(const ClockMode clk,
}

void
modm::stm32::Adc::disable(const bool blocking)
modm::platform::Adc::disable(const bool blocking)
{
ADC1->CR |= ADC_CR_ADDIS;
while ( blocking && (ADC1->CR & ADC_CR_ADEN) != 0 )
;
}

void
modm::stm32::Adc::setAutoOffMode(const bool enable)
modm::platform::Adc::setAutoOffMode(const bool enable)
{
if (enable) {
ADC1->CFGR1 |= ADC_CFGR1_AUTOFF;
Expand All @@ -61,13 +60,13 @@ modm::stm32::Adc::setAutoOffMode(const bool enable)
}

bool
modm::stm32::Adc::isReady()
modm::platform::Adc::isReady()
{
return static_cast<bool>(getInterruptFlags() & InterruptFlag::Ready);
}

uint16_t
modm::stm32::Adc::calibrate(const CalibrationMode mode)
modm::platform::Adc::calibrate(const CalibrationMode mode)
{
if (mode != CalibrationMode::DoNotCalibrate) {
if ( (ADC1->CR & ADC_CR_ADEN) != 0 ) {
Expand All @@ -89,7 +88,7 @@ modm::stm32::Adc::calibrate(const CalibrationMode mode)
}

void
modm::stm32::Adc::setDataAlignmentAndResolution(const DataAlignment align,
modm::platform::Adc::setDataAlignmentAndResolution(const DataAlignment align,
const Resolution res)
{
ADC1->CFGR1 = static_cast<uint32_t>(align) |
Expand All @@ -98,7 +97,7 @@ modm::stm32::Adc::setDataAlignmentAndResolution(const DataAlignment align,
}

bool
modm::stm32::Adc::setChannel(const Channel channel,
modm::platform::Adc::setChannel(const Channel channel,
const SampleTime sampleTime)
{
if(static_cast<uint32_t>(channel) > 18) {
Expand All @@ -118,7 +117,7 @@ modm::stm32::Adc::setChannel(const Channel channel,
}

void
modm::stm32::Adc::clearChannel(const Channel channel)
modm::platform::Adc::clearChannel(const Channel channel)
{
ADC1->CHSELR &= ~(1 << static_cast<uint32_t>(channel));
if (channel == Channel::InternalReference) {
Expand All @@ -129,7 +128,7 @@ modm::stm32::Adc::clearChannel(const Channel channel)
}

void
modm::stm32::Adc::setFreeRunningMode(const bool enable)
modm::platform::Adc::setFreeRunningMode(const bool enable)
{
if (enable) {
ADC1->CFGR1 |= ADC_CFGR1_CONT;
Expand All @@ -139,7 +138,7 @@ modm::stm32::Adc::setFreeRunningMode(const bool enable)
}

void
modm::stm32::Adc::startConversion(void)
modm::platform::Adc::startConversion(void)
{
acknowledgeInterruptFlag(InterruptFlag::EndOfConversion |
InterruptFlag::EndOfSampling |
Expand All @@ -151,13 +150,13 @@ modm::stm32::Adc::startConversion(void)
}

bool
modm::stm32::Adc::isConversionFinished(void)
modm::platform::Adc::isConversionFinished(void)
{
return static_cast<bool>(getInterruptFlags() & InterruptFlag::EndOfSampling);
}

void
modm::stm32::Adc::enableInterruptVector(const uint32_t priority,
modm::platform::Adc::enableInterruptVector(const uint32_t priority,
const bool enable)
{
if (enable) {
Expand All @@ -169,33 +168,33 @@ modm::stm32::Adc::enableInterruptVector(const uint32_t priority,
}

void
modm::stm32::Adc::enableInterrupt(const Interrupt_t interrupt)
modm::platform::Adc::enableInterrupt(const Interrupt_t interrupt)
{
ADC1->IER |= interrupt.value;
}

void
modm::stm32::Adc::disableInterrupt(const Interrupt_t interrupt)
modm::platform::Adc::disableInterrupt(const Interrupt_t interrupt)
{
ADC1->IER &= ~interrupt.value;
}

modm::stm32::Adc::InterruptFlag_t
modm::stm32::Adc::getInterruptFlags()
modm::platform::Adc::InterruptFlag_t
modm::platform::Adc::getInterruptFlags()
{
return InterruptFlag_t(ADC1->ISR);
}

void
modm::stm32::Adc::acknowledgeInterruptFlag(const InterruptFlag_t flags)
modm::platform::Adc::acknowledgeInterruptFlag(const InterruptFlag_t flags)
{
// Flags are cleared by writing a one to the flag position.
// Writing a zero is ignored.
ADC1->ISR = flags.value;
}

void
modm::stm32::Adc::setWaitMode(const bool enable)
modm::platform::Adc::setWaitMode(const bool enable)
{
if (enable) {
ADC1->CFGR1 |= ADC_CFGR1_WAIT;
Expand Down
47 changes: 47 additions & 0 deletions src/modm/platform/adc/stm32f0/module.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016-2018, Niklas Hauser
# Copyright (c) 2017, Fabian Greif
# Copyright (c) 2018, Carl Treudler
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------

def init(module):
module.name = "adc"
module.parent = "platform"
module.description = "Analog-to-Digital Converter (ADC)"

def prepare(module, options):
device = options[":target"]
if not device.has_driver("adc:stm32-f0"):
return False
module.depends(
":architecture:delay",
":architecture:register",
":cmsis:device",
":platform:gpio")
return True

def build(env):
device = env[":target"]
driver = device.get_driver("adc")

properties = device.properties
properties["target"] = device.identifier
properties["driver"] = driver
#properties["id"] = 1

channels = range(0,16)
properties["channels"] = sorted(channels)

env.substitutions = properties
env.outbasepath = "modm/src/modm/platform/adc"

env.template("adc.hpp.in", "adc.hpp")
env.template("adc_impl.hpp.in", "adc_impl.hpp")
1 change: 1 addition & 0 deletions src/modm/platform/gpio/stm32/pin.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class Gpio{{ port ~ pin }} : public Gpio, public ::modm::GpioIO
template<class... Gpios>
friend class GpioSet;
using PinSet = GpioSet<Gpio{{ port ~ pin }}>;
friend class Adc;
friend class Adc1; friend class Adc2;
friend class Adc3; friend class Adc4;
public:
Expand Down

0 comments on commit 79b6828

Please sign in to comment.