⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 emeter-multirate.c

📁 msp430F437三相电表DEMO(编译器 IAR 3.42A)
💻 C
📖 第 1 页 / 共 2 页
字号:
//--------------------------------------------------------------------------
//
//  Software for MSP430 based e-meters.
//
//  You may not use the Program in non-TI devices.
//
//  File: emeter-multirate.c
//
//  Steve Underwood <steve-underwood@ti.com>
//  Texas Instruments Hong Kong Ltd.
//
//  $Id: emeter-multirate.c,v 1.3 2005/12/20 10:17:57 a0754793 Exp $
//
/*! \file emeter-multirate.h */
//
//--------------------------------------------------------------------------
//
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#if !defined(__MSP430__)
#include <stdio.h>
#endif
#include <io.h>
#include <emeter-toolkit.h>
#include "emeter.h"
#include "emeter-structs.h"
#include "emeter-multirate.h"

#if MULTI_RATE_SUPPORT

uint8_t tariff_flags;

eeprom_history_t current_history;
uint8_t current_history_dirty;

/*! The current slot number in the usage history table */
uint8_t current_history_slot;

/*! The tariff type of the current day */
uint8_t current_day_type;

uint8_t current_tariff = 0xFF;

eeprom_daily_peak_t daily_peak;
uint8_t daily_peak_slot;

/*! The current slot in the five minute usage table. */
uint8_t current_five_minute_slot;

/*! This table is 30 minutes long, in 5 minute chunks. Usage is accumulated in
    5 minute chunks, to the centre of the 30 minute period of peak usage may be
    assessed to 5 minute accuracy. */
uint16_t five_minute_usages[6];

/* Add a one byte sumcheck to the passed message, in the byte after the message */
void add_sumcheck(void *buf, int len)
{
    uint8_t *s;
    int sum;

    sum = 0;
    s = (uint8_t *) buf;
    while (--len > 0)
        sum += *s++;
    *s = 0xFF - sum;
}

/* Check the passed message, which must include a one byte sumcheck, is OK */
int test_sumcheck(const void *buf, int len)
{
    const uint8_t *s;
    int sum;

    sum = 0;
    s = (uint8_t *) buf;
    while (len-- > 0)
        sum += *s++;
    return ((sum & 0xFF) == 0xFF);
}

void multirate_energy_pulse(void)
{
    five_minute_usages[current_five_minute_slot]++;
    if (++current_history.energy_lo == 0)
        ++current_history.energy_hi;
    current_history_dirty = TRUE;
}

int find_next_cutoff_date(void)
{
    int year;
    int month;
    int day;
    int best_year;
    int best_month;
    int best_day;
    int best_slot;
    int i;
    eeprom_cutoff_date_t cutoff_date;

    /* We need to find the smallest date which is greater than the current date */
    inhibit_rtc_updates();
    year = rtc.year;
    month = rtc.month;
    day = rtc.day;
    enable_rtc_updates();
    best_year = 99;
    best_month = 12;
    best_day = 31;
    best_slot = -1;
    for (i = 0;  i < MULTIRATE_MAX_CUTOFF_DATES;  i++)
    {
        iicEEPROM_read(EEPROM_START_CUTOFF_DATES + i*sizeof(eeprom_cutoff_date_t), (void *) &cutoff_date, sizeof(cutoff_date));
        if (year < cutoff_date.year
            ||
                (year == cutoff_date.year
                &&
                    (month < cutoff_date.month
                    ||
                    (month == cutoff_date.month  &&  day < cutoff_date.day))))
        {
            if (best_year > cutoff_date.year
                ||
                    (best_year == cutoff_date.year
                    &&
                        (best_month > cutoff_date.month
                        ||
                        (best_month == cutoff_date.month  &&  best_day > cutoff_date.day))))
            {
                /* This is earlier, so use it */
                best_slot = i;
                best_year = cutoff_date.year;
                best_month = cutoff_date.month;
                best_day = cutoff_date.day;
            }
        }
    }
    return best_slot;
}

int find_previous_cutoff_date(void)
{
    int year;
    int month;
    int day;
    int best_year;
    int best_month;
    int best_day;
    int best_slot;
    int i;
    eeprom_cutoff_date_t cutoff_date;
    
    /* We need to find the largest date which is less than the current date */
    inhibit_rtc_updates();
    year = rtc.year;
    month = rtc.month;
    day = rtc.day;
    enable_rtc_updates();
    best_year = 0;
    best_month = 0;
    best_day = 0;
    best_slot = -1;
    for (i = 0;  i < MULTIRATE_MAX_CUTOFF_DATES;  i++)
    {
        iicEEPROM_read(EEPROM_START_CUTOFF_DATES + i*sizeof(eeprom_cutoff_date_t), (void *) &cutoff_date, sizeof(cutoff_date));
        if (year > cutoff_date.year
            ||
                (year == cutoff_date.year
                &&
                    (month > cutoff_date.month
                    ||
                    (month == cutoff_date.month  &&  day >= cutoff_date.day))))
        {
            if (best_year < cutoff_date.year
                ||
                    (best_year == cutoff_date.year
                    &&
                        (best_month < cutoff_date.month
                        ||
                        (best_month == cutoff_date.month  &&  best_day < cutoff_date.day))))
            {
                /* This is later, so use it */
                best_slot = i;
                best_year = cutoff_date.year;
                best_month = cutoff_date.month;
                best_day = cutoff_date.day;
            }
        }
    }
    return best_slot;
}

void new_tariff_day(void)
{
    int i;
    uint8_t day_type;
    int year;
    int month;
    int day;
    int wday;
    eeprom_holiday_t holiday;
    eeprom_cutoff_date_t cutoff_date;

    /* Should be called when the day changes and at reset, to work out
       today's type */
    inhibit_rtc_updates();
    year = rtc.year;
    month = rtc.month;
    day = rtc.day;
    enable_rtc_updates();
    for (i = 0;  i < MULTIRATE_MAX_HOLIDAYS;  i++)
    {
        iicEEPROM_read(EEPROM_START_HOLIDAYS + i*sizeof(eeprom_holiday_t), (void *) &holiday, sizeof(holiday));
        if (year == holiday.year
            &&
            month == holiday.month
            &&
            day == holiday.day)
        {
            /* Its a holiday */
            current_day_type = holiday.day_type;
            return;
        }
    }
    /* Not a holiday. Just use the regular weekday pattern */
    wday = weekday();
    iicEEPROM_read(EEPROM_START_WEEKDAYS + (wday >> 1), (void *) &day_type, sizeof(day_type));
    current_day_type = ((wday & 1)  ?  (day_type >> 4)  :  day_type) & 0x0F;

    /* TODO: what if the real peak were a little before midnight */
    iicEEPROM_write(EEPROM_START_PEAKS + daily_peak_slot*sizeof(eeprom_daily_peak_t), (void *) &daily_peak, sizeof(daily_peak));
    if (++daily_peak_slot >= MULTIRATE_MAX_DAILY_PEAKS)
        daily_peak_slot = 0;

    daily_peak.usage = 0;
    daily_peak.hour = 0;
    daily_peak.minute = 0;
    
    /* Check if we have reached a billing cutoff point */
    iicEEPROM_read(EEPROM_START_CUTOFF_DATES + current_history_slot*sizeof(eeprom_cutoff_date_t), (void *) &cutoff_date, sizeof(cutoff_date));
    if (year > cutoff_date.year
        ||
        (year == cutoff_date.year
            &&
                (month > cutoff_date.month
                ||
                (month == cutoff_date.month  &&  day > cutoff_date.day))))
    {
        /* Its a cutoff point - find the next cutoff point, and start using the
           history slot specified for it. */
        /* If we didn't find a suitable slot, we continue accumulating where we
           are. At least that way we are gathering all the usage. */
        if ((i = find_next_cutoff_date()) >= 0)
            current_history_slot = i;
    }
}


void new_tariff_minute(void)
{
    int i;
    int n;
    int hour;
    int minute;
    eeprom_day_schedule_timeslot_t tariff;
    uint32_t energy;

    inhibit_rtc_updates();
    hour = rtc.hour;
    minute = rtc.minute;
    enable_rtc_updates();
    /* Default to the first timeslot */
    iicEEPROM_read(EEPROM_START_DAY_SCHEDULES + current_day_type*MULTIRATE_DAY_SCHEDULE_TIMESLOTS*sizeof(eeprom_day_schedule_timeslot_t), (void *) &tariff, sizeof(tariff));
    n = tariff.tariff;
    for (i = 1;  i < MULTIRATE_DAY_SCHEDULE_TIMESLOTS;  i++)
    {
        iicEEPROM_read(EEPROM_START_DAY_SCHEDULES + (current_day_type*MULTIRATE_DAY_SCHEDULE_TIMESLOTS + i)*sizeof(eeprom_day_schedule_timeslot_t), (void *) &tariff, sizeof(tariff));
        if (tariff.tariff)
        {
            if (tariff.start_hour > hour
                ||
                (tariff.start_hour == hour  &&  tariff.start_minute > minute))
            {
                n = tariff.tariff;
                break;
            }
        }
    }
    
    if (n != current_tariff)
    {
        /* Save current tariff values, and load the new set */
        write_history_slot(current_history_slot, current_tariff);
        read_history_slot(current_history_slot, n);
        current_tariff = n;
    }
    
    if (rtc.minute%5 == 0)
    {
        /* Deal with the time and size of the daily peak demand */
        energy = 0;
        for (i = 0;  i < 6;  i++)
            energy += five_minute_usages[i];
        if (energy > daily_peak.usage)
        {
            daily_peak.usage = energy;
            daily_peak.hour = rtc.hour;
            daily_peak.minute = rtc.minute;
        }
        five_minute_usages[current_five_minute_slot] = 0;
        if (++current_five_minute_slot >= 6)
            current_five_minute_slot = 0;
    }
    current_tariff = n;
}

int read_history_slot(int slot, int tariff)
{
    int i;
    int pos;
    eeprom_history_t history[3];
    int ok[3];

    if (!current_history_dirty)
        return 0;
    current_history_dirty = FALSE;
    pos = (slot*MULTIRATE_DAY_SCHEDULES + tariff)*sizeof(eeprom_history_t);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -