Skip to content

Use safe clock freqs for AnalogOut; use DAC REFRESH on SAMD51. #649

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions ports/atmel-samd/asf4_conf/samd21/hpl_gclk_config.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Circuit Python SAMD21 clock tree:
// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK0
// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK0, GCLK1
// GCLK0 (48MHz) -> peripherals
// GLCK1 (48MHz divided by 150 = 320Khz) -> DAC peripheral (DAC requires 350KHz or lower)

// We'd like to use XOSC32K as a ref for DFLL48M on boards with a 32kHz crystal,
// but haven't figured that out yet.

// Used in hpl/core/hpl_init.c to define which clocks should be initialized first.
#define CIRCUITPY_GCLK_INIT_1ST (1 << 0)
#define CIRCUITPY_GCLK_INIT_1ST (1 << 0 | 1 << 1)


/* Auto-generated config file hpl_gclk_config.h */
Expand Down Expand Up @@ -127,7 +128,7 @@
// <i> Indicates whether Output Enable is enabled or not
// <id> gclk_arch_gen_1_oe
#ifndef CONF_GCLK_GEN_1_OE
#define CONF_GCLK_GEN_1_OE 0
#define CONF_GCLK_GEN_1_OE 1
#endif

// <q> Output Off Value
Expand Down Expand Up @@ -172,7 +173,7 @@
// <i> This defines the clock source for generic clock generator 1
// <id> gclk_gen_1_oscillator
#ifndef CONF_GCLK_GEN_1_SRC
#define CONF_GCLK_GEN_1_SRC GCLK_GENCTRL_SRC_XOSC32K
#define CONF_GCLK_GEN_1_SRC GCLK_GENCTRL_SRC_DFLL48M
#endif
// </h>

Expand All @@ -181,7 +182,7 @@
// <i>
// <id> gclk_gen_1_div
#ifndef CONF_GCLK_GEN_1_DIV
#define CONF_GCLK_GEN_1_DIV 1
#define CONF_GCLK_GEN_1_DIV 150
#endif

// </h>
Expand Down
4 changes: 2 additions & 2 deletions ports/atmel-samd/asf4_conf/samd21/peripheral_clk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -385,15 +385,15 @@

// <i> Select the clock source for DAC.
#ifndef CONF_GCLK_DAC_SRC
#define CONF_GCLK_DAC_SRC GCLK_CLKCTRL_GEN_GCLK0_Val
#define CONF_GCLK_DAC_SRC GCLK_CLKCTRL_GEN_GCLK1_Val
#endif

/**
* \def CONF_GCLK_DAC_FREQUENCY
* \brief DAC's Clock frequency
*/
#ifndef CONF_GCLK_DAC_FREQUENCY
#define CONF_GCLK_DAC_FREQUENCY 48000000
#define CONF_GCLK_DAC_FREQUENCY 320000
#endif

// <y> USB Clock Source
Expand Down
4 changes: 2 additions & 2 deletions ports/atmel-samd/asf4_conf/samd51/hpl_dac_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
// <i> This defines the refresh period. If it is 0, the refresh mode is disabled, else the refresh period is: value * 500us
// <id> dac0_arch_refresh
#ifndef CONF_DAC0_REFRESH
#define CONF_DAC0_REFRESH 0
#define CONF_DAC0_REFRESH 2
#endif
// </h>
// <h> Channel 1 configuration
Expand Down Expand Up @@ -111,7 +111,7 @@
// <i> This defines the refresh period. If it is 0, the refresh mode is disabled, else the refresh period is: value * 500us
// <id> dac1_arch_refresh
#ifndef CONF_DAC1_REFRESH
#define CONF_DAC1_REFRESH 0
#define CONF_DAC1_REFRESH 2
#endif
// </h>

Expand Down
4 changes: 2 additions & 2 deletions ports/atmel-samd/asf4_conf/samd51/hpl_gclk_config.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Circuit Python SAMD51 clock tree:
// DFLL48M (with USBCRM on to sync with external USB ref) -> GCLK1, GCLK5
// GCLK1 (48MHz) -> peripherals
// GCLK5 (divided down to 2 MHz) -> DPLL0
// GCLK1 (48MHz) -> 48 MHz peripherals
// GCLK5 (48 MHz divided down to 2 MHz) -> DPLL0, DAC peripherals
// DPLL0 (multiplied up to 120 MHz) -> GCLK0, GCLK4 (output for monitoring)

// We'd like to use XOSC32K as a ref for DFLL48M on boards with a 32kHz crystal,
Expand Down
4 changes: 2 additions & 2 deletions ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@
// <id> dac_gclk_selection
// <i> Select the clock source for DAC.
#ifndef CONF_GCLK_DAC_SRC
#define CONF_GCLK_DAC_SRC GCLK_PCHCTRL_GEN_GCLK1_Val
#define CONF_GCLK_DAC_SRC GCLK_PCHCTRL_GEN_GCLK5_Val
#endif

/**
* \def CONF_GCLK_DAC_FREQUENCY
* \brief DAC's Clock frequency
*/
#ifndef CONF_GCLK_DAC_FREQUENCY
#define CONF_GCLK_DAC_FREQUENCY 48000000
#define CONF_GCLK_DAC_FREQUENCY 2000000
#endif

// <y> EVSYS Channel 0 Clock Source
Expand Down
9 changes: 6 additions & 3 deletions ports/atmel-samd/common-hal/analogio/AnalogOut.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "atmel_start_pins.h"
#include "hal/include/hal_dac_sync.h"
#include "hpl/gclk/hpl_gclk_base.h"
#include "peripheral_clk_config.h"

#ifdef SAMD21
#include "hpl/pm/hpl_pm_base.h"
Expand Down Expand Up @@ -65,14 +66,16 @@ void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self,

#ifdef SAMD51
hri_mclk_set_APBDMASK_DAC_bit(MCLK);
hri_gclk_write_PCHCTRL_reg(GCLK, DAC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK5_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
#endif

#ifdef SAMD21
_pm_enable_bus_clock(PM_BUS_APBC, DAC);
_gclk_enable_channel(DAC_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
#endif

// SAMD21: This clock should be <= 12 MHz, per datasheet section 47.6.3.
// SAMD51: This clock should be <= 350kHz, per datasheet table 37-6.
_gclk_enable_channel(DAC_GCLK_ID, CONF_GCLK_DAC_SRC);

// Don't double init the DAC on the SAMD51 when both outputs are in use. We use the free state
// of each output pin to determine DAC state.
int32_t result = ERR_NONE;
Expand Down Expand Up @@ -123,7 +126,7 @@ void common_hal_analogio_analogout_deinit(analogio_analogout_obj_t *self) {

void common_hal_analogio_analogout_set_value(analogio_analogout_obj_t *self,
uint16_t value) {
// Input is 16 bit so make sure and set LEFTADJ to 1 to it takes the top
// Input is 16 bit so make sure and set LEFTADJ to 1 so it takes the top
// bits. This is currently done in asf4_conf/*/hpl_dac_config.h.
dac_sync_write(&self->descriptor, self->channel, &value, 1);
}
Expand Down