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:
2:edd6401d9aa0
Child:
3:67b9a01ad7b0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xIFO.c	Fri May 31 14:45:27 2013 +0000
@@ -0,0 +1,287 @@
+
+ /**
+ * @file    xifo.c
+ * @brief   xifo circular buffer
+ * @details xifo supplies object oriented circular buffer with 32 bit size elements. \n
+ *                     To use either as FIFO (First In First Out) or as FILO (First In Last Out)
+ *
+ * @Author    Jeroen Lodder
+ * @Date        April 2013
+ * @version 2
+ *
+ * @{
+ */
+#include "xifo.h"
+
+/**
+ * @brief   Initialise buffer object structure.
+ *
+ * @note    Does not clear memory pool.
+ *
+ * @param[in] c   Pointer to @p xifo_t object used for configuration.
+ * @param[in] s   Number of elements buffer can hold (size).
+ * @param[in] sp  Start of pre-allocated memory pool.
+ */
+void xifo_init(xifo_t *c, uint32_t s, uint32_t *sp){
+    c->startpool        = sp;
+    c->endpool          = &sp[s-1];
+    c->size             = s;
+    c->full             = 0;
+    c->elementcount     = 0;
+    c->read             = sp;
+    c->write            = sp;
+}
+
+/**
+ * @brief   Clear buffer contents
+ *
+ * @note    Must be used on initialised buffer object.
+ *
+ * @param[in] c   Pointer to @p xifo_t object.
+ */
+void xifo_clear(xifo_t *c){
+    c->ptemp = c->startpool;
+    while(c->ptemp <= c->endpool){
+        *c->ptemp++ = 0;        
+    }
+}
+
+/**
+ * @brief   Read from buffer (lr) Least Recent oriented (fifo)
+ *
+ * @note    Buffer state will be preserved
+ *
+ * @warning    Consider this opertaion as atomic!
+ *
+ * @details Read n elements from the oldest element to the most recent.
+ *                    As for index[0] the least recently added element is returned.
+ *                    And for index[elementcount] the most recent element is returned.
+ *                    This makes it possible to peek in fifo.
+ *
+ * @param[in] c           Pointer to @p xifo_t used for configuration.
+ * @param[in] index   Index relative from least recent
+ *
+ * @return    Contents of element or 0 if failed (element can hold 0)
+ */
+uint32_t xifo_read_lr(xifo_t *c, uint32_t index){
+    /* Verify there is valid data to read */
+    if(index+1 > c->elementcount){
+        return 0;    /* Nothing to read there */
+    }
+    /* Calculate index of oldest element */
+    index = (c->elementcount-1) - index;
+    /* Set pointer */
+    c->ptemp = (c->read) - index;
+    if(c->ptemp < c->startpool){
+        /* We exceeded pool boundaries */
+        /* Calculate overshoot (startpool - indexptr) and subtract from end */
+        /* Since one element of overshoot results in end - 1 you would miss the last value */
+        c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
+    }
+    /* Read most recent */
+    return *c->ptemp;
+}
+
+/**
+ * @brief   Read from buffer (mr) Most Recent oriented (filo)
+ *
+ * @note    Buffer state will be preserved
+ *
+ * @warning    Consider this opertaion as atomic!
+ *
+ * @details Read n elements back in time.
+ *                    As for index[0] the most recently added element is returned.
+ *                    And for index[elementcount] the oldest element is returned.
+ *                    This makes it possible to keep history. For DSP application.
+ *
+ * @param[in] c           Pointer to @p xifo_t used for configuration.
+ * @param[in] index   Index relative from most recent
+ *
+ * @return    Contents of element or 0 if failed (element can hold 0)
+ */
+uint32_t xifo_read_mr(xifo_t *c, uint32_t index){
+    /* Verify there is valid data to read */
+    if(index+1 > c->elementcount){
+        return 0;    /* Nothing to read there */
+    }
+    /* Set pointer */
+    c->ptemp = (c->read) - index;
+    /* Validate pointer */
+    if(c->ptemp < c->startpool){
+        /* We exceeded pool boundaries */
+        /* Calculate overshoot (startpool - indexptr) and subtract from end */
+        /* Since one element of overshoot results in end - 1 you would miss the last value */
+        c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
+    }
+    /* Read most recent */
+    return *c->ptemp;
+}
+
+/**
+ * @brief   Pop (mr) most recent from buffer (filo)
+ *
+ * @note    Buffer state will be altered
+ *
+ * @warning    Consider this opertaion as atomic!
+ *
+ * @details Read and remove the most recently added from the buffer.
+ *                     Using this results in a stack type of buffer.
+ *
+ * @param[in] c           Pointer to @p xifo_t used for configuration.
+ *
+ * @return    Contents of element or 0 if failed (element can hold 0)
+ */
+uint32_t xifo_pop_mr(xifo_t *c){
+    /* Verify there is valid data read */
+    if(c->elementcount == 0){
+        return 0;    /* Nothing to read there */
+    }
+    /* Read */
+    c->temp = *c->read;
+    /* Empty */
+    *c->read = 0;
+    /* Most recent element read, return write pointer */
+    c->write = c->read;
+    /* Decrement read pointer */
+    c->read--;
+    /* Validate pointer */
+    if( c->read < c->startpool ){
+        /* We exceeded pool boundaries */
+        c->read = c->endpool;
+    }
+    /* Reduce elementcount */
+    c->elementcount--;
+    if(c->elementcount < c->size)
+        c->full = 0;
+    return c->temp;
+}
+
+/**
+ * @brief   Pop (lr) least recent from buffer (fifo)
+ *
+ * @note    Buffer state will be altered
+ *
+ * @warning    Consider this opertaion as atomic!
+ *
+ * @details Read and remove the least recently added from the buffer.
+ *                     Using this results in a fifo type of buffer.
+ *
+ * @param[in] c    Pointer to @p xifo_t used for configuration.
+ *
+ * @return    Contents of element or 0 if failed (element can hold 0)
+ */
+uint32_t xifo_pop_lr(xifo_t *c){    
+    /* Verify there is valid data read */
+    if(c->elementcount == 0){
+        return 0;    /* Nothing to read there */
+    }
+    /* Derive least recent buffer element */
+    c->ptemp = c->read+1 - c->elementcount;
+    /* Validate pointer */
+    if(c->ptemp < c->startpool){
+        /* We exceeded pool boundaries */
+        /* Calculate overshoot (startpool - indexptr) and subtract from end */
+        /* Since one element of overshoot results in end - 1 you would miss the last value */
+        c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
+    }
+    /* Read oldest buffer element */
+    { /* block with temporary variable to prevent stack use */
+        register uint32_t element;
+        /* Read to temp register */
+        element = *c->ptemp;
+        /* Empty */
+        *c->ptemp = 0;
+        /* Clear temp register */
+        c->temp = element;
+    }
+    /* Reduce elementcount */
+    c->elementcount--;
+    /* Check full flag */
+    if(c->elementcount < c->size)
+        c->full = 0;
+    return c->temp;
+}
+
+/**
+ * @brief   Write to buffer
+ *
+ * @note    Readpointer is automatically set to the last added element.
+ *
+ * @warning    Consider this opertaion as atomic!
+ *                    
+ * @details Adds a value to the buffer.
+ *                    Automatically overwrites oldest elements when full.
+ *
+ * @param[in] c            Pointer to @p xifo_t used for configuration.
+ * @param[in] data    Data to add to buffer
+ *
+ * @return    Number of free buffer elements
+ */
+uint32_t xifo_write(xifo_t *c, uint32_t data){    
+    /* Write data */
+    *c->write = data;
+    /* Update read pointer to most recent element */
+    c->read = c->write;
+    /* Write pointer increment */
+    c->write += 1;
+    /* Validate pointer */
+    if( c->write > c->endpool){
+          /* We exceeded pool boundaries */
+            c->write = c->startpool;
+    }
+    /* Update elementcount */
+    c->elementcount++;
+    /* Verify full */
+    if( c->elementcount >= c->size ){
+        c->full = 1;
+        c->elementcount = c->size;
+    }
+    /* return free elements count */
+    return c->size - c->elementcount;
+}
+
+/**
+ * @brief   Get buffer size
+ *
+ * @param[in] c    Pointer to @p xifo_t used for configuration.
+ *
+ * @return    Size of memory pool in elements
+ */
+uint32_t xifo_get_size(xifo_t *c){
+    return c->size;
+}
+
+/**
+ * @brief   Get number of used elements
+ *
+ * @param[in] c    Pointer to @p xifo_t used for configuration.
+ *
+ * @return    Number of used buffer elements
+ */
+uint32_t xifo_get_used(xifo_t *c){
+    return c->elementcount;
+}
+
+/**
+* @brief   Get number of free elements
+*
+* @param[in] c    Pointer to @p xifo_t used for configuration.
+*
+* @return    Number of free elements
+*/
+uint32_t xifo_get_free(xifo_t *c){
+    return c->size - c->elementcount;
+}
+
+/**
+ * @brief   Get full flag
+ *
+ * @param[in] c    Pointer to @p xifo_t used for configuration.
+ *
+ * @return    1 if full
+ */
+uint32_t xifo_get_full(xifo_t *c){
+    return c->full;
+}
+
+/** @} */