Skip to content
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
8 changes: 8 additions & 0 deletions src/org/openlcb/cdi/CdiRep.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ public static interface IntegerRep extends Item {
public int getSliderDivisions();
}

public static interface FloatRep extends Item {
public double getDefault();
public double getMin();
public double getMax();

public int getSize();
}

public static interface BitRep extends Item {
public boolean getDefault();

Expand Down
74 changes: 74 additions & 0 deletions src/org/openlcb/cdi/impl/ConfigRepresentation.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.Reader;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
Expand All @@ -24,6 +25,7 @@
import org.openlcb.cdi.jdom.JdomCdiReader;
import org.openlcb.cdi.jdom.XmlHelper;
import org.openlcb.implementations.MemoryConfigurationService;
import org.openlcb.implementations.throttle.Float16;

/**
* Maintains a parsed cache of the CDI config of a remote node. Responsible for fetching the CDI,
Expand Down Expand Up @@ -249,6 +251,8 @@ private long processGroup(String baseName, int segment, List<CdiRep.Item> items,
entry = new GroupEntry(name, (CdiRep.Group) it, segment, origin);
} else if (it instanceof CdiRep.IntegerRep) {
entry = new IntegerEntry(name, (CdiRep.IntegerRep) it, segment, origin);
} else if (it instanceof CdiRep.FloatRep) {
entry = new FloatEntry(name, (CdiRep.FloatRep) it, segment, origin);
} else if (it instanceof CdiRep.EventID) {
entry = new EventEntry(name, (CdiRep.EventID) it, segment, origin);
} else if (it instanceof CdiRep.StringRep) {
Expand Down Expand Up @@ -305,6 +309,8 @@ public void visitEntry(CdiEntry e) {
visitString((StringEntry) e);
} else if (e instanceof IntegerEntry) {
visitInt((IntegerEntry) e);
} else if (e instanceof FloatEntry) {
visitFloat((FloatEntry) e);
} else if (e instanceof EventEntry) {
visitEvent((EventEntry) e);
} else if (e instanceof ActionButtonEntry) {
Expand Down Expand Up @@ -335,6 +341,10 @@ public void visitInt(IntegerEntry e) {
visitLeaf(e);
}

public void visitFloat(FloatEntry e) {
visitLeaf(e);
}

public void visitEvent(EventEntry e) {
visitLeaf(e);
}
Expand Down Expand Up @@ -620,6 +630,70 @@ public void setValue(long value) {
}
}

/**
* Represents a float variable.
*/
public class FloatEntry extends CdiEntry {
public CdiRep.FloatRep rep;

FloatEntry(String name, CdiRep.FloatRep rep, int segment, long origin) {
this.key = name;
this.space = segment;
this.origin = origin;
this.rep = rep;
this.size = rep.getSize();
}

@Override
public CdiRep.Item getCdiItem() {
return rep;
}

@Override
protected void updateVisibleValue() {
lastVisibleValue = Double.toString(getValue());
}

public double getValue() {
MemorySpaceCache cache = getCacheForSpace(space);
byte[] b = cache.read(origin, size);
if (b == null) return 0.0;
switch (size) {
case 8:
return ByteBuffer.wrap(b).getDouble();
case 4:
return ByteBuffer.wrap(b).getFloat();
case 2:
Float16 f = new Float16(b[0], b[1]);
return f.getFloat();

}
return 0.0;
}

public void setValue(double value) {
MemorySpaceCache cache = getCacheForSpace(space);
byte[] bytes;
switch (size) {
case 8:
bytes = new byte[8];
ByteBuffer.wrap(bytes).putDouble(value);
cache.write(origin, bytes, this);
break;
case 4:
bytes = new byte[4];
ByteBuffer.wrap(bytes).putFloat((float)value);
cache.write(origin, bytes, this);
break;
case 2:
Float16 f = new Float16(value, value>=0.0);
bytes = new byte[]{f.getByte1(), f.getByte2()};
cache.write(origin, bytes, this);
break;
}
}
}

/**
* Represents an event variable.
*/
Expand Down
80 changes: 80 additions & 0 deletions src/org/openlcb/cdi/jdom/JdomCdiRep.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ public java.util.List<CdiRep.Item> getItems() {
case "int":
list.add(new IntRep(element));
break;
case "float":
list.add(new FloatRep(element));
break;
case "eventid":
list.add(new EventID(element));
break;
Expand Down Expand Up @@ -364,6 +367,7 @@ int indexOfFirstTrailingDigit(String input) {
public static class EventID extends Item implements CdiRep.EventID {
EventID(Element e) { super(e); }
}

public static class IntRep extends Item implements CdiRep.IntegerRep {
IntRep(Element e) { super(e); }

Expand Down Expand Up @@ -470,6 +474,82 @@ public int getSliderDivisions() {

}


public static class FloatRep extends Item implements CdiRep.FloatRep {
FloatRep(Element e) { super(e); }

@Override
public double getDefault() {
Element target = e.getChild("default");
if (target != null) {
String text = target.getTextNormalize();
try {
return Double.valueOf(text);
} catch (NumberFormatException ex) {
logger.severe("Invalid content for default element: "+text);
// and return the default value from length
}
}
// otherwise, return default value of 0
return 0.0;
}

@Override
public double getMin() {
Element target = e.getChild("min");
if (target != null) {
String text = target.getTextNormalize();
try {
return Double.valueOf(text);
} catch (NumberFormatException ex) {
logger.severe("Invalid content for min element: "+text);
// and return the default value
}
}
// otherwise, return default
return 0.0;
}

@Override
public double getMax() {
Element target = e.getChild("max");
if (target != null) {
String text = target.getTextNormalize();
try {
return Integer.valueOf(text);
} catch (NumberFormatException ex) {
logger.severe("Invalid content for max element: "+text);
// and return the value computed from length
}
}
// otherwise, return value computed from size
switch (getSize()) {
case 8:
return Double.MAX_VALUE-1.0;
case 4:
return Float.MAX_VALUE-1.0;
case 2:
// Float16
return 65504.0-1.0;
default:
logger.severe("Invalid size when finding default max: "+getSize());
return 1.0;
}
}

@Override
public int getSize() {
Attribute a = e.getAttribute("size");
try {
if (a == null) {
return 1;
} else {
return a.getIntValue(); // this doesn't check value for validity, that's the Schema's job
}
} catch (org.jdom2.DataConversionException e1) { return 0; }
}
}

public static class UnknownRep extends Item implements CdiRep.UnknownRep {
UnknownRep(Element e) { super(e); }

Expand Down
97 changes: 97 additions & 0 deletions src/org/openlcb/cdi/swing/CdiPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,11 @@ public void visitInt(ConfigRepresentation.IntegerEntry e) {
writeEntry(e.key, Long.toString(e.getValue()));
}

@Override
public void visitFloat(ConfigRepresentation.FloatEntry e) {
writeEntry(e.key, Double.toString(e.getValue()));
}

@Override
public void visitEvent(ConfigRepresentation.EventEntry e) {
writeEntry(e.key, org.openlcb.Utilities.toHexDotsString(e.getValue
Expand Down Expand Up @@ -1390,6 +1395,12 @@ public void visitInt(ConfigRepresentation.IntegerEntry e) {
super.visitInt(e);
}

@Override
public void visitFloat(ConfigRepresentation.FloatEntry e) {
currentLeaf = new FloatPane(e);
super.visitFloat(e);
}

@Override
public void visitEvent(ConfigRepresentation.EventEntry e) {
currentLeaf = new EventIdPane(e);
Expand Down Expand Up @@ -2567,6 +2578,92 @@ void updateWriteButton() {
}
}

private class FloatPane extends EntryPane {
JTextField textField = null;
private final ConfigRepresentation.FloatEntry entry;


FloatPane(ConfigRepresentation.FloatEntry e) {
super(e, "Float");
this.entry = e;

// display an entry box
textField = new JTextField(24) {
public java.awt.Dimension getMaximumSize() {
return getPreferredSize();
}
};
textComponent = textField;
textField.setToolTipText("Float from "
+entry.rep.getMin()+" to "+entry.rep.getMax()
+" ("+entry.size+" bytes)");

init();
}

@Override
protected void writeDisplayTextToNode() {
double value = Double.parseDouble(textField.getText());
entry.setValue(value);
_changeMade = true;
notifyTabColorRefresh();
}

@Override
protected void updateDisplayText(@NonNull String value) {
textField.setText(value);
}

@NonNull
@Override
protected String getDisplayText() {
String s = textField.getText();
return s == null ? "" : s;
}

/**
* Get the current value as a numerical String.
* Usually, this is the display text, but in the case of a
* a map it's the integer value of the
* current selection.
* @return Current value for storage as a String.
*/
@NonNull
protected String getCurrentValue() {
String s = (String) textField.getText();
return s == null ? "" : s;
}

boolean isDataInvalid() {
try {
double value = Double.valueOf(getCurrentValue());
if (value >= entry.rep.getMin() && value <= entry.rep.getMax() ) {
return false;
} else {
return true;
}
} catch (NumberFormatException ex) {
return true;
}
}

/**
* check that the current (String) value is
* valid and within the min and max range.
* Disable/Enable write button as appropriate.
*/
@Override
void updateWriteButton() {
if (writeButton == null) {
// skip these until the write button has been created
return;
}

writeButton.setEnabled( ! isDataInvalid());

}
}

// Define font to be used in certain types of StringPanes
Font textAreaFont;
{
Expand Down
Loading