7
mirror of https://github.com/EEVengers/ThunderScope.git synced 2025-04-22 17:43:44 +00:00

Merge pull request from EEVengers/electron-pipe

Electron pipe
This commit is contained in:
ratanvarghese 2021-03-22 02:28:13 -04:00 committed by GitHub
commit ec2caa0088
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 348 additions and 278 deletions

View File

@ -34,8 +34,8 @@ Prepend the name with `CMD_` to find it in the Electron and C++ code.
Cmd | DataSize | Name | Description
-----|-----------------|---------------|------------------------
0x01 | 2 (useless) | GetData1 |
0x05 | 2 | GetMin | Data has ch 1,2,3 or 4
0x06 | 2 | GetMax | Data has ch 1,2,3 or 4
0x05 | 4 | GetMin | Data: `[ch1, ch2, ch3, ch4]`, each 1 or 0
0x06 | 4 | GetMax | Data: `[ch1, ch2, ch3, ch4]`, each 1 or 0
0x11 | 2 | SetFile | Number mapped to filename by C++
0x1F | 2 (useless) | RampDemo |
0x21 | 2 (useless) | GetWindowSize |
@ -63,8 +63,8 @@ Note that the encoding used by the protocol might not be same as the encoding us
Cmd | DataSize | Name | Description
-----|-----------------|---------------|------------------------
0x01 | ch * windowSize | GetData1 | Data for all ch
0x05 | 16 | GetMin | Data has x and y as uint64 and int64
0x06 | 16 | GetMax | Data has x and y as uint64 and int64
0x05 | 64 | GetMin | Data has `[x1, x2...]` and `[y1, y2..]` as uint64 and int64
0x06 | 64 | GetMax | Data has `[x1, x2...]` and `[y1, y2..]` as uint64 and int64
0x11 | 0 | SetFile | Set testdata filename
0x1F | 4096 | RampDemo | 4 ch, simple waves
0x21 | 4 | GetWindowSize | Data has window size as uint32
@ -83,20 +83,29 @@ Cmd | DataSize | Name | Description
### Electron -> C++
Cmd | DataSize | Name | Description
-----|-----------------|---------------|------------------------
0x02 | 2 (useless) | GetData2 | Reserved, If we need 1 command/ch
0x03 | 2 (useless) | GetData3 | Reserved, If we need 1 command/ch
0x04 | 2 (useless) | GetData4 | Reserved, If we need 1 command/ch
Cmd | DataSize | Name | Description
-----|-----------------|---------------------|------------------------
0x02 | 2 (useless) | GetData2 | Reserved, If we need 1 command/ch
0x03 | 2 (useless) | GetData3 | Reserved, If we need 1 command/ch
0x04 | 2 (useless) | GetData4 | Reserved, If we need 1 command/ch
0x36 | 2? | SetBandwidth |
0x37 | 2? | SetVerticalScaling |
0x38 | 2 | SetVerticalOffset | Data\[0\] has offset
0x39 | 2? | SetHorizontalOffset |
0x3A | 2 | SetCoupling | Data\[0\] has 0\1 for AC\DC
### C++ -> Electron
Cmd | DataSize | Name | Description
-----|-----------------|---------------|------------------------
0x02 | windowSize | Reserved | If we need 1 command/ch
0x03 | windowSize | Reserved | If we need 1 command/ch
0x04 | windowSize | Reserved | If we need 1 command/ch
Cmd | DataSize | Name | Description
-----|-----------------|---------------------|------------------------
0x02 | windowSize | Reserved | If we need 1 command/ch
0x03 | windowSize | Reserved | If we need 1 command/ch
0x04 | windowSize | Reserved | If we need 1 command/ch
0x36 | 0 | SetBandwidth |
0x37 | 0 | SetVerticalScaling |
0x38 | 0 | SetVerticalOffset |
0x39 | 0 | SetHorizontalOffset |
0x3A | 0 | SetCoupling |
## Proposed But Not Allocated
+ (none)

View File

@ -90,6 +90,11 @@ enum CMD {
CMD_SetLevel = 0x33,
CMD_SetTriggerCh = 0x34,
CMD_SetEdgeType = 0x35,
CMD_SetBandwidth = 0x36,
CMD_SetVerticalScaling = 0x37,
CMD_SetVerticalOffset = 0x38,
CMD_SetHorizontalOffset = 0x39,
CMD_SetCoupling = 0x3A,
CMD_SetMath = 0x3F
};

View File

@ -107,27 +107,29 @@ void controller::controllerLoop()
break;
case CMD_GetMin: {
INFO << "Packet command: GetMin";
const int incomingPacketSize = 2;
int ch = 1;
if(currentPacket->dataSize != incomingPacketSize) {
const int maxCh = 4;
const int incomingDataSize = maxCh;
//calloc to ensure zero
int8_t* outgoingData = (int8_t*) calloc(2*maxCh, sizeof(uint64_t));
if(currentPacket->dataSize != incomingDataSize) {
ERROR << "Unexpected size for GetMin packet";
}
else {
ch = currentPacket->data[0];
uint64_t* outgoingU = (uint64_t*) outgoingData;
int64_t* outgoingS = (int64_t*) outgoingData;
for(int ch = 0; ch < incomingDataSize; ch++) {
if(currentPacket->data[ch]) {
int8_t val;
uint64_t pos;
getMin(ch + 1, &val, &pos);
outgoingU[ch] = pos;
outgoingS[ch + maxCh] = val;
}
}
}
int8_t val;
uint64_t pos;
getMin(ch, &val, &pos);
const int outgoingPacketSize = 2*sizeof(uint64_t);
uint64_t* outgoingU = (uint64_t*) malloc(outgoingPacketSize);
int64_t* outgoingS = (int64_t*) outgoingU;
outgoingU[0] = pos;
outgoingS[1] = val;
EVPacket* tempPacket = (EVPacket*) malloc(sizeof(EVPacket));
tempPacket->data = (int8_t*)outgoingU;
tempPacket->dataSize = outgoingPacketSize;
tempPacket->data = outgoingData;
tempPacket->dataSize = 2*maxCh*sizeof(uint64_t);
tempPacket->packetID = 0;
tempPacket->command = CMD_GetMin;
controllerQueue_tx.push(tempPacket);
@ -135,31 +137,31 @@ void controller::controllerLoop()
break;
case CMD_GetMax: {
INFO << "Packet command: GetMax";
const int incomingPacketSize = 2;
int ch = 1;
if(currentPacket->dataSize != incomingPacketSize) {
ERROR << "Unexpected size for GetMax packet";
const int maxCh = 4;
const int incomingDataSize = maxCh;
//calloc to ensure zero
int8_t* outgoingData = (int8_t*) calloc(2*maxCh, sizeof(uint64_t));
if(currentPacket->dataSize != incomingDataSize) {
ERROR << "Unexpected size for GetMin packet";
}
else {
ch = currentPacket->data[0];
uint64_t* outgoingU = (uint64_t*) outgoingData;
int64_t* outgoingS = (int64_t*) outgoingData;
for(int ch = 0; ch < incomingDataSize; ch++) {
if(currentPacket->data[ch]) {
int8_t val;
uint64_t pos;
getMax(ch + 1, &val, &pos);
outgoingU[ch] = pos;
outgoingS[ch + maxCh] = val;
}
}
}
int8_t val;
uint64_t pos;
getMax(ch, &val, &pos);
INFO << "val: " << convert_int(val) << ", pos: " << convert_int(pos);
const int outgoingPacketSize = 2*sizeof(uint64_t);
uint64_t* outgoingU = (uint64_t*) malloc(outgoingPacketSize);
int64_t* outgoingS = (int64_t*) outgoingU;
outgoingU[0] = pos;
outgoingS[1] = val;
EVPacket* tempPacket = (EVPacket*) malloc(sizeof(EVPacket));
tempPacket->data = (int8_t*)outgoingU;
tempPacket->dataSize = outgoingPacketSize;
tempPacket->data = outgoingData;
tempPacket->dataSize = 2*maxCh*sizeof(uint64_t);
tempPacket->packetID = 0;
tempPacket->command = CMD_GetMax;
tempPacket->command = CMD_GetMin;
controllerQueue_tx.push(tempPacket);
}
break;

View File

@ -19,8 +19,8 @@ Trigger::Trigger(boost::lockfree::queue<buffer*, boost::lockfree::fixed_sized<fa
triggerLevel = level;
clearCount();
stopTrigger.store(false);
pauseTrigger.store(true);
stopTrigger.store(false);
pauseTrigger.store(true);
triggerMet.store(false);
// start thread paused
@ -54,7 +54,7 @@ void Trigger::checkTriggerFalling(buffer* currentBuffer)
DEBUG << "Checking a Trigger with #ch: " << (int)numCh << " triggering on ch: " << (int)triggerCh;
// Compute the trigger
for (int i = 0; i < (BUFFER_SIZE/64)/numCh; i++) {
currentBuffer->trigger[i] =
currentBuffer->trigger[i] =
((uint64_t)((currentBuffer->data[(i * 64 + 0) * numCh + triggerCh] > triggerLevel) &&
(currentBuffer->data[(i * 64 + 0 + 1) * numCh + triggerCh] <= triggerLevel)) << 63) |
((uint64_t)((currentBuffer->data[(i * 64 + 1) * numCh + triggerCh] > triggerLevel) &&
@ -198,7 +198,7 @@ void Trigger::checkTriggerRising(buffer* currentBuffer)
DEBUG << "Checking a Trigger with #ch: " << (int)numCh << " triggering on ch: " << (int)triggerCh;
// Compute the trigger
for (int i = 0; i < (BUFFER_SIZE/64)/numCh; i++) {
currentBuffer->trigger[i] =
currentBuffer->trigger[i] =
((uint64_t)((currentBuffer->data[(i * 64 + 0) * numCh + triggerCh] < triggerLevel) &&
(currentBuffer->data[(i * 64 + 0 + 1) * numCh + triggerCh] >= triggerLevel)) << 63) |
((uint64_t)((currentBuffer->data[(i * 64 + 1) * numCh + triggerCh] < triggerLevel) &&
@ -420,7 +420,7 @@ int8_t Trigger::getTriggerCh ()
// Sets the channel to trigger off of
void Trigger::setTriggerCh (int8_t newTriggerCh)
{
if (newTriggerCh == 1 || newTriggerCh == 2 || newTriggerCh == 4) {
if (newTriggerCh == 1 || newTriggerCh == 2 || newTriggerCh == 3 || newTriggerCh == 4) {
triggerCh = newTriggerCh - 1;
} else {
ERROR << "Invalid trigger channel: " << newTriggerCh;

View File

@ -3,62 +3,15 @@ import './App.css';
import Graph from './components/graph/graph';
import BottomBar from './components/bottombar/bottombar';
import Sidebar from './components/sidebar/sidebar';
import TestPoints from './util/testpoints';
import TestConf from './util/testconf';
interface IAppState {
tickCount: number;
}
let initialState: IAppState = {tickCount: 0};
class App extends React.Component {
state: IAppState;
timerID: number = 0;
generator: TestPoints;
conf: TestConf;
constructor(props: any) {
super(props);
this.state = initialState;
this.generator = new TestPoints(50, 50);
this.conf = new TestConf();
}
componentDidMount() {
this.timerID = window.setInterval(
() => this.tick(),
16.67
);
this.generator.mountCalls();
}
componentWillUnmount() {
clearInterval(this.timerID)
}
tick() {
let tickCount = this.state.tickCount + 1;
this.generator.update();
if(tickCount % 100 === 0) {
console.log(tickCount);
this.conf.update(tickCount % 500 !== 0);
//this.conf.mathUpdate();
}
this.setState({tickCount: tickCount});
}
render() {
return (
<div className="App">
<header
className="App-header">
</header>
<Graph
yDomain={this.generator.y.getDomain()}
xDomain={this.generator.x.getDomain()}
dataSeries={this.generator.getData()}
/>
<Graph />
<BottomBar />
<Sidebar />
</div>

View File

@ -10,36 +10,62 @@ import {
LineSeries
} from 'react-vis';
class Graph extends React.Component<any, any> {
import GraphStatus from '../../configuration/enums/graphStatus';
import TestPoints from '../../util/testpoints';
class Graph extends React.Component<any, any> {
static instanceList: Graph[] = [];
timerID: number = 0;
generator: TestPoints = new TestPoints(50, 50);
componentDidMount() {
Graph.instanceList.push(this);
this.timerID = window.setInterval(
() => this.tick(),
16.67
);
this.generator.mountCalls();
}
componentWillUnmount() {
clearInterval(this.timerID)
}
tick() {
if(this.props.graph.currentStatus === GraphStatus.On) {
this.props.dispatch({type: 'graph/tick'});
this.generator.update();
}
}
render() {
return (
<div className="graph_view">
<div
<div
className="graph_sidebar"
>
<p
<p
className = "graph_arrow"
>
&#x21b3;
</p>
</div>
<FlexibleXYPlot
yDomain={this.props.yDomain}
xDomain={this.props.xDomain}
yDomain={this.generator.y.getDomain()}
xDomain={this.generator.x.getDomain()}
margin={{right:0, bottom:0}}
>
<HorizontalGridLines
<HorizontalGridLines
style={{stroke: '#4D4D4D'}}
left={0}
left={0}
top={0}
width={10000}
height={10000}
tickTotal={12}
/>
<VerticalGridLines
<VerticalGridLines
style={{stroke: '#4D4D4D'}}
left={0}
left={0}
top={0}
width={10000}
height={10000}
@ -49,12 +75,12 @@ class Graph extends React.Component<any, any> {
title=""
hideTicks
/>
<YAxis
title=""
<YAxis
title=""
hideTicks
/>
{
this.props.dataSeries.map((data: any, index: any) => {
this.generator.getData().map((data: any, index: any) => {
return <LineSeries
className="data-series"
data={data}

View File

@ -1,11 +1,16 @@
import React from 'react';
import { connect } from 'react-redux';
import './../../../css/sidebar/core/singleButton.css';
import Graph from '../../graph/graph';
class SingleButton extends React.Component<any, any> {
toggleSingleMode = () => {
this.props.dispatch({type: 'graph/singleMode'});
//this.props.dispatch({type: 'graph/singleMode'}); //TODO: something about this
if(Graph.instanceList.length > 0) {
this.props.dispatch({type: 'graph/tick'});
Graph.instanceList[0].generator.update();
}
}
render() {

View File

@ -2,8 +2,60 @@ import React from 'react';
import { connect } from 'react-redux';
import MathType from '../../../configuration/enums/mathType';
import './../../../css/sidebar/widgets/measurementsWidget.css';
import GraphStatus from '../../../configuration/enums/graphStatus';
import CMD from '../../../configuration/enums/cmd';
import {Plumber, PlumberArgs} from '../../../util/plumber';
class MeasurementsWidget extends React.Component<any, any> {
timerID: number = 0;
componentDidMount() {
this.timerID = window.setInterval(
() => this.tick(),
1000
);
}
tick() {
if(this.props.graph.currentStatus === GraphStatus.On) {
this.props.dispatch({type: 'measurements/tick'});
this.update();
}
}
update() {
//TODO: unit analysis
let channels = this.props.measurementsWidget.displayChannel as boolean[];
let channelNum = channels.map(v => v ? 1 : 0) as number[];
if(channelNum.reduce((a, b) => a + b) == 0) {
return; //Don't bother C if we don't need to.
}
let maxArgs: PlumberArgs = {
headCheck: () => true,
bodyCheck: (args, bytesRead, body) => {
let decoded = Plumber.getInstance().decodeGetMinMax(args, body);
this.props.dispatch({type: 'measurements/setMax', payload: decoded });
return true;
},
cmd: CMD.CMD_GetMax,
id: 0,
writeData: channelNum
}
let minArgs: PlumberArgs = {
headCheck: () => true,
bodyCheck: (args, bytesRead, body) => {
let decoded = Plumber.getInstance().decodeGetMinMax(args, body);
this.props.dispatch({type: 'measurements/setMin', payload: decoded });
return true;
},
cmd: CMD.CMD_GetMin,
id: 0,
writeData: channelNum
}
Plumber.getInstance().cycle(maxArgs);
Plumber.getInstance().cycle(minArgs);
}
measureChannel = (channelNumber: number) => {
this.props.dispatch({type: 'measurements/selectChannel', payload: channelNumber });
@ -58,31 +110,31 @@ class MeasurementsWidget extends React.Component<any, any> {
</button>
</div>
{this.props.measurementsWidget.displayChannel[0] === true &&
{this.props.measurementsWidget.displayChannel[0] === true &&
<div className="Channel1Measurements-Title">
CH1 Measurements
</div>
}
{this.props.measurementsWidget.displayChannel[0] === true &&
{this.props.measurementsWidget.displayChannel[0] === true &&
<div className="Channel1Measurements">
<label
<label
className="Channel1-MaxLabel"
style={{color: this.props.settings.colors.channel[0]}}>
{MathType.Max}
</label>
<label
<label
className="Channel1-MaxValue"
style={{color: this.props.settings.colors.channel[0]}}>
{this.props.measurementsWidget.max[0].value}
{this.props.measurementsWidget.max[0].unit}
</label>
<div className="ClearBlock"></div>
<label
<label
className="Channel1-MinLabel"
style={{color: this.props.settings.colors.channel[0]}}>
{MathType.Min}
</label>
<label
<label
className="Channel1-MinValue"
style={{color: this.props.settings.colors.channel[0]}}>
{this.props.measurementsWidget.min[0].value}
@ -92,31 +144,31 @@ class MeasurementsWidget extends React.Component<any, any> {
</div>
}
{this.props.measurementsWidget.displayChannel[1] === true &&
{this.props.measurementsWidget.displayChannel[1] === true &&
<div className="Channel2Measurements-Title">
CH2 Measurements
</div>
}
{this.props.measurementsWidget.displayChannel[1] === true &&
{this.props.measurementsWidget.displayChannel[1] === true &&
<div className="Channel2Measurements">
<label
<label
className="Channel2-MaxLabel"
style={{color: this.props.settings.colors.channel[1]}}>
{MathType.Max}
</label>
<label
<label
className="Channel2-MaxValue"
style={{color: this.props.settings.colors.channel[1]}}>
{this.props.measurementsWidget.max[1].value}
{this.props.measurementsWidget.max[1].unit}
</label>
<div className="ClearBlock"></div>
<label
<label
className="Channel2-MinLabel"
style={{color: this.props.settings.colors.channel[1]}}>
{MathType.Min}
</label>
<label
<label
className="Channel2-MinValue"
style={{color: this.props.settings.colors.channel[1]}}>
{this.props.measurementsWidget.min[1].value}
@ -126,31 +178,31 @@ class MeasurementsWidget extends React.Component<any, any> {
</div>
}
{this.props.measurementsWidget.displayChannel[2] === true &&
{this.props.measurementsWidget.displayChannel[2] === true &&
<div className="Channel3Measurements-Title">
CH3 Measurements
</div>
}
{this.props.measurementsWidget.displayChannel[2] === true &&
{this.props.measurementsWidget.displayChannel[2] === true &&
<div className="Channel3Measurements">
<label
<label
className="Channel3-MaxLabel"
style={{color: this.props.settings.colors.channel[2]}}>
{MathType.Max}
</label>
<label
<label
className="Channel3-MaxValue"
style={{color: this.props.settings.colors.channel[2]}}>
{this.props.measurementsWidget.max[2].value}
{this.props.measurementsWidget.max[2].unit}
</label>
<div className="ClearBlock"></div>
<label
<label
className="Channel3-MinLabel"
style={{color: this.props.settings.colors.channel[2]}}>
{MathType.Min}
</label>
<label
<label
className="Channel3-MinValue"
style={{color: this.props.settings.colors.channel[2]}}>
{this.props.measurementsWidget.min[2].value}
@ -160,31 +212,31 @@ class MeasurementsWidget extends React.Component<any, any> {
</div>
}
{this.props.measurementsWidget.displayChannel[3] === true &&
{this.props.measurementsWidget.displayChannel[3] === true &&
<div className="Channel4Measurements-Title">
CH4 Measurements
</div>
}
{this.props.measurementsWidget.displayChannel[3] === true &&
{this.props.measurementsWidget.displayChannel[3] === true &&
<div className="Channel4Measurements">
<label
<label
className="Channel4-MaxLabel"
style={{color: this.props.settings.colors.channel[3]}}>
{MathType.Max}
</label>
<label
<label
className="Channel4-MaxValue"
style={{color: this.props.settings.colors.channel[3]}}>
{this.props.measurementsWidget.max[3].value}
{this.props.measurementsWidget.max[3].unit}
</label>
<div className="ClearBlock"></div>
<label
<label
className="Channel4-MinLabel"
style={{color: this.props.settings.colors.channel[3]}}>
{MathType.Min}
</label>
<label
<label
className="Channel4-MinValue"
style={{color: this.props.settings.colors.channel[3]}}>
{this.props.measurementsWidget.min[3].value}
@ -199,10 +251,11 @@ class MeasurementsWidget extends React.Component<any, any> {
}
}
function mapStateToProps(state: { measurementsWidget: any, settings: any }) {
function mapStateToProps(state: { measurementsWidget: any, settings: any, graph: any }) {
return {
measurementsWidget: state.measurementsWidget,
settings: state.settings
settings: state.settings,
graph: state.graph
};
}

View File

@ -4,6 +4,9 @@ import './../../../css/sidebar/widgets/triggerWidget.css';
import VoltageUnit from '../../../configuration/enums/voltageUnit';
import TriggerType from '../../../configuration/enums/triggerType';
import CMD from '../../../configuration/enums/cmd';
import {Plumber, PlumberArgs} from '../../../util/plumber';
class TriggerWidget extends React.Component<any, any> {
// Trigger Channel
@ -16,25 +19,48 @@ class TriggerWidget extends React.Component<any, any> {
}
changeChannel = (channelNumber: number) => {
let args: PlumberArgs = {
headCheck: () => true,
bodyCheck: () => true,
cmd: CMD.CMD_SetTriggerCh,
id: 0,
writeData: [channelNumber, 0]
};
Plumber.getInstance().cycle(args);
this.props.dispatch({type: 'trigger/changeChannel', payload: channelNumber})
}
// Trigger Type
changeTriggerType = (triggerType: TriggerType) => {
let edgeNum = (triggerType == TriggerType.RisingEdge) ? 1 : 2;
let args: PlumberArgs = {
headCheck: () => true,
bodyCheck: () => true,
cmd: CMD.CMD_SetEdgeType,
id: 0,
writeData: [edgeNum, 0]
}
Plumber.getInstance().cycle(args);
this.props.dispatch({type: 'trigger/changeTriggerType', payload: triggerType});
}
// Trigger Level
increaseTriggerLevel = () => {
//TODO: Plumber call
//(TRIGGER LEVEL (V))/((VOLTAGE RANGExDIVISIONS)/256)
this.props.dispatch({type: 'trigger/increaseTriggerLevelValue'});
}
decreaseTriggerLevel = () => {
//TODO: Plumber call
//(TRIGGER LEVEL (V))/((VOLTAGE RANGExDIVISIONS)/256)
this.props.dispatch({type: 'trigger/decreaseTriggerLevelValue'});
}
// Trigger Level Unit
changeTriggerLevelUnit = (voltageUnit: VoltageUnit) => {
//TODO: unit analysis, plumber call
//(TRIGGER LEVEL (V))/((VOLTAGE RANGExDIVISIONS)/256)
this.props.dispatch({type: 'trigger/changeTriggerLevelUnit', payload: voltageUnit});
}
@ -115,19 +141,19 @@ class TriggerWidget extends React.Component<any, any> {
Trigger Level
</div>
<div className="TriggerWidgetAdjustTriggerLevelValue">
<button
<button
className="MinusButton"
onClick={() => this.decreaseTriggerLevel()}>
-
</button>
<label
<label
className="AdjustChannelBlockValue"
style={{color: this.props.settings.colors.channel[this.props.triggerWidget.triggerChannel-1]}}
>
{this.props.triggerWidget.triggerLevel[this.props.triggerWidget.triggerChannel-1].value.toString()}
{this.props.triggerWidget.triggerLevel[this.props.triggerWidget.triggerChannel-1].unit}
</label>
<button
<button
className="PlusButton"
onClick={() => this.increaseTriggerLevel()}>
+
@ -172,7 +198,7 @@ class TriggerWidget extends React.Component<any, any> {
</label>
</button>
</div>
</div>
)
}

View File

@ -0,0 +1,35 @@
enum CMD {
//Data commands
CMD_GetData1 = 0x01,
CMD_GetData2 = 0x02,
CMD_GetData3 = 0x03,
CMD_GetData4 = 0x04,
CMD_GetMin = 0x05,
CMD_GetMax = 0x06,
//Demo commands
CMD_SetFile = 0x11,
CMD_RampDemo = 0x1F,
//Get Config commands
CMD_GetWindowSize = 0x21,
CMD_GetCh = 0x22,
CMD_GetLevel = 0x23,
CMD_GetTriggerCh = 0x24,
CMD_GetEdgeType = 0x25,
//Set Config commands
CMD_SetWindowSize = 0x31,
CMD_SetCh = 0x32,
CMD_SetLevel = 0x33,
CMD_SetTriggerCh = 0x34,
CMD_SetEdgeType = 0x35,
CMD_SetBandwidth = 0x36,
CMD_SetVerticalScaling = 0x37,
CMD_SetVerticalOffset = 0x38,
CMD_SetHorizontalOffset = 0x39,
CMD_SetCoupling = 0x3A,
CMD_SetMath = 0x3F
}
export default CMD;

View File

@ -4,7 +4,8 @@ const GraphInitialState = {
currentStatus: GraphStatus.On,
singleMode: false,
xDomain: [0,0],
yDomain: [0,0]
yDomain: [0,0],
tickCount: 0
};
export default GraphInitialState;

View File

@ -30,27 +30,28 @@ const MeasurementsWidgetInitialState = {
}
],
min: [
{
{
value: 10,
unit: VoltageUnit.MicroVolt,
display: false
},
{
{
value: 20,
unit: VoltageUnit.NanoVolt,
display: false
},
{
{
value: 30,
unit: VoltageUnit.MilliVolt,
display: false
},
{
{
value: 40,
unit: VoltageUnit.Volt,
display: false
}
]
],
tickCount: 0
};
export default MeasurementsWidgetInitialState;

View File

@ -16,6 +16,11 @@ export default function(state = GraphInitialState, action: {type: any, payload:
currentStatus: GraphStatus.Off,
singleMode: !state.singleMode
};
case "graph/tick":
return {
...state,
tickCount: state.tickCount + 1
}
default:
return state;
}

View File

@ -1,6 +1,7 @@
import MeasurementsWidgetInitialState from '../../initialStates/measurementsWidgetInitialState';
import { MaxMinResult } from '../../../util/plumber';
export default function(state = MeasurementsWidgetInitialState, action: {type: any, payload: any}) {
export default function(state = MeasurementsWidgetInitialState, action: {type: any, payload: any}) {
var tmp;
switch(action.type) {
@ -12,6 +13,33 @@ export default function(state = MeasurementsWidgetInitialState, action: {type: a
...state,
displayChannel: tmp
};
case "measurements/setMax":
//TODO: unit analysis
let setMaxPayload = action.payload as MaxMinResult[];
tmp = state.max
for(let maxItem of setMaxPayload) {
tmp[maxItem.ch - 1].value = maxItem.y;
}
return {
...state,
max: tmp
}
case "measurements/setMin":
//TODO: unit analysis
let setMinPayload = action.payload as MaxMinResult[];
tmp = state.min
for(let minItem of setMinPayload) {
tmp[minItem.ch - 1].value = minItem.y;
}
return {
...state,
min: tmp
}
case "measurements/tick":
return {
...state,
tickCount: state.tickCount + 1
}
default:
return state;
}

View File

@ -0,0 +1,24 @@
import VoltageUnit from '../configuration/enums/voltageUnit';
import TimeUnit from '../configuration/enums/timeUnit';
function convertVoltage(x: number, from: VoltageUnit, to: VoltageUnit) {
let power = {
[VoltageUnit.NanoVolt]: -9,
[VoltageUnit.MicroVolt]: -6,
[VoltageUnit.MilliVolt]: -3,
[VoltageUnit.Volt]: 0
}
return x * Math.pow(10, power[from] - power[to]);
}
function convertTime(x: number, from: TimeUnit, to: TimeUnit) {
let power = {
[TimeUnit.NanoSecond]: -9,
[TimeUnit.MicroSecond]: -6,
[TimeUnit.MilliSecond]: -3,
[TimeUnit.Second]: 0
}
return x * Math.pow(10, power[from] - power[to]);
}
export {convertVoltage, convertTime}

View File

@ -1,31 +1,4 @@
export enum CMD {
//Data commands
CMD_GetData1 = 0x01,
CMD_GetData2 = 0x02,
CMD_GetData3 = 0x03,
CMD_GetData4 = 0x04,
CMD_GetMin = 0x05,
CMD_GetMax = 0x06,
//Demo commands
CMD_SetFile = 0x11,
CMD_RampDemo = 0x1F,
//Get Config commands
CMD_GetWindowSize = 0x21,
CMD_GetCh = 0x22,
CMD_GetLevel = 0x23,
CMD_GetTriggerCh = 0x24,
CMD_GetEdgeType = 0x25,
//Set Config commands
CMD_SetWindowSize = 0x31,
CMD_SetCh = 0x32,
CMD_SetLevel = 0x33,
CMD_SetTriggerCh = 0x34,
CMD_SetEdgeType = 0x35,
CMD_SetMath = 0x3F
}
import CMD from '../configuration/enums/cmd';
export enum SetMathOp {
SetMath_None = 0,
@ -33,6 +6,12 @@ export enum SetMathOp {
SetMath_Minus = 2,
}
export interface MaxMinResult {
ch: number,
x: number,
y: number
}
export interface PlumberArgs {
headCheck: (args: PlumberArgs, head: Uint16Array) => boolean;
bodyCheck: (args: PlumberArgs, bytesRead: number, body: Int8Array) => boolean;
@ -132,9 +111,16 @@ export class Plumber {
return [lhsChan, rhsChan, op, 0];
}
public decodeGetMinMax(a: Int8Array) {
var a64u = new BigUint64Array(a.buffer);
var a64s = new BigInt64Array(a.buffer);
return {x: Number(a64u[0]), y: Number(a64s[1])};
public decodeGetMinMax(args: PlumberArgs, a: Int8Array) {
let maxCh = 4;
let a64u = new BigUint64Array(a.buffer);
let a64s = new BigInt64Array(a.buffer);
var res: MaxMinResult[] = [];
for(var i = 0; i < args.writeData.length; i++) {
if(args.writeData[i] != 0) {
res.push({ch: i + 1, x: Number(a64u[i]), y: Number(a64s[i + maxCh])});
}
}
return res;
}
}

View File

@ -1,91 +0,0 @@
import { CMD, PlumberArgs, Plumber } from './plumber';
class TestConf {
getEdgeArgs: PlumberArgs;
setEdgeArgs: PlumberArgs;
getWinArgs: PlumberArgs;
setWinArgs: PlumberArgs;
getMinArgs: PlumberArgs;
getMaxArgs: PlumberArgs;
constructor() {
this.getEdgeArgs = {
headCheck: (a, head) => true,
bodyCheck: (a, bytesRead, body) => {
console.log("C++ edge type: " + body[0]);
return true;
},
cmd: CMD.CMD_GetEdgeType,
id: 0,
writeData: [0, 0]
}
this.setEdgeArgs = {
headCheck: () => true,
bodyCheck: () => true,
cmd: CMD.CMD_SetEdgeType,
id: 0,
writeData: [2, 0]
}
this.getWinArgs = {
headCheck: () => true,
bodyCheck: (args, bytesRead, body) => {
var body32 = new Uint32Array(body.buffer);
console.log(body32);
return true;
},
cmd: CMD.CMD_GetWindowSize,
id: 0,
writeData: [0, 0]
}
this.setWinArgs = {
headCheck: () => {
console.log("I set win");
return true;
},
bodyCheck: () => true,
cmd: CMD.CMD_SetWindowSize,
id: 0,
writeData: new Int8Array((new Uint32Array([20])).buffer)
}
this.getMinArgs = {
headCheck: () => true,
bodyCheck: (args, bytesRead, body) => {
console.log(Plumber.getInstance().decodeGetMinMax(body));
return true;
},
cmd: CMD.CMD_GetMin,
id: 0,
writeData: [3, 0]
}
this.getMaxArgs = {
headCheck: () => true,
bodyCheck: (args, bytesRead, body) => {
console.log(Plumber.getInstance().decodeGetMinMax(body));
return true;
},
cmd: CMD.CMD_GetMax,
id: 0,
writeData: [3, 0]
}
}
update(get: boolean) {
/*if(get) {
Plumber.getInstance().cycle(this.getWinArgs);
}
else {
Plumber.getInstance().cycle(this.setWinArgs);
}*/
Plumber.getInstance().cycle(this.getMaxArgs);
}
}
export default TestConf;

View File

@ -1,4 +1,5 @@
import { CMD, PlumberArgs, Plumber, SetMathOp } from './plumber';
import CMD from '../configuration/enums/cmd';
import { PlumberArgs, Plumber, SetMathOp } from './plumber';
class Range {
dataMin: number = 0;
@ -111,6 +112,7 @@ class TestPoints {
getData() {
var chMax = this.effectiveChCount();
console.log(this.scope_data);
return this.scope_data.slice(0, chMax);
}
}