diff --git a/src/app/channel-details/remote-source/remote-source.component.ts b/src/app/channel-details/remote-source/remote-source.component.ts
index dc2328a..b4cc430 100644
--- a/src/app/channel-details/remote-source/remote-source.component.ts
+++ b/src/app/channel-details/remote-source/remote-source.component.ts
@@ -9,6 +9,10 @@ import { Subscription, interval } from 'rxjs';
import { Utils } from '../../common-components/utils';
import { ChannelSettings } from '../channel-details';
+interface Log2 {
+ value: number;
+ viewValue: number;
+}
@Component({
selector: 'app-remote-source',
templateUrl: './remote-source.component.html',
@@ -38,6 +42,17 @@ export class RemoteSourceComponent implements OnInit {
deltaUncorrectableCount: number;
deltaSampleCount: number;
useReverseAPI: boolean;
+ log2Interps: Log2[] = [
+ {value: 0, viewValue: 1},
+ {value: 1, viewValue: 2},
+ {value: 2, viewValue: 4},
+ {value: 3, viewValue: 8},
+ {value: 4, viewValue: 16},
+ {value: 5, viewValue: 32},
+ {value: 6, viewValue: 64},
+ ];
+ channelDeltaFrequency: number;
+ channelCenterFrequencyKhz: number;
constructor(private route: ActivatedRoute,
private channeldetailsService: ChannelDetailsService,
@@ -100,6 +115,8 @@ export class RemoteSourceComponent implements OnInit {
this.statusMessage = 'OK';
this.statusError = false;
this.settings = channelSettings.RemoteSourceSettings;
+ this.channelDeltaFrequency = this.calculateFrequencyOffset();
+ this.channelCenterFrequencyKhz = (this.deviceCenterFrequency + this.channelDeltaFrequency) / 1000;
this.rgbTitle = Utils.intToRGB(this.settings.rgbColor);
this.rgbTitleStr = Utils.getRGBStr(this.rgbTitle);
this.useReverseAPI = this.settings.useReverseAPI !== 0;
@@ -136,7 +153,7 @@ export class RemoteSourceComponent implements OnInit {
_ => {
this.channeldetailsService.getReport(this.sdrangelURL, this.deviceIndex, this.channelIndex).subscribe(
channelReport => {
- if (channelReport.channelType === 'DaemonSource') {
+ if (channelReport.channelType === 'RemoteSource') {
this.report = channelReport.RemoteSourceReport;
const timestampUs = this.report.tvSec * 1000000 + this.report.tvUSec;
if (this.lastTimestampUs === 0) {
@@ -178,6 +195,11 @@ export class RemoteSourceComponent implements OnInit {
this.enableReporting(this.monitor);
}
+ getReportDateTime(): string {
+ const dateObj = new Date((this.report.tvSec * 1000000 + this.report.tvUSec) / 1000);
+ return dateObj.toISOString();
+ }
+
onTitleColorChanged(colorStr: string) {
this.rgbTitleStr = colorStr;
this.setTitleColor();
@@ -200,6 +222,18 @@ export class RemoteSourceComponent implements OnInit {
this.setDeviceSettings(newSettings);
}
+ setInterp() {
+ const newSettings: RemoteSourceSettings = {};
+ newSettings.log2Interp = this.settings.log2Interp;
+ this.setDeviceSettings(newSettings);
+ }
+
+ setFilterChainHash() {
+ const newSettings: RemoteSourceSettings = {};
+ newSettings.filterChainHash = this.settings.filterChainHash;
+ this.setDeviceSettings(newSettings);
+ }
+
setDataAddress() {
const newSettings: RemoteSourceSettings = {};
newSettings.dataAddress = this.settings.dataAddress;
@@ -256,13 +290,13 @@ export class RemoteSourceComponent implements OnInit {
getStreamStatusColor(): string {
if (this.deltaSampleCount === 0) {
- return 'blue';
+ return 'rgb(0, 0, 200, 1.0)';
} else if (this.deltaUncorrectableCount !== 0) {
- return 'red';
+ return 'rgb(200, 0, 0, 1.0)';
} else if (this.deltaCorrectableCount !== 0) {
- return 'grey';
+ return 'rgb(160, 160, 160, 1.0)';
} else {
- return 'green';
+ return 'rgb(0, 200, 0, 1.0)';
}
}
@@ -277,4 +311,21 @@ export class RemoteSourceComponent implements OnInit {
return 'Streaming OK';
}
}
+
+ getChannelBaseband(): number {
+ return (this.deviceBasebandRate / 1000) / (1 << this.settings.log2Interp);
+ }
+
+ getMaxFilterChainHash(): number {
+ return 3 ** this.settings.log2Interp;
+ }
+
+ getFilterChainString(): string {
+ return Utils.convertHBFilterChainToString(this.settings.log2Interp, this.settings.filterChainHash);
+ }
+
+ calculateFrequencyOffset(): number {
+ return this.deviceBasebandRate * Utils.getHBFilterChainShiftFactor(this.settings.log2Interp, this.settings.filterChainHash);
+ }
+
}
diff --git a/src/app/channel-details/remote-source/remote-source.ts b/src/app/channel-details/remote-source/remote-source.ts
index a46afbe..c3301fc 100644
--- a/src/app/channel-details/remote-source/remote-source.ts
+++ b/src/app/channel-details/remote-source/remote-source.ts
@@ -1,30 +1,36 @@
export interface RemoteSourceSettings {
dataAddress: string;
dataPort: number;
- rgbColor: number;
- title: string;
- useReverseAPI?: number; // bool
+ filterChainHash: number;
+ log2Interp: number;
reverseAPIAddress?: string;
reverseAPIPort?: number;
reverseAPIDeviceIndex?: number;
reverseAPIChannelIndex?: number;
+ rgbColor: number;
+ title: string;
+ useReverseAPI?: number; // bool
}
export const REMOTE_SOURCE_SETTINGS_DEFAULT = {
dataAddress: '127.0.0.1',
dataPort: 9090,
- rgbColor: -7601148,
- title: 'Remote channel source',
- useReverseAPI: 0,
+ filterChainHash: 0,
+ log2Interp: 0,
reverseAPIAddress: '127.0.0.1',
reverseAPIPort: 8888,
reverseAPIDeviceIndex: 0,
- reverseAPIChannelIndex: 0
+ reverseAPIChannelIndex: 0,
+ rgbColor: -7601148,
+ title: 'Remote channel source',
+ useReverseAPI: 0
};
export interface RemoteSourceReport {
centerFreq: number;
correctableErrorsCount: number;
+ deviceCenterFreq: number;
+ deviceSampleRate: number;
nbFECBlocks: number;
nbOriginalBlocks: number;
queueLength: number;
@@ -39,11 +45,13 @@ export interface RemoteSourceReport {
export const REMOTE_SOURCE_REPORT_DEFAULT = {
centerFreq: 434900,
correctableErrorsCount: 0,
+ deviceCenterFreq: 435000000,
+ deviceSampleRate: 48000,
nbFECBlocks: 8,
nbOriginalBlocks: 128,
queueLength: 18,
queueSize: 32,
- sampleRate: 75000,
+ sampleRate: 48000,
samplesCount: 101481494,
tvSec: 1535913707,
tvUSec: 667575,
diff --git a/src/app/device-details/device-details.module.ts b/src/app/device-details/device-details.module.ts
index ca5d25c..6b2de0c 100644
--- a/src/app/device-details/device-details.module.ts
+++ b/src/app/device-details/device-details.module.ts
@@ -34,6 +34,7 @@ import { RemoteInputComponent } from './remote-input/remote-input.component';
import { KiwisdrComponent } from './kiwisdr/kiwisdr.component';
import { RemoteOutputComponent } from './remote-output/remote-output.component';
import { Sdrplayv3Component } from './sdrplayv3/sdrplayv3.component';
+import { MatProgressBarModule } from '@angular/material/progress-bar';
@NgModule({
imports: [
@@ -44,6 +45,7 @@ import { Sdrplayv3Component } from './sdrplayv3/sdrplayv3.component';
MatOptionModule,
MatCheckboxModule,
MatTooltipModule,
+ MatProgressBarModule,
CommonComponentsModule,
DeviceDetailsRoutingModule
],
diff --git a/src/app/device-details/remote-output/remote-output.component.css b/src/app/device-details/remote-output/remote-output.component.css
index 7959cde..239832e 100644
--- a/src/app/device-details/remote-output/remote-output.component.css
+++ b/src/app/device-details/remote-output/remote-output.component.css
@@ -109,4 +109,22 @@ td.yellow {
::ng-deep .mat-checkbox-label {
line-height: 16px!important;
-}
\ No newline at end of file
+}
+
+.fill-bar {
+ height: 10px;
+ width: 40ch;
+ margin:0 auto;
+}
+
+::ng-deep .mat-progress-bar-fill::after {
+ background-color: rgb(33, 124, 30);
+}
+
+::ng-deep .mat-progress-bar-buffer {
+ background: rgb(205, 205, 205);
+}
+
+::ng-deep .mat-progress-bar {
+ border-radius: 5px;
+}
diff --git a/src/app/device-details/remote-output/remote-output.component.html b/src/app/device-details/remote-output/remote-output.component.html
index 4d2af07..79a14ec 100644
--- a/src/app/device-details/remote-output/remote-output.component.html
+++ b/src/app/device-details/remote-output/remote-output.component.html
@@ -9,47 +9,51 @@
(click)="toggleMonitor()">
- Remote output {{getSampleRate()/1000}} kS/s
+ Remote output {{report.sampleRate/1000}} kS/s
-
-
+
+
-
-
-
-
- Samples
- {{report ? report.sampleCount : 0}}
- |
-
- R/W bal
- {{report ? report.bufferRWBalance : 0}}
- %
- |
-
-
-
-
-
{{ statusMessage }}
-
\ No newline at end of file
+
diff --git a/src/app/device-details/remote-output/remote-output.component.ts b/src/app/device-details/remote-output/remote-output.component.ts
index be32202..4098a55 100644
--- a/src/app/device-details/remote-output/remote-output.component.ts
+++ b/src/app/device-details/remote-output/remote-output.component.ts
@@ -21,16 +21,30 @@ export class RemoteOutputComponent implements OnInit {
sdrangelURL: string;
report: RemoteOutputReport = REMOTE_OUTPUT_REPORT_DEFAULT;
settings: RemoteOutputSettings = REMOTE_OUTPUT_SETTINGS_DEFAULT;
- centerFreqKhz: number;
- txDelayPercent: number;
useReverseAPI: boolean;
deviceReportSubscription: Subscription;
monitor: boolean;
+ lastTimestampUs: number;
+ deltaTimestampUs: number;
+ lastSampleCount: number;
+ deltaSampleCount: number;
+ lastCorrectableCount: number;
+ deltaCorrectableCount: number;
+ lastUncorrectableCount: number;
+ deltaUncorrectableCount: number;
constructor(private route: ActivatedRoute,
private devicedetailsService: DeviceDetailsService,
private sdrangelUrlService: SdrangelUrlService,
private deviceStoreService: DeviceStoreService) {
+ this.lastSampleCount = 0;
+ this.deltaSampleCount = 0;
+ this.lastTimestampUs = 0;
+ this.deltaTimestampUs = 0;
+ this.lastCorrectableCount = 0;
+ this.deltaCorrectableCount = 0;
+ this.lastUncorrectableCount = 0;
+ this.deltaUncorrectableCount = 0;
}
ngOnInit() {
@@ -48,10 +62,7 @@ export class RemoteOutputComponent implements OnInit {
this.statusMessage = 'OK';
this.statusError = false;
this.settings = deviceSettings.remoteOutputSettings;
- this.centerFreqKhz = this.settings.centerFrequency / 1000;
- this.txDelayPercent = Math.round(this.settings.txDelay * 100);
this.useReverseAPI = this.settings.useReverseAPI !== 0;
- this.feedDeviceStore();
} else {
this.statusMessage = 'Not a Remote output device';
this.statusError = true;
@@ -60,14 +71,6 @@ export class RemoteOutputComponent implements OnInit {
);
}
- private feedDeviceStore() {
- const deviceStorage = {
- centerFrequency: this.settings.centerFrequency,
- basebandRate: this.settings.sampleRate
- };
- this.deviceStoreService.change(this.deviceIndex, deviceStorage);
- }
-
enableReporting(enable: boolean) {
if (enable) {
this.deviceReportSubscription = interval(1000).subscribe(
@@ -76,6 +79,23 @@ export class RemoteOutputComponent implements OnInit {
devicelReport => {
if ((devicelReport.deviceHwType === 'RemoteOutput') && (devicelReport.direction === 1)) {
this.report = devicelReport.remoteOutputReport;
+ this.feedDeviceStore();
+ const timestampUs = this.report.tvSec * 1000000 + this.report.tvUSec;
+ if (this.lastTimestampUs === 0) {
+ this.lastTimestampUs = timestampUs;
+ }
+ this.deltaTimestampUs = timestampUs - this.lastTimestampUs;
+ this.lastTimestampUs = timestampUs;
+ if (this.report.sampleCount < this.lastSampleCount) {
+ this.deltaSampleCount = (0xFFFFFFFF - this.lastSampleCount) + this.report.sampleCount + 1;
+ } else {
+ this.deltaSampleCount = this.report.sampleCount - this.lastSampleCount;
+ }
+ this.lastSampleCount = this.report.sampleCount;
+ this.deltaCorrectableCount = this.report.correctableErrorsCount - this.lastCorrectableCount;
+ this.deltaUncorrectableCount = this.report.uncorrectableErrorsCount - this.lastUncorrectableCount;
+ this.lastCorrectableCount = this.report.correctableErrorsCount;
+ this.lastUncorrectableCount = this.report.uncorrectableErrorsCount;
}
}
);
@@ -92,6 +112,14 @@ export class RemoteOutputComponent implements OnInit {
this.enableReporting(this.monitor);
}
+ private feedDeviceStore() {
+ const deviceStorage = {
+ centerFrequency: this.report.centerFrequency,
+ basebandRate: this.report.sampleRate
+ };
+ this.deviceStoreService.change(this.deviceIndex, deviceStorage);
+ }
+
private setDeviceSettings(remoteOutputSettings: RemoteOutputSettings) {
const settings: DeviceSettings = {};
settings.deviceHwType = 'RemoteOutput';
@@ -111,33 +139,6 @@ export class RemoteOutputComponent implements OnInit {
);
}
- getSampleRate(): number {
- return this.settings.sampleRate;
- }
-
- setSampleRate() {
- const newSettings: RemoteOutputSettings = {};
- newSettings.sampleRate = this.settings.sampleRate;
- this.setDeviceSettings(newSettings);
- }
-
- onFrequencyUpdate(frequency: number) {
- this.centerFreqKhz = frequency;
- this.setCenterFrequency();
- }
-
- setCenterFrequency() {
- const newSettings: RemoteOutputSettings = {};
- newSettings.centerFrequency = this.centerFreqKhz * 1000;
- this.setDeviceSettings(newSettings);
- }
-
- setTxDelay() {
- const newSettings: RemoteOutputSettings = {};
- newSettings.txDelay = this.txDelayPercent / 100;
- this.setDeviceSettings(newSettings);
- }
-
setRemoteAPIAddress() {
const newSettings: RemoteOutputSettings = {};
newSettings.apiAddress = this.settings.apiAddress;
@@ -162,6 +163,12 @@ export class RemoteOutputComponent implements OnInit {
this.setDeviceSettings(newSettings);
}
+ setNbFECBlocks() {
+ const newSettings: RemoteOutputSettings = {};
+ newSettings.nbFECBlocks = this.settings.nbFECBlocks;
+ this.setDeviceSettings(newSettings);
+ }
+
setUseReverseAPI() {
const newSettings: RemoteOutputSettings = {};
newSettings.useReverseAPI = this.useReverseAPI ? 1 : 0;
@@ -185,4 +192,45 @@ export class RemoteOutputComponent implements OnInit {
newSettings.reverseAPIDeviceIndex = this.settings.reverseAPIDeviceIndex;
this.setDeviceSettings(newSettings);
}
+
+ getReportDateTime(): string {
+ const dateObj = new Date((this.report.tvSec * 1000000 + this.report.tvUSec) / 1000);
+ return dateObj.toISOString();
+ }
+
+ getQueuePercentage(): number {
+ return (this.report.queueLength * 100) / this.report.queueSize;
+ }
+
+ getStreamSampleRate(): number {
+ if (this.deltaTimestampUs === 0) {
+ return 0;
+ } else {
+ return (this.deltaSampleCount * 1e6) / this.deltaTimestampUs;
+ }
+ }
+
+ getStreamStatusColor(): string {
+ if (this.deltaSampleCount === 0) {
+ return 'rgb(0, 0, 200, 1.0)';
+ } else if (this.deltaUncorrectableCount !== 0) {
+ return 'rgb(200, 0, 0, 1.0)';
+ } else if (this.deltaCorrectableCount !== 0) {
+ return 'rgb(160, 160, 160, 1.0)';
+ } else {
+ return 'rgb(0, 200, 0, 1.0)';
+ }
+ }
+
+ getStreamStatusText(): string {
+ if (this.deltaSampleCount === 0) {
+ return 'Not streaming';
+ } else if (this.deltaUncorrectableCount !== 0) {
+ return 'Data lost';
+ } else if (this.deltaCorrectableCount !== 0) {
+ return 'Data corrected';
+ } else {
+ return 'Streaming OK';
+ }
+ }
}
diff --git a/src/app/device-details/remote-output/remote-output.ts b/src/app/device-details/remote-output/remote-output.ts
index 8c3dfc2..f3f7531 100644
--- a/src/app/device-details/remote-output/remote-output.ts
+++ b/src/app/device-details/remote-output/remote-output.ts
@@ -1,43 +1,51 @@
export interface RemoteOutputSettings {
- centerFrequency?: number;
- sampleRate?: number;
- txDelay?: number; // minimum delay in ms between two consecutive packets sending
- nbFECBlocks?: number;
apiAddress?: string;
apiPort?: number;
+ channelIndex?: number; // remote SDRangel instance channel index
dataAddress?: string;
dataPort?: number;
deviceIndex?: number; // remote SDRangel instance deviceset index
- channelIndex?: number; // remote SDRangel instance channel index
- useReverseAPI?: number; // bool
+ nbFECBlocks?: number;
reverseAPIAddress?: string;
- reverseAPIPort?: number;
reverseAPIDeviceIndex?: number;
+ reverseAPIPort?: number;
+ useReverseAPI?: number; // bool
}
export const REMOTE_OUTPUT_SETTINGS_DEFAULT = {
- centerFrequency: 435000000,
- sampleRate: 48000,
- txDelay: 0.35,
- nbFECBlocks: 0,
apiAddress: '127.0.0.1',
apiPort: 9091,
+ channelIndex: 0,
dataAddress: '127.0.0.1',
dataPort: 9090,
deviceIndex: 0,
- channelIndex: 0,
- useReverseAPI: 0,
+ nbFECBlocks: 0,
reverseAPIAddress: '127.0.0.1',
+ reverseAPIDeviceIndex: 0,
reverseAPIPort: 8888,
- reverseAPIDeviceIndex: 0
+ useReverseAPI: 0
};
export interface RemoteOutputReport {
- bufferRWBalance: number; // ratio off the mid buffer (positive read leads)
+ centerFrequency: number; // cener frequency of remote (in stream)
sampleCount: number; // count of samples that have been sent
+ sampleRate: number; // sample rate in remote (in stream)
+ queueLength: number;
+ queueSize: number;
+ correctableErrorsCount: number;
+ uncorrectableErrorsCount: number;
+ tvSec: number;
+ tvUSec: number;
}
export const REMOTE_OUTPUT_REPORT_DEFAULT = {
- bufferRWBalance: 0,
- sampleCount: 0
+ centerFrequency: 435000000,
+ sampleCount: 0,
+ sampleRate: 48000,
+ queueLength: 2,
+ queueSize: 20,
+ correctableErrorsCount: 0,
+ uncorrectableErrorsCount: 0,
+ tvSec: 1535913707,
+ tvUSec: 667575
};
|