-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathstages.py
executable file
·181 lines (145 loc) · 5.36 KB
/
stages.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#!/bin/python
from mi_module import MIModule
from kbhit import KBHit
from factory_test import Command
from typing import Tuple
import time
import sys
NUM_CHANNELS = 6
DEFAULT_SCALE = -32263
DEFAULT_OFFSET = 32768
SLEEP_TIME = 0.25
class Stages(MIModule):
def read_slider(self, channel: int) -> int:
# sliders after pots
return self.read_pot(channel + NUM_CHANNELS)
def read_button(self, channel: int) -> bool:
# buttons after gates
return self.read_gate(channel + NUM_CHANNELS)
def calibrate_dac_channel(self, channel: int) -> Tuple[int, int]:
# Begin signal output
super().calibrate_dac_channel(channel, 0) # Channel to -1.0V
neg_one_reading = float(
input(f"Enter value on voltmeter for output {channel}: ")
)
super().calibrate_dac_channel(channel, 1) # Channel to +2.5V
pos_two_point_five_reading = float(
input(f"Enter value on voltmeter for output {channel}: ")
)
# Calculate scale and offset
neg_one = -1 / 8
pos_two_point_five = 2 / 8
neg_one_dac_code = (
(neg_one * DEFAULT_SCALE) / (neg_one_reading / 8)
) * neg_one + DEFAULT_OFFSET
pos_two_point_five_dac_code = (
(pos_two_point_five * DEFAULT_SCALE) /
(pos_two_point_five_reading / 8)
) * pos_two_point_five + DEFAULT_OFFSET
scale = (pos_two_point_five_dac_code - neg_one_dac_code) / (
(pos_two_point_five - neg_one)
)
offset = neg_one_dac_code - (neg_one * scale)
# Send
self.port.write_calibration_data(scale, offset)
# Save to module
super().calibrate_dac_channel(channel, 3)
return (scale, offset)
def calibrate_adc_channel(self, channel: int):
super().calibrate_adc_channel(channel, 0)
time.sleep(SLEEP_TIME)
super().calibrate_adc_channel(channel, 1)
time.sleep(SLEEP_TIME)
super().calibrate_adc_channel(channel, 2)
time.sleep(SLEEP_TIME)
def calibrate_dac(self):
dac_data = []
for i in range(NUM_CHANNELS):
dac_data[i] = self.calibrate_dac_channel(i)
print(
"For more accurate DAC output, insert the below code before the return of Settings::Init() and rerun ADC calibration"
)
for scale, offset in dac_data:
print(
f"persistent_data_.channel_calibration_data[{
i}].dac_scale = {scale:.4f};"
)
print(
f"persistent_data_.channel_calibration_data[{
i}].dac_offset = {offset:.4f};"
)
def calibrate_adc(self):
print(
"Patch all channels to their corresponding TIME/LEVEL input. Press enter when ready."
)
input()
for i in range(NUM_CHANNELS):
self.calibrate_adc_channel(i)
def calibrate(self):
print("Beginning full calibration")
self.calibrate_dac()
self.calibrate_adc()
print("Calibration complete!")
def get_state(self):
pots = ["Pots:"] + [self.read_pot(i) for i in range(NUM_CHANNELS)]
buttons = ["Buttons:"] + \
[self.read_button(i) for i in range(NUM_CHANNELS)]
sliders = ["Sliders:"] + \
[self.read_slider(i) for i in range(NUM_CHANNELS)]
normals = ["Normals:"] + [
self.read_normalization(i) for i in range(NUM_CHANNELS)
]
gates = ["Gates:"] + [self.read_gate(i) for i in range(NUM_CHANNELS)]
cvs = ["CVs:"] + [self.read_cv(i) for i in range(NUM_CHANNELS)]
return [pots, buttons, sliders, normals, gates, cvs]
def display(stages):
kb = KBHit()
print("Press ESC or 'q' to exit")
channels = ["Channels"] + [f"Channel {c}" for c in range(NUM_CHANNELS)]
while True:
if kb.kbhit():
c = kb.getch()
if ord(c) == 27 or c == "q": # ESC
break
state = [channels] + stages.get_state()
output = ["\t".join(data) for data in state]
for line in output:
# move up cursor and delete whole line
sys.stdout.write("\x1b[1A\x1b[2K")
for line in output:
sys.stdout.write(line + "\n") # reprint the lines
if __name__ == "__main__":
if len(sys.argv) > 1:
port = sys.argv[1]
else:
print("Enter port to connect on:")
port = input()
try:
stages = Stages(port)
except Exception as e:
print(f"Unable to connect: {e}")
exit()
print(f"Attached to serial port {port}...")
print("Stages:")
while True:
print("What would you like to do?")
print("(c): Calibrate both ")
print("(a): Calibrate only the ADC")
print("(d): Calibrate only the DAC")
print("(g): Generate test signals")
print("(r): read the current state of the module")
print("(q): quit")
response = input(">>> ")
match response:
case "c" | "calibrate":
stages.calibrate()
case "a" | "adc":
stages.calibrate_adc()
case "d" | "dac":
stages.calibrate_dac()
case "g" | "generate":
stages.generate_test_signals()
case "r" | "read":
display(stages)
case "q" | "quit":
exit()