/* lfxmit.c - top level.
 *  Copyright (C) 2022 by Jed Marti
 *   This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see https://www.gnu.org/licenses/.
 */


#include <C8051F380.h>
#include <stdint.h>

#include "lfxmit.h"
#include "config.h"
#include "storage.h"

#include "i2c.h"
#include "serial.h"
#include "spi.h"
#include "strings.h"
#include "fs.h"
#include "lex.h"


// Timers for Morse sender.
// TIMER0
// TIMER1                                // UART
// TIMER2                                // I2C
// TIMER3                                // Morse code.
// TIMER4                                // Sleep.
void ISS_SMBUS0(void) __interrupt 7;      // See i2c.c
void ISS_TIMER3(void) __interrupt 14;    // Millisecond clock.
void ISS_TIMER4(void) __interrupt 19;    // LF Sleep clock.

extern __xdata floatOrInt IACC;


// Called by startup code for special stuff. Turn off the watch dog here. This
// avoids watchdog timeouts for large XDATA.
unsigned char _sdcc_external_startup (void)
{
  PCA0MD &= ~0x40;              // Disable watchdog.
  return 0xFF;
}


// Global error handling;
__bit errorThrown;

// Initialized or not. Use lex handle if autoexec.lf is present.
__bit hasRunAuto;
extern __xdata uint8_t infh;
extern __xdata char    STR[];


void main(void)
{
  init51();                     // Crossbar, I/O pin setup.
  hasRunAuto = 0;               // We haven't run autoexec.lf

  initUART0();                  // Serial port I/O.
  EA = 1;                       // Interrupts for the pause/Morse code timers.

  // Hardware initialization.
  initI2C();                    // I2C for synthesizer.
  initDS1085();                 // Frequency synthesizer.
  initMorse();                  // TIMER3 and morse code setup.
  initA2D();                    // A2D and temperature init.

  // Wait some milliseconds for ds1085 to get over itself.
  waitMS(DS1085WAIT);

  // If voltage bad do software reset and init all over again.
  if (RSTSRC & 0x02) RSTSRC = 0x10;

  // Software reset from CLI comes here.
 doreset:
  putstring("lfxmit V");
  putbyte(VERSION);
  putch('.');
  putbyte(RELEASE);
  putch('.');
  putbyte(PATCH);
  putstring(" on " PROCESSOR " " BOARD "\n");

  //  putstring("RSTSRC = 0x"); puthexbyte(RSTSRC); terpri();
  // See ds1085.c - only it knows the frequency.
  showBand();

  putstring("  D-space "); putuint16(DSIZE); putstring(" bytes\n");
  putstring("  I-space "); putuint16(ISIZE); putstring(" bytes\n");
  putstring("  Symtab  "); putbyte(SSIZE);  putstring(" entries\n");
  putstring("  Loops   "); putbyte(FORDEPTH); putstring(" nested\n");

  initProgram();                // No program.
  initDynamic();                // Dynamic storage.
  initSymtab();                 // Symbol table.
  initFS();                     // Initialize file system.
  initLex();                    // Lexical setup.
  initInts();                   // Integer values.
  initParse();                  // Parser stack setup.
  resetFOR();                   // Resets FOR table.

  // If autoexec.lf is present, then run it.
  if (!hasRunAuto)
  {
    strCpy(STR, "autoexec.lf");
    infh = openFile(STR);
    if (infh != 255)
    {
      loadProgramFile();
      closeFile(infh);
      if (errorThrown)
        putstring("autoexec.lf fails\n");
      else
        runAfterLoad();
    }
    infh = serialIn;
  }

  // Set flag so we don't try it again.
  hasRunAuto = 1;
  
  
  cmd();                        // Command line interface.
  goto doreset;                 // Comes here from the reset command.
}


// EOF
