/*
 * pwr_save.h
 *
 *  Created on: Aug 22, 2021
 *      Author: mateusz
 */

#ifndef PWR_SAVE_H_
#define PWR_SAVE_H_

#include <stored_configuration_nvm/config_data.h>
#include "station_config_target_hw.h"

/**
 * This header file defines all functions related to powersaving, switching between different power states,
 * stopping cpu core etc. Generally they are few power states as below
 *
 * /-------------------------------------------------------------------------\
 * | State |  CPU  |   +5V_S  	| +7V5_R and VBATT_SW_R  |  +4V_G  |  +5V_C  |
 * |       |       | VBATT_SW_S |                        |         |         |
 * =-------------------------------------------------------------------------=
 * |   C0  |Running|   ON    	|           ON           |   ON    |   ON    |
 * |   C1  |Running|   ON    	|           ON           |   OFF   |   ON    |
 * |   C2  |Running|   OFF   	|           ON           |   OFF   |   ON    |
 * |   C3  |Running|   OFF   	|           ON           |   ON    |   ON    |
 * |   M4  |Running|   ON    	|           OFF          |   OFF   |   ON    |
 * |   M4a |Running|   ON    	|           OFF          |   ON	   |   ON    |
 * |   I5  |Running|   OFF   	|           OFF          |   OFF   |   OFF   |
 * |   L6  | Stop2 |   OFF   	|           OFF          |   ON    |   OFF   |
 * |   L7  | Stop2 |   OFF   	|           OFF          |   OFF   |   OFF   |
 * \-------------------------------------------------------------------------/
 *
 *      C = modes with communication enabled
 *      M = mode with measuremenet only w/o any communication
 *      I = idle / initialization mode with anything disabled
 *      L = low power consumption modes with CPU halted in STOP2 mode
 *
 *	What is supplied by which voltage
 *	 +3V3_C - Microcontroller and UART-RS232 converter. It is always present
 *	 +4V_G - GSM module
 *	 +5V_C and +3V3_CC derived from it - LMV358 op amp, microSD Cards, PT100 interface
 *	 +5V_S and +3V3_S derived from it - Wind sensor, one wire thermometer, RS485
 *	 +7V5_R - external VHF radio
 *
 *
 *  Stop2 mode is a power saving mode defined in STM paperwork (DM0083560
 *  aka Reference Manual RM0351). This mode halts CPU core completely and
 *  disable HCLK, AHB1 & AHB2 buses, but preserves StaticRAM and registers
 *  content. 32k-LSE and RTC works normally and wakeups the core every
 *  programmed amount of seconds.
 *
 *  C0 - Mode with everything avaliable. Used when station shall works
 *  as APRS digi / igate and is (probably) powered from mains instead
 *  of PV
 *
 *  C1 - Mode with everything except GPRS modem is powered. This is
 *  default mode when station is powered from PV and works as DIGI.
 *  Digi required constant participation in radio channel traffic
 *  so VHF radio must operates constantly.
 *
 *  C2 - Simmilar to C1 but with all meteo sensors disabled. This helps
 *  save some mA of current drain (but presumably radio will consume more
 *  than sensors)
 *
 *  M4 - Measurement only mode when only meteo sensors are enabled
 *
 *  I5 - Idle / initialization mode when only micro is operating normally but
 *  all aux voltages are turned off. This is mode CPU starts after poweron/reset
 *  and wakes up from Stop2
 *
 *  L6 - This is Low power STOP2 mode with GSM radio kept in standby mode. +4V_G
 *  is powered on but GSM radio is left in most power efficient mode available.
 *  This is used when WX packet interval is shorter than 5 minutes. In such case
 *  GSM modem reinitialization and tuning & logging into network will consume more
 *  power than keeping modem on standby.
 *
 *  L7 - Deep sleep mode with everything powered off and CPU kept in STOP2 mode.
 *
 *
 *
 *  Transitions between states depends on configuration and value of config_data_powersave_mode_t.
 *  If 'powersave_keep_gsm_always_enabled' is set to one, the controller will switch to modem M4a instead of M4
 *
 *  ====================================================================================================================================|
 *  |   Mode                |   Powersave Mode  |                                                                                       |
 *  |=======================|===================|=======================================================================================|
 *  |   DIGI                |   don't care      |   Always stays in C2 no matter of how config_data_powersave_mode_t is set             |
 *  |   DIGI + WX           |   PWSAVE_NONE     |       C1                                                                              |
 *  |   DIGI + WX           |   PWSAVE_NORMAL   |       C2 --- (1 minute before WX frame)---> C1 -> C2                                  |
 *  |   DIGI + WX           |   PWSAVE_AGGRESV  |       C2 --- (1 minute before WX frame)---> C1 -> C2                                  |
 *  |   DIGI + WX + GSM     |   PWSAVE_NONE     |       C0                                                                              |
 *  |   DIGI + WX + GSM     |   PWSAVE_NORMAL   |       C2 --- (1 minute before WX frame)---> C0 -> C2  ; if WX_INTERVAL >= 5 minutes   |
 *  |   DIGI + WX + GSM     |   PWSAVE_NORMAL   |       C3 --- (1 minute before WX frame)---> C0 -> C3  ; if WX_INTERVAL < 5 minutes    |
 *  |   DIGI + WX + GSM     |   PWSAVE_AGGRESV  |       C2 --- (1 minute before WX frame)---> C0 -> C2  ; no matter WX_INTERVAL         |
 *  |   WX + GSM            |   PWSAVE_NONE     |       C0                                                                              |
 *  |   WX + GSM            |   PWSAVE_NORMAL   |       M4 --- (2 minute before WX frame)---> C0 -> M4                                  |
 *  |   WX + GSM (only)     |   PWSAVE_AGGRESV  |       L7 --- (2 minute before WX frame)---> C0 -> L7									|
 *  |   WX                  |   PWSAVE_NONE     |       M4 --- (2 minute before WX frame)---> C1 -> M4                                  |
 *  |   WX                  |   PWSAVE_NORMAL   |       L7 --- (2 minute before WX frame)---> C1 -> L7                                  |
 *  |   WX                  |   PWSAVE_AGGRESV  |       L7 --- (1 minute before WX frame)---> M4 --- (30 sec before)---> C1 -> L7       |
 *  ====================================================================================================================================|
 *
 * Note from October 31st. State machine has been changed sligtly for
 * PWSAVE_NORMAL and PWSAVE_AGGRESIVE for WX + GSM configuration. It was
 * simplified by turning GSM module off completely when it is not needed.
 * It has more sense and it is less risky, as it eliminate a possible situation
 * when GSM module will change it internal state while controller is sleeping
 * (like GPRS will die for some reason, or a SIM card will stop working)
 */


#define CURRENTLY_CUTOFF 		0x1
#define CURRENTLY_VBATT_LOW		0x8

#if defined(STM32L471xx)

extern int8_t pwr_save_currently_cutoff;

void pwr_save_init(config_data_powersave_mode_t mode);
int pwr_save_switch_mode_to_c0(void);
int pwr_save_switch_mode_to_c1(void);
void pwr_save_switch_mode_to_c2(void);
void pwr_save_switch_mode_to_c3(void);
int pwr_save_switch_mode_to_m4(void);
int pwr_save_switch_mode_to_m4a(void);
void pwr_save_switch_mode_to_i5(void);
void pwr_save_switch_mode_to_l6(uint16_t sleep_time);
void pwr_save_switch_mode_to_l7(uint16_t sleep_time);
config_data_powersave_mode_t pwr_save_pooling_handler(
											const config_data_mode_t * config,
											const config_data_basic_t * timers,
											int16_t minutes_to_wx,
											uint16_t vbatt_average,
											uint16_t vbatt_current);		// this should be called from 10 seconds pooler

int pwr_save_is_currently_cutoff(void);
#endif

uint8_t pwr_save_get_inhibit_pwr_switch_periodic(void);


#endif /* PWR_SAVE_H_ */
