/* hc08pgm.cpp
 * Stefano Salvi - 8/12/2002
 * Programma per scaricare sulla scheda GPC2 un file .hex da riga di comando.
 * per default scarica il file "protocol.hex" ed usa la seriale "/dev/ttyS0"
 * Accetta i seguenti paramentri:
 *  -f<file sa scaricare> indica che file '.hex' scaricare (default protocol.hex)
 *  -s<seriale> indica il percorso per il dispositivo seriale (default /dev/ttyS0)
 *  -d non far partire il file scaricato (scarica e basta)
 *  -r non scaricare alcun file (avvia il programma sulla scheda)
 * Componenti:
 * MC68HC908LB8CPE  PDIP 20   N   COMMERCIAL, INDUSTRIAL              Available   $2.45 (sample)
 * MC908QB8MPE      PDIP 16   N   COMMERCIAL, INDUSTRIAL, AUTOMOTIVE  Available   $1.62 (sample)
 * MC68HC908QT4CPE  PDIP 8    N   COMMERCIAL, INDUSTRIAL              Available   $0.99 (no sample)
 * MC68HC908QY2CPE  PDIP 16   N   COMMERCIAL, INDUSTRIAL              Available   $0.93 (no sample)
 * MC68HC908GP32CP  PDIP 40   N   COMMERCIAL, INDUSTRIAL, AUTOMOTIVE  Not Recommended for New Design  $5.50 (Sample)
 *
 * Riconoscimento processori:
 * (da nota tecnica an1831)
 * - Diemsioni e limiti RAM:
 *                      RAM  ROWSIZ COMMPORT FLBPR    Put_Byte
 * MC68HC908EY16         $40   32     PTA0    $FF7E      --
 *
 * MC68HC908GR4/8(A)     $40   32     PTA0    $FF7E    $FEAA
 *
 * MC68HC908GT16         $40   32     PTA0    $FF7E      --
 *
 * MC68HC908JB8          $40   64     PTA0    $FE09    $FED6
 *
 * MC68H(R/L)C908JK1(E)  $80   32     PTB0    $FE09    $FED0
 * MC68H(R/L)C908JK3E)
 * MC68H(R/L)C908JL3(E)
 *
 * MC68HC908KX2/8        $40   32     PTA0    $FF7E    $FEAA
 *
 * MC68HC908QT1/2/4      $80   32     PTA0    $FFBE    $FEA1
 * MC68HC908QY1//2/4
 *
 * MC68HLC908QT1/2/4     $80   32     PTA0    $FFBE    $FE9F
 * MC68HLC908QY1/2/4
 *
 * MC68HC908GP32         $40   64     PTA0    $FF7E    $FEAA
 *
 * MC68HC908LB8          $80   32                      $0381
 * MC68HC908QL4          $80   32                      $2B81
 * MC68HC908QY4A         $80   32                      $280F
 * Series(1)
 * MC68HC908QB4/QB8,     $80   32                      $280F
 * MC68HC908QY8

 GET_PUT       EQU      $FE97                ;MON RTN TO GET A BYTE ON
                                            ;PTA0 AND ECHO BACK
PUT_BYTE      EQU      $FEAA                ;SEND A BYTE OUT PTA0

 * Indirizzi routine ROM:
 *                   GETBYTE RDVRRNG ERARNGE   PRGRNGE DELNUS
 * MC68HC908EY16      $1000    $1003   $1006     $1009  $100C
 *
 * MC68HC908GR4(A)    $1C99   $1CAD    $1DA0     $1CEC   $1D96
 * MC68C908GR8(A)
 *
 * MC68HC908GT16      $1B50   $1B53    $1B56     $1B59  $1B5C
 *
 * MC68HC908JB8       $FC00   $FC03    $FC06     $FC09   $FC0C
 *
 * MC68HC908JL1(E)    $FC00   $FC03    $FC06     $FC09   $FC0C
 * MC68HC908JK3(E)
 *
 * MC68HC908KX2       $1000    $1003   $1006     $1009  $100C
 * MC68HC908KX8
 *
 * MC68HC908QT1/2/4   $2800    $2803   $2806     $2809  $280C
 * MC68HC908QY1/2/4
 *
 * MC68HLC908QT1/2/4  $2800    $2803   $2806     $2809  $280C
 * MC68HLC908QY1/2/4

 * MC68HC908LB8       $037E    $0384   $0387     $038A  $038D
 * MC68HC908QL4       $2B7E    $2B84   $2B87     $2B8A  $2B8D
 * MC68HC908QY4A      $2800    $2803   $2806     $2809  $280C
 * Series(1)
 * MC68HC908QB4/QB8,  $2800    $2803   $2806     $2809  $280C
 * MC68HC908QY8

 *
 * Fingerprint (tentativo):
 *            GP32    QT4     QY4       LB8       QB8
 *  $2800
 * (GETBYTE QT1/2/4, QY1/2/4, HLC908QT1/2/4, HLC908QY1/2/4)
 *  $2803
 * (RDVRRNG QT1/2/4, QY1/2/4, HLC908QT1/2/4, HLC908QY1/2/4)
 *  $2806
 * (ERARNGE QT1/2/4, QY1/2/4, HLC908QT1/2/4, HLC908QY1/2/4)
 *  $2809
 * (PRGRNGE QT1/2/4, QY1/2/4, HLC908QT1/2/4, HLC908QY1/2/4)
 *  $280C
 * (DELNUS QT1/2/4, QY1/2/4, HLC908QT1/2/4, HLC908QY1/2/4)
 *  $FE9F
 * (PutByte HLC908QT1/2/4, HLC908QY1/2/4)
 *  $FEA1
 * (PutByte QT1/2/4, QY1//2/4)
 *  $FEAA
 * (Put_Byte gp32, GR4/8, KX2/8)
 *  $FED0
 * (Put_Byte JK1, JK3, JL3)
 *  $FED6
 * (Put_Byte JB8)
 * LED:
 * pongo un LED verso massa in parallelo ad una delle resistenze di pull-down
 * per fare degli esperimenti.
 * Il LED in questione e':
 * QT:  Pin 3     PTA4
 * QY:  Pin 5     PTA4
 * GP:  Pin 8     PTC1
 * 20p: Pin 13
 * 28p: Pin 18
 */

#include <stdio.h>
#include <stdlib.h>


#include "com.h"
#include "hc08monitor.h"
#include "debug.h"
#include "exception.h"
#include "printer.h"
#include "fullscreen.h"

#include "platform.h"

#ifndef __MINGW32_VERSION
#define FALSE 0
#ifndef TRUE
#define TRUE  (!FALSE)
#endif
#endif

void parerr (const char *nome);
void sigTest (Debug *dbg);

// void flushInput (void);
// int getInt (void);

#ifdef __MINGW32_VERSION
/* Dev C++ che usa MingWin sotto Windows */
char ttyName [] = "COM1";
#else
// char ttyName [] = "/dev/ttyS0";
char ttyName [] = "/dev/ttyUSB0";
#endif
char *ttyN = ttyName;

#define NOOP        0
#define PROGRAM     1
#define TESTERASED  2
#define READIT      3
#define CLEARIT     4
#define TESTIT      5
#define RUNIT       6
#define STEPIT      7
#define SIGTEST     8
#define EMULATE     9

/* Programma principale */
int main (int argc, char **argv)
{
int i;
int operation = NOOP;
const char *hexFile = "";                  // Nome del file da scaricare
int n = 0;
int s;
int start,end;
Printer prt;
Debug *dbg = new Debug (&prt);

  // Loop di analisi dei parametri
  for (i = 1; i < argc; i++) {
    if (argv [i][0] == '-') {
      switch (argv [i][1]) {
        case 'p' :  // Program
          hexFile = argv [++i];
          operation = PROGRAM;
          break;
        case 's' :  // Serial
          ttyN = argv [++i];
          printf ("Utilizzo seriale %s\n", ttyN);
          break;
        case 'e' :  // Controlla se il chip e' cancellato
          operation = TESTERASED;
          break;
        case 'r' :  // Legge il contenuto della ROM/Memoria
          start = strtol (argv [++i], NULL, 0);
          end = strtol (argv [++i], NULL, 0);
          operation = READIT;
          break;
        case 'c' :  // Cancella il chip
          operation = CLEARIT;
          break;
        case 't' :  // Test comunicazione
          operation = TESTIT;
          break;
        case 'g' :  // Go
          hexFile = argv [++i];
          operation = RUNIT;
          break;
        case 'd' :  // Go
          hexFile = argv [++i];
          operation = STEPIT;
          break;
        case 'f' :  // Emulate
          hexFile = argv [++i];
          operation = EMULATE;
          break;
        case 'S' :  // Signal Test
          operation = SIGTEST;
          break;
        default :
          parerr (argv [0]);
      }
    } else {
      parerr (argv [0]);
    }
  }

  if (operation == EMULATE) {
    FullScreen *f = new FullScreen (dbg);
    f->run(hexFile);  // non ha aperto la seriale, quindi non la chiude
    exit (0);
  }

  try {
    printf ("hc08pgm - programmazione HC08\n");
    dbg->setupCom (ttyN);  // Imposta la seriale a 9600 Baud

    switch (operation) {
      case PROGRAM :
        dbg->programChip (hexFile);
        break;
      case TESTERASED :
        n = dbg->isErased (NULL);
        if (!n) {
          printf ("La ROM e' cancellata\n");
        } else {
          printf ("La ROM e' prgrammata\n");
        }
        break;
      case READIT :
        dbg->readCip (start, end);
        break;
      case CLEARIT :
        dbg->clearChip ();
        break;
      case TESTIT :
        dbg->testChip ();
        break;
      case RUNIT :
        dbg->runPgm (hexFile);
        break;
      case STEPIT :
        dbg->stepPgm (hexFile);
        break;
      case SIGTEST :
        sigTest (dbg);
        break;
      default:
        break;
    }
  } catch (Exception *e) {
    dbg->closeCom();
    printf ("ERRORE: %s (Errore: %s)\n", e->message, e->error ());
/*
    printf ("Premi un tasto per continuare");
    getchar ();
 */
    printf ("\n");
    // dbg->mysleep (10000000); // 10 second wait after error
    dbg->closeCom();
    exit (1);
  }

  dbg->closeCom();
  // mysleep (3000000);

  return 0;
}

/* Stampa messaggio di errore per i parametri e termina
 */
void parerr (const char *nome)
{
  fprintf (stderr, "Errore. Uso:\n%s [-s <seriale>] [-p <file S19>] [-e] [-e <file S19>] [-r <start> <end>] [-c] [-t]\n"
    "-s <seriale> indica il percorso per il dispositivo seriale\n  (default %s)\n"
    "-p <file S19> programma il file S19 nel chip\n"
    "-e controlla se il chip e' cancellato\n"
    "-f emula il processore in un debugger a pieno schermo\n"
    "-r <start> <end> legge dal chip i byte da <start> a <end>\n"
    "  (start e end in decimale o esadecimala indicando 0xHHHH)\n"
    "-c Cancella il chip\n"
    "-t esegue un ciclo infinito di test\n"
    "-g <file S19> manda in esecuzione il file S19 precedentemete programmato nel chip\n"
    "-d <file S19> manda in single step il file S19 precedentemete programmato nel chip\n"
    "-S Test dei segnali (RTS/DTR)\n",
    nome, ttyName);
  exit (1);
}

void sigTest (Debug *dbg)
{
char selstr [10];
int sel;
int dtr = 0, rts = 0;
    dbg->dtrOff();
    dbg->rtsOff();
    do {
      printf ("1) Commuta DTR (ora %s)\n", (dtr) ? "ON" : "OFF");
      printf ("2) Commuta RTS (ora %s)\n", (rts) ? "ON" : "OFF");
      printf ("3) Esci\n\nFai la tua scelta > ");
            fgets (selstr, 9, stdin);
      sel = strtol (selstr, NULL, 0);
      switch (sel) {
        case 1 :
          dtr = !dtr;
          if (dtr) {
                  dbg->dtrOn();
          } else {
                  dbg->dtrOff();
          }
          break;
        case 2 :
          rts = !rts;
          if (rts) {
                  dbg->rtsOn();
          } else {
                  dbg->rtsOff();
          }
          break;
      }
    } while (sel != 3);
}

