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

📄 psoft.c

📁 TDK 6521 SOC 芯片 DEMO程序
💻 C
字号:
/***************************************************************************
 * This code and information is provided "as is" without warranty of any   *
 * kind, either expressed or implied, including but not limited to the     *
 * implied warranties of merchantability and/or fitness for a particular   *
 * purpose.                                                                *
 *                                                                         *
 * Copyright (C) 2005 Teridian Semiconductor Corp. All Rights Reserved.    *
 ***************************************************************************/
//**************************************************************************
//  DESCRIPTION: 71M65xx POWER METER - Software pulsing.
//  This code emits pulses on two DIO pins, PULSE3 and PULSE4, proportional
//  to power inputs on the psoft_update() interface.  Rename the DIO
//  pins PULSE3 and PULSE4 in reg65xx.h to move the outputs to different pins.
//  The pins for PULSE3 and PULSE4 have to be initialized in defaults.c.
//  It uses the same units and interface as the CE pulse outputs,
//  except implemented in software on the MPU.
//  It generates 50% duty-cycle pulses, and is linear (within 0.0001%) from 
//  150Hz to below 0.01 Hz, giving at least four decades of accuracy.
//  Jitter is about 3.2 ms.
//  It is preintegrated with the version 4 demo firmware, and
//  can optionally count its pulses (See pcnt.c for more info on pulse counts).
// 
//  AUTHOR:  RGV
//
//  HISTORY: See end of file.
//**************************************************************************
//  File: psoft.c
//               
#include "options.h"
#if PULSE_SOFT
#include "library.h"
#include "psoft.h"

/*** Public variables declared within this module *** Selectable via "defaults" */
bool pulse3_val;
bool pulse4_val;
volatile int32i_t pulse3_accum;
volatile int32i_t pulse4_accum;
volatile int32i_t pulse3_inc;
volatile int32i_t pulse4_inc;

#if PULSE_CNT
uint16d_t dPulse3_Cnt, dPulse4_Cnt;
#endif

/*** Private functions declared within this module ***/
#pragma save
#pragma NOAREGS
// This routine can be called in the ce_busy interrupt, 2520/8 times
// per second, and from there it will use about 3% of the total CPU
// in real time.  The hardware and software timers have too much jitter 
// to run this routine and generate a stable pulse output.
// When run from the CE busy interrupt, the pulse outputs appear synchronized
// to the CE pulse outputs, even though they are simply done at the same
// frequency.
void psoft_out(void) small reentrant
{
    // calculates pulse value without using I/O, in order to
    // increase noise resistance
    pulse3_accum += pulse3_inc;
    if (pulse3_val != (pulse3_accum < 0)) // did bit 31 change?
    {
        // It has to change.
        // If it's at the starting value, count it
        #if PULSE_CNT
	    if (pulse3_val)
        {
            ++dPulse3_Cnt; // count the pulse outputs
            // This count needs to be added to a longer, 64 bit
            // count once per second.  See pcnt.c
        }
        #endif
        pulse3_val = ~pulse3_val;
        PULSE3 = pulse3_val; // set a DIO configured for output
    }

    // calculates pulse value without using I/O, in order to
    // increase noise resistance
    pulse4_accum += pulse4_inc;
    if (pulse4_val != (pulse4_accum < 0)) // did bit 31 change?
    {
        // It has to change.
        // If it's at the starting value, count it
        #if PULSE_CNT
        if (pulse4_val)
        {
            ++dPulse4_Cnt; // count the pulse outputs
            // This count needs to be added to a longer, 64 bit
            // count once per second.  See pcnt.c
        }
        #endif
        pulse4_val ^= 1;
        PULSE4 = pulse4_val; // set a DIO configured for output
    }
}
#pragma restore


// the inputs are watt hours, as generated by the CE, and set the pulse 
// generators to blink at the same rate as CE pulse outputs, with the same 
// units.  This should be called each time a new accumulation interval has data.
void psoft_update (int32_t pulse3_in, int32_t pulse4_in)
{
    bool ea_saved;
    bool PulseFast, PulseSlow; 
    int32_t xdata Wrate;
    #if M6520
    uint32_t my_cestate;
    #endif

    // figure software pulse outputs pulse 3 and 4
    // The designed maximum frequency is 157.54 Hz,
    // somewhat over a practical 150 Hz spec.
    // The CE code has a pulse rate 3x2520Hz, 
    // the CE_BUSY interrupt skips 7, a 1/8 decimation of 2520 Hz.k
    #if M6520
    my_cestate = memget_ce(&cestate);
    PulseFast = (0 != (my_cestate & CE_PULSE_FAST));
    PulseSlow = (0 != (my_cestate & CE_PULSE_SLOW));
    #elif TRACE10
    PulseFast = (memget_ce (&pulse_fast) < 0) ? 0 : 1;
    PulseSlow = (memget_ce (&pulse_slow) < 0) ? 0 : 1;
    #elif HOST15
    PulseFast = pulse_fast;
    PulseSlow = pulse_slow;
    #else
    #error unknown device type
    #endif

    Wrate = memget_ce (&wrate);
    pulse3_in = 3 * pulse3_in;
    pulse4_in = 3 * pulse4_in;

    if (!PulseSlow)
    {
        if (!PulseFast)
        {
            // simulated at 0.0001% error
            pulse3_in = ((pulse3_in + 512L) >> 10) * Wrate;
            pulse4_in = ((pulse4_in + 512L) >> 10) * Wrate;
        }
        else
        {
            // simulated at 0% (too small to print) error
            // This case fails for speeds even slightly faster than 150 Hz
            pulse3_in = ((pulse3_in + 32L) >> 6) * Wrate;
            pulse4_in = ((pulse4_in + 32L) >> 6) * Wrate;
        }
    }
    else
    {
        if (!PulseFast)
        {
            // simulated at 0.00006% error
            // The 2^16 divisor causes 0.005% error by
            // underflow unless the division is performed in two steps
            pulse3_in = ((pulse3_in + 512L) >> 10) * Wrate;
            pulse3_in = (pulse3_in + 32L) >> 6;
            pulse4_in = ((pulse4_in + 512L) >> 10) * Wrate;
            pulse4_in = (pulse4_in + 32L) >> 6;
        }
        else
        {
            // simulated at 0.0001% error
            pulse3_in = ((pulse3_in + 2048L) >> 12) * Wrate;
            pulse4_in = ((pulse4_in + 2048L) >> 12) * Wrate;
        }
    }
    ea_saved = EA;
    EA = 0;
    pulse3_val = PULSE3; // update the pulse value
    pulse4_val = PULSE4;
    pulse3_inc = pulse3_in;
    pulse4_inc = pulse4_in;
    EA = ea_saved;
}

// Initialize the software pulse outputs
void psoft_init(void)
{
    // the DIO for pulse3 and 4 should be configured in defaults
    // for the starting values and direction
    // start with pulse outputs high (bit 31 is put out)
    pulse3_inc = 0;
    pulse3_val = PULSE3; // set the starting polarity for the pulse
    if (pulse3_val)
        pulse3_accum = 0xC0000000;
    else
        pulse3_accum = 0x40000000;

    pulse4_inc = 0;
    pulse4_val = PULSE4; // set the starting polarity for the pulse
    if (pulse4_val)
        pulse4_accum = 0xC0000000;
    else
        pulse4_accum = 0x40000000;

    #if M6520 // pulse3 and pulse4 are the same pins as OPT_RX and OPT_TX
    DIO |= OPT_RXDIS;  // disable OPT_RX, enable DIO1 = PULSE3
    // Config2 is also affected by ser1.h, which contains code
    // to switch between an optical serial port, and optical pulse.
    // It does this automatically, by the way, if the command line interface
    // is in the system.  See ser1cli.c for the high level code.
    CONFIG2 = (CONFIG2 & !OPT_TXE) | _DIO2;  // disable OPT_RX, enable DIO2/P4
    #endif
}

#endif // PULSE_SOFT
/***************************************************************************
 * History:
 * $Log: psoft.c,v $
 * Revision 1.15  2006/10/13 00:51:11  tvander
 * Removed compile options for 6530, 6515;
 * renamed 6511 and 6513 to trace11 and trace13;
 * Binary verified unchanged from previous version.
 *
 * Revision 1.14  2006/09/09 01:14:40  gmikef
 * *** empty log message ***
 *
 * Revision 1.13  2006/08/17 22:18:20  tvander
 * Tested with 6513 and 6521F at 4.9mHz.  Fails with 6521F at 614kHz.
 *
 * Revision 1.12  2006/08/08 18:46:13  tvander
 * Added an option for 6515 test PCB
 *
 * Revision 1.11  2006/03/03 11:30:38  Michael T. Fischer
 * Prep for 6530 LCD, etc.
 *
 * Revision 1.10  2006/01/16 20:11:29  tvander
 * Clean Keil build, all versions
 *
 * Revision 1.9  2006/01/04 04:47:54  gmikef
 * Switched RMS and VA calculations to use floating point. (and Calibration).
 *
 * Revision 1.7  2005/12/21 01:35:28  tvander
 * 6513
 *
 * Revision 1.6  2005/09/22 23:45:19  tvander
 * Clean build all models and unit tests, updated copyright to be fore Teridian
 *
 * Revision 1.5  2005/09/12 07:47:31  tvander
 * Power measurement is stable, with no creep.
 * VARh measurement is stable, with no creep.
 * Pulse sources work.
 * Full access to MPU variables.
 * Rolled date.
 * Clock software works.
 *
 * Revision 1.4  2005/08/30 18:19:46  gmikef
 * *** empty log message ***
 *
 * Revision 1.3  2005/08/12 21:56:26  tvander
 * Fixed logic error is flag decoding.
 *
 * Revision 1.2  2005/08/12 06:02:47  gmikef
 * Added MPU temperature compensation for GAIN_ADJ.
 * Added changes to support new CE 6521 code.
 *
 * Revision 1.1  2005/08/02 22:36:30  tvander
 * Optional software pulse logic.
 * Fixed build in 6511B and 6521B
 *
 * Copyright (C) 2005 Teridian Semiconductor Corp. All Rights Reserved.    *
 * this program is fully protected by the United States copyright          *
 * laws and is the property of Teridian Semiconductor Corporation.         *
 ***************************************************************************/

⌨️ 快捷键说明

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