#!/usr/bin/env python

## @package CreativePeach Peripherial Handling Library.
# This library lets you program peripherial cards on high level. It's classes makes following functions easier: connecting to ppds,
# data exchange with driver, raw communication data handling, splitting, and joining data, manipulating bits of data.
# It provides handling classes to most type of cards. Due to this, you can switch digital outputs using their functional name, 
# you can use eventhandlers when digital or analog inputs changes, and also use DC motors, which can be driven using simple commands.
# Writing to LCD display is also easy with simple commands. With the help of eventhandlers of matrix keyboard and rotary encoder handling 
# becomes very easy. The library contains statemachine, timer, and testing class for checking functions of cards.

SoftwareInfo = \
    {
      'Name'     : 'cpphlib.py',
      'Function' : 'CreativePeach Peripherial Handling Library',
      'Design'   : 'CreativePeach c 2013',
      'Version'  : '1.0',
    }

import time
import threading
import os
import sys
import socket
import select
import math
import commands
import Queue
import curses

## The debugger. <B></B> <I></I>  <B><I></I></B>
# This class makes you able to debug your controller program while it is running.
# You can wite data to the file defined in constructor with the help of <B>writetolog</B> method.
class PPDEBUG:
    """Short description: Debugger class"""
    ## Documentation for method. 
    # @param Logname The name of the log with path
    # @param Timewrite If it's value is <B><I>True</I></B>, then the line of the logentry starts with timestamp,
    # if the value is <B><I>False</I></B>, it does not write timestamp.
    # <BR><BR>
    def __init__(self, Logname, Timewrite):
        """Short description: Constructs PPDEBUG class"""
        self._timewrite = Timewrite
        self._logname = Logname

    ## Documentation for method. 
    # @param Text The text to dislplay
    # <BR><BR>
    def writetolog(self, Text):
        """Short description: It writes debug text into the log file"""
        self._logfile = open(self._logname, "a")
        if self._timewrite:
           self._logfile.write(time.strftime('%X %x %Z')+" > ")
        self._logfile.write(Text+"\r\n")
        self._logfile.close()


## The basic communication with any socket. <B></B> <I></I>  <B><I></I></B>
# This class deals with the main socket communication. It connects to the specified computers specified port.
# Using it's <B>send</B> method, data can be sent to the specified computer, a stand alone thread (<B>run</B>) deals with receiving  
# data from a specified computer to load into the receiving queue. 
# The <B>getinputflag</B> method always indicates whether there is received data in the receiving queue, which data can be read using <B>getinputdata</B> method.
# <B>disconnect</B> method disconnects socket connection, <B>stop</B> method stops receiving thread. The <B>commandstatemachine</B> method can check answers got for sent packages.
class PPDCommThread(threading.Thread):
    """Short description: Communication interface class"""
    
    ## Documentation for method.
    # @param IPAddr IP address of the machine which ppds driver is running on
    # @param IPPort The port which ppds driver has opened for the granted interface
    # @param IdentfyText Identifier text, what interface displays when client is connected
    # @param SilentMode Switches silent mode ON/OFF. It can be <B><I>True</I></B> or <B><I>False</I></B>
    # <BR><BR>
    def __init__(self, IPAddr, IPport, IdentfyText, SilentMode = True):
        """Short description: Constructs PPDCommThread class"""
        threading.Thread.__init__(self)
        self.RunFlag = True
        self.InputFlag = False
        self.IPAddr = IPAddr
        self.IPport = IPport
        self.IdentfyText = IdentfyText
        self.SilentMode = SilentMode
        self.RCVQ = Queue.Queue()

    def connect(self):
        """Short description: Connects to ppds interface"""
        self.Comm = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            self.Comm.connect((self.IPAddr, self.IPport))
            self.start()
        except:
            if not self.SilentMode:
                print "Failed to connect to the server."
            sys.exit(1)
        if not self.SilentMode:    
            print "PPDS interface is identified."
        Answer = ""
        StartTime = int(time.time()*1000)
        TimeOut = 0
        OverTimeOut = 2000       
        while (self.IdentfyText not in Answer) and (TimeOut < OverTimeOut):
            if self.getinputflag():
                Answer = Answer + self.getinputdata()
            TimeOut = int(time.time()*1000) - StartTime
        if(TimeOut >= OverTimeOut):
            if not self.SilentMode:
                print "It is not valid ppds interface. Disconnected."
            self.stop()
            self.disconnect()
            sys.exit(1)
        if not self.SilentMode:
            print "Interface OK"    
 
    def disconnect(self):
        """Short description: Disconnects from ppds interface"""
        self.stop()
        self.Comm.close()
 
    def run(self):
        """Short description: Class working loop, receives data from the interface"""
        while self.RunFlag:
            i, o, e = select.select([self.Comm], [], [], 0.01) 
            for x in i:
                self.Input = x.recv(1024)
                if self.Input:
                    depo = self.Input.split("\r\n")
                    for item in depo:
                        self.RCVQ.put_nowait(item+"\r\n")

    def stop(self):
        """Short description: Stops working loop"""
        self.RunFlag = False
        time.sleep(1)
 
    ## Documentation for method.
    # Sends <B>Text</B> to interface. 
    # @param Text text to be sent to the interface
    # <BR><BR>
    def send(self, Text):
        """Short description: Sends data to the interface"""
        self.Comm.send(Text)      
 
    def getinputflag(self):
        """Short description: Flagging when incoming data is coming from the interface"""
        return(False if self.RCVQ.empty() else True)       

    def getinputdata(self):
        """Short description: Gets data from the interface"""
        try:
            item = self.RCVQ.get_nowait()
        except:
            item = ""
        return item

    ## Documentation for method.
    # Sends <B>Command</B> to the interface, then checks expected answer for the command based on <B>ExpAnswer</B>.
    # The answer must arrive within <B>MaxTimeOut</B> milliseconds. Ppds gives answer to every commands and there is a prompt ('>')
    # at the end of the answer. Prompt can always be found after having an answer. At the same time you can also digest every details
    # of the whole answer to make sure if driver has done the required things, or the required parameter is set on the card.
    # If <B>PrintParsableAnswer</B> is set to <B><I>True</I></B>, method displays parsable interface answer.
    # If expected answer is not equals to interface answer and <B>PrintParsableAnswer</B> is set to <B><I>False</I></B>,
    # then method displays only <B><I>'ANSWER WRONG'</I></B>.
    # @param Command Command to interface
    # @param ExpAnswer Expected answer or a part of expected answer for the command
    # @param MaxTimeOut Maximum timeout of the answer
    # @param PrintParsableAnswer If it is set to <B><I>True</I></B>, it prints the anwer, if it is set to <B><I>False</I></B>, it does not print the answer.
    # <BR><BR>
    def commandstatemachine(self,Command,ExpAnswer,MaxTimeOut,PrintParsableAnswer=False):
        """Short description: Checks answer for the sent command"""
        Answer = ""
        StartTime = int(time.time()*1000)
        TimeOut = 0
        self.send(Command)
        while (ExpAnswer not in Answer and TimeOut < MaxTimeOut):
            if self.getinputflag():
                Answer = Answer + self.getinputdata()
            TimeOut = int(time.time()*1000) - StartTime
        if(TimeOut >= MaxTimeOut):
            if PrintParsableAnswer:
                s=""
                for ch in Answer:
                    if ch == "\r":
                        s=s+"\\r"
                    elif ch =="\n":
                        s=s+"\\n"
                    else:
                        s=s+ch
                Answer = ">>>%s<<<"%s
            else:
                Answer = "ANSWER WRONG"
        return Answer

 
## Communication with ppds. <B></B> <I></I>  <B><I></I></B>
#  Pheripherial driver has 3 interfaces. <B>C</B>ommand <B>A</B>nd <B>E</B>rror interface is to send commands to driver, setup commands to IO cards and
#  it receives answers for commands, errors and notifications. <B>I</B>nput <B>O</B>utput interface lets controller program send output change commands
#  to cards, and receives and notifies any input changes on the cards. <B>MON</B>itor interface has only output, wich displays all input and output changes
#  on cards. This class helps to registrate the interfaces, connects to them, and goes back with the attached interfaces. After that you only have to deal
#  with sending commands, and handling anwers. After your program ended the game with IO cards, the class disconnects all driver connections.
class PPDRIVER:
    """Short description: Class for connect to ppds driver's interfaces"""
    def __init__(self):
        """Short description: Constructs PPDRIVER class"""
        self.CAEInterfaceDescriptor = {}
        self.IOInterfaceDescriptor = {}
        self.MONInterfaceDescriptor = {}
        self.CAEIF = None
        self.IOIF = None
        self.MONIF = None
 
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    #  Registers IP address and port of <B>C</B>ommand <B>A</B>nd <B>E</B>rror interface of ppds.
    # @param Ipaddr IP address of machine where the ppds runs on
    # @param Port Port of CAE interface
    # <BR><BR>
    def registerCAEinterface(self, Ipaddr, Port):
        """Short description: Regiters CAE interface of ppds for communication"""
        self.CAEInterfaceDescriptor["Name"] = "CAEIF"
        self.CAEInterfaceDescriptor["IPAddr"] = Ipaddr
        self.CAEInterfaceDescriptor["Port"] = Port
 
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    #  Registers IP address and port of <B>I</B>nput <B>O</B>utput interface of ppds.
    # @param Ipaddr IP address of machine where the ppds runs on
    # @param Port Port of IO interface
    # <BR><BR>
    def registerIOinterface(self, Ipaddr, Port):
        """Short description: Regiters IO interface of ppds for communication"""
        self.IOInterfaceDescriptor["Name"] = "IOIF"
        self.IOInterfaceDescriptor["IPAddr"] = Ipaddr
        self.IOInterfaceDescriptor["Port"] = Port

    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    #  Registers IP address and port of <B>MON</B>itor interface of ppds.
    # @param Ipaddr IP address of machine where the ppds runs on
    # @param Port Port of MON interface
    # <BR><BR>
    def registerMONinterface(self, Ipaddr, Port):
        """Short description: Regiters MON interface of ppds for communication"""
        self.MONInterfaceDescriptor["Name"] = "MONIF"
        self.MONInterfaceDescriptor["IPAddr"] = Ipaddr
        self.MONInterfaceDescriptor["Port"] = Port         

    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    #  Connects to ppds interfaces.
    # @param CAE If CAE is set to <B><I>True</I></B> method connects to Command And Error interface.
    # @param IO If IO is set to <B><I>True</I></B> method connects to Input Output interface.
    # @param MON If MON is set to <B><I>True</I></B> method connects to Monitor interface. <BR><BR>
    # If any of them are set to <B><I>False</I></B> then connection cannot be established.
    # <BR><BR>
    def connectinterfaces(self, CAE = True, IO = True, MON = False):
        """Short description: Connects to ppds interfaces."""
        if CAE:
            self.CAEIF = PPDCommThread(self.CAEInterfaceDescriptor.get("IPAddr"), self.CAEInterfaceDescriptor.get("Port"), "PPDS CAE interface is ready\r\n(Type HELP for help)\r\n>\r\n")    
            self.CAEIF.connect()
        if IO:
            self.IOIF = PPDCommThread(self.IOInterfaceDescriptor.get("IPAddr"), self.IOInterfaceDescriptor.get("Port"), "PPDS IO interface is ready\r\n")
            self.IOIF.connect()
        if MON:
            self.MONIF = PPDCommThread(self.MONInterfaceDescriptor.get("IPAddr"), self.MONInterfaceDescriptor.get("Port"), "PPDS MON interface is ready\r\n")
            self.MONIF.connect()
 
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Connects to ppds interfaces.
    # @param CAE If CAE is set to <B><I>True</I></B> method disconnects from Command And Error interface.
    # @param IO If IO is set to <B><I>True</I></B> method disconnects from Input Output interface.
    # @param MON If MON is set to <B><I>True</I></B> method disconnects from Monitor interface.<BR><BR>
    # If any of them are set to <B><I>False</I></B> then not going to disconnect.
    # <BR><BR>
    def disconnectinterfaces(self, CAE= True , IO = True, MON = False):
        """Short description: Disconnects from ppds interfaces"""
        if CAE and self.CAEIF != None:
            self.CAEIF.commandstatemachine("EXIT\r\n","PPDS: Bye Bye...\r\n",3000)
            self.CAEIF.stop()
        if IO and self.IOIF != None:    
            self.IOIF.commandstatemachine("EXIT\r\n","PPDS: Bye Bye...\r\n",3000)
            self.IOIF.stop()
        if MON and self.MONIF != None:
            self.MONIF.disconnect()       

    def getinterfaces(self):
        """Short description: Gets connected interfaces of ppds"""
        return self.CAEIF, self.IOIF, self.MONIF
 

## The IO card gadgets. <B></B> <I></I>  <B><I></I></B>
#  This class contains constants, and methods needed for identification of cards and contains keycodes for matrix keyboard handling.
class PPIOCARDGADGETS:
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Constructs PPIOCARDGADGETS class.
    # @param CAEIF CAE interface instance is already connected to ppds.
    # @param IOIF IO interface instance is already connected to ppds.
    # <BR><BR>
    def __init__(self, CAEIF, IOIF):
        """Short description: Constructs PPIOCARDGADGETS class"""
        self.Discovered = False
        self.DiscoverDict = {}
        self.CAEIF = CAEIF
        self.IOIF = IOIF
        self.parsediscoverlist()
        ## Card types:
        # ['KEYMX and ROTE CONTROLLER', 
        # '16 channel DIGITAL INPUT',
        # '16 channel DIGITAL OUTPUT',
        # 'ALPHANUMERIC LCD CONTROLLER',
        # '6 channel RC SERVO CONTROLLER', 
        # '6 channel ANALOGUE INPUT', 
        # '3 channel DC MOTOR CONTROLLER',
        # 'IR REMOTE CONTROLLER']
        self.CardIOTypes = {
            'KEYMX and ROTE CONTROLLER' : 'INP',  
            '16 channel DIGITAL INPUT' : 'INP', 
            '16 channel DIGITAL OUTPUT' : 'OUT', 
            'ALPHANUMERIC LCD CONTROLLER' : 'OUT', 
            '6 channel RC SERVO CONTROLLER' : 'OUT', 
            '6 channel ANALOGUE INPUT' : 'INP', 
            '3 channel DC MOTOR CONTROLLER' : 'OUT',
            'IR REMOTE CONTROLLER' : 'OUT',
            'EMPTY' : 'NOTKNOW', 
        }        
        self.KeyCodes = {
             '0':'1',
             '4':'2',
             '8':'3',
             'C':'A',
             '1':'4',
             '5':'5',
             '9':'6',
             'D':'B',
             '2':'7',
             '6':'8',
             'A':'9',
             'E':'C',
             '3':'*',
             '7':'0',
             'B':'#',
             'F':'D',
        }

    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Parsing discoverlist, identification of cards, by their addresses.
    # @param KeyType If  KeyType is set to <B><I>"integer"</I></B>, addresses are stored as numbers in <B>DiscoverDict</B> in other cases addresses are stored as strings.
    # <BR><BR>
    def parsediscoverlist(self, KeyType="integer"):
        """Short description: Parses discover list"""
        self.Discovered = False 
        DiscoverDict = {}
        Answer = self.CAEIF.commandstatemachine("FORCEDISCOVER\r\n",">",3000) 
        DiscoverList=Answer.split("\r\n")
        for item in  DiscoverList:
            if "DTI:" in item:
                rawitems = item.split(":")
                key = rawitems[1]
                cardname = rawitems[2]
                if KeyType == "integer":
                     DiscoverDict[int(key[2],16)] = cardname
                elif KeyType == "string":
                     DiscoverDict[key[2]] = cardname                  
        self.DiscoverDict = DiscoverDict
        self.Discovered = True

    def printdiscoverresult(self):
        """Short description: Displays discover list"""
        for addr in range(16):
            if self.DiscoverDict.get(addr)!="EMPTY":
                print "  %s card found at address %0.2X"%(self.DiscoverDict.get(addr),addr)

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # The method comes back with the list of specified lists of cards. Types can be members of <B>CardIOTypes</B>.
    # @param CardType Type of the card.
    # <BR><BR>
    def searchcards(self, CardType):
        """Short description: Seraches cards by types"""
        CardAddrList = []
        while (not self.Discovered):
            time.sleep(0.01)
        for addr in range(16):
            if self.DiscoverDict.get(addr) == CardType:
                CardAddrList.append(addr)
        return CardAddrList

## LCD handler. <B></B> <I></I> <B><I></I></B>
# With the help of this class, you can write to alphanumeric LCD displays, clear screen and switch cursor, cursorblinking, or even backlight.
# You can give system commands to the LCD driver card regarding selftest, and backlight used during boot process.
# After creating the instance of the class you need to give the jumpered address of the card to send the commands to. 
# The address can be changed on the, fly this way more cards can be driven using only one instance.
class PPLCDHANDLER:
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Constructs PPLCDHANDLER class.
    # @param CAEIF CAE interface instance is already connected to ppds.
    # @param IOIF IO interface instance is already connected to ppds.
    # <BR><BR>
    def __init__(self, CAEIF, IOIF):
        """Short description: Constructs PPLCDHANDLER class"""
        self.CAEIF = CAEIF
        self.IOIF = IOIF
        self.LCDControllerAddress = None
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # @param Address Is the address of the card
    # <BR><BR>
    def setlcdcontrolleraddress(self, Address):
        """Short description: It sets address of LCD driver card"""
        self.LCDControllerAddress = Address
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # @param State If State is set to "ENABLE" LCD selftest runs at booting. If State is set to "DISABLE", selftest does not run.
    # Card remembers for the setting, and acts as set until different setting.
    # <BR><BR>
    def selftest(self, State):
        """Short description: It allows selftest at booting"""
        if self.LCDControllerAddress != None:
            if "ENABLE" in State:
                self.CAEIF.commandstatemachine("LCDSELFTEST:%X=ON\r\n"%self.LCDControllerAddress,">",2500)
            if "DISABLE" in State:
                self.CAEIF.commandstatemachine("LCDSELFTEST:%X=OFF\r\n"%self.LCDControllerAddress,">",2500)
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # @param State If State is set to "ENABLE" LCD backlight switches on at booting. If State is set to "DISABLE", LCD backlight does not swith on at booting.
    # Card remembers for the setting, and acts as set until different setting. LCD backlight can be switched on and off using backlight method any time.
    # <BR><BR>
    def initlight(self, State):
        """Short description: It allows backlight at booting"""
        if self.LCDControllerAddress != None:
            if "ENABLE" in State:
                self.CAEIF.commandstatemachine("LCDINITLIGHT:%X=ON\r\n"%self.LCDControllerAddress,">",2500)
            if "DISABLE" in State:
                self.CAEIF.commandstatemachine("LCDINITLIGHT:%X=OFF\r\n"%self.LCDControllerAddress,">",2500)
 
    def clear(self):
        """Short description: It clears LCD display"""
        if self.LCDControllerAddress != None:
            self.IOIF.send("a%XlCL\r\n"%self.LCDControllerAddress) 
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # @param State If State value is "ON", then cursor switches on, if State value is "OFF", cursor switches off
    # <BR><BR>
    def cursor(self, State):
        """Short description: It swithces cursor"""
        if self.LCDControllerAddress != None:
            if "ON" in State:
                self.IOIF.send("a%XlCO\r\n"%self.LCDControllerAddress)
            if "OFF" in State:
                self.IOIF.send("a%XlCF\r\n"%self.LCDControllerAddress)
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # @param State If State value is "ON", then cursor goes blingking, (only if cursor is on), if State value is "OFF", cursor does not blink.
    # <BR><BR>
    def blink(self, State):
        """Short description: It switches cursor blinking"""
        if self.LCDControllerAddress != None:
            if "ON" in State:
                self.IOIF.send("a%XlBO\r\n"%self.LCDControllerAddress)
            if "OFF" in State:
                self.IOIF.send("a%XlBF\r\n"%self.LCDControllerAddress)
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # @param State If State value is "ON", then LCD backlight goes on, if the State value is "OFF", LCD backlight goes off
    # <BR><BR>
    def backlight(self, State):
        """Short description: It switches backlight"""
        if self.LCDControllerAddress != None:
            if "ON" in State:
                self.IOIF.send("a%XlLO\r\n"%self.LCDControllerAddress)
            if "OFF" in State:
                self.IOIF.send("a%XlLF\r\n"%self.LCDControllerAddress)
                
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It writes text to the required position. Upper right corner of the dislplay is position "0,0".
    # @param Column Vertical position of the text
    # @param Row Horisontal position of the text
    # @param Text The text to display
    # <BR><BR>
    def printat(self, Column, Row, Text):
        """Short description: It writes text to the required position"""
        self.IOIF.send("a%XlPAp%0.2X%0.2Xt%s\r\n"%(self.LCDControllerAddress, Column, Row, Text))  

## DC motor handler. <B></B> <I></I>  <B><I></I></B>
# This class contains all methods needed for controlling DC motors. After creating the instance of the class, you need to give the jumpered address of the 
# DC motor controller card you want to send the commands to. The class supports manual, and automatic modes as well, using system commands, but modes will 
# be set only for the running process, the card will not remember for the mode in static way. In automatic mode only autocontrol method can be used, but 
# in manual mode manualinit, motorenable, motordisable and motorspeed methods also can be used.
class PPDCMOTORHANDLER:
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Constructs PPDCMOTORHANDLER class.
    # @param CAEIF CAE interface instance is already connected to ppds.
    # @param IOIF IO interface instance is already connected to ppds.
    # <BR><BR>
    def __init__(self, CAEIF, IOIF):
        """Short description: Constructs PPDCMOTORHANDLER class"""
        self.CAEIF = CAEIF
        self.IOIF = IOIF
        self.BM = PPBITMANIPULATOR()
        self.MotorControllerAddress = None
        MotorData = {"Mode":"MANUAL"}
        self.ManControlData = "00"
        self.Motor = {}
        for i in range(3):
            self.Motor[i] = MotorData
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # @param Address The address of the card
    # <BR><BR>
    def setmotorcontrolleraddress(self, Address):
        """Short description: It sets the address of DC motor driver card"""
        self.MotorControllerAddress = Address 
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It sets channel modes to idle. All channels must be set to manual mode before using this option.
    # <BR><BR>
    def manualinit(self):
        """Short description: It sets channel modes to idle"""
        if self.MotorControllerAddress != None:
            self.IOIF.send("a%Xb0d00\r\n"%self.MotorControllerAddress)
            self.IOIF.send("a%Xb1dFF\r\n"%self.MotorControllerAddress)
            self.IOIF.send("a%Xb2dFF\r\n"%self.MotorControllerAddress)
            self.IOIF.send("a%Xb3dFF\r\n"%self.MotorControllerAddress)

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Sets the mode of the required channel. If only <B>MotorID</B> is defined, the channel also goes to manual. If <B>SilentRange</B> is set, the channel 
    # goes to automatic mode, this way the motor goes forward as 0..0x80-SilentRange is defined in <B>autocontrol</B>, while it goes backward in the 
    # case of 0x80+SilentRange..0xFF. If the range is in 0x80-SilentRange..0x80+SilentRange, it stops.                                      
    # @param MotorID The ID of the motordriver's channel can be 0..2.
    # @param SilentRange The midrange of the whole control range where the motor stops. SilentRange is the half of the midrange. It can be 0x01..0x20. 
    # @param SendToCard If it's value is <B>True</B>, then mode is set on the card by the method, otherwise not. 
    # If parameter is not defined, the mode is set automatically by method.
    # <BR><BR>
    def setmotormode(self, MotorID, SilentRange = 0, SendToCard = False):
        """Short description: Sets the mode of the required chanel"""
        if self.MotorControllerAddress != None:
            Motor = self.Motor.get(MotorID)
            Motor["Mode"] = "NONE"
            if SilentRange == 0:
                Motor["Mode"] = "MANUAL"
                if SendToCard:
                    self.CAEIF.commandstatemachine("SETMSR%d:%X=00\r\n"%(MotorID,self.MotorControllerAddress),">",2500)
            if SilentRange in range(1,33):
                Motor["Mode"] = "AUTO"
                if SendToCard:
                    self.CAEIF.commandstatemachine("SETMSR%d:%X=%0.2X\r\n"%(MotorID,self.MotorControllerAddress,SilentRange),">",2500)
            self.Motor[MotorID] = Motor
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It allows the motor to turn via the driver channel.
    # @param MotorID ID value of the motordriver channel can be 0..2
    # @param Direction If Direction value is "FORWARD", then motor goes forward, if value is "BACKWARD" then it goes backward. 
    # Speed must be set to the proper values for the operation.
    # <BR><BR>
    def motorenable(self, MotorID, Direction):
        """Short description: It allows the motor to turn via the driver channel"""
        if self.MotorControllerAddress != None:
            Motor = self.Motor.get(MotorID)
            if Motor.get("Mode") == "MANUAL":
                if Direction == "FORWARD":
                    if MotorID == 0:
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,0,2)
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,5)
                    if MotorID == 1:
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,0,1)
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,4)
                    if MotorID == 2:
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,0,0)
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,3)
                if Direction == "BACKWARD":
                    if MotorID == 0:
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,2)
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,5)
                    if MotorID == 1:
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,1)
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,4)
                    if MotorID == 2:
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,0)
                        self.ManControlData = self.BM.setbitstate(self.ManControlData,1,3)
                self.IOIF.send("a%Xb0d%s\r\n"%(self.MotorControllerAddress,self.ManControlData))

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    #  Disables driving the motor on the defined driver channel.
    # @param MotorID The value of the motordriver channel can be 0..2
    # <BR><BR>
    def motordisable(self, MotorID):
        """Short description: Disables driving the motor on the driver channel"""
        if self.MotorControllerAddress != None:
            Motor = self.Motor.get(MotorID)
            if Motor.get("Mode") == "MANUAL":
                if MotorID == 0:
                    self.ManControlData = self.BM.setbitstate(self.ManControlData,0,5)
                if MotorID == 1:
                    self.ManControlData = self.BM.setbitstate(self.ManControlData,0,4)
                if MotorID == 2: 
                    self.ManControlData = self.BM.setbitstate(self.ManControlData,0,3)
                self.IOIF.send("a%Xb0d%s\r\n"%(self.MotorControllerAddress,self.ManControlData))
  
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It sets the speed of the motor on the defined driver channel.
    # @param MotorID The motordriver channel's ID can be 0..2
    # @param SpeedInPercent It turns the motor with the speed defined in the parameters. It's value can be 0..100, what means %. 
    # The motor turns only if the function is allowed.
    # <BR><BR>
    def motorspeed(self, MotorID, SpeedInPercent):
        """Short description: It sets the speed of the motor on the driver channel"""
        if self.MotorControllerAddress != None:
            Motor = self.Motor.get(MotorID)
            if Motor.get("Mode") == "MANUAL":
                self.IOIF.send("a%Xb%dd%0.2X\r\n"%(self.MotorControllerAddress,MotorID+1,255-int(round(SpeedInPercent*2.55))))

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It controlls the turning of the motor in automatic mode on the defined channel.
    # @param MotorID The ID of the motordriver channel. It's value can be 0..2
    # @param ControlData The motor turns forward in the 0..0x80-SilentRange range, and it turns backward in 0x80+SilentRange..0xFF.
    # The motor stops in 0x80-SilentRange..0x80+SilentRange range.
    # <BR><BR>
    def autocontrol(self, MotorID, ControlData):
        """Short description: It controlls the turning of the motor in automatic mode"""
        if self.MotorControllerAddress != None:
            Motor = self.Motor.get(MotorID)
            if Motor.get("Mode") == "AUTO":
                self.IOIF.send("a%Xb%dd%0.2X\r\n"%(self.MotorControllerAddress,MotorID+1,ControlData))

## Analogue input handler. <B></B> <I></I>  <B><I></I></B>
# This class helps to get data from cards with analog inputs. The "CHANGE" event indicates changes of input channels, this time measured 
# values can be read out. To do all of this you should name analog input channels.
class PPAINHANDLER:
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Constructs PPAINHANDLER class.
    # @param CAEIF CAE interface instance is already connected to ppds.
    # @param IOIF IO interface instance is already connected to ppds.
    # <BR><BR>
    def __init__(self, CAEIF, IOIF):
        """Short description: Constructs PPAINHANDLER class"""
        self.CAEIF = CAEIF
        self.IOIF = IOIF
        self.InChannels = {}
        self.InBytes = {}
        self.InBytesPrev = {}
        self.BM = PPBITMANIPULATOR()
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It registers the analog channel, and it pairs a functional name with the channel. Channel name can be defined by you regarding the function it is used for.
    # For example if a variable resistor is connected to one channel, and you want to used it to control speed, it is practical to name as "SPEED CONTROL". 
    # @param ChannelName The functional name of the cannel
    # @param CardAddress The jumpered address of the analog input card what the channel to read is on.
    # @param BlockNumber The number of the chanel you want to use. Value can be 0..5
    # <BR><BR>
    def registerinchannel(self, ChannelName, CardAddress, BlockNumber):
        """Short description: It registers the analog channel"""
        ChData = {}
        ChData["CardAddress"] = "%X"%CardAddress
        ChData["BlockNumber"] = "%X"%BlockNumber
        ChData["CHANGE"] = False
        self.InChannels[ChannelName] = ChData
        InByteKey = ChData.get("CardAddress")+ChData.get("BlockNumber")
        if InByteKey not in self.InBytes.keys():
            self.InBytes[InByteKey] = "00"
            self.InBytesPrev[InByteKey] = "00"

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It purges the analog channel from the store of the class.
    # @param ChannelName The functional name of the channel to be purged.
    # <BR><BR>
    def removeinchannel(self, ChannelName):
        """Short description: It purges the analog channel"""
        del self.InChannels[ChannelName]

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It checks input channel changes.
    # All PP eventhandler classes has method like this. Only one reading method can handle incoming data, because only one clientsocket can be connected 
    # to the ppds IO interface. Due to this, a master one, which reads out the receive queue in the working loop, and the processes incoming data is required
    # to have in the case of using more than one eventhandler. After processing the master passes raw data to the next eventhandlers. This way all data will be 
    # processed. If the <B>chekinchannelschanges</B> method is called as master, then it always reads out the receivequeue of the IO interface. 
    # The master <B>checkinchannelschanges</B> must run first. All the other eventhandlers must receive the data read by the first after each-other, in consequence.
    # @param MasterOrFwdData It can be the "MASTER", or forwarded input data.
    # <BR><BR>
    def chekinchannelschanges(self, MasterOrFwdData):
        """Short description: It checks input channel changes"""
        if not MasterOrFwdData:
            return None
        else:
            if MasterOrFwdData == "MASTER":
                if self.IOIF.getinputflag():
                    dataforward = self.IOIF.getinputdata()
                else:
                    return None
            else:
                dataforward = MasterOrFwdData
            data = dataforward.replace("\r","").replace("\n","")
            InByteKey = data[1:2]+data[3:4]
            if InByteKey in self.InBytes.keys():
                self.InBytes[InByteKey] = data[5:7]
                if self.InBytes[InByteKey] != self.InBytesPrev[InByteKey]:
                    for key in self.InChannels.keys():
                        ChData = self.InChannels.get(key)
                        if ChData.get("CardAddress")+ChData.get("BlockNumber") == InByteKey:
                            ChData["CHANGE"] = True
                            self.InChannels[key] = ChData
                    self.InBytesPrev[InByteKey] = self.InBytes.get(InByteKey)
            return dataforward           

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It is evendhandler of the PPAINHANDLER. It handles only one event, as "CHANGE". If the analog value mesured by the certain channel changes, then 
    # it comes back with value <B><I>True</I></B>, if there is no changes, the value is <B><I>False</I></B>. If the method indicates changes, it is useful to read out using <B>getvalue</B> 
    # method as soon as possible, because the changed data is stored only for the term of the cycle.
    # @param ChannelName The functional name of the channel
    # <BR><BR>
    def inputevent(self, ChannelName, EventName = "CHANGE"):
        """Short description: Event handler for "CHANGES" event"""
        retvalue = False
        ChData = self.InChannels.get(ChannelName)
        if ChData.get(EventName):
            ChData[EventName] = False
            self.InChannels[ChannelName] = ChData
            retvalue = True
        return retvalue 

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It reads out the actual value of the channel
    # @param ChannelName The functional name of the channel
    # <BR><BR>
    def getvalue(self, ChannelName):
        """Short description: It reads out the actual value of the channel"""
        ChData = self.InChannels.get(ChannelName)
        return self.InBytes.get(ChData.get("CardAddress")+ChData.get("BlockNumber"))

## Digital input and output handler. <B></B> <I></I>  <B><I></I></B>
# This class makes handling of digital in, and output cards easy. All input, and output channel can have a functional name,
# which can be used as reference. Output channels can be switched off and on independently. Changes of the input channels
# can be handled via eventhandlers. Eventhandlers can be named as "Alias", so event names can be changed to logical names,
# for example "PUSH" instead of "ON" in the case of a pushbutton. Output channels can be switched off together in one time,
# what is useful in the case of quiting from the controller program. Input block's last stored data can be inquired by cardaddress
# and blocknumber, and result can be forwarded to an own eventhandler.
class PPDIGINOUTHANDLER:
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Constructs PPDIGINOUTHANDLER class.
    # @param CAEIF CAE interface instance is already connected to ppds.
    # @param IOIF IO interface instance is already connected to ppds.
    # <BR><BR>
    def __init__(self, CAEIF, IOIF):
        """Short description: Constructs PPDIGINOUTHANDLER class"""
        self.CAEIF = CAEIF
        self.IOIF = IOIF
        self.OutChannels = {}
        self.OutBytes = {}
        self.OutBytesPrev = {}
        self.InChannels = {}
        self.InBytes = {}
        self.InBytesPrev = {}
        self.InOnAliases = {"ON" : "ON"}
        self.InOffAliases = {"OFF" : "OFF"}
        self.BM = PPBITMANIPULATOR()

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Switches certain chanels to certain states.
    # @param ChannelName The functional name of the out channel
    # @param SwithState Output channel's state can be <B><I>"ON"</I></B>, or <B><I>"OFF"</I></B>
    # @param Send If the values is <B><I>True</I></B>, then it sends the new output value to the card immediately.
    # <BR><BR>
    # If <I>Send</I> parameter is not given, method does not send anything to the card. In this case, one has to make sure
    # if there is the method <B>sendoutputs</B> called at the end of the working loop, otherwise the output channel's
    # value canges can't be sent to the output card.
    # <BR><BR>
    def switch(self, ChannelName, SwitchState, Send = False):
        """Short description: Switches certain chanels"""
        OutByteKey = self.OutChannels.get(ChannelName).get("CardAddress")+self.OutChannels.get(ChannelName).get("BlockNumber")
        if SwitchState == "ON":
            self.OutBytes[OutByteKey] = self.BM.setbitstate(self.OutBytes.get(OutByteKey), 0, self.OutChannels.get(ChannelName).get("BitPosition"))
        if SwitchState == "OFF":
            self.OutBytes[OutByteKey] = self.BM.setbitstate(self.OutBytes.get(OutByteKey), 1, self.OutChannels.get(ChannelName).get("BitPosition"))
        if Send:
            self.sendoutputs()

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It turns all output channels off.
    # @param Send If the values is <B><I>True</I></B>, then it sends the new output value to the card immediately.
    # <BR><BR>
    # If <I>Send</I> parameter is not given, it does not send anything to the card. In this case, one has to make sure
    # if there is the method <B>sendoutputs</B> called at the end of the working loop, otherwise the output channel's
    # value canges can't be sent to the output card.
    # <BR><BR>
    def switchoffall(self, Send = False):
        """Short description: It turns all output channels off"""
        for key in self.OutBytes.keys():
            self.OutBytes[key] = "FF"
            self.OutBytesPrev[key] = "00"
        if Send:
            self.sendoutputs()

    def sendoutputs(self):
        """Short description: It sends all output channel's value changes to the cards"""
        for key in self.OutBytes.keys():
            if self.OutBytes.get(key) != self.OutBytesPrev.get(key):
                self.IOIF.send("a%sb%sd%s\r\n"%(key[0:1],key[1:2],self.OutBytes.get(key)))
                self.OutBytesPrev[key] = self.OutBytes.get(key)
 
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It registrates the digital output channel, and gives a functional name. Channel name is named by you regarding the used function.
    # For example if a relay is on a channel, and you control a light with that, it is useful to name as "LAMP SWITCH RELAY". 
    # @param ChannelName The functional name of the channel
    # @param CardAddress The jumpered address of the digital output card, which is the relevant channel is on.  
    # @param BlockNumber The number of the block, which contains the channel required to be used. It's value can be 0...1.
    # @param BitPosition The position of the channel within the defined block, you want to use. It's value can be 0...7. 
    # <BR><BR>
    def registeroutchannel(self, ChannelName, CardAddress, BlockNumber, BitPosition):
        """Short description: It registrates the digital output channel"""
        ChData = {}
        ChData["CardAddress"] = "%X"%CardAddress
        ChData["BlockNumber"] = "%X"%BlockNumber
        ChData["BitPosition"] = BitPosition
        self.OutChannels[ChannelName] = ChData
        OutByteKey = ChData.get("CardAddress")+ChData.get("BlockNumber")
        if OutByteKey not in self.OutBytes.keys():
            self.OutBytes[OutByteKey] = "FF"
            self.OutBytesPrev[OutByteKey] = "FF"

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It clears digital output channel from the storage of the class
    # @param ChannelName The functional name of the channel to delete
    # <BR><BR>
    def removeoutchannel(self, ChannelName):
        """Short description: It clears digital output channel"""
        del self.OutChannels[ChannelName]

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It registers switching on eventname aliases to input channels
    # @param Aliases String list containing alias names
    # <BR><BR>    
    def registerinoneventaliases(self, Aliases):
        """Short description: It registers switching on eventname aliases"""
        for alias in Aliases:
            self.InOnAliases[alias] = "ON"
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It registers switching off eventname aliases to input channels
    # @param Aliases String list containing alias names
    # <BR><BR>
    def registerinoffeventaliases(self, Aliases):
        """Short description: It registers switching off eventname aliases"""
        for alias in Aliases:
            self.InOffAliases[alias] = "OFF"

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It registers digital input channels, and names them with a functional name. You can define the name of the channel, regarding the function of it.
    # For example if you connect a pushbutton to the channel, and you want to use it to exit the process, it is useful to name it as "EXIT BUTTON".
    # @param ChannelName The functional name of the channel
    # @param CardAddress The jumpered address of the digital input card, what is the channel to read is on
    # @param BlockNumber The name of the block which contains the channel to be used. It's value can be 0..1
    # @param BitPosition The bitposition of the cannel within the certain block, which you want to use. It's value can be 0..7
    # <BR><BR>
    def registerinchannel(self, ChannelName, CardAddress, BlockNumber, BitPosition):
        """Short description: It registers digital input channels"""
        ChData = {}
        ChData["CardAddress"] = "%X"%CardAddress
        ChData["BlockNumber"] = "%X"%BlockNumber
        ChData["BitPosition"] = BitPosition
        ChData["ON"] = False
        ChData["OFF"] = False
        self.InChannels[ChannelName] = ChData
        InByteKey = ChData.get("CardAddress")+ChData.get("BlockNumber")
        if InByteKey not in self.InBytes.keys():
            self.InBytes[InByteKey] = "00"
            self.InBytesPrev[InByteKey] = "00"
 
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It clears digital input channel from the storage of the class.
    # @param ChannelName The functional name of the channel you want to clear.
    # <BR><BR>
    def removeinchannel(self, ChannelName):
        """Short description: It clears digital input channel"""
        del self.InChannels[ChannelName]

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It checks input channel changes.
    # All PP eventhandler classes has method like this. Only one reading method can handle incoming data, because only one clientsocket can be connected 
    # to the ppds IO interface. Due to this, a master one, which reads out the receivequeue in the working loop, and the processes incoming data is required
    # to have in the case of using more than one eventhandler. After processing the master passes raw data to the next eventhandlers. This way all data will be 
    # processed. If <B>chekinchannelschanges</B> method of eventhandler class is called as master, then it always reads out the receive queue of the IO interface. 
    # The master <B>checkinchannelschanges</B> must run first. All the other eventhandlers must receive the data read by the first after each-other, in consequence.
    # @param MasterOrFwdData It can be the "MASTER", or forwarded input data.
    # <BR><BR>
    def chekinchannelschanges(self, MasterOrFwdData):
        """Short description: It checks input channel changes"""
        if not MasterOrFwdData:
            return None
        else:
            if MasterOrFwdData == "MASTER":
                if self.IOIF.getinputflag():
                    dataforward = self.IOIF.getinputdata()
                else:
                    return None
            else:
                dataforward = MasterOrFwdData
            data = dataforward.replace("\r","").replace("\n","")
            InByteKey = data[1:2]+data[3:4]
            if InByteKey in self.InBytes.keys():
                self.InBytes[InByteKey] = data[5:7]
                if self.InBytes[InByteKey] != self.InBytesPrev[InByteKey]:
                    for key in self.InChannels.keys():
                        ChData = self.InChannels.get(key)
                        if (ChData.get("CardAddress")+ChData.get("BlockNumber") == InByteKey and
                        self.BM.getbitstate(self.InBytes.get(InByteKey) ,ChData.get("BitPosition")) == "1" and  
                        self.BM.getbitstate(self.InBytesPrev.get(InByteKey) ,ChData.get("BitPosition")) == "0"):
                            ChData["ON"] = True
                            self.InChannels[key] = ChData
                        if (ChData.get("CardAddress")+ChData.get("BlockNumber") == InByteKey and
                        self.BM.getbitstate(self.InBytes.get(InByteKey) ,ChData.get("BitPosition")) == "0" and
                        self.BM.getbitstate(self.InBytesPrev.get(InByteKey) ,ChData.get("BitPosition")) == "1"):
                            ChData["OFF"] = True
                            self.InChannels[key] = ChData
                    self.InBytesPrev[InByteKey] = self.InBytes.get(InByteKey)
            return dataforward

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It is the PPDIGINOUTHANDLER's eventhandler. It manages "ON" and "OFF" events on input channels, which can be represented
    # by registered aliases as well.
    # Return value is <B><I>True</I></B> if the event happened, <B><I>False</I></B>, if the event did not happened.
    # @param ChannelName The functional name of the channel
    # @param EventName The name of the event
    # <BR><BR>
    def inputevent(self, ChannelName, EventName):
        """Short description: It is the eventhandler"""
        retvalue = False
        ChData = self.InChannels.get(ChannelName)
        if ChData.get(self.InOnAliases.get(EventName)):
            ChData[self.InOnAliases.get(EventName)] = False
            self.InChannels[ChannelName] = ChData
            retvalue = True
        if ChData.get(self.InOffAliases.get(EventName)):
            ChData[self.InOffAliases.get(EventName)] = False
            self.InChannels[ChannelName] = ChData
            retvalue = True    
        return retvalue 

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It returns the last stored data of the input blocks.
    # @param CardAddress CardAddress The address of the digital input card, what the readable block is on
    # @param BlockNumber The number of the block, what is to be known.
    # <BR><BR>
    def getinputblockdata(self, CardAddress, BlockNumber):
        """Short description: It returns the last stored data of the input blocks"""
        return self.InBytes.get("%X%X"%(CardAddress, BlockNumber)) 

## Output actions for rotary encoder handler. <B></B> <I></I>  <B><I></I></B>
# This class contains the output actions of the statemachine dealing with rotary encoder, 
# and also contains variables chained to rotary encoder, and it's other handler methods.
class PPRENCOUTACTIONS:
    def __init__(self):
        """Short description: Constructs PPRENCOUTACTIONS class"""
        self.clear()

    def upsignalaction(self):
        """Short description: The code to run in case of arriving of the rotary encoder upsignal"""
        self.upsignals += 1;
        self.value += 1;

    def downsignalaction(self):
        """Short description: The code to run in case of arriving of the rotary encoder downsignal"""
        self.downsignals += 1;  
        self.value -= 1;  
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Inquiring actual position value of rotary encoder.
    # The return value is formed string, which contains three digits decimal number
    # <BR><BR>
    def getvalue(self):
        """Short description: Inquiring actual position value of the rotary encoder"""
        return "%0.3d "%self.value
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Inquiring upsignals counted since rotary encoder <B>clear</B> method was called.
    # The return value is formed string, which contains three digits decimal number
    # <BR><BR>
    def getupsignals(self):
        """Short description: Inquiring upsignals of rotary encoder"""
        return "%0.3d"%self.upsignals

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Inquiring downsignals counted since rotary encoder <B>clear</B> method was called.
    # The return value is formed string, which contains three digits decimal number
    # <BR><BR>
    def getdownsignals(self):
        """Short description: Inquiring downsignals of rotary encoder"""
        return "%0.3d"%self.downsignals   

    def clear(self):
        """Short description: Setting rotary encoder counters and value to default"""
        self.upsignals = 0
        self.downsignals = 0
        self.value = 0                

## Rotary encoder and matrix keyboard handler. <B></B> <I></I>  <B><I></I></B>
# This class helps to make reading rotary encoder, and matrix keyboard easyer. It's eventhandler reminds if rotary encoder
# is turning, button of the encoder is being pushed, or released, or any key is being pushed on the matrix keyboard. A statemachine
# is handling the rotary encoder. The statemachine is running in a standalone thread, so if you create an instance from this class,
# you need to call the <B>stop</B> method before quitting the control program, otherwise the main thread dies, and the state machine stucks in.
class PPKMREHANDLER:
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Constructs PPKMREHANDLER class.
    # @param CAEIF CAE interface instance is already connected to ppds.
    # @param IOIF IO interface instance is already connected to ppds.
    # @param CardAddress Address of the keymatrix and rotary encoder driver card.
    # <BR><BR>
    def __init__(self, CAEIF, IOIF, CardAddress):
        """Short description: Constructs PPKMREHANDLER class"""
        self.CAEIF = CAEIF
        self.IOIF = IOIF
        self.Addr = CardAddress
        self.PrevData = "00"
        self.PreREOV = "000"
        self.EventAction = {"MXKEYBDCLICK" : False, "REBTNPUSH" : False, "REBTNRELEASE" : False, "REVALUECHANGE" : False}
        self.EventData = {"KEYCODE" : "0", "REVALUE" : "0"}
        self.BM = PPBITMANIPULATOR()
        self.IOCG = PPIOCARDGADGETS(self.CAEIF, self.IOIF)
        self.OA = PPRENCOUTACTIONS()
        self.SM = PPSTATEMACHINE("1", ["00"], self.OA)
        self.SM.additemtostatetable("1", "20", "", "2")
        self.SM.additemtostatetable("2", "60", "upsignalaction()", "3")
        self.SM.additemtostatetable("3", "40", "", "4")
        self.SM.additemtostatetable("4", "00", "upsignalaction()", "1")   
        self.SM.additemtostatetable("1", "40", "", "4")
        self.SM.additemtostatetable("4", "60", "downsignalaction()", "3")
        self.SM.additemtostatetable("3", "20", "", "2")
        self.SM.additemtostatetable("2", "00", "downsignalaction()", "1")
        self.SM.start()
        self.clearstatevalues()

    def stop(self):
        """Short description: Stopping the statemachine of the class"""
        self.SM.stop()

    def clearstatevalues(self):
        """Short description: Setting variables describing the state of the rotary encoder to default state"""
        self.OA.clear()

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It checks input channel changes.
    # All PP eventhandler classes has method like this. Only one reading method can handle incoming data, because only one clientsocket can be connected 
    # to the ppds IO interface. Due to this, a master one, which reads out the receive queue in the working loop, and the processes incoming data is required
    # to have in the case of using more than one eventhandler. After processing the master passes raw data to the next eventhandlers. This way all data will be 
    # processed. If the <B>chekinchannelschanges</B> method is called as master, then it always reads out the receivequeue of the IO interface. 
    # The master <B>checkinchannelschanges</B> must run first. All the other eventhandlers must receive the data read by the first after each-other, in consequence.
    # @param MasterOrFwdData It can be the "MASTER", or forwarded input data.
    # <BR><BR>
    def chekinchannelschanges(self, MasterOrFwdData):
        """Short description: 052"""
        if not MasterOrFwdData:
            return None
        else:
            if MasterOrFwdData == "MASTER":
                if self.IOIF.getinputflag():
                    dataforward = self.IOIF.getinputdata()
                else:
                    return None
            else:
                dataforward = MasterOrFwdData
            data = dataforward.replace("\r","").replace("\n","")
            if "a%Xb0"%self.Addr in data:
                if self.BM.getbitstate(data[5:7],4) == "1":
                    self.EventAction["MXKEYBDCLICK"] = True
                    self.EventData["KEYCODE"] = self.IOCG.KeyCodes.get(data[6:7])
                MDP = self.BM.mask(self.PrevData,"80")
                MD = self.BM.mask(data[5:7],"80")    
                if self.BM.getbitstate(MD, 7) == "1" and self.BM.getbitstate(MDP ,7) == "0":
                    self.EventAction["REBTNPUSH"] = True
                    self.PrevData = data
                if self.BM.getbitstate(MD ,7) == "0" and self.BM.getbitstate(MDP ,7) == "1":
                    self.EventAction["REBTNRELEASE"] = True
                    self.PrevData = data
                encoderstate = self.BM.mask(data[5:7],"60")
                self.SM.inputchange(0,encoderstate)    
                REOV = self.OA.getvalue()    
                if REOV != self.PreREOV:
                    self.EventAction["REVALUECHANGE"] = True 
                    self.EventData["REVALUE"] = REOV
                    self.PreREOV = REOV
            return dataforward

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It is eventhandler of PPKMREHANDLER. Its return value is <B><I>True</I></B> in following event cases : <I>"MXKEYBDCLICK"</I> if key is pushed on the keyboard,
    # <I>"REBTNPUSH"</I> if rotary encoder's butthon is pushed, <I>"REBTNRELEASE"</I> if rotary endoder's button is released, <I>"REVALUECHANGE"</I> if
    # position value of the rotary endoder is changed. In case of "MXKEYBDCLICK" and "REVALUECHANGE" the <B>getvalue</B> method
    # is to get the actual value.
    # @param EventName The name of the event
    # <BR><BR>
    def inputevent(self, EventName):
        """Short description: Returns true if any event happened"""
        retvalue = self.EventAction.get(EventName)
        if retvalue:
            self.EventAction[EventName] = False
        return retvalue

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It reads the actual value belonging to the defined event
    # @param EventDataName The name of the data belonging to the certain event. Its value can be <I>"KEYCODE"</I> or <I>"REVALUE"</I>.
    def getvalue(self, EventDataName):
        """Short description: It reads the actual value belonging to the defined event"""
        return self.EventData.get(EventDataName)

## Bit and byte manipulator. <B></B> <I></I>  <B><I></I></B>
# This class contains all methods needed for manipulating bits and bytes, and converting to different formats.
class PPBITMANIPULATOR:
    def __init__(self):
        """Short description: Constructs PPBITMANIPULATOR class"""
        pass

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Converts defined number to binary string with defined length
    # @param n The number to be converted, entered in decimal or hexadecimal form
    # @param lenght Length of the binary string
    # <BR><BR>
    def int2binstr(self, n, length):
        """Short description: Converts defined number to binary string"""
        binstr = "".join([str((n >> y) & 1) for y in range(length-1, -1, -1)])
        return binstr

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It converts defined binary string to integer number.
    # @param binstr The binary string to be converted
    # <BR><BR>
    def binstr2int(self, binstr):
        """Short description: It converts defined binary string to integer"""
        return int(binstr,2)

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It converts defined binary string to hexadecimal string
    # @param binstr The binary string to be converted
    # <BR><BR>
    # Return value is a byte sized two characters long string.
    # <BR><BR>
    def binstr2hexstr(self, binstr):
        """Short description: It converts defined binary string to hexadecimal string"""
        return "%0.2X"%self.binstr2int(binstr)

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It converts hexadecimal string to binary string
    # @param binstr The hexadecimal string to be converted
    # <BR><BR>
    # Return value is an eight characters long string.
    # <BR><BR>
    def hexstr2binstr(self, str):
        """Short description: It converts hexadecimal string to binary string"""
        bin = ['0000','0001','0010','0011',
             '0100','0101','0110','0111',
             '1000','1001','1010','1011',
             '1100','1101','1110','1111']
        bf = ''
        for i in range(len(str)):
          bf += bin[int(str[i], 16)]      
        return bf 

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It inverts the elements of the binary string bit by bit.
    # @param binstr The binary string to be invertred
    # <BR><BR>
    def inversebinstr(self, binstr):
        """Short description: It inverts the elements of the binary string"""
        ret=""
        s = list(binstr)
        for i in range(len(s)):
            if s[i] == '1':
                s[i] = '0'
            else:
                s[i] = '1'
        return "".join(s)

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Inmediate method.
    # <BR><BR>
    def inverse1(self, invertable):
        if type(invertable).__name__ =='int':
            bs = self.int2binstr(invertable,8)
        if type(invertable).__name__ =='str':
            bs = self.hexstr2binstr(invertable)
        invertedstr = self.inversebinstr(bs)
        if type(invertable).__name__ =='int':
            return self.binstr2int(invertedstr)
        if type(invertable).__name__ =='str':
            return self.binstr2hexstr(invertedstr)

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It inverts the defined byte-sized number, and gives the result in a required output format. 
    # If the output format is not defined, then the result is string.
    # @param invertable The defined number. The number can be defined in three forms, like <I>255</I>, <I>0xFF</I>, or <I>"FF"</I>
    # @param output The output format. Its value can be "int", or "str".
    # <BR><BR>
    def inverse(self, invertable, output=""):
        """Short description: It inverts the defined byte-sized number"""      
        result = self.inverse1(invertable)
        if output == type(result).__name__ or output=="":
            return result
        else:
           if type(result).__name__=='str':
               result = int(result)
           if output == 'int':
               return result
           if output == 'str':
               return "%0.2X"%result        

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It returns a decimal, hexadecimal, or hexastring formed, byte-sized number's bit's value, based on the bitposition, in the required format.
    # If the output format is not defined, result is string.
    # @param input The defined, byte-sized number
    # @param position The position of the bit, which can be 0..7
    # @param output The output fomat. It can be "int", or "str"
    # <BR><BR>
    def getbitstate(self, input, position, output=""):
        """Short description: It returns a number's bit's value, based on the bit position"""  
        if type(input).__name__ == 'int':
            binstr = self.int2binstr(input,8)
        if type(input).__name__ == 'str':
            binstr = self.hexstr2binstr(input)
        result = binstr[7-position:7-position+1]
        if output == "" or output == 'str':
            return result
        if output == 'int':
            return int(result)

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It sets the value of a hexadecimal, or hexastring fomatted, byte-sized number's bit's value based on bit position.
    # It returns the modified byte in a required format. If the format is not defined, result is string.
    # @param input The defined byte-sized number
    # @param bitstate The state of the bit, to set to, binary (fx. 0 or 1), and allowed in string format as well (fx. "0" or "1")
    # @param position The bit position, which can be 0..7
    # @param output The output format. Its value can be "int", like integer, or "str", like hexa string, or "pic" like bitmap string.
    # <BR><BR>
    def setbitstate(self, input, bitstate, position, output=""):
        """Short description: It sets the number's bit's value based on bit position"""
        if type(input).__name__ == 'int':
            binstr = self.int2binstr(input,8)
        if type(input).__name__ == 'str':
            binstr = self.hexstr2binstr(input)
        bitpic = list(binstr)
        if type(bitstate).__name__ == 'int':
            bitstate = "%d"%bitstate
        bitpic[7-position] = bitstate
        result = "".join(bitpic)
        if output =='pic':
            return result      
        if output =='str' or output == "":
            return self.binstr2hexstr(result) 
        if output =='int':
            return self.binstr2int(result)                  

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Masking a decimal, hexadecimal, or hexastring formed byte-sized number with a decimal, hexadecimal, or hexastring
    # formed byte-sized mask, and provides the result in the required output format. If output format is not defined, result is string.
    # @param input The defined byte-sized number
    # @param mask The defined byte-sized mask
    # @param output The output format. It can be "int", or "str"
    # <BR><BR>
    def mask(self, input, mask, output=""):
        """Short description: Masking a number with a mask"""
        if type(input).__name__ == 'int':
            input = "%0.2X"%input
        if type(mask).__name__ == 'int':
            mask = "%0.2X"%mask
        result = int(input, 16) & int(mask, 16)   
        if output =='str' or output == "":
            return "%0.2X"%result
        if output =='int':
            return result

## The statemachine. <B></B> <I></I>  <B><I></I></B>
# This class is a general purpose state machine, what is able to run independently from the main thread of the controller program.
# It must be stopped before quitting from the main thread using <B>stop</B> method, because this class is defined by a different
# thread. Output changes caused by state changes can be described using methods. These methods must be collected in a separate class,
# and must be implemented, and this new class's instance is used by the statemachine.(fx. see how SM implemented in PPKMREHANDLER uses
# methods implemented in PPRENCOUTACTIONS.) State machine can be awaken using method <B>run</B>, but before starting, its temporary
# table must be loaded with method <B>additemtostatetable</B>. Definig table, strings must be used when defining input lists, states,
# new states, and names of change handling methods. Inputs must be given in lists, this way it is easy to change changed values of
# inputs with the position of the list index.
# The operation of the statemachine: The statemachine adds the jointed input list, and the actual state together. If this string
# is not the same as calculated in the previous cycle, then changes occured on the inputs, which causes changes on the outputs, and output action
# starting, if an element can be found in the state table with the jointed input list, and the actual state's result, as key. This
# element is a dicionary, which contains the name of the new state, where we became, and also contains the name of the executable
# action's method. We can execute the executable action, and we can make actual state equal to the new state. From this point,
# the process restarts from the beginig. The statemachine is running in an endless cycle, until we stop it using method <B>stop</B>.
class PPSTATEMACHINE(threading.Thread):
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It is the PPSTATEMACHINE's constructor. In this costructor, the starting state of the statemachine, the valid input combination
    # at the start, and the object class instance, which contains the method collection of the output changes must be given.
    # Defining inputs can be done using lists, fx. binary (["1","0","1"]), it can be one, or more complete byte (["0A"] or ["01","F8"]),
    # word, or long sting as well.
    # In case of changes of certain input channels, we can send the input changes into the state machine with the help of the index of
    # list given at initialising, with the help of method <B>inputchange</B>
    # @param InitState The initial state
    # @param InitInputs The valid input combination at the start given in list 
    # @param OutActionsObject Is the object class instance, which contains the method collection of the output changes
    # @param SilentMode If SilentMode is set to <B><I>False</I></B> then you can follow on the console how the statemachine works
    # <BR><BR>
    def __init__(self, InitState, InitInputs, OutActionsObject, SilentMode = True):
        """Short description: Constructs PPSTATEMACHINE class"""
        threading.Thread.__init__(self)
        self.RunFlag = True 
        self.OutActions = OutActionsObject
        self.InputBlocks = InitInputs
        self.StateTable = {} 
        self.State = InitState 
        self.prevSearchStateChange = ""
        self.SilentMode = SilentMode

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It gives state change to the state table of the state machine. It shows us from what state, with which input combination,
    # and what output action brings us to which state.
    # @param state Starting state, what the state machine is in
    # @param input The changed input combination (must be given, if it was a jointed list)
    # @param outaction The outaction method's name to run
    # @param newstate The new state, what the statemachine came into
    # <BR><BR>
    def additemtostatetable(self, state, input, outaction, newstate):
        """Short description: It gives state change to the state table"""
        statechange = {}
        statechange["OutAction"] = outaction
        statechange["NewState"] = newstate
        self.StateTable[state+input] = statechange
 
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Telling input changes to the state machine.
    # @param inputblock The index of the list given at initialising, what points to the input
    # @param input The changed input value
    # <BR><BR>
    def inputchange(self, inputblock, input):
        """Short description: Telling input changes to the state machine"""
        self.InputBlocks[inputblock] = input 

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Inquiring actual state of the state machine
    # It returns with the actual state of the state machine.
    # <BR><BR>
    def getactualstate(self):
        """Short description: Inquiring actual state of the state machine"""
        return self.State          

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # The working loop of the state machine. It is an endless cycle, until we stop it using method <B>stop</B>.
    # <BR><BR>
    def run(self):
        """Short description: The working loop of the state machine"""
        while self.RunFlag:
            SearchStatechange = self.State+"".join(self.InputBlocks)
            if self.prevSearchStateChange != SearchStatechange:
                if not(self.SilentMode):
                    print "State and input: %s"%SearchStatechange
                self.prevSearchStateChange = SearchStatechange
            StateChange = self.StateTable.get(SearchStatechange)
            if StateChange != None:
                OutAction = StateChange.get("OutAction")
                if not(self.SilentMode):
                    print "Output action: %s"%OutAction
                try:
                    if OutAction != "": 
                        eval("self.OutActions."+OutAction)
                except:
                    if not(self.SilentMode):
                        print "Output action Error: Output action does not exist or incorrect"    
                self.State = StateChange.get("NewState")
                if not(self.SilentMode):
                    print "New state: %s"%self.State
                    print
            time.sleep(0.001)

    def stop(self):
        """Short description: It stops the state machine"""
        self.RunFlag = False   


## The timer. <B></B> <I></I>  <B><I></I></B>
# This class provides a timer which can be used in the working loop of the control programs.
# The working loop must run continously, this way sleep can not be used, because sleep suspends the working loop,
# and input changes can be missed. This is why a timer is needed, which can be started, stopped, and restarted automatically,
# or triggered way, and it timeouts based on delta time.
class PPPASSIVETIMER:
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # When the timer is being created, you can define its timeout value, and you also can activate it immediately.
    # If there is no parameters defined, the timer exists, but it is inactive. Its timeout value can be defined later,
    # and it also can be activated then.
    # @param duration The time in seconds (float number also can be entered fx. 0.01)
    # @param active It the parameter is <B><I>True</I></B>, then timer starts immediately.
    # <BR><BR>
    def __init__(self, duration=0, active=False):        
        """Short description: Constructs PPPASSIVETIMER class"""
        self.active = active
        if self.active:
            self.set(duration)

    def reset(self):
        """Short description: It restarts the timer"""
        self.starttime = time.time()
        self.active = True 

    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # It sets, or changes timing value, and restarts the timer
    # @param duration The time in seconds (float number also can be entered fx. 0.01)
    # <BR><BR>
    def set(self, duration):
        """Short description: It sets, or changes timing value"""
        self.duration = duration 
        self.reset()
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Timeout flag of the timer. Its return value is <B><I>False</I></B> till the time spent since calling <B>set</B> or <B>reset</B>
    # methods less than given in duration parameter. If the value is bigger than the return value is <B><I>True</I></B>, and timer goes
    # inactive state. Restarting the timer can be using <B>reset</B>, or <B>set</B> method with setting new timeout value.
    # <BR><BR>
    def isexpired(self):
        """Short description: Timeout flag of the timer"""
        if self.active and time.time()-self.starttime > self.duration:
            self.active = False
            return True
        else:
            return False

## Complete hardware tests. <B></B> <I></I>  <B><I></I></B>
# This class is for testing the entire system. It tests every cards on the systembus calling the <B>runtests</B> method.
# It uses curses screen for testing input cards, this way it makes changes on input channel visible, using a very nice format.
# The test is not able to check IRRC card, IRRC can be tested by IR receiver setting program.
class PPHWTESTS:
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # Constructs PPHWTESTS class.
    # @param CAEIF CAE interface instance is already connected to ppds.
    # @param IOIF IO interface instance is already connected to ppds.
    # <BR><BR>
    def __init__(self, CAEIF, IOIF):
        """Short description: Constructs PPHWTESTS class"""
        self.CAEIF = CAEIF
        self.IOIF = IOIF
        self.IOCG = PPIOCARDGADGETS(self.CAEIF, self.CAEIF)  
        self.BM = PPBITMANIPULATOR()
        self.DelayBetwenOutTests = 1
        self.InputTests = []
        self.OutputTests = []
        self.stdscr = None
        self.width = 0
        self.height = 0
    
    ## Documentation for method. <B></B> <I></I>  <B><I></I></B>
    # It sets delay between each tests.
    # @param delay The pause between each tests in seconds (float number also can be entered fx. 0.01)
    # <BR><BR>
    def setdelaybetweenouttests(self, delay):
        """Short description: It sets delay between each tests"""
        self.DelayBetwenOutTests = delay
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Inmediate method.
    # <BR><BR>
    def printtocenter(self, screen, raw, width, text):
        """Short description: Text aligment to the middle"""
        l = len(text)
        screen.addstr(raw, (width-l)/2, text, curses.A_BOLD)
        return (width-l)/2

    def runtests(self):
        """Short description: Running tests"""
        print 
        print "Discovering...."
        self.IOCG.printdiscoverresult()  
        print
        for addr in range(16):
            if self.IOCG.DiscoverDict.get(addr) != "EMPTY":
                if self.IOCG.CardIOTypes.get(self.IOCG.DiscoverDict.get(addr)) == "INP":
                    print " Switching off pollflag at address %X"%addr
                    self.CAEIF.commandstatemachine("POLLOFF:%X\r\n"%addr,"CIA: POLLOFF OK at address %X\r\n>\r\n"%addr,500)
                    self.InputTests.append(addr)
                elif self.IOCG.CardIOTypes.get(self.IOCG.DiscoverDict.get(addr)) == "OUT":
                    self.OutputTests.append(addr)
        print
        print "Testing Output cards..." 
        print      
        time.sleep(self.DelayBetwenOutTests)    
        for test in self.OutputTests:
            cardtype = self.IOCG.DiscoverDict.get(test)
            if cardtype != None:     
                testname = "self.test_%s(%d)"%(cardtype.replace(" ","_"),test)
                try:
                    eval(testname)
                except:
                    print "Testing %s at address %0.2X..."%(cardtype,test)
                    print " Has no tests for this card"
                    print "End of test"
                    print 
                time.sleep(self.DelayBetwenOutTests)
        print "End of Output tests"
        print
        print "Enabling global poll"
        print
        self.CAEIF.commandstatemachine("ENABLEPOLL\r\n",">",500)
        time.sleep(1)
        print "Testing Input cards on curses screens..."
        print
        time.sleep(2)  
        self.stdscr = curses.initscr()
        curses.curs_set(0)
        self.height, self.width = self.stdscr.getmaxyx()
        for test in self.InputTests:
            cardtype = self.IOCG.DiscoverDict.get(test)
            if cardtype != None:     
                testname = "self.test_%s(%d)"%(cardtype.replace(" ","_"),test)
                try:   
                    eval(testname)
                except:
                    pass   
        self.stdscr.refresh()
        curses.curs_set(1)
        curses.endwin()
        sys.stdout = sys.__stdout__ = self.stdout = os.fdopen(sys.__stdout__.fileno(), 'w', 0)   
        time.sleep(1)                    
        print "Disabling global poll"
        print
        self.CAEIF.commandstatemachine("DISABLEPOLL\r\n",">",500)
        print "End of Input tests"
        print                   

    def test_16_channel_DIGITAL_OUTPUT(self, addr):
        """Short description: Test for 16 channel DIGITAL OUTPUT cards"""
        print "Testing 16 channel DIGITAL OUTPUT at address %0.2X..."%addr 
        print " Generating Michael Knight side effect on leds"
        self.IOIF.send("a%Xb0dFF\r\n"%addr)
        self.IOIF.send("a%Xb1dFF\r\n"%addr)
        for r in range(4):         
            for i in range(8):
                self.IOIF.send("a%Xb0d%0.2X\r\n"%(addr, self.BM.inverse(int(math.pow(2,i)),'int')))
                self.IOIF.send("a%Xb1d%0.2X\r\n"%(addr, self.BM.inverse(int(math.pow(2,7-i)),'int')))
                time.sleep(0.1)
        self.IOIF.send("a%Xb0dFF\r\n"%addr)
        self.IOIF.send("a%Xb1dFF\r\n"%addr)        
        print "End of all tests"
        print
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # Test can optimize for 20x4 or 20x2 characters LCDs, please comment and uncomment the respective sections in code. 
    # <BR><BR>
    def test_ALPHANUMERIC_LCD_CONTROLLER(self, addr):
        """Short description: Test for ALPHANUMERIC LCD CONTROLLER cards"""
        ##Test optimized for 20X4 Characters LCD
        ##Uncomment the following two lines for test 20x4 characters LCDs
        #DateLine = 2
        #TimeLine = 3
        ##Test optimized for 20X2 Characters LCD
        ##Uncomment the following two lines for test 20x2 characters LCDs
        DateLine = 0
        TimeLine = 1
        ##Test optimize session end
        LCD = PPLCDHANDLER(self.CAEIF, self.IOIF)
        LCD.setlcdcontrolleraddress(addr)
        print "Testing ALPHANUMERIC LCD CONTROLLER at address %0.2X..."%addr    
        print " Clearing LCD"
        LCD.clear()
        time.sleep(2)
        print " Printing text to LCD's first line" 
        LCD.printat(2, 0, "LCD PROGRAMMING")
        print " Printing text to LCD's second line"
        LCD.printat(2, 1, "is  very   easy")
        time.sleep(1)
        DateLineStr = "third"
        if DateLine == 0:
            time.sleep(2)
            LCD.clear()
            DateLineStr = "first"
        print " Printing current date to the %s line"%DateLineStr
        LCD.printat(0, DateLine, time.strftime("Now: %a,%d %b %Y", time.localtime()))
        time.sleep(2)
        TimeLineStr = "fourth"
        if TimeLine == 1:
            TimeLineStr = "second"
        print " Printing current time to %s line 10 times"%TimeLineStr
        for i in range(11):
            LCD.printat(2, TimeLine, time.strftime("Time:  %H:%M:%S", time.localtime()))
            time.sleep(1)
        time.sleep(1)
        print " LCD backlight is off"
        LCD.clear()
        LCD.printat(3, 0, "BACKLIGHT OFF")
        LCD.backlight("OFF")
        time.sleep(3)
        print " LCD backlight is on"
        LCD.clear()
        LCD.printat(3, 0, "BACKLIGHT ON")
        LCD.backlight("ON")
        time.sleep(2)
        print " LCD cursor is on"
        LCD.clear()
        LCD.printat(1, 0, "CURSOR ON")
        LCD.printat(9,1," ")
        LCD.cursor("ON")
        time.sleep(3)
        print " LCD blink is on"
        LCD.printat(11, 0, "BLINK ON")
        LCD.printat(9,1," ")
        LCD.blink("ON")
        time.sleep(4)
        print " LCD cursor is off"
        LCD.cursor("OFF")        
        print " Clearing LCD"
        LCD.clear()
        print " Prints text to LCD's first line"
        LCD.printat(6, 0, "TEST END")
        print "End of test"
        print

    def test_6_channel_RC_SERVO_CONTROLLER(self, addr):
        """Short description: Test for 6 channel RC SERVO CONTROLLER cards"""
        print "Testing 6 channel RC SERVO CONTROLLER at address %0.2X..."%addr
        print " Moving servo on channel 0 to middle"
        self.IOIF.send("a%Xb0d80\r\n"%addr)
        time.sleep(2)
        print " Moving servo on channel 0 to left"
        self.IOIF.send("a%Xb0d50\r\n"%addr)
        time.sleep(2)
        print " Moving servo on channel 0 to right"
        self.IOIF.send("a%Xb0dB0\r\n"%addr)
        print "End of test"
        print
    
    ## Documentation for method. <B></B> <I></I> <B><I></I></B>
    # If you want to test all motor driver channels please uncomment the respective region in code. 
    # <BR><BR>
    def test_3_channel_DC_MOTOR_CONTROLLER(self, addr):
        """Short description: Test for 3 channel DC MOTOR CONTROLLER cards"""
        print "Testing 3 channel DC MOTOR CONTROLLER at address %0.2X..."%addr
        print " Testing manual mode on channel 0..2"
        print " Setting up motor silent range to 00.."
        #Check channel 0 with high level feedback of CAE interface
        if "ANSWER WRONG" not in self.CAEIF.commandstatemachine("SETMSR0:%X=00\r\n"%addr,"CIA: MSR value of the card is SET\r\n\r\r\nMPS:0x%X:MSR0:0x00\r\n\r\r\n>\r\n\r\r\n"%addr,2500):
            print " Enabling control on channel 0 to forward"
            self.IOIF.send("a%Xb1dFF\r\n"%addr)
            self.IOIF.send("a%Xb2dFF\r\n"%addr)
            self.IOIF.send("a%Xb3dFF\r\n"%addr)
            self.IOIF.send("a%Xb0d20\r\n"%addr)
            time.sleep(1)
            print " Throttleing up motor slowly on channel 0..."
            for i in range(0,100):
                self.IOIF.send("a%Xb1d%s\r\n"%(addr,self.BM.inverse(i,'str')))
                time.sleep(0.1)
            time.sleep(2)
            print " Throttleing down motor slowly on channel 0..."
            for i in range(100,0,-1):
                self.IOIF.send("a%Xb1d%s\r\n"%(addr,self.BM.inverse(i,'str')))
                time.sleep(0.1)
            print " Changing motor turning direction. Enabling control on channel 0 to backward"    
            self.IOIF.send("a%Xb0d24\r\n"%addr)
            time.sleep(1)
            print " Throttleing up motor slowly on channel 0..."
            for i in range(0,200):
                self.IOIF.send("a%Xb1d%s\r\n"%(addr,self.BM.inverse(i,'str')))
                time.sleep(0.1)
            print " Stopping motor immediatelly on channel 0..."       
            self.IOIF.send("a%Xb1d%s\r\n"%(addr,self.BM.inverse(0,'str')))
            time.sleep(2)   
            print " Disabling control on channel 0"
            self.IOIF.send("a%Xb0d00\r\n"%addr)
        else:
            print " Motor controller card setup failed"
        ##If you want to test channel 1 and 2 uncomment following region:
        ##Check channel 1 with low level feedback of CAE interface    
        #time.sleep(2)
        #self.CAEIF.commandstatemachine("SETMSR1:%X=00\r\n"%addr,">",2500)
        #print " Enabling control on channel 1 to forward"
        #self.IOIF.send("a%Xb1dFF\r\n"%addr)
        #self.IOIF.send("a%Xb2dFF\r\n"%addr)
        #self.IOIF.send("a%Xb3dFF\r\n"%addr)
        #self.IOIF.send("a%Xb0d10\r\n"%addr)
        #time.sleep(1)
        #print " Throttleing up motor slowly on channel 1..."
        #for i in range(0,100):
        #    self.IOIF.send("a%Xb2d%s\r\n"%(addr,self.BM.inverse(i,'str')))
        #    time.sleep(0.1)
        #time.sleep(2)
        #print " Throttleing down motor slowly on channel 1..."
        #for i in range(100,0,-1):
        #    self.IOIF.send("a%Xb2d%s\r\n"%(addr,self.BM.inverse(i,'str')))
        #    time.sleep(0.1)
        #print " Changing motor turning direction. Enabling control on channel 1 to backward"    
        #self.IOIF.send("a%Xb0d12\r\n"%addr)
        #time.sleep(1)
        #print " Throttleing up motor slowly on channel 1..."
        #for i in range(0,200):
        #    self.IOIF.send("a%Xb2d%s\r\n"%(addr,self.BM.inverse(i,'str')))
        #    time.sleep(0.1)
        #print " Stopping motor immediatelly on channel 1..."       
        #self.IOIF.send("a%Xb2d%s\r\n"%(addr,self.BM.inverse(0,'str')))
        #time.sleep(2)   
        #print " Disabling control on channel 1"
        #self.IOIF.send("a%Xb0d00\r\n"%addr)
        ##Check channel 3 with low level feedback of CAE interface
        #time.sleep(2)
        #self.CAEIF.commandstatemachine("SETMSR2:%X=00\r\n"%addr,">",2500)
        #print " Enabling control on channel 2 to forward"
        #self.IOIF.send("a%Xb1dFF\r\n"%addr)
        #self.IOIF.send("a%Xb2dFF\r\n"%addr)
        #self.IOIF.send("a%Xb3dFF\r\n"%addr)
        #self.IOIF.send("a%Xb0d08\r\n"%addr)
        #time.sleep(1)
        #print " Throttleing up motor slowly on channel 2..."
        #for i in range(0,100):
        #    self.IOIF.send("a%Xb3d%s\r\n"%(addr,self.BM.inverse(i,'str')))
        #    time.sleep(0.1)
        #time.sleep(2)
        #print " Throttleing down motor slowly on channel 2..."
        #for i in range(100,0,-1):
        #    self.IOIF.send("a%Xb3d%s\r\n"%(addr,self.BM.inverse(i,'str')))
        #    time.sleep(0.1)
        #print " Changing motor turning direction. Enabling control on channel 2 to backward"    
        #self.IOIF.send("a%Xb0d09\r\n"%addr)
        #time.sleep(1)
        #print " Throttleing up motor slowly on channel 2..."
        #for i in range(0,200):
        #    self.IOIF.send("a%Xb3d%s\r\n"%(addr,self.BM.inverse(i,'str')))
        #    time.sleep(0.1)
        #print " Stopping motor immediatelly on channel 2..."       
        #self.IOIF.send("a%Xb3d%s\r\n"%(addr,self.BM.inverse(0,'str')))
        #time.sleep(2)   
        #print " Disabling control on channel 2"
        #self.IOIF.send("a%Xb0d00\r\n"%addr)
        ## End of uncommentable region
        
        #Check channel 1 automatic control mode with high level feedback of CAE interface
        time.sleep(1)
        print " Testing automatic mode on channel 0"
        print " Setting up motor silent range to +-0A.."
        if "ANSWER WRONG" not in self.CAEIF.commandstatemachine("SETMSR0:%X=0A\r\n"%addr,"CIA: MSR value of the card is SET\r\n\r\r\nMPS:0x%X:MSR0:0x0A\r\n\r\r\n>\r\n\r\r\n"%addr,2500):
            print " Throttleing motor up then down slowly forward and backward on channel 0..."
            for i in range(128,178):
                self.IOIF.send("a%Xb1d%0.2X\r\n"%(addr,i))
                time.sleep(0.1)
            for i in range(178,78,-1):
                self.IOIF.send("a%Xb1d%0.2X\r\n"%(addr,i))
                time.sleep(0.1)
            for i in range(78,128):
                self.IOIF.send("a%Xb1d%0.2X\r\n"%(addr,i))
                time.sleep(0.1)    
        else:
            print " Motor controller card setup failed"
        print "End of test"    
        print

    def test_16_channel_DIGITAL_INPUT(self, addr):
        """Short description: Test for 16 channel DIGITAL INPUT cards"""
        self.CAEIF.commandstatemachine("POLLON:%X\r\n"%addr,"CIA: POLLON OK at address %X\r\n>\r\n"%addr,500) 
        self.stdscr.clear()
        self.printtocenter(self.stdscr, 2, self.width, "Testing 16 channel DIGITAL INPUT at address %0.2X..."%addr)              
        self.printtocenter(self.stdscr, self.height-2, self.width, "Press any key for next test")
        self.printtocenter(self.stdscr, 10, self.width, "You should be to prod buttons on the input card now...")
        align = self.printtocenter(self.stdscr, 6, self.width, "Block 0 DATA:           BLOCK 1 DATA:")  
        self.stdscr.addstr(8, align-1, "0 0 0 0 0 0 0 0", curses.A_BOLD) 
        self.stdscr.addstr(8, align+23, "0 0 0 0 0 0 0 0", curses.A_BOLD) 
        self.stdscr.nodelay(1) 
        while(1):   
            if self.IOIF.getinputflag():
                data = self.IOIF.getinputdata()
                if "a%Xb0"%addr in data:
                    self.stdscr.addstr(8, align-1, " ".join(list(self.BM.hexstr2binstr(data[5:7]))), curses.A_BOLD)         
                if "a%Xb1"%addr in data:
                    self.stdscr.addstr(8, align + 23, " ".join(list(self.BM.hexstr2binstr(data[5:7]))), curses.A_BOLD)        
            c = self.stdscr.getch()           
            if c != -1:  
                break; 
        self.stdscr.refresh()
        self.CAEIF.commandstatemachine("POLLOFF:%X\r\n"%addr,"CIA: POLLOFF OK at address %X\r\n>\r\n"%addr,500)           

    def test_6_channel_ANALOGUE_INPUT(self, addr):
        """Short description: Test for 6 channel ANALOGUE INPUT cards"""
        self.CAEIF.commandstatemachine("POLLON:%X\r\n"%addr,"CIA: POLLON OK at address %X\r\n>\r\n"%addr,500) 
        self.stdscr.clear()
        self.printtocenter(self.stdscr, 2, self.width, "Testing 6 channel ANALOGUE INPUT at address %0.2X..."%addr)              
        self.printtocenter(self.stdscr, self.height-2, self.width, "Press any key for next test")
        self.printtocenter(self.stdscr, 10, self.width, "You should be to wind connected potmeters on the input card now...")
        align = self.printtocenter(self.stdscr, 6, self.width, "Block 0:  BLOCK 1:  BLOCK 2:  BLOCK 3:  BLOCK 4:  BLOCK 5:")
        self.stdscr.addstr(8, align, "  000       000       000       000       000       000", curses.A_BOLD) 
        self.stdscr.nodelay(1) 
        while(1):   
            if self.IOIF.getinputflag():
                data = self.IOIF.getinputdata()
                if "a%Xb0"%addr in data:
                    self.stdscr.addstr(8, align+2, "%0.3d"%int(data[5:7],16), curses.A_BOLD)
                if "a%Xb1"%addr in data:
                    self.stdscr.addstr(8, align+12, "%0.3d"%int(data[5:7],16), curses.A_BOLD)
                if "a%Xb2"%addr in data:
                    self.stdscr.addstr(8, align+22, "%0.3d"%int(data[5:7],16), curses.A_BOLD)
                if "a%Xb3"%addr in data:
                    self.stdscr.addstr(8, align+32, "%0.3d"%int(data[5:7],16), curses.A_BOLD)    
                if "a%Xb4"%addr in data:
                    self.stdscr.addstr(8, align+42, "%0.3d"%int(data[5:7],16), curses.A_BOLD)   
                if "a%Xb5"%addr in data:
                    self.stdscr.addstr(8, align+52, "%0.3d"%int(data[5:7],16), curses.A_BOLD)                               
            c = self.stdscr.getch()           
            if c != -1:  
                break; 
        self.stdscr.refresh()
        self.CAEIF.commandstatemachine("POLLOFF:%X\r\n"%addr,"CIA: POLLOFF OK at address %X\r\n>\r\n"%addr,500)          
 
    def test_KEYMX_and_ROTE_CONTROLLER(self, addr):
        """Short description: Test for KEYMX and ROTE CONTROLLER cards"""
        self.CAEIF.commandstatemachine("POLLON:%X\r\n"%addr,"CIA: POLLON OK at address %X\r\n>\r\n"%addr,500) 
        OA = PPRENCOUTACTIONS()
        SM = PPSTATEMACHINE("1", ["00"], OA)
        SM.additemtostatetable("1", "20", "", "2")
        SM.additemtostatetable("2", "60", "upsignalaction()", "3")
        SM.additemtostatetable("3", "40", "", "4")
        SM.additemtostatetable("4", "00", "upsignalaction()", "1")   
        SM.additemtostatetable("1", "40", "", "4")
        SM.additemtostatetable("4", "60", "downsignalaction()", "3")
        SM.additemtostatetable("3", "20", "", "2")
        SM.additemtostatetable("2", "00", "downsignalaction()", "1")
        SM.start()
        self.stdscr.clear()
        align = self.printtocenter(self.stdscr, 2, self.width, "Testing KEY matrix and Rotary encoder at address %0.2X..."%addr)
        self.printtocenter(self.stdscr, self.height-2, self.width, "Press any key for next test")
        self.printtocenter(self.stdscr, 5, self.width, "You should prod the matrix keyboard")
        self.printtocenter(self.stdscr, 12, self.width,"indeed you should winding the rotary encoder")
        self.stdscr.addstr(14, align - 7,"| BUTTON: RELEASE | UP SIGNALS: 000 | DOWN SIGNALS: 000 | VALUE:  000  |")                                                   #12345678901234567890123456789012345678901234567890123456789 
        self.stdscr.nodelay(1) 
        for i in range(5):
            self.IOIF.getinputdata()
        #self.IOIF.getinputdata()
        xpos = align + 4
        while(1):   
            if self.IOIF.getinputflag():
                data = self.IOIF.getinputdata()
                if "a%Xb0"%addr in data:
                    encoderstate = self.BM.mask(data[5:7],"60")
                    SM.inputchange(0,encoderstate)
                    if self.BM.getbitstate(data[5:7],4) == "1":
                        self.stdscr.addstr(7, xpos, self.IOCG.KeyCodes.get(data[6:7]))
                        xpos += 1
                    elif self.BM.getbitstate(data[5:7],7) == "1":     
                        self.stdscr.addstr(14, align +2,"  PUSH  ")
                    elif self.BM.getbitstate(data[5:7],7) == "0":     
                        self.stdscr.addstr(14, align +2," RELEASE")
                self.stdscr.addstr(14, align +25,OA.getupsignals())     
                self.stdscr.addstr(14, align +45,OA.getdownsignals())     
                self.stdscr.addstr(14, align +59,OA.getvalue())                      
            c = self.stdscr.getch()           
            if c != -1:  
                break; 
        SM.stop()           
        self.stdscr.refresh()
        self.CAEIF.commandstatemachine("POLLOFF:%X\r\n"%addr,"CIA: POLLOFF OK at address %X\r\n>\r\n"%addr,500)