"""mems.instrument.hardware.inm200

Serial port and microscope control classes for the Leica INM200
microscope, for opening simple RS-232 connections, and for
controlling the Ergoplan and LUDL devices to steer the optics and
stage.
"""

__revision__ = "$Id: inm200.py,v 1.17 2002/03/29 17:03:22 akuchlin Exp $"

# created 1999/12/26, AMK

import sys, os, select, string, time, struct
import math

from mems.instrument.hardware import leica
from mems.instrument import protocols
from mems.instrument.server import util
from mems.instrument.server.configuration import get_configuration

# Global variables holding the controller object
scope = None

# The SCALES dictionary maps a given magnification to the width and
# height of the camera's field of vision, measured in microns.
# According to Ray Malone of Leica, one stage unit = 0.4 microns.

SCALES = {100: (180, 140)}

# List of magnifications; this must be ordered in the same order as
# the microscope handles them.  Only the scale value at 100x has been
# measured; values for lower magnifications are computed from the 100x 
# values by scaling them.  
 
MAGNIFICATIONS = [5, 10, 20, 50, 100]
for i in MAGNIFICATIONS:
    if SCALES.has_key(i): continue
    x, y = SCALES[100]
    factor = 100 / i
    SCALES[i] = x*factor, y*factor


def update_network():
    x_scale, y_scale = SCALES[scope.magnification]
    
    args = {'x':scope.x, 'y':scope.y, 'z':scope.z - scope.z_autofocus,
            'magnification': scope.magnification,
            'mode': scope.mode, 'aperture':scope.aperture,
            'light': (scope.light*100/255),
            'x_scale': x_scale, 'y_scale':y_scale,
            'angle':0,
        }
    
    msg = protocols.build_message_line('scope', **args)
    util.send_message('network_server', msg)
    
def do_move(x=None, y=None, z=None, angle=None):
    if x is not None:     scope.set(x=x)
    if y is not None:     scope.set(y=y)
#    if z is not None:     scope.set(z=z)

def do_magnification(value):
    assert value in [5,10,20,50,100]
    scope.set(magnification=value)

def do_mode(value):
    value = value.lower()
    assert value in [protocols.MODE_BRIGHTFIELD,
                     protocols.MODE_DARKFIELD,
                     protocols.MODE_ICR]
    scope.set(mode=value)
    
def do_light(value):
    assert 0<= value <= 100
    scope.set(light=value*255/100)
    
def do_aperture(value):
    assert 1 <= value <= 5
    scope.set(aperture=value)
    
def do_autofocus(value):
    assert value in ['on', 'off']
    scope.set(autofocus=value)
    

def main():
    config = get_configuration()

    global scope
    scope = leica.Microscope()
    
    while 1:
        if util.has_input_waiting(sys.stdin, 10):
            line = sys.stdin.readline()
            if line == "": continue
            cmd, args = protocols.parse_message_line(line)

            if config.get_debug():
                print '%s: Received command %s %r' % (__name__, cmd, args)

            if cmd == 'quit':
                if config.get_debug():
                    print '%s: exiting' % __name__
                break
            elif cmd == "move":
                do_move(**args)
            elif cmd == "magnification":
                do_magnification(**args)
            elif cmd == "mode":
                do_mode(**args)
            elif cmd == "light":
                do_light(**args)
            elif cmd == "aperture":
                do_aperture(**args)
            elif cmd == "autofocus":
                do_autofocus(**args)
            else:
                raise RuntimeError, ("Unknown command %r args=%r" % (cmd, args))

            # Read the microscope's new status and update the clients
	    util.send_message('camera', 'snapshot')
	    update_network()

        else:
            scope.read_hardware_status()
            
    return 
