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)

Committer:
jeroen3
Date:
Wed Jun 19 08:30:39 2013 +0000
Revision:
3:67b9a01ad7b0
Parent:
2:edd6401d9aa0
Updated;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jeroen3 3:67b9a01ad7b0 1 /*
jeroen3 3:67b9a01ad7b0 2 * 2 Channel DAC WaveSimulator with 2 lpc1768 mbed's.
jeroen3 3:67b9a01ad7b0 3 * Command line or GUI controlled.
jeroen3 3:67b9a01ad7b0 4 */
jeroen3 3:67b9a01ad7b0 5
jeroen3 3:67b9a01ad7b0 6 #include "mbed.h"
jeroen3 3:67b9a01ad7b0 7 #include "MODDMA.h"
jeroen3 3:67b9a01ad7b0 8 #include <cmath>
jeroen3 3:67b9a01ad7b0 9 #include "watchdog.h"
jeroen3 3:67b9a01ad7b0 10 #include "xIFO.h"
jeroen3 3:67b9a01ad7b0 11 #include <stdio.h>
jeroen3 3:67b9a01ad7b0 12 #include <stdlib.h>
jeroen3 3:67b9a01ad7b0 13 #include <ctype.h>
jeroen3 3:67b9a01ad7b0 14
jeroen3 3:67b9a01ad7b0 15 Serial pc(USBTX, USBRX);
jeroen3 3:67b9a01ad7b0 16 Serial sr(p9, p10);
jeroen3 3:67b9a01ad7b0 17 Watchdog wdt;
jeroen3 3:67b9a01ad7b0 18
jeroen3 3:67b9a01ad7b0 19 const double PI = 3.141592653589793238462;
jeroen3 3:67b9a01ad7b0 20 const float PI_F = 3.14159265358979f;
jeroen3 3:67b9a01ad7b0 21
jeroen3 3:67b9a01ad7b0 22 // Make the buffer size match the number of degrees
jeroen3 3:67b9a01ad7b0 23 // in a circle since we are going to output a sinewave.
jeroen3 3:67b9a01ad7b0 24 #define BUFFER_SIZE 360
jeroen3 3:67b9a01ad7b0 25
jeroen3 3:67b9a01ad7b0 26 // Set DAC output power mode.
jeroen3 3:67b9a01ad7b0 27 #define DAC_POWER_MODE (1 << 16)
jeroen3 3:67b9a01ad7b0 28
jeroen3 3:67b9a01ad7b0 29 DigitalOut led1(LED1);
jeroen3 3:67b9a01ad7b0 30 DigitalOut led2(LED2);
jeroen3 3:67b9a01ad7b0 31 DigitalOut led3(LED3);
jeroen3 3:67b9a01ad7b0 32 DigitalOut led4(LED4);
jeroen3 3:67b9a01ad7b0 33 DigitalIn modesel(p22); // mode selector
jeroen3 3:67b9a01ad7b0 34 DigitalInOut trigger(p21); // sync trigger output
jeroen3 3:67b9a01ad7b0 35
jeroen3 3:67b9a01ad7b0 36 uint32_t buffer[3][BUFFER_SIZE];
jeroen3 3:67b9a01ad7b0 37
jeroen3 3:67b9a01ad7b0 38 AnalogOut signal(p18); /* Do not forget output RC filter! */
jeroen3 3:67b9a01ad7b0 39
jeroen3 3:67b9a01ad7b0 40 MODDMA dma;
jeroen3 3:67b9a01ad7b0 41 MODDMA_Config *conf0, *conf1, *conf2, *conf3;
jeroen3 3:67b9a01ad7b0 42
jeroen3 3:67b9a01ad7b0 43 // Config phase (2*pi is one period)
jeroen3 3:67b9a01ad7b0 44 double phase_master = PI * 1;
jeroen3 3:67b9a01ad7b0 45 double phase_slave = PI * 1;
jeroen3 3:67b9a01ad7b0 46 // Config amplitude, x * 3.3 Volt
jeroen3 3:67b9a01ad7b0 47 double amplitude_master = 0.75;
jeroen3 3:67b9a01ad7b0 48 double amplitude_slave = 0.75;
jeroen3 3:67b9a01ad7b0 49 // Config frequency, (if using synchronisation these must be identical)
jeroen3 3:67b9a01ad7b0 50 double freq_master = 50;
jeroen3 3:67b9a01ad7b0 51 double freq_slave = freq_master;
jeroen3 3:67b9a01ad7b0 52 // copy calc buffer[2] to ch0/1
jeroen3 3:67b9a01ad7b0 53 volatile uint32_t toch0 = 0;
jeroen3 3:67b9a01ad7b0 54 volatile uint32_t toch1 = 0;
jeroen3 3:67b9a01ad7b0 55 // Mode typedef
jeroen3 3:67b9a01ad7b0 56 typedef enum {MASTER, SLAVE} modesel_t;
jeroen3 3:67b9a01ad7b0 57 modesel_t mode;
jeroen3 3:67b9a01ad7b0 58 // Ringbuffer for cmd
jeroen3 3:67b9a01ad7b0 59 xifo_t com;
jeroen3 3:67b9a01ad7b0 60 xifo_pool_t compool[128];
jeroen3 3:67b9a01ad7b0 61
jeroen3 3:67b9a01ad7b0 62 /* Dma callbacks */
jeroen3 3:67b9a01ad7b0 63 void TC0_callback(void);
jeroen3 3:67b9a01ad7b0 64 void ERR0_callback(void);
jeroen3 3:67b9a01ad7b0 65
jeroen3 3:67b9a01ad7b0 66 void TC1_callback(void);
jeroen3 3:67b9a01ad7b0 67 void ERR1_callback(void);
jeroen3 3:67b9a01ad7b0 68
jeroen3 3:67b9a01ad7b0 69 // Sync function
jeroen3 3:67b9a01ad7b0 70 void wait_for_sync(){
jeroen3 3:67b9a01ad7b0 71 switch(mode){
jeroen3 3:67b9a01ad7b0 72 case MASTER:
jeroen3 3:67b9a01ad7b0 73 // Wait a few clocks to make sure slave is waiting
jeroen3 3:67b9a01ad7b0 74 for(uint32_t i=0; i<10; i++){ __NOP(); __NOP(); __NOP(); __NOP(); }
jeroen3 3:67b9a01ad7b0 75 // Trigger toggle
jeroen3 3:67b9a01ad7b0 76 LPC_GPIO2->FIOPIN ^= (1<<5);
jeroen3 3:67b9a01ad7b0 77 break;
jeroen3 3:67b9a01ad7b0 78 case SLAVE:
jeroen3 3:67b9a01ad7b0 79 // Wait for pinchange
jeroen3 3:67b9a01ad7b0 80 {
jeroen3 3:67b9a01ad7b0 81 uint32_t pinstate = trigger;
jeroen3 3:67b9a01ad7b0 82 while( pinstate == trigger);
jeroen3 3:67b9a01ad7b0 83 }
jeroen3 3:67b9a01ad7b0 84 break;
jeroen3 3:67b9a01ad7b0 85 }
jeroen3 3:67b9a01ad7b0 86 }
jeroen3 3:67b9a01ad7b0 87
jeroen3 3:67b9a01ad7b0 88 // Calculate function
jeroen3 3:67b9a01ad7b0 89 void calculate_sines(){
jeroen3 3:67b9a01ad7b0 90 // Create a sinewave buffer for testing.
jeroen3 3:67b9a01ad7b0 91 switch(mode){
jeroen3 3:67b9a01ad7b0 92 case MASTER:
jeroen3 3:67b9a01ad7b0 93 for (int i = 0; i <= 359; i++)
jeroen3 3:67b9a01ad7b0 94 {
jeroen3 3:67b9a01ad7b0 95 double rads = (PI/180.0 * i);
jeroen3 3:67b9a01ad7b0 96 buffer[0][i] = amplitude_master * (512*( cos( rads + phase_master ) ))+512;
jeroen3 3:67b9a01ad7b0 97 }
jeroen3 3:67b9a01ad7b0 98 break;
jeroen3 3:67b9a01ad7b0 99 case SLAVE:
jeroen3 3:67b9a01ad7b0 100 for (int i = 0; i <= 359; i++)
jeroen3 3:67b9a01ad7b0 101 {
jeroen3 3:67b9a01ad7b0 102 double rads = (PI/180.0 * i);
jeroen3 3:67b9a01ad7b0 103 buffer[0][i] = amplitude_slave * (512 * cos(rads + phase_slave)) + 511;
jeroen3 3:67b9a01ad7b0 104 }
jeroen3 3:67b9a01ad7b0 105 break;
jeroen3 3:67b9a01ad7b0 106 }
jeroen3 3:67b9a01ad7b0 107
jeroen3 3:67b9a01ad7b0 108 // Adjust the sinewave buffer for use with DAC hardware.
jeroen3 3:67b9a01ad7b0 109 for (int i = 0; i < 360; i++) {
jeroen3 3:67b9a01ad7b0 110 if( buffer[0][i] > 1023 ) buffer[0][i] = 1023;
jeroen3 3:67b9a01ad7b0 111 buffer[0][i] = DAC_POWER_MODE | ((buffer[0][i] << 6) & 0xFFC0);
jeroen3 3:67b9a01ad7b0 112 buffer[1][i] = buffer[0][i]; // Just create a copy of buffer0 to continue sinewave.
jeroen3 3:67b9a01ad7b0 113 }
jeroen3 3:67b9a01ad7b0 114 }
jeroen3 3:67b9a01ad7b0 115
jeroen3 3:67b9a01ad7b0 116 void copycallback(){
jeroen3 3:67b9a01ad7b0 117 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
jeroen3 3:67b9a01ad7b0 118 }
jeroen3 3:67b9a01ad7b0 119
jeroen3 3:67b9a01ad7b0 120 // Main
jeroen3 3:67b9a01ad7b0 121 int main() {
jeroen3 3:67b9a01ad7b0 122 volatile int life_counter = 0;
jeroen3 3:67b9a01ad7b0 123 pc.baud(115200);
jeroen3 3:67b9a01ad7b0 124
jeroen3 3:67b9a01ad7b0 125 if(modesel == 1){
jeroen3 3:67b9a01ad7b0 126 pc.printf("slave\r\n");
jeroen3 3:67b9a01ad7b0 127 trigger.input();
jeroen3 3:67b9a01ad7b0 128 mode = SLAVE;
jeroen3 3:67b9a01ad7b0 129 led2 = 0;
jeroen3 3:67b9a01ad7b0 130 }else{
jeroen3 3:67b9a01ad7b0 131 pc.printf("master\r\n");
jeroen3 3:67b9a01ad7b0 132 trigger.output();
jeroen3 3:67b9a01ad7b0 133 led2 = 1;
jeroen3 3:67b9a01ad7b0 134 mode = MASTER;
jeroen3 3:67b9a01ad7b0 135 // Print command set
jeroen3 3:67b9a01ad7b0 136 pc.printf("Command descriptions: <[master][slave]><[frequency][amplitude][phase]> <number>\r\n");
jeroen3 3:67b9a01ad7b0 137 pc.printf("Commands: <[m][s]><[f][a][p]> <n>\r\n");
jeroen3 3:67b9a01ad7b0 138 pc.printf("Min F = 1.02 Hz\r\n");
jeroen3 3:67b9a01ad7b0 139 pc.printf("Max F limited to synchronisation and DAC speed (200 Hz with sync, max 1000 Hz without)\r\n");
jeroen3 3:67b9a01ad7b0 140 }
jeroen3 3:67b9a01ad7b0 141
jeroen3 3:67b9a01ad7b0 142 calculate_sines();
jeroen3 3:67b9a01ad7b0 143
jeroen3 3:67b9a01ad7b0 144 // Prepare the GPDMA system for buffer0.
jeroen3 3:67b9a01ad7b0 145 conf0 = new MODDMA_Config;
jeroen3 3:67b9a01ad7b0 146 conf0
jeroen3 3:67b9a01ad7b0 147 ->channelNum ( MODDMA::Channel_0 )
jeroen3 3:67b9a01ad7b0 148 ->srcMemAddr ( (uint32_t) &buffer[0] )
jeroen3 3:67b9a01ad7b0 149 ->dstMemAddr ( MODDMA::DAC )
jeroen3 3:67b9a01ad7b0 150 ->transferSize ( 360 )
jeroen3 3:67b9a01ad7b0 151 ->transferType ( MODDMA::m2p )
jeroen3 3:67b9a01ad7b0 152 ->dstConn ( MODDMA::DAC )
jeroen3 3:67b9a01ad7b0 153 ->attach_tc ( &TC0_callback )
jeroen3 3:67b9a01ad7b0 154 ->attach_err ( &ERR0_callback )
jeroen3 3:67b9a01ad7b0 155 ; // config end
jeroen3 3:67b9a01ad7b0 156
jeroen3 3:67b9a01ad7b0 157 // Prepare the GPDMA system for buffer1.
jeroen3 3:67b9a01ad7b0 158 conf1 = new MODDMA_Config;
jeroen3 3:67b9a01ad7b0 159 conf1
jeroen3 3:67b9a01ad7b0 160 ->channelNum ( MODDMA::Channel_1 )
jeroen3 3:67b9a01ad7b0 161 ->srcMemAddr ( (uint32_t) &buffer[1] )
jeroen3 3:67b9a01ad7b0 162 ->dstMemAddr ( MODDMA::DAC )
jeroen3 3:67b9a01ad7b0 163 ->transferSize ( 360 )
jeroen3 3:67b9a01ad7b0 164 ->transferType ( MODDMA::m2p )
jeroen3 3:67b9a01ad7b0 165 ->dstConn ( MODDMA::DAC )
jeroen3 3:67b9a01ad7b0 166 ->attach_tc ( &TC1_callback )
jeroen3 3:67b9a01ad7b0 167 ->attach_err ( &ERR1_callback )
jeroen3 3:67b9a01ad7b0 168 ; // config end
jeroen3 3:67b9a01ad7b0 169
jeroen3 3:67b9a01ad7b0 170
jeroen3 3:67b9a01ad7b0 171 // Calculating the transfer frequency:
jeroen3 3:67b9a01ad7b0 172 // By default, the Mbed library sets the PCLK_DAC clock value
jeroen3 3:67b9a01ad7b0 173 // to 24MHz. One complete sinewave cycle in each buffer is 360
jeroen3 3:67b9a01ad7b0 174 // points long. So, for a 1Hz wave we would need to transfer 360
jeroen3 3:67b9a01ad7b0 175 // values per second. That would be 24000000/360 which is approx
jeroen3 3:67b9a01ad7b0 176 // 66,666. But that's no good! The count val is only 16bits in size
jeroen3 3:67b9a01ad7b0 177 // so bare this in mind. If you need to go slower you will need to
jeroen3 3:67b9a01ad7b0 178 // alter PCLK_DAC from CCLK/4 to CCLK/8.
jeroen3 3:67b9a01ad7b0 179 // For our demo we are going to have the sinewave run at 1kHz.
jeroen3 3:67b9a01ad7b0 180 // That's 24000000/360000 which is approx 66. Experimentation
jeroen3 3:67b9a01ad7b0 181 // however showed 65 to get closer to 1kHz (on my Mbed and scope
jeroen3 3:67b9a01ad7b0 182 // at least).
jeroen3 3:67b9a01ad7b0 183 const double dacclk = 24000000;
jeroen3 3:67b9a01ad7b0 184 const double dacper = dacclk / 360;
jeroen3 3:67b9a01ad7b0 185 double ddacdiv;
jeroen3 3:67b9a01ad7b0 186 switch(mode){
jeroen3 3:67b9a01ad7b0 187 case MASTER:
jeroen3 3:67b9a01ad7b0 188 ddacdiv = dacper / (freq_master);
jeroen3 3:67b9a01ad7b0 189 break;
jeroen3 3:67b9a01ad7b0 190 case SLAVE:
jeroen3 3:67b9a01ad7b0 191 ddacdiv = dacper / (freq_slave);
jeroen3 3:67b9a01ad7b0 192 break;
jeroen3 3:67b9a01ad7b0 193 }
jeroen3 3:67b9a01ad7b0 194 unsigned int dacdiv = ddacdiv;
jeroen3 3:67b9a01ad7b0 195 LPC_DAC->DACCNTVAL = dacdiv; // 6500 for 10Hz
jeroen3 3:67b9a01ad7b0 196
jeroen3 3:67b9a01ad7b0 197 // Watchdogtimer to reset if sync failed
jeroen3 3:67b9a01ad7b0 198 wdt.kick(10.0*(1.0/(dacper/ddacdiv)));
jeroen3 3:67b9a01ad7b0 199
jeroen3 3:67b9a01ad7b0 200 // Prepare first configuration.
jeroen3 3:67b9a01ad7b0 201 if (!dma.Prepare( conf0 )) {
jeroen3 3:67b9a01ad7b0 202 error("Doh!");
jeroen3 3:67b9a01ad7b0 203 }
jeroen3 3:67b9a01ad7b0 204 // Wait period for master (slaves waits for sync)
jeroen3 3:67b9a01ad7b0 205 if(mode == MASTER){
jeroen3 3:67b9a01ad7b0 206 wait(0.1);
jeroen3 3:67b9a01ad7b0 207 }
jeroen3 3:67b9a01ad7b0 208 wait_for_sync();
jeroen3 3:67b9a01ad7b0 209
jeroen3 3:67b9a01ad7b0 210 // Begin (enable DMA and counter). Note, don't enable
jeroen3 3:67b9a01ad7b0 211 // DBLBUF_ENA as we are using DMA double buffering.
jeroen3 3:67b9a01ad7b0 212 LPC_DAC->DACCTRL |= (3UL << 2);
jeroen3 3:67b9a01ad7b0 213
jeroen3 3:67b9a01ad7b0 214 // Disable copy calc buffer flags
jeroen3 3:67b9a01ad7b0 215 toch0 = 0;
jeroen3 3:67b9a01ad7b0 216 toch1 = 0;
jeroen3 3:67b9a01ad7b0 217
jeroen3 3:67b9a01ad7b0 218 // Create ringbuffer for parsing
jeroen3 3:67b9a01ad7b0 219 xifo_init(&com, 128, (uint32_t *)&compool);
jeroen3 3:67b9a01ad7b0 220 xifo_clear(&com);
jeroen3 3:67b9a01ad7b0 221 uint32_t do_calc=0;
jeroen3 3:67b9a01ad7b0 222
jeroen3 3:67b9a01ad7b0 223 while (1) {
jeroen3 3:67b9a01ad7b0 224 // There's not a lot to do as DMA and interrupts are
jeroen3 3:67b9a01ad7b0 225 // now handling the buffer transfers. So we'll just
jeroen3 3:67b9a01ad7b0 226 // flash led1 to show the Mbed is alive and kicking.
jeroen3 3:67b9a01ad7b0 227 if (life_counter++ > 1000000) {
jeroen3 3:67b9a01ad7b0 228 //led1 = !led1; // Show some sort of life.
jeroen3 3:67b9a01ad7b0 229 life_counter = 0;
jeroen3 3:67b9a01ad7b0 230 }
jeroen3 3:67b9a01ad7b0 231
jeroen3 3:67b9a01ad7b0 232 /* Do UART data processing */
jeroen3 3:67b9a01ad7b0 233 if(mode==MASTER){
jeroen3 3:67b9a01ad7b0 234 while(pc.readable()){
jeroen3 3:67b9a01ad7b0 235 xifo_write(&com, pc.getc());
jeroen3 3:67b9a01ad7b0 236 }
jeroen3 3:67b9a01ad7b0 237 while(sr.readable()){
jeroen3 3:67b9a01ad7b0 238 pc.putc(sr.getc());
jeroen3 3:67b9a01ad7b0 239 }
jeroen3 3:67b9a01ad7b0 240 }else{
jeroen3 3:67b9a01ad7b0 241 while(sr.readable()){
jeroen3 3:67b9a01ad7b0 242 xifo_write(&com, sr.getc());
jeroen3 3:67b9a01ad7b0 243 }
jeroen3 3:67b9a01ad7b0 244 }
jeroen3 3:67b9a01ad7b0 245
jeroen3 3:67b9a01ad7b0 246
jeroen3 3:67b9a01ad7b0 247
jeroen3 3:67b9a01ad7b0 248 { /* BLOCK with command parsing */
jeroen3 3:67b9a01ad7b0 249 uint32_t do_parse=0;
jeroen3 3:67b9a01ad7b0 250 // 123456.123456 accurate
jeroen3 3:67b9a01ad7b0 251 char number[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
jeroen3 3:67b9a01ad7b0 252 uint32_t p=0;
jeroen3 3:67b9a01ad7b0 253 // Only parse USB master commands on master mode
jeroen3 3:67b9a01ad7b0 254 if(mode==MASTER){
jeroen3 3:67b9a01ad7b0 255 // MASTER mode
jeroen3 3:67b9a01ad7b0 256 if( xifo_read_mr(&com,0) == '\n'){
jeroen3 3:67b9a01ad7b0 257 xifo_pop_mr(&com);
jeroen3 3:67b9a01ad7b0 258 // We have a line
jeroen3 3:67b9a01ad7b0 259 if( xifo_read_lr(&com,0)== 's' ){ // Slave
jeroen3 3:67b9a01ad7b0 260 xifo_pop_lr(&com);
jeroen3 3:67b9a01ad7b0 261 pc.printf("Slave ");
jeroen3 3:67b9a01ad7b0 262 // command for slave, forward over serial sr
jeroen3 3:67b9a01ad7b0 263 while(xifo_get_used(&com))
jeroen3 3:67b9a01ad7b0 264 sr.putc(xifo_pop_lr(&com));
jeroen3 3:67b9a01ad7b0 265 sr.putc('\n');
jeroen3 3:67b9a01ad7b0 266 xifo_init(&com, 128, (uint32_t *)&compool);
jeroen3 3:67b9a01ad7b0 267 xifo_clear(&com);
jeroen3 3:67b9a01ad7b0 268 } else if( xifo_read_lr(&com,0) == 'm' ){ // Master
jeroen3 3:67b9a01ad7b0 269 xifo_pop_lr(&com);
jeroen3 3:67b9a01ad7b0 270 pc.printf("Master ");
jeroen3 3:67b9a01ad7b0 271 // master
jeroen3 3:67b9a01ad7b0 272 // Parsing
jeroen3 3:67b9a01ad7b0 273 do_parse =1;
jeroen3 3:67b9a01ad7b0 274 } else if( xifo_read_lr(&com,0) == 'f' ){ // Frequency on MASTER and SLAVE
jeroen3 3:67b9a01ad7b0 275 // Parse data
jeroen3 3:67b9a01ad7b0 276 xifo_pop_lr(&com); // space
jeroen3 3:67b9a01ad7b0 277 // Get number
jeroen3 3:67b9a01ad7b0 278 while( xifo_get_used(&com) && p < sizeof(number))
jeroen3 3:67b9a01ad7b0 279 number[p++] = (char)xifo_pop_lr(&com);
jeroen3 3:67b9a01ad7b0 280 freq_master = strtod(number,0);
jeroen3 3:67b9a01ad7b0 281 int t = dacper / (freq_master);
jeroen3 3:67b9a01ad7b0 282 pc.printf("Master Frequency %f, approximate: %f\nSlave ", freq_master, dacper/t);
jeroen3 3:67b9a01ad7b0 283 sr.printf("f %f\n", freq_master);
jeroen3 3:67b9a01ad7b0 284 do_calc = 1;
jeroen3 3:67b9a01ad7b0 285 } else {
jeroen3 3:67b9a01ad7b0 286 pc.printf("fout ");
jeroen3 3:67b9a01ad7b0 287 while(xifo_get_used(&com))
jeroen3 3:67b9a01ad7b0 288 pc.putc(xifo_pop_lr(&com));
jeroen3 3:67b9a01ad7b0 289 pc.putc('\n');
jeroen3 3:67b9a01ad7b0 290 xifo_init(&com, 128, (uint32_t *)&compool);
jeroen3 3:67b9a01ad7b0 291 xifo_clear(&com);
jeroen3 3:67b9a01ad7b0 292 }}
jeroen3 3:67b9a01ad7b0 293 }else{
jeroen3 3:67b9a01ad7b0 294 // SLAVE mode
jeroen3 3:67b9a01ad7b0 295 if( xifo_read_mr(&com,0) == '\n'){
jeroen3 3:67b9a01ad7b0 296 xifo_pop_mr(&com);
jeroen3 3:67b9a01ad7b0 297 do_parse = 1;
jeroen3 3:67b9a01ad7b0 298 }
jeroen3 3:67b9a01ad7b0 299 }
jeroen3 3:67b9a01ad7b0 300 if(do_parse){
jeroen3 3:67b9a01ad7b0 301 do_parse=0;
jeroen3 3:67b9a01ad7b0 302
jeroen3 3:67b9a01ad7b0 303 // Parse data
jeroen3 3:67b9a01ad7b0 304 char filter = xifo_pop_lr(&com);
jeroen3 3:67b9a01ad7b0 305 xifo_pop_lr(&com) ; // space
jeroen3 3:67b9a01ad7b0 306 // Get number
jeroen3 3:67b9a01ad7b0 307 while( xifo_get_used(&com) && p < sizeof(number))
jeroen3 3:67b9a01ad7b0 308 number[p++] = (char)xifo_pop_lr(&com);
jeroen3 3:67b9a01ad7b0 309
jeroen3 3:67b9a01ad7b0 310 if(mode==MASTER){
jeroen3 3:67b9a01ad7b0 311 // frequency
jeroen3 3:67b9a01ad7b0 312 if( filter == 'f' ){
jeroen3 3:67b9a01ad7b0 313 freq_master = strtod(number,0);
jeroen3 3:67b9a01ad7b0 314 int t = dacper / (freq_master);
jeroen3 3:67b9a01ad7b0 315 pc.printf("Frequency %f, approximate: %f\n", freq_master, dacper/t);
jeroen3 3:67b9a01ad7b0 316 do_calc = 1;
jeroen3 3:67b9a01ad7b0 317 }else{
jeroen3 3:67b9a01ad7b0 318 // amplitude
jeroen3 3:67b9a01ad7b0 319 if( filter == 'a'){
jeroen3 3:67b9a01ad7b0 320 amplitude_master = strtod(number,0);
jeroen3 3:67b9a01ad7b0 321 pc.printf("Amplitude %f\n", amplitude_master);
jeroen3 3:67b9a01ad7b0 322 do_calc = 1;
jeroen3 3:67b9a01ad7b0 323 }else{
jeroen3 3:67b9a01ad7b0 324 // phase
jeroen3 3:67b9a01ad7b0 325 if( filter == 'p' ){
jeroen3 3:67b9a01ad7b0 326 phase_master = strtod(number,0) * PI;
jeroen3 3:67b9a01ad7b0 327 pc.printf("Phase %f\n", phase_master);
jeroen3 3:67b9a01ad7b0 328 do_calc = 1;
jeroen3 3:67b9a01ad7b0 329 } else{
jeroen3 3:67b9a01ad7b0 330 pc.printf("fout ");
jeroen3 3:67b9a01ad7b0 331 while(xifo_get_used(&com))
jeroen3 3:67b9a01ad7b0 332 pc.putc(xifo_pop_lr(&com));
jeroen3 3:67b9a01ad7b0 333 pc.putc('\n');
jeroen3 3:67b9a01ad7b0 334 xifo_init(&com, 128, (uint32_t *)&compool);
jeroen3 3:67b9a01ad7b0 335 xifo_clear(&com);
jeroen3 3:67b9a01ad7b0 336 }}}
jeroen3 3:67b9a01ad7b0 337 }else{
jeroen3 3:67b9a01ad7b0 338 // frequency
jeroen3 3:67b9a01ad7b0 339 if( filter == 'f' ){
jeroen3 3:67b9a01ad7b0 340 freq_slave = strtod(number,0);
jeroen3 3:67b9a01ad7b0 341 int t = dacper / (freq_slave);
jeroen3 3:67b9a01ad7b0 342 sr.printf("Frequency %f, approximate: %f\n", freq_slave, dacper/t);
jeroen3 3:67b9a01ad7b0 343 do_calc = 1;
jeroen3 3:67b9a01ad7b0 344 }else{
jeroen3 3:67b9a01ad7b0 345 // amplitude
jeroen3 3:67b9a01ad7b0 346 if( filter == 'a'){
jeroen3 3:67b9a01ad7b0 347 amplitude_slave = strtod(number,0);
jeroen3 3:67b9a01ad7b0 348 sr.printf("Amplitude %f\n", amplitude_slave);
jeroen3 3:67b9a01ad7b0 349 do_calc = 1;
jeroen3 3:67b9a01ad7b0 350 }else{
jeroen3 3:67b9a01ad7b0 351 // phase
jeroen3 3:67b9a01ad7b0 352 if( filter == 'p' ){
jeroen3 3:67b9a01ad7b0 353 phase_slave = strtod(number,0) * PI;
jeroen3 3:67b9a01ad7b0 354 sr.printf("Phase %f\n", phase_slave);
jeroen3 3:67b9a01ad7b0 355 do_calc = 1;
jeroen3 3:67b9a01ad7b0 356 } else{
jeroen3 3:67b9a01ad7b0 357 sr.printf("fout ");
jeroen3 3:67b9a01ad7b0 358 while(xifo_get_used(&com))
jeroen3 3:67b9a01ad7b0 359 sr.putc(xifo_pop_lr(&com));
jeroen3 3:67b9a01ad7b0 360 sr.putc('\n');
jeroen3 3:67b9a01ad7b0 361 xifo_init(&com, 128, (uint32_t *)&compool);
jeroen3 3:67b9a01ad7b0 362 xifo_clear(&com);
jeroen3 3:67b9a01ad7b0 363 }}}
jeroen3 3:67b9a01ad7b0 364 }
jeroen3 3:67b9a01ad7b0 365 }
jeroen3 3:67b9a01ad7b0 366 } /* BLOCK with command parsing */
jeroen3 3:67b9a01ad7b0 367
jeroen3 3:67b9a01ad7b0 368 // recalculate
jeroen3 3:67b9a01ad7b0 369 if(do_calc){
jeroen3 3:67b9a01ad7b0 370 do_calc = 0;
jeroen3 3:67b9a01ad7b0 371 // only continue if previous update is complete
jeroen3 3:67b9a01ad7b0 372 if( !toch0 && !toch1 ){
jeroen3 3:67b9a01ad7b0 373 // calc frequency
jeroen3 3:67b9a01ad7b0 374 switch(mode){
jeroen3 3:67b9a01ad7b0 375 case MASTER:
jeroen3 3:67b9a01ad7b0 376 ddacdiv = dacper / (freq_master);
jeroen3 3:67b9a01ad7b0 377 //pc.printf("set dacdiv to %f\n",ddacdiv);
jeroen3 3:67b9a01ad7b0 378 break;
jeroen3 3:67b9a01ad7b0 379 case SLAVE:
jeroen3 3:67b9a01ad7b0 380 ddacdiv = dacper / (freq_slave);
jeroen3 3:67b9a01ad7b0 381 break;
jeroen3 3:67b9a01ad7b0 382 }
jeroen3 3:67b9a01ad7b0 383 unsigned int dacdiv = ddacdiv;
jeroen3 3:67b9a01ad7b0 384 LPC_DAC->DACCNTVAL = dacdiv; // 6500 for 10Hz
jeroen3 3:67b9a01ad7b0 385 wdt.kick(10.0*(1.0/(dacper/ddacdiv)));
jeroen3 3:67b9a01ad7b0 386 // calculate_sines sine
jeroen3 3:67b9a01ad7b0 387 switch(mode){
jeroen3 3:67b9a01ad7b0 388 case MASTER:
jeroen3 3:67b9a01ad7b0 389 for (int i = 0; i <= 359; i++)
jeroen3 3:67b9a01ad7b0 390 {
jeroen3 3:67b9a01ad7b0 391 double rads = (PI/180.0 * i);
jeroen3 3:67b9a01ad7b0 392 buffer[2][i] = amplitude_master * (512 * cos( rads + phase_master)) + 512;
jeroen3 3:67b9a01ad7b0 393 }
jeroen3 3:67b9a01ad7b0 394 break;
jeroen3 3:67b9a01ad7b0 395 case SLAVE:
jeroen3 3:67b9a01ad7b0 396 for (int i = 0; i <= 359; i++)
jeroen3 3:67b9a01ad7b0 397 {
jeroen3 3:67b9a01ad7b0 398 double rads = (PI/180.0 * i);
jeroen3 3:67b9a01ad7b0 399 buffer[2][i] = amplitude_slave * (512 * cos( rads + phase_slave)) + 512;
jeroen3 3:67b9a01ad7b0 400 }
jeroen3 3:67b9a01ad7b0 401 break;
jeroen3 3:67b9a01ad7b0 402 }
jeroen3 3:67b9a01ad7b0 403 // Adjust the sinewave buffer for use with DAC hardware.
jeroen3 3:67b9a01ad7b0 404 for (int i = 0; i < 360; i++) {
jeroen3 3:67b9a01ad7b0 405 if( buffer[2][i] > 1023 ) buffer[2][i] = 1023;
jeroen3 3:67b9a01ad7b0 406 buffer[2][i] = DAC_POWER_MODE | ((buffer[2][i] << 6) & 0xFFC0);
jeroen3 3:67b9a01ad7b0 407 }
jeroen3 3:67b9a01ad7b0 408 toch0 = 1;
jeroen3 3:67b9a01ad7b0 409 toch1 = 1;
jeroen3 3:67b9a01ad7b0 410 }
jeroen3 3:67b9a01ad7b0 411 }
jeroen3 3:67b9a01ad7b0 412 }
jeroen3 3:67b9a01ad7b0 413 }
jeroen3 3:67b9a01ad7b0 414
jeroen3 3:67b9a01ad7b0 415 // Configuration callback on TC
jeroen3 3:67b9a01ad7b0 416 void TC0_callback(void) {
jeroen3 3:67b9a01ad7b0 417
jeroen3 3:67b9a01ad7b0 418 // Just show sending buffer0 complete.
jeroen3 3:67b9a01ad7b0 419 led3 = !led3;
jeroen3 3:67b9a01ad7b0 420
jeroen3 3:67b9a01ad7b0 421 // Implement wait for trigger if slave mode
jeroen3 3:67b9a01ad7b0 422 wait_for_sync();
jeroen3 3:67b9a01ad7b0 423 wdt.kick();
jeroen3 3:67b9a01ad7b0 424
jeroen3 3:67b9a01ad7b0 425 // Get configuration pointer.
jeroen3 3:67b9a01ad7b0 426 MODDMA_Config *config = dma.getConfig();
jeroen3 3:67b9a01ad7b0 427
jeroen3 3:67b9a01ad7b0 428 // Finish the DMA cycle by shutting down the channel.
jeroen3 3:67b9a01ad7b0 429 dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
jeroen3 3:67b9a01ad7b0 430
jeroen3 3:67b9a01ad7b0 431 // Swap to buffer1
jeroen3 3:67b9a01ad7b0 432 dma.Prepare( conf1 );
jeroen3 3:67b9a01ad7b0 433
jeroen3 3:67b9a01ad7b0 434 // Clear DMA IRQ flags.
jeroen3 3:67b9a01ad7b0 435 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
jeroen3 3:67b9a01ad7b0 436
jeroen3 3:67b9a01ad7b0 437 // Copy to channel 0?
jeroen3 3:67b9a01ad7b0 438 if ( toch0 ){
jeroen3 3:67b9a01ad7b0 439 for (int i = 0; i <= 359; i++) buffer[0][i] = buffer[2][i];
jeroen3 3:67b9a01ad7b0 440 toch0=0;
jeroen3 3:67b9a01ad7b0 441 }
jeroen3 3:67b9a01ad7b0 442 }
jeroen3 3:67b9a01ad7b0 443
jeroen3 3:67b9a01ad7b0 444 // Configuration callback on Error
jeroen3 3:67b9a01ad7b0 445 void ERR0_callback(void) {
jeroen3 3:67b9a01ad7b0 446 error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
jeroen3 3:67b9a01ad7b0 447 }
jeroen3 3:67b9a01ad7b0 448
jeroen3 3:67b9a01ad7b0 449 // Configuration callback on TC
jeroen3 3:67b9a01ad7b0 450 void TC1_callback(void) {
jeroen3 3:67b9a01ad7b0 451 // Just show sending buffer1 complete.
jeroen3 3:67b9a01ad7b0 452 //led4 = !led4;
jeroen3 3:67b9a01ad7b0 453
jeroen3 3:67b9a01ad7b0 454 // Implement wait for trigger if slave mode
jeroen3 3:67b9a01ad7b0 455 wait_for_sync();
jeroen3 3:67b9a01ad7b0 456 wdt.kick();
jeroen3 3:67b9a01ad7b0 457
jeroen3 3:67b9a01ad7b0 458 // Get configuration pointer.
jeroen3 3:67b9a01ad7b0 459 MODDMA_Config *config = dma.getConfig();
jeroen3 3:67b9a01ad7b0 460
jeroen3 3:67b9a01ad7b0 461 // Finish the DMA cycle by shutting down the channel.
jeroen3 3:67b9a01ad7b0 462 dma.Disable( (MODDMA::CHANNELS)config->channelNum() );
jeroen3 3:67b9a01ad7b0 463
jeroen3 3:67b9a01ad7b0 464 // Swap to buffer0
jeroen3 3:67b9a01ad7b0 465 dma.Prepare( conf0 );
jeroen3 3:67b9a01ad7b0 466
jeroen3 3:67b9a01ad7b0 467 // Clear DMA IRQ flags.
jeroen3 3:67b9a01ad7b0 468 if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();
jeroen3 3:67b9a01ad7b0 469
jeroen3 3:67b9a01ad7b0 470 // Copy to channel 1?
jeroen3 3:67b9a01ad7b0 471 if ( toch1 ){
jeroen3 3:67b9a01ad7b0 472 for (int i = 0; i <= 359; i++) buffer[1][i] = buffer[2][i];
jeroen3 3:67b9a01ad7b0 473 toch1=0;
jeroen3 3:67b9a01ad7b0 474 }
jeroen3 3:67b9a01ad7b0 475 }
jeroen3 3:67b9a01ad7b0 476
jeroen3 3:67b9a01ad7b0 477 // Configuration callback on Error
jeroen3 3:67b9a01ad7b0 478 void ERR1_callback(void) {
jeroen3 3:67b9a01ad7b0 479 error("Oh no! My Mbed EXPLODED! :( Only kidding, go find the problem");
jeroen3 3:67b9a01ad7b0 480 }
jeroen3 3:67b9a01ad7b0 481