experiment.c 36.5 KiB
Newer Older
/*
 * experiment.c
 *
 * Created: 01/10/2012 10:59:48 PM
 *  Author: mdryden
 */ 
/**
 * @file experiment.c
 * @author  Michael DM Dryden <mdryden@chem.utoronto.ca>
 * @version 1.0
 *
 *
 * @section DESCRIPTION
 *
 * Contains Functions for performing experiments and adjusting potentiostat settings other than DAC and ADC.
 */
#include "shutter.h"
#include <util/atomic.h>
//Private variables
volatile int32_t voltage = 0;
volatile uint16_t dacindex = 0;
uint16_t dacindex_stop = 0;
volatile int8_t up = 1;
volatile uint16_t iter = 0;
uint16_t* eis_ptr = 0;
volatile uint16_t cycles = 0;
volatile uint16_t samples = 0;
volatile uint16_t tcf0period = 0;
uint32_t skip_samples = 0;

//Private function declarations
//uint16_t set_timer_period(uint32_t period, volatile void *tc);
static void precond_rtc_callback(uint32_t time);
static void porte_int0_lsv(void);
static void tcf0_ovf_callback(void);
static void tce1_ovf_callback_lsv(void);
static void lsv_cca_callback(void);
static void ca_cca_callback(void);
static void portd_int0_ca(void);
static uint8_t _swv_singledir(uint16_t dacindex, uint16_t dacindex_stop, uint16_t dacindex_pulse_height, uint16_t dacindex_step, uint8_t direction);
static uint8_t _dpv_singledir(uint16_t dacindex, uint16_t dacindex_stop, uint16_t dacindex_pulse_height, uint16_t dacindex_step, uint8_t direction);
Michael DM Dryden's avatar
Michael DM Dryden committed
static void pmt_idle(void);

//interrupt callback setup
typedef void (*port_callback_t) (void);

static port_callback_t portd_int0_callback;
static port_callback_t portd_int1_callback;

void experiment_handler(char command[]){
Michael DM Dryden's avatar
 
Michael DM Dryden committed
    static uint16_t u1, u2, u3, u4, u5, u6;
    static uint8_t p5, o1, o2, o3;
    static int16_t pcv1, pcv2;
    static uint16_t pct1, pct2;
    uint16_t tcs_data[] = {0,0,0,0};
    uint16_t tcs_data1[] = {0,0,0,0};
        case 'A': //ADS Buffer/rate/PGA values from ads1255.h
            sscanf(command+1, "%hhx%hhx%hhx",&o1,&o2,&o3);
            printf("#A: %x %x %x\n",o1,o2,o3);
            sscanf(command+1, "%u%hhu",&g_gain, &g_short);
            printf("#G: %u %u\n", g_gain, g_short);
            pot_set_gain(); //uses global g_gain, so no params
            break;
            
        case 'L': //LSV - start, stop, slope
Michael DM Dryden's avatar
 
Michael DM Dryden committed
            if (settings.settings.dac_units_true) {
                sscanf(command+1, "%u%u%u%u%u%u%u",&pct1,&pct2,&pcv1,&pcv2,&u1,&u2,&u3);
                precond(pcv1,pct1,pcv2,pct2);
                lsv_experiment(u1,u2,u3,2);
            } else {
                sscanf(command+1, "%u%u%i%i%i%i%u",&pct1,&pct2,&pcv1,&pcv2,&p1,&p2,&u1);
                
                //start
                u2 = ceil(p1*(65536/(double)3000)+32768);
                //stop
                u3 = ceil(p2*(65536/(double)3000)+32768);
                
                precond(pcv1,pct1,pcv2,pct2);
                lsv_experiment(u2,u3,u1,2);
            }
Michael DM Dryden's avatar
 
Michael DM Dryden committed
            if (settings.settings.dac_units_true) {
                sscanf(command+1, "%u%u%i%i%u%u%u%hhu%u",&pct1,&pct2,&pcv1,&pcv2,&u1,&u2,&u3,&p5,&u4);
                precond(pcv1,pct1,pcv2,pct2);
                cv_experiment(u1,u2,u3,p5,u4);
            } else {
                sscanf(command+1, "%u%u%i%i%i%i%i%hhu%u",&pct1,&pct2,&pcv1,&pcv2,&p1,&p2,&p3,&p5,&u4);
                
                //v1
                u1 = ceil(p1*(65536/(double)3000)+32768);
                //v2
                u2 = ceil(p2*(65536/(double)3000)+32768);
                //start
                u3 = ceil(p3*(65536/(double)3000)+32768);
                //slope
                u4 = ceil(u4*(65536/(double)3000));
                
                precond(pcv1,pct1,pcv2,pct2);
                cv_experiment(u1,u2,u3,p5,u4);
            }
            break;
            
        case 'S': //SWV - start, stop, step size, pulse_height, frequency, scans
Michael DM Dryden's avatar
 
Michael DM Dryden committed
            if (settings.settings.dac_units_true) {
                sscanf(command+1, "%u%u%i%i%u%u%u%u%u%hhu",&pct1,&pct2,&pcv1,&pcv2,&u1,&u2,&u3,&u4,&u5,&p5);
                precond(pcv1,pct1,pcv2,pct2);
                swv_experiment(u1,u2,u3,u4,u5,p5);
            } else {
                sscanf(command+1, "%u%u%i%i%i%i%u%u%u%hhu",&pct1,&pct2,&pcv1,&pcv2,&p1,&p2,&u1,&u2,&u3,&p5);
                
                //start
                uint16_t start = ceil(p1*(65536/(double)3000)+32768);
                //stop
                uint16_t stop = ceil(p2*(65536/(double)3000)+32768);
                //step
                u1 = ceil(u1*(65536/(double)3000));
                //pulse_height
                u2 = ceil(u2*(65536/(double)3000));
                
                precond(pcv1,pct1,pcv2,pct2);
                swv_experiment(start,stop,u1,u2,u3,p5);
            }
            break;
            
        case 'D': //DPV - start, stop, step size, pulse_height, period, width
Michael DM Dryden's avatar
 
Michael DM Dryden committed
            if (settings.settings.dac_units_true) {
                sscanf(command+1, "%u%u%i%i%u%u%u%u%u%u",&pct1,&pct2,&pcv1,&pcv2,&u1,&u2,&u3,&u4,&u5,&u6);
                precond(pcv1,pct1,pcv2,pct2);
                dpv_experiment(u1,u2,u3,u4,u5,u6);
            } else {
                sscanf(command+1, "%u%u%i%i%i%i%u%u%u%u",&pct1,&pct2,&pcv1,&pcv2,&p1,&p2,&u1,&u2,&u3,&u4);
                
                //start
                uint16_t start = ceil(p1*(65536/(double)3000)+32768);
                //stop
                uint16_t stop = ceil(p2*(65536/(double)3000)+32768);
                //step
                u1 = ceil(u1*(65536/(double)3000));
                //pulse_height
                u2 = ceil(u2*(65536/(double)3000));
                
                precond(pcv1,pct1,pcv2,pct2);
                dpv_experiment(start,stop,u1,u2,u3,u4);
            }
Michael DM Dryden's avatar
Michael DM Dryden committed
        case 'M': //PMT idle mode - holds voltage at 0 V with no data output
            pmt_idle();
            break;
            
        #if BOARD_VER_MAJOR == 1 && BOARD_VER_MINOR >= 2
        case 'P': //potentiometry - time, OCP/poteniometry
            sscanf(command+1, "%u%hhu",&pct1, &o1);
            pot_experiment(pct1, o1);
            break;
        #endif
            
        case 'R': //CA - steps, step_dac[], step_seconds[]
        {
            sscanf(command+1, "%hhu%hhu",&p5, &o1); //get number of steps
            printf("#INFO: Steps: %u\n", p5);
            
            //allocate arrays for steps
            uint16_t * step_dac = malloc(p5*sizeof(uint16_t));
            uint16_t * step_seconds = malloc(p5*sizeof(uint16_t));
            
            //check for successful allocation
            if (!step_dac || !step_seconds){
                printf("#ERR: Could not allocate memory\n");
            //request additional parameters from computer
            printf("@RQP %u\n", 2*(uint16_t)p5);
            
            uint16_t i;
            uint8_t result;
Loading full blame...