annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
1 /*
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
2 * PWM library which allows you to control an arbitrary number of outputs. All
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
3 * outputs must have the same period, but each one can have a different phase.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
4 * This library relies on a 16 bit TIMER1, so cannot be run on any chip which
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
5 * does not have access to this hardware.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
6 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
7 * Please set CDEF PWM_PORTx_UNUSED for all ports which either are not on your
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
8 * chip, or which are not being used for PWM. (If your chip does not have a
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
9 * given port, e.g. the ATMega168 does not have a PORTA, then there will be
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
10 * compile errors. If you have the hardware, but are not using it for PWM,
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
11 * then it will just use (slightly) more memory and will be (slightly) slower.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
12 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
13 * Written by Wyatt Olson and Warren Janssens http://digitalcave.ca Released
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
14 * under the Creative Commons Attribution-NonCommercial-ShareAlike license.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
15 */
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
16
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
17 #ifndef PWM_H
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
18 #define PWM_H
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
19
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
20 #define PWM_PORTA_UNUSED
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
21
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
22 #include <avr/io.h>
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
23 #include <avr/interrupt.h>
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
24 #include <math.h>
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
25 #include <stdlib.h>
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
26
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
27 // The absolute maximum number of pins defined. The actual 'used' count is
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
28 // passed into pwm_init, and there is no problem with having a larger number
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
29 // here than is actually used (other than a bit of wasted SRAM space for
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
30 // pre-defined arrays). By default we set this to 4 as that is a decently
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
31 // large number, but not so huge that tons of excess SRAM is wasted. If you
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
32 // are low on memory, or need more outputs, feel free to redefine this in your
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
33 // makefile (in the CDEFS variable, beside where F_CPU is defined).
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
34 #ifndef PWM_MAX_PINS
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
35 #define PWM_MAX_PINS 18
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
36 #endif
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
37
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
38
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
39 /*
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
40 * Initializes the PWM library at a given period, using the specified ports.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
41 * You can have up to PWM_MAX_PINS pins defined here.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
42 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
43 * To initialize this, you must pass in references to each of the PORTs, DDRs,
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
44 * and the values of each pin. You can do it like this:
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
45 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
46 * volatile uint8_t *ports[8]; ports[0] = &PORTB; ports[1] = &PORTD; ....
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
47 * ports[5] = &PORTD;
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
48 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
49 * uint8_t pins[8]; pins[0] = 1; .... pins[5] = 3;
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
50 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
51 * pwm_init(ports, pins, 6, 20000);
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
52 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
53 * While the code to do this is uglier than if it were to just be a function
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
54 * call, by allowing an arbitrary number of PWM pins, it is best to do it like
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
55 * this.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
56 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
57 * The period must be less than 3354624us (about 3.3 seconds); any more than
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
58 * this and we just set it to the maximum. There is no theoretical minimum,
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
59 * but in practice you should probably keep it at 1000us or so (1ms).
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
60 */
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
61 void pwm_init(volatile uint8_t *ports[], uint8_t pins[], uint8_t count,
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
62 uint32_t period);
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
63
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
64
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
65 /*
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
66 * Sets the phase of the pin at the given index to the specified value. The
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
67 * index matches the index used for the arrays in pwm_init(). Internally, this
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
68 * calls pwm_set_phase_batch() and then pwm_apply_batch().
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
69 */
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
70 void pwm_set_phase(uint8_t index, uint32_t phase);
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
71
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
72 /*
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
73 * Sets the phase of the pin at the given index to the specified value, but
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
74 * does not apply the change (recalculate all pin values). This can be called
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
75 * multiple times for different pins with minimal overhead; when completed all
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
76 * changes, call pwm_apply_batch().
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
77 */
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
78 void pwm_set_phase_batch(uint8_t index, uint32_t phase);
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
79
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
80 /*
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
81 * Recalculates all pin / timer values. Required after calling
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
82 * pwm_set_phase_batch().
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
83 */
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
84 void pwm_apply_batch();
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
85
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
86 /*
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
87 * Sets the period of the PWM generator, changing the period specified in
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
88 * init(). Applies to all active PWM pins.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
89 */
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
90 void pwm_set_period(uint32_t period);
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
91
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
92 /*
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
93 * Turns off the PWM generator and stops the timer clock. Does not clear any
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
94 * config variables. You can turn PWM back on again using the pwm_start()
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
95 * function.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
96 */
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
97 void pwm_stop();
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
98
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
99 /*
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
100 * Turns on the PWM generator, starting back at 0. This should be called after
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
101 * pwm_off() has been called, but pwm_init() *must* already have been called.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
102 * Calling this when the generator is already on will reset the timer to 0, but
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
103 * otherwise will have no effect.
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
104 *
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
105 * If TIMER1 control registers have been modified by other libraries, you must
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
106 * call pwm_init() instead of pwm_start().
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
107 */
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
108 void pwm_start();
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
109
2b5078b37907 Working servo PWM
Radomir Dopieralski <sheep-devel@sheep.art.pl>
parents:
diff changeset
110 #endif