ExposureControl.py

#############################################################
 # 
 # FILE:        ExposureControl.py
 # DATE:        11/16/2021
 # AUTHOR:      Arjun Krishna
 # COMPANY:     BitFlow, Inc.
 # DESCRIPTION: Open a single BitFlow board for capture and 
 #              allow the user to adjust the 
 #              board's timing generator on the fly.
 #              
#############################################################

import sys

if (sys.version_info.major >= 3 and sys.version_info.minor >= 8):
    import os
    #Following lines specifying, the location of DLLs, are required for Python Versions 3.8 and greater
    os.add_dll_directory("C:\BitFlow SDK 6.5\Bin64")
    os.add_dll_directory("C:\Program Files\CameraLink\Serial")

import BFModule.BufferAcquisition as Buf
import BFModule.Display as Disp

import time
import os
import msvcrt

keepUpdating = True

def main():
    global keepUpdating

    print('Exposure Control Example')
    print('---------------------------------')

    numBuffers = 100

    CirAq = Buf.clsCircularAcquisition()

    #Call Open board function by showing the Board select dialog
    CirAq.Open()
    print('Board has been opened\n')

    #Allocate the requested number of buffers
    CirAq.BufferSetup(numBuffers)

    #Setup acquisition using the default options
    CirAq.AqSetup(Buf.SetupOptions.setupDefault)

    #Get board info parameters to create and open a display surface
    xsize = CirAq.GetBoardInfo(Buf.InquireParams.XSize)
    ysize = CirAq.GetBoardInfo(Buf.InquireParams.YSize)
    dispBitsPerPix = CirAq.GetBoardInfo(Buf.InquireParams.BitsPerPixDisplay) #Number of bits per pixel of the display. Currently this value must = 8, 24, or 32.
    imageBitsPerPix = CirAq.GetBoardInfo(Buf.InquireParams.BitsPerPix)

    dispSurf = Disp.clsDispSurf(xsize, ysize, dispBitsPerPix, imageBitsPerPix)

    #Open the display surface
    dispSurf.Open()

    #Get pointer to the memory buffer of the bitmap behind a display surface
    dispSurf.getBitmap()

    time.sleep(0.25)

    print('\nHit \'x\' to Exit')
    print('Hit \'m\' to modify line/frame rate and exposure')
    print('Hit \'r\' to read the exposure control parameters')
    print('Hit \'G\' to Start Acquisition.')

    while(keepUpdating):
        if (msvcrt.kbhit()):
            ch = msvcrt.getch().decode('utf-8')
            if(ch.upper() == 'X'):
                keepUpdating = False
                try:
                    CirAq.AqControl(Buf.AcqCommands.Stop, Buf.AcqControlOptions.Async)
                except:
                    pass
                CirAq.AqCleanup()
                break

            elif(ch.upper() == 'G'):
                #Start acquisition
                CirAq.AqControl(Buf.AcqCommands.Start, Buf.AcqControlOptions.Async)
    
            elif(ch.upper() == 'M'):
                    print("Please enter line/frame rate and exposure time parameters:")
                    expTime = float(input("Enter exposure time in milliseconds: "))
                    period = float(input("Enter line/frame period in milliseconds: "))

                    print("\nTrigger Options:")
                    print("0 - Free run mode")
                    print("1 - One-shot from trigger")
                    print("2 - One-shot from encoder")
                    trigMode = Buf.NTGTrigModes(int(input("Enter trigger mode: ")))

                    print(trigMode)

                    print("\nExposure signal mode options:")
                    print("0 - Asserted low")
                    print("1 - Asserted high")
                    selection = int(input("Enter exposure signal mode: "))
                    if(selection == 0):
                        trigPolarity = False #Buf.TriggerPolarity.AssertedLow
                    elif(selection == 1):
                        trigPolarity = True #Buf.TriggerPolarity.AssertedHigh
                    else:
                        print("Invalid selection")

                    print(trigPolarity)

                    print("\nOutput signal options:")
                    print("1 - CC1")
                    print("2 - CC2")
                    print("3 - CC3")
                    print("4 - CC4")
        
                    if (CirAq.isGen2()):
                        print("5 - TRIGGER")
                        print("6 - ENCODER A")
                        print("7 - ENCODER B")
                        userInput = int(input("\nEnter output signal: "))

                        if(userInput < 5):
                            outputSignal = Buf.NTGOutputSignal(userInput)
                        else:
                            if(userInput == 5):
                                outputSignal = Buf.NTGOutputSignal.InputTrig
                            elif(userInput == 6):
                                outputSignal = Buf.NTGOutputSignal.InputEncA
                            elif(userInput == 7):
                                outputSignal = Buf.NTGOutputSignal.InputEncB
                    else:
                        print("5 - GPOUT0")
                        print("6 - GPOUT1")
                        print("7 - GPOUT2")
                        print("8 - GPOUT3")
                        print("9 - TRIGGER")
                        print("10 - ENCODER")

                        if(userInput < 5):
                            outputSignal = Buf.NTGOutputSignal(userInput)
                        else:
                            if(userInput == 5):
                                outputSignal = Buf.NTGOutputSignal.OutputGP0
                            elif(userInput == 6):
                                outputSignal = Buf.NTGOutputSignal.OutputGP1
                            elif(userInput == 7):
                                outputSignal = Buf.NTGOutputSignal.OutputGP2
                            elif(userInput == 8):
                                outputSignal = Buf.NTGOutputSignal.OutputGP3
                            elif(userInput == 9):
                                outputSignal = Buf.NTGOutputSignal.InputTrig
                            elif(userInput == 10):
                                outputSignal = Buf.NTGOutputSignal.InputEncA

                    print(outputSignal)

                    exp = Buf.ExposureControl(expTime, period, trigMode, trigPolarity, outputSignal)

                    CirAq.SetExposureControl(exp)
                    print("\nProgramming new exposure parameters")
                    try:
                        CirAq.SetExposureControl(exp)
                    except Exception as e:
                        print(e.what())
                        print("Error programming new exposure. No changes made\n")
                    else:
                        print('Done.')

            elif(ch.upper() == 'R'):
                print('\nReading Exposure control parameters')
                try:
                    exp = CirAq.GetExposureControl()
                except Exception as e:
                    print(e.what())
                    print("Error reading exposure control parameters.\n")
                else:
                    print('Exposure time =\t\t', exp.ExposurePeriod, ' ms')
                    print('Line Frame Period =\t', exp.LineFramePeriod, ' ms')
                    print('Trigger Mode =\t\t', exp.TriggerMode)
                    print('Assert High =\t\t', exp.AssertHigh)
                    print('Output Signal =\t\t', exp.OutputSignal)

        else:
            try:
                if(CirAq.GetAcqStatus().Start == True):
                    curBuf = CirAq.WaitForFrame(0)
                    if (dispSurf.isOpen()):
                        dispSurf.updateDisplay(CirAq.GetBufArray(), curBuf, Disp.DispOptions.FORMAT_NORMAL)
                    #print(CirAq.)
            except Exception as e:
                print(e)

    #Close the display surface and free the resources
    dispSurf.Close()          

    #Deallocate buffers
    CirAq.BufferCleanup()

    #Close the board
    CirAq.Close()

if __name__ == "__main__":
    main()