160 lines
3.8 KiB
C
160 lines
3.8 KiB
C
/*
|
|
* @copyright (c) 2023-2024, MR Development Team
|
|
*
|
|
* @license SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* @date 2023-11-14 MacRsh First version
|
|
*/
|
|
|
|
#include "drv_dac.h"
|
|
|
|
#ifdef MR_USING_DAC
|
|
|
|
#if !defined(MR_USING_DAC1)
|
|
#warning "Please enable at least one DAC driver"
|
|
#endif /* !defined(MR_USING_DAC1) */
|
|
|
|
static struct drv_dac_data dac_drv_data[] =
|
|
{
|
|
#ifdef MR_USING_DAC1
|
|
{RCC_APB1Periph_DAC}
|
|
#endif /* MR_USING_DAC1 */
|
|
};
|
|
|
|
static struct drv_dac_channel_data dac_channel_drv_data[] = DRV_DAC_CHANNEL_CONFIG;
|
|
|
|
static struct mr_dac dac_dev;
|
|
|
|
static struct drv_dac_channel_data *drv_dac_get_channel_data(int channel)
|
|
{
|
|
if ((channel >= MR_ARRAY_NUM(dac_channel_drv_data)) || (dac_channel_drv_data[channel].port == NULL))
|
|
{
|
|
return NULL;
|
|
}
|
|
return &dac_channel_drv_data[channel];
|
|
}
|
|
|
|
static int drv_dac_configure(struct mr_dac *dac, int state)
|
|
{
|
|
struct drv_dac_data *dac_data = (struct drv_dac_data *)dac->dev.drv->data;
|
|
|
|
/* Configure clock */
|
|
RCC_APB1PeriphClockCmd(dac_data->clock, state);
|
|
return MR_EOK;
|
|
}
|
|
|
|
static int drv_dac_channel_configure(struct mr_dac *dac, int channel, int state)
|
|
{
|
|
struct drv_dac_channel_data *dac_channel_data = drv_dac_get_channel_data(channel);
|
|
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
|
DAC_InitTypeDef DAC_InitStructure = {0};
|
|
|
|
/* Check channel is valid */
|
|
if (dac_channel_data == NULL)
|
|
{
|
|
return MR_EINVAL;
|
|
}
|
|
|
|
/* Configure clock */
|
|
RCC_APB2PeriphClockCmd(dac_channel_data->gpio_clock, ENABLE);
|
|
|
|
switch (dac_channel_data->channel)
|
|
{
|
|
#ifdef DAC_Channel_1
|
|
case DAC_Channel_1:
|
|
{
|
|
DAC_SetChannel1Data(DAC_Align_12b_R, 0);
|
|
break;
|
|
}
|
|
#endif /* DAC_Channel_1 */
|
|
#ifdef DAC_Channel_2
|
|
case DAC_Channel_2:
|
|
{
|
|
DAC_SetChannel2Data(DAC_Align_12b_R, 0);
|
|
break;
|
|
}
|
|
#endif /* DAC_Channel_2 */
|
|
default:
|
|
{
|
|
return MR_EINVAL;
|
|
}
|
|
}
|
|
|
|
/* Configure pin */
|
|
if (dac_channel_data->port != MR_NULL)
|
|
{
|
|
if (state == MR_ENABLE)
|
|
{
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
|
|
GPIO_InitStructure.GPIO_Pin = dac_channel_data->pin;
|
|
GPIO_Init(dac_channel_data->port, &GPIO_InitStructure);
|
|
}
|
|
}
|
|
|
|
/* Configure DAC */
|
|
DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
|
|
DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
|
|
DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
|
|
DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;
|
|
DAC_Init(dac_channel_data->channel, &DAC_InitStructure);
|
|
DAC_Cmd(dac_channel_data->channel, state);
|
|
return MR_EOK;
|
|
}
|
|
|
|
static int drv_dac_write(struct mr_dac *dac, int channel, uint32_t data)
|
|
{
|
|
struct drv_dac_channel_data *dac_channel_data = drv_dac_get_channel_data(channel);
|
|
|
|
#ifdef MR_USING_DAC_CHANNEL_CHECK
|
|
/* Check channel is valid */
|
|
if (dac_channel_data == NULL)
|
|
{
|
|
return MR_EINVAL;
|
|
}
|
|
#endif /* MR_USING_DAC_CHANNEL_CHECK */
|
|
|
|
/* Write data */
|
|
switch (dac_channel_data->channel)
|
|
{
|
|
#ifdef DAC_Channel_1
|
|
case DAC_Channel_1:
|
|
{
|
|
DAC_SetChannel1Data(DAC_Align_12b_R, data);
|
|
break;
|
|
}
|
|
#endif /* DAC_Channel_1 */
|
|
#ifdef DAC_Channel_2
|
|
case DAC_Channel_2:
|
|
{
|
|
DAC_SetChannel2Data(DAC_Align_12b_R, data);
|
|
break;
|
|
}
|
|
#endif /* DAC_Channel_2 */
|
|
default:
|
|
{
|
|
return MR_EINVAL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static struct mr_dac_ops dac_drv_ops =
|
|
{
|
|
drv_dac_configure,
|
|
drv_dac_channel_configure,
|
|
drv_dac_write,
|
|
};
|
|
|
|
static struct mr_drv dac_drv =
|
|
{
|
|
&dac_drv_ops,
|
|
&dac_drv_data,
|
|
};
|
|
|
|
static void drv_dac_init(void)
|
|
{
|
|
mr_dac_register(&dac_dev, "dac1", &dac_drv);
|
|
}
|
|
MR_INIT_DRV_EXPORT(drv_dac_init);
|
|
|
|
#endif /* MR_USING_DAC */
|