#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This demo was created by Andrew Schofield to show how to use the advanced input/output 
functionality in the bits.py module. 

It also acts as a test routine to make sure your device is working and that the 
bits.py module is intact. 

The bits.py module mostly provides wrapper functions for getting control of the
CRS hardware famility, Bits++, Bits#, Display++ and their variants. ViSaGe devices
are not supported unless you have one with a Bits# emulation mode. 

Most but not all of the bits.py commands are tested. Similarly
most but not all of the CRS functionality is tested often in combination. But there 
are two many combinations to test every thing.

There is some support for driving stereo goggles (CRS FE1) via the D25 feature connector 
output. Bits# has a stereo goggles port which works differently and is not tested. Nor is 
support for it currently provided in bits.py.

Stereo via frame interleaving is not recommended on a Display++ due to LCD pixel transition speeds.
CRS have a 3D version of Display++ which uses polarised galsses and line interlaving. This is not
specifically implemente din bits.py yet but you can still build an stereo image yourself.

Bits++ support is relatively minimal with, in particular, digital inputs not being supported.

To work effectively on a Bits++ box you will need an Oscilloscope and:
    Connect DOUT1 (pin2) to Oscilloscope channel A"
    Connect DOUT5 (pin6) to Oscilloscope channel B"
You will then observe changes in those outputs.

To work effectively on all other devices you will need to:
    Connect DOUT1 (pin 2) to DIN7 (pin 21)
    Connect DOUT5 (pin 6) to DIN8 (pin 24)
    Connect DOUT6 (pin 7) to DIN9 (pin 25)
and Connect Analog OUT 1 TO Analog IN 1 if you have a Bits# or a Display++
with the optional Analog factures. This will cunningly allow the CRS device to monitor
its own outputs. Testing both output and input features at once.

You can select the CRS hardware and options in a dialog box.
Note Screen is the screen number of your CRS connected monitor = 0 or 1.
(your working in coder after all).

Enter None to see what happens if there is 
no device and hnce no serial comms.

Note that the monitor and LUT sessings don't really matter much.

You will get warnings about stuff being found on the input buffer. This is because the command to
stop the CRS device from sending data expects a return message to say that data collection has stopped
but will always find the last chunk of data recorded instead.

See xxxxx for a description of the bits.py appraoch to CRS hardware and programer guide.

"""
from __future__ import absolute_import, division, print_function
from psychopy import locale_setup, sound, gui, visual, core, data, event, logging
from psychopy import monitors, filters, gamma 
from psychopy.hardware import crs
from scipy import misc

from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,
                                STOPPED, FINISHED, PRESSED, RELEASED, FOREVER)
import numpy as np  # whole numpy lib is available, prepend 'np.'
from numpy import (sin, cos, tan, log, log10, pi, average,
                   sqrt, std, deg2rad, rad2deg, linspace, asarray)
from time import sleep, clock, time
import os  # handy system and path functions
import sys  # to get file system encoding


# Ensure that relative paths start from the same directory as this script
_thisDir = os.path.dirname(os.path.abspath(__file__))#.decode(sys.getfilesystemencoding())
os.chdir(_thisDir)

# Store info about the experiment session
expName = 'crsTest'  # from the Builder filename that created this script
expInfo = {'Device': 'Display++',
           'Analog': 'No',
           'Touch screen': 'Yes',
           'Button box': 'CB6',
           'Monitor': 'Display++160',
           'LUTfile': 'invGammaLUT.txt',
           'Screen': '1'}
dlg = gui.DlgFromDict(dictionary=expInfo, title=expName)
if dlg.OK == False:
    core.quit()  # user pressed cancel


#===================================================================#
# Setup the Window
print("Open window")
win = visual.Window(
    size=(800, 600), fullscr=True, screen=int(expInfo['Screen']),
    allowGUI=False, allowStencil=False,
    monitor=expInfo['Monitor'], color=[0,0,0], colorSpace='rgb',
    blendMode='avg', useFBO=True,
    units='deg')
# store frame rate of monitor if we can measure it
expInfo['frameRate'] = win.getActualFrameRate()
if expInfo['frameRate'] != None:
    frameDur = 1.0 / round(expInfo['frameRate'])
else:
    frameDur = 1.0 / 60.0  # could not measure, so guess

# Initialize components for Routine "preflight"
#preflightClock = core.Clock()


#frameRate=win.getActualFrameRate()
#print(expInfo['frameRate'])

mon=monitors.Monitor(expInfo['Monitor'],distance=56)

#=======================================================================================#
#Opening the appropriate a CRS class of the desired / necessary type
print("open CRS")
if expInfo['Device']=='Bits++':
    bits = crs.BitsPlusPlus(win, mode='bits++',rampType=1) 
if expInfo['Device']=='Bits#':
    bits = crs.BitsSharp(win, mode='bits++',checkConfigLevel=1) 
if expInfo['Device']=='Display++' or expInfo['Device']=='None':
    if expInfo['Touch screen']=="Yes":
        if expInfo['Device']=='Display++':
            bits = crs.DisplayPlusPlusTouch(win, mode='bits++',checkConfigLevel=1) 
        else:
            bits = crs.DisplayPlusPlusTouch(win, mode='bits++',checkConfigLevel=1,noComms=True) 
    else:
        if expInfo['Device']=='Display++':
            bits = crs.DisplayPlusPlus(win, mode='bits++',checkConfigLevel=1) 
        else:
            bits = crs.DisplayPlusPlus(win, mode='bits++',checkConfigLevel=1,noComms=True) 

#=======================================================================================#
# If Bits# or Display++ initialise the device.                                          #
# This can also be done via parameter setters but this illustrates the low level send   #
# comands.                                                                              #
if  expInfo['Device'] != 'Bits++':
    #bits = crs.BitsSharp(win, mode='bits++') 
    #gamma.setGamma(win.winHandle._dc, 1.0, 1)
    bits.sendMessage('$TemporalDithering=[ON]\r')
    bits.read(timeout=0.1)
    bits.sendMessage('$VideoFrameRate\r')
    bits.read(timeout=0.1)
    lutfile = expInfo['LUTfile']
    msg='$enableGammaCorrection=['+lutfile+']\r'
    bits.sendMessage(msg)
    bits.read(timeout=0.1)
    bits.sendMessage('$EnableTouchScreen=[OFF]\e')
    bits.read(timeout=0.1)
    bits.sendMessage('$Stop\r')
    # Clear the buffer
    bits.flush()
    bits.RTBoxDisable()
    bits.flush()
    print("OK I seem to have cleared the buffer now")

#=======================================================================================#
# House keeping
    print("Connect DOUT1 (pin 2) to DIN7 (pin 21)")
    print("Connect DOUT5 (pin 6) to DIN8 (pin 24)")
    print("Connect DOUT6 (pin 7) to DIN9 (pin 25)")
    if expInfo['Device'] == 'Bits#' or expInfo['Analog'] == 'Yes':
        print("Connect Analog OUT 1 TO Analog IN 1")
else:
    print("Connect DOUT1 (pin2) to Oscilloscope A")
    print("Connect DOUT5 (pin6) to Oscilloscope B")

sleep(10)

# Make a grating
grating = visual.GratingStim(
    win=win, name='grating',units='norm', 
    tex='sin', mask=None,
    ori=0, pos=(0,0), size=(1, 1), sf=5, phase=1.0,
    color=[1,1,1], colorSpace='rgb', opacity=1,blendmode='avg',
    texRes=128, interpolate=True, depth=-2.0)

bits.resetClock()
bits.win.flip()
sleep(1)

#=============================================================================#
#LUT test
# Varies the contrast of a grating by setting the software LUT in bits++ mode
# via a Tlock command.
print("1: LUT test")
print("Should see pulsating grating")
frameN=-1
while frameN < bits.frameRate*5:
    # get current time
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    #bits.setAnalog(AOUT1 = 5*sin(t*50), AOUT2 = 5*cos(t*50))
    # *thanksMsg* updates
    if frameN == 0:
        grating.setAutoDraw(True)
    bits.setContrast((sin(np.pi*frameN/bits.frameRate)))
    win.flip()
grating.setAutoDraw(False)
bits.setContrast(1.0)
win.flip()



#=============================================================================#
# Trigger and goggle tests
print("2a: Triggers test")
# Sets up a 2ms trigger pulse and issues via TLock 
# Recoding Digital inputs via the status logging commands
bits.setTrigger(0b0000000010,0.002,0.002)
bits.startTrigger()
bits.win.flip()
T=clock()
if expInfo['Device'] != 'Bits++': #Bist# / Display++ version
    # Recording Digital inputs via the status logging commands

    # Example of starting and stopping status log
    bits.startStatusLog()
    while clock()-T<5:
        bits.win.flip()
    bits.stopStatusLog()
    
    #Example of reading status values
    vals = bits.getAllStatusValues()
    if vals:
        if len(vals) > 20:
            print("All status values")
            for i in range(-20,0):
                print(vals[i])
            print("DIN7 should change lots")
    
    #Example of reading status events
    vals = bits.getAllStatusEvents()
    if vals:
        if len(vals) > 20:
            print("All status events")
            for i in range(-20,0):
                print(vals[i])
            print("Input 7 should have 2ms high every frame.")
else: # Bits++ version
    print("Should observe 2ms pulses on Ch A")
    while clock()-T<5:
        bits.win.flip()
bits.stopTrigger()
bits.win.flip()
sleep(5)
if expInfo['Device'] != 'Bits++':
    bits.flush()

#=============================================================================#
print("2b: Goggles test")
# Sets up alternating left / right goggle control via D25 output and the TLock
bits.startGoggles(left=0,right=1)
bits.win.flip()
T=clock()
if expInfo['Device'] != 'Bits++': # Bits# and Display++ version
    # Recording Digital inputs via the status logging commands
    
    # Example of starting and stopping status log
    bits.startStatusLog()
    while clock()-T<5:
        bits.win.flip()
    bits.stopStatusLog()
    bits.flush()
    
    #Example of reading status values
    vals = bits.getAllStatusValues()
    if vals:
        if len(vals) > 20:
            print("All status values")
            for i in range(-20,0):
                print(vals[i])
            print("DIN8 should change lots")
    
    #Example of reading status events
    vals = bits.getAllStatusEvents()
    if vals:
        if len(vals) > 20:
            print("All status events")
            for i in range(-20,0):
                print(vals[i])
            print("Input 8 should change state every frame.")
else: # Bits++ version
    print("Should observe square wave on Ch B")
    while clock()-T<5:
        bits.win.flip()

bits.stopGoggles()
bits.win.flip()
sleep(5)
if expInfo['Device'] != 'Bits++':
    bits.flush()

#=============================================================================#
print("2c: Goggles with  triggers")
# Drive the goggles and a trigger at the same time.
# Note uses trigger from 2a as this will have been kept
# even when the goggles were used ioin 2b.
bits.startTrigger()
bits.startGoggles()
bits.win.flip()
T=clock()
if expInfo['Device'] != 'Bits++':# Bits# and Display++ version
    # Recording Digital inputs via the status logging commands
    
    # Example of starting and stopping status log
    bits.startStatusLog()
    while clock()-T<5:
        bits.win.flip()
    bits.stopStatusLog()
    bits.flush()
    
    #Example of reading status values
    vals = bits.getAllStatusValues()
    if vals:
        if len(vals) > 20:
            print("All status values")
            for i in range(-20,0):
                print(vals[i])
            print("DIN7 and DIN8 should change lots")
            
    #Example of reading status events
    vals = bits.getAllStatusEvents()
    if vals:
        if len(vals) > 20:
            print("All status events")
            for i in range(-20,0):
                print(vals[i])
            print("Input 7 should have 2ms high every frame.")
            print("Input 8 should change state every frame.")
else: # Bits++ version
    print("Should observe 2ms pulses on Ch A")
    print("Should observe square wave on Ch B")
    while clock()-T<5:
        #sleep(0.002)
        bits.win.flip()

bits.stopGoggles()
bits.stopTrigger()
bits.win.flip()
sleep(5)

if expInfo['Device'] != 'Bits++':
    bits.flush()

#=============================================================================#
# If using a bits++ all available tests are now done
if expInfo['Device'] == 'Bits++':
    print("All tests done")
else: # otherwise carry on
    bits.flush() # Flush the com port often
    
    print("2d: Poll status")
    #=============================================================================#
    # Status polling
    # Example of using the pollStatus command
    bits.pollStatus()
    # Get the digital word form of DIN states
    valD = bits.getDigitalWord()
    # Example of how to print it
    if valD:
        print(bin(valD['DWORD']))
    
    #=============================================================================#
    #RTBox operation
    # Example of RTBox Enable, here using a bespoke mapping to route DIN9 to btn1
    print("2e: Single shot trigger detected by RTBox  via DIN")
    bits.RTBoxEnable(mode=['down'], map=[('btn1','Din9')])
    
    # Example of using send trigger to issue a trigger that will pulse Dout6 which whould be connected to DIN
    bits.sendTrigger(0b1111111,0,0.004)
    bits.win.flip()  # win.flip needed to finish off the trigger

    #Example of using RTBoxKeysPressed to detect button box events.
    if not bits.noComms: # noComms safe
        # Wait for a key - its probably already been recvied anyway.
        while not bits.RTBoxKeysPressed(1):
            continue
    # Get the response
    btn=bits.getRTBoxResponse()
    # Example button response
    if btn:
        print(btn)
    else:
        print("No button")
    bits.flush()
    btn = None
    # Disable the RTBox for now
    bits.RTBoxDisable()
    sleep(5)

    #=============================================================================#
    # Example for makign the CRS device beep
    print("3a: Beep test")
    bits.beep(400,0.5)
    sleep(0.5)
    
    #=============================================================================#
    # Using Tlock to reset the CRS device clock
    print("3b: Clock Reset test")
    bits.resetClock()
    bits.win.flip()
    sleep(1)
    T=clock()
    
    #=============================================================================#
    # Example for using PollStatus to read the device time
    bits.pollStatus()
    print("Time taken to poll status = ",clock()-T)
    val = bits.getStatus()
    if val:
        print("Time recorded by device should be about 1s. Actually = ", val.time)
    sleep(5)
    # Just to make sure the status log has been stopped
    bits.sendMessage('$Stop\r')
    bits.flush()

    #=============================================================================#
    # Example Using statusBox to record key presses
    
    print("4a: Using statusBox and Din")
    bits.statusBoxEnable(mode = ['up','IO10'])
    bits.sendTrigger(0b1111111,0,0.004)
    bits.win.flip()  # win.flip needed to finish off the trigger

    if not bits.noComms: # noComms safe
        # Wait for a key - its probably already been recvied anyway.
        while not bits.statusBoxKeysPressed(1):
            continue
    # Disable the status box as soon as you don't need it.
    bits.statusBoxDisable()
    bits.stopTrigger()
    bits.win.flip() # win.flip to make sure triggers are off.
    # Get the response
    btn = bits.getStatusBoxResponse() # just get first response and ditch others.
    # Example button response
    if btn:
        print(btn)
    else:
        print("No button")

    btn = None
    
    bits.flush()
    sleep(5)
    
    #=============================================================================#
    #   Example using the statusBox with different button boxes
    print("4b: Using statusBox with a button box")
    
    # Enables different statusBox defaults depending on users input
    if expInfo['Button box'] == 'CB6': #IR box
        bits.statusBoxEnable(mode=['CB6','Down'])
        print("Press a button on the Box")
        
        #Example statusBoxWait commant - waits for a button press
        button = bits.statusBoxWait()
        if button:
            print(button)
    elif expInfo['Button box'] == 'IO6': # A wired box
        bits.statusBoxEnable(mode=['IO6','Down'])
        print("Press one of first 3 buttons on the Box")
        
        #Example statusBoxWait commant - waits for a button press
        button = bits.statusBoxWait()
        if button:
            print(button)
    elif expInfo['Button box'] == 'IO': # A wired box with only 3 buttons
        bits.statusBoxEnable(mode=['IO','Down'])
        print("Press of first 3 buttons on the Box")
        
        #Example statusBoxWait commant - waits for a button press
        button = bits.statusBoxWait()
        if button:
            print(button)
    
    #=============================================================================#
    #   Example using the statusBox to get multiple responses
    #   We've left the statusBix running for this
    print("4c: Multiple buttons")
    print("Now press some buttons")
    T = clock()
    while clock()-T<10:
        bits.win.flip()
    bits.statusBoxDisable()
    print('Some buttons presses ',bits.statusBoxKeysPressed())
    res = bits.getAllStatusBoxResponses()
    if res:
        print(len(res))
        print(res)
    bits.flush()

    #=============================================================================#
    # Nore RTBox usage examples
    print("4d: RTBox test")
    bits.flush()
    
    # Enables different RTBox defaults depending on users input
    if expInfo['Button box'] == 'CB6': #IR box
        bits.RTBoxEnable(mode=['CB6','Down'])
        print("Press a button on the Box")
        
        #Example RTBoxWait commant - waits for a button press
        button = bits.RTBoxWait()
        if button:
            print(button)
    elif expInfo['Button box'] == 'IO6': # A wired box
        bits.RTBoxEnable(mode=['IO6','Down'])
        print("Press one of first 3 buttons on the Box")
        
        #Example RTBoxWait commant - waits for a button press
        button = bits.RTBoxWait()
        if button:
            print(button)
    elif expInfo['Button box'] == 'IO': # A wired box
        bits.RTBoxEnable(mode=['IO','Down'])
        print("Press of first 3 buttons on the Box")
        
        #Example RTBoxWait commant - waits for a button press
        button = bits.RTBoxWait()
        if button:
            print(button)
    
    #=============================================================================#
    # Example of how to calibrate or charaterise the RTBox timer
    # relative to the host clock
    print("4e: RTBox calibration test")
    res=bits.RTBoxCalibrate(5)
    bits.RTBoxDisable()
    bits.flush()
    print('Average clock difference =', res)
    
    #=============================================================================#
    # Commands for analog outputs, used if we have a Bits# or a 
    # display++ with analog feature
    if (expInfo['Device'] == 'Bits#' 
        or expInfo['Device'] == 'None' 
        or expInfo['Analog'] == 'Yes'):
        print("5: Analog tests")
        
        
        #=============================================================================#
        # Example of sending an analog out - will continue while we poll the status
        print("5a: Analog only using pollStatus")
        bits.sendAnalog(2,2)
        sleep(1) # let the output it settle
        bits.pollStatus()
        
        # Example for getting analog values and displaying them
        val = bits.getAnalog()
        bits.win.flip()
        #bits.stopAnalog
        print("Analog 1 should be = 2v")
        if val:
            print(val['ADC'])
        sleep(5)
        bits.flush()
        
        #=============================================================================#
        # Example using triggers and analog outputs at the same time.
        print("5b: Analog and triggers")
        # Example using set analog
        bits.setAnalog(3,3)
        # Set a long trigger
        bits.setTrigger(0b1111111101,0.0,0.0084)
        
        #Start both outputs
        bits.startTrigger()
        bits.startAnalog()
        bits.win.flip()
        sleep(1)
        bits.pollStatus()
        valA = bits.getAnalog()
        valD = bits.getDigitalWord()
        bits.stopAnalog
        bits.stopTrigger()
        print("Analog 1 should be = 3v")
        if valA:
            print(valA['ADC'])
        print("Digital word should have bit 8 low")
        if valD:
            print(bin(valD['DWORD']))
        sleep(5)
        bits.flush()
        
        #=============================================================================#
        # Example using triggers, goggles and anaog all at once
        # ALso test the ability of triggers to servive people messing with
        # Goggles and Analog outs as these all use the same communications channel.
        print("5c: Goggles, analog and triggers")
        bits.setAnalog(3,3)
        bits.setTrigger(0b0000000010,0.002,0.002)
        
        # Test to see if triggers can servive lots of toing a froing
        # of the analog and goggles outputs.
        bits.startAnalog()
        bits.win.flip()
        bits.startGoggles()
        bits.win.flip()
        bits.stopAnalog()
        bits.win.flip()
        bits.stopGoggles()
        bits.win.flip()
        
        # Now set them all going
        bits.startGoggles()
        bits.startAnalog()
        bits.startTrigger()
        bits.win.flip()
        T=time()
        
        #Setting the status event parameters to determine which events
        #are recorded. Now only 'up' events will be registered
        bits.setStatusEventParams(DINBase=0b1111111111, 
                                      IRBase=0b111111, 
                                      TrigInBase=0,
                                      ADCBase=0,
                                      threshold=1.0,
                                      mode=['up'])
        bits.startStatusLog()
        while time()-T<5:
            bits.setAnalog(5*sin((time()-T)), 0)
            bits.win.flip()
        bits.stopStatusLog()
        sleep(1)
        bits.flush()
        
        # Analog should show up on the status log
        vals = bits.getAllStatusValues()
        if vals:
            if len(vals) > 1:
                print("All status values")
                for i in range(1,len(vals),700):# only read every 700'th status report as 
                    # analog inputs update slowly relative to everything else
                    print(vals[i])
                print("Should see analog 1 changing")
                
        #The Goggles and triggers are best detected as events
        vals = bits.getAllStatusEvents()
        if vals:
            if len(vals) > 20:
                print("All status events")
                for i in range(-20,0):
                    print(vals[i])
            print("Input 7 should go up once every frame.")
            print("Input 8 should go up every other frame.")
        bits.stopTrigger()
        bits.stopGoggles()
        bits.stopAnalog()
        bits.win.flip()
        
        #=============================================================================#
        # Example for detecting changes on the analog inputs via status events
        # Not the analog threshold was set to 0.5 volts above
        print("5d: Detecting analog events via status")
        bits.setStatusEventParams(DINBase=0b1111111111, 
                                      IRBase=0b111111, 
                                      TrigInBase=0,
                                      ADCBase=0,
                                      threshold=1.0,
                                      mode=['Up'])
        bits.startStatusLog()
        bits.startAnalog()
        T = time()
        while time()-T<10:
            bits.setAnalog(5*sin((time()-T)), 0)
            bits.win.flip()
        bits.stopStatusLog()
        sleep(1)
        bits.stopAnalog()
        bits.flush()
        
        # Analog should show up on the status log
        vals = bits.getAllStatusValues()
        if vals:
            if len(vals) > 1:
                print("Status values")
                for i in range(1,len(vals),700):# only read every 700'th status report as 
                    # analog inputs update slowly relative to everything else
                    print(vals[i])
                print("Should see analog 1 changing")
                
        #Analog changes as events
        vals = bits.getAllStatusEvents()
        if vals:
            if len(vals) > 5:
                print("Status events")
                for i in range(len(vals)):
                    print(vals[i])
            print("Should see some events on Analog 1.")
            print("May get spurious events on some Bits# boxes.")
        bits.stopAnalog()
        bits.win.flip()
       
        #=============================================================================#
        # Example for usinf the statusBox to detect analog events
        print("5e: Using status box to detect analog events")
        bits.sendAnalog(0.5,0.5)
        bits.win.flip
        bits.win.flip
        bits.statusBoxEnable(mode=['Analog','Up','down'], threshold = 3.25)
        bits.sendAnalog(4.0,4.0)
        bits.win.flip
        sleep(2)
        # need to set analog low again by more than
        # threshold in order to record new event
        bits.sendAnalog(0.5,0.5)
        bits.win.flip
        sleep(2)
        bits.sendAnalog(4.0,4.0)
        bits.win.flip
        sleep(2)
        if not bits.noComms: # noComms safe
        # Wait for a key - its probably already been recvied anyway.
            while not bits.statusBoxKeysPressed():
                continue
        # Get the response
        bits.statusBoxDisable()
        btn = bits.getAllStatusBoxResponses()
        
        # Example button response
        if btn:
            print(btn)
        else:
            print("No button")
    
    #=============================================================================#
    # Touch screen tests
    if ((expInfo['Device'] == 'Display++' and expInfo['Touch screen'] == 'Yes')
          or expInfo['Device'] == 'None'):
        print("6: Touch Screen test")
        
        #=============================================================================#
        #Example of a touch enable, wait, disable cycle
        print("6a: Touch the screen")
        bits.touchEnable()
        val=bits.touchWait() # pause while waiting for touch
        bits.touchDisable()
        if val:
            print(val)
        sleep(5)
        
        #=============================================================================#
        # Example of a touch enable, touchPressed, disable cycle
        print("6b: Touch the screen again")
        bits.touchEnable()
        if not bits.noComms:
            while not bits.touchPressed(): # idle while waiting for touch
                # But you could do stuff here
                continue
        # Example of getAllTouchResponses()
        vals=bits.getAllTouchResponses()
        bits.touchDisable()
        if vals:
            for i in range(len(vals)):
                print(vals[i])
            
        sleep(5)
        
        #=============================================================================#
        # Exampe of using a touch log cycle to get lots of touch responses
        bits.startTouchLog()
        print("6c: Touch the screen lots")
        sleep(10)
        bits.stopTouchLog()
        
        #=============================================================================#
        # Example of getting the full touch log and then extracting events
        bits.getTouchLog()
        vals=bits.getTouchEvents()
        if vals:
            for i in range(len(vals)):
                print(vals[i])
    print("All tests done")
del bits
win.close()
core.quit()
