Add new measurement recording infrastructure
This commit is contained in:
parent
b8812245ec
commit
c75c48e53c
5 changed files with 259 additions and 198 deletions
|
|
@ -21,16 +21,12 @@ svd_load upstream/stm32square/svd/STM32G474.svd
|
|||
|
||||
break debug_plot_hook
|
||||
commands
|
||||
dump binary memory /tmp/adc1_readings.bin adc1_readings adc1_readings+(sizeof(adc1_readings)/sizeof(*adc1_readings))
|
||||
dump binary memory /tmp/adc1_variance.bin adc1_variance adc1_variance+(sizeof(adc1_readings)/sizeof(*adc1_readings))
|
||||
dump binary memory /tmp/adc2_readings.bin adc2_readings adc2_readings+(sizeof(adc1_readings)/sizeof(*adc1_readings))
|
||||
dump binary memory /tmp/adc2_variance.bin adc2_variance adc2_variance+(sizeof(adc1_readings)/sizeof(*adc1_readings))
|
||||
dump binary memory /tmp/adc_stats.bin &host_data &host_data+1
|
||||
restore /tmp/dbg_settings.bin binary dbg_settings
|
||||
p/x dbg_settings
|
||||
cont
|
||||
end
|
||||
|
||||
dump binary memory /tmp/dbg_settings.bin &dbg_settings &dbg_settings+1
|
||||
|
||||
load
|
||||
dump binary memory /tmp/dbg_settings.bin &dbg_settings &dbg_settings+1
|
||||
cont
|
||||
|
|
|
|||
|
|
@ -22,15 +22,14 @@ dbg_settings = None
|
|||
def index():
|
||||
return render_template('index.html')
|
||||
|
||||
def watch_adc_graphs(sock):
|
||||
def watch_adc_graphs(sock, stat_path='/tmp/adc_stats.bin'):
|
||||
stat_path = Path(stat_path)
|
||||
|
||||
def handler():
|
||||
Path('/tmp/adc1_readings.bin').touch()
|
||||
Path('/tmp/adc2_readings.bin').touch()
|
||||
Path('/tmp/adc1_variance.bin').touch()
|
||||
Path('/tmp/adc2_variance.bin').touch()
|
||||
stat_path.touch()
|
||||
|
||||
in_handle = inotify.adapters.Inotify()
|
||||
in_handle.add_watch('/tmp/adc2_variance.bin', mask=inotify.constants.IN_CLOSE_WRITE)
|
||||
in_handle.add_watch(str(stat_path), mask=inotify.constants.IN_CLOSE_WRITE)
|
||||
for event in in_handle.event_gen(yield_nones=False):
|
||||
if dbg_settings is None: # not yet initialized from UI
|
||||
print('ignoring update')
|
||||
|
|
@ -40,16 +39,43 @@ def watch_adc_graphs(sock):
|
|||
oversampling = int(dbg_settings['oversampling']);
|
||||
scale = 3.3 / (2**12) / oversampling;
|
||||
|
||||
def read_data(fn, scale):
|
||||
data = np.frombuffer(Path(fn).read_bytes(), dtype=np.uint32)
|
||||
data = data[::-1] # restore causality ;)
|
||||
data = data * scale
|
||||
return data.tolist()
|
||||
|
||||
sock.emit('graph_update', {'adc1': read_data('/tmp/adc1_readings.bin', scale),
|
||||
'var1': read_data('/tmp/adc1_variance.bin', scale**2/oversampling),
|
||||
'adc2': read_data('/tmp/adc2_readings.bin', scale),
|
||||
'var2': read_data('/tmp/adc2_variance.bin', scale**2/oversampling)})
|
||||
data = np.frombuffer(stat_path.read_bytes(), dtype=np.uint32)
|
||||
# cast to python ints for arbitrary precision arithmetic
|
||||
mcu_serial = int(data[0]) | (int(data[1])<<32) | (int(data[2])<<64);
|
||||
mcu_serial = f'{mcu_serial:024x}'
|
||||
|
||||
chip_type = {
|
||||
'203632423631500f003f0034': 'pi3hdx12211',
|
||||
'b': 'tdp0604',
|
||||
}.get(mcu_serial, 'unknown')
|
||||
|
||||
data = data[3:].astype(float).reshape((7, 4, -1))
|
||||
data[:,:,:] = data[:,:,::-1] # restore causality ;)
|
||||
|
||||
# Scale mean data
|
||||
data[:,0,:] *= scale
|
||||
data[:,2,:] *= scale
|
||||
|
||||
# Scale variance data
|
||||
data[:,1,:] *= scale**2/oversampling
|
||||
data[:,3,:] *= scale**2/oversampling
|
||||
|
||||
sock.emit('graph_update', {
|
||||
'mcu_serial': mcu_serial,
|
||||
'chip_type': chip_type,
|
||||
'data': {key: {
|
||||
'adc1': data[idx][0].tolist(),
|
||||
'var1': data[idx][1].tolist(),
|
||||
'adc2': data[idx][2].tolist(),
|
||||
'var2': data[idx][3].tolist(),
|
||||
} for idx, key in enumerate([
|
||||
'cal',
|
||||
'open_fwd',
|
||||
'open_flip',
|
||||
'load_fwd',
|
||||
'load_flip',
|
||||
'short_fwd',
|
||||
'short_flip'])}})
|
||||
|
||||
adc_thr = threading.Thread(target=handler, daemon=True)
|
||||
adc_thr.start()
|
||||
|
|
@ -62,11 +88,7 @@ def handle(data):
|
|||
else:
|
||||
dbg_settings.update(data)
|
||||
|
||||
out = 0
|
||||
for i, key in enumerate(['mesh_flip_n', 'mesh_flip', 'rf_term', 'rf_term_short']):
|
||||
if dbg_settings[key]:
|
||||
out |= 1<<i
|
||||
out |= (int(dbg_settings['sampling_phase_var']) & 0xff) << 4
|
||||
out = (int(dbg_settings['sampling_phase_var']) & 0xff) << 4
|
||||
out |= (int(dbg_settings['sampling_width']) & 0xff) << 12
|
||||
out |= (int(dbg_settings['stimulus_offset']) & 0xff) << 20
|
||||
out1 = (int(dbg_settings['oversampling']) & 0x1ff)
|
||||
|
|
|
|||
108
fw/src/main.c
108
fw/src/main.c
|
|
@ -11,10 +11,30 @@ int sampling_phase = 0;
|
|||
int adc_backoff = 60;
|
||||
uint16_t adc1_raw[512];
|
||||
uint16_t adc2_raw[COUNT_OF(adc1_raw)];
|
||||
uint32_t adc1_readings[1024];
|
||||
uint32_t adc2_readings[COUNT_OF(adc1_readings)];
|
||||
uint32_t adc1_variance[COUNT_OF(adc1_readings)];
|
||||
uint32_t adc2_variance[COUNT_OF(adc1_readings)];
|
||||
|
||||
#define ADC_DELAY_WINDOW_SIZE 768
|
||||
struct adc_stat_buffer {
|
||||
uint32_t adc1_mean[ADC_DELAY_WINDOW_SIZE];
|
||||
uint32_t adc1_var[ADC_DELAY_WINDOW_SIZE];
|
||||
uint32_t adc2_mean[ADC_DELAY_WINDOW_SIZE];
|
||||
uint32_t adc2_var[ADC_DELAY_WINDOW_SIZE];
|
||||
};
|
||||
|
||||
enum {
|
||||
MEAS_PB_CAL = 0,
|
||||
MEAS_PB_OPEN_FWD = 1,
|
||||
MEAS_PB_OPEN_FLIP = 2,
|
||||
MEAS_PB_LOAD_FWD = 3,
|
||||
MEAS_PB_LOAD_FLIP = 4,
|
||||
MEAS_PB_SHORT_FWD = 5,
|
||||
MEAS_PB_SHORT_FLIP = 6,
|
||||
_MEAS_PB_COUNT = 7
|
||||
} meas_pb_now = 0;
|
||||
|
||||
struct {
|
||||
uint32_t mcu_serial[3];
|
||||
struct adc_stat_buffer adc_stats[_MEAS_PB_COUNT];
|
||||
} host_data;
|
||||
|
||||
/* Bootup values. Will be overwritten with defaults from web interface HTML on launch. */
|
||||
const int default_sampling_phase_var = 2;
|
||||
|
|
@ -36,32 +56,56 @@ enum dbg_settings_mask {
|
|||
volatile uint32_t dbg_settings[2] = {
|
||||
(default_sampling_phase_var<<4) |
|
||||
(default_sampling_width<<12) |
|
||||
(default_stim_offset<<20) |
|
||||
DBG_MESH_FLIP_N,
|
||||
(default_stim_offset<<20),
|
||||
(default_oversampling<<0)};
|
||||
|
||||
void debug_plot_hook(void);
|
||||
void debug_plot_hook(void){
|
||||
if (dbg_settings[0] & DBG_MESH_FLIP) {
|
||||
void meas_pb_config();
|
||||
void meas_pb_config() {
|
||||
struct flags {
|
||||
bool flip,
|
||||
flip_n,
|
||||
term,
|
||||
term_short;
|
||||
};
|
||||
struct flags config[_MEAS_PB_COUNT] = {
|
||||
[MEAS_PB_CAL] = {.flip=0, .flip_n=0, .term=0, .term_short=0},
|
||||
[MEAS_PB_OPEN_FWD] = {.flip=0, .flip_n=1, .term=0, .term_short=0},
|
||||
[MEAS_PB_OPEN_FLIP] = {.flip=1, .flip_n=0, .term=0, .term_short=0},
|
||||
[MEAS_PB_LOAD_FWD] = {.flip=0, .flip_n=1, .term=1, .term_short=0},
|
||||
[MEAS_PB_LOAD_FLIP] = {.flip=1, .flip_n=0, .term=1, .term_short=0},
|
||||
[MEAS_PB_SHORT_FWD] = {.flip=0, .flip_n=1, .term=1, .term_short=1},
|
||||
[MEAS_PB_SHORT_FLIP] = {.flip=1, .flip_n=0, .term=1, .term_short=1},
|
||||
};
|
||||
|
||||
struct flags now = config[meas_pb_now];
|
||||
|
||||
if (now.flip) {
|
||||
GPIOC->BSRR = 1<<4;
|
||||
} else {
|
||||
GPIOC->BRR = 1<<4;
|
||||
}
|
||||
if (dbg_settings[0] & DBG_MESH_FLIP_N) {
|
||||
|
||||
if (now.flip_n) {
|
||||
GPIOB->BSRR = 1<<1;
|
||||
} else {
|
||||
GPIOB->BRR = 1<<1;
|
||||
}
|
||||
if (dbg_settings[0] & DBG_RF_TERM) {
|
||||
|
||||
if (now.term) {
|
||||
GPIOC->BSRR = 1<<14;
|
||||
} else {
|
||||
GPIOC->BRR = 1<<14;
|
||||
}
|
||||
if (dbg_settings[0] & DBG_RF_TERM_SHORT) {
|
||||
|
||||
if (now.term_short) {
|
||||
GPIOC->BSRR = 1<<15;
|
||||
} else {
|
||||
GPIOC->BRR = 1<<15;
|
||||
}
|
||||
}
|
||||
|
||||
void debug_plot_hook(void);
|
||||
void debug_plot_hook(void){
|
||||
sampling_phase_var = (dbg_settings[0]>>4) & 0xff;
|
||||
sampling_width = (dbg_settings[0]>>12) & 0xff;
|
||||
stim_offset = (dbg_settings[0]>>20) & 0xff;
|
||||
|
|
@ -232,6 +276,11 @@ int main(void) {
|
|||
GPIOC->BRR = (1<<4) | (1<<7) | (1<<14) | (1<<15); /* Clear all outputs on this bank */
|
||||
GPIOC->BSRR = 0xf;
|
||||
|
||||
const uint32_t *mcu_uid_reg = (const uint32_t *)UID_BASE;
|
||||
host_data.mcu_serial[0] = mcu_uid_reg[0];
|
||||
host_data.mcu_serial[1] = mcu_uid_reg[1];
|
||||
host_data.mcu_serial[2] = mcu_uid_reg[2];
|
||||
|
||||
/* GPIOD:
|
||||
* 2 - SFP5
|
||||
*
|
||||
|
|
@ -335,7 +384,7 @@ int main(void) {
|
|||
HRTIM1->sTimerxRegs[1].TIMxCR = HRTIM_TIMCR_MSTU;
|
||||
HRTIM1->sTimerxRegs[1].PERxR = HRTIM1->sMasterRegs.MPER;
|
||||
HRTIM1->sTimerxRegs[1].RSTxR = HRTIM_RSTR_MSTPER;
|
||||
int sampling_phase_var = (dbg_settings[0]>>4) & 0x3f;
|
||||
//int sampling_phase_var = (dbg_settings[0]>>4) & 0x3f;
|
||||
//HRTIM1->sTimerxRegs[1].CMP3xR = (global_sampling_offset + sampling_phase_var) * 0x20;
|
||||
//HRTIM1->sTimerxRegs[1].CMP4xR = (global_sampling_offset + sampling_phase_var) * 0x20;
|
||||
|
||||
|
|
@ -479,7 +528,7 @@ void DMA1_Channel1_IRQHandler(void) {
|
|||
* width anyway. */
|
||||
int mean1 = 0, sqmean1 = 0;
|
||||
int mean2 = 0, sqmean2 = 0;
|
||||
for (size_t i=2; i<oversampling+2; i++) {
|
||||
for (ssize_t i=2; i<oversampling+2; i++) {
|
||||
int entry = adc1_raw[i];
|
||||
mean1 += entry;
|
||||
sqmean1 += entry*entry;
|
||||
|
|
@ -488,22 +537,27 @@ void DMA1_Channel1_IRQHandler(void) {
|
|||
mean2 += entry;
|
||||
sqmean2 += entry*entry;
|
||||
}
|
||||
adc1_readings[sampling_phase] = mean1;
|
||||
adc1_variance[sampling_phase] = sqmean1*oversampling - mean1*mean1;
|
||||
adc2_readings[sampling_phase] = mean2;
|
||||
adc2_variance[sampling_phase] = sqmean2*oversampling - mean2*mean2;
|
||||
host_data.adc_stats[meas_pb_now].adc1_mean[sampling_phase] = mean1;
|
||||
host_data.adc_stats[meas_pb_now].adc1_var[sampling_phase] = sqmean1*oversampling - mean1*mean1;
|
||||
host_data.adc_stats[meas_pb_now].adc2_mean[sampling_phase] = mean2;
|
||||
host_data.adc_stats[meas_pb_now].adc2_var[sampling_phase] = sqmean2*oversampling - mean2*mean2;
|
||||
|
||||
sampling_phase ++;
|
||||
if (sampling_phase == COUNT_OF(adc1_readings)) {
|
||||
if (sampling_phase == ADC_DELAY_WINDOW_SIZE) {
|
||||
sampling_phase = 0;
|
||||
GPIOC->BRR = 1<<2;
|
||||
debug_plot_hook();
|
||||
GPIOC->BSRR = 1<<2;
|
||||
for (size_t i=0; i<COUNT_OF(adc1_readings); i++) {
|
||||
adc1_readings[i] = 0;
|
||||
}
|
||||
for (size_t i=0; i<COUNT_OF(adc2_readings); i++) {
|
||||
adc2_readings[i] = 0;
|
||||
|
||||
if (meas_pb_now < _MEAS_PB_COUNT) {
|
||||
meas_pb_now ++;
|
||||
meas_pb_config();
|
||||
|
||||
} else {
|
||||
GPIOC->BRR = 1<<2;
|
||||
debug_plot_hook();
|
||||
GPIOC->BSRR = 1<<2;
|
||||
|
||||
meas_pb_now = 0;
|
||||
|
||||
memset(&host_data.adc_stats, 0, sizeof(host_data.adc_stats));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,31 +9,17 @@
|
|||
<script src="{{url_for('static', filename='plotly-2.35.2.min.js')}}" charset="utf-8"></script>
|
||||
<script src="{{url_for('static', filename='socket.io.min.js')}}" charset="utf-8"></script>
|
||||
<style>
|
||||
#plot_adc1, #plot_adc2 {
|
||||
width: 600px;
|
||||
height: 250px;
|
||||
#plot-grid {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
/* grid-template-rows: repeat(6, 600px); */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h4>Device settings</h4>
|
||||
<div>
|
||||
<label for="cb_dev_mesh_flip">
|
||||
<input type="checkbox" id="cb_dev_mesh_flip" data-dev-setting="mesh_flip"/>
|
||||
MESH_FLIP
|
||||
</label>
|
||||
<label for="cb_dev_mesh_flip_n">
|
||||
<input type="checkbox" id="cb_dev_mesh_flip_n" checked data-dev-setting="mesh_flip_n"/>
|
||||
MESH_FLIP_N
|
||||
</label>
|
||||
<label for="cb_dev_rf_term">
|
||||
<input type="checkbox" id="cb_dev_rf_term" data-dev-setting="rf_term"/>
|
||||
RF_TERM
|
||||
</label>
|
||||
<label for="cb_dev_rf_term_short">
|
||||
<input type="checkbox" id="cb_dev_rf_term_short" data-dev-setting="rf_term_short"/>
|
||||
RF_TERM_SHORT
|
||||
</label>
|
||||
<label for="sampling_phase_inp">
|
||||
Sampling phase <input type="number" id="sampling_phase_inp" min="0" max="180" step="1" value="6" data-dev-setting="sampling_phase_var"/>
|
||||
</label>
|
||||
|
|
@ -50,122 +36,84 @@
|
|||
|
||||
<h4>Download data</h4>
|
||||
<div class="download">
|
||||
<div>
|
||||
<label for="dl_meta_info">Meta info: <input type="text" id="dl_meta_info"/> <a id="download-button" href="#">Download</a>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="dl_meta_suffix_0" name="meta_suffix" value=""/>
|
||||
<label for="dl_meta_suffix_1"><none></label>
|
||||
<input type="radio" id="dl_meta_suffix_1" name="meta_suffix" value="_baseline1"/>
|
||||
<label for="dl_meta_suffix_1">baseline1</label>
|
||||
<input type="radio" id="dl_meta_suffix_2" name="meta_suffix" value="_short1"/>
|
||||
<label for="dl_meta_suffix_2">short1</label>
|
||||
<input type="radio" id="dl_meta_suffix_3" name="meta_suffix" value="_short2"/>
|
||||
<label for="dl_meta_suffix_3">short2</label>
|
||||
<input type="radio" id="dl_meta_suffix_4" name="meta_suffix" value="_short3"/>
|
||||
<label for="dl_meta_suffix_4">short3</label>
|
||||
<input type="radio" id="dl_meta_suffix_5" name="meta_suffix" value="_baseline2"/>
|
||||
<label for="dl_meta_suffix_5">baseline2</label>
|
||||
<input type="radio" id="dl_meta_suffix_6" name="meta_suffix" value="_probe1a"/>
|
||||
<label for="dl_meta_suffix_6">probe1a</label>
|
||||
<input type="radio" id="dl_meta_suffix_7" name="meta_suffix" value="_probe1b"/>
|
||||
<label for="dl_meta_suffix_7">probe1b</label>
|
||||
<input type="radio" id="dl_meta_suffix_8" name="meta_suffix" value="_probe2a"/>
|
||||
<label for="dl_meta_suffix_8">probe2a</label>
|
||||
<input type="radio" id="dl_meta_suffix_9" name="meta_suffix" value="_probe2b"/>
|
||||
<label for="dl_meta_suffix_9">probe2b</label>
|
||||
<input type="radio" id="dl_meta_suffix_10" name="meta_suffix" value="_probe3a"/>
|
||||
<label for="dl_meta_suffix_10">probe3a</label>
|
||||
<input type="radio" id="dl_meta_suffix_11" name="meta_suffix" value="_probe3b"/>
|
||||
<label for="dl_meta_suffix_11">probe3b</label>
|
||||
<input type="radio" id="dl_meta_suffix_12" name="meta_suffix" value="_baseline3"/>
|
||||
<label for="dl_meta_suffix_12">baseline3</label>
|
||||
<input type="radio" id="dl_meta_suffix_13" name="meta_suffix" value="_cut"/>
|
||||
<label for="dl_meta_suffix_13">cut</label>
|
||||
<input type="radio" id="dl_meta_suffix_14" name="meta_suffix" value="_baseline4"/>
|
||||
<label for="dl_meta_suffix_14">baseline4</label>
|
||||
</div>
|
||||
<form id="download_form">
|
||||
<div>
|
||||
<label for="dl_meta_info">Meta info: <input type="text" id="dl_meta_info"/></label>
|
||||
<label for="dl_meta_specimen">Specimen: <input type="text" id="dl_meta_specimen"/></label>
|
||||
<label for="dl_meta_mcu">MCU Serial: <input type="text" id="dl_meta_mcu" readonly/></label>
|
||||
<label for="dl_meta_chip">Driver IC: <input type="text" id="dl_meta_chip" readonly/></label>
|
||||
<input type="submit" value="Download"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<h4 id="adc1_heading">ADC 1</h4>
|
||||
<div id="plot_adc1"></div>
|
||||
<div class="measurement" id="meas_adc1_thr">
|
||||
<h5>Threshold</h5>
|
||||
<div id="plot-grid">
|
||||
<adc-plot adc-index="1" playbook-item="open_fwd"></adc-plot>
|
||||
<adc-plot adc-index="1" playbook-item="load_fwd"></adc-plot>
|
||||
<adc-plot adc-index="1" playbook-item="short_fwd"></adc-plot>
|
||||
|
||||
<label for="adc1_thr_v_spin">
|
||||
Voltage <input type="number" id="adc1_thr_v_spin" class="v_spin" min="-0.3" max="3.6" step="0.01"/> V
|
||||
</label>
|
||||
<adc-plot adc-index="2" playbook-item="open_fwd"></adc-plot>
|
||||
<adc-plot adc-index="2" playbook-item="load_fwd"></adc-plot>
|
||||
<adc-plot adc-index="2" playbook-item="short_fwd"></adc-plot>
|
||||
|
||||
<label for="adc1_thr_v_spin">
|
||||
Anchor time: <input type="number" id="adc1_thr_v_spin" class="t_spin" min="0" max="500" step="1"/> ns
|
||||
</label>
|
||||
<adc-plot adc-index="1" playbook-item="open_flip"></adc-plot>
|
||||
<adc-plot adc-index="1" playbook-item="load_flip"></adc-plot>
|
||||
<adc-plot adc-index="1" playbook-item="short_flip"></adc-plot>
|
||||
|
||||
<div class="stats" id="table_adc1">
|
||||
<table>
|
||||
<tr><td></td><th>10</th><th>100</th><th>1000</th></tr>
|
||||
<tr><th>Mean [ns]</th>
|
||||
<td class="mean_10"></td>
|
||||
<td class="mean_100"></td>
|
||||
<td class="mean_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Stdev [ps]</th>
|
||||
<td class="stdev_10"></td>
|
||||
<td class="stdev_100"></td>
|
||||
<td class="stdev_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Min [ns]</th>
|
||||
<td class="min_10"></td>
|
||||
<td class="min_100"></td>
|
||||
<td class="min_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Max [ns]</th>
|
||||
<td class="max_10"></td>
|
||||
<td class="max_100"></td>
|
||||
<td class="max_1000"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<adc-plot adc-index="2" playbook-item="open_flip"></adc-plot>
|
||||
<adc-plot adc-index="2" playbook-item="load_flip"></adc-plot>
|
||||
<adc-plot adc-index="2" playbook-item="short_flip"></adc-plot>
|
||||
|
||||
<div></div>
|
||||
<adc-plot adc-index="1" playbook-item="cal"></adc-plot>
|
||||
<div></div>
|
||||
|
||||
<div></div>
|
||||
<adc-plot adc-index="2" playbook-item="cal"></adc-plot>
|
||||
<div></div>
|
||||
</div>
|
||||
|
||||
<h4 id="adc2_heading">ADC 2</h4>
|
||||
<div id="plot_adc2"></div>
|
||||
<div class="measurement" id="meas_adc2_thr">
|
||||
<h5>Threshold</h5>
|
||||
<template id="adc_plot_template">
|
||||
<h4 id="heading"></h4>
|
||||
<div id="plot"></div>
|
||||
<div class="measurement" id="measurement">
|
||||
<h5>Threshold</h5>
|
||||
|
||||
<label for="adc2_thr_v_spin">
|
||||
Voltage <input type="number" id="adc2_thr_v_spin" class="v_spin" min="-0.3" max="3.6" step="0.01"/> V
|
||||
</label>
|
||||
<label for="thr_v_spin">
|
||||
Voltage <input type="number" id="thr_v_spin" class="v_spin" min="-0.3" max="3.6" step="0.01"/> V
|
||||
</label>
|
||||
|
||||
<label for="adc2_thr_v_spin">
|
||||
Anchor time: <input type="number" id="adc2_thr_v_spin" class="t_spin" min="0" max="500" step="1"/> ns
|
||||
</label>
|
||||
<label for="thr_t_spin">
|
||||
Anchor time: <input type="number" id="thr_t_spin" class="t_spin" min="0" max="500" step="1"/> ns
|
||||
</label>
|
||||
|
||||
<div class="stats" id="table_adc2">
|
||||
<table>
|
||||
<tr><td></td><th>10</th><th>100</th><th>1000</th></tr>
|
||||
<tr><th>Mean [ns]</th>
|
||||
<td class="mean_10"></td>
|
||||
<td class="mean_100"></td>
|
||||
<td class="mean_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Stdev [ps]</th>
|
||||
<td class="stdev_10"></td>
|
||||
<td class="stdev_100"></td>
|
||||
<td class="stdev_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Min [ns]</th>
|
||||
<td class="min_10"></td>
|
||||
<td class="min_100"></td>
|
||||
<td class="min_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Max [ns]</th>
|
||||
<td class="max_10"></td>
|
||||
<td class="max_100"></td>
|
||||
<td class="max_1000"></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="stats" id="table">
|
||||
<table>
|
||||
<tr><td></td><th>10</th><th>100</th><th>1000</th></tr>
|
||||
<tr><th>Mean [ns]</th>
|
||||
<td class="mean_10"></td>
|
||||
<td class="mean_100"></td>
|
||||
<td class="mean_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Stdev [ps]</th>
|
||||
<td class="stdev_10"></td>
|
||||
<td class="stdev_100"></td>
|
||||
<td class="stdev_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Min [ns]</th>
|
||||
<td class="min_10"></td>
|
||||
<td class="min_100"></td>
|
||||
<td class="min_1000"></td>
|
||||
</tr>
|
||||
<tr><th>Max [ns]</th>
|
||||
<td class="max_10"></td>
|
||||
<td class="max_100"></td>
|
||||
<td class="max_1000"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
class ThresholdStats {
|
||||
|
|
@ -243,8 +191,8 @@
|
|||
class DataPlot {
|
||||
constructor(plot_div, table_div, meas_div, heading_div) {
|
||||
this.lock = false;
|
||||
this.heading = document.querySelector(heading_div);
|
||||
this.div = document.querySelector(plot_div);
|
||||
this.heading = heading_div;
|
||||
this.div = plot_div;
|
||||
this.layout_settings = {
|
||||
margin: {t: 20, l: 60, r: 20, b: 40},
|
||||
hovermode: 'closest',
|
||||
|
|
@ -256,7 +204,7 @@
|
|||
{'x': [], 'y': [], 'type': 'scatter'},
|
||||
{'x': [], 'y': [], 'type': 'scatter'}
|
||||
], this.layout_settings);
|
||||
this.stats = new ThresholdStats(document.querySelector(table_div), document.querySelector(meas_div));
|
||||
this.stats = new ThresholdStats(table_div, meas_div);
|
||||
|
||||
this.div.on('plotly_click', (evt) => {
|
||||
this.stats.set_thr(evt.points[0].y, evt.points[0].x);
|
||||
|
|
@ -314,36 +262,77 @@
|
|||
}
|
||||
};
|
||||
|
||||
adc1_plot = new DataPlot('#plot_adc1', '#table_adc1', '#meas_adc1_thr', '#adc1_heading');
|
||||
adc2_plot = new DataPlot('#plot_adc2', '#table_adc2', '#meas_adc2_thr', '#adc2_heading');
|
||||
adc_update_listeners = {};
|
||||
|
||||
customElements.define("adc-plot",
|
||||
class extends HTMLElement {
|
||||
constructor () {
|
||||
super();
|
||||
let template = document.getElementById("adc_plot_template");
|
||||
const shadowRoot = this.attachShadow({"mode": "open"});
|
||||
shadowRoot.appendChild(template.content.cloneNode(true));
|
||||
|
||||
let heading = shadowRoot.getElementById("heading");
|
||||
let adc_index = this.getAttribute("adc-index");
|
||||
let playbook_item = this.getAttribute("playbook-item");
|
||||
heading.innerText = `ADC ${adc_index} ${playbook_item}`;
|
||||
|
||||
const plot = new DataPlot(
|
||||
shadowRoot.getElementById("plot"),
|
||||
shadowRoot.getElementById("table"),
|
||||
shadowRoot.getElementById("measurement"),
|
||||
heading);
|
||||
this.plot = plot;
|
||||
|
||||
adc_update_listeners[`${playbook_item}_${adc_index}`] = (mean, variance) => {
|
||||
plot.update_plot(mean, variance);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('#download_form').addEventListener('submit', (evt) => {
|
||||
evt.preventDefault();
|
||||
|
||||
document.querySelector('#download-button').addEventListener('click', (evt) => {
|
||||
let a = document.createElement('a');
|
||||
let spec_inp = document.querySelector('#dl_meta_specimen');
|
||||
const meta = document.querySelector('#dl_meta_info').value;
|
||||
const suffix = document.querySelector('input[name="meta_suffix"]:checked').value;
|
||||
adc1_plot.lock = true;
|
||||
adc2_plot.lock = true;
|
||||
const specimen = spec_inp.value;
|
||||
const mcu = document.querySelector('#dl_meta_mcu').value;
|
||||
const chip = document.querySelector('#dl_meta_chip').value;
|
||||
const timestamp = (new Date).toISOString();
|
||||
spec_inp.value = "";
|
||||
|
||||
a.setAttribute('href', 'data:application/json;charset=utf-8,' + JSON.stringify({
|
||||
meta: meta + suffix,
|
||||
meta: `${meta}_${mcu}_${chip}_${specimen}`,
|
||||
info: {
|
||||
meta: meta,
|
||||
specimen: specimen,
|
||||
mcu: mcu,
|
||||
chip: chip,
|
||||
timestamp: timestamp,
|
||||
},
|
||||
settings: dbg_settings(),
|
||||
adc1: adc1_plot.adc_data,
|
||||
var1: adc1_plot.var_data,
|
||||
adc2: adc2_plot.adc_data,
|
||||
var2: adc2_plot.var_data,
|
||||
data: last_data,
|
||||
}));
|
||||
adc1_plot.lock = false;
|
||||
adc2_plot.lock = false;
|
||||
a.setAttribute('download', 'adc-capture-' + (new Date).toISOString() + '.json');
|
||||
|
||||
a.setAttribute('download', 'multisample-' + timestamp + '.json');
|
||||
a.style.display = 'none';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
});
|
||||
|
||||
let last_data = null;
|
||||
const socket = io();
|
||||
socket.on('graph_update', (arg, callback) => {
|
||||
adc1_plot.update_plot(arg['adc1'], arg['var1']);
|
||||
adc2_plot.update_plot(arg['adc2'], arg['var2']);
|
||||
last_data = structuredClone(arg['data']);
|
||||
document.getElementById('dl_meta_mcu').value = arg['mcu_serial'];
|
||||
document.getElementById('dl_meta_chip').value = arg['chip_type'];
|
||||
for (const [playbook_item, value] of Object.entries(arg['data'])) {
|
||||
nop = (a, b) => null;
|
||||
(adc_update_listeners[`${playbook_item}_1`] || nop)(value['adc1'], value['var1']);
|
||||
(adc_update_listeners[`${playbook_item}_2`] || nop)(value['adc2'], value['var2']);
|
||||
}
|
||||
});
|
||||
|
||||
function dbg_settings() {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5ff70236318a1e48bcc89a6174b243c7443ae1c1
|
||||
Subproject commit e2f4fa6e7975baa3dc4256c4d64c81a1c191675b
|
||||
Loading…
Add table
Add a link
Reference in a new issue