view pwm.h @ 4:e2ec8dc3a6d8 default tip

Always empty the receive buffer
author Radomir Dopieralski <sheep-devel@sheep.art.pl>
date Thu, 15 Sep 2016 00:03:04 +0200
parents 2b5078b37907
children
line wrap: on
line source

/*
 * PWM library which allows you to control an arbitrary number of outputs.  All
 * outputs must have the same period, but each one can have a different phase.
 * This library relies on a 16 bit TIMER1, so cannot be run on any chip which
 * does not have access to this hardware.
 *
 * Please set CDEF PWM_PORTx_UNUSED for all ports which either are not on your
 * chip, or which are not being used for PWM.  (If your chip does not have a
 * given port, e.g.  the ATMega168 does not have a PORTA, then there will be
 * compile errors.  If you have the hardware, but are not using it for PWM,
 * then it will just use (slightly) more memory and will be (slightly) slower.
 *
 * Written by Wyatt Olson and Warren Janssens http://digitalcave.ca Released
 * under the Creative Commons Attribution-NonCommercial-ShareAlike license.
 */

#ifndef PWM_H
#define PWM_H

#define PWM_PORTA_UNUSED

#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>
#include <stdlib.h>

// The absolute maximum number of pins defined.  The actual 'used' count is
// passed into pwm_init, and there is no problem with having a larger number
// here than is actually used (other than a bit of wasted SRAM space for
// pre-defined arrays).  By default we set this to 4 as that is a decently
// large number, but not so huge that tons of excess SRAM is wasted.  If you
// are low on memory, or need more outputs, feel free to redefine this in your
// makefile (in the CDEFS variable, beside where F_CPU is defined).
#ifndef PWM_MAX_PINS
#define PWM_MAX_PINS 18
#endif


/*
 * Initializes the PWM library at a given period, using the specified ports.
 * You can have up to PWM_MAX_PINS pins defined here.
 *
 * To initialize this, you must pass in references to each of the PORTs, DDRs,
 * and the values of each pin.  You can do it like this:
 *
 *    volatile uint8_t *ports[8]; ports[0] = &PORTB; ports[1] = &PORTD; ....
 *    ports[5] = &PORTD;
 *
 *    uint8_t pins[8]; pins[0] = 1; ....  pins[5] = 3;
 *
 *    pwm_init(ports, pins, 6, 20000);
 *
 * While the code to do this is uglier than if it were to just be a function
 * call, by allowing an arbitrary number of PWM pins, it is best to do it like
 * this.
 *
 * The period must be less than 3354624us (about 3.3 seconds); any more than
 * this and we just set it to the maximum.  There is no theoretical minimum,
 * but in practice you should probably keep it at 1000us or so (1ms).
 */
void pwm_init(volatile uint8_t *ports[], uint8_t pins[], uint8_t count,
        uint32_t period);


/*
 * Sets the phase of the pin at the given index to the specified value.  The
 * index matches the index used for the arrays in pwm_init().  Internally, this
 * calls pwm_set_phase_batch() and then pwm_apply_batch().
 */
void pwm_set_phase(uint8_t index, uint32_t phase);

/*
 * Sets the phase of the pin at the given index to the specified value, but
 * does not apply the change (recalculate all pin values).  This can be called
 * multiple times for different pins with minimal overhead; when completed all
 * changes, call pwm_apply_batch().
 */
void pwm_set_phase_batch(uint8_t index, uint32_t phase);

/*
 * Recalculates all pin / timer values.  Required after calling
 * pwm_set_phase_batch().
 */
void pwm_apply_batch();

/*
 * Sets the period of the PWM generator, changing the period specified in
 * init().  Applies to all active PWM pins.
 */
void pwm_set_period(uint32_t period);

/*
 * Turns off the PWM generator and stops the timer clock.  Does not clear any
 * config variables.  You can turn PWM back on again using the pwm_start()
 * function.
 */
void pwm_stop();

/*
 * Turns on the PWM generator, starting back at 0.  This should be called after
 * pwm_off() has been called, but pwm_init() *must* already have been called.
 * Calling this when the generator is already on will reset the timer to 0, but
 * otherwise will have no effect.
 *
 * If TIMER1 control registers have been modified by other libraries, you must
 * call pwm_init() instead of pwm_start().
 */
void pwm_start();

#endif