/*
 * BRLTTY - A background process providing access to the console screen (when in
 *          text mode) for a blind person using a refreshable braille display.
 *
 * Copyright (C) 1995-2023 by The BRLTTY Developers.
 *
 * BRLTTY comes with ABSOLUTELY NO WARRANTY.
 *
 * This is free software, placed under the terms of the
 * GNU Lesser General Public License, as published by the Free Software
 * Foundation; either version 2.1 of the License, or (at your option) any
 * later version. Please see the file LICENSE-LGPL for details.
 *
 * Web Page: http://brltty.app/
 *
 * This software is maintained by Dave Mielke <dave@mielke.cc>.
 */

/*
 * Miscellaneous FM chip soundcard routines for BRLTTY.
 * Implemented by Dave Mielke <dave@mielke.cc>.
 * Method gleaned from sccw, a morse code program written
 * by Steven J. Merrifield <sjm@ee.latrobe.edu.au> (VK3ESM).
 * Must compile with -O2.
 * Must link with -lm.
 * May compile with -DDEBUG_ADLIB.
 */

#include "prologue.h"

#include "log.h"
#include "async_wait.h"
#include "timing.h"
#include "ports.h"
#include "fm.h"
#include "fm_adlib.h"

const unsigned char AL_channelOffsets[] = {
  /* 1     2     3     4     5     6     7     8     9 */
  0X00, 0X01, 0X02, 0X08, 0X09, 0X0A, 0X10, 0X11, 0X12
};
const unsigned char AL_channelCount = ARRAY_COUNT(AL_channelOffsets);

static unsigned int portsEnabledCount = 0;

int
fmEnablePorts (int errorLevel) {
  if (portsEnabledCount) return 1;

  if (enablePorts(errorLevel, ALP_REGISTER, 1)) {
    if (enablePorts(errorLevel, ALP_DATA, 1)) {
      portsEnabledCount++;
      return 1;
    }

    disablePorts(ALP_REGISTER, 1);
  }

  return 0;
}

void
fmDisablePorts (void) {
  if (!--portsEnabledCount) {
    disablePorts(ALP_REGISTER, 1);
    disablePorts(ALP_DATA, 1);
  }
}

unsigned char
AL_readStatus (void) {
  return readPort1(ALP_STATUS);
}

static void
AL_writeDelay (int delay) {
  while (delay-- > 0) {
    AL_readStatus();
  }
}

void
AL_writeRegister (int number, unsigned char data) {
  /* logMessage(LOG_DEBUG, "AL_writeRegister: %2.2X=%2.2X", number, data); */
  writePort1(ALP_REGISTER, number);
  AL_writeDelay(6);
  writePort1(ALP_DATA, data);
  AL_writeDelay(35);
}

void
fmResetCard (void) {
  int number;
  for (number=ALR_FIRST; number<=ALR_LAST; ++number) {
    AL_writeRegister(number, 0);
  }
}

static void
AL_resetTimers (void) {
  AL_writeRegister(ALR_TCTL, AL_TCTL_T1MASK|AL_TCTL_T2MASK);
  AL_writeRegister(ALR_TCTL, AL_TCTL_RESET);
}

int
fmTestCard (int errorLevel) {
  const unsigned char mask = AL_STAT_EXP | AL_STAT_EXP1 | AL_STAT_EXP2;

  AL_resetTimers();
  if (!(AL_readStatus() & mask)) {
    unsigned char status;

    AL_writeRegister(ALR_T1DATA, 0xFF);
    AL_writeRegister(ALR_TCTL, AL_TCTL_T1START|AL_TCTL_T2MASK);

    {
      const TimeValue duration = {
        .seconds = 0,
        .nanoseconds = 80 * NSECS_PER_USEC
      };

      accurateDelay(&duration);
    }

    status = AL_readStatus();
    AL_resetTimers(); 

    if ((status & mask) == (AL_STAT_EXP | AL_STAT_EXP1)) return 1; 
  }

  logMessage(errorLevel, "FM synthesizer initialization failure");
  return 0;
}

static void
AL_evaluatePitch (int pitch, int *exponent, int *mantissa) {
  int shift = 21;
  while ((*mantissa = (int)((float)pitch * (1 << --shift) / 50000.0)) > 0X3FF);
  *exponent = 20 - shift;
}

static void
AL_initiateTone (int channel, int exponent, int mantissa) {
  /* logMessage(LOG_DEBUG, "AL_initiateTone: %1.1X[%3.3X]", exponent, mantissa); */
  AL_writeRegister(ALR_FREQUENCY_LSB(channel),
                   (mantissa & 0XFF));
  AL_writeRegister(ALR_FREQUENCY_MSB(channel),
                   (((mantissa >> 8) & 0X3) |
                    ((exponent & 0X7) << AL_OCTAVE_SHIFT) |
                    AL_FREQ_ON));
}

void
fmStartTone (int channel, int pitch) {
  int exponent;
  int mantissa;
  AL_evaluatePitch(pitch, &exponent, &mantissa);
  /* logMessage(LOG_DEBUG, "fmStartTone: %d", pitch); */
  AL_initiateTone(channel, exponent, mantissa);
}

void
fmStopTone (int channel) {
  AL_writeRegister(ALR_FREQUENCY_MSB(channel), 0);
}

void
fmPlayTone (int channel, unsigned int pitch, unsigned long int duration, unsigned int volume) {
  /* Play tone at fundamental frequency. */
  AL_writeRegister(ALR_MODULATOR(ALG_EFFECT, channel),
                   (AL_HARMONIC_1 << AL_HARMONIC_SHIFT));

  /* Set the carrier to the fundamental frequency. */
  AL_writeRegister(ALR_CARRIER(ALG_EFFECT, channel),
                   (AL_HARMONIC_1 << AL_HARMONIC_SHIFT));

  /* Set the volume (passed in as 0-100) */
  AL_writeRegister(ALR_CARRIER(ALG_LEVEL, channel),
                   ((AL_VOLUME_SOFT - ((AL_VOLUME_SOFT * volume) / 100)) << AL_VOLUME_SHIFT));

  /* Set fast attack and slow decay. */
  AL_writeRegister(ALR_CARRIER(ALG_ATTDEC, channel),
                   ((AL_ATTACK_FAST << AL_ATTACK_SHIFT) |
                    (AL_DECAY_SLOW << AL_DECAY_SHIFT)));

  /* Set soft sustain and fast release. */
  AL_writeRegister(ALR_CARRIER(ALG_SUSREL, channel),
                   ((AL_SUSTAIN_SOFT << AL_SUSTAIN_SHIFT) |
                    (AL_RELEASE_FAST << AL_RELEASE_SHIFT)));
      
  fmStartTone(channel, pitch);
  asyncWait(duration);
  fmStopTone(channel);
}
