public TimingEnvironmentDialog(Frame f) {
   super(f, "Timing Environment");
   parent = f;
   Panel infoPanel = new Panel(new GridLayout(0, 2, 0, 0));
   add(infoPanel, BorderLayout.CENTER);
   infoPanel.add(new Label("PXLab High Resolution Timer:", Label.RIGHT));
   infoPanel.add(new Label(HiresClock.getTimerName(), Label.LEFT));
   int cpg = HiresClock.getChecksPerTimerGranularityStep();
   infoPanel.add(new Label("Resolution:", Label.RIGHT));
   infoPanel.add(
       new Label(
           ((cpg > 1) ? "better than " : "")
               + String.valueOf(HiresClock.getTimerGranularity())
               + " ms",
           Label.LEFT));
   infoPanel.add(new Label("Checks per Step:", Label.RIGHT));
   infoPanel.add(new Label(String.valueOf(cpg), Label.LEFT));
   infoPanel.add(new Label("Java Sleep Timer:", Label.RIGHT));
   infoPanel.add(new Label("java.lang.System.currentTimeMillis()", Label.LEFT));
   infoPanel.add(new Label("Resolution:", Label.RIGHT));
   infoPanel.add(
       new Label(String.valueOf(HiresClock.getSleepTimerGranularity()) + " ms", Label.LEFT));
   double r = VideoSystem.getFrameDuration();
   if (r > 0.0) {
     infoPanel.add(new Label("Video Cycle Duration:", Label.RIGHT));
     infoPanel.add(new Label(String.valueOf(r) + " ms", Label.LEFT));
     infoPanel.add(new Label("Video Refresh Rate:", Label.RIGHT));
     infoPanel.add(new Label(String.valueOf(1000.0 / r) + " Hz", Label.LEFT));
   }
   pack();
   setVisible(true);
 }
  public PolledDeviceDIData read() {
    delay();
    // long t1 = HiresClock.getTimeNanos();
    long time = HiresClock.getTimeNanos();
    diDevice.update();
    // System.out.println("DIDevice.read() takes time: " + (time-t1));

    if (useAxisDeltas) {
      for (int i = 0; i < diAxis.length; i++) {
        if (diAxis[i] != null) {
          axisValue[i] = axisTransform.valueOf(diAxis[i].getValue());
          axisDelta[i] = (axisValue[i] - lastAxisValue[i]) / axisLimit;
          lastAxisValue[i] = axisValue[i];
        }
      }
    } else {
      for (int i = 0; i < diAxis.length; i++) {
        axisValue[i] = axisTransform.valueOf(diAxis[i].getValue()) / axisLimit;
      }
    }

    changedButtonIndex = -1;
    for (int i = diButton.length - 1; i >= 0; i--) {
      boolean s = diButton[i].getState();
      if (s != buttonState[i]) {
        changedButtonIndex = i;
      }
      buttonState[i] = s;
    }

    changedDirectionalIndex = -1;
    for (int i = diDirectional.length - 1; i >= 0; i--) {
      boolean s = diDirectional[i].isCentered();
      if (s != directionalState[i]) {
        changedDirectionalIndex = i;
      }
      directionalState[i] = s;
      directionalValue[i] = diDirectional[i].getDirection() / 100;
    }

    return new PolledDeviceDIData(
        this,
        changedButtonIndex,
        buttonState,
        changedDirectionalIndex,
        directionalState,
        directionalValue,
        useAxisDeltas ? axisDelta : axisValue,
        time);
  }