Skip to content

Commit

Permalink
oe sync
Browse files Browse the repository at this point in the history
  • Loading branch information
mvladic committed Jan 22, 2020
1 parent 359d486 commit 0c97202
Show file tree
Hide file tree
Showing 28 changed files with 644 additions and 563 deletions.
3 changes: 3 additions & 0 deletions src/eez/index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ ChannelInterface::ChannelInterface(int slotIndex_)
{
}

void ChannelInterface::onAfterOutputEnableSync(int subchannelIndex) {
}

unsigned ChannelInterface::getRPol(int subchannelIndex) {
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions src/eez/index.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ struct ChannelInterface {
virtual void adcMeasureMonDac(int subchannelIndex) = 0;
virtual void adcMeasureAll(int subchannelIndex) = 0;

virtual void setOutputEnable(int subchannelIndex, bool enable) = 0;
virtual void setOutputEnable(int subchannelIndex, bool enable, uint16_t tasks) = 0;
virtual void onAfterOutputEnableSync(int subchannelIndex);

virtual DprogState getDprogState() = 0;
virtual void setDprogState(DprogState dprogState) = 0;

virtual void setDacVoltage(int subchannelIndex, uint16_t value) = 0;
Expand Down
4 changes: 1 addition & 3 deletions src/eez/modules/bp3c/flash_slave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,7 @@ void enterBootloaderMode(int slotIndex) {
psu::reset();

// power down channels
for (int i = 0; i < psu::CH_NUM; ++i) {
psu::Channel::get(i).onPowerDown();
}
psu::powerDownChannels();

osDelay(25);

Expand Down
40 changes: 18 additions & 22 deletions src/eez/modules/dcm220/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,32 @@ namespace dcm220 {
static GPIO_TypeDef *SPI_IRQ_GPIO_Port[] = { SPI2_IRQ_GPIO_Port, SPI4_IRQ_GPIO_Port, SPI5_IRQ_GPIO_Port };
static const uint16_t SPI_IRQ_Pin[] = { SPI2_IRQ_Pin, SPI4_IRQ_Pin, SPI5_IRQ_Pin };

uint8_t g_firmwareVersionMajor;
uint8_t g_firmwareVersionMinor;

bool masterSynchro(int slotIndex) {
uint32_t start = millis();
uint8_t txackbytes = SPI_MASTER_SYNBYTE, rxackbytes = 0x00;
do {

uint8_t txBuffer[3] = { SPI_MASTER_SYNBYTE, 0, 0 };
uint8_t rxBuffer[3] = { 0, 0, 0 };

while (true) {
spi::select(slotIndex, spi::CHIP_DCM220);
spi::transfer(slotIndex, &txackbytes, &rxackbytes, 1);
spi::transfer(slotIndex, txBuffer, rxBuffer, 3);
spi::deselect(slotIndex);

if (rxBuffer[0] == SPI_SLAVE_SYNBYTE) {
g_firmwareVersionMajor = rxBuffer[1];
g_firmwareVersionMinor = rxBuffer[2];
DebugTrace("DCM220 slot #%d firmware version %d.%d\n", slotIndex + 1, (int)g_firmwareVersionMajor, (int)g_firmwareVersionMinor);
break;
}

int32_t diff = millis() - start;
if (diff > CONF_MASTER_SYNC_TIMEOUT_MS) {
return false;
}
} while(rxackbytes != SPI_SLAVE_SYNBYTE);
}

while (HAL_GPIO_ReadPin(SPI_IRQ_GPIO_Port[slotIndex], SPI_IRQ_Pin[slotIndex]) != GPIO_PIN_SET) {
int32_t diff = millis() - start;
Expand Down Expand Up @@ -308,11 +321,6 @@ struct Channel : ChannelInterface {
if (subchannelIndex == 0 && diff > 1000) {
uint8_t output0 = 0x80 | (outputEnable[0] ? REG0_OE1_MASK : 0) | (outputEnable[1] ? REG0_OE2_MASK : 0);

bool oeSync = output[0] != output0;
if (oeSync) {
channel_dispatcher::outputEnableSyncPrepare(channel);
}

output[0] = output0;

#if defined(EEZ_PLATFORM_STM32)
Expand All @@ -335,14 +343,6 @@ struct Channel : ChannelInterface {
transfer();
#endif

if (oeSync) {
delayMicroseconds(50);
channel_dispatcher::outputEnableSyncReady(channel);

channel_dispatcher::outputEnableSyncPrepare(channel);
channel_dispatcher::outputEnableSyncReady(psu::Channel::getBySlotIndex(slotIndex, 1));
}

#if defined(EEZ_PLATFORM_STM32)
if (numCrcErrors == 0) {
temperature[0] = calcTemperature(*((uint16_t *)(input + 10)));
Expand Down Expand Up @@ -481,14 +481,10 @@ struct Channel : ChannelInterface {
void adcMeasureAll(int subchannelIndex) {
}

void setOutputEnable(int subchannelIndex, bool enable) {
void setOutputEnable(int subchannelIndex, bool enable, uint16_t tasks) {
outputEnable[subchannelIndex] = enable;
}

DprogState getDprogState() {
return DPROG_STATE_OFF;
}

void setDprogState(DprogState dprogState) {
}

Expand Down
164 changes: 96 additions & 68 deletions src/eez/modules/dcpX05/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ struct Channel : ChannelInterface {
DigitalAnalogConverter dac;
IOExpander ioexp;

DprogState dprogState;
bool delayed_dp_off;
uint32_t delayed_dp_off_start;
bool dpOn;
Expand Down Expand Up @@ -173,16 +172,13 @@ struct Channel : ChannelInterface {
ioexp.init();
adc.init();
dac.init();

dprogState = DPROG_STATE_ON;
}

void onPowerDown(int subchannelIndex) {
}

void reset(int subchannelIndex) {
uSet = 0;
dprogState = DPROG_STATE_ON;
dpOn = false;
uBeforeBalancing = NAN;
iBeforeBalancing = NAN;
Expand Down Expand Up @@ -240,7 +236,7 @@ struct Channel : ChannelInterface {
}

if (channel.params.features & CH_FEATURE_DPROG) {
if (dprogState == DPROG_STATE_ON) {
if (channel.flags.dprogState == DPROG_STATE_ON) {
// turn off DP after delay
if (delayed_dp_off && (millis() - delayed_dp_off_start) >= DP_OFF_DELAY_PERIOD) {
delayed_dp_off = false;
Expand Down Expand Up @@ -304,7 +300,7 @@ struct Channel : ChannelInterface {
}

// HW OVP handling
if (channel.isOutputEnabled()) {
if (ioexp.testBit(IOExpander::IO_BIT_OUT_OUTPUT_ENABLE)) {
if (!fallingEdge && channel.isHwOvpEnabled() && !ioexp.testBit(IOExpander::DCP405_IO_BIT_OUT_OVP_ENABLE)) {
// activate HW OVP
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OVP_ENABLE, true);
Expand Down Expand Up @@ -405,103 +401,133 @@ struct Channel : ChannelInterface {
}
}

void setOutputEnable(int subchannelIndex, bool enable) {
void setOutputEnable(int subchannelIndex, bool enable, uint16_t tasks) {
psu::Channel &channel = psu::Channel::getBySlotIndex(slotIndex);

if (enable) {
dac.setVoltage(uSet);
// OE
if (tasks & OUTPUT_ENABLE_TASK_OE) {
ioexp.changeBit(IOExpander::IO_BIT_OUT_OUTPUT_ENABLE, true);
}

setCurrentRange(subchannelIndex);
// DAC
if (tasks & OUTPUT_ENABLE_TASK_DAC) {
dac.setVoltage(uSet);
}

ioexp.changeBit(IOExpander::IO_BIT_OUT_OUTPUT_ENABLE, true);
// Current range
if (tasks & OUTPUT_ENABLE_TASK_CURRENT_RANGE) {
setCurrentRange(subchannelIndex);
}

if (channel.params.features & CH_FEATURE_HW_OVP) {
if (channel.isHwOvpEnabled()) {
// OVP has to be enabled after OE activation
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OVP_ENABLE, true);
// OVP
if (tasks & OUTPUT_ENABLE_TASK_OVP) {
if (channel.params.features & CH_FEATURE_HW_OVP) {
if (channel.isHwOvpEnabled()) {
// OVP has to be enabled after OE activation
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OVP_ENABLE, true);
}
}
}

if (channel.params.features & CH_FEATURE_DPROG) {
if (dprogState == DPROG_STATE_ON) {
// enable DP
dpNegMonitoringTime = micros();
delayed_dp_off = false;
setDpEnable(true);
// DP
if (tasks & OUTPUT_ENABLE_TASK_DP) {
if (channel.params.features & CH_FEATURE_DPROG) {
if (channel.flags.dprogState == DPROG_STATE_ON) {
// enable DP
dpNegMonitoringTime = micros();
delayed_dp_off = false;
setDpEnable(true);
}
}
}

adc.start(ADC_DATA_TYPE_U_MON);
if (tasks & OUTPUT_ENABLE_TASK_FINALIZE) {
adc.start(ADC_DATA_TYPE_U_MON);
}
} else {
if (channel.params.features & CH_FEATURE_HW_OVP) {
if (channel.isHwOvpEnabled()) {
// OVP has to be disabled before OE deactivation
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OVP_ENABLE, false);
// OVP
if (tasks & OUTPUT_ENABLE_TASK_OVP) {
if (channel.params.features & CH_FEATURE_HW_OVP) {
if (channel.isHwOvpEnabled()) {
// OVP has to be disabled before OE deactivation
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OVP_ENABLE, false);
}
}
}

dac.setVoltage(channel.getCalibratedVoltage(0));
// DAC
if (tasks & OUTPUT_ENABLE_TASK_DAC) {
dac.setDacVoltage(0);
}

ioexp.changeBit(IOExpander::IO_BIT_OUT_OUTPUT_ENABLE, false);
// OE
if (tasks & OUTPUT_ENABLE_TASK_OE) {
ioexp.changeBit(IOExpander::IO_BIT_OUT_OUTPUT_ENABLE, false);
}

setCurrentRange(subchannelIndex);
// Current range
if (tasks & OUTPUT_ENABLE_TASK_CURRENT_RANGE) {
setCurrentRange(subchannelIndex);
}

if (channel.params.features & CH_FEATURE_DPROG) {
if (dprogState == DPROG_STATE_ON) {
// turn off DP after some delay
delayed_dp_off = true;
delayed_dp_off_start = millis();
// DP
if (tasks & OUTPUT_ENABLE_TASK_DP) {
if (channel.params.features & CH_FEATURE_DPROG) {
if (channel.flags.dprogState == DPROG_STATE_ON) {
// turn off DP after some delay
delayed_dp_off = true;
delayed_dp_off_start = millis();
}
}
}
}

if (channel.params.features & CH_FEATURE_COUPLING) {
if (channel.channelIndex == 0 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_PARALLEL) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, enable);
} else if (channel.channelIndex == 1 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_PARALLEL) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, false);
} else if (channel.channelIndex == 0 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_SERIES) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, enable);
} else if (channel.channelIndex == 1 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_SERIES) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, false);
} else if (channel.channelIndex < 2 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_SPLIT_RAILS) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, enable);
} else if (channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_COMMON_GND) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, enable);
if (tasks & OUTPUT_ENABLE_TASK_FINALIZE) {
if (channel.params.features & CH_FEATURE_COUPLING) {
if (channel.channelIndex == 0 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_PARALLEL) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, enable);
} else if (channel.channelIndex == 1 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_PARALLEL) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, false);
} else if (channel.channelIndex == 0 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_SERIES) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, enable);
} else if (channel.channelIndex == 1 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_SERIES) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, false);
} else if (channel.channelIndex < 2 && channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_SPLIT_RAILS) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, enable);
} else if (channel_dispatcher::getCouplingType() == channel_dispatcher::COUPLING_TYPE_COMMON_GND) {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, enable);
} else {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, enable);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, false);
}
} else {
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_UNCOUPLED_LED, enable);
ioexp.changeBit(IOExpander::DCP405_IO_BIT_OUT_OE_COUPLED_LED, false);
ioexp.changeBit(IOExpander::DCP505_IO_BIT_OUT_OE_UNCOUPLED_LED, enable);

}
} else {
ioexp.changeBit(IOExpander::DCP505_IO_BIT_OUT_OE_UNCOUPLED_LED, enable);

restoreVoltageToValueBeforeBalancing(channel);
restoreCurrentToValueBeforeBalancing(channel);
}

restoreVoltageToValueBeforeBalancing(channel);
restoreCurrentToValueBeforeBalancing(channel);
}

DprogState getDprogState() {
return dprogState;
}
void onAfterOutputEnableSync(int subchannelIndex) {
}

void setDprogState(DprogState dprogState_) {
void setDprogState(DprogState dprogState) {
psu::Channel &channel = psu::Channel::getBySlotIndex(slotIndex);
if (channel.params.features & CH_FEATURE_DPROG) {
dprogState = dprogState_;

if (dprogState == DPROG_STATE_OFF) {
setDpEnable(false);
} else {
setDpEnable(channel.isOk() && channel.isOutputEnabled());
setDpEnable(channel.isOk() && ioexp.testBit(IOExpander::IO_BIT_OUT_OUTPUT_ENABLE));
}

delayed_dp_off = false;
}
}
Expand Down Expand Up @@ -536,8 +562,10 @@ struct Channel : ChannelInterface {
}
}

if (channel.isOutputEnabled() || isDacTesting(subchannelIndex)) {
if (ioexp.testBit(IOExpander::IO_BIT_OUT_OUTPUT_ENABLE) || isDacTesting(subchannelIndex)) {
dac.setVoltage(value);
} else {
dac.setDacVoltage(0);
}

uSet = value;
Expand Down
4 changes: 2 additions & 2 deletions src/eez/modules/dcpX05/dac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ bool DigitalAnalogConverter::test(IOExpander &ioexp, AnalogDigitalConverter &adc

channel.adcMeasureMonDac();

channel.setVoltage(0);
channel.setCurrent(0);
setDacVoltage(0);
setDacCurrent(0);

float uMon = channel.u.mon_dac_last;
float uDiff = uMon - uSet;
Expand Down
Loading

0 comments on commit 0c97202

Please sign in to comment.