Newer
Older
*/
Michael DM Dryden
committed
PORTD.INTCTRL = PORT_INT0LVL_OFF_gc;
up = 0;
return;
}
void swv_experiment(uint16_t start, uint16_t stop, uint16_t step, uint16_t pulse_height, uint16_t frequency, uint8_t scans){
Michael DM Dryden
committed
/**
* Perform a SWV experiment
*
* @param start Start voltage in dac units.
* @param stop Stop voltage in dac units.
* @param step Step voltage in dac units.
* @param pulse_height Pulse amplitude in dac units.
Michael DM Dryden
committed
* @param frequency Frequency in Hz.
Michael DM Dryden
committed
* @param scans Number of scans (0 for single direction mode)
Michael DM Dryden
committed
*/
Michael DM Dryden
committed
uint8_t direction;
uint32_t period;
if (start < stop)
Michael DM Dryden
committed
direction = 1;
Michael DM Dryden
committed
else
Michael DM Dryden
committed
direction = 0;
Michael DM Dryden
committed
tc_enable(&EXP_TC0_1);
tc_enable(&EXP_TC0_0);
Michael DM Dryden
committed
frequency *= 2; //compensate for half-period triggers
//calculate time to ADC trigger
period = ceil((1/(double)frequency)*F_CPU);
uint32_t adc_period = ceil(((1/(double)frequency)-(double)(sample_delay_ms_100div/1e5))*F_CPU);
set_timer_period(period, &EXP_TC0_1);
set_timer_period(adc_period, &EXP_TC0_0);
Michael DM Dryden
committed
ads1255_wakeup();
ads1255_standby();
Michael DM Dryden
committed
Michael DM Dryden
committed
Michael DM Dryden
committed
do{
EXP_TC0_1.CNT = 0;
EXP_TC0_0.CNT = 0;
Michael DM Dryden
committed
Michael DM Dryden
committed
goto aborting; //function will return non-zero if abort called over USB
Michael DM Dryden
committed
Michael DM Dryden
committed
if (scans > 0){ //non-cyclic mode skips out after one direction
EXP_TC0_1.CNT = 0;
EXP_TC0_0.CNT = 0;
if (_swv_singledir(stop, start, pulse_height, step, !direction)) //swap start and stop and invert direction for second half of scan
Michael DM Dryden
committed
goto aborting;
}
Michael DM Dryden
committed
Michael DM Dryden
committed
} while (scans-- > 1); //will underflow after comparison for scans = 0 , but shouldn't matter
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);
EXP_TC0_1.CNT = 0;
tc_write_clock_source(&EXP_TC0_0, TC_CLKSEL_OFF_gc);
tc_disable(&EXP_TC0_0);
EXP_TC0_0.CNT = 0;
Michael DM Dryden
committed
ads1255_standby();
return;
}
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
}
void dpv_experiment(uint16_t start, uint16_t stop, uint16_t step, uint16_t pulse_height, uint16_t pulse_period, uint16_t pulse_width){
Michael DM Dryden
committed
/**
* Perform a DPV experiment
*
* @param start Start voltage in dac units.
* @param stop Stop voltage in dac units.
* @param step Step voltage in dac units.
* @param pulse_height Pulse amplitude in dac units.
Michael DM Dryden
committed
* @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));
Michael DM Dryden
committed
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
Michael DM Dryden
committed
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
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
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();
}