Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Other Smith chart "characterization" views #145

Merged
merged 1 commit into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions Impedance Converter/Impedance Converter/CharacterizationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,51 @@ struct SWRView: View {
}
}

struct ReturnLossView: View {
struct SWRDBView: View {
@ObservedObject var viewModel: ViewModel

var body: some View {
UnitInputView(value: $viewModel.returnLoss, unit: ReturnLossUnit.dB, label: "RL", description: "return loss")
UnitInputView(value: $viewModel.swr_dB, unit: StandingWaveRatioDBUnit.dB, label: "SWR", description: "st. wave ratio")
}
}

struct ReflectionCoefficientView: View {
@ObservedObject var viewModel: ViewModel

var body: some View {
UnitInputView(value: $viewModel.reflectionCoefficientRho, unit: ReflectionCoefficientRhoUnit.ρ, label: "ρ", description: "refl. coeff.")
}
}

struct ReflectionCoefficientPowerView: View {
@ObservedObject var viewModel: ViewModel

var body: some View {
UnitInputView(value: $viewModel.reflectionCoefficientPower, unit: ReflectionCoefficientPowerUnit.ρ², label: "ρ²", description: "refl. coeff. power")
}
}

struct TransmissionCoefficientView: View {
@ObservedObject var viewModel: ViewModel

var body: some View {
UnitInputView(value: $viewModel.transmissionCoefficient, unit: TransmissionCoefficientUnit.T, label: "T", description: "transmission coeff.")
UnitInputView(value: $viewModel.transmissionCoefficient, unit: TransmissionCoefficientUnit.τ, label: "τ", description: "trans. coeff.")
}
}

struct TransmissionCoefficientPowerView: View {
@ObservedObject var viewModel: ViewModel

var body: some View {
UnitInputView(value: $viewModel.transmissionCoefficientPower, unit: TransmissionCoefficientPowerUnit.τ², label: "τ²", description: "trans. coeff. power")
}
}

struct ReturnLossView: View {
@ObservedObject var viewModel: ViewModel

var body: some View {
UnitInputView(value: $viewModel.returnLoss, unit: ReturnLossUnit.dB, label: "RL", description: "return loss")
}
}

Expand All @@ -43,12 +75,24 @@ struct CharacterizationView: View {
DisplayView {
HStack {
SWRView(viewModel: viewModel)
ReturnLossView(viewModel: viewModel)
SWRDBView(viewModel: viewModel)
}
}
DisplayView {
HStack {
ReflectionCoefficientView(viewModel: viewModel)
TransmissionCoefficientView(viewModel: viewModel)
}
}
DisplayView {
HStack {
ReflectionCoefficientPowerView(viewModel: viewModel)
TransmissionCoefficientPowerView(viewModel: viewModel)
}
}
DisplayView {
HStack {
ReturnLossView(viewModel: viewModel)
TransmissionLossView(viewModel: viewModel)
}
}
Expand Down
41 changes: 40 additions & 1 deletion Impedance Converter/Impedance Converter/Units.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ enum StandingWaveRatioUnit: String, UnitWithPowerOfTen {
case SWR
var id: Self { self }
var basePower: Int { 0 }
var shouldRender: Bool {
return self != .SWR
}
}

enum StandingWaveRatioDBUnit: String, UnitWithPowerOfTen {
case dB
var id: Self { self }
var basePower: Int { 0 }
}

enum ReflectionCoefficientRhoUnit: String, UnitWithPowerOfTen {
case ρ
var id: Self { self }
var basePower: Int { 0 }
var shouldRender: Bool {
return self != .ρ
}
}

enum ReflectionCoefficientPowerUnit: String, UnitWithPowerOfTen {
case ρ²
var id: Self { self }
var basePower: Int { 0 }
var shouldRender: Bool {
return self != .ρ²
}
}

enum ReturnLossUnit: String, UnitWithPowerOfTen {
Expand All @@ -61,9 +88,21 @@ enum ReturnLossUnit: String, UnitWithPowerOfTen {
}

enum TransmissionCoefficientUnit: String, UnitWithPowerOfTen {
case T
case τ
var id: Self { self }
var basePower: Int { 0 }
var shouldRender: Bool {
return self != .τ
}
}

enum TransmissionCoefficientPowerUnit: String, UnitWithPowerOfTen {
case τ²
var id: Self { self }
var basePower: Int { 0 }
var shouldRender: Bool {
return self != .τ²
}
}

enum TransmissionLossUnit: String, UnitWithPowerOfTen {
Expand Down
53 changes: 47 additions & 6 deletions Impedance Converter/Impedance Converter/ViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,35 @@ class ViewModel: ObservableObject, Codable {
}
}

var swr_dB: Double {
get {
return 20 * log10(swr)
}
set {
swr = pow(10, newValue / 20)
}
}

var reflectionCoefficientRho: Double {
get {
return reflectionCoefficient.length
}
set {
guard !reflectionCoefficient.phase.isNaN else { return }
reflectionCoefficient = Complex.init(length: newValue, phase: reflectionCoefficient.phase)
}
}

var reflectionCoefficientPower: Double {
get {
return reflectionCoefficient.lengthSquared
}
set {
guard !reflectionCoefficient.phase.isNaN else { return }
reflectionCoefficient = Complex.init(length: sqrt(newValue), phase: reflectionCoefficient.phase)
}
}

var returnLoss: Double {
get {
if (unityReflectionCoefficient()) {
Expand All @@ -459,27 +488,39 @@ class ViewModel: ObservableObject, Codable {
if (unityReflectionCoefficient()) {
return 0
} else {
return 1 - pow(reflectionCoefficient.length, 2)
return 1 - reflectionCoefficient.length
}
}
set {
guard newValue >= 0 && newValue <= 1 else { return }
let reflectionCoefficientLength = sqrt(1 - newValue)
if (reflectionCoefficient.length > 0) {
reflectionCoefficient = Complex.init(length: reflectionCoefficientLength, phase: reflectionCoefficient.phase)
let reflectionCoefficientLength = 1 - newValue
reflectionCoefficient = Complex.init(length: reflectionCoefficientLength, phase: reflectionCoefficient.phase)
}
}

var transmissionCoefficientPower: Double {
get {
if (unityReflectionCoefficient()) {
return 0
} else {
return transmissionCoefficient * transmissionCoefficient
}
}
set {
guard newValue >= 0 && newValue <= 1 else { return }
transmissionCoefficient = sqrt(newValue)
}
}

var transmissionLoss: Double {
get {
let transmissionCoefficientValue = transmissionCoefficient
let transmissionCoefficientValue = transmissionCoefficientPower
return -10 * log10(transmissionCoefficientValue)
}
set {
guard newValue >= 0 else { return }
let transmissionCoefficientValue = pow(10, -newValue / 10)
transmissionCoefficient = transmissionCoefficientValue
transmissionCoefficientPower = transmissionCoefficientValue
}
}

Expand Down
76 changes: 70 additions & 6 deletions Impedance Converter/Impedance ConverterTests/ViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,70 @@ class TransmissionParametersTests: ViewModelTestBase {
XCTAssertEqual(viewModel.swr, 1)
}

// Testing Standing Wave Ratio (SWR) dB
func testSWR_db() {
viewModel.reactance = 40
viewModel.swr = 10
XCTAssertEqual(viewModel.swr_dB, 20, accuracy: 1e-6)

viewModel.swr = 100
XCTAssertEqual(viewModel.swr_dB, 40, accuracy: 1e-6)

viewModel.swr_dB = 20
XCTAssertEqual(viewModel.swr, 10, accuracy: 1e-6)

viewModel.swr = 1
XCTAssertEqual(viewModel.swr_dB, 0, accuracy: 1e-6)

viewModel.reactance = 40
viewModel.swr_dB = 0
XCTAssertEqual(viewModel.swr, 1, accuracy: 1e-6)
}

// Testing Reflection Coefficient Power
func testReflectionCoefficientPower() {
let reflectionCoefficient = Complex(0.5, 0)
viewModel.reflectionCoefficient = reflectionCoefficient

let expectedReflectionCoefficientPower = reflectionCoefficient.lengthSquared
XCTAssertEqual(viewModel.reflectionCoefficientPower, expectedReflectionCoefficientPower)

let newReflectionCoefficientPower = 0.3
viewModel.reflectionCoefficientPower = newReflectionCoefficientPower
let expectedReflectionCoefficientMagnitude = sqrt(newReflectionCoefficientPower)
XCTAssertEqual(viewModel.reflectionCoefficient.magnitude, expectedReflectionCoefficientMagnitude, accuracy: 1e-6)
}

// Testing Transmission Coefficient Power
func testTransmissionCoefficientPower() {
let reflectionCoefficient = Complex(0.5, 0)
viewModel.reflectionCoefficient = reflectionCoefficient

let expectedTransmisionCoefficientPower = pow(1 - reflectionCoefficient.length, 2)
XCTAssertEqual(viewModel.transmissionCoefficientPower, expectedTransmisionCoefficientPower)

let newTransmissionCoefficientPower = 0.3
viewModel.transmissionCoefficientPower = newTransmissionCoefficientPower
let expectedReflectionCoefficientMagnitude = 1 - sqrt(newTransmissionCoefficientPower)
XCTAssertEqual(viewModel.reflectionCoefficient.magnitude, expectedReflectionCoefficientMagnitude, accuracy: 1e-6)
}

func testReflectionCoefficientTransmissionCoefficient() {
viewModel.reactance = 40
property("Reflection coefficient plus transmission coefficient must sum to 1") <- forAll( Gen<Double>.choose((0, 1)) ) { rho in
self.viewModel.reflectionCoefficientRho = rho
return abs(rho + self.viewModel.transmissionCoefficient - 1) < 1e-6
}
}

func testTransmissionCoefficientReflectionCoefficient() {
viewModel.reactance = 40
property("Reflection coefficient plus transmission coefficient must sum to 1") <- forAll( Gen<Double>.choose((0, 1)) ) { tau in
self.viewModel.transmissionCoefficient = tau
return abs(self.viewModel.reflectionCoefficientRho + tau - 1) < 1e-6
}
}

// Testing Return Loss
func testReturnLoss() {
let reflectionCoefficient = Complex(0.5, 0)
Expand Down Expand Up @@ -575,13 +639,13 @@ class TransmissionParametersTests: ViewModelTestBase {
viewModel.reflectionCoefficient = reflectionCoefficient

// Check transmission coefficient calculation
let expectedTransmissionCoefficient = 1 - pow(reflectionCoefficient.magnitude, 2)
let expectedTransmissionCoefficient = 1 - reflectionCoefficient.length
XCTAssertEqual(viewModel.transmissionCoefficient, expectedTransmissionCoefficient)

// Set transmission coefficient and check reflection coefficient changes
let newTransmissionCoefficient = 0.75
viewModel.transmissionCoefficient = newTransmissionCoefficient
let expectedReflectionCoefficientMagnitude = sqrt(1 - newTransmissionCoefficient)
let expectedReflectionCoefficientMagnitude = 1 - newTransmissionCoefficient
XCTAssertEqual(viewModel.reflectionCoefficient.magnitude, expectedReflectionCoefficientMagnitude, accuracy: 1e-6)
}

Expand All @@ -598,13 +662,13 @@ class TransmissionParametersTests: ViewModelTestBase {
viewModel.transmissionCoefficient = 0.75

// Check transmission loss calculation
let expectedTransmissionLoss = -10 * log10(viewModel.transmissionCoefficient)
let expectedTransmissionLoss = -20 * log10(viewModel.transmissionCoefficient)
XCTAssertEqual(viewModel.transmissionLoss, expectedTransmissionLoss)

// Set transmission loss and check transmission coefficient changes
let newTransmissionLoss = 3.0
viewModel.transmissionLoss = newTransmissionLoss
let expectedTransmissionCoefficientValue = pow(10, -newTransmissionLoss / 10)
let expectedTransmissionCoefficientValue = pow(10, -newTransmissionLoss / 20)
XCTAssertEqual(viewModel.transmissionCoefficient, expectedTransmissionCoefficientValue, accuracy: 1e-6)
}
}
Expand Down Expand Up @@ -729,10 +793,10 @@ class FullTests: ViewModelTestBase {
XCTAssertEqual(viewModel.reactance, -51, accuracy: 5e-1)
XCTAssertEqual(viewModel.reflectionCoefficient.length, 0.54, accuracy: 5e-2)
XCTAssertEqual(Angle(radians: viewModel.reflectionCoefficient.phase).degrees, -76.4, accuracy: 8e-1)
// TODO gamma power should be 0.3
XCTAssertEqual(viewModel.reflectionCoefficientPower, 0.3, accuracy: 5e-2)
XCTAssertEqual(viewModel.returnLoss, 5.25, accuracy: 1e-1)
XCTAssertEqual(viewModel.swr, 3.4, accuracy: 1e-1)
// TODO SWR DB 10.6
XCTAssertEqual(viewModel.swr_dB, 10.6, accuracy: 3e-1)
XCTAssertEqual(viewModel.wavelength, 21.13, accuracy: 5e-2)
viewModel.angleOrientation = .clockwise
viewModel.zeroLength()
Expand Down