dac-cosine/main/dac-cosine.c

176 lines
4.6 KiB
C

/* DAC Cosine Generator Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/dac.h"
/* Declare global sine waveform parameters
* so they may be then accessed and changed from debugger
* over an JTAG interface
*/
int frequency = 8; // about 1kHz
int scale = 1; // 50% of the full scale
int offset; // leave it default / 0 = no any offset
int invert = 2; // invert MSB to get sine waveform
/*
* Enable cosine waveform generator on a DAC channel
*/
void dac_cosine_enable(dac_channel_t channel)
{
// Enable tone generator common to both channels
SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
switch(channel) {
case DAC_CHANNEL_1:
// Enable / connect tone tone generator on / to this channel
SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
// Invert MSB, otherwise part of waveform will have inverted
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV1, 2, SENS_DAC_INV1_S);
break;
case DAC_CHANNEL_2:
SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M);
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV2, 2, SENS_DAC_INV2_S);
break;
default :
printf("Channel %d\n", channel);
}
}
/*
* Set frequency of internal CW generator common to both DAC channels
*
* Range 0x0001 - 0xFFFF
*
*/
void dac_frequency_set(int frequency)
{
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL1_REG, SENS_SW_FSTEP, frequency, SENS_SW_FSTEP_S);
}
/*
* Scale output of a DAC channel using two bit pattern:
*
* - 00: no scale
* - 01: scale to 1/2
* - 10: scale to 1/4
* - 11: scale to 1/8
*
*/
void dac_scale_set(dac_channel_t channel, int scale)
{
switch(channel) {
case DAC_CHANNEL_1:
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_SCALE1, scale, SENS_DAC_SCALE1_S);
break;
case DAC_CHANNEL_2:
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_SCALE2, scale, SENS_DAC_SCALE2_S);
break;
default :
printf("Channel %d\n", channel);
}
}
/*
* Offset output of a DAC channel
*
* Range 0x00 - 0xFF
*
*/
void dac_offset_set(dac_channel_t channel, int offset)
{
switch(channel) {
case DAC_CHANNEL_1:
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_DC1, offset, SENS_DAC_DC1_S);
break;
case DAC_CHANNEL_2:
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_DC2, offset, SENS_DAC_DC2_S);
break;
default :
printf("Channel %d\n", channel);
}
}
/*
* Invert output pattern of a DAC channel
*
* - 00: does not invert any bits,
* - 01: inverts all bits,
* - 10: inverts MSB,
* - 11: inverts all bits except for MSB
*
*/
void dac_invert_set(dac_channel_t channel, int invert)
{
switch(channel) {
case DAC_CHANNEL_1:
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV1, invert, SENS_DAC_INV1_S);
break;
case DAC_CHANNEL_2:
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_INV2, invert, SENS_DAC_INV2_S);
break;
default :
printf("Channel %d\n", channel);
}
}
void dactask(void* arg)
{
while(1){
// frequency setting is common to both channels
dac_frequency_set(frequency);
/* Tune parameters of channel 2 only
* to see and compare changes against channel 1
*/
dac_scale_set(DAC_CHANNEL_2, scale);
dac_offset_set(DAC_CHANNEL_2, offset);
dac_invert_set(DAC_CHANNEL_2, invert);
printf("DAC frequency: %5d, DAC2 scale: %d, offset %3d, invert: %d\n", frequency, scale, offset, invert);
vTaskDelay(1000/portTICK_PERIOD_MS);
}
}
/*
* Generate a sine waveform on both DAC channels:
*
* DAC_CHANNEL_1 - GPIO25
* DAC_CHANNEL_2 - GPIO26
*
* Connect scope to both GPIO25 and GPIO26
* to observe the waveform changes
* in response to the parameter change
*/
void app_main()
{
dac_cosine_enable(DAC_CHANNEL_1);
dac_cosine_enable(DAC_CHANNEL_2);
dac_output_enable(DAC_CHANNEL_1);
dac_output_enable(DAC_CHANNEL_2);
xTaskCreate(dactask, "dactask", 1024*3, NULL, 10, NULL);
}