diff --git a/dstat_interface/dstat-interface.bat b/dstat_interface/dstat-interface.bat
index 031c2147b93a3881ae054470d674f286c8c25e53..da83e27ab1d09b0b02466c89f033c52a7621b484 100644
--- a/dstat_interface/dstat-interface.bat
+++ b/dstat_interface/dstat-interface.bat
@@ -1 +1 @@
-python .\__main__.py
+python .\main.py
diff --git a/dstat_interface/dstat_comm.py b/dstat_interface/dstat_comm.py
index 59b15d3b9254ab200575f3ab078b638d205797a6..d5edd59e98011c73cccdc7c39bae0ded203342fa 100644
--- a/dstat_interface/dstat_comm.py
+++ b/dstat_interface/dstat_comm.py
@@ -79,19 +79,6 @@ class SerialConnection(object):
         self.proc.start()
         
 
-def call_it(instance, name, args=(), kwargs=None):
-    """Indirect caller for instance methods and multiprocessing.
-    
-    Arguments:
-    instance -- instance to which the method belongs
-    name -- method to call
-    args -- passed to method
-    kwargs -- passed to method
-    """
-    if kwargs is None:
-        kwargs = {}
-    return getattr(instance, name)(*args, **kwargs)
-
 class VersionCheck:
     def __init__(self):
         pass
@@ -131,7 +118,31 @@ class VersionCheck:
         
         finally:
             return status
+
+def version_check(ser_port):
+    """Tries to contact DStat and get version. Returns a list of
+    [(major, minor), serial instance]. If no response, returns empty tuple.
         
+    Arguments:
+    ser_port -- address of serial port to use
+    """
+    try:        
+        global serial_instance
+        serial_instance = SerialConnection(ser_port)
+        
+        serial_instance.proc_pipe_p.send(VersionCheck())
+        result = serial_instance.proc_pipe_p.recv()
+        if result == "SERIAL_ERROR":
+            buffer = 1
+        else:
+            buffer = serial_instance.data_pipe_p.recv()
+        print result
+        
+        return buffer
+        
+    except:
+        pass
+
 class Settings:
     def __init__(self, task, settings=None):
         self.task = task
@@ -201,7 +212,39 @@ class Settings:
             self.ser.write(' ')
         
         return
-
+        
+def read_settings():
+    """Tries to contact DStat and get settings. Returns dict of
+    settings.
+    """
+    
+    global settings
+    settings = {}
+    
+    while serial_instance.data_pipe_p.poll():
+        serial_instance.data_pipe_p.recv()
+    
+    serial_instance.proc_pipe_p.send(Settings(task='r'))
+    settings = serial_instance.data_pipe_p.recv()
+    
+    print serial_instance.proc_pipe_p.recv()
+    
+    return
+    
+def write_settings():
+    """Tries to write settings to DStat from global settings var.
+    """
+    
+    while serial_instance.data_pipe_p.poll():
+        serial_instance.data_pipe_p.recv()
+    
+    serial_instance.proc_pipe_p.send(Settings(task='w', settings=settings))
+    
+    while serial_instance.proc_pipe_p.recv() != "DONE":
+        pass
+    
+    return
+    
 class LightSensor:
     def __init__(self):
         pass
@@ -238,37 +281,14 @@ class LightSensor:
         
         return status
 
-
-def version_check(ser_port):
-    """Tries to contact DStat and get version. Returns a list of
-    [(major, minor), serial instance]. If no response, returns empty tuple.
-        
-    Arguments:
-    ser_port -- address of serial port to use
-    """
-    try:
-        global serial_instance
-        serial_instance = SerialConnection(ser_port)
-        
-        serial_instance.proc_pipe_p.send(VersionCheck())
-        result = serial_instance.proc_pipe_p.recv()
-        if result == "SERIAL_ERROR":
-            buffer = 1
-        else:
-            buffer = serial_instance.data_pipe_p.recv()
-        print result
-        
-        return buffer
-        
-    except:
-        pass
-    
-    
 def read_light_sensor():
     """Tries to contact DStat and get light sensor reading. Returns uint of
     light sensor clear channel.
     """
     
+    while serial_instance.data_pipe_p.poll():
+        serial_instance.data_pipe_p.recv()
+        
     serial_instance.proc_pipe_p.send(LightSensor())
     
     while serial_instance.proc_pipe_p.recv() != "DONE":
@@ -276,32 +296,6 @@ def read_light_sensor():
     
     return serial_instance.data_pipe_p.recv()
     
-def read_settings():
-    """Tries to contact DStat and get settings. Returns dict of
-    settings.
-    """
-    
-    global settings
-    settings = {}
-    serial_instance.proc_pipe_p.send(Settings(task='r'))
-    settings = serial_instance.data_pipe_p.recv()
-    
-    while serial_instance.proc_pipe_p.recv() != "DONE":
-        pass
-    
-    return
-    
-def write_settings():
-    """Tries to write settings to DStat from global settings var.
-    """
-    
-    serial_instance.proc_pipe_p.send(Settings(task='w'))
-    
-    while serial_instance.proc_pipe_p.recv() != "DONE":
-        pass
-    
-    return
-    
 
 class delayedSerial(serial.Serial): 
     """Extends Serial.write so that characters are output individually
@@ -329,12 +323,6 @@ class Experiment(object):
     """Store and acquire a potentiostat experiment. Meant to be subclassed
     to by different experiment types and not used instanced directly.
     """
-    # def run_wrapper(self, *argv):
-    #     """Execute experiment indirectly using call_it to bypass lack of fork()
-    #     on Windows for multiprocessing.
-    #     """
-    #     self.proc = mp.Process(target=call_it, args=(self, 'run', argv))
-    #     self.proc.start()
 
     def __init__(self, parameters):
         """Adds commands for gain and ADC."""
@@ -399,16 +387,14 @@ class Experiment(object):
                 self.serial.write(i)
                 if not self.serial_handler():
                     status = "ABORT"
-                    break
-                
+            
+            self.data_postprocessing()
         except serial.SerialException:
             status = "SERIAL_ERROR"
-            
         finally:
-            self.data_postprocessing()
             while self.ctrl_pipe.poll():
                 self.ctrl_pipe.recv()
-            return status
+        return status
     
     def serial_handler(self):
         """Handles incoming serial transmissions from DStat. Returns False
@@ -468,6 +454,91 @@ class Experiment(object):
         """
         pass
 
+class CALExp(Experiment):
+    """Offset calibration experiment"""
+    def __init__(self, parameters):
+        self.parameters = parameters
+        self.databytes = 8
+        self.scan = 0
+        self.data = []
+
+        self.commands = ["EA2 3 1 ", "EG", "ER"]
+
+        self.commands[1] += str(self.parameters['gain'])
+        self.commands[1] += " "
+        self.commands[1] += "0 "
+        self.commands[2] += "1 32768 "
+        self.commands[2] += str(self.parameters['time'])
+        self.commands[2] += " "
+        self.commands[2] += "0 " # disable photodiode interlock
+        
+    def serial_handler(self):
+        """Handles incoming serial transmissions from DStat. Returns False
+        if stop button pressed and sends abort signal to instrument. Sends
+        data to self.data_pipe as result of self.data_handler).
+        """
+
+        try:
+            while True:
+                if self.ctrl_pipe.poll():
+                    print "serial_handler ctrl_pipe"
+                    input = self.ctrl_pipe.recv()
+                    print input
+                    if input == ('a' or "DISCONNECT"):
+                        self.serial.write('a')
+                        print "ABORT pressed!"
+                        return False
+                        
+                for line in self.serial:                    
+                    if self.ctrl_pipe.poll():
+                        if self.ctrl_pipe.recv() == 'a':
+                            self.serial.write('a')
+                            print "ABORT pressed"
+                            return False
+                            
+                    if line.startswith('B'):
+                        self.data.append(self.data_handler(
+                                        self.serial.read(size=self.databytes)))
+                        
+                    elif line.lstrip().startswith("#"):
+                        print line
+                        
+                    elif line.lstrip().startswith("no"):
+                        print line
+                        self.serial.flushInput()
+                        return True
+                        
+        except serial.SerialException:
+            return False
+            
+    def data_handler(self, data):
+        """Takes data_input as tuple -- (scan, data).
+        Returns:
+        current
+        """
+        
+        seconds, milliseconds, current = struct.unpack('<HHl', data)
+        return current
+    
+    def data_postprocessing(self):
+        """Averages data points
+        """
+        
+        sum = 0
+        self.data[0] = 0 # Skip first point
+        
+        for i in self.data:
+            sum += i
+        
+        sum /= len(self.data)
+        
+        if (sum > 32767):
+            sum = 32767
+        elif (sum < -32768):
+            sum = -32768
+        
+        self.data_pipe.send(sum)        
+
 class Chronoamp(Experiment):
     """Chronoamperometry experiment"""
     def __init__(self, parameters):
@@ -754,4 +825,21 @@ class OCPExp(Experiment):
         scan, data = data_input
         # 2*uint16 + int32
         seconds, milliseconds, voltage = struct.unpack('<HHl', data)
-        return (voltage/5.592405e6)
\ No newline at end of file
+        return (voltage/5.592405e6)
+        
+def measure_offset(time):
+    gain_trim_table = [None, 'r100_trim', 'r3k_trim', 'r30k_trim', 'r300k_trim',
+                        'r3M_trim', 'r30M_trim', 'r100M_trim']
+    
+    parameters = {}
+    parameters['time'] = time
+    
+    gain_offset = {}
+    
+    for i in range(1,8):
+        parameters['gain'] = i
+        serial_instance.proc_pipe_p.send(CALExp(parameters))
+        print serial_instance.proc_pipe_p.recv()
+        gain_offset[gain_trim_table[i]] = serial_instance.data_pipe_p.recv()
+        
+    return gain_offset
\ No newline at end of file
diff --git a/dstat_interface/interface/calib.glade b/dstat_interface/interface/calib.glade
index f5db97b6f4dc66772750ac69f76d29653a5ff552..2c72437a2aecb5ed935bd60f6206f56932605cae 100644
--- a/dstat_interface/interface/calib.glade
+++ b/dstat_interface/interface/calib.glade
@@ -26,10 +26,20 @@
                     <property name="n_rows">13</property>
                     <property name="n_columns">2</property>
                     <property name="homogeneous">True</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
+                    <child>
+                      <placeholder/>
+                    </child>
                     <child>
                       <object class="GtkEntry" id="time_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
+                        <property name="max_length">5</property>
                         <property name="invisible_char">●</property>
                         <property name="width_chars">8</property>
                         <property name="text" translatable="yes">0</property>
@@ -55,6 +65,7 @@
                         <property name="label" translatable="yes">Measurement Time (s)</property>
                       </object>
                       <packing>
+                        <property name="x_options"/>
                         <property name="y_options">GTK_FILL</property>
                       </packing>
                     </child>
@@ -78,6 +89,8 @@
                       <packing>
                         <property name="top_attach">2</property>
                         <property name="bottom_attach">3</property>
+                        <property name="x_options"/>
+                        <property name="x_padding">10</property>
                       </packing>
                     </child>
                     <child>
@@ -102,6 +115,7 @@
                       <packing>
                         <property name="top_attach">3</property>
                         <property name="bottom_attach">4</property>
+                        <property name="x_options"/>
                       </packing>
                     </child>
                     <child>
@@ -113,6 +127,7 @@
                       <packing>
                         <property name="top_attach">4</property>
                         <property name="bottom_attach">5</property>
+                        <property name="x_options">GTK_EXPAND</property>
                       </packing>
                     </child>
                     <child>
@@ -124,6 +139,7 @@
                       <packing>
                         <property name="top_attach">5</property>
                         <property name="bottom_attach">6</property>
+                        <property name="x_options">GTK_EXPAND</property>
                       </packing>
                     </child>
                     <child>
@@ -135,6 +151,7 @@
                       <packing>
                         <property name="top_attach">6</property>
                         <property name="bottom_attach">7</property>
+                        <property name="x_options">GTK_EXPAND</property>
                       </packing>
                     </child>
                     <child>
@@ -146,6 +163,7 @@
                       <packing>
                         <property name="top_attach">7</property>
                         <property name="bottom_attach">8</property>
+                        <property name="x_options">GTK_EXPAND</property>
                       </packing>
                     </child>
                     <child>
@@ -157,6 +175,7 @@
                       <packing>
                         <property name="top_attach">8</property>
                         <property name="bottom_attach">9</property>
+                        <property name="x_options">GTK_EXPAND</property>
                       </packing>
                     </child>
                     <child>
@@ -168,13 +187,14 @@
                       <packing>
                         <property name="top_attach">9</property>
                         <property name="bottom_attach">10</property>
+                        <property name="x_options">GTK_EXPAND</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkEntry" id="30k_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="max_length">4</property>
+                        <property name="max_length">6</property>
                         <property name="invisible_char">●</property>
                         <property name="width_chars">8</property>
                         <property name="text" translatable="yes">0</property>
@@ -199,7 +219,7 @@
                       <object class="GtkEntry" id="3k_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="max_length">4</property>
+                        <property name="max_length">6</property>
                         <property name="invisible_char">●</property>
                         <property name="width_chars">8</property>
                         <property name="text" translatable="yes">0</property>
@@ -224,7 +244,7 @@
                       <object class="GtkEntry" id="100_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="max_length">4</property>
+                        <property name="max_length">6</property>
                         <property name="invisible_char">●</property>
                         <property name="width_chars">8</property>
                         <property name="text" translatable="yes">0</property>
@@ -249,7 +269,7 @@
                       <object class="GtkEntry" id="300k_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="max_length">4</property>
+                        <property name="max_length">6</property>
                         <property name="invisible_char">●</property>
                         <property name="width_chars">8</property>
                         <property name="text" translatable="yes">0</property>
@@ -274,7 +294,7 @@
                       <object class="GtkEntry" id="3M_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="max_length">4</property>
+                        <property name="max_length">6</property>
                         <property name="invisible_char">●</property>
                         <property name="width_chars">8</property>
                         <property name="text" translatable="yes">0</property>
@@ -299,7 +319,7 @@
                       <object class="GtkEntry" id="30M_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="max_length">4</property>
+                        <property name="max_length">6</property>
                         <property name="invisible_char">●</property>
                         <property name="width_chars">8</property>
                         <property name="text" translatable="yes">0</property>
@@ -324,7 +344,7 @@
                       <object class="GtkEntry" id="100M_entry">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="max_length">4</property>
+                        <property name="max_length">6</property>
                         <property name="invisible_char">●</property>
                         <property name="width_chars">8</property>
                         <property name="text" translatable="yes">0</property>
@@ -385,6 +405,7 @@
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">True</property>
+                        <signal name="clicked" handler="on_measure_button_clicked" swapped="no"/>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
@@ -395,15 +416,6 @@
                         <property name="y_options">GTK_EXPAND | GTK_SHRINK | GTK_FILL</property>
                       </packing>
                     </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
-                    <child>
-                      <placeholder/>
-                    </child>
                   </object>
                   <packing>
                     <property name="expand">False</property>
@@ -415,9 +427,10 @@
                   <object class="GtkLabel" id="label13">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="xpad">20</property>
+                    <property name="xpad">5</property>
                     <property name="ypad">20</property>
-                    <property name="label" translatable="yes">Measure with WE open. Offsets cannot exceed 16 bit unsigned int.</property>
+                    <property name="label" translatable="yes">Measure with WE open.
+Offsets cannot exceed 16 bit unsigned int.</property>
                     <attributes>
                       <attribute name="weight" value="bold"/>
                     </attributes>
diff --git a/dstat_interface/interface/exp_int.py b/dstat_interface/interface/exp_int.py
index 682d375124a92eb63d12f2036256926b08490127..edc13d09478a7c4a929660b35b86fdffc2f098fa 100644
--- a/dstat_interface/interface/exp_int.py
+++ b/dstat_interface/interface/exp_int.py
@@ -262,40 +262,100 @@ class CAL(ExpInterface):
         self.entry['R30M'] = self.builder.get_object('30M_entry')
         self.entry['R100M'] = self.builder.get_object('100M_entry')
         
-    def on_read_button_clicked(self, data=None):
-        __main__.MAIN.on_pot_stop_clicked()
+        self.buttons = [self.builder.get_object('read_button'),
+                        self.builder.get_object('write_button'),
+                        self.builder.get_object('measure_button')]
         
-        gobject.source_remove(__main__.MAIN.ocp_proc)
-        dstat_comm.read_settings()
-
-        self.entry['R100'].set_text(str(
-            dstat_comm.settings['r100_trim'][1]))
-        self.entry['R3k'].set_text(str(
-            dstat_comm.settings['r3k_trim'][1]))
-        self.entry['R30k'].set_text(str(
-            dstat_comm.settings['r30k_trim'][1]))
-        self.entry['R300k'].set_text(str(
-            dstat_comm.settings['r300k_trim'][1]))
-        self.entry['R3M'].set_text(str(
-            dstat_comm.settings['r3M_trim'][1]))
-        self.entry['R30M'].set_text(str(
-            dstat_comm.settings['r30M_trim'][1]))
-        self.entry['R100M'].set_text(str(
-            dstat_comm.settings['r100M_trim'][1]))
-   
-        __main__.MAIN.start_ocp()
+    def on_read_button_clicked(self, data=None):        
+        for i in self.buttons:
+            i.set_sensitive(False)
+        
+        try:
+            __main__.MAIN.on_pot_stop_clicked()
+            gobject.source_remove(__main__.MAIN.ocp_proc)
+            dstat_comm.read_settings()
+    
+            self.entry['R100'].set_text(str(
+                dstat_comm.settings['r100_trim'][1]))
+            self.entry['R3k'].set_text(str(
+                dstat_comm.settings['r3k_trim'][1]))
+            self.entry['R30k'].set_text(str(
+                dstat_comm.settings['r30k_trim'][1]))
+            self.entry['R300k'].set_text(str(
+                dstat_comm.settings['r300k_trim'][1]))
+            self.entry['R3M'].set_text(str(
+                dstat_comm.settings['r3M_trim'][1]))
+            self.entry['R30M'].set_text(str(
+                dstat_comm.settings['r30M_trim'][1]))
+            self.entry['R100M'].set_text(str(
+                dstat_comm.settings['r100M_trim'][1]))
+    
+            __main__.MAIN.start_ocp()
+            
+        finally:
+            for i in self.buttons:
+                i.set_sensitive(True)
         
     def on_write_button_clicked(self, data=None):
-        __main__.MAIN.on_pot_stop_clicked()
-        gobject.source_remove(__main__.MAIN.ocp_proc)
+        for i in self.buttons:
+            i.set_sensitive(False)
+        
+        try:
+            __main__.MAIN.on_pot_stop_clicked()
+            gobject.source_remove(__main__.MAIN.ocp_proc)
+            
+            dstat_comm.settings['r100_trim'][1] = self.entry['R100'].get_text()
+            dstat_comm.settings['r3k_trim'][1] = self.entry['R3k'].get_text()
+            dstat_comm.settings['r30k_trim'][1] = self.entry['R30k'].get_text()
+            dstat_comm.settings['r300k_trim'][1] = self.entry['R300k'].get_text()
+            dstat_comm.settings['r3M_trim'][1] = self.entry['R3M'].get_text()
+            dstat_comm.settings['r30M_trim'][1] = self.entry['R30M'].get_text()
+            dstat_comm.settings['r100M_trim'][1] = self.entry['R100M'].get_text()
+            dstat_comm.write_settings()        
+                                
+            __main__.MAIN.start_ocp()
+            
+        finally:
+            for i in self.buttons:
+                i.set_sensitive(True)
+                
+    def on_measure_button_clicked(self, data=None):
+        if (int(self.entry['time'].get_text()) <= 0 or int(self.entry['time'].get_text()) > 65535):
+            print "ERR: Time out of range"
+            return
+        
+        for i in self.buttons:
+            i.set_sensitive(False)
+        
+        try:
+            __main__.MAIN.on_pot_stop_clicked()
+            gobject.source_remove(__main__.MAIN.ocp_proc)
+            __main__.MAIN.spinner.start()
+            
+            offset = dstat_comm.measure_offset(self.get_params()['time'])
+            
+            for i in offset:
+                print i
+                print str(-offset[i])
+                dstat_comm.settings[i][1] = str(-offset[i])
+            
+            self.entry['R100'].set_text(str(
+                dstat_comm.settings['r100_trim'][1]))
+            self.entry['R3k'].set_text(str(
+                dstat_comm.settings['r3k_trim'][1]))
+            self.entry['R30k'].set_text(str(
+                dstat_comm.settings['r30k_trim'][1]))
+            self.entry['R300k'].set_text(str(
+                dstat_comm.settings['r300k_trim'][1]))
+            self.entry['R3M'].set_text(str(
+                dstat_comm.settings['r3M_trim'][1]))
+            self.entry['R30M'].set_text(str(
+                dstat_comm.settings['r30M_trim'][1]))
+            self.entry['R100M'].set_text(str(
+                dstat_comm.settings['r100M_trim'][1]))
+            __main__.MAIN.start_ocp()
         
-        dstat_comm.settings['r100_trim'][1] = self.entry['R100'].get_text()
-        dstat_comm.settings['r3k_trim'][1] = self.entry['R3k'].get_text()
-        dstat_comm.settings['r30k_trim'][1] = self.entry['R30k'].get_text()
-        dstat_comm.settings['r300k_trim'][1] = self.entry['R300k'].get_text()
-        dstat_comm.settings['r3M_trim'][1] = self.entry['R3M'].get_text()
-        dstat_comm.settings['r30M_trim'][1] = self.entry['R30M'].get_text()
-        dstat_comm.settings['r100M_trim'][1] = self.entry['R100M'].get_text()
-        dstat_comm.write_settings()        
-                            
-        __main__.MAIN.start_ocp()
\ No newline at end of file
+        finally:
+            for i in self.buttons:
+                i.set_sensitive(True)
+            __main__.MAIN.spinner.stop()
\ No newline at end of file
diff --git a/dstat_interface/__main__.py b/dstat_interface/main.py
similarity index 99%
rename from dstat_interface/__main__.py
rename to dstat_interface/main.py
index 64619738042a501d408c4ea985c2d4b629630cec..fbf795cb200cdcd80f0a681415607a862497444f 100755
--- a/dstat_interface/__main__.py
+++ b/dstat_interface/main.py
@@ -731,6 +731,8 @@ class Main(object):
         for i in self.current_exp.commands:
             self.rawbuffer.insert_at_cursor(i)
 
+        self.rawbuffer.insert_at_cursor("\n")
+
         for col in zip(*self.current_exp.data):
             for row in col:
                 self.rawbuffer.insert_at_cursor(str(row)+ "    ")
@@ -769,6 +771,9 @@ class Main(object):
             comm.serial_instance.ctrl_pipe_p.send('a')
             while not (comm.serial_instance.proc_pipe_p.recv() == "ABORT"):
                 pass
+                
+            while comm.serial_instance.data_pipe_p.poll():
+                comm.serial_instance.data_pipe_p.recv() 
         except AttributeError:
             pass
         except: