diff --git a/china_io-2019/python/calibrator.py b/china_io-2019/python/calibrator.py
index 51423c5770ef23ecacbcba47a7dcad864a9abdbc..81f4160264d8132231f676bec595cc9d5b7e1f7e 100755
--- a/china_io-2019/python/calibrator.py
+++ b/china_io-2019/python/calibrator.py
@@ -6,6 +6,7 @@ import numpy
 import traceback
 from serialio import SerialIO
 import math
+import curses
 
 class Welford:
 
@@ -27,7 +28,7 @@ class Welford:
         return self.M
     
     def stddev(self):
-        if self.k==1:
+        if self.k==1:                # Loop until external ref disabled
             return 0
         return math.sqrt(self.S/(self.k-1))
 
@@ -41,22 +42,53 @@ class ChinaIO:
     AIN_STEP = 20/(1<<18) # 20V, 18 bit resolution
     AOUT_STEP = 20/(1<<16) # 20V, 18 bit resolution
 
-    def __init__(self, port):
+    def __init__(self, stdscr, port):
+        self.stdscr = stdscr
         self.io = SerialIO(port)
         self.action_msg = ""
         self.status_msg = ""
+        begin_x = 20; begin_y = 7
+        height = 5; width = 40
+        if self.stdscr:
+            self.iowin = curses.newwin(2 + len(self.io.analogIn()), 80, 0,0)
+            self.gotoxy(0,0)
+            pass
         pass
     
     def close(self):
         self.io.setchannel(self.ANALOG_OUT_0, 0x8000)
         self.io.setchannel(self.ANALOG_OUT_1, 0x8000)
+        pass
+
+    def gotoxy(self, x, y):
+        if self.stdscr == None:
+            return
+        self.iowin.move(y,x)
+
+    def print(self, *args, **kwargs):
+        if self.stdscr == None:
+            print(*args, **kwargs)
+            return
+
+        for s in args:
+            try:
+                self.iowin.addstr(s)
+            except:
+                pass
+            pass
+        if not 'end' in kwargs or kwargs['end'] != '':
+            self.iowin.refresh()
+            pass
 
     def measure(self, analogIn, N=100, message=''):
         time.sleep(0.1)
         stat = {}
         for b in range(N):
-            print(message, '[',  end='')
-            for i,c in analogIn.items():
+            self.gotoxy(0,0)
+            self.print(message, end='')
+            channels = analogIn.items()
+            for i,c in channels:
+                self.gotoxy(0,i+2)
                 value = (self.io.getchannel(i) - (1<<17)) * self.AIN_STEP
                 if not i in stat:
                     stat[i] = Welford(value)
@@ -64,11 +96,11 @@ class ChinaIO:
                 else:
                     stat[i].update(value)
                     pass
-                print('%s ' % stat[i], end='')
+                self.print('%s ' % stat[i], end='')
                 pass
-            print(']', end='\r')
+            self.print(end='\r')
             pass
-        print()
+        self.print()
         return [ stat[i] for i in sorted(stat.keys()) ]
 
     def setCalibration(self, index, value):
@@ -90,10 +122,11 @@ class ChinaIO:
                 pass
             pass
         time.sleep(0.1) # Let values settle
-        sample = self.measure(analogIn, N=N, message=message)
-        for e,v in zip(expect, sample):
+        self.gotoxy(0,1)
+        self.print("Ref=", str(ref), " Expecting=", str(expect))
+        self.sample = self.measure(analogIn, N=N, message=message)
+        for e,v in zip(expect, self.sample):
             if e != None and (v.mean() < e[0] or e[1] < v.mean()):
-                print("      Expected:", expect)
                 return False
             pass
         return True
@@ -132,13 +165,41 @@ class ChinaIO:
         self.setCalibration(0, 0x8000)
         self.setCalibration(1, 0x8000)
 
-        # Read values from grounded inputs
-        while not self.expect(analogIn,
-                              [ -9, 9 ], 
-                              [ (-0.1, 0.1), (-0.1, 0.1),
-                                (-0.1, 0.1), (-0.1, 0.1) ],
-                              N=500,
-                              message='Ground all input pins'):
+        # Loop while connected to test harness 5V ref
+        badSamples = 0
+        inHarness = 0
+        while True:
+            badSamples += 1
+            if self.expect(analogIn,
+                               [ 0, 0 ], 
+                               [ (4.5, 5.5), (-0.1, 0.1),
+                                 (4.5, 5.5), (-0.1, 0.1) ],
+                               N=50,
+                               message='Checking if in test harness 1'):
+                badSamples = 0
+                pass
+            if self.expect(analogIn,
+                           [ 0, 0 ], 
+                           [ (-0.1, 0.1), (4.5, 5.5), 
+                             (-0.1, 0.1), (4.5, 5.5) ],
+                           N=50,
+                           message='Checking if in test harness 2'):
+                badSamples = 0
+                pass
+            inHarness += 1
+            if badSamples > 4:
+                break
+            pass
+
+        if inHarness < 10:
+            # Read values from grounded inputs
+            while not self.expect(analogIn,
+                                  [ -9, 9 ],
+                                  [ (-0.1, 0.1), (-0.1, 0.1),
+                                    (-0.1, 0.1), (-0.1, 0.1) ],
+                                  N=500,
+                                  message='Ground all input pins'):
+                pass
             pass
 
         # Connect AOut0 -> AIn0,AIn2 (+9V)
@@ -197,7 +258,7 @@ class ChinaIO:
             pass
         best = [ sorted(candidate[0], key=lambda x: abs(x[1].mean())),
                  sorted(candidate[1], key=lambda x: abs(x[1].mean())) ]
-        print("Done %x %x : %x %x" % (v0, v1, best[0][0][0], best[1][0][0]))
+        self.print("Done %x %x : %x %x" % (v0, v1, best[0][0][0], best[1][0][0]))
         v0 = best[0][0][0]
         v1 = best[0][0][0]
         self.setCalibration(0, v0)
@@ -210,9 +271,9 @@ class ChinaIO:
         self.setVoltage(0, 9)
         self.setVoltage(1, 9)
         max_sample = self.measure(analogIn, N=200, message='Max (+9V)')
-        print("0: Min: %f, Max: %f" % (min_sample[0].mean() / 9 * 10,
+        self.print("0: Min: %f, Max: %f" % (min_sample[0].mean() / 9 * 10,
                                        max_sample[0].mean() / 9 * 10))
-        print("1: Min: %f, Max: %f" % (min_sample[1].mean() / 9 * 10,
+        self.print("1: Min: %f, Max: %f" % (min_sample[1].mean() / 9 * 10,
                                        max_sample[1].mean() / 9 * 10))
         def millivolt(v):
             return int(v * 1000)
@@ -228,15 +289,19 @@ class ChinaIO:
             tmp = (int(-value * 1000) << 8) | 0x80 | index
         else:
             tmp = (int(value * 1000) << 8) | index
-        print("%d %8x" % (index, tmp))
+        self.print("%d %8x" % (index, tmp))
         self.io.setchannel(31, tmp, 0xffffffff)
         
-if __name__ == "__main__":
-    io = ChinaIO(sys.argv[1])
+
+def main(stdscr):
+    io = ChinaIO(stdscr, sys.argv[1])
     try:
         io.calibrate()
-    except:
-        traceback.print_exc()
         pass
+    finally:
+        io.close()
+        pass
+    pass
 
-    io.close()
+if __name__ == "__main__":
+    curses.wrapper(main)