Пример #1
0
/**
 * \brief Enable the DAC module.
 *
 * Enables the DAC interface and the selected output. If any internal reference
 * is selected it will be enabled.
 *
 * \param[in] module_inst  Pointer to the DAC software instance struct
 *
 */
void dac_enable(
		struct dac_module *const module_inst)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(module_inst->hw);

	Dac *const dac_module = module_inst->hw;

	/* Enable selected output */
	dac_module->CTRLB.reg |= module_inst->output;

	while (dac_is_syncing(module_inst)) {
		/* Wait until the synchronization is complete */
	}

	/* Enable the module */
	dac_module->CTRLA.reg |= DAC_CTRLA_ENABLE;

	/* Enable internal bandgap reference if selected in the configuration */
	if (module_inst->reference == DAC_REFERENCE_INT1V) {
#if (SAMC21)
		system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_OUTPUT);
	}

	if(dac_module->CTRLA.reg & DAC_CTRLA_ENABLE) {
		while(! (dac_module->STATUS.reg & DAC_STATUS_READY)) {
		};
	}
#else
		system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_BANDGAP);
	}
Пример #2
0
/**
 * \brief Write to the DAC.
 *
 * This function writes to the DATA or DATABUF register.
 * If the conversion is not event-triggered, the data will be written to
 * the DATA register and the conversion will start.
 * If the conversion is event-triggered, the data will be written to DATABUF
 * and transferred to the DATA register and converted when a Start Conversion
 * Event is issued.
 * Conversion data must be right or left adjusted according to configuration
 * settings.
 * \note To be event triggered, the enable_start_on_event must be
 * enabled in the configuration.
 *
 * \param[in] module_inst      Pointer to the DAC software device struct
 * \param[in] channel          DAC channel to write to
 * \param[in] data             Conversion data
 *
 * \return Status of the operation.
 * \retval STATUS_OK           If the data was written
 */
enum status_code dac_chan_write(
		struct dac_module *const module_inst,
		enum dac_channel channel,
		const uint16_t data)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(module_inst->hw);

	Dac *const dac_module = module_inst->hw;

	while (dac_is_syncing(module_inst)) {
		/* Wait until the synchronization is complete */
	}

	if (module_inst->start_on_event[channel]) {
		/* Write the new value to the buffered DAC data register */
		dac_module->DATABUF[channel].reg = data;
	} else {
		/* Write the new value to the DAC data register */
		dac_module->DATA[channel].reg = data;
	}

	return STATUS_OK;
}
Пример #3
0
/**
 * \brief Enable the DAC module.
 *
 * Enables the DAC interface and the selected output. If any internal reference
 * is selected it will be enabled.
 *
 * \param[in] module_inst  Pointer to the DAC software instance struct
 *
 */
void dac_enable(
		struct dac_module *const module_inst)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(module_inst->hw);

	Dac *const dac_module = module_inst->hw;

	while (dac_is_syncing(module_inst)) {
		/* Wait until the synchronization is complete */
	}

	/* Enable the module */
	dac_module->CTRLA.reg |= DAC_CTRLA_ENABLE;

	/* Enable internal bandgap reference if selected in the configuration */
	if (module_inst->reference == DAC_REFERENCE_INTREF) {
		system_voltage_reference_enable(SYSTEM_VOLTAGE_REFERENCE_OUTPUT);
	}

	if(dac_module->DACCTRL[DAC_CHANNEL_0].reg & DAC_DACCTRL_ENABLE) {
		while(! (dac_module->STATUS.reg & DAC_STATUS_READY(DAC_CHANNEL_0 + 1))) {
		};
	} else if(dac_module->DACCTRL[DAC_CHANNEL_1].reg & DAC_DACCTRL_ENABLE) {
		while(! (dac_module->STATUS.reg & DAC_STATUS_READY(DAC_CHANNEL_1 + 1))) {
		};
	}
}
Пример #4
0
/**
 * \brief Write to the DAC.
 *
 * This function converts a specific number of digital data.
 * The conversion should be event-triggered, the data will be written to DATABUF
 * and transferred to the DATA register and converted when a Start Conversion
 * Event is issued.
 * Conversion data must be right or left adjusted according to configuration
 * settings.
 * \note To be event triggered, the enable_start_on_event must be
 * enabled in the configuration.
 *
 * \param[in] module_inst      Pointer to the DAC software device struct
 * \param[in] channel          DAC channel to write to
 * \param[in] buffer             Pointer to the digital data write buffer to be converted
 * \param[in] length             Length of the write buffer
 *
 * \return Status of the operation.
 * \retval STATUS_OK           If the data was written or no data conversion required
 * \retval STATUS_ERR_UNSUPPORTED_DEV  The DAC is not configured as using
 *                                         event trigger
 * \retval STATUS_BUSY      The DAC is busy to convert
 */
enum status_code dac_chan_write_buffer_wait(
		struct dac_module *const module_inst,
		enum dac_channel channel,
		uint16_t *buffer,
		uint32_t length)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(module_inst->hw);

	Dac *const dac_module = module_inst->hw;

	while (dac_is_syncing(module_inst)) {
		/* Wait until the synchronization is complete */
	}

	/* Zero length request */
	if (length == 0) {
		/* No data to be converted */
		return STATUS_OK;
	}

#if DAC_CALLBACK_MODE == true
	/* Check if busy */
	if (module_inst->job_status[channel] == STATUS_BUSY) {
		return STATUS_BUSY;
	}
#endif

	/* Only support event triggered conversion */
	if (module_inst->start_on_event[channel] == false) {
		return STATUS_ERR_UNSUPPORTED_DEV;
	}

	/* Blocks while buffer is being transferred */
	while (length--) {
		/* Convert one data */
		dac_chan_write(module_inst, channel, buffer[length]);

		/* Wait until Transmit is complete or timeout */
		for (uint32_t i = 0; i <= DAC_TIMEOUT; i++) {
			if(channel == DAC_CHANNEL_0) {
				if (dac_module->INTFLAG.reg & DAC_INTFLAG_EMPTY0) {
					break;
				} else if (i == DAC_TIMEOUT) {
					return STATUS_ERR_TIMEOUT;
				}
			} else if(channel == DAC_CHANNEL_1) {
				if (dac_module->INTFLAG.reg & DAC_INTFLAG_EMPTY1) {
					break;
				} else if (i == DAC_TIMEOUT) {
					return STATUS_ERR_TIMEOUT;
				}
			}
		}
	}

	return STATUS_OK;
}
Пример #5
0
/**
 * \internal Writes a DAC configuration to the hardware module.
 *
 * Writes out a given configuration to the hardware module.
 *
 * \param[out] module_inst  Pointer to the DAC software instance struct
 * \param[in]  config       Pointer to the configuration struct
 *
 */
static void _dac_set_config(
		struct dac_module *const module_inst,
		struct dac_config *const config)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(config);
	Assert(module_inst->hw);

	Dac *const dac_module = module_inst->hw;

	/* Set selected DAC output to be enabled when enabling the module */
	module_inst->output = config->output;
	module_inst->start_on_event = false;

	uint32_t new_ctrla = 0;
	uint32_t new_ctrlb = 0;

	/* Enable DAC in standby sleep mode if configured */
	if (config->run_in_standby) {
		new_ctrla |= DAC_CTRLA_RUNSTDBY;
	}

	/* Set reference voltage */
	new_ctrlb |= config->reference;

	/* Left adjust data if configured */
	if (config->left_adjust) {
		new_ctrlb |= DAC_CTRLB_LEFTADJ;
	}

#ifdef FEATURE_DAC_DATABUF_WRITE_PROTECTION
	/* Bypass DATABUF write protection if configured */
	if (config->databuf_protection_bypass) {
		new_ctrlb |= DAC_CTRLB_BDWP;
	}
#endif

	/* Voltage pump disable if configured */
	if (config->voltage_pump_disable) {
		new_ctrlb |= DAC_CTRLB_VPD;
	}

	/* Apply the new configuration to the hardware module */
	dac_module->CTRLA.reg = new_ctrla;

	while (dac_is_syncing(module_inst)) {
		/* Wait until the synchronization is complete */
	}

	dac_module->CTRLB.reg = new_ctrlb;
}
Пример #6
0
/**
 * \brief Resets the DAC module.
 *
 * This function will reset the DAC module to its power on default values and
 * disable it.
 *
 * \param[in] module_inst  Pointer to the DAC software instance struct
 */
void dac_reset(
		struct dac_module *const module_inst)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(module_inst->hw);

	Dac *const dac_module = module_inst->hw;

	while (dac_is_syncing(module_inst)) {
		/* Wait until the synchronization is complete */
	}

	/* Software reset the module */
	dac_module->CTRLA.reg |= DAC_CTRLA_SWRST;
}
Пример #7
0
/**
 * \brief Disable the DAC module.
 *
 * Disables the DAC interface and the output buffer.
 *
 * \param[in] module_inst  Pointer to the DAC software instance struct
 *
 */
void dac_disable(
		struct dac_module *const module_inst)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(module_inst->hw);

	Dac *const dac_module = module_inst->hw;

	while (dac_is_syncing(module_inst)) {
		/* Wait until the synchronization is complete */
	}

	/* Disable DAC */
	dac_module->CTRLA.reg &= ~DAC_CTRLA_ENABLE;
}
Пример #8
0
/**
 * \brief Convert a specific number digital data to analog through DAC.
 *
 * This function will perform a conversion of specific number of digital data.
 * The conversion should be event-triggered, the data will be written to DATABUF
 * and transferred to the DATA register and converted when a Start Conversion
 * Event is issued.
 * Conversion data must be right or left adjusted according to configuration
 * settings.
 * \note To be event triggered, the enable_start_on_event must be
 * enabled in the configuration.
 *
 * \param[in] module_inst      Pointer to the DAC software device struct
 * \param[in] channel          DAC channel to write to
 * \param[in] buffer             Pointer to the digital data write buffer to be converted
 * \param[in] length             Size of the write buffer
 *
 * \return Status of the operation.
 * \retval STATUS_OK           If the data was written
 * \retval STATUS_ERR_UNSUPPORTED_DEV  If a callback that requires event driven
 *                                     mode was specified with a DAC instance
 *                                     configured in non-event mode
 * \retval STATUS_BUSY      The DAC is busy to accept new job
 */
enum status_code dac_chan_write_buffer_job(
		struct dac_module *const module_inst,
		const enum dac_channel channel,
		uint16_t *buffer,
		uint32_t length)
{
	/* Sanity check arguments */
	Assert(module_inst);
	Assert(module_inst->hw);
	Assert(buffer);

	UNUSED(channel);

	Dac *const dac_module = module_inst->hw;

	/* DAC interrupts require it to be driven by events to work, fail if in
	 * unbuffered (polled) mode */
	if (module_inst->start_on_event == false) {
		return STATUS_ERR_UNSUPPORTED_DEV;
	}

	if(module_inst->remaining_conversions != 0 ||
			module_inst->job_status == STATUS_BUSY){
		return STATUS_BUSY;
	}

	/* Wait until the synchronization is complete */
	while (dac_is_syncing(module_inst)) {
	};

	module_inst->job_status = STATUS_BUSY;

	module_inst->remaining_conversions = length;
	module_inst->job_buffer = buffer;
	module_inst->transferred_conversions = 0;

	/* Enable interrupt */
	system_interrupt_enable(SYSTEM_INTERRUPT_MODULE_DAC);
	dac_module->INTFLAG.reg = DAC_INTFLAG_UNDERRUN | DAC_INTFLAG_EMPTY;
	dac_module->INTENSET.reg = DAC_INTENSET_UNDERRUN | DAC_INTENSET_EMPTY;

	return STATUS_OK;
}