/* please put some text you'll search for one day here */

// version zero. 2S, just the four ohm load (2 amp nominal)
// report 1/s, toggle 10 seconds

// v2 on the way to a flight profile. for now, just using the 2 ohm load
// v3 first flioght profile idea, out to the wokwi and back...

// back from wokwi with power fight tm 

# include "jbutton.h"

# define oneOhm	10
# define twoOhm	9
# define fourOhm	8

byte currentLoad = 0;
unsigned long currentTotal;
unsigned long flightCount;
unsigned long startTest;

unsigned long now;

# undef SIM

enum mode {IDLE, RUNNING, RESTING} testState;

# define KILL	6
# define START	2
# define STIFLE 3

# define BLOW 11

# define IND0 7
# define IND1 3

jButton kickStart;

// unit is inverse ohms or "amps"
//const byte flight[] = {0, 0, 0, 1, 1, 1, 4, 4, 8, 1, 1, 1, 8, 4, 4, 1, 1, 1, 0, 0, 0,};
// const byte flight[] = {0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0,};

// const byte flight[] = {0, 0, 0, 1, 1, 1, 2, 2, 4, 2, 2, 2, 4, 2, 2, 1, 1, 1, 0, 0, 0,};

const byte flight0[] = {
	0,0,0,0,0,0,0,
	1,1,1,1,1,1,1,
	1,2,
	2,2,4,  
	     1,1,0,1,1,
	2,2,4,
	    1,1,0,1,1,
	2,4,2,
	    1,1,0,1,1,
	4,2,2,
	    1,1,0,1,1,
	4,2,2,
	2,1,
	1,1,1,1,1,1,1,
	1,1,1,1,0,0,0,0,0,
};

const byte flight[] = {
2,4,
2,2,4,2,2, 1,1,1,1,1, 4,2,2, 1,1,1,1,1, 2,4,4,2, 1,1,1,1,1, 2,4,2,2,
1,1,0,0,0,0,0,
};

const byte flight1[] = {
2,4,
1,1,1,1,1,1,1,1,1, 1,1,1,1,1, 2,2,2, 2,2,2,2,2,2,2 ,2,2,0,0,0,0,0,
};

const byte flightLength = sizeof flight / sizeof *flight;

void setup()
{
  mySetup(115200);


# ifdef SIM
  xprintf("\nhello world.\n");
# else
  xprintf("\nhello REAL world.\n");
  xprintf("flight length %d\n", flightLength);
# endif

  pinMode(KILL, INPUT_PULLUP);
  pinMode(STIFLE, INPUT_PULLUP);
  pinMode(IND0, OUTPUT);
  pinMode(IND1, OUTPUT);
  pinMode(BLOW, OUTPUT);


  reset();
  analysis();
  
  kickStart.begin(START);

//  analysis(); for (; ; );
//  for (; ; ) testLamps();

}

void testLamps()
{
	for (; ; ) 
		for (unsigned char oh = 0; oh < 8; oh++) {
			turnLoad(oh);
			delay(400);
		}
}

void testLamps0()
{

delay(300);
  digitalWrite(oneOhm, HIGH);
  digitalWrite(twoOhm, HIGH);
  digitalWrite(fourOhm, HIGH);

delay(300);
  digitalWrite(oneOhm, LOW);
  digitalWrite(twoOhm, LOW);
  digitalWrite(fourOhm, LOW);
}

unsigned int count[3] = {0, 0, 0};

void resetReport()
{
  currentTotal = 0;
  for (unsigned char ii = 0; ii < 3; ii++) count[ii] = 0;
}

void accumulate()
{
  currentTotal += currentLoad;
  flightCount++;

  if (digitalRead(oneOhm) == HIGH) ++count[2];
  if (digitalRead(twoOhm) == HIGH) ++count[1];
  if (digitalRead(fourOhm) == HIGH) ++count[0];
}

void pReport()
{
  xprintf("\nFlight length %ld units\n", flightCount);
  xprintf("\n time in millis %ld\n", now - startTest);

  unsigned char mask = 1;
  for (unsigned char oh = 0; oh < 3; oh++, mask <<= 1)
    xprintf("%d at %d  ", count[oh], mask);
  
  xprintf("\n");
}

void analysis()
{
	unsigned char mask;
	
	for (unsigned char ii = 0; ii < flightLength; ii++) {
		mask = 1;
		for (unsigned char oh = 0; oh < 3; oh++, mask <<= 1)
		  if (flight[ii] & mask) ++count[oh];
	}
	
	mask = 1;
	for (unsigned char oh = 0; oh < 3; oh++, mask <<= 1)
		xprintf("%d of %d  ", count[oh], mask);

	xprintf("\n");
}

static bool once;

void reset()
{
  pinMode(oneOhm, OUTPUT);
  pinMode(twoOhm, OUTPUT);
  pinMode(fourOhm, OUTPUT);

// no load
  digitalWrite(oneOhm, LOW);
  digitalWrite(twoOhm, LOW);
  digitalWrite(fourOhm, LOW);

  resetReport(); 
  once = false;
  testState = IDLE;
}


// now - enhance so that if the time < MAX (3000, say) then the power is logged at the average of Vn-1 and Vn
// flag an error if a change from needing any power comes after MAX - why was load switched on unsupervised?
void turnLoad(byte theLoad)
{
// 1/ohm load oneL is but 1 ohm switched in it gets the MSB
  digitalWrite(oneOhm, theLoad & 0x4 ? HIGH : LOW);		  // 1 ohm 100 
  digitalWrite(twoOhm, theLoad & 0x2  ? HIGH : LOW);		// 2 ohm 010
  digitalWrite(fourOhm, theLoad & 0x1 ? HIGH : LOW);		// 4 ohm 001

// power will be in watt seconds 100 v * 100 v / r * millisconds          // * 1000 * 10000
}

const float lowBatt = 3.55;
const float terminateTest = 3.33;



bool doWork;
bool checkPrint;

void runTestFSM()
{
  switch (testState) {
  case IDLE :
    break;

  case RUNNING :
    break;
  }
}

# define TICK 777

void loop()
{
	static int counter;
	static unsigned long lastTime;
	static unsigned char wCount;

  checkPrint = digitalRead(STIFLE) == HIGH;
  float voltage = getCV();
	now = millis();

  digitalWrite(BLOW, voltage < lowBatt ? HIGH : LOW);

  if (voltage < terminateTest || digitalRead(KILL) == LOW) {
//  int ivoltage = 1000 * voltage;
//  xprintf("stop at %d\n", ivoltage);


  
//if (digitalRead(KILL) == LOW) {
		// no load
	  turnLoad(0);

	  if (doWork) {
	  	Serial.print("STOP at ");
		  Serial.println(voltage);
	  	Serial.println("\n\n              LOAD REMOVED!");
	  }
	  doWork = false;
	}

  kickStart.update();	
  if (kickStart.uolPress()) {
    reset();
    wCount = 0;
    doWork = true;
  }


	if (now - lastTime < TICK) return;
	lastTime = now;



	if (doWork) {

// read last tick power and log it
    accumulate();

	  currentLoad = flight[wCount];
	  turnLoad(currentLoad);
//	  xprintf("%2d %x  ", wCount, currentLoad); // the load being switched to
	  
	
	  wCount++;	
	  if (wCount >= flightLength)
	    wCount = 0;
	}
	else {
		turnLoad(0);

		static unsigned long lastVPrint;
		
		if (!once++) {
      pReport();
			Serial.println("           not under load now.");
			lastVPrint = 0;
		}

if (checkPrint)
		if (now - lastVPrint > 13000) {
			Serial.print("+");
			Serial.print(getCV()); Serial.print("  ");
			Serial.println(millis());
			lastVPrint = now;
		}
	}

	if (doWork) {
		static unsigned long lastPrint;
 		if (now - lastPrint > 5000) {
      xprintf("%2d %x  ", wCount, currentLoad); // the load being switched to

      Serial.print(millis()); Serial.print(" ");
      Serial.print(" : ");
      Serial.print(voltage); Serial.print(" ");
      Serial.println("");
      lastPrint = now;
    }

//	if (voltage < lowBatt && doWork) Serial.println("                    LAND NOW!");

  }

	counter++;

// no floats	xprintf("%5d reading %4d volts %4d\n", counter, reading, voltage);
}

// return the adjusted average cell voltage.
// currently QND matches the voltage divider for 2S
// measurement is of entire battery

float getCV()
{
  const float scale2S = 0.005;		// adjust for 1/2 Vbatt, average cell voltage
  static unsigned long counter = 0;
  static float voltage = 7.4;		// just so it doen't trip right away

  float reading = analogRead(A1);	
  voltage = (reading / 755.5 * 738.5 + 0.5) * scale2S;

  if (0) {
    Serial.print(counter); Serial.print(" "); counter++;
    Serial.print(reading, 3); Serial.print(" ");
    Serial.print(voltage); Serial.print(" ");
    Serial.println("");
  }

  return voltage;
}

// 

// programmer misses printf...

void xprintf(const char *format, ...)
{
  char buffer[256];
  va_list args;
  va_start(args, format);
  vsprintf(buffer, format, args);
  va_end(args);
  Serial.print(buffer);
}

// programmer forgets day of week, version

void mySetup(unsigned long bandRate)
{
  Serial.begin(bandRate);
  
  char s[] = __FILE__;
  byte b = sizeof(s);
  while ( (b > 0) && (s[b] != 47)) b--;
  char *u = s + b + 1;
 
  xprintf("\nHEllo WOrld!\n");
  xprintf("%s  %s\n\n", __DATE__, u);

  xprintf("!\n");
}
STOP....WARN....CHANGE
STOP....WARN....CHANGE
KILL
START
1A
2A
4A
LOW