from psychopy import core
import pygame, parallel, serial


# this defines the DataSync class, scroll down to see an example of how to use it

class DataSync():
    def __init__(self,audioSync = None, portType = None, portAddress = None, portResetCode = 0, portSyncCode = 10):
        
        if audioSync!=None:
            self.audioOn = True
            pygame.mixer.pre_init() 
            pygame.mixer.init()
            self.syncSound = pygame.mixer.Sound(audioSync)
        else:
            self.audioOn = False
        
        self.portType = portType
        self.resetCode = portResetCode
        self.syncPulse = portSyncCode
        
        if self.portType == 'parallel':
            self.port = parallel.ParallelPort(portAddress)
            self.port.setData(self.reset)
        elif self.portType == 'serial':
            self.port = serial.Serial(portAddress,9600,timeout = 0.05)
            self.port.write(int(self.reset).to_bytes(1,'big'))
    
    def send_signal(self,signalCode):
        if self.portType == 'parallel':
            self.port.setData(signalCode)
        elif self.portType == 'serial':
            self.port.write(int(signalCode).to_bytes(1,'big'))
    
    def reset(self):
        self.send_signal(self.resetCode)
    
    def send_sync_pulse(self):
        self.send_signal(self.syncPulse)
        if self.audioOn:
            soundCh = self.syncSound.play()
        core.wait(0.1)
        self.reset()
        if self.audioOn:
            while soundCh.get_busy():
                pass
    


# this code will run if you run this script
if __name__ == "__main__":
    
    # this is the address for the serial port used in the facial EMG lab at CSAN
    serialPortAddress = 'COM5'
    
    # this is the address for the parallel port used in the GRASP fEMG lab at clinical neurophysiology or the pain clinic
    parallelPortAddress = '0x3FF8'
    
    # audio file if you want to additioanlly use audio sync, e.g. if video recording the experiment
    mySyncSound = 'sync.wav'
    
    # the value when nothing is happening
    myResetCode = 0
    
    # the value to send with the sync pulse
    mySyncCode = 10
    
    # the value to send with a sync pulse
    
    # first set it up, default values of 'None' will turn off that type of sync
    # you can't use both parallel and serial, just one, but you can use audio simultaneously with either, or turn it off
    # this example uses sound and a parallel port
    # this line goes somewhere at the start of your experiment
    mySync = DataSync(audioSync = mySyncSound, portType = 'parallel', portAddress = parallelPortAddress, portResetCode = myResetCode, portSyncCode = mySyncCode)
    
    #then run this line if you want to send a 100ms pulse signal, and play the sound e.g. at the start of the experiment or with the onset of a stimulus
    mySync.send_sync_pulse()
    
    # run this line if you want to send a specific parallel (or serial) value, e.g. when signalling which stimulus is being presented
    mySync.send_signal(5) ## this doesn't play a sound
    
    # wait for the stimulus to be presented
    core.wait(0.5) ## do nothing for 500 ms
    
    # reset the signal
    mySync.reset()