content: /*
   * HalfNES by Andrew Hoffman
   * Licensed under the GNU GPL Version 3. See LICENSE file
   */
  package com.grapeshot.halfnes.audio;
  
  /**
   *
   * @author Andrew
   */
  public class TriangleTimer extends Timer {
  
      private int divider = 0;
      private final static int periodadd = 1;
      private final static int[] triangle = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
          12, 13, 14, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
          5, 4, 3, 2, 1, 0};
  
      public TriangleTimer() {
          period = 0;
          position = 0;
      }
  
      @Override
      public final void reset() {
          //no way to reset the triangle
      }
  
      @Override
      public final void clock() {
          if (period == 0) {
              return;
          }
          ++divider;
          // note: stay away from negative division to avoid rounding problems
          int periods = (divider + period + periodadd) / (period + periodadd);
          if (periods < 0) {
              periods = 0; // can happen if period or periodadd were made smaller
          }
          position = (position + periods) & 0x1F;
          divider -= (period + periodadd) * periods;
      }
  
      @Override
      public final void clock(final int cycles) {
          if (period == 0) {
              return;
          }
          divider += cycles;
          // note: stay away from negative division to avoid rounding problems
          int periods = (divider + period + periodadd) / (period + periodadd);
          if (periods < 0) {
              periods = 0; // can happen if period or periodadd were made smaller
          }
          position = (position + periods) & 0x1F;
          divider -= (period + periodadd) * periods;
      }
  
      @Override
      public final int getval() {
          return (period == 0) ? 7 : triangle[position];
          //needed to avoid screech when period is zero
      }
  
      @Override
      public final void setperiod(final int newperiod) {
          period = newperiod;
          if (period == 0) {
              position = 7;
          }
      }
  
      @Override
      public void setduty(int duty) {
          throw new UnsupportedOperationException("Triangle counter has no duty setting.");
      }
  
      @Override
      public void setduty(int[] duty) {
          throw new UnsupportedOperationException("Triangle counter has no duty setting.");
      }
  }