# this implements a very basic auditory oddball task using PsychoPy
# which also sends triggers to an Arduino Bitsi device over a serial connection to mark the presentation of standard and deviant stimuli.
# see https://en.wikipedia.org/wiki/Oddball_paradigm for more details

from psychopy import prefs, visual, core, sound
from utilities import wait_for_space
import random
import serial

prefs.hardware['audioDevice'] = 'Speaker/HP (2- Realtek High Definition Audio)'

bitsi = serial.Serial('COM6', 115200, timeout=1)

screen = visual.Window([800, 600], color='black', units='pix')
fixation = visual.TextStim(screen, text='+', color='white', height=50)
text_standard = visual.TextStim(screen, text='s', color='white', height=50)
text_deviant  = visual.TextStim(screen, text='d', color='white', height=50)
sound_standard = sound.Sound('A', octave=4, secs=0.5)  # standard sound stimulus
sound_deviant  = sound.Sound('A', octave=5, secs=0.5)   # deviant sound stimulus

wait_for_space(screen, 'Press SPACE to start')
fixation.draw()
screen.flip()
core.wait(2)

# present 10 trials of the oddball task
for trial in range(10):
    fixation.draw()
    screen.flip()
    core.wait(0.5)

    condition = random.choice(['s', 's', 's', 's', 'd'])  # 80% standard, 20% deviant

    if condition == 's':
        print('standard')
        stimulus = sound_standard
        trigger = b'\x01'
        text_standard.draw()
    else:
        print('deviant')
        stimulus = sound_deviant
        trigger = b'\x02'
        text_deviant.draw()

    screen.flip()
    bitsi.write(trigger)  # send the trigger to the Arduino Bitsi device
    stimulus.play()  # play the randomly chosen stimulus

wait_for_space(screen, 'Done, press SPACE to finish')

screen.close()
core.quit()
bitsi.close()
