Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: MAX5719BOB_FunctionGen
FunctionGenerator.h@0:1c31998b91c6, 2021-01-03 (annotated)
- Committer:
- whismanoid
- Date:
- Sun Jan 03 06:15:34 2021 +0000
- Revision:
- 0:1c31998b91c6
Initial commit class DACFunctionGenerator
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| whismanoid | 0:1c31998b91c6 | 1 | // /******************************************************************************* |
| whismanoid | 0:1c31998b91c6 | 2 | // * Copyright (C) 2021 Maxim Integrated Products, Inc., All Rights Reserved. |
| whismanoid | 0:1c31998b91c6 | 3 | // * |
| whismanoid | 0:1c31998b91c6 | 4 | // * Permission is hereby granted, free of charge, to any person obtaining a |
| whismanoid | 0:1c31998b91c6 | 5 | // * copy of this software and associated documentation files (the "Software"), |
| whismanoid | 0:1c31998b91c6 | 6 | // * to deal in the Software without restriction, including without limitation |
| whismanoid | 0:1c31998b91c6 | 7 | // * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| whismanoid | 0:1c31998b91c6 | 8 | // * and/or sell copies of the Software, and to permit persons to whom the |
| whismanoid | 0:1c31998b91c6 | 9 | // * Software is furnished to do so, subject to the following conditions: |
| whismanoid | 0:1c31998b91c6 | 10 | // * |
| whismanoid | 0:1c31998b91c6 | 11 | // * The above copyright notice and this permission notice shall be included |
| whismanoid | 0:1c31998b91c6 | 12 | // * in all copies or substantial portions of the Software. |
| whismanoid | 0:1c31998b91c6 | 13 | // * |
| whismanoid | 0:1c31998b91c6 | 14 | // * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| whismanoid | 0:1c31998b91c6 | 15 | // * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| whismanoid | 0:1c31998b91c6 | 16 | // * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
| whismanoid | 0:1c31998b91c6 | 17 | // * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES |
| whismanoid | 0:1c31998b91c6 | 18 | // * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| whismanoid | 0:1c31998b91c6 | 19 | // * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| whismanoid | 0:1c31998b91c6 | 20 | // * OTHER DEALINGS IN THE SOFTWARE. |
| whismanoid | 0:1c31998b91c6 | 21 | // * |
| whismanoid | 0:1c31998b91c6 | 22 | // * Except as contained in this notice, the name of Maxim Integrated |
| whismanoid | 0:1c31998b91c6 | 23 | // * Products, Inc. shall not be used except as stated in the Maxim Integrated |
| whismanoid | 0:1c31998b91c6 | 24 | // * Products, Inc. Branding Policy. |
| whismanoid | 0:1c31998b91c6 | 25 | // * |
| whismanoid | 0:1c31998b91c6 | 26 | // * The mere transfer of this software does not imply any licenses |
| whismanoid | 0:1c31998b91c6 | 27 | // * of trade secrets, proprietary technology, copyrights, patents, |
| whismanoid | 0:1c31998b91c6 | 28 | // * trademarks, maskwork rights, or any other form of intellectual |
| whismanoid | 0:1c31998b91c6 | 29 | // * property whatsoever. Maxim Integrated Products, Inc. retains all |
| whismanoid | 0:1c31998b91c6 | 30 | // * ownership rights. |
| whismanoid | 0:1c31998b91c6 | 31 | // ******************************************************************************* |
| whismanoid | 0:1c31998b91c6 | 32 | // */ |
| whismanoid | 0:1c31998b91c6 | 33 | // ********************************************************************* |
| whismanoid | 0:1c31998b91c6 | 34 | // @file FunctionGenerator.h |
| whismanoid | 0:1c31998b91c6 | 35 | // ********************************************************************* |
| whismanoid | 0:1c31998b91c6 | 36 | |
| whismanoid | 0:1c31998b91c6 | 37 | // Prevent multiple declaration |
| whismanoid | 0:1c31998b91c6 | 38 | #ifndef __FunctionGenerator_H__ |
| whismanoid | 0:1c31998b91c6 | 39 | #define __FunctionGenerator_H__ |
| whismanoid | 0:1c31998b91c6 | 40 | |
| whismanoid | 0:1c31998b91c6 | 41 | //-------------------------------------------------- |
| whismanoid | 0:1c31998b91c6 | 42 | // Option to support Sine waveform; requires floating point |
| whismanoid | 0:1c31998b91c6 | 43 | // |
| whismanoid | 0:1c31998b91c6 | 44 | // Triangle Ramp: Ramp Up then Ramp Down |
| whismanoid | 0:1c31998b91c6 | 45 | #ifndef USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 46 | #define USE_FunctionGenerator_TriangleRampUpDown 0 |
| whismanoid | 0:1c31998b91c6 | 47 | #endif // USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 48 | // |
| whismanoid | 0:1c31998b91c6 | 49 | // Ramp Up from m_code_limit_L to m_code_limit_H by m_code_increment |
| whismanoid | 0:1c31998b91c6 | 50 | #ifndef USE_FunctionGenerator_RampUp |
| whismanoid | 0:1c31998b91c6 | 51 | #define USE_FunctionGenerator_RampUp 0 |
| whismanoid | 0:1c31998b91c6 | 52 | #endif // USE_FunctionGenerator_RampUp |
| whismanoid | 0:1c31998b91c6 | 53 | // |
| whismanoid | 0:1c31998b91c6 | 54 | // Ramp Down from m_code_limit_H to m_code_limit_L by m_code_increment |
| whismanoid | 0:1c31998b91c6 | 55 | #ifndef USE_FunctionGenerator_RampDown |
| whismanoid | 0:1c31998b91c6 | 56 | #define USE_FunctionGenerator_RampDown 0 |
| whismanoid | 0:1c31998b91c6 | 57 | #endif // USE_FunctionGenerator_RampDown |
| whismanoid | 0:1c31998b91c6 | 58 | // |
| whismanoid | 0:1c31998b91c6 | 59 | // Computed Sinusoid (Sine wave) m_code_amplitude * sin(m_phase_accumulator) + m_code_offset; m_phase_increment determines frequency |
| whismanoid | 0:1c31998b91c6 | 60 | #ifndef USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 61 | #define USE_FunctionGenerator_Sine 0 |
| whismanoid | 0:1c31998b91c6 | 62 | #endif // USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 63 | // |
| whismanoid | 0:1c31998b91c6 | 64 | // Arbitrary Waveform Generation by table lookup; m_table_index_increment determines frequency |
| whismanoid | 0:1c31998b91c6 | 65 | #ifndef USE_FunctionGenerator_Table |
| whismanoid | 0:1c31998b91c6 | 66 | #define USE_FunctionGenerator_Table 0 |
| whismanoid | 0:1c31998b91c6 | 67 | #endif // USE_FunctionGenerator_Table |
| whismanoid | 0:1c31998b91c6 | 68 | // |
| whismanoid | 0:1c31998b91c6 | 69 | // Sinusoid using Arbitrary Waveform Generation table lookup |
| whismanoid | 0:1c31998b91c6 | 70 | #ifndef USE_FunctionGenerator_Sine_Table |
| whismanoid | 0:1c31998b91c6 | 71 | #define USE_FunctionGenerator_Sine_Table 1 |
| whismanoid | 0:1c31998b91c6 | 72 | #endif // USE_FunctionGenerator_Sine_Table |
| whismanoid | 0:1c31998b91c6 | 73 | // |
| whismanoid | 0:1c31998b91c6 | 74 | |
| whismanoid | 0:1c31998b91c6 | 75 | // standard include for target platform |
| whismanoid | 0:1c31998b91c6 | 76 | #include "mbed.h" |
| whismanoid | 0:1c31998b91c6 | 77 | // workaround for error 'M_PI' was not declared |
| whismanoid | 0:1c31998b91c6 | 78 | #ifndef M_PI |
| whismanoid | 0:1c31998b91c6 | 79 | #define M_PI 3.14159265358979323846 |
| whismanoid | 0:1c31998b91c6 | 80 | #endif |
| whismanoid | 0:1c31998b91c6 | 81 | |
| whismanoid | 0:1c31998b91c6 | 82 | /** |
| whismanoid | 0:1c31998b91c6 | 83 | @brief DACFunctionGenerator class is a Function Generator for DAC output |
| whismanoid | 0:1c31998b91c6 | 84 | */ |
| whismanoid | 0:1c31998b91c6 | 85 | // |
| whismanoid | 0:1c31998b91c6 | 86 | class DACFunctionGenerator |
| whismanoid | 0:1c31998b91c6 | 87 | { |
| whismanoid | 0:1c31998b91c6 | 88 | public: |
| whismanoid | 0:1c31998b91c6 | 89 | enum shape_t { |
| whismanoid | 0:1c31998b91c6 | 90 | // Constant DC output |
| whismanoid | 0:1c31998b91c6 | 91 | Constant = 0, |
| whismanoid | 0:1c31998b91c6 | 92 | // |
| whismanoid | 0:1c31998b91c6 | 93 | #if USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 94 | // Triangle Ramp: Ramp Up then Ramp Down |
| whismanoid | 0:1c31998b91c6 | 95 | TriangleRampUpDown, |
| whismanoid | 0:1c31998b91c6 | 96 | #endif // USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 97 | // |
| whismanoid | 0:1c31998b91c6 | 98 | #if USE_FunctionGenerator_RampUp |
| whismanoid | 0:1c31998b91c6 | 99 | // Ramp Up from m_code_limit_L to m_code_limit_H by m_code_increment |
| whismanoid | 0:1c31998b91c6 | 100 | RampUp, |
| whismanoid | 0:1c31998b91c6 | 101 | #endif // USE_FunctionGenerator_RampUp |
| whismanoid | 0:1c31998b91c6 | 102 | // |
| whismanoid | 0:1c31998b91c6 | 103 | #if USE_FunctionGenerator_RampDown |
| whismanoid | 0:1c31998b91c6 | 104 | // Ramp Down from m_code_limit_H to m_code_limit_L by m_code_increment |
| whismanoid | 0:1c31998b91c6 | 105 | RampDown, |
| whismanoid | 0:1c31998b91c6 | 106 | #endif // USE_FunctionGenerator_RampDown |
| whismanoid | 0:1c31998b91c6 | 107 | // |
| whismanoid | 0:1c31998b91c6 | 108 | #if USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 109 | // Computed Sinusoid (Sine wave) m_code_amplitude * sin(m_phase_accumulator) + m_code_offset; m_phase_increment determines frequency |
| whismanoid | 0:1c31998b91c6 | 110 | Sine, |
| whismanoid | 0:1c31998b91c6 | 111 | #endif // USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 112 | // |
| whismanoid | 0:1c31998b91c6 | 113 | #if (USE_FunctionGenerator_Table) || (USE_FunctionGenerator_Sine_Table) |
| whismanoid | 0:1c31998b91c6 | 114 | // Arbitrary Waveform Generation by table lookup; m_table_index_increment determines frequency |
| whismanoid | 0:1c31998b91c6 | 115 | Table, |
| whismanoid | 0:1c31998b91c6 | 116 | #endif // USE_FunctionGenerator_Table |
| whismanoid | 0:1c31998b91c6 | 117 | // |
| whismanoid | 0:1c31998b91c6 | 118 | } m_shape; //!< shape of the generated waveform |
| whismanoid | 0:1c31998b91c6 | 119 | private: |
| whismanoid | 0:1c31998b91c6 | 120 | uint32_t m_code; //!< DAC output code value (unsigned value) |
| whismanoid | 0:1c31998b91c6 | 121 | public: |
| whismanoid | 0:1c31998b91c6 | 122 | uint32_t m_code_limit_H; //!< high limit of code (unsigned value) |
| whismanoid | 0:1c31998b91c6 | 123 | uint32_t m_code_limit_L; //!< low limit of code (unsigned value) |
| whismanoid | 0:1c31998b91c6 | 124 | #if (USE_FunctionGenerator_TriangleRampUpDown) || (USE_FunctionGenerator_RampUp) || (USE_FunctionGenerator_RampDown) |
| whismanoid | 0:1c31998b91c6 | 125 | int32_t m_code_increment; //!< amount to be added to code (signed value) (Ramp) |
| whismanoid | 0:1c31998b91c6 | 126 | #endif |
| whismanoid | 0:1c31998b91c6 | 127 | #if (USE_FunctionGenerator_Sine) || (USE_FunctionGenerator_Sine_Table) |
| whismanoid | 0:1c31998b91c6 | 128 | uint32_t m_code_offset; //!< (Sine) |
| whismanoid | 0:1c31998b91c6 | 129 | uint32_t m_code_amplitude; //!< (Sine) |
| whismanoid | 0:1c31998b91c6 | 130 | #endif // USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 131 | #if (USE_FunctionGenerator_Sine) |
| whismanoid | 0:1c31998b91c6 | 132 | float m_phase_accumulator; //!< phase angle in radians (Sine) |
| whismanoid | 0:1c31998b91c6 | 133 | float m_phase_increment; //!< increment in phase angle in radians, per sample period (Sine) |
| whismanoid | 0:1c31998b91c6 | 134 | const float m_phase_accumulator_limit_H = (2 * M_PI); //!< high limit of phase angle in radians (Sine) |
| whismanoid | 0:1c31998b91c6 | 135 | #endif // USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 136 | #if (USE_FunctionGenerator_Table) || (USE_FunctionGenerator_Sine_Table) |
| whismanoid | 0:1c31998b91c6 | 137 | uint32_t* m_table_data; //!< (Table) |
| whismanoid | 0:1c31998b91c6 | 138 | uint32_t m_table_index; //!< (Table) |
| whismanoid | 0:1c31998b91c6 | 139 | int32_t m_table_index_increment; //!< (Table) |
| whismanoid | 0:1c31998b91c6 | 140 | uint32_t m_table_length; //!< (Table) |
| whismanoid | 0:1c31998b91c6 | 141 | #endif // USE_FunctionGenerator_Table |
| whismanoid | 0:1c31998b91c6 | 142 | public: |
| whismanoid | 0:1c31998b91c6 | 143 | DACFunctionGenerator() //!< #ctor |
| whismanoid | 0:1c31998b91c6 | 144 | { // ............0xFFFFF for 20-bit |
| whismanoid | 0:1c31998b91c6 | 145 | m_code_limit_H = 0xFFFFF; |
| whismanoid | 0:1c31998b91c6 | 146 | m_code_limit_L = 0x00000; |
| whismanoid | 0:1c31998b91c6 | 147 | #if (USE_FunctionGenerator_TriangleRampUpDown) || (USE_FunctionGenerator_RampUp) || (USE_FunctionGenerator_RampDown) |
| whismanoid | 0:1c31998b91c6 | 148 | m_code_increment = 0x00001; |
| whismanoid | 0:1c31998b91c6 | 149 | #endif |
| whismanoid | 0:1c31998b91c6 | 150 | m_code = (m_code_limit_L/4 + m_code_limit_H/4) * 2; // approx (code_limit_H+code_limit_L)/2 but avoid overflow |
| whismanoid | 0:1c31998b91c6 | 151 | #if USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 152 | m_shape = TriangleRampUpDown; |
| whismanoid | 0:1c31998b91c6 | 153 | #else // USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 154 | m_shape = Constant; |
| whismanoid | 0:1c31998b91c6 | 155 | #endif // USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 156 | }; |
| whismanoid | 0:1c31998b91c6 | 157 | void Configure_Constant(uint32_t code = 0x5555) |
| whismanoid | 0:1c31998b91c6 | 158 | { |
| whismanoid | 0:1c31998b91c6 | 159 | m_code = code; |
| whismanoid | 0:1c31998b91c6 | 160 | m_shape = Constant; |
| whismanoid | 0:1c31998b91c6 | 161 | } |
| whismanoid | 0:1c31998b91c6 | 162 | #if USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 163 | void Configure_TriangleRampUpDown( |
| whismanoid | 0:1c31998b91c6 | 164 | uint32_t code_limit_L = 0x00000, |
| whismanoid | 0:1c31998b91c6 | 165 | uint32_t code_limit_H = 0xFFFFF, |
| whismanoid | 0:1c31998b91c6 | 166 | int32_t increment = 0x00001 |
| whismanoid | 0:1c31998b91c6 | 167 | ) |
| whismanoid | 0:1c31998b91c6 | 168 | { |
| whismanoid | 0:1c31998b91c6 | 169 | m_code_limit_H = code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 170 | m_code_limit_L = code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 171 | m_code_increment = increment; |
| whismanoid | 0:1c31998b91c6 | 172 | m_code = (m_code_limit_L/4 + m_code_limit_H/4) * 2; // approx (code_limit_H+code_limit_L)/2 but avoid overflow |
| whismanoid | 0:1c31998b91c6 | 173 | m_shape = TriangleRampUpDown; |
| whismanoid | 0:1c31998b91c6 | 174 | } |
| whismanoid | 0:1c31998b91c6 | 175 | #endif // USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 176 | #if USE_FunctionGenerator_RampUp |
| whismanoid | 0:1c31998b91c6 | 177 | void Configure_RampUp( |
| whismanoid | 0:1c31998b91c6 | 178 | uint32_t code_limit_L = 0x00000, |
| whismanoid | 0:1c31998b91c6 | 179 | uint32_t code_limit_H = 0xFFFFF, |
| whismanoid | 0:1c31998b91c6 | 180 | int32_t increment = 0x00001 |
| whismanoid | 0:1c31998b91c6 | 181 | ) |
| whismanoid | 0:1c31998b91c6 | 182 | { |
| whismanoid | 0:1c31998b91c6 | 183 | m_code_limit_H = code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 184 | m_code_limit_L = code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 185 | m_code_increment = increment; |
| whismanoid | 0:1c31998b91c6 | 186 | m_code = code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 187 | m_shape = RampUp; |
| whismanoid | 0:1c31998b91c6 | 188 | } |
| whismanoid | 0:1c31998b91c6 | 189 | #endif // USE_FunctionGenerator_RampUp |
| whismanoid | 0:1c31998b91c6 | 190 | #if USE_FunctionGenerator_RampDown |
| whismanoid | 0:1c31998b91c6 | 191 | void Configure_RampDown( |
| whismanoid | 0:1c31998b91c6 | 192 | uint32_t code_limit_L = 0x00000, |
| whismanoid | 0:1c31998b91c6 | 193 | uint32_t code_limit_H = 0xFFFFF, |
| whismanoid | 0:1c31998b91c6 | 194 | int32_t increment = 0x00001 |
| whismanoid | 0:1c31998b91c6 | 195 | ) |
| whismanoid | 0:1c31998b91c6 | 196 | { |
| whismanoid | 0:1c31998b91c6 | 197 | m_code_limit_H = code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 198 | m_code_limit_L = code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 199 | m_code_increment = increment; |
| whismanoid | 0:1c31998b91c6 | 200 | m_code = code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 201 | m_shape = RampDown; |
| whismanoid | 0:1c31998b91c6 | 202 | } |
| whismanoid | 0:1c31998b91c6 | 203 | #endif // USE_FunctionGenerator_RampDown |
| whismanoid | 0:1c31998b91c6 | 204 | #if USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 205 | void Configure_Sine( // TODO WIP Sine |
| whismanoid | 0:1c31998b91c6 | 206 | uint32_t code_limit_L = 0x00000, |
| whismanoid | 0:1c31998b91c6 | 207 | uint32_t code_limit_H = 0xFFFFF, |
| whismanoid | 0:1c31998b91c6 | 208 | float num_samples_per_tone_cycle = 10.0 |
| whismanoid | 0:1c31998b91c6 | 209 | ) |
| whismanoid | 0:1c31998b91c6 | 210 | { |
| whismanoid | 0:1c31998b91c6 | 211 | m_code_limit_H = code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 212 | m_code_limit_L = code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 213 | //~ m_code_increment = increment; |
| whismanoid | 0:1c31998b91c6 | 214 | m_code = (m_code_limit_L/4 + m_code_limit_H/4) * 2; // approx (code_limit_H+code_limit_L)/2 but avoid overflow |
| whismanoid | 0:1c31998b91c6 | 215 | m_code_offset = (m_code_limit_L/4 + m_code_limit_H/4) * 2; // approx (code_limit_H+code_limit_L)/2 but avoid overflow |
| whismanoid | 0:1c31998b91c6 | 216 | m_code_amplitude = m_code_limit_H - m_code_offset; |
| whismanoid | 0:1c31998b91c6 | 217 | m_phase_accumulator = 0; |
| whismanoid | 0:1c31998b91c6 | 218 | //~ m_phase_accumulator_limit_H = (2 * M_PI); |
| whismanoid | 0:1c31998b91c6 | 219 | m_phase_increment = m_phase_accumulator_limit_H / num_samples_per_tone_cycle; |
| whismanoid | 0:1c31998b91c6 | 220 | //~ m_phase_increment = (2 * M_PI) / num_samples_per_tone_cycle; |
| whismanoid | 0:1c31998b91c6 | 221 | m_shape = Sine; |
| whismanoid | 0:1c31998b91c6 | 222 | } |
| whismanoid | 0:1c31998b91c6 | 223 | #endif // USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 224 | #if USE_FunctionGenerator_Table |
| whismanoid | 0:1c31998b91c6 | 225 | void Configure_Table( // TODO WIP Table |
| whismanoid | 0:1c31998b91c6 | 226 | uint32_t* table_data, |
| whismanoid | 0:1c31998b91c6 | 227 | uint32_t table_length, |
| whismanoid | 0:1c31998b91c6 | 228 | int32_t increment = 0x00001 |
| whismanoid | 0:1c31998b91c6 | 229 | ) |
| whismanoid | 0:1c31998b91c6 | 230 | { |
| whismanoid | 0:1c31998b91c6 | 231 | m_table_data = table_data; |
| whismanoid | 0:1c31998b91c6 | 232 | m_table_length = table_length; |
| whismanoid | 0:1c31998b91c6 | 233 | m_code = table_data[0]; |
| whismanoid | 0:1c31998b91c6 | 234 | //~ m_phase_accumulator = 0; |
| whismanoid | 0:1c31998b91c6 | 235 | //~ m_phase_increment = (2 * M_PI) / num_samples_per_tone_cycle; |
| whismanoid | 0:1c31998b91c6 | 236 | m_table_index_increment = increment; |
| whismanoid | 0:1c31998b91c6 | 237 | m_shape = Table; |
| whismanoid | 0:1c31998b91c6 | 238 | } |
| whismanoid | 0:1c31998b91c6 | 239 | #endif // USE_FunctionGenerator_Table |
| whismanoid | 0:1c31998b91c6 | 240 | #if USE_FunctionGenerator_Sine_Table |
| whismanoid | 0:1c31998b91c6 | 241 | // TODO: implement Configure_Sine_Table(uint32_t code_limit_L, uint32_t code_limit_H, float num_samples_per_tone_cycle, uint32_t* table_data_out, uint32_t table_length) |
| whismanoid | 0:1c31998b91c6 | 242 | void Configure_Sine_Table( |
| whismanoid | 0:1c31998b91c6 | 243 | uint32_t* table_data_buffer, |
| whismanoid | 0:1c31998b91c6 | 244 | uint32_t table_length, |
| whismanoid | 0:1c31998b91c6 | 245 | uint32_t code_limit_L = 0x00000, |
| whismanoid | 0:1c31998b91c6 | 246 | uint32_t code_limit_H = 0xFFFFF, |
| whismanoid | 0:1c31998b91c6 | 247 | float num_tone_cycles_in_table = 7 |
| whismanoid | 0:1c31998b91c6 | 248 | ) |
| whismanoid | 0:1c31998b91c6 | 249 | { |
| whismanoid | 0:1c31998b91c6 | 250 | m_code_limit_H = code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 251 | m_code_limit_L = code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 252 | //~ m_code_increment = increment; |
| whismanoid | 0:1c31998b91c6 | 253 | m_code = (m_code_limit_L/4 + m_code_limit_H/4) * 2; // approx (code_limit_H+code_limit_L)/2 but avoid overflow |
| whismanoid | 0:1c31998b91c6 | 254 | m_code_offset = (m_code_limit_L/4 + m_code_limit_H/4) * 2; // approx (code_limit_H+code_limit_L)/2 but avoid overflow |
| whismanoid | 0:1c31998b91c6 | 255 | m_code_amplitude = m_code_limit_H - m_code_offset; |
| whismanoid | 0:1c31998b91c6 | 256 | m_table_data = table_data_buffer; |
| whismanoid | 0:1c31998b91c6 | 257 | m_table_length = table_length; |
| whismanoid | 0:1c31998b91c6 | 258 | // |
| whismanoid | 0:1c31998b91c6 | 259 | // DIAGNOSTIC: initialize table to midscale |
| whismanoid | 0:1c31998b91c6 | 260 | //~ for (m_table_index = 0; m_table_index < m_table_length; m_table_index++) |
| whismanoid | 0:1c31998b91c6 | 261 | //~ { |
| whismanoid | 0:1c31998b91c6 | 262 | //~ m_table_data[m_table_index] = m_code_offset - 0.75 * m_code_amplitude; |
| whismanoid | 0:1c31998b91c6 | 263 | //~ } |
| whismanoid | 0:1c31998b91c6 | 264 | //~ m_code_amplitude = 0.5 * m_code_amplitude; // DIAGNOSTIC |
| whismanoid | 0:1c31998b91c6 | 265 | //~ m_table_data[0] = m_code_limit_L; // DIAGNOSTIC |
| whismanoid | 0:1c31998b91c6 | 266 | //~ m_table_data[1] = m_code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 267 | //~ m_table_data[3] = m_code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 268 | //~ m_table_data[m_table_length-1] = m_code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 269 | // |
| whismanoid | 0:1c31998b91c6 | 270 | // write a sine wave table into caller-provided buffer table_data_buffer[table_length] |
| whismanoid | 0:1c31998b91c6 | 271 | // float num_tone_cycles_in_table = 7; // num_samples_per_tone_cycle; // ???? |
| whismanoid | 0:1c31998b91c6 | 272 | // TODO: is m_table_data[m_table_length-1] not being initialized? |
| whismanoid | 0:1c31998b91c6 | 273 | for (m_table_index = 0; m_table_index < /* DIAGNOSTIC */ m_table_length+0; m_table_index++) |
| whismanoid | 0:1c31998b91c6 | 274 | { |
| whismanoid | 0:1c31998b91c6 | 275 | // calculate phase angle from m_table_index |
| whismanoid | 0:1c31998b91c6 | 276 | // m_table_index = m_table_length * m_phase_accumulator / (2 * M_PI); |
| whismanoid | 0:1c31998b91c6 | 277 | // m_phase_accumulator = m_phase_accumulator + m_phase_increment |
| whismanoid | 0:1c31998b91c6 | 278 | // m_phase_increment = m_phase_accumulator_limit_H / num_samples_per_tone_cycle; |
| whismanoid | 0:1c31998b91c6 | 279 | float phase_accumulator = num_tone_cycles_in_table * ((((float)m_table_index + 0.5) / (float)m_table_length) * (2.0 * M_PI)); |
| whismanoid | 0:1c31998b91c6 | 280 | // |
| whismanoid | 0:1c31998b91c6 | 281 | // calculate code from sine(phase angle) |
| whismanoid | 0:1c31998b91c6 | 282 | float code = m_code_amplitude * sin(phase_accumulator) + m_code_offset; |
| whismanoid | 0:1c31998b91c6 | 283 | m_code = code; |
| whismanoid | 0:1c31998b91c6 | 284 | if (code > m_code_limit_H) { |
| whismanoid | 0:1c31998b91c6 | 285 | m_code = m_code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 286 | } |
| whismanoid | 0:1c31998b91c6 | 287 | if (code < m_code_limit_L) { |
| whismanoid | 0:1c31998b91c6 | 288 | m_code = m_code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 289 | } |
| whismanoid | 0:1c31998b91c6 | 290 | //~ m_code = m_code_offset - m_code_amplitude + m_table_index * 0.1 * m_code_amplitude; // DIAGNOSITC override sine with a ramp |
| whismanoid | 0:1c31998b91c6 | 291 | // |
| whismanoid | 0:1c31998b91c6 | 292 | // store code into table_data[m_table_index] |
| whismanoid | 0:1c31998b91c6 | 293 | m_table_data[m_table_index] = m_code; |
| whismanoid | 0:1c31998b91c6 | 294 | // |
| whismanoid | 0:1c31998b91c6 | 295 | } |
| whismanoid | 0:1c31998b91c6 | 296 | // |
| whismanoid | 0:1c31998b91c6 | 297 | m_table_index = 0; |
| whismanoid | 0:1c31998b91c6 | 298 | m_code = m_table_data[m_table_index]; |
| whismanoid | 0:1c31998b91c6 | 299 | //~ m_phase_accumulator = 0; |
| whismanoid | 0:1c31998b91c6 | 300 | //~ m_phase_increment = (2 * M_PI) / num_samples_per_tone_cycle; |
| whismanoid | 0:1c31998b91c6 | 301 | m_table_index_increment = 1; |
| whismanoid | 0:1c31998b91c6 | 302 | m_shape = Table; |
| whismanoid | 0:1c31998b91c6 | 303 | } |
| whismanoid | 0:1c31998b91c6 | 304 | #endif // USE_FunctionGenerator_Sine_Table |
| whismanoid | 0:1c31998b91c6 | 305 | public: |
| whismanoid | 0:1c31998b91c6 | 306 | uint32_t Code() const { return m_code; }; //!< get DAC output code value |
| whismanoid | 0:1c31998b91c6 | 307 | public: |
| whismanoid | 0:1c31998b91c6 | 308 | uint32_t Next() //!< determine next code value |
| whismanoid | 0:1c31998b91c6 | 309 | { |
| whismanoid | 0:1c31998b91c6 | 310 | switch(m_shape) |
| whismanoid | 0:1c31998b91c6 | 311 | { |
| whismanoid | 0:1c31998b91c6 | 312 | // Constant DC output |
| whismanoid | 0:1c31998b91c6 | 313 | case Constant: |
| whismanoid | 0:1c31998b91c6 | 314 | break; |
| whismanoid | 0:1c31998b91c6 | 315 | #if USE_FunctionGenerator_TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 316 | // Triangle Ramp: Ramp Up then Ramp Down |
| whismanoid | 0:1c31998b91c6 | 317 | case TriangleRampUpDown: |
| whismanoid | 0:1c31998b91c6 | 318 | if (m_code_increment >= 0) { |
| whismanoid | 0:1c31998b91c6 | 319 | // increment is positive or zero: rising ramp |
| whismanoid | 0:1c31998b91c6 | 320 | // avoid (code + increment) overflow maxint |
| whismanoid | 0:1c31998b91c6 | 321 | // avoid (code + increment) > code_limit_H |
| whismanoid | 0:1c31998b91c6 | 322 | if ((m_code + m_code_increment) < m_code) { // arithmetic overflow |
| whismanoid | 0:1c31998b91c6 | 323 | m_code_increment = -m_code_increment; // change the slope |
| whismanoid | 0:1c31998b91c6 | 324 | m_code = m_code + m_code_increment; // note: increment is negative |
| whismanoid | 0:1c31998b91c6 | 325 | } |
| whismanoid | 0:1c31998b91c6 | 326 | else if ((m_code + m_code_increment) > m_code_limit_H) { |
| whismanoid | 0:1c31998b91c6 | 327 | m_code_increment = -m_code_increment; // change the slope |
| whismanoid | 0:1c31998b91c6 | 328 | m_code = m_code + m_code_increment; // note: increment is negative |
| whismanoid | 0:1c31998b91c6 | 329 | } |
| whismanoid | 0:1c31998b91c6 | 330 | else { |
| whismanoid | 0:1c31998b91c6 | 331 | m_code = m_code + m_code_increment; // note: increment is positive |
| whismanoid | 0:1c31998b91c6 | 332 | } |
| whismanoid | 0:1c31998b91c6 | 333 | } |
| whismanoid | 0:1c31998b91c6 | 334 | else { |
| whismanoid | 0:1c31998b91c6 | 335 | // increment is negative: falling ramp |
| whismanoid | 0:1c31998b91c6 | 336 | // avoid (code + increment) underflow minint |
| whismanoid | 0:1c31998b91c6 | 337 | // avoid (code + increment) < code_limit_L which might be 0U |
| whismanoid | 0:1c31998b91c6 | 338 | if (m_code < (m_code + m_code_increment)) { // arithmetic underflow |
| whismanoid | 0:1c31998b91c6 | 339 | m_code_increment = -m_code_increment; // change the slope |
| whismanoid | 0:1c31998b91c6 | 340 | m_code = m_code + m_code_increment; // note: increment is positive |
| whismanoid | 0:1c31998b91c6 | 341 | } |
| whismanoid | 0:1c31998b91c6 | 342 | else if (m_code_limit_L > (m_code + m_code_increment)) { |
| whismanoid | 0:1c31998b91c6 | 343 | m_code_increment = -m_code_increment; // change the slope |
| whismanoid | 0:1c31998b91c6 | 344 | m_code = m_code + m_code_increment; // note: increment is positive |
| whismanoid | 0:1c31998b91c6 | 345 | } |
| whismanoid | 0:1c31998b91c6 | 346 | else { |
| whismanoid | 0:1c31998b91c6 | 347 | m_code = m_code + m_code_increment; // note: increment is negative |
| whismanoid | 0:1c31998b91c6 | 348 | } |
| whismanoid | 0:1c31998b91c6 | 349 | } |
| whismanoid | 0:1c31998b91c6 | 350 | break; // case TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 351 | #endif // TriangleRampUpDown |
| whismanoid | 0:1c31998b91c6 | 352 | #if USE_FunctionGenerator_RampUp |
| whismanoid | 0:1c31998b91c6 | 353 | // Ramp Up from m_code_limit_L to m_code_limit_H by m_code_increment |
| whismanoid | 0:1c31998b91c6 | 354 | case RampUp: |
| whismanoid | 0:1c31998b91c6 | 355 | // increment must be positive or zero: rising ramp |
| whismanoid | 0:1c31998b91c6 | 356 | if (m_code_increment < 0) { |
| whismanoid | 0:1c31998b91c6 | 357 | m_code_increment = -m_code_increment; // change the slope |
| whismanoid | 0:1c31998b91c6 | 358 | } |
| whismanoid | 0:1c31998b91c6 | 359 | // increment is positive or zero: rising ramp |
| whismanoid | 0:1c31998b91c6 | 360 | // avoid (code + increment) overflow maxint |
| whismanoid | 0:1c31998b91c6 | 361 | // avoid (code + increment) > code_limit_H |
| whismanoid | 0:1c31998b91c6 | 362 | if ((m_code + m_code_increment) < m_code) { // arithmetic overflow |
| whismanoid | 0:1c31998b91c6 | 363 | m_code = m_code + m_code_increment; // note: increment is negative |
| whismanoid | 0:1c31998b91c6 | 364 | } |
| whismanoid | 0:1c31998b91c6 | 365 | else if ((m_code + m_code_increment) > m_code_limit_H) { |
| whismanoid | 0:1c31998b91c6 | 366 | m_code = m_code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 367 | } |
| whismanoid | 0:1c31998b91c6 | 368 | else { |
| whismanoid | 0:1c31998b91c6 | 369 | m_code = m_code + m_code_increment; // note: increment is positive |
| whismanoid | 0:1c31998b91c6 | 370 | } |
| whismanoid | 0:1c31998b91c6 | 371 | break; // case RampUp |
| whismanoid | 0:1c31998b91c6 | 372 | #endif // USE_FunctionGenerator_RampUp |
| whismanoid | 0:1c31998b91c6 | 373 | #if USE_FunctionGenerator_RampDown |
| whismanoid | 0:1c31998b91c6 | 374 | // Ramp Down from m_code_limit_H to m_code_limit_L by m_code_increment |
| whismanoid | 0:1c31998b91c6 | 375 | case RampDown: |
| whismanoid | 0:1c31998b91c6 | 376 | // increment must be negative: falling ramp |
| whismanoid | 0:1c31998b91c6 | 377 | if (m_code_increment >= 0) { |
| whismanoid | 0:1c31998b91c6 | 378 | m_code_increment = -m_code_increment; // change the slope |
| whismanoid | 0:1c31998b91c6 | 379 | } |
| whismanoid | 0:1c31998b91c6 | 380 | // increment is negative: falling ramp |
| whismanoid | 0:1c31998b91c6 | 381 | // avoid (code + increment) underflow minint |
| whismanoid | 0:1c31998b91c6 | 382 | // avoid (code + increment) < code_limit_L which might be 0U |
| whismanoid | 0:1c31998b91c6 | 383 | if (m_code < (m_code + m_code_increment)) { // arithmetic underflow |
| whismanoid | 0:1c31998b91c6 | 384 | m_code = m_code + m_code_increment; // note: increment is positive |
| whismanoid | 0:1c31998b91c6 | 385 | } |
| whismanoid | 0:1c31998b91c6 | 386 | else if (m_code_limit_L > (m_code + m_code_increment)) { |
| whismanoid | 0:1c31998b91c6 | 387 | m_code = m_code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 388 | } |
| whismanoid | 0:1c31998b91c6 | 389 | else { |
| whismanoid | 0:1c31998b91c6 | 390 | m_code = m_code + m_code_increment; // note: increment is negative |
| whismanoid | 0:1c31998b91c6 | 391 | } |
| whismanoid | 0:1c31998b91c6 | 392 | break; // case RampDown |
| whismanoid | 0:1c31998b91c6 | 393 | #endif // RampDown |
| whismanoid | 0:1c31998b91c6 | 394 | #if USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 395 | // Computed Sinusoid (Sine wave) m_code_amplitude * sin(m_phase_accumulator) + m_code_offset; m_phase_increment determines frequency |
| whismanoid | 0:1c31998b91c6 | 396 | case Sine: |
| whismanoid | 0:1c31998b91c6 | 397 | { |
| whismanoid | 0:1c31998b91c6 | 398 | // |
| whismanoid | 0:1c31998b91c6 | 399 | // DIAGNOSTIC: scope trigger |
| whismanoid | 0:1c31998b91c6 | 400 | // ARDUINO |
| whismanoid | 0:1c31998b91c6 | 401 | //~ pinMode (8, OUTPUT); |
| whismanoid | 0:1c31998b91c6 | 402 | //~ digitalWrite(8, 0); // output logic low |
| whismanoid | 0:1c31998b91c6 | 403 | // ARDUINO |
| whismanoid | 0:1c31998b91c6 | 404 | // |
| whismanoid | 0:1c31998b91c6 | 405 | // DIAGNOSTIC: this line is likely compute heavy on soft float systems |
| whismanoid | 0:1c31998b91c6 | 406 | // ARDUINO UNO 16MHz: this line takes 132.0 to 154.0us, limiting sample update rate |
| whismanoid | 0:1c31998b91c6 | 407 | float code = m_code_amplitude * sin(m_phase_accumulator) + m_code_offset; |
| whismanoid | 0:1c31998b91c6 | 408 | // |
| whismanoid | 0:1c31998b91c6 | 409 | // DIAGNOSTIC: scope trigger |
| whismanoid | 0:1c31998b91c6 | 410 | // ARDUINO |
| whismanoid | 0:1c31998b91c6 | 411 | //~ pinMode (8, OUTPUT); |
| whismanoid | 0:1c31998b91c6 | 412 | //~ digitalWrite(8, 1); // output logic high -- initial value in constructor |
| whismanoid | 0:1c31998b91c6 | 413 | // ARDUINO |
| whismanoid | 0:1c31998b91c6 | 414 | // |
| whismanoid | 0:1c31998b91c6 | 415 | m_code = code; |
| whismanoid | 0:1c31998b91c6 | 416 | if (code > m_code_limit_H) { |
| whismanoid | 0:1c31998b91c6 | 417 | m_code = m_code_limit_H; |
| whismanoid | 0:1c31998b91c6 | 418 | } |
| whismanoid | 0:1c31998b91c6 | 419 | if (code < m_code_limit_L) { |
| whismanoid | 0:1c31998b91c6 | 420 | m_code = m_code_limit_L; |
| whismanoid | 0:1c31998b91c6 | 421 | } |
| whismanoid | 0:1c31998b91c6 | 422 | m_phase_accumulator = m_phase_accumulator + m_phase_increment; |
| whismanoid | 0:1c31998b91c6 | 423 | if (m_phase_accumulator > m_phase_accumulator_limit_H) { |
| whismanoid | 0:1c31998b91c6 | 424 | m_phase_accumulator = m_phase_accumulator - m_phase_accumulator_limit_H; |
| whismanoid | 0:1c31998b91c6 | 425 | } |
| whismanoid | 0:1c31998b91c6 | 426 | } |
| whismanoid | 0:1c31998b91c6 | 427 | break; // case Sine |
| whismanoid | 0:1c31998b91c6 | 428 | #endif // USE_FunctionGenerator_Sine |
| whismanoid | 0:1c31998b91c6 | 429 | #if (USE_FunctionGenerator_Table) || (USE_FunctionGenerator_Sine_Table) |
| whismanoid | 0:1c31998b91c6 | 430 | // Arbitrary Waveform Generation by table lookup; m_phase_increment determines frequency |
| whismanoid | 0:1c31998b91c6 | 431 | case Table: |
| whismanoid | 0:1c31998b91c6 | 432 | if (m_table_index >= m_table_length) { |
| whismanoid | 0:1c31998b91c6 | 433 | m_table_index = m_table_length; |
| whismanoid | 0:1c31998b91c6 | 434 | } |
| whismanoid | 0:1c31998b91c6 | 435 | m_code = m_table_data[m_table_index]; |
| whismanoid | 0:1c31998b91c6 | 436 | //~ m_phase_accumulator = m_phase_accumulator + m_phase_increment; |
| whismanoid | 0:1c31998b91c6 | 437 | //~ if (m_phase_accumulator > m_phase_accumulator_limit_H) { |
| whismanoid | 0:1c31998b91c6 | 438 | //~ m_phase_accumulator = m_phase_accumulator - m_phase_accumulator_limit_H; |
| whismanoid | 0:1c31998b91c6 | 439 | //~ } |
| whismanoid | 0:1c31998b91c6 | 440 | //~ m_table_index = m_table_length * m_phase_accumulator / m_phase_accumulator_limit_H; |
| whismanoid | 0:1c31998b91c6 | 441 | m_table_index = m_table_index + m_table_index_increment; |
| whismanoid | 0:1c31998b91c6 | 442 | // if (m_table_index < 0) { // m_table_index is unsigned so no underflow |
| whismanoid | 0:1c31998b91c6 | 443 | // m_table_index = 0; |
| whismanoid | 0:1c31998b91c6 | 444 | // } |
| whismanoid | 0:1c31998b91c6 | 445 | if (m_table_index >= m_table_length) { |
| whismanoid | 0:1c31998b91c6 | 446 | m_table_index = 0; // wrap to 0, assuming increment is 1 |
| whismanoid | 0:1c31998b91c6 | 447 | } |
| whismanoid | 0:1c31998b91c6 | 448 | break; // case Table |
| whismanoid | 0:1c31998b91c6 | 449 | #endif // USE_FunctionGenerator_Table |
| whismanoid | 0:1c31998b91c6 | 450 | } // switch(shape) |
| whismanoid | 0:1c31998b91c6 | 451 | return m_code; |
| whismanoid | 0:1c31998b91c6 | 452 | }; |
| whismanoid | 0:1c31998b91c6 | 453 | }; |
| whismanoid | 0:1c31998b91c6 | 454 | |
| whismanoid | 0:1c31998b91c6 | 455 | #endif // __FunctionGenerator_H__ |
| whismanoid | 0:1c31998b91c6 | 456 | |
| whismanoid | 0:1c31998b91c6 | 457 | // End of file |