Newer
Older
Michael DM Dryden
committed
}
uint8_t _swv_singledir (uint16_t dacindex, uint16_t dacindex_stop, uint16_t dacindex_pulse_height, uint16_t dacindex_step, uint8_t direction){
Michael DM Dryden
committed
/**
* Internal function that performs a single direction sweep for SWV
*
* @param dacindex Starting voltage as dac index
* @param dacindex_stop Stop voltage in dac index.
* @param dacindex_step Step voltage in dac index.
* @param dacindex_pulse_height Pulse amplitude in dac index.
* @param direction Scan direction - 1 for up, 0 for down.
*/
Michael DM Dryden
committed
int32_t forward = 0;
int32_t reverse = 0;
uint16_t lastindex = 0;
if (direction == 1)
max5443_set_voltage1(dacindex+dacindex_pulse_height);
else
max5443_set_voltage1(dacindex-dacindex_pulse_height);
while ((dacindex <= dacindex_stop && direction == 1) || (dacindex >= dacindex_stop && direction == 0)){
tc_clear_overflow(&EXP_TC0_1);
tc_clear_overflow(&EXP_TC0_0);
Michael DM Dryden
committed
while (!tc_is_overflow(&EXP_TC0_0)){ //ADC tc overflow
Michael DM Dryden
committed
if (udi_cdc_is_rx_ready()){ //check for abort signal over USB
Michael DM Dryden
committed
if (getchar() == 'a')
Michael DM Dryden
committed
return 1;
}
Michael DM Dryden
committed
}
ads1255_wakeup();
while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5)));
forward = ads1255_read_single24();
ads1255_standby();
while (!tc_is_overflow(&EXP_TC0_1)); //wait for end of half-cycle
EXP_TC0_0.CNT = 0;
Michael DM Dryden
committed
if (direction == 1) //switch voltage to other half of cycle
max5443_set_voltage1(dacindex-dacindex_pulse_height);
Michael DM Dryden
committed
else
Michael DM Dryden
committed
max5443_set_voltage1(dacindex+dacindex_pulse_height);
Michael DM Dryden
committed
tc_clear_overflow(&EXP_TC0_1); //reset timer OVF
tc_clear_overflow(&EXP_TC0_0);
Michael DM Dryden
committed
while (!tc_is_overflow(&EXP_TC0_0)){ //ADC tc overflow
if (udi_cdc_is_rx_ready()){ //check for abort signal over USB
Michael DM Dryden
committed
if (getchar() == 'a')
Michael DM Dryden
committed
}
Michael DM Dryden
committed
}
ads1255_wakeup();
while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5)));
reverse = ads1255_read_single24();
ads1255_standby();
while (!tc_is_overflow(&EXP_TC0_1)); //wait for end of half-cycle
EXP_TC0_0.CNT = 0;
Michael DM Dryden
committed
lastindex = dacindex;
//increment dacindex
if (direction == 1){
dacindex += dacindex_step;
Michael DM Dryden
committed
max5443_set_voltage1(dacindex+dacindex_pulse_height);
Michael DM Dryden
committed
}
Michael DM Dryden
committed
Michael DM Dryden
committed
else{
dacindex -= dacindex_step;
max5443_set_voltage1(dacindex-dacindex_pulse_height);
}
//data output
Michael DM Dryden
committed
struct
{
uint16_t lastindex;
int32_t forward;
int32_t reverse;
} data;
data.lastindex = lastindex;
data.forward = forward;
data.reverse = reverse;
Michael DM Dryden
committed
printf("B\n");
Michael DM Dryden
committed
udi_cdc_write_buf(&data, 10);
Michael DM Dryden
committed
printf("\n");
Michael DM Dryden
committed
}
Michael DM Dryden
committed
return 0;
Michael DM Dryden
committed
}
Michael DM Dryden
committed
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
void dpv_experiment(int16_t start, int16_t stop, uint16_t step, uint16_t pulse_height, uint16_t pulse_period, uint16_t pulse_width){
/**
* Perform a DPV experiment
*
* @param start Start voltage in mV.
* @param stop Stop voltage in mV.
* @param step Step voltage in mV.
* @param pulse_height Pulse amplitude in mV.
* @param pulse_period Pulse period in ms.
* @param pulse_width Pulse width in ms.
*/
uint8_t direction;
uint16_t dacindex_start = ceil((start)*(65536/(double)3000))+32768;
uint16_t dacindex_stop = ceil(stop*(65536/(double)3000))+32768;
uint16_t dacindex_step = ceil(step*(65536/(double)3000));
uint16_t dacindex_pulse_height = ceil(pulse_height*(65536/(double)3000));
uint32_t cpu_period;
uint32_t cpu_width;
if (start < stop)
direction = 1;
else
direction = 0;
tc_enable(&EXP_TC0_1);
tc_enable(&EXP_TC0_0);
Michael DM Dryden
committed
//calculate time to ADC trigger
cpu_period = ceil((double)pulse_period*1e-3*F_CPU);
uint32_t adc_period = ceil((((double)pulse_period*1e-3)-(double)(sample_delay_ms_100div/1e5))*F_CPU);
uint16_t divider = set_timer_period(cpu_period, &EXP_TC0_1);
uint16_t adc_divider = set_timer_period(adc_period, &EXP_TC0_0);
Michael DM Dryden
committed
cpu_width = (double)pulse_width*1e-3*F_CPU;
uint32_t adc_width = ceil((((double)pulse_width*1e-3)-(double)(sample_delay_ms_100div/1e5))*F_CPU);
tc_write_cc(&EXP_TC0_1, TC_CCA, (uint16_t)(cpu_width/divider));
tc_enable_cc_channels(&EXP_TC0_1, TC_CCAEN);
tc_write_cc(&EXP_TC0_0, TC_CCA, (uint16_t)(adc_width/adc_divider));
tc_enable_cc_channels(&EXP_TC0_0, TC_CCAEN);
Michael DM Dryden
committed
ads1255_wakeup();
ads1255_standby();
Michael DM Dryden
committed
EXP_TC0_1.CNT = 0;
EXP_TC0_0.CNT = 0;
Michael DM Dryden
committed
if (_dpv_singledir(dacindex_start, dacindex_stop, dacindex_pulse_height, dacindex_step, direction))
goto aborting; //function will return non-zero if abort called over USB
printf("D\n"); //signal end of experiment
Michael DM Dryden
committed
aborting:
volt_exp_stop();
tc_write_clock_source(&EXP_TC0_1, TC_CLKSEL_OFF_gc);
tc_disable(&EXP_TC0_1);
tc_write_clock_source(&EXP_TC0_0, TC_CLKSEL_OFF_gc);
tc_disable(&EXP_TC0_0);
EXP_TC0_1.CNT = 0;
EXP_TC0_0.CNT = 0;
Michael DM Dryden
committed
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
ads1255_standby();
return;
}
uint8_t _dpv_singledir (uint16_t dacindex, uint16_t dacindex_stop, uint16_t dacindex_pulse_height, uint16_t dacindex_step, uint8_t direction){
/**
* Internal function that performs a single direction sweep for DPV
*
* @param dacindex Starting voltage as dac index
* @param dacindex_stop Stop voltage in dac index.
* @param dacindex_step Step voltage in dac index.
* @param dacindex_pulse_height Pulse amplitude in dac index.
* @param direction Scan direction - 1 for up, 0 for down.
*/
int32_t forward = 0;
int32_t reverse = 0;
uint16_t lastindex = 0;
if (direction == 1)
max5443_set_voltage1(dacindex+dacindex_pulse_height);
else
max5443_set_voltage1(dacindex-dacindex_pulse_height);
while ((dacindex <= dacindex_stop && direction == 1) || (dacindex >= dacindex_stop && direction == 0)){
tc_clear_overflow(&EXP_TC0_1);
tc_clear_cc_interrupt(&EXP_TC0_1, TC_CCA);
tc_clear_overflow(&EXP_TC0_0);
tc_clear_cc_interrupt(&EXP_TC0_0, TC_CCA);
Michael DM Dryden
committed
while (!tc_is_cc_interrupt(&EXP_TC0_0, TC_CCA)){ //wait until ADC TC CCA match
Michael DM Dryden
committed
if (udi_cdc_is_rx_ready()){ //check for abort signal over USB
if (getchar() == 'a')
return 1;
}
}
ads1255_wakeup();
while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5)));
forward = ads1255_read_single24();
ads1255_standby();
while (!tc_is_cc_interrupt(&EXP_TC0_1, TC_CCA)); //wait for end of half-cycle
Michael DM Dryden
committed
//switch voltage to baseline
max5443_set_voltage1(dacindex);
while (!tc_is_overflow(&EXP_TC0_0)){ //wait for ADC TC overflow
Michael DM Dryden
committed
if (udi_cdc_is_rx_ready()){
if (getchar() == 'a')
return 1;
}
}
ads1255_wakeup();
while (ioport_pin_is_high(IOPORT_CREATE_PIN(PORTD, 5)));
reverse = ads1255_read_single24();
ads1255_standby();
while (!tc_is_overflow(&EXP_TC0_1)); //wait for end of half-cycle
EXP_TC0_0.CNT = 0; // Resync ADC TC
Michael DM Dryden
committed
lastindex = dacindex;
//increment dacindex
if (direction == 1){
dacindex += dacindex_step;
max5443_set_voltage1(dacindex+dacindex_pulse_height);
}
else{
dacindex -= dacindex_step;
max5443_set_voltage1(dacindex-dacindex_pulse_height);
}
//data output
Michael DM Dryden
committed
struct
{
uint16_t lastindex;
int32_t forward;
int32_t reverse;
} data;
data.lastindex = lastindex;
data.forward = forward;
data.reverse = reverse;
Michael DM Dryden
committed
printf("B\n");
Michael DM Dryden
committed
udi_cdc_write_buf(&data, 10);
Michael DM Dryden
committed
printf("\n");
}
return 0;
}
Michael DM Dryden
committed
ISR(PORTD_INT0_vect){
if (portd_int0_callback) {
portd_int0_callback();
}