Signal Generator

Dependencies:   IniManager RA8875 Watchdog mbed-rtos mbed

Fork of speaker_demo_Analog by jim hamblen

Committer:
WiredHome
Date:
Mon Jan 16 04:33:06 2017 +0000
Revision:
3:d22f3e52d06a
Parent:
2:8f71b71fce1b
Child:
4:10281ddb673d
Added button for Start/Stop/Pulse

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 2:8f71b71fce1b 1
WiredHome 2:8f71b71fce1b 2 #include "SignalGenDAC.h"
WiredHome 2:8f71b71fce1b 3
WiredHome 2:8f71b71fce1b 4 #define PI 3.14159
WiredHome 2:8f71b71fce1b 5
WiredHome 2:8f71b71fce1b 6 /// The linked list structure used to control the DMA transfer
WiredHome 2:8f71b71fce1b 7 ///
WiredHome 2:8f71b71fce1b 8 typedef struct {
WiredHome 2:8f71b71fce1b 9 uint32_t source; /// start of source area
WiredHome 2:8f71b71fce1b 10 uint32_t destination;/// start of destination area
WiredHome 2:8f71b71fce1b 11 uint32_t next; /// address of next strLLI in chain
WiredHome 2:8f71b71fce1b 12 uint32_t control; /// DMACCxControl register
WiredHome 2:8f71b71fce1b 13 } LinkListItem_t;
WiredHome 2:8f71b71fce1b 14
WiredHome 3:d22f3e52d06a 15 /// The DACsignal memory, which is DMA sent to the DAC to play the waveform,
WiredHome 3:d22f3e52d06a 16 /// produced by scaling the VoltSignal array
WiredHome 2:8f71b71fce1b 17 ///
WiredHome 3:d22f3e52d06a 18 float VoltSignal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0")));
WiredHome 3:d22f3e52d06a 19 signed long DACsignal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0")));
WiredHome 2:8f71b71fce1b 20
WiredHome 2:8f71b71fce1b 21 /// The linked list item record, used by the DMA engine to decide how to play
WiredHome 2:8f71b71fce1b 22 ///
WiredHome 2:8f71b71fce1b 23 LinkListItem_t llio __attribute__ ((section("AHBSRAM0")));
WiredHome 2:8f71b71fce1b 24
WiredHome 2:8f71b71fce1b 25
WiredHome 2:8f71b71fce1b 26 SignalGenDAC::SignalGenDAC(PinName _aout, float _minV, float _maxV) :
WiredHome 2:8f71b71fce1b 27 minV(_minV), maxV(_maxV) {
WiredHome 2:8f71b71fce1b 28 aout = new AnalogOut(_aout);
WiredHome 2:8f71b71fce1b 29 }
WiredHome 2:8f71b71fce1b 30
WiredHome 2:8f71b71fce1b 31 SignalGenDAC::~SignalGenDAC() {
WiredHome 2:8f71b71fce1b 32 }
WiredHome 2:8f71b71fce1b 33
WiredHome 2:8f71b71fce1b 34 void SignalGenDAC::Start(bool oneShot) {
WiredHome 3:d22f3e52d06a 35 printf("Start(%d)\r\n", oneShot ? 1 : 0);
WiredHome 3:d22f3e52d06a 36 LPC_GPDMACH0->DMACCLLI = (oneShot) ? 0 : (uint32_t) &llio;
WiredHome 3:d22f3e52d06a 37 isOn = (oneShot) ? false : true;
WiredHome 2:8f71b71fce1b 38 }
WiredHome 2:8f71b71fce1b 39
WiredHome 2:8f71b71fce1b 40 void SignalGenDAC::Stop(void) {
WiredHome 3:d22f3e52d06a 41 printf("Stop()\r\n");
WiredHome 3:d22f3e52d06a 42 LPC_GPDMACH0->DMACCLLI = 0;
WiredHome 3:d22f3e52d06a 43 isOn = false;
WiredHome 2:8f71b71fce1b 44 }
WiredHome 2:8f71b71fce1b 45
WiredHome 2:8f71b71fce1b 46
WiredHome 2:8f71b71fce1b 47 void SignalGenDAC::PrepareWaveform(SG_Mode mode, float frequency, float dutycycle, float voltage, float offset) {
WiredHome 2:8f71b71fce1b 48 int x, dcCount, firstQtr, lastQtr;
WiredHome 2:8f71b71fce1b 49 float upp = rangelimit(offset + voltage/2, minV, maxV);
WiredHome 2:8f71b71fce1b 50 float mid = rangelimit(offset, minV, maxV);
WiredHome 2:8f71b71fce1b 51 float low = rangelimit(offset - voltage/2, minV, maxV);
WiredHome 2:8f71b71fce1b 52 float v;
WiredHome 2:8f71b71fce1b 53 int numSamples = 32; // Ideally, compute this based on the frequency for good resolution
WiredHome 2:8f71b71fce1b 54 dcCount = dutycycle/100.0 * numSamples;
WiredHome 2:8f71b71fce1b 55 firstQtr = dcCount / 2;
WiredHome 2:8f71b71fce1b 56 lastQtr = dcCount + (numSamples - dcCount)/2;
WiredHome 2:8f71b71fce1b 57
WiredHome 2:8f71b71fce1b 58 // Set the timebased based on the frequency
WiredHome 2:8f71b71fce1b 59 if (isOn) {
WiredHome 2:8f71b71fce1b 60 // stop the signal during the change
WiredHome 2:8f71b71fce1b 61 isOn = false;
WiredHome 2:8f71b71fce1b 62 }
WiredHome 2:8f71b71fce1b 63 switch (mode) {
WiredHome 2:8f71b71fce1b 64 case SG_SINE:
WiredHome 2:8f71b71fce1b 65 for (x=0; x<numSamples; x++) {
WiredHome 2:8f71b71fce1b 66 if (x < dcCount) {
WiredHome 2:8f71b71fce1b 67 v = offset + voltage/2 * sin(x * 1 * PI / dcCount);
WiredHome 2:8f71b71fce1b 68 } else {
WiredHome 2:8f71b71fce1b 69 v = offset - voltage/2 * sin((x - dcCount) * 1 * PI / (numSamples-dcCount));
WiredHome 2:8f71b71fce1b 70 }
WiredHome 3:d22f3e52d06a 71 v = rangelimit(v, minV, maxV);
WiredHome 3:d22f3e52d06a 72 VoltSignal[x] = v;
WiredHome 2:8f71b71fce1b 73 }
WiredHome 2:8f71b71fce1b 74 break;
WiredHome 2:8f71b71fce1b 75 case SG_SQUARE:
WiredHome 2:8f71b71fce1b 76 for (x=0; x<numSamples; x++) {
WiredHome 2:8f71b71fce1b 77 if (x < dcCount) {
WiredHome 2:8f71b71fce1b 78 v = rangelimit(offset + voltage/2, minV, maxV);
WiredHome 2:8f71b71fce1b 79 } else {
WiredHome 2:8f71b71fce1b 80 v = rangelimit(offset - voltage/2, minV, maxV);
WiredHome 2:8f71b71fce1b 81 }
WiredHome 3:d22f3e52d06a 82 VoltSignal[x] = v;
WiredHome 2:8f71b71fce1b 83 }
WiredHome 2:8f71b71fce1b 84 break;
WiredHome 2:8f71b71fce1b 85 case SG_TRIANGLE:
WiredHome 2:8f71b71fce1b 86 for (x=0; x<numSamples; x++) {
WiredHome 2:8f71b71fce1b 87 if (x < firstQtr) {
WiredHome 3:d22f3e52d06a 88 v = voltage/2 * (float)x/(firstQtr);
WiredHome 3:d22f3e52d06a 89 v += offset;
WiredHome 2:8f71b71fce1b 90 } else if (x < dcCount) {
WiredHome 3:d22f3e52d06a 91 v = voltage/2 * (float)x/(firstQtr);
WiredHome 3:d22f3e52d06a 92 v = voltage - (v - offset);
WiredHome 2:8f71b71fce1b 93 } else if (x < lastQtr) {
WiredHome 3:d22f3e52d06a 94 v = voltage * (float)(x - dcCount)/(numSamples - dcCount);
WiredHome 3:d22f3e52d06a 95 v = offset - v;
WiredHome 2:8f71b71fce1b 96 } else {
WiredHome 3:d22f3e52d06a 97 v = voltage * (float)(x - dcCount)/(numSamples - dcCount);
WiredHome 3:d22f3e52d06a 98 v = v + offset - voltage;
WiredHome 2:8f71b71fce1b 99 }
WiredHome 3:d22f3e52d06a 100 VoltSignal[x] = v;
WiredHome 2:8f71b71fce1b 101 }
WiredHome 2:8f71b71fce1b 102 break;
WiredHome 2:8f71b71fce1b 103 case SG_SAWTOOTH:
WiredHome 2:8f71b71fce1b 104 for (x=0; x<numSamples; x++) {
WiredHome 2:8f71b71fce1b 105 if (x < dcCount) {
WiredHome 3:d22f3e52d06a 106 v = offset - voltage/2 + (float)x/dcCount * voltage/2;
WiredHome 2:8f71b71fce1b 107 } else {
WiredHome 3:d22f3e52d06a 108 v = offset + (float)(x - dcCount)/(numSamples - dcCount) * voltage/2;
WiredHome 2:8f71b71fce1b 109 }
WiredHome 3:d22f3e52d06a 110 v = rangelimit(v, minV, maxV);
WiredHome 3:d22f3e52d06a 111 VoltSignal[x] = v;
WiredHome 2:8f71b71fce1b 112 }
WiredHome 2:8f71b71fce1b 113 break;
WiredHome 2:8f71b71fce1b 114 case SG_USER:
WiredHome 2:8f71b71fce1b 115 break;
WiredHome 2:8f71b71fce1b 116 }
WiredHome 3:d22f3e52d06a 117 //printf("DAC Data %3.2f %3.2f\r\n", voltage, offset);
WiredHome 2:8f71b71fce1b 118 for (x=0; x<numSamples; x++) {
WiredHome 3:d22f3e52d06a 119 DACsignal[x] = ((uint16_t)(VoltSignal[x]/maxV * 1023) << 6) | (1 << 16);
WiredHome 3:d22f3e52d06a 120 //printf("%3d, %5.3f, %d\r\n", x, VoltSignal[x], DACsignal[x]);
WiredHome 2:8f71b71fce1b 121 }
WiredHome 3:d22f3e52d06a 122 llio.source = (uint32_t)&DACsignal;
WiredHome 3:d22f3e52d06a 123 llio.destination = (uint32_t)&LPC_DAC->DACR;
WiredHome 3:d22f3e52d06a 124 llio.next = (uint32_t)&llio;
WiredHome 3:d22f3e52d06a 125 llio.control = (1<<26) | (2<<21) | (2<<18) | numSamples;
WiredHome 3:d22f3e52d06a 126
WiredHome 3:d22f3e52d06a 127 LPC_SC->PCONP |= (1<<29);
WiredHome 3:d22f3e52d06a 128
WiredHome 3:d22f3e52d06a 129 /* Enable GPDMA and sync logic */
WiredHome 3:d22f3e52d06a 130 LPC_GPDMA->DMACConfig = 1;
WiredHome 3:d22f3e52d06a 131 LPC_GPDMA->DMACSync = (1<<6);
WiredHome 3:d22f3e52d06a 132
WiredHome 3:d22f3e52d06a 133 /* Load DMA Channel0 */
WiredHome 3:d22f3e52d06a 134 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t) &DACsignal[0];
WiredHome 3:d22f3e52d06a 135 LPC_GPDMACH0->DMACCDestAddr = (uint32_t) &LPC_DAC->DACR;
WiredHome 3:d22f3e52d06a 136
WiredHome 3:d22f3e52d06a 137 // Free Running
WiredHome 3:d22f3e52d06a 138 LPC_GPDMACH0->DMACCLLI = (uint32_t) &llio;
WiredHome 3:d22f3e52d06a 139 // One-Shot
WiredHome 3:d22f3e52d06a 140 // LPC_GPDMACH0->DMACCLLI = 0;
WiredHome 3:d22f3e52d06a 141
WiredHome 3:d22f3e52d06a 142 LPC_DAC->DACCNTVAL = numSamples // transfer size (0 - 11) = 64
WiredHome 3:d22f3e52d06a 143 | (0 << 12) // source burst size (12 - 14) = 1
WiredHome 3:d22f3e52d06a 144 | (0 << 15) // destination burst size (15 - 17) = 1
WiredHome 3:d22f3e52d06a 145 | (2 << 18) // source width (18 - 20) = 32 bit
WiredHome 3:d22f3e52d06a 146 | (2 << 21) // destination width (21 - 23) = 32 bit
WiredHome 3:d22f3e52d06a 147 | (0 << 24) // source AHB select (24) = AHB 0
WiredHome 3:d22f3e52d06a 148 | (0 << 25) // destination AHB select (25) = AHB 0
WiredHome 3:d22f3e52d06a 149 | (1 << 26) // source increment (26) = increment
WiredHome 3:d22f3e52d06a 150 | (0 << 27) // destination increment (27) = no increment
WiredHome 3:d22f3e52d06a 151 | (0 << 28) // mode select (28) = access in user mode
WiredHome 3:d22f3e52d06a 152 | (0 << 29) // (29) = access not bufferable
WiredHome 3:d22f3e52d06a 153 | (0 << 30) // (30) = access not cacheable
WiredHome 3:d22f3e52d06a 154 | (0 << 31); // terminal count interrupt disabled
WiredHome 3:d22f3e52d06a 155
WiredHome 3:d22f3e52d06a 156 LPC_GPDMA->DMACConfig = 1
WiredHome 3:d22f3e52d06a 157 | (0 << 1) // source peripheral (1 - 5) = none
WiredHome 3:d22f3e52d06a 158 | (7 << 6) // destination peripheral (6 - 10) = DAC
WiredHome 3:d22f3e52d06a 159 | (1 << 11) // flow control (11 - 13) = mem to per
WiredHome 3:d22f3e52d06a 160 | (0 << 14) // (14) = mask out error interrupt
WiredHome 3:d22f3e52d06a 161 | (0 << 15) // (15) = mask out terminal count interrupt
WiredHome 3:d22f3e52d06a 162 | (0 << 16) // (16) = no locked transfers
WiredHome 3:d22f3e52d06a 163 | (0 << 18); // (27) = no HALT
WiredHome 3:d22f3e52d06a 164
WiredHome 3:d22f3e52d06a 165 /* DACclk = 25 MHz, so 10 usec interval */
WiredHome 3:d22f3e52d06a 166 LPC_DAC->DACCNTVAL = 250; // 16-bit reload value
WiredHome 3:d22f3e52d06a 167 /* DMA, timer running, dbuff */
WiredHome 3:d22f3e52d06a 168 LPC_DAC->DACCTRL =
WiredHome 3:d22f3e52d06a 169 1<<3 // DMA_ENA dma burst is enabled
WiredHome 3:d22f3e52d06a 170 | 1<<2 // CNT_ENA Timeout couner is enabled
WiredHome 3:d22f3e52d06a 171 | 1<<1; // DBLBUF_ENA double-buffering enabled
WiredHome 2:8f71b71fce1b 172 }
WiredHome 2:8f71b71fce1b 173
WiredHome 2:8f71b71fce1b 174 float SignalGenDAC::rangelimit(float value, float min, float max) {
WiredHome 2:8f71b71fce1b 175 if (value < min)
WiredHome 2:8f71b71fce1b 176 return min;
WiredHome 2:8f71b71fce1b 177 else if (value > max)
WiredHome 2:8f71b71fce1b 178 return max;
WiredHome 2:8f71b71fce1b 179 else
WiredHome 2:8f71b71fce1b 180 return value;
WiredHome 2:8f71b71fce1b 181 }
WiredHome 2:8f71b71fce1b 182