📄 emeter-background.c
字号:
// File: emeter-background.c
//
// Steve Underwood <steve-underwood@ti.com>
// Texas Instruments Hong Kong Ltd.
//
// $Id: emeter-background.c,v 1.28 2005/12/20 10:17:56 a0754793 Exp $
//
/*! \file emeter-structs.h */
//
//--------------------------------------------------------------------------
//
// MSP430 background (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.
//
// The background process deals with the input samples.
// These are first stored into buffers.
// The buffered samples are processed as follows:
// -Voltage and current signals are converted to DC-less AC signals
// -The current signal is phase compensated
// -Voltage and current are signed multiplied to give power.
// -Power samples are accumulated. The accumulated power samples are averaged (in foreground.c)
// after a number of voltage cycles has been detected.
//
#include <stdint.h>
#include <stdlib.h>
#include <io.h>
#include <emeter-toolkit.h>
#include "emeter.h"
#include "emeter-structs.h"
#if !defined(NULL)
#define NULL (void *) 0
#endif
int samples_per_second;
#if defined(RF_LINK_SUPPORT)
int rf_timeout;
#endif
#if defined(PWM_DITHERING_SUPPORT)
unsigned char pwm_stutter;
#endif
#if defined(__MSP430__)
#if defined(BASIC_KEYPAD_SUPPORT) || defined(CUSTOM_KEYPAD_SUPPORT)
#if defined(sense_key_1_up)
static unsigned char debounce_key_1;
static int key_timer_1;
#endif
#if defined(sense_key_2_up)
static unsigned char debounce_key_2;
static int key_timer_2;
#endif
#if defined(sense_key_3_up)
static unsigned char debounce_key_3;
static int key_timer_3;
#endif
#if defined(sense_key_4_up)
static unsigned char debounce_key_4;
static int key_timer_4;
#endif
unsigned char key_states;
#endif
#endif
unsigned int battery_countdown;
#if defined(POWER_DOWN_SUPPORT) && defined(POWER_UP_BY_SUPPLY_SENSING)
unsigned char power_down_debounce;
#endif
#if defined(POWER_DOWN_SUPPORT) && defined(POWER_UP_BY_VOLTAGE_PULSES)
unsigned char pd_pin_debounce;
#endif
#if defined(FINE_ENERGY_PULSE_TIMING_SUPPORT)
unsigned char fine_pulse_operation;
#endif
#if defined(MAGNETIC_INTERFERENCE_SUPPORT)
unsigned int magnetic_sensor_count;
unsigned int magnetic_sensor_count_logged;
#endif
/* This keypad debounce code provides for 1 to 4 keys, with debounce + long
press detect, of debounce + auto-repeat on long press selectable for each
key. Definitions in emeter.h control this. A long press means >2s.
Auto-repeat means holding the key >1s starts repeats at 3 per second. */
#if defined(__MSP430__) && (defined(BASIC_KEYPAD_SUPPORT) || defined(CUSTOM_KEYPAD_SUPPORT))
static __inline__ int keypad_debounce(void)
{
int kick_foreground;
kick_foreground = FALSE;
#if defined(sense_key_1_up)
switch (debounce(&debounce_key_1, sense_key_1_up()))
{
case DEBOUNCE_JUST_RELEASED:
key_timer_1 = 0;
break;
case DEBOUNCE_JUST_HIT:
#if defined(KEY_1_LONG_DOWN)
/* Start a 2s timer to detect mode change request */
key_timer_1 = samples_per_second << 1;
#elif defined(KEY_1_REPEAT_DOWN)
/* Start an initial 1s timeout for repeats */
key_timer_1 = samples_per_second;
#endif
key_states |= KEY_1_DOWN;
kick_foreground = TRUE;
break;
case DEBOUNCE_HIT:
if (key_timer_1 && --key_timer_1 == 0)
{
#if defined(KEY_1_LONG_DOWN)
key_states |= KEY_1_LONG_DOWN;
#elif defined(KEY_1_REPEAT_DOWN)
/* Start a 1/3s timeout for repeats */
#if defined(LIMP_MODE_SUPPORT)
if (operating_mode == OPERATING_MODE_LIMP)
key_timer_1 = 273;
else
#endif
key_timer_1 = 1092;
key_states |= KEY_1_REPEAT_DOWN;
#endif
kick_foreground = TRUE;
}
break;
}
#endif
#if defined(sense_key_2_up)
switch (debounce(&debounce_key_2, sense_key_2_up()))
{
case DEBOUNCE_JUST_RELEASED:
key_timer_2 = 0;
break;
case DEBOUNCE_JUST_HIT:
#if defined(KEY_2_LONG_DOWN)
/* Start a 2s timer to detect mode change request */
key_timer_2 = samples_per_second << 1;
#elif defined(KEY_2_REPEAT_DOWN)
/* Start an initial 1s timeout for repeats */
key_timer_2 = samples_per_second;
#endif
key_states |= KEY_2_DOWN;
kick_foreground = TRUE;
break;
case DEBOUNCE_HIT:
if (key_timer_2 && --key_timer_2 == 0)
{
#if defined(KEY_2_LONG_DOWN)
key_states |= KEY_2_LONG_DOWN;
#elif defined(KEY_2_REPEAT_DOWN)
/* Start a 1/3s timeout for repeats */
key_timer_2 = 1092;
key_states |= KEY_2_REPEAT_DOWN;
#endif
kick_foreground = TRUE;
}
break;
}
#endif
#if defined(sense_key_3_up)
switch (debounce(&debounce_key_3, sense_key_3_up()))
{
case DEBOUNCE_JUST_RELEASED:
key_timer_3 = 0;
break;
case DEBOUNCE_JUST_HIT:
#if defined(KEY_3_LONG_DOWN)
/* Start a 2s timer to detect mode change request */
key_timer_3 = samples_per_second << 1;
#elif defined(KEY_3_REPEAT_DOWN)
/* Start an initial 1s timeout for repeats */
key_timer_3 = samples_per_second;
#endif
key_states |= KEY_3_DOWN;
kick_foreground = TRUE;
break;
case DEBOUNCE_HIT:
if (key_timer_3 && --key_timer_3 == 0)
{
#if defined(KEY_3_LONG_DOWN)
key_states |= KEY_3_LONG_DOWN;
#elif defined(KEY_3_REPEAT_DOWN)
/* Start a 1/3s timeout for repeats */
key_timer_3 = 1092;
key_states |= KEY_3_REPEAT_DOWN;
#endif
kick_foreground = TRUE;
}
break;
}
#endif
#if defined(sense_key_4_up)
switch (debounce(&debounce_key_4, sense_key_4_up()))
{
case DEBOUNCE_JUST_RELEASED:
key_timer_4 = 0;
break;
case DEBOUNCE_JUST_HIT:
#if defined(KEY_4_LONG_DOWN)
/* Start a 2s timer to detect mode change request */
key_timer_4 = samples_per_second << 1;
#elif defined(KEY_4_REPEAT_DOWN)
/* Start an initial 1s timeout for repeats */
key_timer_4 = samples_per_second;
#endif
key_states |= KEY_4_DOWN;
kick_foreground = TRUE;
break;
case DEBOUNCE_HIT:
if (key_timer_4 && --key_timer_4 == 0)
{
#if defined(KEY_4_LONG_DOWN)
key_states |= KEY_3_LONG_DOWN;
#elif defined(KEY_4_REPEAT_DOWN)
/* Start a 1/3s timeout for repeats */
key_timer_4 = 1092;
key_states |= KEY_4_REPEAT_DOWN;
#endif
kick_foreground = TRUE;
}
break;
}
#endif
return kick_foreground;
}
#endif
#if defined(SINGLE_PHASE)
static void __inline__ log_parameters(void)
#else
static void __inline__ log_parameters(struct phase_parms_s *phase)
#endif
{
#if GAIN_STAGES > 1
int i;
#else
#define i 0
#endif
/**/ P3OUT ^= 0x02;
/* Take a snapshot of various values for logging purposes; tell the
foreground to deal with them; and clear the working values ready
for the next analysis period. */
if (phase->V_endstops <= 0)
phase->status |= V_OVERRANGE;
else
phase->status &= ~V_OVERRANGE;
phase->V_endstops = ENDSTOP_HITS_FOR_OVERLOAD;
#if defined(VRMS_SUPPORT)
transfer48(phase->V_sq_accum_logged, phase->V_sq_accum);
#endif
if (phase->current.I_endstops <= 0)
phase->status |= I_OVERRANGE;
else
phase->status &= ~I_OVERRANGE;
phase->current.I_endstops = ENDSTOP_HITS_FOR_OVERLOAD;
#if defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT)
if (phase->neutral.I_endstops <= 0)
phase->status |= I_NEUTRAL_OVERRANGE;
else
phase->status &= ~I_NEUTRAL_OVERRANGE;
phase->neutral.I_endstops = ENDSTOP_HITS_FOR_OVERLOAD;
#endif
phase->current.sample_count_logged = phase->current.sample_count;
phase->current.sample_count = 0;
#if defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT)
phase->neutral.sample_count_logged = phase->neutral.sample_count;
phase->neutral.sample_count = 0;
#endif
#if GAIN_STAGES > 1
for (i = 0; i < GAIN_STAGES; i++)
#endif
{
#if defined(IRMS_SUPPORT)
transfer48(phase->current.I_sq_accum_logged[i], phase->current.I_sq_accum[i]);
#endif
transfer48(phase->current.P_accum_logged[i], phase->current.P_accum[i]);
#if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT)
transfer48(phase->current.P_reactive_accum_logged[i], phase->current.P_reactive_accum[i]);
#endif
#if defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT)
#if defined(IRMS_SUPPORT)
transfer48(phase->neutral.I_sq_accum_logged[i], phase->neutral.I_sq_accum[i]);
#endif
transfer48(phase->neutral.P_accum_logged[i], phase->neutral.P_accum[i]);
#if defined(REACTIVE_POWER_BY_QUADRATURE_SUPPORT)
transfer48(phase->neutral.P_reactive_accum_logged[i], phase->neutral.P_reactive_accum[i]);
#endif
#endif
}
phase->sample_count_logged = phase->sample_count;
phase->sample_count = 0;
#if defined(MAGNETIC_INTERFERENCE_SUPPORT)
magnetic_sensor_count_logged = magnetic_sensor_count;
/* Don't reset to zero, to prevent divide by zero */
magnetic_sensor_count = 1;
#endif
/* Tell the foreground there are things to process. */
phase->status |= NEW_LOG;
#if GAIN_STAGES <= 1
#undef i
#endif
}
#if !defined(SINGLE_PHASE) && defined(NEUTRAL_MONITOR_SUPPORT) && defined(IRMS_SUPPORT)
/* This routine logs neutral lead information for poly-phase meters. It is
not used for single phase meters with neutral monitoring. */
static void __inline__ log_neutral_parameters(void)
{
#if GAIN_STAGES > 1
int i;
#else
#define i 0
#endif
if (neutral.I_endstops <= 0)
neutral.status |= I_OVERRANGE;
else
neutral.status &= ~I_OVERRANGE;
neutral.I_endstops = ENDSTOP_HITS_FOR_OVERLOAD;
neutral.sample_count_logged = neutral.sample_count;
#if GAIN_STAGES > 1
for (i = 0; i < GAIN_STAGES; i++)
#endif
{
#if defined(IRMS_SUPPORT) || defined(POWER_FACTOR_SUPPORT)
transfer48(neutral.I_sq_accum_logged[i], neutral.I_sq_accum[i]);
#endif
neutral.sample_count[i] = 0;
}
/* Tell the foreground there are things to process. */
neutral.status |= NEW_LOG;
#if GAIN_STAGES <= 1
#undef i
#endif
}
#endif
#if defined(HARMONICS_SUPPORT)
const int16_t harm_factors[][4] =
{
{ 138, 2040, 1972, 1839},
{ 138, 2039, 1972, 1838},
{ 137, 2039, 1971, 1838},
{ 137, 2039, 1971, 1837},
{ 137, 2039, 1971, 1836},
{ 137, 2039, 1970, 1835},
{ 136, 2039, 1970, 1834},
{ 136, 2039, 1970, 1833},
{ 136, 2039, 1969, 1832},
{ 135, 2039, 1969, 1831},
{ 135, 2039, 1969, 1831},
{ 135, 2039, 1968, 1830},
{ 135, 2039, 1968, 1829},
{ 134, 2039, 1968, 1828},
{ 134, 2039, 1968, 1827},
{ 134, 2039, 1967, 1826},
{ 133, 2039, 1967, 1825},
{ 133, 2039, 1967, 1824},
{ 133, 2039, 1966, 1823},
{ 133, 2039, 1966, 1823},
{ 132, 2039, 1966, 1822},
{ 132, 2039, 1965, 1821},
{ 132, 2039, 1965, 1820},
{ 132, 2039, 1965, 1819},
{ 131, 2039, 1964, 1818},
{ 131, 2039, 1964, 1817},
{ 131, 2039, 1964, 1816},
{ 131, 2039, 1963, 1815},
{ 130, 2038, 1963, 1814},
{ 130, 2038, 1963, 1814},
{ 130, 2038, 1962, 1813},
{ 130, 2038, 1962, 1812},
{ 129, 2038, 1962, 1811},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -