Android Open Source - cwp-morse-mangle C W Output






From Project

Back to project page cwp-morse-mangle.

License

The source code is released under:

Copyright (C) 2012 Jussi Kivilinna <jussi.kivilinna@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "S...

If you think the Android project cwp-morse-mangle listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2012 Jussi Kivilinna <jussi.kivilinna@gmail.com>
 */* w ww. ja v  a 2 s  . c  o m*/
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

package fi_81.cwp_morse_mangle.cwp;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayDeque;

import fi_81.cwp_morse_mangle.morse.BitString;

public class CWOutput {
  /* Callbacks from output, frequency change, state changes */
  public interface CWOutputNotification {
    public abstract void frequencyChange(long newFreq);

    public abstract void stateChange(byte newState, int value);
  }

  public static class NotificationNone implements CWOutputNotification {
    public void frequencyChange(long newFreq) {
    }

    public void stateChange(byte newState, int value) {
    }
  }

  private final ArrayDeque<CWStateChange> queue = new ArrayDeque<CWStateChange>();
  private final CWStateChangeQueueFromMorseCode stateChangeBuilder = new CWStateChangeQueueFromMorseCode();
  private ByteBuffer outBuf;
  private long startTime;

  private boolean inManualUp;
  private long manualUpStartTime;
  private long delayedFreq = -1;

  public CWOutput(long connectionStartTime) {
    this(null, connectionStartTime);
  }

  public CWOutput(ByteBuffer bb, long connectionStartTime) {
    startTime = connectionStartTime;
    inManualUp = false;
    manualUpStartTime = 0;

    if (bb == null) {
      /* Allocate IO buffer and set it to big-endian byteorder */
      outBuf = ByteBuffer.allocateDirect(128);
      outBuf.order(ByteOrder.BIG_ENDIAN);
    } else {
      outBuf = bb;
    }

    outBuf.flip();
  }

  public ByteBuffer getOutputBuffer() {
    return outBuf;
  }

  public long timeToNextQueueWork() {
    if (queue.isEmpty())
      return Long.MAX_VALUE;

    long currentTime = System.currentTimeMillis();
    long timeSinceConnCreation = currentTime - startTime;
    long timeToNext = queue.peek().getOutTime() - timeSinceConnCreation;

    if (timeToNext < 0)
      return 0;

    return timeToNext;
  }

  public long timeToNextContinuousUpWaveWork() {
    if (!inManualUp)
      return Long.MAX_VALUE;

    /*
     * Split up-waves to 55 second chunks (max duration of up-wave is ~65
     * sec [(2^16-1) msec]).
     */
    long nextReupTime = manualUpStartTime + (55 * 1000);
    long currentTime = System.currentTimeMillis();
    long timeToNext = nextReupTime - currentTime;

    if (timeToNext < 0)
      return 0;

    return timeToNext;
  }

  public long timeToNextWork() {
    long nextQueueWork = timeToNextQueueWork();
    long nextContiniousUpWaveWork = timeToNextContinuousUpWaveWork();

    return Math.min(nextQueueWork, nextContiniousUpWaveWork);
  }

  private boolean isTimeToSend() {
    return timeToNextQueueWork() == 0;
  }

  public boolean isBusy() {
    return !queue.isEmpty() && inManualUp;
  }

  public boolean isBusyDown() {
    return !queue.isEmpty() && !inManualUp;
  }

  public boolean sendMorseCode(BitString morseCode) {
    if (!queue.isEmpty() || inManualUp)
      return false;

    stateChangeBuilder.encode(queue, morseCode);

    /* adjust timestamps based on time since connection was created */
    long currentTime = System.currentTimeMillis();
    long timeSinceConnCreation = currentTime - startTime;
    CWStateChange last = null;

    for (CWStateChange stateChange : queue) {
      stateChange.addTimestamp(timeSinceConnCreation);
      last = stateChange;
    }

    /* sanity check */
    if (last != null) {
      assert (last.getType() == CWStateChange.TYPE_UP_TO_DOWN);
    }

    return true;
  }

  public boolean sendFrequenceChange(long newFreq) {
    if (newFreq < 1 || -newFreq < CWFrequencyChange.MAX_FREQ_NEG)
      return true;

    /* Current send state is at 'down' always except when inManualUp. */
    if (inManualUp) {
      delayedFreq = newFreq;

      return true;
    }

    queue.add(new CWFrequencyChange(newFreq));
    delayedFreq = -1;

    return true;
  }

  private boolean sendStateChange(byte stateChange) {
    /*
     * if inManualUp, then queue might have the up-value that we add there
     * moment ago
     */
    if (!queue.isEmpty() && !inManualUp)
      return false;

    /* already in manual up */
    if (inManualUp && stateChange == CWStateChange.TYPE_DOWN_TO_UP)
      return true;

    /* already in down state */
    if (!inManualUp && stateChange == CWStateChange.TYPE_UP_TO_DOWN)
      return true;

    /* from manual up to down, check elapsed time and add message to queue */
    if (inManualUp && stateChange == CWStateChange.TYPE_UP_TO_DOWN) {
      long currentTime = System.currentTimeMillis();
      long timestamp = currentTime - startTime;
      int upStateDuration = (int) (currentTime - manualUpStartTime);

      queue.add(new CWStateChange(stateChange, upStateDuration, timestamp));

      inManualUp = false;
      sendFrequenceChange(delayedFreq);

      return true;
    }

    /*
     * from down to manual up, generate down-to-up state change with
     * timestamp
     */
    if (!inManualUp && stateChange == CWStateChange.TYPE_DOWN_TO_UP) {
      manualUpStartTime = System.currentTimeMillis();
      long timestamp = manualUpStartTime - startTime;

      queue.add(new CWStateChange(stateChange, (int) timestamp, timestamp));

      inManualUp = true;
      return true;
    }

    return true;
  }

  private void renewUpState() {
    if (!inManualUp)
      return;

    long currentTime = System.currentTimeMillis();
    long timestamp = currentTime - startTime;
    int upStateDuration = (int) (currentTime - manualUpStartTime);

    /* Send state change up-to-down ... */
    queue.add(new CWStateChange(CWStateChange.TYPE_UP_TO_DOWN,
        upStateDuration, timestamp));

    /* ... immediately followed by state change down-to-up. */
    queue.add(new CWStateChange(CWStateChange.TYPE_DOWN_TO_UP,
        (int) timestamp, timestamp));

    manualUpStartTime = currentTime;
  }

  public boolean sendDown() {
    return sendStateChange(CWStateChange.TYPE_UP_TO_DOWN);
  }

  public boolean sendUp() {
    return sendStateChange(CWStateChange.TYPE_DOWN_TO_UP);
  }

  public boolean processOutput(CWOutputNotification notify) {
    boolean addedToBuffer = false;

    /* Time to renew up-wave? */
    if (inManualUp && timeToNextContinuousUpWaveWork() == 0)
      renewUpState();

    outBuf.compact();

    while (isTimeToSend()) {
      /* Get first state-change from queue */
      CWStateChange stateToSend = queue.peek();

      if (!stateToSend.writeToBuffer(outBuf)) {
        /* Could not fit state-change to outBuf */
        break;
      }

      queue.remove();

      switch (stateToSend.getType()) {
      case CWStateChange.TYPE_DOWN_TO_UP:
        notify.stateChange(CWave.TYPE_UP, stateToSend.getValue());
        break;
      case CWStateChange.TYPE_UP_TO_DOWN:
        notify.stateChange(CWave.TYPE_DOWN, stateToSend.getValue());
        break;
      case CWStateChange.TYPE_FREQUENCY_CHANGE:
        notify.frequencyChange(((CWFrequencyChange) stateToSend)
            .getFrequency());
        break;
      }

      addedToBuffer = true;
    }

    outBuf.flip();

    return addedToBuffer;
  }

  public int queueSize() {
    if (queue != null)
      return queue.size();

    return 0;
  }
}




Java Source Code List

fi_81.cwp_morse_mangle.CWPControlService.java
fi_81.cwp_morse_mangle.CWPControlThread.java
fi_81.cwp_morse_mangle.DefaultSettings.java
fi_81.cwp_morse_mangle.EventLog.java
fi_81.cwp_morse_mangle.MainActivity.java
fi_81.cwp_morse_mangle.MainSettingsActivity.java
fi_81.cwp_morse_mangle.SinAudioLoop.java
fi_81.cwp_morse_mangle.cwp.CWFrequencyChange.java
fi_81.cwp_morse_mangle.cwp.CWInputQueue.java
fi_81.cwp_morse_mangle.cwp.CWInput.java
fi_81.cwp_morse_mangle.cwp.CWOutput.java
fi_81.cwp_morse_mangle.cwp.CWStateChangeQueueFromMorseCode.java
fi_81.cwp_morse_mangle.cwp.CWStateChange.java
fi_81.cwp_morse_mangle.cwp.CWaveQueueToMorseCode.java
fi_81.cwp_morse_mangle.cwp.CWave.java
fi_81.cwp_morse_mangle.morse.BitString.java
fi_81.cwp_morse_mangle.morse.MorseCharList.java
fi_81.cwp_morse_mangle.morse.MorseChar.java
fi_81.cwp_morse_mangle.morse.MorseCodec.java