Skip to content

Commit

Permalink
XMP should be fully functional
Browse files Browse the repository at this point in the history
  • Loading branch information
integralfx authored Jul 2, 2019
1 parent 2a5d8f7 commit 3f82e2c
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 54 deletions.
162 changes: 108 additions & 54 deletions SPDEditorGUI.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
Expand All @@ -12,20 +10,23 @@

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SPDEditorGUI extends JFrame {
private JButton btnXMPset;
private JButton btnSet, btnXMPset;
private JComboBox<Integer> cboXMPNum;
private JLabel lblSPDFile, lblXMP;
private JRadioButton rdoTime, rdoCycles, rdoXMPTime, rdoXMPCycles;
private JSpinner spnXMPVoltage;
private JTabbedPane tabbedPane;
private JTextField txtFrequencyns, txtFrequency, txtXMPmtbDividend, txtXMPmtbDivisor, txtXMPmtbns,
txtXMPFrequencyValue, txtXMPFrequencyns, txtXMPFrequency;
private LinkedHashMap<String, TextFieldPair> nameTextFieldMap, XMPnameTextFieldMap;
private LinkedHashMap<String, TextFieldPair> timingsTextFieldMap, XMPtimingsTextFieldMap;
private LinkedHashMap<Integer, JCheckBox> clCheckBoxMap, XMPclCheckBoxMap;
private LinkedHashMap<String, JCheckBox> voltageCheckBoxMap;
private SPDEditor spd;
private final String VERSION = "Version 1.0.0", DISCORD = "∫ntegral#7834";
private XMP xmp;

public static void main(String[] args) {
Expand All @@ -39,7 +40,10 @@ public SPDEditorGUI() {

tabbedPane = new JTabbedPane();
addSPDTab();
setSPDControlsEnabled(false);
addXMPTab();
setXMPControlsEnabled(false);
addAboutTab();
add(tabbedPane);

setDefaultCloseOperation(EXIT_ON_CLOSE);
Expand All @@ -58,19 +62,8 @@ private void addSPDTab() {
panel.add(lblSPDFile);
panelSPD.add(panel);

// TODO: Only allow the user to select certain frequencies
Frequency[] frequencies = {
new Frequency(1200/3.0), // 400
new Frequency(1600/3.0), // 533.33...
new Frequency(2000/3.0), // 666.66...
new Frequency(2400/3.0), // 800
new Frequency(2800/3.0), // 933.33...
new Frequency(3200/3.0) // 1066.66...
};
panel = new JPanel();
panel.add(new JLabel("Frequency:"));
//JComboBox<Frequency> cboFrequencies = new JComboBox<>(frequencies);
//panel.add(cboFrequencies);
txtFrequency = new JTextField(5);
txtFrequency.addActionListener(new ActionListener() {
@Override
Expand All @@ -86,7 +79,7 @@ public void actionPerformed(ActionEvent e) {
double f = Double.valueOf(s);
if (f < 400) valid = false;
else {
txtFrequencyns.setText(String.format("%.3f", 1000/f));
txtFrequencyns.setText(String.format("%.3f ns", 1000/f));
/*
* Timings are calculated from the cycle time (ns),
* which don't change when changing frequency.
Expand Down Expand Up @@ -125,10 +118,10 @@ else if (rdoTime.isSelected()) {
panel = new JPanel();
rdoCycles = new JRadioButton("Scale from cycles (ticks)");
rdoCycles.setToolTipText("Keeps the same amount of cycles in ticks when changing frequency.");
rdoCycles.setSelected(true);
panel.add(rdoCycles);
rdoTime = new JRadioButton("Scale from time (ns)");
rdoTime.setToolTipText("Keeps the same absolute time in ns when changing frequency.");
rdoTime.setSelected(true);
panel.add(rdoTime);
ButtonGroup group = new ButtonGroup();
group.add(rdoCycles);
Expand Down Expand Up @@ -186,7 +179,7 @@ public void actionPerformed(ActionEvent e) {
"tCL", "tRCD", "tRP", "tRAS", "tRC","tRFC",
"tRRD", "tFAW", "tWR", "tWTR", "tRTP"
};
nameTextFieldMap = new LinkedHashMap<>();
timingsTextFieldMap = new LinkedHashMap<>();
for (String name : timingNames) {
panel = new JPanel();

Expand Down Expand Up @@ -231,22 +224,22 @@ else if (name.equals("tCL")) {
}
});
panel.add(txtTicks);
JTextField txtns = new JTextField(5);
JTextField txtns = new JTextField(6);
txtns.setEditable(false);
panel.add(txtns);
timingsPanel.add(panel);

nameTextFieldMap.put(name, new TextFieldPair(txtTicks, txtns));
timingsTextFieldMap.put(name, new TextFieldPair(txtTicks, txtns));
}
panel = new JPanel();
JButton btnSet = new JButton("Set");
btnSet = new JButton("Set");
btnSet.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (spd == null)
showErrorMsg("Please open an SPD file.");

for (Map.Entry<String, TextFieldPair> entry : nameTextFieldMap.entrySet()) {
for (Map.Entry<String, TextFieldPair> entry : timingsTextFieldMap.entrySet()) {
JTextField txt = entry.getValue().left;
String name = entry.getKey(),
input = txt.getText();
Expand Down Expand Up @@ -284,7 +277,10 @@ else if (name.equals("tCL")) {
timingsPanel.setBorder(BorderFactory.createTitledBorder(b, "Timings"));
panelSPD.add(timingsPanel);

tabbedPane.addTab("SPD", panelSPD);
// default layout manager is FlowLayout, which will only use as much space as necessary
panel = new JPanel();
panel.add(panelSPD);
tabbedPane.addTab("SPD", panel);
}

private void addXMPTab() {
Expand All @@ -307,8 +303,10 @@ public void actionPerformed(ActionEvent e) {
panel = new JPanel();
panel.add(new JLabel("MTB:"));
txtXMPmtbDividend = new JTextField(2);
txtXMPmtbDividend.setToolTipText("Dividend for MTB.");
panel.add(txtXMPmtbDividend);
txtXMPmtbDivisor = new JTextField(2);
txtXMPmtbDivisor.setToolTipText("Divisor for MTB.");
panel.add(txtXMPmtbDivisor);
txtXMPmtbns = new JTextField(5);
txtXMPmtbns.setEditable(false);
Expand Down Expand Up @@ -342,6 +340,7 @@ else if (xmp == null)
panel = new JPanel();
panel.add(new JLabel("Frequency:"));
txtXMPFrequencyValue = new JTextField(2);
txtXMPFrequencyValue.setToolTipText("This value is multiplied by the MTB to derive the frequency.");
txtXMPFrequencyValue.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Expand All @@ -357,22 +356,22 @@ else if (xmp == null)
}
});
panel.add(txtXMPFrequencyValue);
txtXMPFrequency = new JTextField(7);
txtXMPFrequency.setEditable(false);
panel.add(txtXMPFrequency);
txtXMPFrequencyns = new JTextField(5);
txtXMPFrequencyns.setEditable(false);
panel.add(txtXMPFrequencyns);
txtXMPFrequency = new JTextField(7);
txtXMPFrequency.setEditable(false);
panel.add(txtXMPFrequency);
panelXMP.add(panel);

panel = new JPanel();
rdoXMPTime = new JRadioButton("Scale from time (ns)");
rdoXMPTime.setToolTipText("Keeps the same absolute time in ns when changing frequency.");
rdoXMPTime.setSelected(true);
panel.add(rdoXMPTime);
rdoXMPCycles = new JRadioButton("Scale from cycles (ticks)");
rdoXMPCycles.setToolTipText("Keeps the same amount of cycles in ticks when changing frequency.");
rdoXMPCycles.setSelected(true);
panel.add(rdoXMPCycles);
rdoXMPTime = new JRadioButton("Scale from time (ns)");
rdoXMPTime.setToolTipText("Keeps the same absolute time in ns when changing frequency.");
panel.add(rdoXMPTime);
ButtonGroup group = new ButtonGroup();
group.add(rdoXMPTime);
group.add(rdoXMPCycles);
Expand All @@ -386,6 +385,14 @@ else if (xmp == null)
SpinnerListModel model = new SpinnerListModel(voltages.toArray(new String[0]));
spnXMPVoltage = new JSpinner(model);
((JSpinner.DefaultEditor)spnXMPVoltage.getEditor()).getTextField().setEditable(false);
spnXMPVoltage.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
XMP.Profile selected = xmp.getProfile(cboXMPNum.getSelectedIndex());
double value = Double.valueOf((String)spnXMPVoltage.getValue());
selected.setVoltage((int)Math.round(100 * value));
}
});
panel.add(spnXMPVoltage);
panelXMP.add(panel);

Expand Down Expand Up @@ -429,7 +436,7 @@ else if (spd.getXMP() == null)
"tCL", "tRCD", "tRP", "tRAS", "tRC","tRFC",
"tRRD", "tFAW", "tWR", "tWTR", "tRTP", "tCWL", "tREFI"
};
XMPnameTextFieldMap = new LinkedHashMap<>();
XMPtimingsTextFieldMap = new LinkedHashMap<>();
for (String name : timingNames) {
panel = new JPanel();

Expand Down Expand Up @@ -486,7 +493,7 @@ else if (name.equals("tCL")) {
panel.add(txtns);
timingsPanel.add(panel);

XMPnameTextFieldMap.put(name, new TextFieldPair(txtTicks, txtns));
XMPtimingsTextFieldMap.put(name, new TextFieldPair(txtTicks, txtns));
}
panel = new JPanel();
btnXMPset = new JButton("Set");
Expand All @@ -498,7 +505,7 @@ public void actionPerformed(ActionEvent e) {
else if (spd.getXMP() == null)
showErrorMsg("No XMPs found.");
else {
for (Map.Entry<String, TextFieldPair> entry : XMPnameTextFieldMap.entrySet()) {
for (Map.Entry<String, TextFieldPair> entry : XMPtimingsTextFieldMap.entrySet()) {
JTextField txt = entry.getValue().left;
String name = entry.getKey(),
input = txt.getText();
Expand Down Expand Up @@ -543,6 +550,27 @@ else if (name.equals("tCL")) {
tabbedPane.addTab("XMP", panelXMP);
}

private void addAboutTab() {
JPanel panelAbout = new JPanel();
panelAbout.setLayout(new BoxLayout(panelAbout, BoxLayout.Y_AXIS));

JPanel panel = new JPanel();
panel.add(new JLabel(VERSION));
panelAbout.add(panel);

panel = new JPanel();
panel.add(new JLabel("Discord:"));
JTextField txtDiscord = new JTextField(DISCORD);
txtDiscord.setEditable(false);
panel.add(txtDiscord);
panelAbout.add(panel);

// wrap in a GridBagLayout to centre content
panel = new JPanel(new GridBagLayout());
panel.add(panelAbout);
tabbedPane.addTab("About", panel);
}

private void addMenuBar() {
JMenuBar menuBar = new JMenuBar();

Expand Down Expand Up @@ -621,8 +649,10 @@ private void updateSPDTab() {
if (spd == null) return;

SwingUtilities.invokeLater(() -> {
setSPDControlsEnabled(true);

double f = spd.getFrequency();
txtFrequencyns.setText(String.format("%.3f", 1000/f));
txtFrequencyns.setText(String.format("%.3f ns", 1000/f));
txtFrequency.setText(String.format("%.2f", f));

LinkedHashMap<String, Boolean> voltages = spd.getVoltages();
Expand All @@ -645,10 +675,10 @@ private void updateSPDTab() {
private void updateSPDTimingsText() {
SwingUtilities.invokeLater(() -> {
for (Map.Entry<String, Integer> e : spd.getTimings().entrySet()) {
if (nameTextFieldMap.containsKey(e.getKey())) {
TextFieldPair pair = nameTextFieldMap.get(e.getKey());
if (timingsTextFieldMap.containsKey(e.getKey())) {
TextFieldPair pair = timingsTextFieldMap.get(e.getKey());
pair.left.setText(e.getValue().toString());
pair.right.setText(String.format("%.3f", 1000/spd.getFrequency()*e.getValue()));
pair.right.setText(String.format("%.3f ns", 1000/spd.getFrequency()*e.getValue()));
}
}
});
Expand Down Expand Up @@ -700,18 +730,46 @@ private void updateXMPTab() {
});
}

private void setSPDControlsEnabled(boolean enable) {
SwingUtilities.invokeLater(() -> {
txtFrequency.setEnabled(enable);
rdoCycles.setEnabled(enable);
rdoTime.setEnabled(enable);

for (Map.Entry<String, JCheckBox> e : voltageCheckBoxMap.entrySet())
e.getValue().setEnabled(enable);

for (Map.Entry<Integer, JCheckBox> e : clCheckBoxMap.entrySet())
e.getValue().setEnabled(enable);

for (Map.Entry<String, TextFieldPair> e : timingsTextFieldMap.entrySet())
e.getValue().left.setEnabled(enable);

btnSet.setEnabled(enable);
});
}

private void setXMPControlsEnabled(boolean enable) {
SwingUtilities.invokeLater(() -> {
cboXMPNum.setEnabled(enable);

txtXMPmtbDividend.setEnabled(enable);
txtXMPmtbDivisor.setEnabled(enable);
txtXMPmtbDividend.setEnabled(enable);

txtXMPFrequencyValue.setEnabled(enable);
txtXMPFrequencyns.setEnabled(enable);
txtXMPFrequency.setEnabled(enable);

rdoXMPTime.setEnabled(enable);
rdoXMPCycles.setEnabled(enable);

spnXMPVoltage.setEnabled(enable);

for (Map.Entry<Integer, JCheckBox> e : XMPclCheckBoxMap.entrySet())
e.getValue().setEnabled(enable);

for (Map.Entry<String, TextFieldPair> e : XMPnameTextFieldMap.entrySet()) {
for (Map.Entry<String, TextFieldPair> e : XMPtimingsTextFieldMap.entrySet()) {
e.getValue().left.setEnabled(enable);
e.getValue().right.setEnabled(enable);
}
Expand All @@ -727,7 +785,15 @@ private void updateXMPFrequencyText() {
int input = Integer.valueOf(txtXMPFrequencyValue.getText()),
num = cboXMPNum.getSelectedIndex();
XMP.Profile selected = xmp.getProfiles()[num];
selected.settCKmin((byte)input);

if (rdoCycles.isSelected()) {
LinkedHashMap<String, Integer> t = selected.getTimings();
selected.settCKmin((byte)input);
selected.setTimings(t);
}
else if (rdoTime.isSelected()) {
selected.settCKmin((byte)input);
}

double freqns = input * selected.getMTB().getTime();
txtXMPFrequency.setText(String.format("%.2f MHz", 1000 / freqns));
Expand All @@ -744,8 +810,8 @@ private void updateXMPTimingsText() {
if (selected == null) return;

for (Map.Entry<String, Integer> e : selected.getTimings().entrySet()) {
if (XMPnameTextFieldMap.containsKey(e.getKey())) {
TextFieldPair pair = XMPnameTextFieldMap.get(e.getKey());
if (XMPtimingsTextFieldMap.containsKey(e.getKey())) {
TextFieldPair pair = XMPtimingsTextFieldMap.get(e.getKey());
double time = 1000 / selected.getFrequency() * e.getValue();
pair.left.setText(e.getValue().toString());
pair.right.setText(String.format("%.3f ns", time));
Expand Down Expand Up @@ -779,16 +845,4 @@ public TextFieldPair(JTextField l, JTextField r) {
left = l;
right = r;
}
}

class Frequency {
public final double frequency;
public Frequency(double f) {
frequency = f;
}

@Override
public String toString() {
return String.format("%.2f", frequency);
}
}
5 changes: 5 additions & 0 deletions XMP.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public XMP(byte[] bytes) throws IllegalArgumentException {

public Profile[] getProfiles() { return profile; }

public Profile getProfile(int index) {
if (index < 0 || index > 1) return null;
return profile[index];
}

public void setProfile(int index, Profile p) {
if (index >= 0 && index <= 1 && profile != null) {
profile[index] = p;
Expand Down
Binary file modified spdeditor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 3f82e2c

Please sign in to comment.