home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
-
- FILE
- pwm.c - Pulse Width Modulation using timer and parallel port
-
- ENTRY ROUTINES
- pulse - interrupt service routine
- setpfreq - set pulse frequency
- setdcycle - set duty cycle
-
- INITIALIZATION ROUTINE
- pwm_init - initialize for pwm
-
- REMARKS
- This module uses the IBM-PC's parallel printer port to send out
- pulse width modulated motor control pulses. One timer is needed
- to time the pulses. Since the overall control program probably
- needs a timer also, it must tell the initialization routine
- which timer this module can use. The time2.c module is assumed.
-
- The maximum pulse frequency is limited by the timer resolution
- and execution speed.
-
- LAST UPDATE
- 26 January 1988
-
- Copyright(c) 1984-1988, D.M.Auslander and C.H. Tham
-
- ***********************************************************************/
-
- /***********************************************************************
- I M P O R T S
- ***********************************************************************/
-
- #include <stdio.h>
-
- #include "envir.h" /* environment definitions */
- #include "inout.h" /* in() and out() mapping */
- #include "time2.h" /* time2.c module declarations */
-
- #include "pwm.h" /* exported declarations */
-
- #ifdef ANSI
- extern int enable(void);
- extern int disable(void);
- #else
- extern int enable();
- extern int disable();
- #endif
-
-
- /***********************************************************************
- P R I V A T E D A T A V A R I A B L E S
- ***********************************************************************/
-
- #define OUTPORT 0x3BC /* parallel port address */
- #define PULSEON 0x01 /* pulse on output byte */
- #define PULSEOFF 0x00 /* pulse off output byte */
- #define FORWARD 0x10 /* direction bit OR mask for forward */
- #define REVERSE 0x00 /* direction bit OR mask for reverse */
-
- static int ptimer; /* timer number to use with this module */
- static long period; /* cycle period in milliseconds */
- static long ontime; /* on period in milliseconds */
- static long offtime; /* off period in milliseconds */
- static int state; /* current output state, 0 - off, 1 - on */
- static int direction; /* direction, FORWARD or REVERSE */
- static double dcycle; /* PWM duty cycle */
-
-
- /***********************************************************************
- E N T R Y R O U T I N E S
- /***********************************************************************
-
- /*----------------------------------------------------------------------
- PROCEDURE
- SETPFREQ - set pulse frequency in hertz
-
- SYNOPSIS
- void setpfreq(f)
- double f;
-
- PARAMETER
- f - pulse frequency
-
- REMARKS
- Adjust ontime and offtime to new cycle period. Since they are
- accessed asynchronously by pulse(), they must be modifed with
- interrupts disabled. To minimize the interval with interrupts
- disabled, the calculations are stored in temporary variables,
- only assignment is performed with interrupts disabled.
-
- LAST UPDATE
- 25 January 1988
- ----------------------------------------------------------------------*/
-
- void setpfreq(f)
- double f;
- {
- int istat; /* interrupt status */
- long on, off; /* temporary for ontime and offtime */
-
-
- period = (long)(1000.0 / f + 0.5); /* cycle time in ms */
-
- on = (long)(dcycle * period + 0.5);
- off = period - ontime;
-
- istat = disable(); /* begin critical section */
-
- ontime = on;
- offtime = off;
-
- if (istat) /* end critical section */
- enable();
-
- }
-
-
-
- /*----------------------------------------------------------------------
- PROCEDURE
- SETDCYCLE - set duty cycle
-
- SYNOPSIS
- void setdcycle(dc)
- double dc;
-
- PARAMETER
- dc - duty cycle, between 0.0 and 1.0
-
- REMARKS
- Adjust ontime and offtime to new duty cycle. Since they are
- accessed asynchronously by pulse(), they must be modifed with
- interrupts disabled.
-
- To minimize the time where interrupts are disabled, the new on
- and off times are calculated and stored in temporary variables;
- only the assignment to ontime and offtime takes place in the
- critical section.
-
- LAST UPDATE
- 25 January 1988
- ----------------------------------------------------------------------*/
-
- void setdcycle(dc)
- double dc;
- {
- long on, off; /* temporary copies of ontime and offtime */
- int istat; /* interrupt status */
-
-
- if ((dc >= -1.0) && (dc <= 1.0)) /* range check */
- {
- if (dc < 0.0)
- {
- direction = REVERSE; /* set direction mask */
- dcycle = -dc; /* record absolute duty cycle */
- }
- else
- {
- direction = FORWARD;
- dcycle = dc;
- }
-
- on = (long)(dcycle * period + 0.5);
- off = period - on;
-
- istat = disable();
-
- ontime = on;
- offtime = off;
-
- if (istat)
- enable();
- }
- else
- fprintf(stderr, "setdcycle: invalid duty cycle %lf\n", dc);
-
- }
-
-
- /***********************************************************************
- P R I V A T E R O U T I N E
- ***********************************************************************/
-
- /*----------------------------------------------------------------------
- PROCEDURE
- PULSE - pulse control timeout routine
-
- SYNOPSIS
- static void pulse(), called by timer service routine when timeout.
-
- REMARKS
- The timer is reset as soon as possible to reduce timing offsets.
-
- LAST UPDATE
- 25 January 1988
- ----------------------------------------------------------------------*/
-
- static void pulse()
- {
-
- if (state == PULSEOFF) /* is in pulse off state */
- {
- SetDTimer(ptimer, ontime); /* set timer for on interval */
-
- out(OUTPORT, PULSEON | direction); /* pulse on */
-
- state = PULSEON; /* record current state */
- }
- else
- {
- SetDTimer(ptimer, offtime);
-
- out(OUTPORT, PULSEOFF | direction);
-
- state = PULSEOFF;
- }
-
- }
-
-
-
- /***********************************************************************
- I N I T I A L I Z A T I O N R O U T I N E
- ***********************************************************************/
-
- /*----------------------------------------------------------------------
- PROCEDURE
- PWM_INIT - initialize and start PWM pulses
-
- SYNOPSIS
- void pwm_init(timer)
- int timer;
-
- PARAMETER
- timer - which timer to use
-
- REMARKS
- Assumes timing is done using time2.c and install pulse() as the
- timeout routine for the specified timer. Defaults initial duty
- cycle to 0.5 and pulse frequency to quarter MAXFREQ.
-
- LAST UPDATE
- 25 January 1988
- ----------------------------------------------------------------------*/
-
- void pwm_init(timer)
- int timer;
- {
-
- ptimer = timer; /* record timer number */
-
- period = 1000L; /* default 1 second */
-
- setdcycle(0.0); /* direction is set in setdcycle() */
-
- out(OUTPORT, PULSEOFF); /* make sure outputs are off */
- state = PULSEOFF;
-
- SetTsr(timer, pulse, (void *)NULL);
-
- }
-
-
-