Browse Source
This is a re-write of the PWM generator.
This is a re-write of the PWM generator.
It is modelled according to the new d_OSC by Giles Atkinson. Here frequency is fixed and duty cycle is controlled by an analog input.pre-master-46
2 changed files with 155 additions and 511 deletions
@ -1,477 +1,214 @@ |
|||||
/*.......1.........2.........3.........4.........5.........6.........7.........8 |
|
||||
================================================================================ |
|
||||
|
/* XSPICE code model for the Controlled PWM Oscillator. |
||||
|
* This is a complete redesign of the original version, |
||||
|
* according to the d_osc model provided by G. Atkinson |
||||
|
*/ |
||||
|
|
||||
FILE d_pwm/cfunc.mod |
|
||||
|
|
||||
Public Domain |
|
||||
|
|
||||
Georgia Tech Research Corporation |
|
||||
Atlanta, Georgia 30332 |
|
||||
PROJECT A-8503-405 |
|
||||
The ngspice team |
|
||||
|
|
||||
AUTHORS |
|
||||
|
|
||||
24 Jul 1991 Jeffrey P. Murray |
|
||||
02 Mar 2022 Holger Vogt |
|
||||
|
|
||||
MODIFICATIONS |
|
||||
|
|
||||
23 Aug 1991 Jeffrey P. Murray |
|
||||
30 Sep 1991 Jeffrey P. Murray |
|
||||
06 Oct 2022 Holger Vogt |
|
||||
05 Jan 2023 Robert Turnbull |
|
||||
|
|
||||
SUMMARY |
|
||||
|
|
||||
This file contains the model-specific routines used to |
|
||||
functionally describe the d_pwm code model. |
|
||||
|
|
||||
|
|
||||
INTERFACES |
|
||||
|
|
||||
FILE ROUTINE CALLED |
|
||||
|
|
||||
CMmacros.h cm_message_send(); |
|
||||
|
|
||||
CM.c void *cm_analog_alloc() |
|
||||
void *cm_analog_get_ptr() |
|
||||
|
|
||||
CMevt.c void cm_event_queue() |
|
||||
|
|
||||
|
|
||||
REFERENCED FILES |
|
||||
|
|
||||
Inputs from and outputs to ARGS structure. |
|
||||
|
|
||||
|
|
||||
NON-STANDARD FEATURES |
|
||||
|
|
||||
NONE |
|
||||
|
|
||||
===============================================================================*/ |
|
||||
|
|
||||
/*=== INCLUDE FILES ====================*/ |
|
||||
|
|
||||
#include "d_pwm.h" /* ...contains macros & type defns. |
|
||||
for this model. 7/24/91 - JPM */ |
|
||||
#include <stdlib.h> |
#include <stdlib.h> |
||||
|
|
||||
|
#define FACTOR 0.75 // Controls timing of next scheduled call. */ |
||||
|
|
||||
|
/* PWL table entry. */ |
||||
|
|
||||
/*=== CONSTANTS ========================*/ |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/*=== MACROS ===========================*/ |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/*=== LOCAL VARIABLES & TYPEDEFS =======*/ |
|
||||
|
struct pwl { |
||||
|
double ctl, dc; |
||||
|
}; |
||||
|
|
||||
typedef struct { |
|
||||
double *x; |
|
||||
double *y; |
|
||||
} Local_Data_t; |
|
||||
|
/* Called at end to free memory. */ |
||||
|
|
||||
|
static void cm_d_pwm_callback(ARGS, Mif_Callback_Reason_t reason) |
||||
|
{ |
||||
|
if (reason == MIF_CB_DESTROY) { |
||||
|
struct pwl *table = STATIC_VAR(locdata); |
||||
|
|
||||
/*=== FUNCTION PROTOTYPE DEFINITIONS ===*/ |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/*============================================================================== |
|
||||
|
|
||||
FUNCTION cm_d_pwm() |
|
||||
|
|
||||
AUTHORS |
|
||||
|
|
||||
24 Jul 1991 Jeffrey P. Murray |
|
||||
02 Mar 2022 Holger Vogt |
|
||||
|
|
||||
MODIFICATIONS |
|
||||
|
|
||||
30 Sep 1991 Jeffrey P. Murray |
|
||||
|
|
||||
SUMMARY |
|
||||
|
|
||||
This function implements the d_pwm code model. |
|
||||
|
|
||||
INTERFACES |
|
||||
|
|
||||
FILE ROUTINE CALLED |
|
||||
|
|
||||
CMmacros.h cm_message_send(); |
|
||||
|
|
||||
CM.c void *cm_analog_alloc() |
|
||||
void *cm_analog_get_ptr() |
|
||||
|
if (table) |
||||
|
free(table); |
||||
|
STATIC_VAR(locdata) = NULL; |
||||
|
} |
||||
|
} |
||||
|
|
||||
CMevt.c void cm_event_queue() |
|
||||
|
/* Get the current duty cycle. */ |
||||
|
|
||||
RETURNED VALUE |
|
||||
|
static double get_dc(double ctl, struct pwl *table, int csize) |
||||
|
{ |
||||
|
double d; |
||||
|
int i; |
||||
|
|
||||
Returns inputs and outputs via ARGS structure. |
|
||||
|
for (i = 0; i < csize; ++i) { |
||||
|
if (table[i].ctl > ctl) |
||||
|
break; |
||||
|
} |
||||
|
|
||||
GLOBAL VARIABLES |
|
||||
|
/* Interpolation outside input range continues slope. */ |
||||
|
|
||||
NONE |
|
||||
|
if (i > 0) { |
||||
|
if (i == csize) |
||||
|
i -= 2; |
||||
|
else |
||||
|
i--; |
||||
|
} |
||||
|
d = table[i].dc + |
||||
|
(ctl - table[i].ctl) * ((table[i + 1].dc - table[i].dc) / |
||||
|
(table[i + 1].ctl - table[i].ctl)); |
||||
|
|
||||
NON-STANDARD FEATURES |
|
||||
|
/* limit duty cycle d to 0.01 <= d <= 0.99 */ |
||||
|
if (d > 0.99) |
||||
|
d = 0.99; |
||||
|
else if (d < 0.01) |
||||
|
d = 0.01; |
||||
|
|
||||
NONE |
|
||||
|
return d; |
||||
|
} |
||||
|
|
||||
==============================================================================*/ |
|
||||
|
/* The state data. */ |
||||
|
|
||||
static void cm_d_pwm_callback(ARGS, |
|
||||
Mif_Callback_Reason_t reason) |
|
||||
{ |
|
||||
switch (reason) { |
|
||||
case MIF_CB_DESTROY: { |
|
||||
Local_Data_t *loc = STATIC_VAR(locdata); |
|
||||
if (loc) { |
|
||||
if (loc->x) |
|
||||
free(loc->x); |
|
||||
if(loc->y) |
|
||||
free(loc->y); |
|
||||
free(loc); |
|
||||
STATIC_VAR(locdata) = loc = NULL; |
|
||||
} |
|
||||
break; |
|
||||
} /* end of case MIF_CB_DESTROY */ |
|
||||
} /* end of switch over reason being called */ |
|
||||
} /* end of function cm_d_pwm_callback */ |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*=== CM_D_PWM ROUTINE ===*/ |
|
||||
|
|
||||
/************************************************************* |
|
||||
* The following is the model for a duty cycle controlled * |
|
||||
* digital oscillator, derived from the controlled digital * |
|
||||
* oscillator d_osc. * |
|
||||
* * |
|
||||
* Created 3/02/2022 H. Vogt * |
|
||||
*************************************************************/ |
|
||||
|
|
||||
/************************************************************* |
|
||||
* * |
|
||||
* * |
|
||||
* <-----duty_cycle-----> * |
|
||||
* I * |
|
||||
* I t2 t3 * |
|
||||
* I \______________/_____ * |
|
||||
* I | | * |
|
||||
* I | | | | * |
|
||||
* I | | * |
|
||||
* I | | | | * |
|
||||
* I | | * |
|
||||
* I | | | | * |
|
||||
* I-----------------*-----* - - - - - - - - - -*--------- * |
|
||||
* t1 t4 * |
|
||||
* * |
|
||||
* * |
|
||||
* t2 = t1 + rise_delay * |
|
||||
* t4 = t3 + fall_delay * |
|
||||
* * |
|
||||
* Note that for the digital model, unlike for the * |
|
||||
* analog "square" model, t1 and t3 are stored and * |
|
||||
* adjusted values, but t2 & t4 are implied by the * |
|
||||
* rise and fall delays of the model, but are otherwise * |
|
||||
* not stored values. JPM * |
|
||||
* * |
|
||||
*************************************************************/ |
|
||||
|
struct state { |
||||
|
double last_time; // Time of last output change. |
||||
|
Digital_State_t last; // Last value output. |
||||
|
}; |
||||
|
|
||||
|
/* The code-model function. */ |
||||
|
|
||||
void cm_d_pwm(ARGS) |
void cm_d_pwm(ARGS) |
||||
{ |
{ |
||||
|
struct pwl *table; |
||||
|
struct state *state; |
||||
|
double ctl, delta, when, ddc; |
||||
|
int csize, i; |
||||
|
|
||||
double *x, /* analog input value control array */ |
|
||||
*y, /* frequency array */ |
|
||||
cntl_input, /* control input value */ |
|
||||
*phase, /* instantaneous phase of the model */ |
|
||||
*phase_old, /* previous phase of the model */ |
|
||||
*t1, /* pointer to t1 value */ |
|
||||
*t3, /* pointer to t3 value */ |
|
||||
/*time1,*/ /* variable for calculating new time1 value */ |
|
||||
/*time3,*/ /* variable for calculating new time3 value */ |
|
||||
dc = 0.5, /* instantaneous duty cycle value */ |
|
||||
dphase, /* fractional part into cycle */ |
|
||||
frequency, /* frequency value */ |
|
||||
test_double, /* testing variable */ |
|
||||
slope; /* slope value...used to extrapolate |
|
||||
freq values past endpoints. */ |
|
||||
|
|
||||
int i, /* generic loop counter index */ |
|
||||
cntl_size, /* control array size */ |
|
||||
dc_size; /* duty cycle array size */ |
|
||||
|
|
||||
Local_Data_t *loc; /* Pointer to local static data, not to be included |
|
||||
in the state vector (save memory!) */ |
|
||||
|
|
||||
/**** Retrieve frequently used parameters... ****/ |
|
||||
|
|
||||
cntl_size = PARAM_SIZE(cntl_array); |
|
||||
dc_size = PARAM_SIZE(dc_array); |
|
||||
frequency = PARAM(frequency); |
|
||||
|
|
||||
/* check and make sure that the control array is the |
|
||||
same size as the frequency array */ |
|
||||
|
|
||||
if(cntl_size != dc_size){ |
|
||||
cm_message_send(d_pwm_array_error); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (INIT) { /*** Test for INIT == TRUE. If so, allocate storage, etc. ***/ |
|
||||
|
|
||||
/* Allocate storage for internal variables */ |
|
||||
cm_analog_alloc(0, sizeof(double)); |
|
||||
cm_analog_alloc(1, sizeof(double)); |
|
||||
cm_analog_alloc(2, sizeof(double)); |
|
||||
|
|
||||
/* assign internal variables */ |
|
||||
phase = phase_old = (double *) cm_analog_get_ptr(0,0); |
|
||||
|
|
||||
t1 = (double *) cm_analog_get_ptr(1,0); |
|
||||
|
CALLBACK = cm_d_pwm_callback; |
||||
|
|
||||
t3 = (double *) cm_analog_get_ptr(2,0); |
|
||||
|
csize = PARAM_SIZE(cntl_array); |
||||
|
delta = 1.0 / PARAM(frequency); |
||||
|
|
||||
|
if (INIT) { |
||||
|
|
||||
/*** allocate static storage for *loc ***/ |
|
||||
STATIC_VAR (locdata) = calloc (1 , sizeof ( Local_Data_t )); |
|
||||
loc = STATIC_VAR (locdata); |
|
||||
CALLBACK = cm_d_pwm_callback; |
|
||||
|
/* Validate PWL table. */ |
||||
|
|
||||
x = loc->x = (double *) calloc((size_t) cntl_size, sizeof(double)); |
|
||||
if (!x) { |
|
||||
cm_message_send(d_pwm_allocation_error); |
|
||||
return; |
|
||||
} |
|
||||
y = loc->y = (double *) calloc((size_t) cntl_size, sizeof(double)); |
|
||||
if (!y) { |
|
||||
cm_message_send(d_pwm_allocation_error); |
|
||||
if(x) |
|
||||
free(x); |
|
||||
return; |
|
||||
} |
|
||||
/* Retrieve x and y values. */ |
|
||||
for (i=0; i<cntl_size; i++) { |
|
||||
x[i] = PARAM(cntl_array[i]); |
|
||||
y[i] = PARAM(dc_array[i]); |
|
||||
|
for (i = 0; i < csize - 1; ++i) { |
||||
|
if (PARAM(cntl_array[i]) >= PARAM(cntl_array[i + 1])) |
||||
|
break; |
||||
} |
} |
||||
} |
|
||||
|
|
||||
else { /*** This is not an initialization pass...retrieve storage |
|
||||
addresses and calculate new outputs, if required. ***/ |
|
||||
|
|
||||
/** Retrieve previous values... **/ |
|
||||
|
|
||||
/* assign internal variables */ |
|
||||
phase = (double *) cm_analog_get_ptr(0,0); |
|
||||
phase_old = (double *) cm_analog_get_ptr(0,1); |
|
||||
|
|
||||
t1 = (double *) cm_analog_get_ptr(1,0); |
|
||||
|
|
||||
t3 = (double *) cm_analog_get_ptr(2,0); |
|
||||
|
|
||||
} |
|
||||
|
|
||||
switch (CALL_TYPE) { |
|
||||
|
|
||||
case ANALOG: /** analog call **/ |
|
||||
|
|
||||
test_double = TIME; |
|
||||
|
|
||||
if ( AC == ANALYSIS ) { /* this model does not function |
|
||||
in AC analysis mode. */ |
|
||||
|
if (i < csize - 1 || csize != PARAM_SIZE(dc_array)) { |
||||
|
cm_message_send("Badly-formed control table"); |
||||
|
STATIC_VAR(locdata) = NULL; |
||||
return; |
return; |
||||
} |
} |
||||
else { |
|
||||
|
|
||||
if ( 0.0 == TIME ) { /* DC analysis */ |
|
||||
|
|
||||
/* retrieve & normalize phase value */ |
|
||||
*phase = PARAM(init_phase); |
|
||||
if ( 0 > *phase ) { |
|
||||
*phase = *phase + 360.0; |
|
||||
} |
|
||||
*phase = *phase / 360.0; |
|
||||
|
|
||||
/* set phase value to init_phase */ |
|
||||
*phase_old = *phase; |
|
||||
|
|
||||
/* preset time values to harmless values... */ |
|
||||
*t1 = -1; |
|
||||
*t3 = -1; |
|
||||
} |
|
||||
|
|
||||
loc = STATIC_VAR (locdata); |
|
||||
x = loc->x; |
|
||||
y = loc->y; |
|
||||
|
|
||||
/* Retrieve cntl_input value. */ |
|
||||
cntl_input = INPUT(cntl_in); |
|
||||
|
|
||||
/* Determine segment boundaries within which cntl_input resides */ |
|
||||
/*** cntl_input below lowest cntl_voltage ***/ |
|
||||
if (cntl_input <= x[0]) { |
|
||||
|
|
||||
slope = (y[1] - y[0])/(x[1] - x[0]); |
|
||||
dc = y[0] + (cntl_input - x[0]) * slope; |
|
||||
|
|
||||
} |
|
||||
else |
|
||||
/*** cntl_input above highest cntl_voltage ***/ |
|
||||
|
|
||||
if (cntl_input >= x[cntl_size-1]) { |
|
||||
|
|
||||
slope = (y[cntl_size-1] - y[cntl_size-2]) / |
|
||||
(x[cntl_size-1] - x[cntl_size-2]); |
|
||||
dc = y[cntl_size-1] + (cntl_input - x[cntl_size-1]) * slope; |
|
||||
|
|
||||
} |
|
||||
else { /*** cntl_input within bounds of end midpoints... |
|
||||
must determine position progressively & then |
|
||||
calculate required output. ***/ |
|
||||
|
|
||||
for (i=0; i<cntl_size-1; i++) { |
|
||||
|
|
||||
if ( (cntl_input < x[i+1]) && (cntl_input >= x[i]) ) { |
|
||||
|
/* Allocate PWL table. */ |
||||
|
|
||||
/* Interpolate to the correct duty cycle value */ |
|
||||
|
|
||||
dc = ( (cntl_input - x[i]) / (x[i+1] - x[i]) ) * |
|
||||
( y[i+1]-y[i] ) + y[i]; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
table = malloc(csize * sizeof (struct pwl)); |
||||
|
STATIC_VAR(locdata) = table; |
||||
|
if (!table) |
||||
|
return; |
||||
|
|
||||
/*** If dc < 0.0, clamp to 0 & issue a warning ***/ |
|
||||
if ( 0.0 > dc ) { |
|
||||
dc = 0; |
|
||||
// cm_message_send(d_pwm_negative_dc_error); |
|
||||
|
for (i = 0; i < csize; ++i) { |
||||
|
table[i].ctl = PARAM(cntl_array[i]); |
||||
|
table[i].dc = PARAM(dc_array[i]); |
||||
|
if (table[i].dc <= 0) { |
||||
|
cm_message_printf("Error: duty cycle %g is not positve, " |
||||
|
"value replaced by 0.01.", |
||||
|
table[i].dc); |
||||
|
table[i].dc = 0.01; |
||||
} |
} |
||||
/*** If dc > 1.0, clamp to 1 & issue a warning ***/ |
|
||||
if ( 1.0 < dc ) { |
|
||||
dc = 1; |
|
||||
// cm_message_send(d_pwm_positive_dc_error); |
|
||||
|
else if (table[i].dc >= 1) { |
||||
|
cm_message_printf("Error: duty cycle %g is 1 or larger, " |
||||
|
"value replaced by 0.99.", |
||||
|
table[i].dc); |
||||
|
table[i].dc = 0.99; |
||||
} |
} |
||||
|
} |
||||
|
|
||||
/* calculate the instantaneous phase */ |
|
||||
*phase = *phase_old + frequency * (TIME - T(1)); |
|
||||
|
|
||||
/* dphase is the percent into the cycle for |
|
||||
the period */ |
|
||||
dphase = *phase_old - floor(*phase_old); |
|
||||
|
|
||||
/* Calculate the time variables and the output value |
|
||||
for this iteration */ |
|
||||
|
|
||||
if((*t1 <= TIME) && (TIME <= *t3)) { /* output high */ |
|
||||
|
|
||||
*t3 = T(1) + (1 - dphase)/frequency; |
|
||||
|
/* Allocate state data. */ |
||||
|
|
||||
if(TIME < *t3) { |
|
||||
cm_event_queue(*t3); |
|
||||
} |
|
||||
} |
|
||||
else |
|
||||
|
cm_event_alloc(0, sizeof (struct state)); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
if((*t3 <= TIME) && (TIME <= *t1)) { /* output low */ |
|
||||
|
table = STATIC_VAR(locdata); |
||||
|
if (!table) |
||||
|
return; |
||||
|
state = (struct state *)cm_event_get_ptr(0, 0); |
||||
|
|
||||
if(dphase > (1.0 - dc) ) { |
|
||||
dphase = dphase - 1.0; |
|
||||
} |
|
||||
*t1 = T(1) + ( (1.0 - dc) - dphase)/frequency; |
|
||||
|
if (CALL_TYPE != EVENT) { |
||||
|
if (TIME == 0.0) { |
||||
|
double phase; |
||||
|
|
||||
if(TIME < *t1) { |
|
||||
|
/* Set initial output and state data. */ |
||||
|
|
||||
cm_event_queue(*t1); |
|
||||
} |
|
||||
} |
|
||||
else { |
|
||||
|
ctl = INPUT(cntl_in); |
||||
|
ddc = get_dc(ctl, table, csize); |
||||
|
|
||||
if(dphase > (1.0 - dc) ) { |
|
||||
dphase = dphase - 1.0; |
|
||||
} |
|
||||
*t1 = T(1) + ( (1.0 - dc) - dphase )/frequency; |
|
||||
|
phase = PARAM(init_phase); |
||||
|
phase /= 360.0; |
||||
|
if (phase < 0.0) |
||||
|
phase += 1.0; |
||||
|
|
||||
if((TIME < *t1) || (T(1) == 0)) { |
|
||||
cm_event_queue(*t1); |
|
||||
} |
|
||||
|
/* When would a hypothetical previous transition have been? */ |
||||
|
|
||||
*t3 = T(1) + (1 - dphase)/frequency; |
|
||||
|
state->last_time = delta * (1.0 - ddc - phase); |
||||
|
if (state->last_time < 0.0) { |
||||
|
state->last = ONE; |
||||
|
} else { |
||||
|
state->last = ZERO; |
||||
|
state->last_time = -delta * phase; |
||||
} |
} |
||||
cm_analog_set_temp_bkpt(*t1); |
|
||||
cm_analog_set_temp_bkpt(*t3); |
|
||||
} |
} |
||||
break; |
|
||||
|
|
||||
case EVENT: /** discrete call...lots to do **/ |
|
||||
|
|
||||
test_double = TIME; |
|
||||
|
|
||||
if ( 0.0 == TIME ) { /* DC analysis...preset values, |
|
||||
as appropriate.... */ |
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
/* retrieve & normalize phase value */ |
|
||||
*phase = PARAM(init_phase); |
|
||||
if ( 0 > *phase ) { |
|
||||
*phase = *phase + 360.0; |
|
||||
} |
|
||||
*phase = *phase / 360.0; |
|
||||
|
/* Event call; either one requested previously or just before |
||||
|
* a time-step is accepted. |
||||
|
*/ |
||||
|
|
||||
/* set phase value to init_phase */ |
|
||||
*phase_old = *phase; |
|
||||
|
if (TIME == 0.0) { |
||||
|
OUTPUT_STATE(out) = state->last; |
||||
|
OUTPUT_STRENGTH(out) = STRONG; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
/* preset time values to harmless values... */ |
|
||||
*t1 = -1; |
|
||||
*t3 = -1; |
|
||||
} |
|
||||
|
/* When is the next transition due? */ |
||||
|
|
||||
/* Calculate the time variables and the output value |
|
||||
for this iteration */ |
|
||||
|
ctl = INPUT(cntl_in); |
||||
|
ddc = get_dc(ctl, table, csize); |
||||
|
if (state->last) |
||||
|
delta *= ddc; |
||||
|
else |
||||
|
delta *= (1.0 - ddc); |
||||
|
when = state->last_time + delta; |
||||
|
|
||||
/* Output is always set to STRONG */ |
|
||||
OUTPUT_STRENGTH(out) = STRONG; |
|
||||
|
if (TIME >= when) { |
||||
|
// If the frequency rose rapidly, the transition has been missed. |
||||
|
// Force a shorter time-step and schedule then. |
||||
|
|
||||
if( *t1 == TIME ) { /* rising edge */ |
|
||||
|
cm_analog_set_temp_bkpt(state->last_time + FACTOR * delta); |
||||
|
OUTPUT_CHANGED(out) = FALSE; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
OUTPUT_STATE(out) = ONE; |
|
||||
OUTPUT_DELAY(out) = PARAM(rise_delay); |
|
||||
|
if (TIME >= state->last_time + FACTOR * delta) { |
||||
|
/* TIME is reasonably close to transition time. Request output. */ |
||||
|
|
||||
} |
|
||||
else { |
|
||||
|
state->last_time = when; |
||||
|
state->last ^= ONE; |
||||
|
OUTPUT_STATE(out) = state->last; |
||||
|
OUTPUT_STRENGTH(out) = STRONG; |
||||
|
OUTPUT_DELAY(out) = when - TIME; |
||||
|
|
||||
if ( *t3 == TIME ) { /* falling edge */ |
|
||||
|
/* Request a call in the next half-cycle. */ |
||||
|
|
||||
OUTPUT_STATE(out) = ZERO; |
|
||||
OUTPUT_DELAY(out) = PARAM(fall_delay); |
|
||||
} |
|
||||
|
cm_event_queue(when + FACTOR * delta); |
||||
|
} else { |
||||
|
OUTPUT_CHANGED(out) = FALSE; |
||||
|
|
||||
else { /* no change in output */ |
|
||||
|
if (TIME < state->last_time) { |
||||
|
/* Output transition pending, nothing to do. */ |
||||
|
|
||||
if ( TIME != 0.0 ) { |
|
||||
OUTPUT_CHANGED(out) = FALSE; |
|
||||
} |
|
||||
|
return; |
||||
|
} else { |
||||
|
/* Request a call nearer to transition time. */ |
||||
|
|
||||
if ( (*t1 < TIME) && (TIME < *t3) ) { |
|
||||
OUTPUT_STATE(out) = ONE; |
|
||||
} |
|
||||
else { |
|
||||
OUTPUT_STATE(out) = ZERO; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
break; |
|
||||
} |
|
||||
|
cm_event_queue(state->last_time + FACTOR * delta); |
||||
|
} |
||||
|
} |
||||
} |
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
@ -1,93 +0,0 @@ |
|||||
/*.......1.........2.........3.........4.........5.........6.........7.........8 |
|
||||
================================================================================ |
|
||||
|
|
||||
FILE d_pwm/d_pwm.h |
|
||||
|
|
||||
Public Domain |
|
||||
|
|
||||
Georgia Tech Research Corporation |
|
||||
Atlanta, Georgia 30332 |
|
||||
PROJECT A-8503-405 |
|
||||
The ngspice team |
|
||||
|
|
||||
AUTHORS |
|
||||
|
|
||||
25 Jul 1991 Jeffrey P. Murray |
|
||||
02 Mar 2022 Holger Vogt |
|
||||
|
|
||||
|
|
||||
MODIFICATIONS |
|
||||
|
|
||||
30 Sept 1991 Jeffrey P. Murray |
|
||||
|
|
||||
|
|
||||
SUMMARY |
|
||||
|
|
||||
This file contains the header information for the d_pwm |
|
||||
code model. |
|
||||
|
|
||||
|
|
||||
INTERFACES |
|
||||
|
|
||||
FILE ROUTINE CALLED |
|
||||
|
|
||||
N/A N/A |
|
||||
|
|
||||
|
|
||||
|
|
||||
REFERENCED FILES |
|
||||
|
|
||||
N/A |
|
||||
|
|
||||
|
|
||||
NON-STANDARD FEATURES |
|
||||
|
|
||||
NONE |
|
||||
|
|
||||
===============================================================================*/ |
|
||||
/* |
|
||||
Structures, etc. for d_pwm oscillator model. |
|
||||
7/25/90 |
|
||||
Last Modified 7/25/91 J.P.Murray |
|
||||
3/02/22 H. Vogt */ |
|
||||
|
|
||||
/*=======================================================================*/ |
|
||||
|
|
||||
/*=== INCLUDE FILES =====================================================*/ |
|
||||
|
|
||||
#include <stdio.h> |
|
||||
#include <ctype.h> |
|
||||
#include <math.h> |
|
||||
#include <string.h> |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/*=== CONSTANTS =========================================================*/ |
|
||||
|
|
||||
|
|
||||
/**** Error Messages ****/ |
|
||||
char *d_pwm_allocation_error = "\n**** Error ****\nD_PWM: Error allocating VCO block storage \n"; |
|
||||
char *d_pwm_array_error = "\n**** Error ****\nD_PWM: Size of control array different than duty cycle array \n"; |
|
||||
char *d_pwm_negative_dc_error = "\n**** Error ****\nD_PWM: The extrapolated value for duty cycle\nhas been found to be negative... \n Lower duty cycle level has been clamped to 0.0 \n"; |
|
||||
char *d_pwm_positive_dc_error = "\n**** Error ****\nD_PWM: The extrapolated value for duty cycle\nhas been found to be > 1... \n Upper duty cycle level has been clamped to 1.0 \n"; |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
/*=== MACROS ============================================================*/ |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*=== LOCAL VARIABLES & TYPEDEFS ========================================*/ |
|
||||
|
|
||||
|
|
||||
|
|
||||
/*=== FUNCTION PROTOTYPE DEFINITIONS ====================================*/ |
|
||||
|
|
||||
|
|
||||
/*=======================================================================*/ |
|
||||
|
|
||||
|
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue