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:
Fri May 31 14:45:27 2013 +0000
Revision:
2:edd6401d9aa0
Parent:
1:b97d61d415ff
Child:
3:67b9a01ad7b0
Fixed sine generator bug.; Added command line over USB uart

Who changed what in which revision?

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