diff --git a/firmware/.vscode/settings.json b/firmware/.vscode/settings.json index eed5eb5..fed0f00 100644 --- a/firmware/.vscode/settings.json +++ b/firmware/.vscode/settings.json @@ -15,6 +15,8 @@ "disp_layout_types.h": "c", "ctrl_app_types.h": "c", "tim.h": "c", - "ulog.h": "c" + "ulog.h": "c", + "ctrl_generator.h": "c", + "type_traits": "c" } } \ No newline at end of file diff --git a/firmware/func_gen_stm32f303re_nucleo/Makefile b/firmware/func_gen_stm32f303re_nucleo/Makefile index c5a2606..9acac78 100644 --- a/firmware/func_gen_stm32f303re_nucleo/Makefile +++ b/firmware/func_gen_stm32f303re_nucleo/Makefile @@ -92,6 +92,7 @@ C_SOURCES += ../shared_libs/controllers/ctrl_bottom_button.c C_SOURCES += ../shared_libs/controllers/ctrl_channel_button.c C_SOURCES += ../shared_libs/controllers/ctrl_app.c C_SOURCES += ../shared_libs/controllers/ctrl_encoder.c +C_SOURCES += ../shared_libs/controllers/ctrl_generator.c # utils/printf C_SOURCES += ../shared_libs/utils/printf/printf.c diff --git a/firmware/shared_libs/controllers/ctrl_app_types.h b/firmware/shared_libs/controllers/ctrl_app_types.h index d2d5c1e..63a506f 100644 --- a/firmware/shared_libs/controllers/ctrl_app_types.h +++ b/firmware/shared_libs/controllers/ctrl_app_types.h @@ -8,6 +8,12 @@ #define MAX_PHAS 360 #define MAX_DUTY 100 +typedef enum +{ + FALSE, + TRUE +} bool_t; + typedef enum { GEN_FG_TYPE, diff --git a/firmware/shared_libs/controllers/ctrl_generator.c b/firmware/shared_libs/controllers/ctrl_generator.c new file mode 100644 index 0000000..585d0a1 --- /dev/null +++ b/firmware/shared_libs/controllers/ctrl_generator.c @@ -0,0 +1,277 @@ +#include "main.h" +#include "spi.h" +#include "i2c.h" +#include "ctrl_app_types.h" +#include "ctrl_app.h" +#include "ad9833.h" +#include "ltc2631.h" +#include "mcp41x.h" +#include "ctrl_generator.h" + +typedef struct FG_handle_s FG_handle_t; + +struct FG_handle_s +{ + ad9833_handle_t hdds; + ltc2631_handle_t hoffs; + mcp41x_handle_t hampl; + FG_handle_t *link[2]; +}; + +typedef uint8_t timer_handle_t; +typedef struct +{ + timer_handle_t hpwm; + ltc2631_handle_t hoffs; + mcp41x_handle_t hampl; +} PWM_handle_t; + +typedef enum +{ + FG_CHAN1, + FG_CHAN2, + FG_CHAN3, + FG_CHAN_MAX, +} FG_channel_t; + +typedef enum +{ + PWM_CHAN1, + PWM_CHAN2, + PWM_CHAN3, + PWM_CHAN_MAX, +} PWM_channel_t; + +FG_handle_t dds_gen[FG_CHAN_MAX]; +PWM_handle_t pwm_gen[PWM_CHAN_MAX]; + +uint8_t ch_to_gen_ch[CHANNEL_MAX] = {FG_CHAN1, FG_CHAN2, FG_CHAN3, PWM_CHAN1, PWM_CHAN2, PWM_CHAN3}; + +#define DDS1_CS_PORT GPIOC +#define DDS2_CS_PORT GPIOC +#define DDS3_CS_PORT GPIOC + +#define DDS1_CS_PIN GPIO_PIN_0 +#define DDS2_CS_PIN GPIO_PIN_0 +#define DDS3_CS_PIN GPIO_PIN_0 + +#define AMP1_CS_PORT GPIOC +#define AMP2_CS_PORT GPIOC +#define AMP3_CS_PORT GPIOC + +#define AMP1_CS_PIN GPIO_PIN_0 +#define AMP2_CS_PIN GPIO_PIN_0 +#define AMP3_CS_PIN GPIO_PIN_0 + +void gen_init() +{ + ad9833_init(&dds_gen[FG_CHAN1].hdds, &hspi2, DDS1_CS_PORT, DDS1_CS_PIN); + ad9833_init(&dds_gen[FG_CHAN2].hdds, &hspi2, DDS2_CS_PORT, DDS2_CS_PIN); + ad9833_init(&dds_gen[FG_CHAN3].hdds, &hspi2, DDS3_CS_PORT, DDS3_CS_PIN); + + ltc2631_init(&dds_gen[FG_CHAN1].hoffs, &hi2c1, 0x00, LTC2631_8BIT, LTC_REF_2V5); + ltc2631_init(&dds_gen[FG_CHAN2].hoffs, &hi2c1, 0x01, LTC2631_8BIT, LTC_REF_2V5); + ltc2631_init(&dds_gen[FG_CHAN3].hoffs, &hi2c1, 0x02, LTC2631_8BIT, LTC_REF_2V5); + + mcp41x_init(&dds_gen[FG_CHAN1].hampl, &hspi2, AMP1_CS_PORT, AMP1_CS_PIN, MCP41X_10K); + mcp41x_init(&dds_gen[FG_CHAN1].hampl, &hspi2, AMP2_CS_PORT, AMP2_CS_PIN, MCP41X_10K); + mcp41x_init(&dds_gen[FG_CHAN1].hampl, &hspi2, AMP3_CS_PORT, AMP3_CS_PIN, MCP41X_10K); +} + +static void _setAmpliude(mcp41x_handle_t *hampl, uint16_t ampl_x100) +{ + uint8_t value = (ampl_x100 * UINT8_MAX) / MAX_VOLT_POS; + ULOG_DEBUG("(%d:_setAmplitude) ampl_x100: %d, value: %d", __LINE__, ampl_x100, value); + mcp41x_setValue(hampl, value); +} + +static void _setOffset(ltc2631_handle_t *hoffs, int16_t offs_x100) +{ + uint32_t value = (offs_x100 + MAX_VOLT_POS) * LTC_REF_2V5; + ULOG_DEBUG("(%d:_setAmplitude) offs_x100: %d, value: %d", __LINE__, offs_x100, value); + ltc2631_setOutputVoltage_u(hoffs, value); +} + +static void _setFreqDdsGen(ad9833_handle_t *hdds, uint32_t freq) +{ + ULOG_DEBUG("(%d:_setAmplitude) freq: %d", __LINE__, freq); + ad9833_setFrequency(hdds, CHAN_0, freq); +} + +static void _setPhaseDdsGen(ad9833_handle_t *hdds, uint32_t phas) +{ + ULOG_DEBUG("(%d:_setAmplitude) phase: %d", __LINE__, phas); + ad9833_setPhase(hdds, CHAN_0, phas); +} + +static void _setWaveDdsGen(ad9833_handle_t *hdds, GEN_wave_t wave) +{ + ULOG_DEBUG("(%d:_setAmplitude) wave: %d", __LINE__, wave); + switch (wave) + { + case GEN_SIN: + ad9833_setMode(hdds, MODE_SINE); + break; + case GEN_TRI: + ad9833_setMode(hdds, MODE_TRIANGLE); + break; + case GEN_SQR: + ad9833_setMode(hdds, MODE_SQUARE1); + break; + + default: + ULOG_ERROR("%s:%d: Unknown wave type: %d", __FILE__, __LINE__, wave); + break; + } +} + +static void _setEnabledDdsGen(ad9833_handle_t *hdds, GEN_fg_t *gen) +{ + ULOG_DEBUG("(%d:_setAmplitude) phase: %d", __LINE__, gen->enabled); + switch (gen->enabled) + { + case FALSE: + ad9833_setMode(hdds, MODE_OFF); + break; + case TRUE: + _setWaveDdsGen(hdds, gen->wave); + break; + + default: + ULOG_ERROR("%s:%d: Value out of range: %d", __FILE__, __LINE__, gen->enabled); + break; + } +} + +static void _setFreqPwmGen(timer_handle_t *hpwm, uint32_t freq) +{ +} + +static void _setPhasePwmGen(timer_handle_t *hpwm, uint16_t phas) +{ +} + +static void _setDutyPwmGen(timer_handle_t *hpwm, uint8_t duty) +{ +} + +static void _setEnabledPwmGen(timer_handle_t *hpwm, bool_t en) +{ +} + +void setFreq(GENERATOR_t *gen, GEN_channel_t channel) +{ + switch (gen->gen_type) + { + case GEN_FG_TYPE: + _setFreqDdsGen(&dds_gen[ch_to_gen_ch[channel]].hdds, ((GEN_fg_t *)gen->gen)->frequency); + break; + case GEN_PWM_TYPE: + _setFreqPwmGen(&pwm_gen[ch_to_gen_ch[channel]].hpwm, ((GEN_pwm_t *)gen->gen)->frequency); + break; + + default: + ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, gen->gen_type); + break; + } +} + +void setAmplitude(GENERATOR_t *gen, GEN_channel_t channel) +{ + switch (gen->gen_type) + { + case GEN_FG_TYPE: + _setAmpliude(&dds_gen[ch_to_gen_ch[channel]].hampl, ((GEN_fg_t *)gen->gen)->amplitude); + break; + case GEN_PWM_TYPE: + _setAmpliude(&pwm_gen[ch_to_gen_ch[channel]].hampl, ((GEN_pwm_t *)gen->gen)->amplitude); + break; + + default: + ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, gen->gen_type); + break; + } +} + +void setOfsset(GENERATOR_t *gen, GEN_channel_t channel) +{ + switch (gen->gen_type) + { + case GEN_FG_TYPE: + _setOffset(&dds_gen[ch_to_gen_ch[channel]].hoffs, ((GEN_fg_t *)gen->gen)->offset); + break; + case GEN_PWM_TYPE: + _setOffset(&pwm_gen[ch_to_gen_ch[channel]].hoffs, ((GEN_pwm_t *)gen->gen)->offset); + break; + + default: + ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, gen->gen_type); + break; + } +} + +void setPhase(GENERATOR_t *gen, GEN_channel_t channel) +{ + switch (gen->gen_type) + { + case GEN_FG_TYPE: + _setPhaseDdsGen(&dds_gen[ch_to_gen_ch[channel]].hdds, ((GEN_fg_t *)gen->gen)->phase); + break; + case GEN_PWM_TYPE: + _setPhasePwmGen(&pwm_gen[ch_to_gen_ch[channel]].hpwm, ((GEN_pwm_t *)gen->gen)->phase); + break; + + default: + ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, gen->gen_type); + break; + } +} + +void setWave(GENERATOR_t *gen, GEN_channel_t channel) +{ + switch (gen->gen_type) + { + case GEN_FG_TYPE: + _setWaveDdsGen(&dds_gen[ch_to_gen_ch[channel]].hdds, ((GEN_fg_t *)gen->gen)->wave); + break; + + default: + ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, gen->gen_type); + break; + } +} + +void setDuty(GENERATOR_t *gen, GEN_channel_t channel) +{ + switch (gen->gen_type) + { + case GEN_PWM_TYPE: + _setDutyPwmGen(&pwm_gen[ch_to_gen_ch[channel]].hpwm, ((GEN_pwm_t *)gen->gen)->duty); + break; + + default: + ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, gen->gen_type); + break; + } +} + +void setEnabled(GENERATOR_t *gen, GEN_channel_t channel) +{ + switch (gen->gen_type) + { + case GEN_FG_TYPE: + _setEnabledDdsGen(&dds_gen[ch_to_gen_ch[channel]].hdds, ((GEN_fg_t *)gen->gen)); + break; + case GEN_PWM_TYPE: + _setEnabledPwmGen(&pwm_gen[ch_to_gen_ch[channel]].hpwm, ((GEN_pwm_t *)gen->gen)->enabled); + break; + + default: + ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, gen->gen_type); + break; + } +} + +void setLink(GENERATOR_t *source_gen, GEN_channel_t source_ch, GENERATOR_t *dest_gen, GEN_channel_t dest_ch) +{ +} \ No newline at end of file diff --git a/firmware/shared_libs/controllers/ctrl_generator.h b/firmware/shared_libs/controllers/ctrl_generator.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/firmware/shared_libs/controllers/ctrl_generator.h @@ -0,0 +1 @@ +#pragma once