-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Analog Filter Designer: added new tool
- Loading branch information
1 parent
a2ed9a3
commit 4e2ef3b
Showing
16 changed files
with
1,423 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Analog Filter Designer</title> | ||
<!-- Bootstrap CSS --> | ||
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> | ||
|
||
<!-- Custom CSS (now in the /css folder) --> | ||
<link rel="stylesheet" href="css/style.css"> | ||
|
||
<script type="text/x-mathjax-config"> | ||
MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}}); | ||
</script> | ||
<script type="text/javascript" | ||
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"> | ||
</script> | ||
|
||
<style> | ||
.input-field:invalid { | ||
background-color: lightcoral; | ||
} | ||
</style> | ||
|
||
<!-- __COMMON_HEAD_START__ --> | ||
<style> | ||
html, body { | ||
height: 100%; | ||
overflow: scroll; | ||
} | ||
|
||
.footer { | ||
position: fixed; | ||
bottom: 0; | ||
left: 0; | ||
width: 100%; | ||
background-color: #333; | ||
padding: 10px 0; | ||
text-align: left; | ||
color: white; | ||
margin-top: auto; /* Push the footer to the bottom of the page */ | ||
} | ||
.footer i { | ||
margin: 0 10px; | ||
font-size: 18px; | ||
cursor: pointer; | ||
} | ||
.footer i:hover { | ||
color: #007bff; | ||
} | ||
|
||
.github-corner { | ||
position: fixed; | ||
top: 0; | ||
right: 0; | ||
} | ||
</style> | ||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet"> | ||
|
||
<a href="https://github.com/ChSotiriou/SimpleElectronicsTools" class="github-corner" aria-label="View source on GitHub"><svg width="80" height="80" viewBox="0 0 250 250" style="fill:#151513; color:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style><!-- __COMMON_HEAD_END__ --> | ||
</head> | ||
|
||
<body> | ||
|
||
<div class="container-fluid my-5"> | ||
<div class="row"> | ||
<div class="col-md-8 offset-md-2"> | ||
<h1 class="text-center mb-4">Analog Filter Designer</h1> | ||
|
||
<div class="input-group mb-3"> | ||
<span class="input-group-text bg-dark text-white" data-toggle="tooltip" | ||
title="Filter Type Selection">Type</span> | ||
<select class="form-control input-field" id="select-filter-type"> | ||
<option value="se_rc">Single Ended RC</option> | ||
<option value="diff_rc">Differential RC</option> | ||
</select> | ||
</div> | ||
|
||
<div class="input-group mb-3 div-type-se_rc div-type-diff_rc type-input-group"> | ||
<span class="input-group-text bg-dark text-white" data-toggle="tooltip" | ||
title="Max Simulation Frequency">$f_{max}$</span> | ||
<input required type="text" class="form-control mode-specific input-field type-se_rc type-diff_rc" | ||
id="max-freq" placeholder="(e.g. 100k, 10Meg)" value="1Meg"> | ||
|
||
<span class="input-group-text bg-dark text-white" data-toggle="tooltip" | ||
title="Resistance R1 value">$R_1$</span> | ||
<input required type="text" class="form-control mode-specific input-field type-se_rc type-diff_rc" | ||
id="RC_R1" placeholder="(e.g. 100k, 1Meg)" value="1k"> | ||
|
||
<span class="input-group-text bg-dark text-white" data-toggle="tooltip" | ||
title="Capacitance C1 value">$C_1$</span> | ||
<input required type="text" class="form-control mode-specific input-field type-se_rc type-diff_rc" | ||
id="RC_C1" placeholder="(100n, 1u)" value="100n"> | ||
</div> | ||
|
||
<hr /> | ||
|
||
<div id="plot"> | ||
</div> | ||
|
||
<hr /> | ||
<!-- <div class="text-center w-50"> | ||
<img></img> | ||
</div> --> | ||
<!-- <hr /> --> | ||
|
||
<div class="input-group mb-3 h-20"> | ||
<textarea class="form-control" id="spice-input" readonly></textarea> | ||
</div> | ||
|
||
<button class="btn btn-primary" id="downloadRawData">Download RAW</button> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<!-- __COMMON_BODY_START__ --> | ||
<div style="height: 10%"></div> | ||
<footer class="footer"> | ||
<div class="container"> | ||
<div class="row justify-content-left"> | ||
<div class="col-auto"> | ||
<a href="/" class="text-white"><i class="fas fa-home"></i></a> | ||
</div> | ||
<div class="col-auto"> | ||
<a href="https://github.com/chsotiriou/simpleelectronicstools" class="text-white"><i class="fab fa-github"></i></a> | ||
</div> | ||
<div class="col-auto"> | ||
<a href="https://csotiriou.com" class="text-white"><i class="fas fa-globe"></i></a> | ||
</div> | ||
</div> | ||
</div> | ||
</footer> | ||
<!-- __COMMON_BODY_END__ --> | ||
|
||
<!-- Bootstrap JS (Popper and Bootstrap JS) --> | ||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script> | ||
|
||
<script src="https://cdn.plot.ly/plotly-2.35.2.min.js" charset="utf-8"></script> | ||
|
||
<!-- External JavaScript (now in the /js folder) --> | ||
<script src="js/ngrp.js"></script> | ||
<script src="js/ngspice.js"></script> | ||
<script src="js/models.js"></script> | ||
<script src="js/main.js"></script> | ||
|
||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
var sim_model = "" | ||
|
||
function plottly_xline(x, y_min = -1e10, y_max = 1e10) { | ||
return { | ||
type: 'line', | ||
x0: x, // X position where the vertical line starts | ||
x1: x, // X position where the vertical line ends | ||
y0: y_min, // Y position where the line starts | ||
y1: y_max, // Y position where the line ends | ||
line: { | ||
color: 'red', | ||
width: 1 | ||
} | ||
} | ||
} | ||
|
||
function plottly_yline(y, x_min = -1e10, x_max = 1e10) { | ||
return { | ||
type: 'line', | ||
y0: y, // X position where the vertical line starts | ||
y1: y, // X position where the vertical line ends | ||
x0: x_min, // Y position where the line starts | ||
x1: x_max, // Y position where the line ends | ||
line: { | ||
color: 'red', | ||
width: 1, | ||
} | ||
} | ||
} | ||
|
||
let rawData = '' | ||
|
||
function processSimulation() { | ||
runSpiceSim(sim_model).then(raw => { | ||
rawData = raw | ||
data = ngrp(raw) | ||
|
||
freq = data['data'][0]['v1'] | ||
vout_p = data['data'].filter(x => x.name.toLowerCase() == 'v(vout+)')[0] | ||
vout_n = data['data'].filter(x => x.name.toLowerCase() == 'v(vout-)')[0] | ||
|
||
y_data = vout_p['v1'] | ||
if (vout_n != undefined) y_data = y_data.map((x, i) => x - vout_n['v1'][i]) | ||
|
||
y_data = y_data.map(x => 10*Math.log10(x)) | ||
cutoff = freq[y_data.indexOf(y_data.reduce((c, v) => Math.abs(v - (-3)) < Math.abs(c - (-3)) ? v : c ))] | ||
|
||
Plotly.newPlot(document.getElementById('plot'), [{ | ||
x: freq, | ||
y: y_data | ||
}], { | ||
margin: { t: 0 }, | ||
yaxis: { | ||
title: "Attenuation (dB)", | ||
}, | ||
xaxis: { | ||
type: 'log', | ||
title: "Frequency (Hz)", | ||
}, | ||
shapes: [ | ||
plottly_xline(cutoff, y_min=Math.min(...y_data), y_max=0) | ||
] | ||
}, { | ||
responsive: true | ||
}); | ||
|
||
}) | ||
} | ||
|
||
function update() { | ||
sim_name = document.getElementById('select-filter-type').value | ||
|
||
Array.from(document.getElementsByClassName('type-input-group')).forEach(x => x.hidden = true) | ||
Array.from(document.getElementsByClassName(`div-type-${sim_name}`)).forEach(x => x.removeAttribute('hidden')) | ||
|
||
|
||
args_elem = Array.from(document.getElementsByClassName(`type-${sim_name}`)) | ||
if (!args_elem.every(x => x.validity.valid)) return | ||
|
||
args = args_elem.map(x => x.value) | ||
|
||
sim_model = createFormattedString(sim_models[sim_name], args) | ||
document.getElementById('spice-input').textContent = sim_model | ||
|
||
processSimulation() | ||
} | ||
|
||
Array.from(document.getElementsByClassName('input-field')).forEach(x => x.addEventListener('change', update)) | ||
setTimeout(() => update(), 1000) | ||
|
||
document.getElementById('downloadRawData').addEventListener('click', x => downloadBlob(rawData, 'out.raw')) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
createFormattedString = function(template, values) { | ||
return template.replace(/{(\d+)}/g, (match, index) => { | ||
return typeof values[index] !== 'undefined' ? values[index] : match; | ||
}); | ||
} | ||
|
||
downloadBlob = function(data, fileName='out.raw', mimeType='application/octet-stream') { | ||
var blob, url; | ||
blob = new Blob([data], { | ||
type: mimeType | ||
}); | ||
url = window.URL.createObjectURL(blob); | ||
downloadURL(url, fileName); | ||
setTimeout(function() { | ||
return window.URL.revokeObjectURL(url); | ||
}, 1000); | ||
}; | ||
|
||
downloadURL = function(data, fileName) { | ||
var a; | ||
a = document.createElement('a'); | ||
a.href = data; | ||
a.download = fileName; | ||
document.body.appendChild(a); | ||
a.style = 'display: none'; | ||
a.click(); | ||
a.remove(); | ||
}; | ||
|
||
|
||
const sim_command = `.ac dec 100 1 {0}` | ||
|
||
const sim_models = { | ||
'se_rc': `Single Ended RC | ||
R1 Vin Vout+ {1} | ||
C1 Vout+ 0 {2} | ||
VCC Vin 0 AC 1. | ||
${sim_command} | ||
.save V(vout+) | ||
.end`, | ||
|
||
'diff_rc': `Differential RC | ||
R1 Vin Vout+ {1} | ||
R2 0 Vout- {1} | ||
C1 Vout+ Vout- {2} | ||
VCC Vin 0 AC 1. | ||
${sim_command} | ||
.save V(Vout+, Vout-) | ||
.end`, | ||
|
||
} | ||
|
||
const spiceinit = ` | ||
set filetype=ascii | ||
` |
Oops, something went wrong.