/*############################################################################################*/
/*############################################################################################*/
/**
 * \file    ButtonManager.c
 * \author  Thibaut LALUQUE 3D-Ouest
 * \date    20/11/2014
 * \version 1.0
 * \brief 	Source file for button management.
 * \details All Right Reserved.
 */
/*############################################################################################*/
/*############################################################################################*/


/*############################################################################################*/
/*## INCLUDES ################################################################################*/
/*############################################################################################*/
#include "ButtonManager.h"
/*############################################################################################*/
/*## END INCLUDES ############################################################################*/
/*############################################################################################*/

/*############################################################################################*/
/*## CONFIGURATION BITS ######################################################################*/
/*############################################################################################*/

/*############################################################################################*/
/*## END CONFIGURATION BITS ##################################################################*/
/*############################################################################################*/

/*############################################################################################*/
/*## LOCAL DEFINES ###########################################################################*/
/*############################################################################################*/

/*############################################################################################*/
/*## END LOCAL DEFINES ######################################################################*/
/*############################################################################################*/


/*############################################################################################*/
/*## LOCAL FONCTIONS DECLARATION #############################################################*/
/*############################################################################################*/
void ButtonManagerDealer (void);

void ButtonManagerDisplayProgrammedError (void);
void ButtonManagerDisplayDateError (void);
void ButtonManagerDisplayRfidError (void);
void ButtonManagerDisplayRead (void);
void ButtonManagerDisplayWrite (void);
void ButtonManagerDisplayWriteError (void);
void ButtonManagerDisplayLogError (void);
void ButtonManagerDisplayNone (void);
/*############################################################################################*/
/*## END LOCAL FONCTIONS DECLARATION #########################################################*/
/*############################################################################################*/


/*############################################################################################*/
/*## LOCAL VARIABLES #########################################################################*/
/*############################################################################################*/
tButtonState lastWriteBpState = BUTTON_RELEASED;
tButtonState lastReadBpState = BUTTON_RELEASED;
tButtonState waitAllUnpressed = BUTTON_RELEASED;
unsigned long writeBpMsRef = 0;
unsigned long readBpMsRef = 0;
/*############################################################################################*/
/*## END LOCAL VARIABLES #####################################################################*/
/*############################################################################################*/

/*############################################################################################*/
/*## GLOBAL VARIABLES ########################################################################*/
/*############################################################################################*/
tButtonManagerCtrl ButtonManagerCtrl;
/*############################################################################################*/
/*## END GLOBAL VARIABLES ####################################################################*/
/*############################################################################################*/


/*############################################################################################*/
/*## LOCAL FONCTIONS #########################################################################*/
/*############################################################################################*/
void ButtonManagerDealer (void) {

	static unsigned long msRef = 0;

	switch (ButtonManagerCtrl.opState) {

	case BUTTONMANAGER_STATE_START :
		if(ButtonManagerCtrl.operation.bits.read) {
			RFIDCtrl.request.bits.read = 1;
			ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_WAIT_RFID;
		} else if (ButtonManagerCtrl.operation.bits.write) {
			RFIDCtrl.request.bits.write = 1;
			ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_WAIT_RFID;
		} else {
			ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_FINISH;
		}
		break;

	case BUTTONMANAGER_STATE_WAIT_RFID :
		if(ButtonManagerCtrl.operation.bits.read) {
			if(RFIDCtrl.state == RFID_STATE_STANDBY && RFIDCtrl.request.bits.read == 0) {
				if(RFIDCtrl.result == RFID_RESULT_OK) {
					unsigned short result = MemoryManagerWriteLog(RtcGetTime(),MEMORYMANAGER_READ_OPERATION,&SRDEeprom);
					if(result == 0) {
						ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_RFID_READ;
					} else {
						ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_LOG_ERROR;
					}
				} else {
					ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_RFID_ERROR;
				}
			}
		}


		if(ButtonManagerCtrl.operation.bits.write) {
			if (RFIDCtrl.state == RFID_STATE_STANDBY && RFIDCtrl.request.bits.write == 0) {
				if(RFIDCtrl.result == RFID_RESULT_OK) {

					unsigned short result = MemoryManagerWriteLog(RtcGetTime(),MEMORYMANAGER_WRITE_OPERATION,&SRDEeprom);

					//Check data written
					if(SRDEeprom.activationDepth == DivingParameters.depth && SRDEeprom.filterLSB == DivingParameters.filterLSB && SRDEeprom.filterMSB == DivingParameters.filterMSB) {
						if(result == 0) {
							ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_RFID_WRITE;
						} else {
							ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_LOG_ERROR;
						}
					} else {
						ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_RFID_WRITE_ERROR;
					}

				} else {
					ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_RFID_ERROR;
				}
			}
		}
		break;

	case BUTTONMANAGER_STATE_DISPLAY_RFID_ERROR :
		LedSet(LED_RED);
		LedClear(LED_GREEN);
		ButtonManagerDisplayRfidError();
		msRef = TickGetMsCounter();
		ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_WAIT_TIME;
		break;

	case BUTTONMANAGER_STATE_DISPLAY_LOG_ERROR :
		LedSet(LED_GREEN);
		LedClear(LED_RED);
		ButtonManagerDisplayLogError();
		msRef = TickGetMsCounter();
		ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_WAIT_TIME;
		break;

	case BUTTONMANAGER_STATE_DISPLAY_RFID_WRITE_ERROR :
		LedSet(LED_RED);
		LedClear(LED_GREEN);
		ButtonManagerDisplayWriteError();
		msRef = TickGetMsCounter();
		ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_WAIT_TIME;
		break;

	case BUTTONMANAGER_STATE_DISPLAY_RFID_WRITE :
		LedSet(LED_GREEN);
		LedClear(LED_RED);
		ButtonManagerDisplayWrite();
		msRef = TickGetMsCounter();
		ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_WAIT_TIME;
		break;

	case BUTTONMANAGER_STATE_DISPLAY_RFID_READ :
		LedSet(LED_GREEN);
		LedClear(LED_RED);
		ButtonManagerDisplayRead();
		msRef = TickGetMsCounter();
		ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_DISPLAY_WAIT_TIME;
		break;

	case BUTTONMANAGER_STATE_DISPLAY_WAIT_TIME :
		if(TickMilliSecElapsedFrom(msRef)  >= BUTTON_MANAGER_TIME_MS_DISPLAY) {
			ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_WAIT_RELEASE;
		}
		break;

	case BUTTONMANAGER_STATE_WAIT_RELEASE :
		if(ButtonReadGetState() == BUTTON_RELEASED && ButtonWriteGetState() == BUTTON_RELEASED) {
			ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_FINISH;
		}
		break;

	case BUTTONMANAGER_STATE_FINISH :
		ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_STANDBY;
		ButtonManagerCtrl.operation.all = 0;
		break;

	default :
		ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_STANDBY;
		ButtonManagerCtrl.operation.all = 0;
		break;

	}

}

void ButtonManagerDisplayProgrammedError (void) {

	char data[DISPLAY_TOTAL_DIGIT] = {'P','e','r','r'};

	DisplaySetPower(DISPLAY_POWER_ON);
	DisplaySetDataDisplayed(data);
}

void ButtonManagerDisplayDateError (void) {

	char data[DISPLAY_TOTAL_DIGIT] = {'D','e','r','r'};

	DisplaySetPower(DISPLAY_POWER_ON);
	DisplaySetDataDisplayed(data);

}

void ButtonManagerDisplayRfidError (void) {

	char data[DISPLAY_TOTAL_DIGIT] = {'R','e','r','r'};

	DisplaySetPower(DISPLAY_POWER_ON);
	DisplaySetDataDisplayed(data);
}

void ButtonManagerDisplayRead (void) {

	char data[DISPLAY_TOTAL_DIGIT] = {0};

	unsigned char nbr = SRDEeprom.activationDepth;

	data[DISPLAY_TOTAL_DIGIT-1] = (nbr % 10) + '0';
	nbr /= 10;
	if(nbr != 0) {
		data[DISPLAY_TOTAL_DIGIT-2] = (nbr % 10) + '0';

		nbr /= 10;
		if(nbr != 0) {
			data[DISPLAY_TOTAL_DIGIT-3] = (nbr % 10) + '0';
		}
	}

	if(SRDEeprom.errorStatus.all != 0) {
		if(SRDEeprom.errorStatus.bits.battery) {
			data[0] = 'B';
		} else if(SRDEeprom.errorStatus.bits.supercap) {
			data[0] = 'C';
		} else if(SRDEeprom.errorStatus.bits.pressure) {
			data[0] = 'P';
		} else if(SRDEeprom.errorStatus.bits.output) {
			data[0] = 'L';
		} else if(SRDEeprom.errorStatus.bits.current) {
			data[0] = 'A';
		} else if(SRDEeprom.errorStatus.bits.eeprom) {
			data[0] = 'E';
		} else if(SRDEeprom.errorStatus.bits.timer) {
			data[0] = 'T';
		} else if(SRDEeprom.errorStatus.bits.watchdog) {
			data[0] = 'W';
		}
	}

	DisplaySetPower(DISPLAY_POWER_ON);
	DisplaySetDataDisplayed(data);
}

void ButtonManagerDisplayWrite (void) {

	char data[DISPLAY_TOTAL_DIGIT] = {0};

	unsigned char nbr = SRDEeprom.activationDepth;

	data[DISPLAY_TOTAL_DIGIT-1] = (nbr % 10) + '0';
	nbr /= 10;
	if(nbr != 0) {
		data[DISPLAY_TOTAL_DIGIT-2] = (nbr % 10) + '0';

		nbr /= 10;
		if(nbr != 0) {
			data[DISPLAY_TOTAL_DIGIT-3] = (nbr % 10) + '0';
		}
	}

	/*if(SRDEeprom.errorStatus.all != 0) {
		if(SRDEeprom.errorStatus.bits.battery) {
			data[0] = 'B';
		} else if(SRDEeprom.errorStatus.bits.current) {
			data[0] = 'A';
		} else if(SRDEeprom.errorStatus.bits.eeprom) {
			data[0] = 'E';
		} else if(SRDEeprom.errorStatus.bits.output) {
			data[0] = 'F';
		} else if(SRDEeprom.errorStatus.bits.pressure) {
			data[0] = 'P';
		} else if(SRDEeprom.errorStatus.bits.supercap) {
			data[0] = 'C';
		} else if(SRDEeprom.errorStatus.bits.timer) {
			data[0] = 'T';
		} else if(SRDEeprom.errorStatus.bits.watchdog) {
			data[0] = 'W';
		}
	}*/

	DisplaySetPower(DISPLAY_POWER_ON);
	DisplaySetDataDisplayed(data);
}

void ButtonManagerDisplayWriteError (void) {
	char data[DISPLAY_TOTAL_DIGIT] = {'W','E','r','r'};

	DisplaySetPower(DISPLAY_POWER_ON);
	DisplaySetDataDisplayed(data);
}

void ButtonManagerDisplayLogError (void) {
	char data[DISPLAY_TOTAL_DIGIT] = {'E','L','o','g'};

	DisplaySetPower(DISPLAY_POWER_ON);
	DisplaySetDataDisplayed(data);
}

void ButtonManagerDisplayNone (void) {
	char data[DISPLAY_TOTAL_DIGIT] = {0};

	DisplaySetPower(DISPLAY_POWER_ON);
	DisplaySetDataDisplayed(data);
}
/*############################################################################################*/
/*## END LOCAL FONCTIONS #####################################################################*/
/*############################################################################################*/


/*############################################################################################*/
/*## EXTERNAL FONCTIONS ######################################################################*/
/*############################################################################################*/
void ButtonManagerInit (void) {
	ButtonInit();
	lastWriteBpState = BUTTON_RELEASED;
	lastReadBpState = BUTTON_RELEASED;
	writeBpMsRef = 0;
	readBpMsRef = 0;
	ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_STANDBY;
	ButtonManagerCtrl.operation.all = 0;
	ButtonManagerCtrl.lpm = BUTTONMANAGER_WORKING;
	waitAllUnpressed = BUTTON_RELEASED;
}

void ButtonManager (void) {
	static unsigned char state = 0;
	static unsigned long msRef = 0;

	/*=== button management for connected device ===*/
	if(PowerManagerCtrl.flags.bits.usbConnected ) {

		if(ButtonWriteGetState() == BUTTON_PRESSED && ButtonReadGetState() == BUTTON_PRESSED ) {

			ButtonManagerCtrl.lpm = BUTTONMANAGER_WORKING;

			/*-- Display current load only if battery have no error --*/
			if(PowerManagerCtrl.flags.bits.batteryError == 0) {
				DisplaySetPower(DISPLAY_POWER_ON);
				char data[DISPLAY_TOTAL_DIGIT];
				DisplayGetDataDisplayed(data);

				if(state == 0) {
					state = 1;
					msRef = TickGetMsCounter();
				}

				if(state == 1) {
					if(TickMilliSecElapsedFrom(msRef) >= 2000) {
						state = 2;
						msRef = TickGetMsCounter();
					}
					unsigned short load = BQBatteryStatus.stateOfCharge;
					data[DISPLAY_TOTAL_DIGIT-1] = (load % 10) + '0';
					load /= 10;
					if(load != 0) {
						data[DISPLAY_TOTAL_DIGIT-2] = (load % 10) + '0';
					} else {
						data[DISPLAY_TOTAL_DIGIT-2] = 0;
					}
					load /= 10;
					if(load != 0) {
						data[DISPLAY_TOTAL_DIGIT-3] = (load) + '0';
					} else {
						data[DISPLAY_TOTAL_DIGIT-3] = 0;
					}
					data[0] = 'b';
				} else {
					if(TickMilliSecElapsedFrom(msRef) >= 2000) {
						state = 1;
						msRef = TickGetMsCounter();
					}
					unsigned short load = DivingParameters.depth;
					data[DISPLAY_TOTAL_DIGIT-1] = (load % 10) + '0';
					load /= 10;
					if(load != 0) {
						data[DISPLAY_TOTAL_DIGIT-2] = (load % 10) + '0';
					} else {
						data[DISPLAY_TOTAL_DIGIT-2] = 0;
					}
					load /= 10;
					if(load != 0) {
						data[DISPLAY_TOTAL_DIGIT-3] = (load) + '0';
					} else {
						data[DISPLAY_TOTAL_DIGIT-3] = 0;
					}
					data[0] = 'd';
				}
				DisplaySetDataDisplayed(data);
			}
		} else {
			state = 0;
			ButtonManagerCtrl.lpm = BUTTONMANAGER_READY_FOR_LPM;
			if(PowerManagerCtrl.flags.bits.batteryError == 0) {
				//ButtonManagerDisplayNone();
				char data[DISPLAY_TOTAL_DIGIT];
				DisplayGetDataDisplayed(data);
				data[1] = 0;
				data[2] = 0;
				data[3] = 0;
				DisplaySetDataDisplayed(data);
			}
		}


		/*=== Button management for disconnected device ===*/
	} else {

		if(ButtonWriteGetState() == BUTTON_PRESSED && ButtonReadGetState() == BUTTON_PRESSED ) {

			ButtonManagerCtrl.lpm = BUTTONMANAGER_WORKING;
			waitAllUnpressed = BUTTON_PRESSED;

			/*-- Display current load only if battery have no error --*/
			if(PowerManagerCtrl.flags.bits.batteryError == 0) {
				char data[DISPLAY_TOTAL_DIGIT];
				DisplayGetDataDisplayed(data);
				DisplaySetPower(DISPLAY_POWER_ON);

				if(state == 0) {
					state = 1;
					msRef = TickGetMsCounter();
				}

				if(state == 1) {
					if(TickMilliSecElapsedFrom(msRef) >= 2000) {
						state = 2;
						msRef = TickGetMsCounter();
					}
					unsigned short load = BQBatteryStatus.stateOfCharge;
					data[DISPLAY_TOTAL_DIGIT-1] = (load % 10) + '0';
					load /= 10;
					if(load != 0) {
						data[DISPLAY_TOTAL_DIGIT-2] = (load % 10) + '0';
					} else {
						data[DISPLAY_TOTAL_DIGIT-2] = 0;
					}
					load /= 10;
					if(load != 0) {
						data[DISPLAY_TOTAL_DIGIT-3] = (load) + '0';
					} else {
						data[DISPLAY_TOTAL_DIGIT-3] = 0;
					}
					data[0] = 'b';
				} else {
					if(TickMilliSecElapsedFrom(msRef) >= 2000) {
						state = 1;
						msRef = TickGetMsCounter();
					}
					unsigned short load = DivingParameters.depth;
					data[DISPLAY_TOTAL_DIGIT-1] = (load % 10) + '0';
					load /= 10;
					if(load != 0) {
						data[DISPLAY_TOTAL_DIGIT-2] = (load % 10) + '0';
					} else {
						data[DISPLAY_TOTAL_DIGIT-2] = 0;
					}
					load /= 10;
					if(load != 0) {
						data[DISPLAY_TOTAL_DIGIT-3] = (load) + '0';
					} else {
						data[DISPLAY_TOTAL_DIGIT-3] = 0;
					}
					data[0] = 'd';
				}
				DisplaySetDataDisplayed(data);
			}

			/*-- Reset bp counter --*/
			lastWriteBpState = BUTTON_RELEASED;
			writeBpMsRef = 0;
			lastReadBpState = BUTTON_RELEASED;
			readBpMsRef = 0;

		} else {

			state = 0;

			if(waitAllUnpressed == BUTTON_RELEASED) {

				if(ButtonWriteGetState() == BUTTON_PRESSED) {

					ButtonManagerCtrl.lpm = BUTTONMANAGER_WORKING;

					if(MemoryManagerCtrl.isValid.bits.diving && RtcUpdatedSinceLastReset()) {

						if(lastWriteBpState == BUTTON_RELEASED) {
							lastWriteBpState = BUTTON_PRESSED;
							writeBpMsRef = TickGetMsCounter();
						} else {

							if( TickMilliSecElapsedFrom(writeBpMsRef) >= BUTTON_MANAGER_TIME_MS_TO_TRIG) {
								if(ButtonManagerCtrl.opState == BUTTONMANAGER_STATE_STANDBY) {
									ButtonManagerCtrl.operation.bits.write = 1;
									ButtonManagerCtrl.operation.bits.read = 0;
									ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_START;
								}
							}
						}
					} else {
						if(MemoryManagerCtrl.isValid.bits.diving == 0) {
							ButtonManagerDisplayProgrammedError();
						} else {
							ButtonManagerDisplayDateError();
						}
					}

				} else {
					lastWriteBpState = BUTTON_RELEASED;
					writeBpMsRef = 0;
				}


				if(ButtonReadGetState() == BUTTON_PRESSED) {

					ButtonManagerCtrl.lpm = BUTTONMANAGER_WORKING;

					if(RtcUpdatedSinceLastReset() ) {

						if(lastReadBpState == BUTTON_RELEASED) {
							lastReadBpState = BUTTON_PRESSED;
							readBpMsRef = TickGetMsCounter();
						} else {

							if( TickMilliSecElapsedFrom(readBpMsRef) >= BUTTON_MANAGER_TIME_MS_TO_TRIG) {
								if(ButtonManagerCtrl.opState == BUTTONMANAGER_STATE_STANDBY) {
									ButtonManagerCtrl.operation.bits.read = 1;
									ButtonManagerCtrl.operation.bits.write = 0;
									ButtonManagerCtrl.opState = BUTTONMANAGER_STATE_START;
								}
							}
						}
					} else {
						ButtonManagerDisplayDateError();
					}

				} else {
					lastReadBpState = BUTTON_RELEASED;
					readBpMsRef = 0;
				}

				ButtonManagerDealer();
			} else {
				ButtonManagerDisplayNone();
				if(ButtonReadGetState() == BUTTON_RELEASED && ButtonWriteGetState() == BUTTON_RELEASED) {
					waitAllUnpressed = BUTTON_RELEASED;
				}
			}

			if(waitAllUnpressed == BUTTON_RELEASED && lastReadBpState == BUTTON_RELEASED && lastWriteBpState == BUTTON_RELEASED && ButtonManagerCtrl.opState == BUTTONMANAGER_STATE_STANDBY && ButtonManagerCtrl.operation.all == 0) {
				ButtonManagerDisplayNone();
				ButtonManagerCtrl.lpm = BUTTONMANAGER_READY_FOR_LPM;
			}
		}
	}
}

/*############################################################################################*/
/*## END EXTERNAL FONCTIONS ##################################################################*/
/*############################################################################################*/
