Generate sine waves with 2 mbeds synchronised. Configurable amplitude and phase. Built for 50 Hz mains simulations.

Dependencies:   MODDMA mbed

Description

Small program based on the MODDMA buffered sine wave example.

This programs reads pin 22 to operate in Master (low) or Slave mode. Then configures pin 21 as output (master) or input (slave), in master mode led2 is on. Use a resistor (100 ohm) between the pin21's of master to slave.

The program then calculates a buffer of sine waves for the DMA with parameters given. And starts the DMA and DAC to generate the sine.

On the callbacks of the dma complete (there are 2) slave waits for a sync and master gives a sync, p21. Master waits a few extra clocks to make sure slave is ready.

Commands can be given over Serial port to modify the parameters on the run. Frequency can be changed for master and slave, but it is better to keep the same. Use "f xx.xx". Phase can be changed for master and slave Amplitude can be changed for master and slave.

Hookup

  • Wire p22 high or low.
  • Serial sr(p9,p10) from master to slave.
  • Wire trigger p21 to p21.
  • Output p18 (analogout)

Information

Do not forget a small RC filter on the DAC output.

Master Commands

<master/slave/frequency> <frequency/phase/amplitude> <space> <number> <line feed>

Example commands for serial:

  • master frequency 50.1 hz
    • mf 50.1\n
  • frequency 50.1 Hz
    • f 50.1\n
  • master phase 3.1415 (or 1.0)
    • mp 1\n
  • slave phase 1.5 pi
    • sp 1.5\n

Or use this GUI

https://dl.dropboxusercontent.com/s/uvwsroyu41vzkwg/2013-06-19%2010_35_52-WaveSim.png

Download, or Download C# Code (Visual Studio 2010)

Revision:
3:67b9a01ad7b0
Parent:
2:edd6401d9aa0
--- a/main.cpp	Fri May 31 14:45:27 2013 +0000
+++ b/main.cpp	Wed Jun 19 08:30:39 2013 +0000
@@ -1,480 +1,481 @@
-/*
- * Demonstrates sending a buffer repeatedly to the DAC using DMA.
- * Connect an oscilloscope to Mbed pin 18. This example doesn't
- * output anything else (nothing on any serial ports).
- */
-#include "mbed.h"
-#include "MODDMA.h"
-#include <cmath>
-#include "watchdog.h"
-#include "xifo.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-Serial pc(USBTX, USBRX);
-Serial sr(p9, p10);
-Watchdog wdt;
-
-const double PI   = 3.141592653589793238462;
-const float  PI_F = 3.14159265358979f;
- 
-// Make the buffer size match the number of degrees
-// in a circle since we are going to output a sinewave.
-#define BUFFER_SIZE 360
- 
-// Set DAC output power mode.
-#define DAC_POWER_MODE  (1 << 16)
- 
-DigitalOut led1(LED1);
-DigitalOut led2(LED2);
-DigitalOut led3(LED3);
-DigitalOut led4(LED4);
-DigitalIn    modesel(p22);      // mode selector
-DigitalInOut trigger(p21);  // sync trigger output
- 
-uint32_t buffer[3][BUFFER_SIZE];
- 
-AnalogOut signal(p18);
- 
-MODDMA dma;
-MODDMA_Config *conf0, *conf1, *conf2, *conf3;
- 
-// Config phase (2*pi is one period)
-double phase_master         = PI * 1;
-double phase_slave          = PI * 1;
-// Config amplitude, x * 3.3 Volt
-double amplitude_master =   1;
-double amplitude_slave  = 1;
-// Config frequency, (if using synchronisation these must be identical)
-double freq_master          = 50;
-double freq_slave               = freq_master;
-// copy calc buffer[2] to ch0/1
-volatile uint32_t toch0 = 0;
-volatile uint32_t toch1 = 0;
-// Mode typedef
-typedef enum {MASTER, SLAVE} modesel_t;
-modesel_t mode;
-// Ringbuffer for cmd
-xifo_t com;
-xifo_pool_t compool[128]; 
- 
-/* Dma callbacks */
-void TC0_callback(void);
-void ERR0_callback(void);
- 
-void TC1_callback(void);
-void ERR1_callback(void);
-
-// Sync function
-void wait_for_sync(){
-    switch(mode){
-        case MASTER:
-            // Wait a few clocks to make sure slave is waiting
-            for(uint32_t i=0; i<10; i++){ __NOP(); __NOP(); __NOP(); __NOP(); }
-            // Trigger toggle
-            LPC_GPIO2->FIOPIN ^= (1<<5);
-        break;
-        case SLAVE:
-            // Wait for pinchange
-            {
-            uint32_t pinstate = trigger;
-            while( pinstate == trigger);
-            }
-        break;
-    }
-}
- 
-// Calculate function
-void calculate_sines(){
-     // Create a sinewave buffer for testing.           
-        switch(mode){
-        case MASTER:
-            for (int i =   0; i <=  359; i++)
-            {
-                    double rads = (PI/180.0 * i);
-                    buffer[0][i] =  amplitude_master * (512*( sin( rads + phase_master )  ))+512;                
-            }
-        break;
-        case SLAVE:
-            for (int i =   0; i <=  359; i++)
-            { 
-                double rads = (PI/180.0 * i);
-                buffer[0][i] =  amplitude_slave * (512 * sin(rads + phase_slave)) + 512;                
-            }
-        break;
-        }
-        
-    // Adjust the sinewave buffer for use with DAC hardware.
-    for (int i = 0; i < 360; i++) {
-                if( buffer[0][i] > 1023 ) buffer[0][i] = 1023;
-        buffer[0][i] = DAC_POWER_MODE | ((buffer[0][i] << 6) & 0xFFC0); 
-        buffer[1][i] = buffer[0][i]; // Just create a copy of buffer0 to continue sinewave.
-    }
-}
- 
-void copycallback(){
-        if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
-}
- 
-// Main
-int main() {
-    volatile int life_counter = 0;
-        pc.baud(115200);
-        
-        if(modesel == 1){
-            pc.printf("slave\r\n");
-            trigger.input();
-            mode = SLAVE;
-            led2 = 0;
-        }else{
-          pc.printf("master\r\n");
-            trigger.output();
-            led2 = 1;
-            mode = MASTER;
-                    // Print command set
-        pc.printf("Command descriptions: <[master][slave]><[frequency][amplitude][phase]> <number>\r\n");
-        pc.printf("Commands: <[m][s]><[f][a][p]> <n>\r\n");
-        pc.printf("Min F = 1.02 Hz\r\n");
-        pc.printf("Max F limited to synchronisation and DAC speed (200 Hz with sync, max 1000 Hz without)\r\n");
-        }
-    
-    calculate_sines();
-    
-    // Prepare the GPDMA system for buffer0.
-    conf0 = new MODDMA_Config;
-    conf0
-     ->channelNum    ( MODDMA::Channel_0 )
-     ->srcMemAddr    ( (uint32_t) &buffer[0] )
-     ->dstMemAddr    ( MODDMA::DAC )
-     ->transferSize  ( 360 )
-     ->transferType  ( MODDMA::m2p )
-     ->dstConn       ( MODDMA::DAC )
-     ->attach_tc     ( &TC0_callback )
-     ->attach_err    ( &ERR0_callback )     
-    ; // config end
-    
-    // Prepare the GPDMA system for buffer1.
-    conf1 = new MODDMA_Config;
-    conf1
-     ->channelNum    ( MODDMA::Channel_1 )
-     ->srcMemAddr    ( (uint32_t) &buffer[1] )
-     ->dstMemAddr    ( MODDMA::DAC )
-     ->transferSize  ( 360 )
-     ->transferType  ( MODDMA::m2p )
-     ->dstConn       ( MODDMA::DAC )
-     ->attach_tc     ( &TC1_callback )
-     ->attach_err    ( &ERR1_callback )     
-    ; // config end
-
-                        
-    // Calculating the transfer frequency:
-    // By default, the Mbed library sets the PCLK_DAC clock value
-    // to 24MHz. One complete sinewave cycle in each buffer is 360
-    // points long. So, for a 1Hz wave we would need to transfer 360
-    // values per second. That would be 24000000/360 which is approx
-    // 66,666. But that's no good! The count val is only 16bits in size
-    // so bare this in mind. If you need to go slower you will need to
-    // alter PCLK_DAC from CCLK/4 to CCLK/8.
-    // For our demo we are going to have the sinewave run at 1kHz.
-    // That's 24000000/360000 which is approx 66. Experimentation
-    // however showed 65 to get closer to 1kHz (on my Mbed and scope 
-    // at least).
-        const double dacclk = 24000000;
-        const double dacper = dacclk / 360;
-        double ddacdiv;
-        switch(mode){
-        case MASTER:
-            ddacdiv = dacper / (freq_master);   
-        break;
-        case SLAVE:
-          ddacdiv = dacper / (freq_slave);
-        break;
-        }
-        unsigned int dacdiv = ddacdiv;
-    LPC_DAC->DACCNTVAL = dacdiv; // 6500 for 10Hz
-        
-        // Watchdogtimer to reset if sync failed
-        wdt.kick(10.0*(1.0/(dacper/ddacdiv))); 
- 
-    // Prepare first configuration.
-    if (!dma.Prepare( conf0 )) {
-        error("Doh!");
-    }
-    // Wait period for master (slaves waits for sync)
-        if(mode == MASTER){
-            wait(0.1);
-        }
-        wait_for_sync();
-        
-    // Begin (enable DMA and counter). Note, don't enable
-    // DBLBUF_ENA as we are using DMA double buffering.
-    LPC_DAC->DACCTRL |= (3UL << 2);
-    
-        // Disable copy calc buffer flags
-        toch0 = 0; 
-        toch1 = 0;
-        
-        // Create ringbuffer for parsing
-        xifo_init(&com, 128, (uint32_t *)&compool); 
-        xifo_clear(&com);
-        uint32_t do_calc=0;
-
-    while (1) {
-            // There's not a lot to do as DMA and interrupts are
-            // now handling the buffer transfers. So we'll just
-            // flash led1 to show the Mbed is alive and kicking.
-            if (life_counter++ > 1000000) {
-                    led1 = !led1; // Show some sort of life.
-                    life_counter = 0;
-            }
-            
-            /* Do UART data processing */
-            if(mode==MASTER){
-                while(pc.readable()){
-                    xifo_write(&com, pc.getc());
-                }
-                while(sr.readable()){
-                    pc.putc(sr.getc());
-                }
-            }else{
-                while(sr.readable()){
-                xifo_write(&com, sr.getc());
-                }
-            }
-                    
-            
-            
-            {   /* BLOCK with command parsing */
-                uint32_t do_parse=0;
-                // 123456.123456 accurate
-                char number[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
-                uint32_t p=0;               
-                // Only parse USB master commands on master mode
-                if(mode==MASTER){
-                    // MASTER mode
-                    if( xifo_read_mr(&com,0) == '\n'){
-                    xifo_pop_mr(&com);
-                        // We have a line
-                        if( xifo_read_lr(&com,0)== 's' ){                                   // Slave
-                            xifo_pop_lr(&com);
-                            pc.printf("Slave ");
-                            // command for slave, forward over serial sr
-                            while(xifo_get_used(&com))
-                            sr.putc(xifo_pop_lr(&com));
-                            sr.putc('\n');
-                            xifo_init(&com, 128, (uint32_t *)&compool); 
-                            xifo_clear(&com);
-                        } else if( xifo_read_lr(&com,0) == 'm' ){                               // Master
-                            xifo_pop_lr(&com);
-                            pc.printf("Master ");
-                            // master
-                            // Parsing
-                            do_parse =1;
-                        } else if( xifo_read_lr(&com,0) == 'f' ){                               // Frequency on MASTER and SLAVE
-                            // Parse data
-                            xifo_pop_lr(&com); // space
-                            // Get number
-                            while( xifo_get_used(&com) && p < sizeof(number))
-                                number[p++] = (char)xifo_pop_lr(&com);
-                            freq_master = strtod(number,0);
-                                int t = dacper / (freq_master);
-                                pc.printf("Master Frequency %f, approximate: %f\nSlave ", freq_master, dacper/t);
-                                sr.printf("f %f\n", freq_master);
-                                do_calc = 1;
-                        } else {
-                            pc.printf("fout ");
-                            while(xifo_get_used(&com))
-                                    pc.putc(xifo_pop_lr(&com));
-                            pc.putc('\n');
-                            xifo_init(&com, 128, (uint32_t *)&compool); 
-                            xifo_clear(&com);
-                        }}
-                }else{
-                    // SLAVE mode
-                    if( xifo_read_mr(&com,0) == '\n'){
-                        xifo_pop_mr(&com);
-                        do_parse = 1;
-                    }
-                }
-                if(do_parse){
-                    do_parse=0;
-                    
-                    // Parse data
-                    char filter = xifo_pop_lr(&com);
-                    xifo_pop_lr(&com) ; // space
-                    // Get number
-                    while( xifo_get_used(&com) && p < sizeof(number))
-                        number[p++] = (char)xifo_pop_lr(&com);
-                    
-                    if(mode==MASTER){   
-                        // frequency
-                        if( filter == 'f' ){
-                            freq_master = strtod(number,0);
-                            int t = dacper / (freq_master);
-                            pc.printf("Frequency %f, approximate: %f\n", freq_master, dacper/t);
-                            do_calc = 1;
-                        }else{
-                        // amplitude
-                        if( filter == 'a'){
-                            amplitude_master = strtod(number,0);
-                            pc.printf("Amplitude %f\n", amplitude_master);
-                            do_calc = 1;
-                        }else{
-                        // phase
-                        if( filter == 'p' ){
-                            phase_master = strtod(number,0) * PI;
-                            pc.printf("Phase %f\n", phase_master);
-                            do_calc = 1;                            
-                        } else{
-                        pc.printf("fout ");
-                        while(xifo_get_used(&com))
-                                pc.putc(xifo_pop_lr(&com));
-                        pc.putc('\n');
-                        xifo_init(&com, 128, (uint32_t *)&compool); 
-                        xifo_clear(&com);
-                        }}}
-                    }else{
-                        // frequency
-                        if( filter == 'f' ){
-                            freq_slave = strtod(number,0);
-                            int t = dacper / (freq_slave);
-                            sr.printf("Frequency %f, approximate: %f\n", freq_slave, dacper/t);
-                            do_calc = 1;
-                        }else{
-                        // amplitude
-                        if( filter == 'a'){
-                            amplitude_slave = strtod(number,0);
-                            sr.printf("Amplitude %f\n", amplitude_slave);
-                            do_calc = 1;
-                        }else{
-                        // phase
-                        if( filter == 'p' ){
-                            phase_slave = strtod(number,0) * PI;
-                            sr.printf("Phase %f\n", phase_slave);
-                            do_calc = 1;                            
-                        } else{
-                        sr.printf("fout ");
-                        while(xifo_get_used(&com))
-                                sr.putc(xifo_pop_lr(&com));
-                        sr.putc('\n');
-                        xifo_init(&com, 128, (uint32_t *)&compool); 
-                        xifo_clear(&com);
-                        }}}
-                    }
-                    }
-            } /* BLOCK with command parsing */
-
-            // recalculate
-            if(do_calc){
-                do_calc = 0;
-                // only continue if previous update is complete
-                if( !toch0 && !toch1 ){
-                    // calc frequency
-                        switch(mode){
-                        case MASTER:
-                            ddacdiv = dacper / (freq_master);
-                            //pc.printf("set dacdiv to %f\n",ddacdiv);
-                        break;
-                        case SLAVE:
-                            ddacdiv = dacper / (freq_slave);
-                        break;
-                        }
-                        unsigned int dacdiv = ddacdiv;
-                        LPC_DAC->DACCNTVAL = dacdiv; // 6500 for 10Hz
-                        wdt.kick(10.0*(1.0/(dacper/ddacdiv)));
-                    // calculate_sines sine
-                    switch(mode){
-                    case MASTER:
-                        for (int i =   0; i <=  359; i++) 
-                        {
-                            double rads = (PI/180.0 * i);
-                            buffer[2][i] =  amplitude_master * (512 * sin( rads + phase_master)) + 512;                     
-                        }
-                    break;
-                    case SLAVE:
-                        for (int i =   0; i <=  359; i++)
-                        {
-                            double rads = (PI/180.0 * i);
-                            buffer[2][i] =  amplitude_slave * (512 * sin( rads + phase_slave)) + 512;                
-                        }
-                    break;
-                    }
-                    // Adjust the sinewave buffer for use with DAC hardware.
-                    for (int i = 0; i < 360; i++) {
-                            if( buffer[2][i] > 1023 ) buffer[2][i] = 1023;
-                            buffer[2][i] = DAC_POWER_MODE | ((buffer[2][i] << 6) & 0xFFC0); 
-                    }
-                toch0 = 1; 
-                toch1 = 1;
-            }
-        }
-    }
-}
- 
-// Configuration callback on TC
-void TC0_callback(void) {
-
-    // Just show sending buffer0 complete.
-    led3 = !led3; 
-    
-    // Implement wait for trigger if slave mode
-        wait_for_sync();
-        wdt.kick();
-            
-    // Get configuration pointer.
-    MODDMA_Config *config = dma.getConfig();
-    
-    // Finish the DMA cycle by shutting down the channel.
-    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
-   
-    // Swap to buffer1
-    dma.Prepare( conf1 );
- 
-    // Clear DMA IRQ flags.
-    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
-
-        // Copy to channel 0?   
-        if ( toch0 ){
-            for (int i =   0; i <=  359; i++) buffer[0][i] =  buffer[2][i];
-            toch0=0;
-        }
-}
- 
-// Configuration callback on Error
-void ERR0_callback(void) {
-    error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
-}
- 
-// Configuration callback on TC
-void TC1_callback(void) {
-    // Just show sending buffer1 complete.
-    led4 = !led4; 
-   
-    // Implement wait for trigger if slave mode
-        wait_for_sync();
-        wdt.kick();
-     
-    // Get configuration pointer.
-    MODDMA_Config *config = dma.getConfig();
-
-        // Finish the DMA cycle by shutting down the channel.
-        dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
-        
-        // Swap to buffer0
-        dma.Prepare( conf0 );
-        
-        // Clear DMA IRQ flags.
-        if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
-      
-        // Copy to channel 1? 
-        if ( toch1 ){
-            for (int i =   0; i <=  359; i++) buffer[1][i] =  buffer[2][i];
-            toch1=0;
-        }
-}
- 
-// Configuration callback on Error
-void ERR1_callback(void) {
-    error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
-}
+/*
+ *  2 Channel DAC WaveSimulator with 2 lpc1768 mbed's. 
+ *  Command line or GUI controlled.
+ */
+
+#include "mbed.h"
+#include "MODDMA.h"
+#include <cmath>
+#include "watchdog.h"
+#include "xIFO.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+Serial pc(USBTX, USBRX);
+Serial sr(p9, p10);
+Watchdog wdt;
+
+const double PI   = 3.141592653589793238462;
+const float  PI_F = 3.14159265358979f;
+ 
+// Make the buffer size match the number of degrees
+// in a circle since we are going to output a sinewave.
+#define BUFFER_SIZE 360
+ 
+// Set DAC output power mode.
+#define DAC_POWER_MODE  (1 << 16)
+ 
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+DigitalIn     modesel(p22);   // mode selector
+DigitalInOut trigger(p21);    // sync trigger output
+ 
+uint32_t buffer[3][BUFFER_SIZE];
+ 
+AnalogOut signal(p18);      /* Do not forget output RC filter! */
+ 
+MODDMA dma;
+MODDMA_Config *conf0, *conf1, *conf2, *conf3;
+ 
+// Config phase (2*pi is one period)
+double phase_master         = PI * 1;
+double phase_slave             = PI * 1;
+// Config amplitude, x * 3.3 Volt
+double amplitude_master    =    0.75;
+double amplitude_slave    = 0.75;
+// Config frequency, (if using synchronisation these must be identical)
+double freq_master            = 50;
+double freq_slave                = freq_master;
+// copy calc buffer[2] to ch0/1
+volatile uint32_t toch0 = 0;
+volatile uint32_t toch1 = 0;
+// Mode typedef
+typedef enum {MASTER, SLAVE} modesel_t;
+modesel_t mode;
+// Ringbuffer for cmd
+xifo_t com;
+xifo_pool_t compool[128]; 
+ 
+/* Dma callbacks */
+void TC0_callback(void);
+void ERR0_callback(void);
+ 
+void TC1_callback(void);
+void ERR1_callback(void);
+
+// Sync function
+void wait_for_sync(){
+    switch(mode){
+        case MASTER:
+            // Wait a few clocks to make sure slave is waiting
+            for(uint32_t i=0; i<10; i++){ __NOP(); __NOP(); __NOP(); __NOP(); }
+            // Trigger toggle
+            LPC_GPIO2->FIOPIN ^= (1<<5);
+        break;
+        case SLAVE:
+            // Wait for pinchange
+            {
+            uint32_t pinstate = trigger;
+            while( pinstate == trigger);
+            }
+        break;
+    }
+}
+ 
+// Calculate function
+void calculate_sines(){
+     // Create a sinewave buffer for testing.            
+        switch(mode){
+        case MASTER:
+            for (int i =   0; i <=  359; i++)
+            {
+                    double rads = (PI/180.0 * i);
+                    buffer[0][i] =  amplitude_master * (512*( cos( rads + phase_master )  ))+512;                
+            }
+        break;
+        case SLAVE:
+            for (int i =   0; i <=  359; i++)
+            { 
+                double rads = (PI/180.0 * i);
+                buffer[0][i] =  amplitude_slave * (512 * cos(rads + phase_slave)) + 511;                
+            }
+        break;
+        }
+        
+    // Adjust the sinewave buffer for use with DAC hardware.
+    for (int i = 0; i < 360; i++) {
+                if( buffer[0][i] > 1023 ) buffer[0][i] = 1023;
+        buffer[0][i] = DAC_POWER_MODE | ((buffer[0][i] << 6) & 0xFFC0);    
+        buffer[1][i] = buffer[0][i]; // Just create a copy of buffer0 to continue sinewave.
+    }
+}
+ 
+void copycallback(){
+        if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
+}
+ 
+// Main
+int main() {
+    volatile int life_counter = 0;
+        pc.baud(115200);
+        
+        if(modesel == 1){
+            pc.printf("slave\r\n");
+            trigger.input();
+            mode = SLAVE;
+            led2 = 0;
+        }else{
+          pc.printf("master\r\n");
+            trigger.output();
+            led2 = 1;
+            mode = MASTER;
+                    // Print command set
+        pc.printf("Command descriptions: <[master][slave]><[frequency][amplitude][phase]> <number>\r\n");
+        pc.printf("Commands: <[m][s]><[f][a][p]> <n>\r\n");
+        pc.printf("Min F = 1.02 Hz\r\n");
+        pc.printf("Max F limited to synchronisation and DAC speed (200 Hz with sync, max 1000 Hz without)\r\n");
+        }
+    
+    calculate_sines();
+    
+    // Prepare the GPDMA system for buffer0.
+    conf0 = new MODDMA_Config;
+    conf0
+     ->channelNum    ( MODDMA::Channel_0 )
+     ->srcMemAddr    ( (uint32_t) &buffer[0] )
+     ->dstMemAddr    ( MODDMA::DAC )
+     ->transferSize  ( 360 )
+     ->transferType  ( MODDMA::m2p )
+     ->dstConn       ( MODDMA::DAC )
+     ->attach_tc     ( &TC0_callback )
+     ->attach_err    ( &ERR0_callback )     
+    ; // config end
+    
+    // Prepare the GPDMA system for buffer1.
+    conf1 = new MODDMA_Config;
+    conf1
+     ->channelNum    ( MODDMA::Channel_1 )
+     ->srcMemAddr    ( (uint32_t) &buffer[1] )
+     ->dstMemAddr    ( MODDMA::DAC )
+     ->transferSize  ( 360 )
+     ->transferType  ( MODDMA::m2p )
+     ->dstConn       ( MODDMA::DAC )
+     ->attach_tc     ( &TC1_callback )
+     ->attach_err    ( &ERR1_callback )     
+    ; // config end
+
+                        
+    // Calculating the transfer frequency:
+    // By default, the Mbed library sets the PCLK_DAC clock value
+    // to 24MHz. One complete sinewave cycle in each buffer is 360
+    // points long. So, for a 1Hz wave we would need to transfer 360
+    // values per second. That would be 24000000/360 which is approx
+    // 66,666. But that's no good! The count val is only 16bits in size
+    // so bare this in mind. If you need to go slower you will need to
+    // alter PCLK_DAC from CCLK/4 to CCLK/8.
+    // For our demo we are going to have the sinewave run at 1kHz.
+    // That's 24000000/360000 which is approx 66. Experimentation
+    // however showed 65 to get closer to 1kHz (on my Mbed and scope 
+    // at least).
+        const double dacclk = 24000000;
+        const double dacper = dacclk / 360;
+        double ddacdiv;
+        switch(mode){
+        case MASTER:
+            ddacdiv = dacper / (freq_master);    
+        break;
+        case SLAVE:
+          ddacdiv = dacper / (freq_slave);
+        break;
+        }
+        unsigned int dacdiv = ddacdiv;
+    LPC_DAC->DACCNTVAL = dacdiv; // 6500 for 10Hz
+        
+        // Watchdogtimer to reset if sync failed
+        wdt.kick(10.0*(1.0/(dacper/ddacdiv))); 
+ 
+    // Prepare first configuration.
+    if (!dma.Prepare( conf0 )) {
+        error("Doh!");
+    }
+    // Wait period for master (slaves waits for sync)
+        if(mode == MASTER){
+            wait(0.1);
+        }
+        wait_for_sync();
+        
+    // Begin (enable DMA and counter). Note, don't enable
+    // DBLBUF_ENA as we are using DMA double buffering.
+    LPC_DAC->DACCTRL |= (3UL << 2);
+    
+        // Disable copy calc buffer flags
+        toch0 = 0; 
+        toch1 = 0;
+        
+        // Create ringbuffer for parsing
+        xifo_init(&com, 128, (uint32_t *)&compool); 
+        xifo_clear(&com);
+        uint32_t do_calc=0;
+
+    while (1) {
+            // There's not a lot to do as DMA and interrupts are
+            // now handling the buffer transfers. So we'll just
+            // flash led1 to show the Mbed is alive and kicking.
+            if (life_counter++ > 1000000) {
+                    //led1 = !led1; // Show some sort of life.
+                    life_counter = 0;
+            }
+            
+            /* Do UART data processing */
+            if(mode==MASTER){
+                while(pc.readable()){
+                    xifo_write(&com, pc.getc());
+                }
+                while(sr.readable()){
+                    pc.putc(sr.getc());
+                }
+            }else{
+                while(sr.readable()){
+                xifo_write(&com, sr.getc());
+                }
+            }
+                      
+            
+            
+            {    /* BLOCK with command parsing */
+                uint32_t do_parse=0;
+                // 123456.123456 accurate
+                char number[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
+                uint32_t p=0;                
+                // Only parse USB master commands on master mode
+                if(mode==MASTER){
+                    // MASTER mode
+                    if( xifo_read_mr(&com,0) == '\n'){
+                    xifo_pop_mr(&com);
+                        // We have a line
+                        if( xifo_read_lr(&com,0)== 's' ){                                    // Slave
+                            xifo_pop_lr(&com);
+                            pc.printf("Slave ");
+                            // command for slave, forward over serial sr
+                            while(xifo_get_used(&com))
+                            sr.putc(xifo_pop_lr(&com));
+                            sr.putc('\n');
+                            xifo_init(&com, 128, (uint32_t *)&compool); 
+                            xifo_clear(&com);
+                        } else if( xifo_read_lr(&com,0) == 'm' ){                                // Master
+                            xifo_pop_lr(&com);
+                            pc.printf("Master ");
+                            // master
+                            // Parsing
+                            do_parse =1;
+                        } else if( xifo_read_lr(&com,0) == 'f' ){                                // Frequency on MASTER and SLAVE
+                            // Parse data
+                            xifo_pop_lr(&com); // space
+                            // Get number
+                            while( xifo_get_used(&com) && p < sizeof(number))
+                                number[p++] = (char)xifo_pop_lr(&com);
+                            freq_master = strtod(number,0);
+                                int t = dacper / (freq_master);
+                                pc.printf("Master Frequency %f, approximate: %f\nSlave ", freq_master, dacper/t);
+                                sr.printf("f %f\n", freq_master);
+                                do_calc = 1;
+                        } else {
+                            pc.printf("fout ");
+                            while(xifo_get_used(&com))
+                                    pc.putc(xifo_pop_lr(&com));
+                            pc.putc('\n');
+                            xifo_init(&com, 128, (uint32_t *)&compool); 
+                            xifo_clear(&com);
+                        }}
+                }else{
+                    // SLAVE mode
+                    if( xifo_read_mr(&com,0) == '\n'){
+                        xifo_pop_mr(&com);
+                        do_parse = 1;
+                    }
+                }
+                if(do_parse){
+                    do_parse=0;
+                    
+                    // Parse data
+                    char filter = xifo_pop_lr(&com);
+                    xifo_pop_lr(&com) ; // space
+                    // Get number
+                    while( xifo_get_used(&com) && p < sizeof(number))
+                        number[p++] = (char)xifo_pop_lr(&com);
+                    
+                    if(mode==MASTER){    
+                        // frequency
+                        if( filter == 'f' ){
+                            freq_master = strtod(number,0);
+                            int t = dacper / (freq_master);
+                            pc.printf("Frequency %f, approximate: %f\n", freq_master, dacper/t);
+                            do_calc = 1;
+                        }else{
+                        // amplitude
+                        if( filter == 'a'){
+                            amplitude_master = strtod(number,0);
+                            pc.printf("Amplitude %f\n", amplitude_master);
+                            do_calc = 1;
+                        }else{
+                        // phase
+                        if( filter == 'p' ){
+                            phase_master = strtod(number,0) * PI;
+                            pc.printf("Phase %f\n", phase_master);
+                            do_calc = 1;                            
+                        } else{
+                        pc.printf("fout ");
+                        while(xifo_get_used(&com))
+                                pc.putc(xifo_pop_lr(&com));
+                        pc.putc('\n');
+                        xifo_init(&com, 128, (uint32_t *)&compool); 
+                        xifo_clear(&com);
+                        }}}
+                    }else{
+                        // frequency
+                        if( filter == 'f' ){
+                            freq_slave = strtod(number,0);
+                            int t = dacper / (freq_slave);
+                            sr.printf("Frequency %f, approximate: %f\n", freq_slave, dacper/t);
+                            do_calc = 1;
+                        }else{
+                        // amplitude
+                        if( filter == 'a'){
+                            amplitude_slave = strtod(number,0);
+                            sr.printf("Amplitude %f\n", amplitude_slave);
+                            do_calc = 1;
+                        }else{
+                        // phase
+                        if( filter == 'p' ){
+                            phase_slave = strtod(number,0) * PI;
+                            sr.printf("Phase %f\n", phase_slave);
+                            do_calc = 1;                            
+                        } else{
+                        sr.printf("fout ");
+                        while(xifo_get_used(&com))
+                                sr.putc(xifo_pop_lr(&com));
+                        sr.putc('\n');
+                        xifo_init(&com, 128, (uint32_t *)&compool); 
+                        xifo_clear(&com);
+                        }}}
+                    }
+                    }
+            } /* BLOCK with command parsing */
+
+            // recalculate
+            if(do_calc){
+                do_calc = 0;
+                // only continue if previous update is complete
+                if( !toch0 && !toch1 ){
+                    // calc frequency
+                        switch(mode){
+                        case MASTER:
+                            ddacdiv = dacper / (freq_master);
+                            //pc.printf("set dacdiv to %f\n",ddacdiv);
+                        break;
+                        case SLAVE:
+                            ddacdiv = dacper / (freq_slave);
+                        break;
+                        }
+                        unsigned int dacdiv = ddacdiv;
+                        LPC_DAC->DACCNTVAL = dacdiv; // 6500 for 10Hz
+                        wdt.kick(10.0*(1.0/(dacper/ddacdiv)));
+                    // calculate_sines sine
+                    switch(mode){
+                    case MASTER:
+                        for (int i =   0; i <=  359; i++) 
+                        {
+                            double rads = (PI/180.0 * i);
+                            buffer[2][i] =  amplitude_master * (512 * cos( rads + phase_master)) + 512;                        
+                        }
+                    break;
+                    case SLAVE:
+                        for (int i =   0; i <=  359; i++)
+                        {
+                            double rads = (PI/180.0 * i);
+                            buffer[2][i] =  amplitude_slave * (512 * cos( rads + phase_slave)) + 512;                
+                        }
+                    break;
+                    }
+                    // Adjust the sinewave buffer for use with DAC hardware.
+                    for (int i = 0; i < 360; i++) {
+                            if( buffer[2][i] > 1023 ) buffer[2][i] = 1023;
+                            buffer[2][i] = DAC_POWER_MODE | ((buffer[2][i] << 6) & 0xFFC0);    
+                    }
+                toch0 = 1; 
+                toch1 = 1;
+            }
+        }
+    }
+}
+ 
+// Configuration callback on TC
+void TC0_callback(void) {
+
+    // Just show sending buffer0 complete.
+    led3 = !led3; 
+    
+    // Implement wait for trigger if slave mode
+        wait_for_sync();
+        wdt.kick();
+            
+    // Get configuration pointer.
+    MODDMA_Config *config = dma.getConfig();
+    
+    // Finish the DMA cycle by shutting down the channel.
+    dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
+   
+    // Swap to buffer1
+    dma.Prepare( conf1 );
+ 
+    // Clear DMA IRQ flags.
+    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq(); 
+
+        // Copy to channel 0?    
+        if ( toch0 ){
+            for (int i =   0; i <=  359; i++) buffer[0][i] =  buffer[2][i];
+            toch0=0;
+        }
+}
+ 
+// Configuration callback on Error
+void ERR0_callback(void) {
+    error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
+}
+ 
+// Configuration callback on TC
+void TC1_callback(void) {
+    // Just show sending buffer1 complete.
+    //led4 = !led4; 
+   
+    // Implement wait for trigger if slave mode
+        wait_for_sync();
+        wdt.kick();
+     
+    // Get configuration pointer.
+    MODDMA_Config *config = dma.getConfig();
+
+        // Finish the DMA cycle by shutting down the channel.
+        dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
+        
+        // Swap to buffer0
+        dma.Prepare( conf0 );
+        
+        // Clear DMA IRQ flags.
+        if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
+      
+        // Copy to channel 1? 
+        if ( toch1 ){
+            for (int i =   0; i <=  359; i++) buffer[1][i] =  buffer[2][i];
+            toch1=0;
+        }
+}
+ 
+// Configuration callback on Error
+void ERR1_callback(void) {
+    error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
+}
+