//--------------------------------------------------------------------------
//
//  Software for MSP430 based e-meters.
//
//  THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
//  REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
//  INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
//  FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
//  COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.
//  TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET
//  POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY
//  INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR
//  YOUR USE OF THE PROGRAM.
//
//  IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
//  CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY
//  THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED
//  OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT
//  OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM.
//  EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF
//  REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS
//  OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF
//  USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S
//  AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF
//  YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS
//  (U.S.$500).
//
//  Unless otherwise stated, the Program written and copyrighted
//  by Texas Instruments is distributed as "freeware".  You may,
//  only under TI's copyright in the Program, use and modify the
//  Program without any charge or restriction.  You may
//  distribute to third parties, provided that you transfer a
//  copy of this license to the third party and the third party
//  agrees to these terms by its first use of the Program. You
//  must reproduce the copyright notice and any other legend of
//  ownership on each copy or partial copy, of the Program.
//
//  You acknowledge and agree that the Program contains
//  copyrighted material, trade secrets and other TI proprietary
//  information and is protected by copyright laws,
//  international copyright treaties, and trade secret laws, as
//  well as other intellectual property laws.  To protect TI's
//  rights in the Program, you agree not to decompile, reverse
//  engineer, disassemble or otherwise translate any object code
//  versions of the Program to a human-readable form.  You agree
//  that in no event will you alter, remove or destroy any
//  copyright notice included in the Program.  TI reserves all
//  rights not specifically granted under this license. Except
//  as specifically provided herein, nothing in this agreement
//  shall be construed as conferring by implication, estoppel,
//  or otherwise, upon you, any license or other right under any
//  TI patents, copyrights or trade secrets.
//
//  You may not use the Program in non-TI devices.
//
//  File: emeter-main.c
//
//  Steve Underwood <steve-underwood@ti.com>
//  Texas Instruments Hong Kong Ltd.
//
//  $Id: emeter-main.c,v 1.10 2009/04/27 06:21:22 a0754793 Exp $
//
/*! \file emeter-structs.h */
//
//--------------------------------------------------------------------------
//
//  MSP430 foreground (non-interrupt) routines for e-meters
//
//  This software is appropriate for single phase and three phase e-meters
//  using a voltage sensor plus a CT or shunt resistor current sensors, or
//  a combination of a CT plus a shunt.
// 
//    Foreground process includes:
//    -Using timer tick to wait
//    -Calculating the power per channel
//    -Determine if current channel needs scaling.
//    -Determine if needs to be in low power modes.
//    -Compensate reference from temperature sensor
//
#include <stdint.h>
#include <stdlib.h>
#if defined(__GNUC__)
#include <signal.h>
#endif
#include <math.h>
#include <io.h>
#include <emeter-toolkit.h>
#define __MAIN_PROGRAM__

#include "emeter-structs.h"
#if defined(MESH_NET_SUPPORT)
#include "mesh_structure.h"
#endif


#if defined(TOTAL_ACTIVE_ENERGY_SUPPORT)
typedef union
{
    unsigned char uint8[4];
    unsigned int uint16[2];
    uint32_t uint32;
} power_array;
uint8_t total_active_energy_pulse_remaining_time;
int32_t total_active_power;
power_array    total_active_power_array;
int32_t total_active_power_counter;
    #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
int16_t extra_total_active_power_counter;
    #endif
uint32_t total_consumed_active_energy;
#endif

#if defined(TOTAL_REACTIVE_ENERGY_SUPPORT)
uint8_t total_reactive_energy_pulse_remaining_time;
int32_t total_reactive_power;
int32_t total_reactive_power_counter;
    #if TOTAL_ENERGY_PULSES_PER_KW_HOUR < 1000
int16_t extra_total_reactive_power_counter;
    #endif
uint32_t total_consumed_reactive_energy;
#endif

#if 0 //CUSTOM_LCD_SUPPORT
/* Keep the toolkit library happy */
const int lcd_cells = LCD_CELLS;
const int lcd_pos_base = LCD_POS_BASE;
const int lcd_pos_step = LCD_POS_STEP;
#endif

#if defined(TEMPERATURE_SUPPORT)
uint16_t temperature;
#endif

int i;

/* Meter status flag bits. */
uint16_t meter_status;

/* Current operating mode - normal, limp, power down, etc. */
int8_t operating_mode;

/* Persistence check counters for anti-tamper measures. */
#if defined(PHASE_REVERSED_DETECTION_SUPPORT)
int8_t current_reversed;
#endif
#if defined(POWER_BALANCE_DETECTION_SUPPORT)
int8_t current_unbalanced;
#endif
#if defined(MAGNETIC_INTERFERENCE_SUPPORT)
int8_t magnetic_interference_persistence;
#endif

#if defined(IHD430_SUPPORT)
unsigned char RF_Tx[17]={0xFE,0x0C,0x29,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x05,0x01};
#endif 

/* The main per-phase working parameter structure */
struct phase_parms_s chan[NUM_PHASES];
    #if defined(NEUTRAL_MONITOR_SUPPORT)
struct neutral_parms_s neutral;
    #endif
/* The main per-phase non-volatile parameter structure */
__infomem__ const struct info_mem_s nv_parms =
{
    {
    {
        0xFFFF,
#if defined(SELF_TEST_SUPPORT)
        0xFFFF,
        0xFFFF,
#endif
        {
            {
                {
#if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR_A},
                    0,
#endif

                    DEFAULT_P_SCALE_FACTOR_A_LOW,
                    DEFAULT_I_DC_ESTIMATE << 16,
#if defined(PHASE_CORRECTION_SUPPORT)
                    DEFAULT_BASE_PHASE_A_CORRECTION_LOW,
#endif
                },
#if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR_A,
#endif
                DEFAULT_V_DC_ESTIMATE << 16,
            },
            {
                {
    #if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR_B},
                    0,
    #endif
                    DEFAULT_P_SCALE_FACTOR_B_LOW,
                    DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
                    DEFAULT_BASE_PHASE_B_CORRECTION_LOW,
    #endif
                },
    #if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR_B,
    #endif
                DEFAULT_V_DC_ESTIMATE << 16,
            },
            {
                {
    #if defined(IRMS_SUPPORT)
                    {DEFAULT_I_RMS_SCALE_FACTOR_C},
                    0,
    #endif
                    DEFAULT_P_SCALE_FACTOR_C_LOW,
                    DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
                    DEFAULT_BASE_PHASE_C_CORRECTION_LOW,
    #endif
                },
    #if defined(VRMS_SUPPORT)
                DEFAULT_V_RMS_SCALE_FACTOR_C,
    #endif
                DEFAULT_V_DC_ESTIMATE << 16,
            }
        },
#if defined(NEUTRAL_MONITOR_SUPPORT)
        {
    #if defined(IRMS_SUPPORT)
            DEFAULT_I_RMS_SCALE_FACTOR_NEUTRAL,
            0,
    #endif
            DEFAULT_P_SCALE_FACTOR_NEUTRAL,
            DEFAULT_I_DC_ESTIMATE << 16,
    #if defined(PHASE_CORRECTION_SUPPORT)
            DEFAULT_NEUTRAL_BASE_PHASE_CORRECTION,
    #endif
        },
#endif
#if defined(TEMPERATURE_SUPPORT)
        25,
        DEFAULT_TEMPERATURE_OFFSET,
        DEFAULT_TEMPERATURE_SCALING,
#endif
#if defined(CORRECTED_RTC_SUPPORT)
        0,
#endif
        {
            0,
            0,
            0,
            0,
            0,
            0
        },
        0,
        "",
        "",
        ""
    }
    }
};

#if !defined(__IAR_SYSTEMS_ICC__)
static __inline__ long labs(long __x);
static __inline__ long labs(long __x)
{
    return (__x < 0) ? -__x : __x;
}
#endif

#if defined(SELF_TEST_SUPPORT)
int record_meter_failure(int type)
{
    /* The error type should be a value between 0 and 15, specifying the unrecoverable error
       type to be recorded in the failures word in flash. */
    /* Don't worry about the time taken to write to flash - we are recording a serious
       error condition! */
    flash_write_int16((int *) &(nv_parms.seg_a.s.meter_failures), nv_parms.seg_a.s.meter_failures & ~(1 << type));
    flash_secure();
    return TRUE;
}

int record_meter_warning(int type)
{
    /* The warning type should be a value between 0 and 15, specifying the warning type to be
       recorded in the recoverable failures word in flash. */
    /* Don't worry about the time taken to write to flash - we are recording a serious
       problem! */
    flash_write_int16((int *) &(nv_parms.seg_a.s.meter_warnings), nv_parms.seg_a.s.meter_warnings & ~(1 << type));
    flash_secure();
    return TRUE;
}
#endif

#if defined(BATTERY_MONITOR_SUPPORT)
void test_battery(void)
{
    P3DIR |= (BIT1);
    P3OUT &= ~(BIT1);
    battery_countdown = 1000;
}
#endif

#if defined(IO_EXPANDER_SUPPORT)
/* This routine supports the use of a device like the 74HC595 to expand the number of
   output bits available on the lower pin count MSP430s. */
void set_io_expander(int what, int which)
{
    static uint8_t io_state = 0;
    int i;
    int j;

    if (what < 0)
        io_state &= ~which;
    else if (what > 0)
        io_state |= which;
    else
        io_state = which;
    /* Pump the data into the shift register */
    for (i = 8, j = io_state;  i > 0;  i--)
    {
        P1OUT &= ~BIT4;
        if ((j & 0x80))
            P1OUT |= BIT7;
        else
            P1OUT &= ~BIT7;
        P1OUT |= BIT4;
        j <<= 1;
    }
    /* Clock the data into the output register */
    P1OUT &= ~BIT6;
    P1OUT |= BIT6;
}
#endif


enum display_LCD
{
   DISPLAY_START                              =-1,
   DISPLAY_VOLTAGE                          = 0,     
   DISPLAY_CURRENT                          = 1,    
   DISPLAY_ACTIVE_POWER                     = 2,
   DISPLAY_REACTIVE_POWER                   = 3,
   DISPLAY_APPARENT_POWER                   = 4,
   DISPLAY_FREQUENCY                        = 5,
   DISPLAY_POWER_FACTOR                     = 6,
   DISPLAY_TOTAL_START                      =7,
   DISPLAY_ACCUMULATED_ACTIVE_POWER   = 8, 
   DISPLAY_SKIP_REACTIVE_POWER = 9, 
   DISPLAY_ACCUMULATED_REACTIVE_POWER = 10,
   DISPLAY_END                                =11

};

enum display_phase
{
   DISPLAY_PHASE_START                      = -1,
   DISPLAY_PHASE_A                          = 0,     
   DISPLAY_PHASE_B                          = 1,    
   DISPLAY_PHASE_C                          = 2,
   DISPLAY_PHASE_TOTAL                      = 4,
   DISPLAY_PHASE_END                        = 5
};

long long temp=0, temp2=0;
static int thou,hun,ten,unit,ten_thou, thou_thou, hun_thou;
int lcd_display_mode=DISPLAY_START, change_display=0, LCDM3constant=0, phase_display_mode=DISPLAY_PHASE_START;
volatile unsigned int LCD_reg; 

// After DISPLAY_TOTAL_START until DISPLAY_END must correspond to variables that are displayed as sum of the
//corresponding values for the phases.



 const unsigned char LCD_Char_Map[] =
{
    BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7,                // '0' or 'O'
    BIT5 | BIT6,                                            // '1' or 'I'
    BIT0 | BIT1 | BIT3 | BIT4 | BIT6 | BIT7,                // '2' or 'Z'
    BIT0 | BIT1 | BIT4 | BIT5 | BIT6 | BIT7,                // '3'
    BIT0 | BIT1 | BIT2 | BIT5 | BIT6,                       // '4' or 'y'
    BIT0 | BIT1 | BIT2 | BIT4 | BIT5 | BIT7,                // '5' or 'S'
    BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT7,         // '6' or 'b'
    BIT5 | BIT6 | BIT7,                                     // '7'
    BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7,  // '8' or 'B'
    BIT0 | BIT1 | BIT2 | BIT4 | BIT5 | BIT6 | BIT7,         // '9' or 'g'
};


int display_count=1;
void main(void)
{
    int ch;
    static struct phase_parms_s *phase;
    static struct phase_nv_parms_s const *phase_nv;
    static int32_t x;
    system_setup();
    #if !defined(ESP_SUPPORT)  &&  defined(PHASE_CORRECTION_SUPPORT)  &&  !defined(DYNAMIC_PHASE_CORRECTION_SUPPORT)
        for (ch = 0;  ch < NUM_PHASES;  ch++)
        {
            phase = &chan[ch];
            phase_nv = &nv_parms.seg_a.s.chan[ch];
            set_sd16_phase_correction(&phase->metrology.current.in_phase_correction[0], ch, phase_nv->current.phase_correction[0]);
        }
    #endif

    send_message(0, 1);
    for (;;)
    {
        kick_watchdog();
        phase = chan;
        phase_nv = nv_parms.seg_a.s.chan;

        for (ch = 0;  ch < NUM_PHASES;  ch++)
        {
            /* Unless we are in normal operating mode, we should wait to be
               woken by a significant event from the interrupt routines. */
            #if defined(POWER_DOWN_SUPPORT)
                        if (operating_mode == OPERATING_MODE_POWERFAIL)
                            switch_to_powerfail_mode();
            #endif
            if ((phase->status & NEW_LOG))
            {
                        /* The background activity has informed us that it is time to
                           perform a block processing operation. */
                phase->status &= ~NEW_LOG;
                if (operating_mode == OPERATING_MODE_NORMAL)
                {
                   x = active_power(phase, phase_nv);
                   #if defined(PRECALCULATED_PARAMETER_SUPPORT)
                      #if defined(IRMS_SUPPORT)
                        phase->readings.I_rms = current(phase, phase_nv, ch);
                      #endif
                      #if defined(VRMS_SUPPORT)
                         phase->readings.V_rms = voltage(phase, phase_nv);
                      #endif
                   #endif
                }
                if (labs(x) < RESIDUAL_POWER_CUTOFF  ||  (phase->status & V_OVERRANGE))
                {
                     x = 0;
                   /* Turn off the LEDs, regardless of the internal state of the
                                 reverse and imbalance assessments. */
                    #if defined(PHASE_REVERSED_DETECTION_SUPPORT)
                      meter_status &= ~STATUS_REVERSED;
                      clr_reverse_current_indicator();
                    #endif
                    #if defined(POWER_BALANCE_DETECTION_SUPPORT)
                                        meter_status &= ~STATUS_EARTHED;
                                        clr_earthed_indicator();
                    #endif
                 }
                else
                {
                      if (operating_mode == OPERATING_MODE_NORMAL)
                      {
                          #if defined(PHASE_REVERSED_DETECTION_SUPPORT)  &&  defined(PHASE_REVERSED_IS_TAMPERING)
                                  if ((phase->status & PHASE_REVERSED))
                                  {
                                      meter_status |= STATUS_REVERSED;
                                      set_reverse_current_indicator();
                                  }
                                  else
                                  {
                                      meter_status &= ~STATUS_REVERSED;
                                      clr_reverse_current_indicator();
                                  }
                          #endif
                          #if defined(POWER_BALANCE_DETECTION_SUPPORT)
                                  if ((phase->status & PHASE_UNBALANCED))
                                  {
                                      meter_status |= STATUS_EARTHED;
                                      set_earthed_indicator();
                                  }
                                  else
                                  {
                                      meter_status &= ~STATUS_EARTHED;
                                      clr_earthed_indicator();
                                  }
                          #endif
                      }
                }
                total_active_power += (x - phase->readings.active_power);
                #if defined(IHD430_SUPPORT)
                total_active_power_array.uint32=total_active_power;

                #endif
                phase->readings.active_power = x;
                
                #if defined(PRECALCULATED_PARAMETER_SUPPORT)
                    #if defined(REACTIVE_POWER_SUPPORT)
                      x = reactive_power(phase, phase_nv);
                      total_reactive_power += (x - phase->readings.reactive_power);
                      phase->readings.reactive_power = x;
                    #endif
                    #if defined(APPARENT_POWER_SUPPORT)
                      phase->readings.apparent_power = apparent_power(phase, phase_nv);
                    #endif
                    #if defined(POWER_FACTOR_SUPPORT)
                      phase->readings.power_factor = power_factor(phase, phase_nv);
                    #endif
                #endif
                #if defined(PER_PHASE_ACTIVE_ENERGY_SUPPORT)
//                    phase->active_energy_counter += x*phase->metrology.dot_prod_logged.sample_count;
//                    while (phase->active_energy_counter > ENERGY_WATT_HOUR_THRESHOLD)
//                    {
//                          phase->active_energy_counter -= ENERGY_WATT_HOUR_THRESHOLD;
//                          phase->consumed_active_energy++;
//                    }
                #endif
                #if defined(PRECALCULATED_PARAMETER_SUPPORT)  && defined(MAINS_FREQUENCY_SUPPORT)
                    phase->readings.frequency = frequency(phase, phase_nv);
      
                #endif
          if (ch==0 && display_count==1)
          {
             
            display_count=0;
            lcd_display_mode++;   
           
            if (lcd_display_mode == DISPLAY_SKIP_REACTIVE_POWER) 
            {
              
                if(phase_display_mode!=DISPLAY_PHASE_TOTAL)
                  lcd_display_mode+=2;
                else 
                   lcd_display_mode++;
            }
            
            
             if (lcd_display_mode== DISPLAY_END)
            {
        
                if (phase_display_mode==DISPLAY_PHASE_C)
                {
                   phase_display_mode= DISPLAY_PHASE_TOTAL;
                   lcd_display_mode= DISPLAY_TOTAL_START;
                   //Change phase display (T)
                   LCDM14=0xE1;
                   LCDM15=0x10;
                   LCDM16=0xE2;
                   LCDM17=0xEC;
                }
                else
                {
                   lcd_display_mode= DISPLAY_START;
                   phase_display_mode++; 
                   //Change phase display (All except T )
                    LCDM15=0x10;
                   LCDM16=0xE2;
                   LCDM17=0xEC;
                if(phase_display_mode== DISPLAY_PHASE_A ) LCDM14=0xEE; 
                else if(phase_display_mode== DISPLAY_PHASE_B ) LCDM14=0xEF;
                else if(phase_display_mode== DISPLAY_PHASE_C ) LCDM14=0xC9;
                }
              
            } 

            if (lcd_display_mode == DISPLAY_START || lcd_display_mode==DISPLAY_TOTAL_START)
            {
                lcd_display_mode++;
              
            }
            
            if (phase_display_mode == DISPLAY_PHASE_END)
            {
                phase_display_mode= DISPLAY_PHASE_START;
              
            }  
            if (phase_display_mode == DISPLAY_PHASE_START)
            {
                phase_display_mode++;
                   LCDM15=0x10;
                   LCDM16=0xE2;
                   LCDM17=0xEC;
                LCDM14=0xEE;
            }  
        
            
            
            
             switch( lcd_display_mode ) 
                      {
                          
                          case DISPLAY_VOLTAGE:
                              temp= current_rms_voltage(phase_display_mode);
                               if (temp <0) temp=0;
                               LCDM1=0xC;
                               LCDM2=0x29;
                              break;
                          case DISPLAY_CURRENT:
                               temp= current_rms_current(phase_display_mode);
                               if (temp <0) temp=0;
                               LCDM1=0x9C;
                               LCDM2=0x1;
                               //Take care of different decimal.
                              break;
                          case DISPLAY_ACTIVE_POWER:
                              temp= current_active_power(phase_display_mode);
                              if (temp <0) temp=0;
                              LCDM1=0xCF;
                               LCDM2=0x1;
                              break;
                          case DISPLAY_REACTIVE_POWER:
                               temp= current_reactive_power(phase_display_mode);
                               if (temp <0) temp=0;
                               LCDM1=0xC7;
                               LCDM2=0x3;
                              break;
                          case DISPLAY_APPARENT_POWER:
                               temp= current_apparent_power(phase_display_mode);
                               if (temp <0) temp=0;
                               LCDM1=0xB7;
                               LCDM2=0x1;
                              break;
                          case DISPLAY_FREQUENCY:
                               temp= current_mains_frequency(phase_display_mode);
                               if (temp <0) temp=0;
                               LCDM1=0x8F;
                               LCDM2=0x1;
                              break;  
                          case DISPLAY_POWER_FACTOR:
                               temp= current_power_factor(phase_display_mode)/10;
                               LCDM1=0x8F;
                               LCDM2=0x50;
                               
                               if (temp < 0)
                               {
                                  temp*= -1;
                                 LCDM3=0x1C;
                               }
                               else
                               {
                                  LCDM3= 0x9C; 
                               }
                               LCDM3constant=1;
                               //Take negative and positive case for inductive and capacitive
                              break;                  
                         case DISPLAY_ACCUMULATED_ACTIVE_POWER: 
                              temp= current_consumed_active_energy(phase_display_mode)/10;
                              LCDM1=0x9F;
                               LCDM2=0x1;
                              break; 
                         case DISPLAY_ACCUMULATED_REACTIVE_POWER: 
                              temp= current_consumed_reactive_energy(phase_display_mode)/10;
                              LCDM1=0x9F;
                               LCDM2=0x11;
                              break; 
                      default:
                        break;
                        
                                             
                    }
  
                     if(!LCDM3constant)
                     {
                       LCDM3 = 0;             
                     }
                     else
                     {
                       LCDM3constant=0;
                     }
                       
                  LCDM4 = 0;
                  LCDM5 = 0;
                  LCDM6 = 0;
                  LCDM7 = 0;
                  LCDM8 = 0;
                  LCDM9 = 0;
                  LCDM10 = 0;
                  LCDM11 = 0;
                  LCDM12 = 0;  
                  LCDM13=0;
                  //LCDM17 = 0;
                  LCDM18 = 0;
                  LCDM19 = 0;
                  LCDM20 = 0;
                  
                 
               thou_thou=0;
                 hun_thou=0;       
                ten_thou=0;
            thou=0;
            hun=0;
            ten=0;
            unit=0; 
                        while (temp >=1000000)
                        {
                            thou_thou++;
                            temp-=1000000;
                        }
                         while (temp >=100000)
                        {
                            hun_thou++;
                            temp-=100000;
                        }
                        while (temp >=10000)
                        {
                            ten_thou++;
                            temp-=10000;
                        }
                        while (temp >=1000)
                        {
                            thou++;
                            temp-=1000;
                        }
                        while (temp >=100)
                        {
                            hun++;
                            temp-=100;
                        }
                        while (temp >=10)
                        {
                            ten++;
                            temp-=10;
                        }
                        while (temp >=1)
                        {
                            unit++;
                            temp--;
                        }
                       
                        if(thou_thou)
                        {
                          LCDM11 = LCD_Char_Map[hun];
                          LCDM9 = LCD_Char_Map[thou];
                          //LCDM8 = 0x1;
                          LCDM7 = LCD_Char_Map[ten_thou];
                          LCDM5 = LCD_Char_Map[hun_thou];
                          LCDM3 = LCD_Char_Map[thou_thou];          
                        }
                        else if(hun_thou)
                        {        
                          
                          LCDM11 = LCD_Char_Map[ten];
                          if (lcd_display_mode==DISPLAY_CURRENT) LCDM8 = 0x1;      
                          else if(lcd_display_mode!=DISPLAY_ACCUMULATED_ACTIVE_POWER || lcd_display_mode!=DISPLAY_ACCUMULATED_REACTIVE_POWER) LCDM10 = 0x1;     
                          LCDM9 = LCD_Char_Map[hun];
                          LCDM7 = LCD_Char_Map[thou];
                          LCDM5 = LCD_Char_Map[ten_thou];
                          LCDM3 = LCD_Char_Map[hun_thou]; 
                        }
                        else
                        {
                          LCDM11 = LCD_Char_Map[unit];
                          LCDM9 = LCD_Char_Map[ten];
                          if (lcd_display_mode==DISPLAY_CURRENT || lcd_display_mode==DISPLAY_POWER_FACTOR) 
                          {
                            LCDM6 = 0x1;
                          }
                          else if(lcd_display_mode==DISPLAY_ACCUMULATED_ACTIVE_POWER || lcd_display_mode==DISPLAY_ACCUMULATED_REACTIVE_POWER) 
                          {
                            
                            LCDM10 = 0x1;
                              
                          }
                          else
                          {
                                               LCDM8 = 0x1; 
                          }
                             
                          if (lcd_display_mode!=DISPLAY_POWER_FACTOR) 
                             {
                               
                               LCDM3 = LCD_Char_Map[ten_thou];
         
                             }
        
                          LCDM7 = LCD_Char_Map[hun];
                          LCDM5 = LCD_Char_Map[thou];                 
                        }                             
                    
          }
          else if (ch==0  && display_count==0)
          {
            display_count=1;
          }
          
          #if defined(IHD430_SUPPORT)
          else if (ch==1)
          {

               RF_Tx[12]=total_active_power_array.uint8[0];
               RF_Tx[13]=total_active_power_array.uint8[1];
               RF_Tx[14]=total_active_power_array.uint8[2];
               RF_Tx[15]=total_active_power_array.uint8[3]; 
               RF_Tx[16] =0x28 ^ RF_Tx[12] ^ RF_Tx[13] ^ RF_Tx[14] ^ RF_Tx[15];
               for (i=0; i<17; i++)
               {
                  UCA3TXBUF=RF_Tx[i];
                  while(!(UCA3IFG&UCTXIFG));
               }               
          }
         #endif
        }        
          phase++;
          phase_nv++;
        }// END OF CHANNEL FOR LOOP

        #if  defined(NEUTRAL_MONITOR_SUPPORT)  &&  defined(IRMS_SUPPORT)
                if ((neutral.status & NEW_LOG))
                {
                    /* The background activity has informed us that it is time to
                       perform a block processing operation. */
                    neutral.status &= ~NEW_LOG;
                    neutral.readings.I_rms = neutral_current();
                }
        #endif
           /* Do display and other housekeeping here */
         if ((meter_status & TICKER))
         {
                /* Two seconds have passed */
                /* We have a 2 second tick */
            meter_status &= ~TICKER;
            #if defined(__MSP430__)  &&  defined(BASIC_LCD_SUPPORT)
                        /* Update the display, cycling through the phases */
                        //update_display();
            #endif
            custom_2second_handler();
            #if (defined(RTC_SUPPORT)  ||  defined(CUSTOM_RTC_SUPPORT))  &&  defined(CORRECTED_RTC_SUPPORT)
                        correct_rtc();
            #endif
         }
         custom_keypad_handler();
         custom_mainloop_handler();
     
     } //End of the infinite FOR loop
} // END OF MAIN

#if defined(PRECALCULATED_PARAMETER_SUPPORT)
  int32_t current_consumed_active_energy(int ph)
  {
    #if defined(TOTAL_ACTIVE_ENERGY_SUPPORT)
      if (ph == FAKE_PHASE_TOTAL)
        return total_consumed_active_energy;
    #endif
    #if defined(PER_PHASE_ACTIVE_ENERGY_SUPPORT)
      return chan[ph].consumed_active_energy;
    #else
      return 0;
    #endif
  }
  int32_t current_active_power(int ph)
  {
      if (ph == FAKE_PHASE_TOTAL)
        return total_active_power;
      return chan[ph].readings.active_power;
  }
  #if defined(REACTIVE_POWER_SUPPORT)
    int32_t current_consumed_reactive_energy(int ph)
    {
        #if defined(TOTAL_REACTIVE_ENERGY_SUPPORT)
            if (ph == FAKE_PHASE_TOTAL)
                return total_consumed_reactive_energy;
        #endif
        #if defined(PER_PHASE_REACTIVE_ENERGY_SUPPORT)
            return chan[ph].consumed_reactive_energy;
        #else
            return 0;
        #endif
    }
    int32_t current_reactive_power(int ph)
    {
        if (ph == FAKE_PHASE_TOTAL)
            return total_reactive_power;
        return chan[ph].readings.reactive_power;
    
    }
  #endif
  #if defined(APPARENT_POWER_SUPPORT)
    int32_t current_apparent_power(int ph)
    {
       return chan[ph].readings.apparent_power;
    }
  #endif

  #if defined(POWER_FACTOR_SUPPORT)
    int32_t current_power_factor(int ph)
    {
      return chan[ph].readings.power_factor;
    }
  #endif

  #if defined(VRMS_SUPPORT)
    int32_t current_rms_voltage(int ph)
    {
      int32_t x;
      if (chan[ph].readings.V_rms == 0xFFFF)
          x = -1;
      else
          x = chan[ph].readings.V_rms;
      return x;
    }
  #endif

  #if defined(IRMS_SUPPORT)
    int32_t current_rms_current(int ph)
    {
      int32_t x;
      #if defined(NEUTRAL_MONITOR_SUPPORT)
        if (ph == 3)
          x = neutral.readings.I_rms;
        else
      #endif
      x = chan[ph].readings.I_rms;
      if (x == 0xFFFF)
        x = -1;
      return x;
    }
  #endif

  #if defined(MAINS_FREQUENCY_SUPPORT)
  int32_t current_mains_frequency(int ph)
  {
      return chan[ph].readings.frequency;
  }
  #endif
#else
  int32_t current_consumed_active_energy(int ph)
  {
      return chan[ph].consumed_active_energy;
  } 

  int32_t current_active_power(int ph)
  {
      if (ph == FAKE_PHASE_TOTAL)
          return total_active_power;
      return active_power(&chan[ph], &nv_parms.seg_a.s.chan[ch]);
  }
  #if defined(REACTIVE_POWER_SUPPORT)
    int32_t current_consumed_reactive_energy(int ph)
    {
        return chan[ph].consumed_active_energy;
    }
  
    int32_t current_reactive_power(int ph)
    {
        if (ph == FAKE_PHASE_TOTAL)
            return total_reactive_power;
        return reactive_power(&chan[ph], &nv_parms.seg_a.s.chan[ch]);
    }
  #endif
  #if defined(APPARENT_POWER_SUPPORT)
    int32_t current_apparent_power(int ph)
    {
        return apparent_power(&chan[ph], &nv_parms.seg_a.s.chan[ch]);
    }
  #endif
  #if defined(POWER_FACTOR_SUPPORT)
    int32_t current_power_factor(int ph)
    {
        return power_factor(&chan[ph], &nv_parms.seg_a.s.chan[ch]);
    }
  #endif
  #if defined(VRMS_SUPPORT)
    int32_t current_rms_voltage(int ph)
    {
        return voltage(&chan[ph], &nv_parms.seg_a.s.chan[ch]);
    }
  #endif

  #if defined(IRMS_SUPPORT)
    int32_t current_rms_current(int ph)
    {
        return current(&chan[ph], &nv_parms.seg_a.s.chan[ch]);
    }
  #endif

  #if defined(MAINS_FREQUENCY_SUPPORT)
    int32_t current_mains_frequency(int ph)
    {
        return frequency(&chan[ph], &nv_parms.seg_a.s.chan[ch]);
    }
  #endif
#endif
