//------------------------------------------------------------------------------
//--                                                                          --
//--  Continuously data logs MS output as fast as it can.                     --
//--  All documentation is contained within this file.                        --
//--                                                                          --
//--  Copyright (c) 2001 by Eric Fahlgren.  All rights reserved.              --
//--                                                                          --
//--  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            --
//--  2 of the License, or (at your option) any later version.                --
//--  See http://www.gnu.org/licenses/gpl.txt                                 --
//--                                                                          --
//--  For support contact <eric.fahlgren@mscsoftware.com>.                    --
//--                                                                          --
//------------------------------------------------------------------------------
//--                                                                          --
//--  History                                                                 --
//--  1.0 - Eric Fahlgren's original code.                                    --
//--                                                                          --
//------------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>

static char *rcsId = "$Id$";

#ifdef _DEBUG
#  define new DEBUG_NEW
#  undef THIS_FILE
   static char THIS_FILE[] = __FILE__;
#endif

//------------------------------------------------------------------------------

#define MAJOR 1
#define MINOR 0

static int     commPortNumber  = 1;
static HANDLE  hPortHandle     = NULL;
static char    logName[128]    = "datalog.xls";
static char   *logMode         = "a";
static FILE   *log             = NULL;
static char   *progName        = NULL;

//------------------------------------------------------------------------------

static void usage(void)
{
   // Make sure usage fits on an 80-column screen.
   //               123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789x
   fprintf(stderr, "usage: %s [-b] [-c<port>] [log-file]\n"
                   "   as in\n"
                   "\n"
                   "      %s -c2 mysquirt.log\n"
                   "\n", progName, progName); 
   fprintf(stderr, "Datalogger requires exclusive access to the comm port, it can't run beside MT\n"
                   "\n"
                   "   -o       - overwrite any existing file, default is append.\n"
                   "   -c       - specify comm port to which MegaSquirt is connected, default is\n"
                   "              port 1.\n"
                   "   log-file - the name of the log file to download, default is datalog.xls.\n"
                   "\n");
   exit(1);
} 

//------------------------------------------------------------------------------

#define AdjustI(n) {argv[iarg] += (n); if (argv[iarg][0] == '\0') ++iarg;}

static void parseArgs(int argc, char *argv[])
{
   progName = argv[0];

   for (int iarg = 1; iarg < argc; iarg++) {
      switch (argv[iarg][1]) {
         case 'o':
            logMode = "w";
            break;

         case 'c':
            AdjustI(2);
            commPortNumber = strtol(argv[iarg], NULL, 10);
            break;

         default:
            if (argv[iarg][0] == '-') usage();
            if (strcmp(logName, "datalog.xls") != 0) usage();
            strcpy(logName, argv[iarg]);
            break;
      }
   }
}

//------------------------------------------------------------------------------

#include <stdarg.h>

static void error(int exitCode, char *fmt, ...)
{
   va_list args;
   va_start(args, fmt);
      vfprintf(stderr, fmt, args);
   va_end(args);

   exit(exitCode);
}

//------------------------------------------------------------------------------

bool openCommPort()
{
   char pPortName[6];
   sprintf(pPortName, "com%d", commPortNumber);
   hPortHandle = CreateFile(pPortName,
                    GENERIC_READ | GENERIC_WRITE,
                    0,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    NULL);
   if (hPortHandle == INVALID_HANDLE_VALUE) return false;

   DCB dcb;
   if (!GetCommState(hPortHandle, &dcb)) return false;
   dcb.BaudRate = 9600;
   dcb.ByteSize = 8;
   dcb.Parity   = NOPARITY;
   dcb.StopBits = ONESTOPBIT;
   if (!SetCommState(hPortHandle, &dcb)) return false;

   COMMTIMEOUTS timeout;
   if (!GetCommTimeouts(hPortHandle, &timeout)) return false;
   timeout.ReadIntervalTimeout         =   0; // ms between chars on read.
   timeout.ReadTotalTimeoutMultiplier  =   0;
   timeout.ReadTotalTimeoutConstant    = 250;
   timeout.WriteTotalTimeoutMultiplier =   0;
   timeout.WriteTotalTimeoutConstant   =   0;
   if (!SetCommTimeouts(hPortHandle, &timeout)) return false;

   return true;
}

//------------------------------------------------------------------------------

void closeCommPort()
{
   if (hPortHandle != NULL) {
      CloseHandle(hPortHandle);
      hPortHandle = NULL;
   }
}

//------------------------------------------------------------------------------
// readCommPort - Read char from from the COM port.  Non-blocking, timeout set
// in openCommPort.

bool readCommPort(BYTE *pChar, DWORD nChars)
{
   DWORD dwActualRead;
   bool bOK = 0 != ReadFile(hPortHandle, pChar, nChars, &dwActualRead, NULL);
   if (dwActualRead != nChars) bOK = false;
   return bOK;
}

//------------------------------------------------------------------------------

bool writeCommPort(char *pBuf, DWORD dwCount)
{
   DWORD dwBytesWritten;
   bool  bOK = 0 != WriteFile(hPortHandle, pBuf, dwCount, &dwBytesWritten, NULL);
   if (dwBytesWritten != dwCount) bOK = false;
   return bOK;
}

//------------------------------------------------------------------------------

#define Rsecl      0
#define Rsquirt    1
#define Rengine    2
#define Rbaro      3
#define Rmap       4
#define Rmat       5
#define Rclt       6
#define Rtps       7
#define Rbatt      8
#define Rego       9
#define Regocorr  10
#define Raircorr  11
#define Rwarmcorr 12
#define Rrpm      13
#define Rpw       14
#define Rtpsaccel 15
#define Rbarocorr 16
#define Rgammae   17
#define Rvecurr   18
#define Rbspot1   19
#define Rbspot2   20
#define Rbspot3   21

#define Rget      22

bool getRuntime(BYTE rBuf[Rget])
{
   writeCommPort("A", 1);
   return readCommPort(rBuf, Rget);
}

//------------------------------------------------------------------------------

// Motorola MPX4115A
//double  volt[NPRES] = {  0.204,   4.794 };
//double  pres[NPRES] = { 15.0  , 115.0   };
// Motorola MPX4250
double  vLo =   0.204;
double  vHi =   4.896;
double  dV  = vHi - vLo;
double  pLo =  20.0;
double  pHi = 250.0;
double  dP  = pHi - pLo;

int kpa(BYTE adc)
{
   return int((5.0 * adc / 255.0 - vLo) / dV * dP + pLo);
}

//------------------------------------------------------------------------------

int main(int argc, char *argv[])
{
   printf("MS Datalogger %d.%02d\n", MAJOR, MINOR);

   parseArgs(argc, argv);

   if (!openCommPort())
      error(2, "Download failed:\n"
               "   Could not open comm port %d.", commPortNumber);

   int  sec = 0;
   int nSec = 0;
   int nSamples = 0;
   FILE *log = fopen(logName, logMode);
   fprintf(log, "Seconds\tRPM\tMAP\tO2\tEngineBit\tGego\tGair\tGwarm\tGbaro\tGve\tGammae\tPW\n");
   BYTE rBuf[Rget];
   while (getRuntime(rBuf)) {
      nSamples++;
      if (rBuf[Rsecl] != sec) {
         printf("%5d - %3d Hz\n", nSamples, nSec);
         sec  = rBuf[Rsecl];
         nSec = 0;
      }
      nSec++;
      fprintf(log, "%d\t%d\t%d\t%.3f\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%.1f\n",
              rBuf[Rsecl],
              rBuf[Rrpm] * 100,
              kpa(rBuf[Rmap]),
              rBuf[Rego] * 0.0195312,
              rBuf[Rengine],
              rBuf[Regocorr],
              rBuf[Raircorr],
              rBuf[Rwarmcorr],
              rBuf[Rbarocorr],
              rBuf[Rvecurr],
              rBuf[Rgammae],
              rBuf[Rpw]/10.0);
      fflush(log);
   }
   fclose(log);
   closeCommPort();
   exit(0);
   return 0; // So lint doesn't complain.
}

//------------------------------------------------------------------------------

