-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrig_state_machine.py
141 lines (111 loc) · 3.85 KB
/
rig_state_machine.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import pyaudio
import wave
import time
import sys
import os
import zmq
import serial
import struct
import RPi.GPIO as GPIO
# Classes and functions
class WavPlayer():
def __init__(self, pin = 5):
self.pin = pin
self.pa = pyaudio.PyAudio()
self.wf = None
self.played = False
# init the pins
GPIO.setup(self.pin, GPIO.OUT)
GPIO.output(self.pin, GPIO.LOW)
def play_callback(self, in_data, frame_count, time_info, status):
data = self.wf.readframes(frame_count)
return (data, pyaudio.paContinue)
def play_file(self, wave_file_path):
self.wf = wave.open(wave_file_path, 'rb')
stream = self.pa.open(format=self.pa.get_format_from_width(self.wf.getsampwidth()),
channels=self.wf.getnchannels(),
rate=self.wf.getframerate(),
output=True,
stream_callback=self.play_callback)
GPIO.output(self.pin, GPIO.HIGH)
stream.start_stream()
while stream.is_active():
#time.sleep(0.1)
pass
GPIO.output(self.pin, GPIO.LOW)
time.sleep(0.1)
stream.stop_stream()
stream.close()
self.flush_file()
def flush_file(self):
self.wf = None
self.played = False
class SerialOutput():
def __init__(self, port="/dev/ttyS0", baudrate=300):
self.port = port
self.baudrate = baudrate
self.serial = serial.Serial(port=port, baudrate=self.baudrate)
def open_out(self):
self.serial.close()
self.serial.open()
if self.serial.isOpen():
print "Serial is open!"
def close(self):
self.serial.close()
def write_number(self, number, dtype='L'):
self.serial.write(struct.pack(dtype, number))
# receives a line and turns it into a dictionary
# the line has one word for the command and n pairs that go to key, value (separator is space)
def parse_command(cmd_str):
split_cmd = cmd_str.split(' ')
assert(len(split_cmd)%2)
cmd_par = {split_cmd[i] : split_cmd[i+1] for i in range(1, len(split_cmd), 2)}
cmd = split_cmd[0]
return cmd, cmd_par
def execute_command(cmd, pars):
command = command_functions[cmd]
response = command(pars)
return response
def run_trial(trial_pars):
#for now the trial is just playing a sound file
# read the parameters
wavefile_path = trial_pars['stim_file']
trial_number = int(float(trial_pars['number']))
# do the deed
so.write_number(trial_number)
time.sleep(0.5)
wp.play_file(wavefile_path)
return 'played'
def init_board():
# init the board, the pins, and everything
GPIO.setmode(GPIO.BCM)
return 'ok'
def state_machine():
command_functions = {'trial' : run_trial, 'init' : init_board}
# Configuration of Pins
pin_audio = 26
port = "5558"
wave_file = os.path.abspath('/root/experiment/stim/audiocheck.net_sin_1000Hz_-3dBFS_3s.wav')
# a very simple server that waits for commands
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://*:%s" % port)
print('Setup ZMQ')
while True:
print('Waiting for commands...')
# Wait for next request from client
command = socket.recv()
print("Received request: " + command)
cmd, cmd_par = parse_command(command)
response = execute_command(cmd, cmd_par)
time.sleep(1)
socket.send("%s from %s" % (response, port))
command_functions = {'trial' : run_trial, 'init' : init_board}
if __name__ == '__main__':
print('Gentnerlab OpenEphys Rig State Machine')
print('Originally by Zeke Arneodo, Modified by Brad Theilman')
# start the wave player
init_board()
wp = WavPlayer()
so = SerialOutput()
state_machine()