diff --git a/midi2cv/drivers/ad57x4.cc b/midi2cv/drivers/ad57x4.cc index 0295250..c14690a 100644 --- a/midi2cv/drivers/ad57x4.cc +++ b/midi2cv/drivers/ad57x4.cc @@ -1,8 +1,8 @@ #include "ad57x4.h" #include "peripherals.h" #include "spi_mode.h" -#include #include +#include static const uint32_t kPinEnable = GPIO_PIN_5; @@ -16,26 +16,34 @@ void AD57X4::Init() HAL_GPIO_Init(GPIOB, &init); HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_SET); + + this->Write(REGISTER_CONTROL, 1, 0b100); } -void AD57X4::WriteVoltage(uint8_t dac, float voltage) { +void AD57X4::WriteVoltage(uint8_t dac, float voltage) +{ + CONSTRAIN(voltage, -10.799f, 10.799f); VoltageRange range = VOLTAGE_RANGE_FIVE_VOLTS; - if(fabs(voltage) > 5) range = VOLTAGE_RANGE_TEN_VOLTS; - if(fabs(voltage) > 10) range = VOLTAGE_RANGE_TEN_EIGHT_VOLTS; + if (fabs(voltage) > 5) + range = VOLTAGE_RANGE_TEN_VOLTS; + if (fabs(voltage) > 10) + range = VOLTAGE_RANGE_TEN_EIGHT_VOLTS; float multiplier = 2.0f; - if(range == VOLTAGE_RANGE_TEN_VOLTS) multiplier = 4.0f; - if(range == VOLTAGE_RANGE_TEN_EIGHT_VOLTS) multiplier = 4.32f; + if (range == VOLTAGE_RANGE_TEN_VOLTS) + multiplier = 4.0f; + if (range == VOLTAGE_RANGE_TEN_EIGHT_VOLTS) + multiplier = 4.32f; float refin = 2.5f; - if(voltage < 0) { + if (voltage < 0) { // convert to signed value - int16_t value = (voltage / (multiplier * refin)) * (65535.0f); + int16_t value = (32768.0f * voltage) / (multiplier * refin); this->WriteDacBipolar(dac, range, value); } else { // convert to unsigned value - uint16_t value = (voltage / (multiplier * refin)) * (65535.0f); + uint16_t value = (65536.0f * voltage) / (multiplier * refin); this->WriteDacUnipolar(dac, range, value); } @@ -47,17 +55,25 @@ void AD57X4::EnableAndSetRange(uint8_t dac, VoltageRange range, bool bipolar) // power on dac this->dacPower |= 1 << dac; this->Write(REGISTER_POWER_CONTROL, 0, this->dacPower); + for (int i = 0; i < 10000; i++) + asm("nop"); } - if (this->dacRange[dac] != range) { + if (this->dacRange[dac] != range || this->dacBipolar[dac] != bipolar) { this->Write(REGISTER_OUTPUT_RANGE, dac, range + (bipolar ? 3 : 0)); this->dacRange[dac] = range; + this->dacBipolar[dac] = bipolar; } } +void AD57X4::WriteDac(uint8_t dac, VoltageRange range, uint16_t value, bool bipolar) { + EnableAndSetRange(dac, range, bipolar); + this->Write(REGISTER_DAC, dac, value); + this->Write(REGISTER_CONTROL, 0b101, 0); // LOAD command in Control Register +} + void AD57X4::WriteDacUnipolar(uint8_t dac, VoltageRange range, uint16_t value) { - EnableAndSetRange(dac, range, false); - this->Write(REGISTER_DAC, dac, value); + WriteDac(dac, range, value, false); } void AD57X4::WriteDacBipolar(uint8_t dac, VoltageRange range, int16_t value) @@ -66,9 +82,7 @@ void AD57X4::WriteDacBipolar(uint8_t dac, VoltageRange range, int16_t value) if (value < 0) { twosComplement = ~(-value) + 1; } - - EnableAndSetRange(dac, range, true); - this->Write(REGISTER_DAC, dac, twosComplement); + WriteDac(dac, range, twosComplement, true); } void AD57X4::Write(Register reg, uint8_t address, uint16_t data) @@ -82,6 +96,7 @@ void AD57X4::Write(Register reg, uint8_t address, uint16_t data) 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_SPI_Transmit(&hspi2, reinterpret_cast(&data) + 1, 1, HAL_MAX_DELAY); + HAL_SPI_Transmit(&hspi2, reinterpret_cast(&data), 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(GPIOB, kPinEnable, GPIO_PIN_SET); } diff --git a/midi2cv/drivers/ad57x4.h b/midi2cv/drivers/ad57x4.h index 1f2f32b..4a463ec 100644 --- a/midi2cv/drivers/ad57x4.h +++ b/midi2cv/drivers/ad57x4.h @@ -12,8 +12,8 @@ enum VoltageRange { enum Register { REGISTER_DAC = 0, REGISTER_OUTPUT_RANGE = 1, - REGISTER_CONTROL = 2, - REGISTER_POWER_CONTROL = 3 + REGISTER_CONTROL = 3, + REGISTER_POWER_CONTROL = 2 }; class AD57X4 { @@ -34,6 +34,8 @@ class AD57X4 { private: uint8_t dacPower = 0; VoltageRange dacRange[4]; + bool dacBipolar[4]; + void WriteDac(uint8_t dac, VoltageRange range, uint16_t value, bool bipolar); 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 1b228fb..3e40315 100644 --- a/midi2cv/drivers/spi_mode.cc +++ b/midi2cv/drivers/spi_mode.cc @@ -45,7 +45,7 @@ void InitSPIAD5754(void) 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.CLKPolarity = SPI_POLARITY_HIGH; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; diff --git a/midi2cv/midi2cv.cc b/midi2cv/midi2cv.cc index 83a4d9a..abccbe5 100644 --- a/midi2cv/midi2cv.cc +++ b/midi2cv/midi2cv.cc @@ -112,7 +112,7 @@ void SysTick_Handler(void) system_clock.Tick(); } -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) // called with 1kHz (OPTIMIZE!) the display should get its own spi bus { if (htim != &htim2) { return; @@ -120,12 +120,19 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) static uint16_t count = 0; count++; - if (count % (8000L / 20) == 0) { + if (count % (1000L / 20) == 0) { // refresh display with 20fps ui.Flush(); count = 0; } + static float v = 0; + dac1.WriteVoltage(0, v+= 0.1f); + dac1.WriteVoltage(1, v*3); + dac1.WriteVoltage(2, v*5); + dac1.WriteVoltage(3, v*10); + if(v > 1) v = -1; + // write audiodac1 // write audiodac2 // write audiodac3 @@ -136,7 +143,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) void InitTimers(void) { __HAL_RCC_TIM2_CLK_ENABLE(); - htim2.Init.Period = F_CPU / (8000 * 1) - 1; + htim2.Init.Period = F_CPU / (1000 * 1) - 1; htim2.Init.Prescaler = 0; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; @@ -161,6 +168,7 @@ void Init(void) //IWDG_Enable(); display.Init(); encoder.Init(); + dac1.Init(); InitTimers(); }