@ -60,12 +60,23 @@ class DisplayMono { 
			
		
	
		
			
				
					            mLuminance  =  lum ;  
			
		
	
		
			
				
					            mDisplay - > setContrast ( mLuminance ) ;  
			
		
	
		
			
				
					         }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					         monoMaintainDispSwitchState ( ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					   protected :  
			
		
	
		
			
				
					      U8G2 *  mDisplay ;  
			
		
	
		
			
				
					      DisplayData  * mDisplayData ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      float   * mPgData = nullptr ;  
			
		
	
		
			
				
					      uint8_t  mPgWidth = 0 ;  
			
		
	
		
			
				
					      uint8_t  mPgHeight = 0 ;  
			
		
	
		
			
				
					      float    mPgMaxPwr = 0.0 ;  
			
		
	
		
			
				
					//      float   mPgMaxAvailPower = 0.0;
  
			
		
	
		
			
				
					      uint32_t  mPgPeriod = 0 ;  // seconds
  
			
		
	
		
			
				
					      uint32_t  mPgTimeOfDay = 0 ;  
			
		
	
		
			
				
					      uint8_t   mPgLastPos = 0 ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      uint8_t  mType ;  
			
		
	
		
			
				
					      uint16_t  mDispWidth ;  
			
		
	
		
			
				
					      uint16_t  mDispHeight ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -81,9 +92,16 @@ class DisplayMono { 
			
		
	
		
			
				
					      uint8_t  mExtra ;  
			
		
	
		
			
				
					      int8_t   mPixelshift = 0 ;  
			
		
	
		
			
				
					      TimeMonitor  mDisplayTime  =  TimeMonitor ( 1000  *  DISP_DEFAULT_TIMEOUT ,  true ) ;  
			
		
	
		
			
				
					      TimeMonitor  mDispSwitchTime  =  TimeMonitor ( 10000 ,  true ) ;  
			
		
	
		
			
				
					      uint8_t  mDispSwitchState  =  0 ;  
			
		
	
		
			
				
					      bool  mDisplayActive  =  true ;   // always start with display on
  
			
		
	
		
			
				
					      char  mFmtText [ DISP_FMT_TEXT_LEN ] ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      enum  _dispSwitchState  {  
			
		
	
		
			
				
					         d_POWER_TEXT  =  0 ,  
			
		
	
		
			
				
					         d_POWER_GRAPH  =  1 ,  
			
		
	
		
			
				
					      } ;  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      // Common initialization function to be called by subclasses
  
			
		
	
		
			
				
					      void  monoInit ( U8G2 *  display ,  uint8_t  type ,  DisplayData  * displayData )  {  
			
		
	
		
			
				
					         mDisplay  =  display ;  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -97,6 +115,133 @@ class DisplayMono { 
			
		
	
		
			
				
					         mDispHeight  =  mDisplay - > getDisplayHeight ( ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      void  monoMaintainDispSwitchState ( void )  {  
			
		
	
		
			
				
					         switch ( mDispSwitchState )  {  
			
		
	
		
			
				
					            case  d_POWER_TEXT :  
			
		
	
		
			
				
					               if  ( mDispSwitchTime . isTimeout ( ) )  {  
			
		
	
		
			
				
					                  mDispSwitchState  =  d_POWER_GRAPH ;  
			
		
	
		
			
				
					                  mDispSwitchTime . startTimeMonitor ( 5000 ) ;  
			
		
	
		
			
				
					               }  
			
		
	
		
			
				
					               break ;  
			
		
	
		
			
				
					            case  d_POWER_GRAPH :  
			
		
	
		
			
				
					               if  ( mDispSwitchTime . isTimeout ( ) )  {  
			
		
	
		
			
				
					                  mDispSwitchState  =  d_POWER_TEXT ;  
			
		
	
		
			
				
					                  mDispSwitchTime . startTimeMonitor ( 10000 ) ;  
			
		
	
		
			
				
					               }  
			
		
	
		
			
				
					               break ;  
			
		
	
		
			
				
					         }  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      void  initPowerGraph ( uint8_t  width ,  uint8_t  height )  {  
			
		
	
		
			
				
					         mPgWidth  =  width ;  
			
		
	
		
			
				
					         mPgHeight  =  height ;  
			
		
	
		
			
				
					         mPgData  =  new  float [ mPgWidth ] ;  
			
		
	
		
			
				
					         //memset(mPgData, 0, mPgWidth);
  
			
		
	
		
			
				
					         resetPowerGraph ( ) ;  
			
		
	
		
			
				
					/*
  
			
		
	
		
			
				
					         Inverter < >  * iv ;  
			
		
	
		
			
				
					         mPgMaxAvailPower  =  0 ;  
			
		
	
		
			
				
					         uint8_t  nInv  =  mSys - > getNumInverters ( ) ;  
			
		
	
		
			
				
					         for  ( uint8_t  i  =  0 ;  i  <  nInv ;  i + + )  {  
			
		
	
		
			
				
					            iv  =  mSys - > getInverterByPos ( i ) ;  
			
		
	
		
			
				
					            if  ( iv  = =  NULL )  
			
		
	
		
			
				
					               continue ;  
			
		
	
		
			
				
					            for  ( uint8_t  ch  =  0 ;  ch  <  6 ;  ch + + )  {  
			
		
	
		
			
				
					               mPgMaxAvailPower  + =  iv - > config - > chMaxPwr [ ch ] ;  
			
		
	
		
			
				
					            }  
			
		
	
		
			
				
					         }  
			
		
	
		
			
				
					         DBGPRINTLN ( " max. Power =  "  +  String ( mPgMaxAvailPower ) ) ; */  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      void  resetPowerGraph ( )  {  
			
		
	
		
			
				
					        if  ( mPgData  ! =  nullptr )  {  
			
		
	
		
			
				
					           mPgMaxPwr  =  0.0 ;  
			
		
	
		
			
				
					           mPgLastPos  =  0 ;  
			
		
	
		
			
				
					           for  ( uint8_t  i  =  0 ;  i  <  mPgWidth ;  i + + )  
			
		
	
		
			
				
					              mPgData [ i ]  =  0.0 ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      uint8_t  sss2pgpos ( uint  seconds_since_start )  {  
			
		
	
		
			
				
					        return ( seconds_since_start  *  ( mPgWidth  -  1 )  /  ( mDisplayData - > pGraphEndTime  -  mDisplayData - > pGraphStartTime ) ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      void  calcPowerGraphValues ( )  {  
			
		
	
		
			
				
					         mPgPeriod  =  mDisplayData - > pGraphEndTime  -  mDisplayData - > pGraphStartTime ;   // length of power graph for scaling of x-axis
  
			
		
	
		
			
				
					         uint32_t  oldTimeOfDay  =  mPgTimeOfDay ;  
			
		
	
		
			
				
					         mPgTimeOfDay  =  ( mDisplayData - > utcTs  >  mDisplayData - > pGraphStartTime )  ?  mDisplayData - > utcTs  -  mDisplayData - > pGraphStartTime  :  0 ;  // current time of day with respect to current sunrise time
  
			
		
	
		
			
				
					         if  ( oldTimeOfDay  >  mPgTimeOfDay )  // new day -> reset old data
  
			
		
	
		
			
				
					            resetPowerGraph ( ) ;  
			
		
	
		
			
				
					         mPgLastPos  =  std : : min ( ( uint8_t )  ( mPgTimeOfDay  *  ( mPgWidth  -  1 )  /  mPgPeriod ) ,  ( uint8_t )  ( mPgWidth  -  1 ) ) ;   // current datapoint based on currenct time of day
  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      void  addPowerGraphEntry ( float  val )  {  
			
		
	
		
			
				
					         if  ( mDisplayData - > utcTs  >  0 )  {   // precondition: utc time available
  
			
		
	
		
			
				
					            calcPowerGraphValues ( ) ;  
			
		
	
		
			
				
					            //mPgData[mPgLastPos] = std::max(mPgData[mPgLastPos], (uint8_t) (val * 255.0 / mPgMaxAvailPower));  // normalizing of data to 0-255
  
			
		
	
		
			
				
					            mPgData [ mPgLastPos ]  =  std : : max ( mPgData [ mPgLastPos ] ,  val ) ;  
			
		
	
		
			
				
					            mPgMaxPwr  =  std : : max ( mPgMaxPwr ,  val ) ;   // max value of stored data for scaling of y-axis
  
			
		
	
		
			
				
					         }  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      uint8_t  getPowerGraphXpos ( uint8_t  p )  {   //
  
			
		
	
		
			
				
					        if  ( ( p  < =  mPgLastPos )  & &  ( mPgLastPos  >  0 ) )  
			
		
	
		
			
				
					            return ( ( p  *  ( mPgWidth  -  1 ) )  /  mPgLastPos ) ;   // scaling of x-axis
  
			
		
	
		
			
				
					        else  
			
		
	
		
			
				
					            return ( 0 ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      uint8_t  getPowerGraphYpos ( uint8_t  p )  {  
			
		
	
		
			
				
					        if  ( p  <  mPgWidth )  
			
		
	
		
			
				
					            //return(((uint32_t) mPgData[p] * (uint32_t) mPgMaxAvailPower) * (uint32_t) mPgHeight / mPgMaxPwr / 255); // scaling of normalized data (0-255) to graph height
  
			
		
	
		
			
				
					            return ( ( mPgData [ p ]  *  ( uint32_t )  mPgHeight  /  mPgMaxPwr ) ) ;  // scaling of data to graph height
  
			
		
	
		
			
				
					        else  
			
		
	
		
			
				
					            return ( 0 ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      void  plotPowerGraph ( uint8_t  xoff ,  uint8_t  yoff )  {  
			
		
	
		
			
				
					        // draw axes
  
			
		
	
		
			
				
					        mDisplay - > drawLine ( xoff ,  yoff ,  xoff ,             yoff  -  mPgHeight ) ;   // vertical axis
  
			
		
	
		
			
				
					        mDisplay - > drawLine ( xoff ,  yoff ,  xoff  +  mPgWidth ,  yoff ) ;               // horizontal axis
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        // draw X scale
  
			
		
	
		
			
				
					        tmElements_t  tm ;  
			
		
	
		
			
				
					        breakTime ( mDisplayData - > pGraphEndTime ,  tm ) ;  
			
		
	
		
			
				
					        uint8_t  endHourPg  =  tm . Hour ;  
			
		
	
		
			
				
					        breakTime ( mDisplayData - > utcTs ,  tm ) ;  
			
		
	
		
			
				
					        uint8_t  endHour  =  std : : min ( endHourPg ,  tm . Hour ) ;  
			
		
	
		
			
				
					        breakTime ( mDisplayData - > pGraphStartTime ,  tm ) ;  
			
		
	
		
			
				
					        tm . Hour  + =  1 ;  
			
		
	
		
			
				
					        tm . Minute  =  0 ;  
			
		
	
		
			
				
					        tm . Second  =  0 ;  
			
		
	
		
			
				
					        for  ( ;  tm . Hour  < =  endHour ;  tm . Hour + + )  {  
			
		
	
		
			
				
					            uint8_t  x_pos_screen  =  getPowerGraphXpos ( sss2pgpos ( ( uint32_t )  makeTime ( tm )  -  mDisplayData - > pGraphStartTime ) ) ;  // scale horizontal axis
  
			
		
	
		
			
				
					            mDisplay - > drawPixel ( xoff  +  x_pos_screen ,  yoff  -  1 ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        // draw Y scale
  
			
		
	
		
			
				
					        uint16_t  scale_y  =  10 ;  
			
		
	
		
			
				
					        uint32_t  maxpwr_int  =  static_cast < uint8_t > ( std : : round ( mPgMaxPwr ) ) ;  
			
		
	
		
			
				
					        if  ( maxpwr_int  >  100 )  
			
		
	
		
			
				
					            scale_y  =  100 ;  
			
		
	
		
			
				
					        for  ( uint32_t  i  =  scale_y ;  i  < =  maxpwr_int ;  i  + =  scale_y )  {  
			
		
	
		
			
				
					            uint8_t  ypos  =  yoff  -  static_cast < uint8_t > ( std : : round ( i  *  ( float )  mPgHeight  /  mPgMaxPwr ) ) ;  // scale vertical axis
  
			
		
	
		
			
				
					            mDisplay - > drawPixel ( xoff  +  1 ,  ypos ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        // draw curve
  
			
		
	
		
			
				
					        for  ( uint8_t  i  =  1 ;  i  < =  mPgLastPos ;  i + + )  {  
			
		
	
		
			
				
					            mDisplay - > drawLine ( xoff  +  getPowerGraphXpos ( i  -  1 ) ,  yoff  -  getPowerGraphYpos ( i  -  1 ) ,  
			
		
	
		
			
				
					                               xoff  +  getPowerGraphXpos ( i ) ,      yoff  -  getPowerGraphYpos ( i ) ) ;  
			
		
	
		
			
				
					        }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        // print max power value
  
			
		
	
		
			
				
					        mDisplay - > setFont ( u8g2_font_4x6_tr ) ;  
			
		
	
		
			
				
					        snprintf ( mFmtText ,  DISP_FMT_TEXT_LEN ,  " %dW " ,  static_cast < uint16_t > ( std : : round ( mPgMaxPwr ) ) ) ;  
			
		
	
		
			
				
					        mDisplay - > drawStr ( xoff  +  3 ,  yoff  -  mPgHeight  +  5 ,  mFmtText ) ;  
			
		
	
		
			
				
					      }  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      // pixelshift screensaver with wipe effect
  
			
		
	
		
			
				
					      void  calcPixelShift ( int  range )  {  
			
		
	
		
			
				
					         int8_t  mod  =  ( millis ( )  /  10000 )  %  ( ( range  > >  1 )  < <  2 ) ;  
			
		
	
		
			
				
					         mPixelshift  =  mScreenSaver  = =  1  ?  ( ( mod  <  range )  ?  mod  -  ( range  > >  1 )  :  - ( mod  -  range  -  ( range  > >  1 )  +  1 ) )  :  0 ;