summaryrefslogtreecommitdiff
path: root/plugins/ZamTube/wdfcircuits.h
blob: 726c0a7c996f358f87244ccd033c2c836ebce540 (plain)
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
#ifndef WDFCIRCUITS_H
#define WDFCIRCUITS_H
#include "glue.h"
#include "triode.h"

class TubeStageCircuit {
	/*Tube Preamp*/
public:
	Triode t;
	bool on;

	TubeStageCircuit() {
		Cia = 0.0;
		Cka = 0.0;
		Coa = 0.0;
		on = false;
	}
	TubeStageCircuit(Real C_Ci, Real C_Ck, Real C_Co, Real E_E250, Real R_E250, Real R_Rg, Real R_Ri, Real R_Rk, Real R_Ro, Real R_Vi, Real sampleRate, Triode& tube) {
		Cia = 0.0;
		Cka = 0.0;
		Coa = 0.0;
		on = false;
		updateRValues(C_Ci, C_Ck, C_Co, E_E250, R_E250, R_Rg, R_Ri, R_Rk, R_Ro, R_Vi, sampleRate, tube);
	}

	void updateRValues(Real C_Ci, Real C_Ck, Real C_Co, Real E_E250, Real R_E250, Real R_Rg, Real R_Ri, Real R_Rk, Real R_Ro, Real R_Vi, Real sampleRate, Triode& tube) {
		t = tube;
		Real ViR = R_Vi;
		CiR = 1.0 / (2.0*C_Ci*sampleRate);
		CkR = 1.0 / (2.0*C_Ck*sampleRate);
		CoR = 1.0 / (2.0*C_Co*sampleRate);
		Real RoR = R_Ro;
		Real RgR = R_Rg;
		Real RiR = R_Ri;
		Real RkR = R_Rk;
		Real E250R = R_E250;
		E250E = E_E250;
		Real S0_3R = (CiR + ViR);
		S0_3Gamma1 = CiR/(CiR + ViR);
		Assert(S0_3Gamma1 >= 0.0 && S0_3Gamma1 <= 1.0);
		Real P0_1R = S0_3R;
		Real P0_2R = RiR;
		Real P0_3R = 1.0 /(1.0 / P0_1R + 1.0 / P0_2R);
		P0_3Gamma1 = 1.0 / P0_1R/(1.0 / P0_1R + 1.0 / P0_2R);
		Assert(P0_3Gamma1 >= 0.0 && P0_3Gamma1 <= 1.0);
		S1_3Gamma1 = RgR/(RgR + P0_3R);
		Assert(S1_3Gamma1 >= 0.0 && S1_3Gamma1 <= 1.0);
		Real I3_1R = CkR;
		Real I3_2R = RkR;
		I3_3Gamma1 = 1.0 / I3_1R/(1.0 / I3_1R + 1.0 / I3_2R);
		Assert(I3_3Gamma1 >= 0.0 && I3_3Gamma1 <= 1.0);
		Real S2_3R = (CoR + RoR);
		S2_3Gamma1 = CoR/(CoR + RoR);
		Assert(S2_3Gamma1 >= 0.0 && S2_3Gamma1 <= 1.0);
		Real P2_1R = S2_3R;
		Real P2_2R = E250R;
		P2_3Gamma1 = 1.0 / P2_1R/(1.0 / P2_1R + 1.0 / P2_2R);
		Assert(P2_3Gamma1 >= 0.0 && P2_3Gamma1 <= 1.0);
		t.Kr = sanitize_denormal(I3_3Gamma1);
		t.Pr = sanitize_denormal(P2_3Gamma1);
		t.Gr = sanitize_denormal(S1_3Gamma1);
		//printf("Kr = %f  Pr = %f  Gr = %f\n", t.Kr, t.Pr, t.Gr);
	}

	void warmup_tubes(void) {
		int i;
		on = false;
		for (i = 0; i < 8000; i++) {
			advanc(0.0);
		}
		on = true;
	}

	Real advanc(Real VE){
		//a = (v + R*i)/2.
		//b = (v - R*i)/2.
		//par -> v1=v2=v3   i1+i2+i3=0
		//ser -> v1+v2+v3=0 i1=i2=i3

		//Set Bs
		ViE = VE;
		Real Ckb = -Cka;
		Real I3_3b3 = 0.5*(Ckb/CkR-I3_3Gamma1*(Ckb)/CkR);

		Real Cib = -Cia;
		Real S0_3b3 = 0.5*(ViE - S0_3Gamma1*(-Cib)/CiR);
		Real P0_3b3 = 0.5*(S0_3b3 - P0_3Gamma1*(-S0_3b3));
		Real S1_3b3 = 0.5*(P0_3b3 - S1_3Gamma1*(-P0_3b3));
		
		Real Cob = -Coa;
		Real S2_3b3 = 0.5*(Cob/CoR - S2_3Gamma1*(-Cob)/CoR);
		Real P2_3b3 = 0.5*(E250E - P2_3Gamma1*(-S2_3b3));
		
		Real P2_3b1 = 0.5*(S2_3b3 - P2_3Gamma1*(-S2_3b3));

		//Tube:    K       G      P
		t.compute(I3_3b3,-S1_3b3,P2_3b3);
		Real b1 = t.getC();
		Real b2 = -t.getG();
		Real b3 = t.getP();
		
		//Set As
		//a = (v + R*i)/2
		Real I3_3a1 = 0.5*(b1 + I3_3Gamma1*(-b1));
		Cka = I3_3a1;

		Real S1_3a2 = 0.5*(b2 + S1_3Gamma1*(-b2));
		Real S0_3a1 = 0.5*(S1_3a2 + S0_3Gamma1*(-S1_3a2));
		Cia = S0_3a1;

		Real P2_3a1 = 0.5*(b3 + P2_3Gamma1*(-b3));
		Real S2_3a2 = 0.5*(-P2_3a1+ S2_3Gamma1*(P2_3a1));
		Coa = S2_3a2;

		Real S2_3a1 = 0.5*(-(Cob/CoR) - S2_3b3 + S2_3Gamma1*(-Cob)/CoR);
		Real Roa = S2_3a1;
		//printf("Ki=%f Ko=%f Gi=%f Go=%f Pi=%f Po=%f  Ro=%f\n", I3_3b3, b1, -S1_3b3, b2, P2_3b3, b3, Roa);
		return -Roa;
	}

private:
	//State variables
	Real Cia;
	Real Cka;
	Real Coa;

	//R values
	Real CiR;
	Real CkR;
	Real CoR;
	Real I3_3Gamma1;
	Real E250E;
	Real ViE;
	Real P0_3Gamma1;
	Real S0_3Gamma1;
	Real S2_3Gamma1;
	Real S1_3Gamma1;
	Real P2_3Gamma1;
};

#endif