Mark Underwood / FunctionGenerator

Dependents:   MAX5719BOB_FunctionGen

Committer:
whismanoid
Date:
Sun Jan 03 06:15:34 2021 +0000
Revision:
0:1c31998b91c6
Initial commit class DACFunctionGenerator

Who changed what in which revision?

UserRevisionLine numberNew 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