/*
 * tuner/tea5757h.c:
 *
 * Copyright (c) 2000 James McKenzie <james@fishsoup.dhs.org>,
 * All rights reserved.
 *
 */

static char rcsid[] =
  "$Id: tea5757h.c,v 1.11 2001/10/12 13:51:17 root Exp root $";

/*
 * $Log: tea5757h.c,v $
 * Revision 1.11  2001/10/12 13:51:17  root
 * #
 *
 * Revision 1.10  2001/01/30 06:16:30  root
 * #
 *
 * Revision 1.9  2000/12/01 04:42:19  root
 * #
 *
 * Revision 1.8  2000/12/01 04:13:51  root
 * #
 *
 * Revision 1.7  2000/11/23 23:45:28  root
 * #
 *
 * Revision 1.6  2000/10/07 18:30:09  root
 * #
 *
 * Revision 1.5  2000/10/06 19:52:44  root
 * #
 *
 * Revision 1.4  2000/09/24 01:52:21  root
 * #
 *
 * Revision 1.3  2000/09/24 01:48:15  root
 * #
 *
 */

#include "project.h"
#include "tea5757h.h"

static DWord ifoff[] = { -TEA5757H_FM_IF, 0, 0, 0 };
static char *name[] = { "FM", "MW", "LW", "SW" };
static char *am_level[] = { "28uV", "40uV", "63uV", "1mV" };
static char *fm_level[] = { "5uV", "10uV", "30uV", "150uV" };
static char **level[] = { fm_level, am_level, am_level, am_level };
static DWord fstep[] =
  { TEA5757H_FREQ_FM_STEP, TEA5757H_FREQ_AM_STEP, TEA5757H_FREQ_AM_STEP,
  TEA5757H_FREQ_AM_STEP
};

static void
tea5757h_decode (DWord v)
{
  int band;
  float f;

  band = (v & TEA5757H_BAND_MASK) >> TEA5757H_BAND_SHIFT;

  if (v & TEA5757H_SEARCH)
    {
      printf ("[Searching %s %s] ", (v & TEA5757H_SEARCH_DIR) ? "Up" : "Down",
              level[band][(v & TEA5757H_SEARCH_STRENGTH_MASK) >>
                          TEA5757H_SEARCH_STRENGTH_SHIFT]);
    }
  else
    {
      printf ("[Fixed] ");
    }
  if (v & TEA5757H_MONO)
    {
      printf ("[Forced Mono] ");
    }
  else
    {
      printf ("[Auto Stereo] ");
    }
  printf ("[%s] ", name[band]);
  printf ("[Ports 0x%lx] ", (v & TEA5757H_PORT_MASK) >> TEA5757H_PORT_SHIFT);

  v &= TEA5757H_FREQ_MASK;

  v *= fstep[band];
  v += ifoff[band];

  f = (float) v;
  f = f / 1000.0;
  if (f > 2000)
    {
      f = f / 1000.0;
      printf ("%.3f MHz\n", f);
    }
  else
    {
      printf ("%.3f kHz\n", f);
    }
}

static Hifi_Radio_Frequency
count_to_freq (DWord v)
{
  Hifi_Radio_Frequency f;
  DWord band = (v & TEA5757H_BAND_MASK) >> TEA5757H_BAND_SHIFT;
  DWord freq = v & TEA5757H_FREQ_MASK;


  switch (band)
    {
    case TEA5757H_BAND_FM:
      f.band = HIFI_TUNER_Band_FM;

      freq *= TEA5757H_FREQ_FM_STEP;
      freq -= TEA5757H_FM_IF;

      f.freq = freq;

      break;
    }


  return f;


}

static DWord
freq_to_count (Hifi_Radio_Frequency f)
{
  DWord freq = f.freq;
  switch (f.band)
    {
    case HIFI_TUNER_Band_FM:
      freq += TEA5757H_FM_IF;
      freq += (TEA5757H_FREQ_FM_STEP >> 1);
      freq = freq / TEA5757H_FREQ_FM_STEP;
      freq &= TEA5757H_FREQ_MASK;
      freq |= TEA5757H_BAND_FM;
      return (freq);
    }

  return 0;
}


void
tuner_re_search (int dir)
{
  DWord sens = TEA5757H_SEARCH_STRENGTH_FM_5uV;
  DWord freq = tea5757h_read () & TEA5757H_TUNING_MASK;

  freq |= TEA5757H_SEARCH;
  if (dir)
    freq |= TEA5757H_SEARCH_DIR;

  freq |= sens;

  tea5757h_write (freq);

}

void
tuner_search_up (void)
{
  tuner_re_search (HIFI_TUNER_Search_Up);
  usleep (500000);
}

void
tuner_search_down (void)
{
  tuner_re_search (HIFI_TUNER_Search_Down);
  usleep (500000);
}



void
tuner_search (Hifi_Radio_Frequency f, int dir)
{

  DWord sens = TEA5757H_SEARCH_STRENGTH_FM_5uV;
  DWord freq = freq_to_count (f);

  freq |= TEA5757H_SEARCH;
  if (dir)
    freq |= TEA5757H_SEARCH_DIR;
  freq |= sens;

  tea5757h_write (freq);


}


void
tuner_tune (Hifi_Radio_Frequency f)
{

  DWord freq;

  if (f.freq == HIFI_TUNER_Freq_Mute)
    {
      tea5757h_mute ();
    }
  else
    {
      freq = freq_to_count (f);

      tea5757h_write (freq);
    }

}

Hifi_Tuner_State
tuner_state ()
{
  Hifi_Tuner_State ret;

  DWord st;


  if (tea5757h_ismutted ())
    {
      ret.f.freq = HIFI_TUNER_Freq_Mute;
      ret.lock = ret.stereo = 0;
    }
  else
    {
      st = tea5757h_read ();
      tea5757h_decode (st);
      ret.f = count_to_freq (st);
      ret.lock = tea5757h_islocked ();
      ret.stereo = tea5757h_isstereo ();
    }

  return ret;

}

void
tuner_mono (void)
{
  DWord freq;

  if (tea5757h_ismutted ())
    return;
  freq = tea5757h_read () & TEA5757H_TUNING_MASK;

  freq |= TEA5757H_MONO;

  tea5757h_write (freq);
}


void
tuner_stereo (void)
{
  DWord freq;

  if (tea5757h_ismutted ())
    return;
  freq = tea5757h_read () & TEA5757H_TUNING_MASK;


  tea5757h_write (freq);
}


void
tea5757h_open (void)
{
  tea5757h_if_open ();
}
