From 3f83d40ec83f455d3f4490387daa7e2dde8e936a Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Sat, 18 Apr 2020 17:37:08 +0200 Subject: [PATCH] Add draft of AD57X4 driver --- midi2cv/drivers/ad57x4.cc | 64 +++++++++++++++++++++++++++++++++++++ midi2cv/drivers/ad57x4.h | 33 +++++++++++++++++++ midi2cv/drivers/spi_mode.cc | 20 +++++++++++- midi2cv/midi2cv.cc | 2 ++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 midi2cv/drivers/ad57x4.cc create mode 100644 midi2cv/drivers/ad57x4.h diff --git a/midi2cv/drivers/ad57x4.cc b/midi2cv/drivers/ad57x4.cc new file mode 100644 index 0000000..42868e0 --- /dev/null +++ b/midi2cv/drivers/ad57x4.cc @@ -0,0 +1,64 @@ +#include "ad57x4.h" +#include "peripherals.h" +#include "spi_mode.h" +#include "stm32f3xx_hal_gpio.h" +#include + +static const uint32_t kPinEnable = GPIO_PIN_5; + +void AD57X4::Init() +{ + GPIO_InitTypeDef init; + init.Pin = kPinEnable; + init.Mode = GPIO_MODE_OUTPUT_PP; + init.Pull = GPIO_NOPULL; + init.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(GPIOB, &init); + + HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_SET); +} + +void AD57X4::EnableAndSetRange(uint8_t dac, VoltageRange range, bool bipolar) +{ + if (!(this->dacPower & (1 << dac))) { + // power on dac + this->dacPower |= 1 << dac; + this->Write(REGISTER_POWER_CONTROL, 0, this->dacPower); + } + if (this->dacRange[dac] != range) { + this->Write(REGISTER_OUTPUT_RANGE, dac, range + (bipolar ? 3 : 0)); + this->dacRange[dac] = range; + } +} + +void AD57X4::WriteDacUnipolar(uint8_t dac, VoltageRange range, uint16_t value) +{ + EnableAndSetRange(dac, range, false); + this->Write(REGISTER_DAC, dac, value); +} + +void AD57X4::WriteDacBipolar(uint8_t dac, VoltageRange range, int16_t value) +{ + uint16_t twosComplement = value; + if (value < 0) { + twosComplement = ~(-value) + 1; + } + + EnableAndSetRange(dac, range, true); + this->Write(REGISTER_DAC, dac, twosComplement); +} + +void AD57X4::Write(Register reg, uint8_t address, uint16_t data) +{ + uint8_t first = address; // select address + first |= reg << 3; // select register + first |= 0 << 7; // write command + first |= 0 << 6; // always 0 + + InitSPI(SPI_MODE_DAC1); + + HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_RESET); + HAL_SPI_Transmit(&hspi2, &first, 1, HAL_MAX_DELAY); // write data + HAL_SPI_Transmit(&hspi2, reinterpret_cast(&data), 2, HAL_MAX_DELAY); + HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_SET); +} diff --git a/midi2cv/drivers/ad57x4.h b/midi2cv/drivers/ad57x4.h new file mode 100644 index 0000000..121b065 --- /dev/null +++ b/midi2cv/drivers/ad57x4.h @@ -0,0 +1,33 @@ +#pragma once + +#include "stmlib/stmlib.h" + +enum VoltageRange { + VOLTAGE_RANGE_FIVE_VOLTS = 0, + VOLTAGE_RANGE_TEN_VOLTS = 1, + VOLTAGE_RANGE_TEN_EIGHT_VOLTS = 2 +}; + +enum Register { + REGISTER_DAC = 0, + REGISTER_OUTPUT_RANGE = 1, + REGISTER_CONTROL = 2, + REGISTER_POWER_CONTROL = 3 +}; + +class AD57X4 { + public: + AD57X4() {}; + + void Init(); + + void WriteDacBipolar(uint8_t dac, VoltageRange range, int16_t value); + void WriteDacUnipolar(uint8_t dac, VoltageRange range, uint16_t value); + + private: + uint8_t dacPower = 0; + VoltageRange dacRange[4]; + void EnableAndSetRange(uint8_t dac, VoltageRange range, bool bipolar); + void Write(Register reg, uint8_t address, uint16_t data); + DISALLOW_COPY_AND_ASSIGN(AD57X4); +}; diff --git a/midi2cv/drivers/spi_mode.cc b/midi2cv/drivers/spi_mode.cc index 8bf3008..1b228fb 100644 --- a/midi2cv/drivers/spi_mode.cc +++ b/midi2cv/drivers/spi_mode.cc @@ -6,6 +6,7 @@ SPIMode currentMode = SPI_MODE_UNINITIALIZED; void InitSPIDisplay(void); +void InitSPIAD5754(void); void InitSPI(SPIMode mode) { @@ -26,8 +27,10 @@ void InitSPI(SPIMode mode) case SPI_MODE_DISPLAY: InitSPIDisplay(); break; - case SPI_MODE_DAC0: case SPI_MODE_DAC1: + InitSPIAD5754(); + break; + case SPI_MODE_DAC0: case SPI_MODE_USB: case SPI_MODE_UNINITIALIZED: @@ -37,6 +40,21 @@ void InitSPI(SPIMode mode) } } +void InitSPIAD5754(void) +{ // the same as the display(?) + hspi2.Init.Direction = SPI_DIRECTION_2LINES; + hspi2.Init.Mode = SPI_MODE_MASTER; + hspi2.Init.DataSize = SPI_DATASIZE_8BIT; + hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi2.Init.NSS = SPI_NSS_SOFT; + hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi2.Init.CRCPolynomial = 7; + hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + HAL_SPI_Init(&hspi2); +} + void InitSPIDisplay(void) { hspi2.Init.Direction = SPI_DIRECTION_2LINES; diff --git a/midi2cv/midi2cv.cc b/midi2cv/midi2cv.cc index 99d1c70..83a4d9a 100644 --- a/midi2cv/midi2cv.cc +++ b/midi2cv/midi2cv.cc @@ -4,6 +4,7 @@ #include "drivers/display.h" #include "drivers/encoder.h" #include "drivers/peripherals.h" +#include "drivers/ad57x4.h" #include "menu/menu.h" #include "menu/menu_items.h" #include "part.h" @@ -30,6 +31,7 @@ extern "C" void __cxa_pure_virtual() using namespace stmlib; Display display; +AD57X4 dac1; Encoder encoder; Settings settings;