Signal Generator
Dependencies: IniManager RA8875 Watchdog mbed-rtos mbed
Fork of speaker_demo_Analog by
Diff: SignalGenDAC.cpp
- Revision:
- 3:d22f3e52d06a
- Parent:
- 2:8f71b71fce1b
- Child:
- 4:10281ddb673d
--- a/SignalGenDAC.cpp Sun Jan 15 03:11:22 2017 +0000 +++ b/SignalGenDAC.cpp Mon Jan 16 04:33:06 2017 +0000 @@ -12,9 +12,11 @@ uint32_t control; /// DMACCxControl register } LinkListItem_t; -/// The signal memory, which is DMA sent to the DAC to play the waveform +/// The DACsignal memory, which is DMA sent to the DAC to play the waveform, +/// produced by scaling the VoltSignal array /// -float /*signed long*/ signal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0"))); +float VoltSignal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0"))); +signed long DACsignal[SIGNAL_MEM_ENTRIES] __attribute__ ((section("AHBSRAM0"))); /// The linked list item record, used by the DMA engine to decide how to play /// @@ -30,9 +32,15 @@ } void SignalGenDAC::Start(bool oneShot) { + printf("Start(%d)\r\n", oneShot ? 1 : 0); + LPC_GPDMACH0->DMACCLLI = (oneShot) ? 0 : (uint32_t) &llio; + isOn = (oneShot) ? false : true; } void SignalGenDAC::Stop(void) { + printf("Stop()\r\n"); + LPC_GPDMACH0->DMACCLLI = 0; + isOn = false; } @@ -57,12 +65,11 @@ for (x=0; x<numSamples; x++) { if (x < dcCount) { v = offset + voltage/2 * sin(x * 1 * PI / dcCount); - v = rangelimit(v, minV, maxV); } else { v = offset - voltage/2 * sin((x - dcCount) * 1 * PI / (numSamples-dcCount)); - v = rangelimit(v, minV, maxV); } - signal[x] = v; + v = rangelimit(v, minV, maxV); + VoltSignal[x] = v; } break; case SG_SQUARE: @@ -72,39 +79,96 @@ } else { v = rangelimit(offset - voltage/2, minV, maxV); } - signal[x] = v; + VoltSignal[x] = v; } break; case SG_TRIANGLE: for (x=0; x<numSamples; x++) { if (x < firstQtr) { - v = (float)x/(firstQtr) * mid + mid; + v = voltage/2 * (float)x/(firstQtr); + v += offset; } else if (x < dcCount) { - v = upp - (float)(x-firstQtr)/(dcCount - firstQtr) * mid; + v = voltage/2 * (float)x/(firstQtr); + v = voltage - (v - offset); } else if (x < lastQtr) { - v = mid - (float)(x-dcCount)/(lastQtr - dcCount) * mid; + v = voltage * (float)(x - dcCount)/(numSamples - dcCount); + v = offset - v; } else { - v = (float)(x-lastQtr)/(numSamples - lastQtr) * mid; + v = voltage * (float)(x - dcCount)/(numSamples - dcCount); + v = v + offset - voltage; } - signal[x] = v; + VoltSignal[x] = v; } break; case SG_SAWTOOTH: for (x=0; x<numSamples; x++) { if (x < dcCount) { - v = (float)x/dcCount * (upp - low)/2 + low; + v = offset - voltage/2 + (float)x/dcCount * voltage/2; } else { - v = (float)(x - dcCount)/(numSamples - dcCount) * (upp - low)/2 + (upp - low)/2; + v = offset + (float)(x - dcCount)/(numSamples - dcCount) * voltage/2; } - signal[x] = v; + v = rangelimit(v, minV, maxV); + VoltSignal[x] = v; } break; case SG_USER: break; } + //printf("DAC Data %3.2f %3.2f\r\n", voltage, offset); for (x=0; x<numSamples; x++) { - printf("%3d, %5.3f\r\n", x, signal[x]); + DACsignal[x] = ((uint16_t)(VoltSignal[x]/maxV * 1023) << 6) | (1 << 16); + //printf("%3d, %5.3f, %d\r\n", x, VoltSignal[x], DACsignal[x]); } + llio.source = (uint32_t)&DACsignal; + llio.destination = (uint32_t)&LPC_DAC->DACR; + llio.next = (uint32_t)&llio; + llio.control = (1<<26) | (2<<21) | (2<<18) | numSamples; + + LPC_SC->PCONP |= (1<<29); + + /* Enable GPDMA and sync logic */ + LPC_GPDMA->DMACConfig = 1; + LPC_GPDMA->DMACSync = (1<<6); + + /* Load DMA Channel0 */ + LPC_GPDMACH0->DMACCSrcAddr = (uint32_t) &DACsignal[0]; + LPC_GPDMACH0->DMACCDestAddr = (uint32_t) &LPC_DAC->DACR; + + // Free Running + LPC_GPDMACH0->DMACCLLI = (uint32_t) &llio; + // One-Shot +// LPC_GPDMACH0->DMACCLLI = 0; + + LPC_DAC->DACCNTVAL = numSamples // transfer size (0 - 11) = 64 + | (0 << 12) // source burst size (12 - 14) = 1 + | (0 << 15) // destination burst size (15 - 17) = 1 + | (2 << 18) // source width (18 - 20) = 32 bit + | (2 << 21) // destination width (21 - 23) = 32 bit + | (0 << 24) // source AHB select (24) = AHB 0 + | (0 << 25) // destination AHB select (25) = AHB 0 + | (1 << 26) // source increment (26) = increment + | (0 << 27) // destination increment (27) = no increment + | (0 << 28) // mode select (28) = access in user mode + | (0 << 29) // (29) = access not bufferable + | (0 << 30) // (30) = access not cacheable + | (0 << 31); // terminal count interrupt disabled + + LPC_GPDMA->DMACConfig = 1 + | (0 << 1) // source peripheral (1 - 5) = none + | (7 << 6) // destination peripheral (6 - 10) = DAC + | (1 << 11) // flow control (11 - 13) = mem to per + | (0 << 14) // (14) = mask out error interrupt + | (0 << 15) // (15) = mask out terminal count interrupt + | (0 << 16) // (16) = no locked transfers + | (0 << 18); // (27) = no HALT + + /* DACclk = 25 MHz, so 10 usec interval */ + LPC_DAC->DACCNTVAL = 250; // 16-bit reload value + /* DMA, timer running, dbuff */ + LPC_DAC->DACCTRL = + 1<<3 // DMA_ENA dma burst is enabled + | 1<<2 // CNT_ENA Timeout couner is enabled + | 1<<1; // DBLBUF_ENA double-buffering enabled } float SignalGenDAC::rangelimit(float value, float min, float max) {