@@ -27,10 +27,15 @@ In practice the generator is useful for low frequencies,
27
27
Note: this class generates float values, performance wise this can be optimized,
28
28
to achieve higher speeds at cost of accuracy / precision.
29
29
30
+ As always, feedback and ideas are welcome.
30
31
31
- #### Performance
32
32
33
- Indication of what performance can be expected (based upon 0.2.1 version).
33
+ ### Performance
34
+
35
+ You always have to verify your own performance measurements to see if
36
+ your requirements are met by this library.
37
+
38
+ ** Indication** of what performance can be expected (based upon 0.2.1 version).
34
39
Note that the values need to be transported to a DAC or serial port too.
35
40
Numbers based on performance example, for one single signal.
36
41
@@ -72,55 +77,67 @@ have become slightly slower.
72
77
| Arduino UNO | 16 MHz | square | 57 | 1000 Hz |
73
78
| Arduino UNO | 16 MHz | random_DC | 68 | 500 Hz |
74
79
80
+ See ** functionGeneratorPerformance.ino**
81
+
75
82
76
- #### Accuracy
83
+ ### Accuracy
77
84
78
85
If the time parameter ** t** grows large, the internal math may have rounding
79
86
problems after some time. This can and will affect the quality of the output.
87
+ It is advised to reset ** t** after a number (e.g. 100) full periods
80
88
81
89
Needs further investigations.
82
90
91
+ ### Related
92
+
93
+ - https://github.com/RobTillaart/AD9833 hardware waveform generator.
94
+ - https://github.com/RobTillaart/AD985X hardware waveform generator.
95
+ - https://github.com/RobTillaart/functionGenerator software waveform generator.
96
+ - https://pages.mtu.edu/~suits/notefreqs.html frequency table for notes.
97
+
83
98
84
99
## Interface
85
100
86
101
``` cpp
87
102
#include " functionGenerator.h"
88
103
```
89
104
90
- #### Constructor
105
+ ### Constructor
91
106
92
107
- ** funcgen(float period = 1.0, float amplitude = 1.0, float phase = 0.0, float yShift = 0.0)**
93
108
All parameters (except duty cycle) can be set in the constructor but also later in configuration.
94
109
Default dutyCycle is 50%.
95
110
96
111
97
- #### Configuration
112
+ ### Configuration
98
113
99
- - ** void setPeriod(float period = 1.0)** set the period of the wave in seconds.
114
+ - ** void setPeriod(float period = 1.0)** set the period of the wave in seconds.
115
+ This is the inverse of the frequency.
100
116
- ** float getPeriod()** returns the set period.
101
- - ** void setFrequency(float frequency = 1.0)** set the frequency of the wave in Hertz (1/s).
117
+ - ** void setFrequency(float frequency = 1.0)** set the frequency of the wave in Hertz (1/s).
118
+ This is the inverse of the period.
102
119
- ** float getFrequency()** returns the set frequency in Hertz.
103
- - ** void setAmplitude(float amplitude = 1.0)** sets the amplitude of the wave.
120
+ - ** void setAmplitude(float amplitude = 1.0)** sets the amplitude of the wave.
104
121
The range is from ** -amplitude** to ** +amplitude** .
105
122
Setting the amplitude to 0 gives effectively a zero signal.
106
123
Setting the amplitude to a negative value effectively inverts the signal.
107
124
- ** float getAmplitude()** returns the set amplitude.
108
- - ** void setPhase(float phase = 0.0)** shifts the phase of the wave.
125
+ - ** void setPhase(float phase = 0.0)** shifts the phase of the wave.
109
126
Will only be noticeable when compared with other waves.
110
127
Phase is also known as the X- or horizontal shift.
111
128
- ** float getPhase()** returns the set phase.
112
- - ** void setYShift(float yShift = 0.0)** sets an Y-shift or vertical offset in amplitude.
129
+ - ** void setYShift(float yShift = 0.0)** sets an Y-shift or vertical offset in amplitude.
113
130
This allows to set e.g. the zero level.
114
131
- ** float getYShift()** returns the set Y-shift.
115
- - ** void setDutyCycle(float percentage = 100)** sets the duty cycle of the signal.
132
+ - ** void setDutyCycle(float percentage = 100)** sets the duty cycle of the signal.
116
133
Experimental, not all waveforms have a duty cycle or interpret it differently, see below.
117
134
Duty cycle must be between 0 and 100% and will be clipped otherwise.
118
- - ** float getDutyCycle()** returns the set duty cycle.
119
- - ** void setRandomSeed(uint32_t a, uint32_t b = 314159265)** sets the initial seeds for the
135
+ - ** float getDutyCycle()** returns the set (clipped) duty cycle.
136
+ - ** void setRandomSeed(uint32_t a, uint32_t b = 314159265)** sets the initial seeds for the
120
137
(Marsaglia) random number generator. The first is mandatory, the second is optional.
121
138
122
139
123
- #### Wave forms
140
+ ### Wave forms
124
141
125
142
The variable t == time in seconds.
126
143
@@ -129,11 +146,12 @@ The variable t == time in seconds.
129
146
- mode == 1 ==> sawtooth |\\ . Effectively equals inverting the amplitude.
130
147
- ** float triangle(float t)** triangle form, duty cycle default 50%.
131
148
- ** float square(float t)** square wave with duty cycle default 50%.
132
- - ** float sinus(float t)** sinus wave, has no duty cycle.
149
+ - ** float sinus(float t)** sinus wave, has no duty cycle.
133
150
- ** float stair(float t, uint16_t steps = 8, uint8_t mode = 0)** defaults to 8 steps up.
134
151
- mode = 0 ==> steps up
135
152
- mode = 1 ==> steps down. Effectively equals inverting the amplitude.
136
- - ** float random()** random noise generation.
153
+ - ** float random()** random noise generation between 0 and amplitude.
154
+ Uses Marsaglia random generator.
137
155
- ** float line()** constant voltage line.
138
156
Height depends on the YShift and amplitude.
139
157
- ** float zero()** constant zero.
@@ -142,7 +160,29 @@ The functions **line()** and **zero()** can be used to drive a constant voltage
142
160
from a DAC and can be used to calibrate the generator / DAC combination.
143
161
144
162
145
- #### Duty Cycle
163
+ Experimental 0.2.7
164
+
165
+ - ** float sinusDiode(float t)** sinus wave, only positive pulses.
166
+ (better name welcome).
167
+ - ** float sinusRectified(float t)** sinus wave, with "abs(negative pulses)".
168
+ (better name welcome).
169
+ - ** float trapezium1(float t)** trapezium wave.
170
+ DutyCycle changes steepness of the falling and rising edge.
171
+ The wave changes from a square wave, via trapezium to a triangle wave.
172
+ - ** float trapezium2(float t)** trapezium wave.
173
+ DutyCycle changes duration HIGH vs LOW, wave stays trapezium like.
174
+ Note at 50% DC the two trapezium functions are identical.
175
+ - ** float heartBeat(float t)** simplified heartbeat wave.
176
+ To get a regular BPM heartbeat one should ** setFrequency(BPM/60.0)** e.g 72/60 = 1.2.
177
+ - ** float freeWave(float t, int16_t arr, int16_t N)** define a free wave form.
178
+ It uses an array of ** N+1** values, dividing a full period in ** N** equidistant steps.
179
+ The last value should equal the first value to have a smooth transition.
180
+ The values of the array normally vary between -10000 and +10000 to manage
181
+ the set the relative amplitude in small steps.
182
+ These are scaled back to -1.0 to +1.0 times the amplitude.
183
+
184
+
185
+ ### Duty Cycle
146
186
147
187
Since 0.2.5 the library has ** experimental** support for duty cycle.
148
188
The meaning of duty cycle differs per wave form.
@@ -160,7 +200,16 @@ with respect to previous value.
160
200
Implemented as a weighed average between new and previous value.
161
201
Made a separate function as handling the duty cycle slows performance substantial.
162
202
Initial starts at zero and can be adjusted with ** YShift()** .
203
+ - ** float trapezium1(float t)** The duty cycle changes the steepness of the rising
204
+ and falling edges. This changes the form from square wave to trapezium to triangle.
205
+ The length of the HIGH LOW level go from 0 to half a period.
206
+ - ** float trapezium2(float t)** The duty cycle determines the length of the HIGH level,
207
+ which is 0 for 0% DC and half a period for 100% DC.
208
+ The rising and falling edges stay same.
209
+ - ** float heartBeat(float t)** The duty cycle determines the part of the period
210
+ that the signal ~ zero.
163
211
212
+ ### No duty cycle
164
213
165
214
The other functions need to be investigated what duty cycle means.
166
215
Current ideas that are ** NOT** implemented:
@@ -171,41 +220,52 @@ Think of it as the halve of the triangle wave.
171
220
- ** stair()** like sawtooth??
172
221
- ** line()** has no period so does not make sense (yet).
173
222
- ** zero()** has no period so does not make sense (yet).
174
-
175
- Feedback and ideas are welcome.
176
-
223
+ - ** float sinusDiode(float t) **
224
+ - ** float sinusRectified(float t) **
225
+ - ** float freeWave(float t, int16_t arr, int16_t N) **
177
226
178
227
## Future
179
228
180
-
181
229
#### Must
182
230
183
- - documentation
184
- - quality of signals - after substantial time t
185
- - max freq per wave form etc.
186
- Should this be in the library?
187
-
231
+ - improve documentation
232
+ - reorganize
233
+ - section per function might be better.
188
234
189
235
#### Should
190
236
191
237
- smart reseed needed for random().
192
- - initialize random generator with compile time.
193
-
238
+ - initialize random generator with compile file + date + time.
239
+ - use function values for seed bits.
240
+ - stand-alone functions in separate .h
241
+ - clean up code
194
242
195
243
#### Could
196
244
197
- - waves
198
- - trapezium wave (could merge square and triangle and sawtooth)
199
- - white noise, pink noise etc.
200
- - RC function curve.
245
+ - ASDR wave
246
+ - https://en.wikipedia.org/wiki/Envelope_(music)
247
+ - ** float ADSR(float t, float A, float D, float S, float R)**
248
+ - ADSR are percentages, A + D + R < 1.0
249
+ - S = % of amplitude.
201
250
- external clock to synchronize two or more software function generators.
202
- - stand-alone functions in separate .h
203
251
- check for synergy with https://github.com/RobTillaart/AD985X
204
252
- investigate performance.
205
253
- algorithms for DAC specific gains e.g. 10-12-16 bit.
206
254
- improve performance sin() lookup table.
207
255
- add float variable for ``` _perDC = _period * _dutyCycle ```
208
256
- do we need ** freq4** ? not since DC.
257
+ - heartBeat
258
+ - small noise/variation parameter on amplitude and frequency.
259
+ - reduce footprint ==> wrapper around freeWave()
260
+ - waves
261
+ - white noise, pink noise (better done with hardware)
262
+ - min() + max() => return +-amplitude + yshift?
263
+ - RC function curve.
264
+ - Gamma curve.
265
+ - create a function table? with what?
266
+ - create an example program to sample an arbitrary wave form
267
+ - output in the right format.
268
+ - slow sampling vs real time.
209
269
210
270
211
271
#### Examples
@@ -228,6 +288,8 @@ Feedback and ideas are welcome.
228
288
- ** float stairDC()**
229
289
- Bezier curve? (too complex)
230
290
- record a signal and play back ==> separate class
291
+ - document max frequency per wave form etc.
292
+ Should this be in the library? differs per board.
231
293
232
294
233
295
## Support
0 commit comments