public synchronized void saveButtonActionPerformed(java.awt.event.ActionEvent e) {
    SprogMessage saveMsg;
    // Send Current Limit if possible
    state = State.CURRENTSENT;
    if (isCurrentLimitPossible()) {
      validateCurrent();
      // Value written is number of ADC steps 0f 4.88mV across 0.47 ohms
      currentLimit = currentLimit * 470 / 4880;
      if (sv.sprogType.sprogType < SprogType.SPROGIIv3) {
        // Hack for SPROG bug where MSbyte of value must be non-zero
        currentLimit += 256;
      }
      tmpString = String.valueOf(currentLimit);
      saveMsg = new SprogMessage("I " + tmpString);
    } else {
      // Else send blank message to kicj things off
      saveMsg = new SprogMessage(" " + tmpString);
    }
    nextLine("cmd: \"" + saveMsg.toString() + "\"\n", "");
    tc.sendSprogMessage(saveMsg, this);

    // Further messages will be sent from state machine
  }
  public synchronized void notifyReply(SprogReply l) { // receive a reply message and log it
    SprogMessage msg;
    replyString = l.toString();
    nextLine("rep: \"" + replyString + "\"\n", "");

    // *** Check for error reply
    switch (state) {
      case IDLE:
        if (log.isDebugEnabled()) {
          log.debug("reply in IDLE state: " + replyString);
        }
        break;
      case CURRENTQUERYSENT:
        if (log.isDebugEnabled()) {
          log.debug("reply in CURRENTQUERYSENT state: " + replyString);
        }
        int valueLength = 4;
        if (sv.sprogType.sprogType >= SprogType.SPROGIIv3) {
          valueLength = 6;
        }
        tmpString =
            replyString.substring(
                replyString.indexOf("=") + 1, replyString.indexOf("=") + valueLength);
        if (log.isDebugEnabled()) {
          log.debug("Current limit string: " + tmpString);
        }
        // Value returned is number of ADC steps 0f 4.88mV across 0.47 ohms
        // SPROG 3 is equivalent, using .047R sense with 10x amplifier
        // Convert to milliAmps using integer math
        try {
          currentLimit = (Integer.parseInt(tmpString) * 4880) / 470;
        } catch (NumberFormatException e) {
          JOptionPane.showMessageDialog(
              null,
              "Malformed Reply for current limit",
              "SPROG Console",
              JOptionPane.ERROR_MESSAGE);
          state = State.IDLE;
          return;
        }
        if (log.isDebugEnabled()) {
          log.debug("Current limit value: " + currentLimit);
        }
        currentTextField.setText(String.valueOf(currentLimit));
        currentTextField.setEnabled(true);
        // Next get the mode word
        // Only get this if we have zero active slots in slot manager
        // in command mode
        if (sm.getInUseCount() == 0) {
          state = State.MODEQUERYSENT;
          msg = new SprogMessage(1);
          msg.setOpCode('M');
          nextLine("cmd: \"" + msg + "\"\n", "");
          tc.sendSprogMessage(msg, this);
        } else {
          state = State.IDLE;
        }
        break;
      case MODEQUERYSENT:
        if (log.isDebugEnabled()) {
          log.debug("reply in MODEQUERYSENT state: " + replyString);
        }
        tmpString =
            replyString.substring(replyString.indexOf("=") + 2, replyString.indexOf("=") + 6);
        // Value returned is in hex
        try {
          modeWord = Integer.parseInt(tmpString, 16);
        } catch (NumberFormatException e) {
          JOptionPane.showMessageDialog(
              null, "Malformed Reply for mode word", "SPROG Console", JOptionPane.ERROR_MESSAGE);
          state = State.IDLE;
          return;
        }
        state = State.IDLE;
        // Set Speed step radio buttons, etc., according to mode word
        if ((modeWord & SprogConstants.STEP14_BIT) != 0) {
          speed14Button.setSelected(true);
        } else if ((modeWord & SprogConstants.STEP28_BIT) != 0) {
          speed28Button.setSelected(true);
        } else {
          speed128Button.setSelected(true);
        }
        if ((modeWord & SprogConstants.ZTC_BIT) != 0) {
          ztcCheckBox.setSelected(true);
        }
        if ((modeWord & SprogConstants.BLUE_BIT) != 0) {
          blueCheckBox.setSelected(true);
        }
        break;
      case CURRENTSENT:
        if (log.isDebugEnabled()) {
          log.debug("reply in CURRENTSENT state: " + replyString);
        }
        // Get new mode word - assume 128 steps
        modeWord = SprogConstants.STEP128_BIT;
        if (speed14Button.isSelected()) {
          modeWord = modeWord & ~SprogConstants.STEP_MASK | SprogConstants.STEP14_BIT;
        } else if (speed28Button.isSelected()) {
          modeWord = modeWord & ~SprogConstants.STEP_MASK | SprogConstants.STEP28_BIT;
        }

        // ZTC mode
        if (ztcCheckBox.isSelected() == true) {
          modeWord = modeWord | SprogConstants.ZTC_BIT;
        }

        // Blueline mode
        if (blueCheckBox.isSelected() == true) {
          modeWord = modeWord | SprogConstants.BLUE_BIT;
        }

        // firmware unlock
        if (unlockCheckBox.isSelected() == true) {
          modeWord = modeWord | SprogConstants.UNLOCK_BIT;
        }

        // Send new mode word
        state = State.MODESENT;
        msg = new SprogMessage("M " + modeWord);
        nextLine("cmd: \"" + msg.toString() + "\"\n", "");
        tc.sendSprogMessage(msg, this);
        break;
      case MODESENT:
        if (log.isDebugEnabled()) {
          log.debug("reply in MODESENT state: " + replyString);
        }
        // Write to EEPROM
        state = State.WRITESENT;
        msg = new SprogMessage("W");
        nextLine("cmd: \"" + msg.toString() + "\"\n", "");
        tc.sendSprogMessage(msg, this);
        break;
      case WRITESENT:
        if (log.isDebugEnabled()) {
          log.debug("reply in WRITESENT state: " + replyString);
        }
        // All done
        state = State.IDLE;
    }
  }
 public synchronized void notifyMessage(SprogMessage l) { // receive a message and log it
   nextLine("cmd: \"" + l.toString() + "\"\n", "");
 }
 public void sendButtonActionPerformed(java.awt.event.ActionEvent e) {
   SprogMessage m = new SprogMessage(cmdTextField.getText());
   // Messages sent by us will not be forwarded back so add to display manually
   nextLine("cmd: \"" + m.toString() + "\"\n", "");
   SprogTrafficController.instance().sendSprogMessage(m, this);
 }