-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds basic polling driver for ADC, and updates the UART example to include ADC readings.
- Loading branch information
Showing
9 changed files
with
275 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
|
||
# Configure for ATSAMG55-XPRO dev board | ||
source [find interface/cmsis-dap.cfg] | ||
|
||
set CHIPNAME ATSAMG55J19 | ||
source [find target/at91samg5x.cfg] |
4 changes: 3 additions & 1 deletion
4
...ples/samg55_xplained_pro/uart/project.xml → .../samg55_xplained_pro/adc-uart/project.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,11 @@ | ||
<library> | ||
<extends>modm:samg55-xplained-pro</extends> | ||
<options> | ||
<option name="modm:build:build.path">../../../build/samg55_xplained_pro/uart</option> | ||
<option name="modm:build:build.path">../../../build/samg55_xplained_pro/adc-uart</option> | ||
<option name="modm:build:openocd.cfg">openocd.cfg</option> | ||
</options> | ||
<modules> | ||
<module>modm:build:scons</module> | ||
<module>modm:platform:adc</module> | ||
</modules> | ||
</library> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
/* | ||
* Copyright (c) 2021, Jeff McBride | ||
* | ||
* 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/. | ||
*/ | ||
#pragma once | ||
|
||
#include <modm/architecture/interface/adc.hpp> | ||
#include <modm/math/algorithm/prescaler.hpp> | ||
#include <modm/platform/clock/clockgen.hpp> | ||
#include <modm/platform/gpio/connector.hpp> | ||
|
||
|
||
namespace modm::platform | ||
{ | ||
|
||
class Adc : modm::Adc | ||
{ | ||
static const modm::frequency_t MaxAdcFrequency = modm::MHz(10); | ||
|
||
// Work around a name collision between 'struct modm::Adc' and 'struct Adc' | ||
// defined in the CMSIS headers | ||
static inline ::Adc* | ||
Regs() | ||
{ | ||
return (::Adc*)ADC; | ||
}; | ||
|
||
public: | ||
enum class Channel : uint8_t | ||
{ | ||
Ch0 = 0, | ||
Ch1, | ||
Ch2, | ||
Ch3, | ||
Ch4, | ||
Ch5, | ||
Ch6, | ||
Ch7 | ||
}; | ||
|
||
/** Analog settling time setting | ||
* | ||
* Controls how many periods of ADC clock are allowed for input to settle. | ||
*/ | ||
enum class SettlingTime : uint8_t | ||
{ | ||
AST3 = 0, | ||
AST5, | ||
AST9, | ||
AST17 | ||
}; | ||
|
||
public: | ||
// start inherited documentation | ||
template<class Pin, class... Pins> | ||
static inline void | ||
connect() | ||
{ | ||
// Pins are automatically connected to the ADC when they are enabled, | ||
// so all this does is set the pin mode to input. | ||
using Connector = typename Pin::template Connector<Peripherals::Adc, Peripherals::Adc::Ad>; | ||
static_assert(Connector::PinSignal::AdcChannel >= 0, "Pin cannot be used as ADC input"); | ||
Pin::setInput(); | ||
|
||
// Call recursively for all Pins | ||
if constexpr (sizeof...(Pins)) { connect<Pins...>(); } | ||
} | ||
|
||
template<class SystemClock, frequency_t frequency = MHz(10), percent_t tolerance = pct(10)> | ||
static inline void | ||
initialize() | ||
{ | ||
constexpr auto result = modm::Prescaler::from_function( | ||
SystemClock::Frequency, // input frequency | ||
frequency, // desired adc frequency | ||
0, // lowest prescaler value | ||
255, // highest prescaler value | ||
[](uint32_t x) { return 2 * (x + 1); } // transform function | ||
); | ||
static_assert(result.frequency <= MaxAdcFrequency, | ||
"Generated ADC frequency is above maximum frequency!"); | ||
assertBaudrateInTolerance<result.frequency, frequency, tolerance>(); | ||
|
||
ClockGen::enable<ClockPeripheral::Adc>(); | ||
|
||
Regs()->ADC_MR = ADC_MR_PRESCAL(result.index) | ADC_MR_TRANSFER(2); | ||
} | ||
|
||
static inline void | ||
startConversion() | ||
{ | ||
Regs()->ADC_CR = ADC_CR_START; | ||
} | ||
|
||
static inline bool | ||
isConversionFinished() | ||
{ | ||
return Regs()->ADC_ISR & ADC_ISR_DRDY; | ||
} | ||
|
||
static inline uint16_t | ||
getValue() | ||
{ | ||
return (uint16_t)(Regs()->ADC_LCDR & 0xffff); | ||
} | ||
|
||
static inline uint16_t | ||
readChannel(uint8_t channel) | ||
{ | ||
if (!setChannel(channel)) return 0; | ||
|
||
startConversion(); | ||
while (!isConversionFinished()) {} | ||
|
||
return getValue(); | ||
} | ||
|
||
static inline bool | ||
setChannel(Channel channel) | ||
{ | ||
return setChannel((uint8_t)channel); | ||
} | ||
|
||
static inline bool | ||
setChannel(uint8_t channel) | ||
{ | ||
if (channel > 7) return false; | ||
Regs()->ADC_CHDR = 0xff; | ||
Regs()->ADC_CHER = (1 << channel); | ||
return true; | ||
} | ||
|
||
static inline void | ||
enableFreeRunningMode() | ||
{ | ||
Regs()->ADC_MR |= ADC_MR_FREERUN; | ||
} | ||
|
||
static inline void | ||
disableFreeRunningMode() | ||
{ | ||
Regs()->ADC_MR &= ~ADC_MR_FREERUN; | ||
} | ||
|
||
// end inherited documentation | ||
|
||
/** Configure the amount of time the ADC input is allowed to settle before sampling | ||
*/ | ||
static inline void | ||
setSettlingTime(SettlingTime time) | ||
{ | ||
Regs()->ADC_MR = (Regs()->ADC_MR & ~ADC_MR_SETTLING_Msk) | ADC_MR_SETTLING((uint8_t)time); | ||
} | ||
|
||
template<class Pin> | ||
static inline constexpr uint8_t | ||
getPinChannel() | ||
{ | ||
using Connector = typename Pin::template Connector<Peripherals::Adc, Peripherals::Adc::Ad>; | ||
static_assert(Connector::PinSignal::AdcChannel >= 0, "Pin cannot be used as ADC input"); | ||
return Connector::PinSignal::AdcChannel; | ||
} | ||
}; | ||
|
||
} // namespace modm::platform |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#!/usr/bin/env python3 | ||
# -*- coding: utf-8 -*- | ||
# | ||
# Copyright (c) 2021, Jeff McBride | ||
# | ||
# 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 = ":platform:adc" | ||
module.description = "Analog-to-Digital Converter (ADC)" | ||
|
||
def prepare(module, options): | ||
device = options[":target"] | ||
if not device.has_driver("adc:samg*"): | ||
return False | ||
global props | ||
props = {} | ||
driver = device.get_driver("adc") | ||
props["target"] = device.identifier | ||
props["driver"] = driver | ||
props["instances"] = [] | ||
|
||
module.depends( | ||
":architecture:adc", | ||
":architecture:register", | ||
":cmsis:device", | ||
":platform:gpio", | ||
":platform:clockgen", | ||
":math:algorithm", | ||
":utils") | ||
|
||
return True | ||
|
||
def build(env): | ||
env.outbasepath = "modm/src/modm/platform/adc" | ||
|
||
env.copy("adc.hpp") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters