From 4b37390cfd041c0c29a76d62dc2c8e0e1146b5c5 Mon Sep 17 00:00:00 2001 From: Christodoulos Sotiriou Date: Sun, 5 Jan 2025 17:25:16 +0000 Subject: [PATCH] filter-designer added rc hpf and lrc --- .../assets/filters.drawio | 120 ++- .../analog-filter-designer/assets/lrc_lpf.svg | 4 + .../assets/se_rc_hpf.svg | 4 + .../general/analog-filter-designer/index.html | 46 +- .../analog-filter-designer/js/complex.min.js | 26 + .../general/analog-filter-designer/js/main.js | 41 +- .../analog-filter-designer/js/models.js | 30 +- .../general/analog-filter-designer/js/ngrp.js | 12 +- .../general/analog-filter-designer/test.html | 941 ------------------ 9 files changed, 223 insertions(+), 1001 deletions(-) create mode 100644 dist/tools/general/analog-filter-designer/assets/lrc_lpf.svg create mode 100644 dist/tools/general/analog-filter-designer/assets/se_rc_hpf.svg create mode 100644 dist/tools/general/analog-filter-designer/js/complex.min.js delete mode 100644 dist/tools/general/analog-filter-designer/test.html diff --git a/dist/tools/general/analog-filter-designer/assets/filters.drawio b/dist/tools/general/analog-filter-designer/assets/filters.drawio index fea6dca..d3c8962 100644 --- a/dist/tools/general/analog-filter-designer/assets/filters.drawio +++ b/dist/tools/general/analog-filter-designer/assets/filters.drawio @@ -1,16 +1,16 @@ - + - + - + - + - + @@ -19,65 +19,65 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -86,70 +86,128 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dist/tools/general/analog-filter-designer/assets/lrc_lpf.svg b/dist/tools/general/analog-filter-designer/assets/lrc_lpf.svg new file mode 100644 index 0000000..02b7bfb --- /dev/null +++ b/dist/tools/general/analog-filter-designer/assets/lrc_lpf.svg @@ -0,0 +1,4 @@ + + + +
\ No newline at end of file diff --git a/dist/tools/general/analog-filter-designer/assets/se_rc_hpf.svg b/dist/tools/general/analog-filter-designer/assets/se_rc_hpf.svg new file mode 100644 index 0000000..1ba305d --- /dev/null +++ b/dist/tools/general/analog-filter-designer/assets/se_rc_hpf.svg @@ -0,0 +1,4 @@ + + + +
\ No newline at end of file diff --git a/dist/tools/general/analog-filter-designer/index.html b/dist/tools/general/analog-filter-designer/index.html index f4bbed7..334925d 100644 --- a/dist/tools/general/analog-filter-designer/index.html +++ b/dist/tools/general/analog-filter-designer/index.html @@ -74,38 +74,63 @@

Analog Filter Designer

-
+
Type -
- -
$f_{max}$ - +
+ + + +
$R_1$ - $C_1$ -
+ +
-
+
$$\omega_c = \frac{1}{R_1C_1}$$
+ +
@@ -154,6 +179,7 @@

Analog Filter Designer

+ @@ -161,4 +187,4 @@

Analog Filter Designer

- \ No newline at end of file + diff --git a/dist/tools/general/analog-filter-designer/js/complex.min.js b/dist/tools/general/analog-filter-designer/js/complex.min.js new file mode 100644 index 0000000..722aaf7 --- /dev/null +++ b/dist/tools/general/analog-filter-designer/js/complex.min.js @@ -0,0 +1,26 @@ +/* +Complex.js v2.4.2 11/5/2024 +https://raw.org/article/complex-numbers-in-javascript/ + +Copyright (c) 2024, Robert Eisele (https://raw.org/) +Licensed under the MIT license. +*/ +'use strict';(function(r){function l(a,b){if(void 0===a||null===a)f.re=f.im=0;else if(void 0!==b)f.re=a,f.im=b;else switch(typeof a){case "object":if("im"in a&&"re"in a)f.re=a.re,f.im=a.im;else if("abs"in a&&"arg"in a){if(!isFinite(a.abs)&&isFinite(a.arg))return c.INFINITY;f.re=a.abs*Math.cos(a.arg);f.im=a.abs*Math.sin(a.arg)}else if("r"in a&&"phi"in a){if(!isFinite(a.r)&&isFinite(a.phi))return c.INFINITY;f.re=a.r*Math.cos(a.phi);f.im=a.r*Math.sin(a.phi)}else 2===a.length?(f.re=a[0],f.im=a[1]):m(); +break;case "string":f.im=f.re=0;a=a.replace(/_/g,"").match(/\d+\.?\d*e[+-]?\d+|\d+\.?\d*|\.\d+|./g);b=1;let d=0;null===a&&m();for(let e=0;ea)return Math.sqrt(a*a+b*b);b/=a;return a*Math.sqrt(1+b*b)}function p(a,b){const d=Math.abs(a),e=Math.abs(b);if(0===a)return Math.log(e);if(0===b)return Math.log(d);if(3E3>d&&3E3>e)return.5*Math.log(a*a+b*b);a*=.5;b*=.5;return.5*Math.log(a*a+b*b)+Math.LN2}function c(a,b){if(!(this instanceof c))return new c(a,b);a=l(a, +b);this.re=a.re;this.im=a.im}const h=Math.cosh||function(a){return 1E-9>Math.abs(a)?1-a:.5*(Math.exp(a)+Math.exp(-a))},k=Math.sinh||function(a){return 1E-9>Math.abs(a)?a:.5*(Math.exp(a)-Math.exp(-a))},f={re:0,im:0};c.prototype={re:0,im:0,sign:function(){const a=n(this.re,this.im);return new c(this.re/a,this.im/a)},add:function(a,b){a=l(a,b);b=this.isInfinite();const d=!(isFinite(a.re)&&isFinite(a.im));return b||d?b&&d?c.NAN:c.INFINITY:new c(this.re+a.re,this.im+a.im)},sub:function(a,b){a=l(a,b);b= +this.isInfinite();const d=!(isFinite(a.re)&&isFinite(a.im));return b||d?b&&d?c.NAN:c.INFINITY:new c(this.re-a.re,this.im-a.im)},mul:function(a,b){a=l(a,b);b=this.isInfinite();const d=!(isFinite(a.re)&&isFinite(a.im)),e=0===this.re&&0===this.im,g=0===a.re&&0===a.im;return b&&g||d&&e?c.NAN:b||d?c.INFINITY:0===a.im&&0===this.im?new c(this.re*a.re,0):new c(this.re*a.re-this.im*a.im,this.re*a.im+this.im*a.re)},div:function(a,b){a=l(a,b);b=this.isInfinite();const d=!(isFinite(a.re)&&isFinite(a.im)),e=0=== +this.re&&0===this.im,g=0===a.re&&0===a.im;if(e&&g||b&&d)return c.NAN;if(g||b)return c.INFINITY;if(e||d)return c.ZERO;if(0===a.im)return new c(this.re/a.re,this.im/a.re);if(Math.abs(a.re)b?-e:e):new c(e,0>b?-d:d)},exp:function(){const a=Math.exp(this.re);return 0===this.im?new c(a,0):new c(a*Math.cos(this.im),a*Math.sin(this.im))},expm1:function(){const a=this.re,b=this.im;var d=Math.expm1(a)*Math.cos(b);var e=Math.PI/4;-e>b||b>e?e=Math.cos(b)-1:(e=b*b,e*=e*(e*(e*(e*(e*(e*(e/20922789888E3-1/87178291200)+1/479001600)-1/3628800)+1/40320)-1/720)+1/24)-.5);return new c(d+e,Math.exp(a)*Math.sin(b))}, +log:function(){const a=this.re,b=this.im;return 0===b&&0=a.im){var b=a.re;a.re=-a.im;a.im=b}else b=a.im,a.im=-a.re,a.re=b;return a},atanh:function(){var a=this.re,b=this.im;const d=1b?(b=-b,d+="-"):d+="+",d+=" "):0>b&&(b=-b,d+="-");1!== +b&&(d+=b);return d+"i"},toVector:function(){return[this.re,this.im]},valueOf:function(){return 0===this.im?this.re:null},isNaN:function(){return isNaN(this.re)||isNaN(this.im)},isZero:function(){return 0===this.im&&0===this.re},isFinite:function(){return isFinite(this.re)&&isFinite(this.im)},isInfinite:function(){return!this.isFinite()}};c.ZERO=new c(0,0);c.ONE=new c(1,0);c.I=new c(0,1);c.PI=new c(Math.PI,0);c.E=new c(Math.E,0);c.INFINITY=new c(Infinity,Infinity);c.NAN=new c(NaN,NaN);c.EPSILON=1E-15; +"function"===typeof define&&define.amd?define([],function(){return c}):"object"===typeof exports?(Object.defineProperty(c,"__esModule",{value:!0}),c["default"]=c,c.Complex=c,module.exports=c):r.Complex=c})(this); diff --git a/dist/tools/general/analog-filter-designer/js/main.js b/dist/tools/general/analog-filter-designer/js/main.js index 7881471..eb4e6a6 100644 --- a/dist/tools/general/analog-filter-designer/js/main.js +++ b/dist/tools/general/analog-filter-designer/js/main.js @@ -35,30 +35,53 @@ function processSimulation() { rawData = raw data = ngrp(raw) - freq = data['data'][0]['v1'] + freq = data['data'][0]['value'].map(x => x.abs()) + 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]) + vout = vout_p['value'] + if (vout_n != undefined) vout = vout.map((x, i) => x.sub(vout_n['value'][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 ))] + amplitude = vout.map(x => 10*Math.log10(x.abs())) + phase = vout.map(x => 180 * x.arg() / Math.PI) + cutoff = freq[amplitude.indexOf(amplitude.reduce((c, v) => Math.abs(v - (-3)) < Math.abs(c - (-3)) ? v : c ))] Plotly.newPlot(document.getElementById('plot'), [{ x: freq, - y: y_data + y: amplitude + }, { + x: freq, + y: phase, + yaxis: 'y2', + line: { + dash: 'dot', + } }], { margin: { t: 0 }, + showlegend: false, yaxis: { - title: "Attenuation (dB)", + title: { + text: "Attenuation (dB)", + font: {color: '#1F77B4'} + }, + tickfont: {color: '#1F77B4'}, + }, + yaxis2: { + title: { + text: 'Phase (deg)', + font: {color: '#FF7F0E'} + }, + tickfont: {color: '#FF7F0E'}, + overlaying: 'y', + side: 'right' }, xaxis: { type: 'log', title: "Frequency (Hz)", }, shapes: [ - plottly_xline(cutoff, y_min=Math.min(...y_data), y_max=0) + plottly_xline(cutoff, y_min=Math.min(...amplitude), y_max=Math.max(...amplitude)) ] }, { responsive: true @@ -92,4 +115,4 @@ function update() { 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')) \ No newline at end of file +document.getElementById('downloadRawData').addEventListener('click', x => downloadBlob(rawData, 'out.raw')) diff --git a/dist/tools/general/analog-filter-designer/js/models.js b/dist/tools/general/analog-filter-designer/js/models.js index edc8d1b..145f75f 100644 --- a/dist/tools/general/analog-filter-designer/js/models.js +++ b/dist/tools/general/analog-filter-designer/js/models.js @@ -28,10 +28,11 @@ downloadURL = function(data, fileName) { }; -const sim_command = `.ac dec 100 1 {0}` +const sim_command = `.ac dec 500 1 {0}` const sim_models = { - 'se_rc': `Single Ended RC + // ---------------------------------------- + 'se_rc': `Single Ended RC LPF R1 Vin Vout+ {1} C1 Vout+ 0 {2} VCC Vin 0 AC 1. @@ -41,6 +42,18 @@ ${sim_command} .end`, + // ---------------------------------------- + 'se_rc_hpf': `Single Ended RC HPF +C1 Vin Vout+ {2} +R1 Vout+ 0 {1} +VCC Vin 0 AC 1. + +${sim_command} +.save V(vout+) + +.end`, + + // ---------------------------------------- 'diff_rc': `Differential RC R1 Vin Vout+ {1} @@ -54,8 +67,19 @@ ${sim_command} .end`, + // ---------------------------------------- + 'lrc_lpf': `LRC LPF 1 +L1 Vin 1 {1} +R1 1 Vout+ {2} +C1 Vout+ 0 {3} +VCC Vin 0 AC 1. + +${sim_command} +.save V(vout+) + +.end`, } const spiceinit = ` set filetype=ascii -` \ No newline at end of file +` diff --git a/dist/tools/general/analog-filter-designer/js/ngrp.js b/dist/tools/general/analog-filter-designer/js/ngrp.js index 81449a2..604e1fe 100644 --- a/dist/tools/general/analog-filter-designer/js/ngrp.js +++ b/dist/tools/general/analog-filter-designer/js/ngrp.js @@ -49,8 +49,7 @@ function ngrp(data) { out['data'].push({ 'name': varName, 'type': type, - 'v1': [], - 'v2': [], + 'value': [], }) } @@ -60,12 +59,11 @@ function ngrp(data) { for (let j = 0; j < out['varCount']; j++) { values = next().split("\t").slice(-1)[0].split(",") - v1 = parseFloat(values[0]) - v2 = parseFloat(values[1]) - out['data'][j]['v1'].push(v1) - out['data'][j]['v2'].push(v2) + re = parseFloat(values[0]) + im = parseFloat(values[1]) + out['data'][j]['value'].push(Complex(re, im)) } } return out -} \ No newline at end of file +} diff --git a/dist/tools/general/analog-filter-designer/test.html b/dist/tools/general/analog-filter-designer/test.html deleted file mode 100644 index 011caa3..0000000 --- a/dist/tools/general/analog-filter-designer/test.html +++ /dev/null @@ -1,941 +0,0 @@ - - - - - Document - - - -
- - - - - - \ No newline at end of file