/*
 * NCDXF/IARU HF Beacon Tracker
 *
 * Very simple console mode program that displays the
 * currently transmitting NCDXF beacon. Your computer
 * clock must be accurate. Compiled and tested on
 * Debian Linux, but should work anywhere standard
 * C is available (the sleep() function might be the
 * only wrinkle). This program is freeware. Enjoy and 73.
 *
 * Bugs and typos to ward@kg6haf.com.
 * http://www.kg6haf.com
 *
 * HISTORY
 * 22Feb03  wwillats    create
 *
 */
#include <stdio.h>
#include <time.h>
#include <unistd.h>

/****************************************
CONSTANTS
****************************************/

#define VERSION "1.0"
#define DATE "22Feb03"

#define NUM_BEACONS 18
#define NUM_BANDS    5

static char szUN[]          = "United Nations 4U1UN";
static char szCanada[]      = "Canada VE8AT";
static char szUS[]          = "United States W6WX";
static char szHawaii[]      = "Hawaii KH6WO";
static char szNewZealand[]  = "New Zealand ZL6B";
static char szAustralia[]   = "Australia VK6RBP";
static char szJapan[]       = "Japan JA2IGY";
static char szRussia[]      = "Russia RR90";
static char szHongKong[]    = "Hong Kong VR2B";
static char szSriLanka[]    = "Sri Lanka 4S7B";
static char szSouthAfrica[] = "South Africa ZS6DN";
static char szKenya[]       = "Kenya 5Z4B";
static char szIsrael[]      = "Israel 4X6TU";
static char szFinland[]     = "Finland OH2B";
static char szMadeira[]     = "Madeira CS3B";
static char szArgentina[]   = "Argentina LU4AA";
static char szPeru[]        = "Peru OA4B";
static char szVenezuela[]   = "Venezuela YV5B";

/****************************************
LOOKUP TABLES
****************************************/

static char * band_titles[ NUM_BANDS ] =
{ "20 Meter Beacons - Tune to 14.100 MHZ",
  "17 Meter Beacons - Tune to 18.110 MHZ",
  "15 Meter Beacons - Tune to 21.150 MHZ",
  "12 Meter Beacons - Tune to 24.930 MHZ",
  "10 Meter Beacons - Tune to 28.200 MHZ"
};


static char * names[ NUM_BANDS][ NUM_BEACONS ] = 
{
  /* 20 meters */
  { szUN, szCanada, szUS,
    szHawaii, szNewZealand, szAustralia,
    szJapan, szRussia, szHongKong,
    szSriLanka, szSouthAfrica, szKenya,
    szIsrael, szFinland, szMadeira,
    szArgentina, szPeru, szVenezuela 
  },

  /* 17 meters */
  { szVenezuela,szUN,szCanada,
    szUS,szHawaii,szNewZealand,
    szAustralia,szJapan,szRussia,
    szHongKong,szSriLanka,szSouthAfrica,
    szKenya,szIsrael,szFinland,
    szMadeira,szArgentina,szPeru 
  },

  /* 15 meters */
  { szPeru,szVenezuela,szUN,
    szCanada,szUS,szHawaii,
    szNewZealand,szAustralia,szJapan,
    szRussia,szHongKong,szSriLanka,
    szSouthAfrica,szKenya,szIsrael,
    szFinland,szMadeira,szArgentina 
  },

  /* 12 Meters */
  { szArgentina,szPeru,szVenezuela,
    szUN,szCanada,szUS,
    szHawaii,szNewZealand,szAustralia,
    szJapan,szRussia,szHongKong,
    szSriLanka,szSouthAfrica,szKenya,
    szIsrael,szFinland,szMadeira 
  },

  /* 10 Meters */
  { szMadeira,szArgentina,szPeru,
    szVenezuela,szUN,szCanada,
    szUS,szHawaii,szNewZealand,
    szAustralia,szJapan,szRussia,
    szHongKong,szSriLanka,szSouthAfrica,
    szKenya,szIsrael,szFinland
  }
};

/****************************************
CODE
****************************************/

static void usage( const char * pszMe, 
                   const char * pszErr )
{
  fprintf( stderr,
           "\n%s\n"
           "\n"
           "Usage:\n"
           "  %s band_number\n"
           "Where:\n"
           "  band_number is one of 20, 17, 15, 12 or 10 (meters)\n"
           "For example:\n"
           "  %s 20\n\n",           
           pszErr, pszMe, pszMe
           );
}



int main( int argc, char ** argv )
{
  int band;
  char * pCur = NULL;
  char * pNew;

  fprintf( stderr, 
           "NCDXF/IARU HF Beacon Tracker by KG6HAF - %s - %s\n",
           VERSION, DATE );

  /* parse command line */

  if ( argc != 2 ) {
    usage( argv[0], "Band number required" );
    return -1;
  }

  band = atoi( argv[1] );

  switch( band ) {
  case 20: band = 0; break;
  case 17: band = 1; break;
  case 15: band = 2; break;
  case 12: band = 3; break;
  case 10: band = 4; break;
  default: usage( argv[0], "Invalid band number" ); return -2;
  }

  /* Here we go... */

  fprintf( stderr, "%s\nControl-C to quit...\n\n", band_titles[ band ] );
  fprintf( stderr, 
           "Slot    Now Transmitting         Next Up\n"
           "-----   -----------------------  -------\n"
           );

  while( 1 ) {
    /* get time */
    time_t now    = time( NULL );
    struct tm * p = localtime( &now );

    /* compute slot and next slot */
    int min       = p->tm_min % 3;
    int sec       = p->tm_sec / 10;
    int idx       = min * 6 + sec;
    int idx_next  = ( idx + 1 ) % NUM_BEACONS;
    pNew          = names[band][idx];

    /* if change, print something */
    if ( pNew != pCur ) {
      printf( "%02d:%02d : --> %-20.20s (%s)\n",
              min, p->tm_sec, pNew, names[band][idx_next] 
              );
      if ( pCur != NULL )   /* if not first time */
        sleep(9);           /* sleep til close to next change */
      pCur = pNew;
    }
  }
  return 0;
}

/* end: beacon.c */

