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
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 2:edd6401d9aa0 1
jeroen3 2:edd6401d9aa0 2 /**
jeroen3 2:edd6401d9aa0 3 * @file xifo.c
jeroen3 2:edd6401d9aa0 4 * @brief xifo circular buffer
jeroen3 2:edd6401d9aa0 5 * @details xifo supplies object oriented circular buffer with 32 bit size elements. \n
jeroen3 2:edd6401d9aa0 6 * To use either as FIFO (First In First Out) or as FILO (First In Last Out)
jeroen3 2:edd6401d9aa0 7 *
jeroen3 2:edd6401d9aa0 8 * @Author Jeroen Lodder
jeroen3 2:edd6401d9aa0 9 * @Date April 2013
jeroen3 2:edd6401d9aa0 10 * @version 2
jeroen3 2:edd6401d9aa0 11 *
jeroen3 2:edd6401d9aa0 12 * @{
jeroen3 2:edd6401d9aa0 13 */
jeroen3 2:edd6401d9aa0 14 #include "xifo.h"
jeroen3 2:edd6401d9aa0 15
jeroen3 2:edd6401d9aa0 16 /**
jeroen3 2:edd6401d9aa0 17 * @brief Initialise buffer object structure.
jeroen3 2:edd6401d9aa0 18 *
jeroen3 2:edd6401d9aa0 19 * @note Does not clear memory pool.
jeroen3 2:edd6401d9aa0 20 *
jeroen3 2:edd6401d9aa0 21 * @param[in] c Pointer to @p xifo_t object used for configuration.
jeroen3 2:edd6401d9aa0 22 * @param[in] s Number of elements buffer can hold (size).
jeroen3 2:edd6401d9aa0 23 * @param[in] sp Start of pre-allocated memory pool.
jeroen3 2:edd6401d9aa0 24 */
jeroen3 2:edd6401d9aa0 25 void xifo_init(xifo_t *c, uint32_t s, uint32_t *sp){
jeroen3 2:edd6401d9aa0 26 c->startpool = sp;
jeroen3 2:edd6401d9aa0 27 c->endpool = &sp[s-1];
jeroen3 2:edd6401d9aa0 28 c->size = s;
jeroen3 2:edd6401d9aa0 29 c->full = 0;
jeroen3 2:edd6401d9aa0 30 c->elementcount = 0;
jeroen3 2:edd6401d9aa0 31 c->read = sp;
jeroen3 2:edd6401d9aa0 32 c->write = sp;
jeroen3 2:edd6401d9aa0 33 }
jeroen3 2:edd6401d9aa0 34
jeroen3 2:edd6401d9aa0 35 /**
jeroen3 2:edd6401d9aa0 36 * @brief Clear buffer contents
jeroen3 2:edd6401d9aa0 37 *
jeroen3 2:edd6401d9aa0 38 * @note Must be used on initialised buffer object.
jeroen3 2:edd6401d9aa0 39 *
jeroen3 2:edd6401d9aa0 40 * @param[in] c Pointer to @p xifo_t object.
jeroen3 2:edd6401d9aa0 41 */
jeroen3 2:edd6401d9aa0 42 void xifo_clear(xifo_t *c){
jeroen3 2:edd6401d9aa0 43 c->ptemp = c->startpool;
jeroen3 2:edd6401d9aa0 44 while(c->ptemp <= c->endpool){
jeroen3 2:edd6401d9aa0 45 *c->ptemp++ = 0;
jeroen3 2:edd6401d9aa0 46 }
jeroen3 2:edd6401d9aa0 47 }
jeroen3 2:edd6401d9aa0 48
jeroen3 2:edd6401d9aa0 49 /**
jeroen3 2:edd6401d9aa0 50 * @brief Read from buffer (lr) Least Recent oriented (fifo)
jeroen3 2:edd6401d9aa0 51 *
jeroen3 2:edd6401d9aa0 52 * @note Buffer state will be preserved
jeroen3 2:edd6401d9aa0 53 *
jeroen3 2:edd6401d9aa0 54 * @warning Consider this opertaion as atomic!
jeroen3 2:edd6401d9aa0 55 *
jeroen3 2:edd6401d9aa0 56 * @details Read n elements from the oldest element to the most recent.
jeroen3 2:edd6401d9aa0 57 * As for index[0] the least recently added element is returned.
jeroen3 2:edd6401d9aa0 58 * And for index[elementcount] the most recent element is returned.
jeroen3 2:edd6401d9aa0 59 * This makes it possible to peek in fifo.
jeroen3 2:edd6401d9aa0 60 *
jeroen3 2:edd6401d9aa0 61 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 62 * @param[in] index Index relative from least recent
jeroen3 2:edd6401d9aa0 63 *
jeroen3 2:edd6401d9aa0 64 * @return Contents of element or 0 if failed (element can hold 0)
jeroen3 2:edd6401d9aa0 65 */
jeroen3 2:edd6401d9aa0 66 uint32_t xifo_read_lr(xifo_t *c, uint32_t index){
jeroen3 2:edd6401d9aa0 67 /* Verify there is valid data to read */
jeroen3 2:edd6401d9aa0 68 if(index+1 > c->elementcount){
jeroen3 2:edd6401d9aa0 69 return 0; /* Nothing to read there */
jeroen3 2:edd6401d9aa0 70 }
jeroen3 2:edd6401d9aa0 71 /* Calculate index of oldest element */
jeroen3 2:edd6401d9aa0 72 index = (c->elementcount-1) - index;
jeroen3 2:edd6401d9aa0 73 /* Set pointer */
jeroen3 2:edd6401d9aa0 74 c->ptemp = (c->read) - index;
jeroen3 2:edd6401d9aa0 75 if(c->ptemp < c->startpool){
jeroen3 2:edd6401d9aa0 76 /* We exceeded pool boundaries */
jeroen3 2:edd6401d9aa0 77 /* Calculate overshoot (startpool - indexptr) and subtract from end */
jeroen3 2:edd6401d9aa0 78 /* Since one element of overshoot results in end - 1 you would miss the last value */
jeroen3 2:edd6401d9aa0 79 c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
jeroen3 2:edd6401d9aa0 80 }
jeroen3 2:edd6401d9aa0 81 /* Read most recent */
jeroen3 2:edd6401d9aa0 82 return *c->ptemp;
jeroen3 2:edd6401d9aa0 83 }
jeroen3 2:edd6401d9aa0 84
jeroen3 2:edd6401d9aa0 85 /**
jeroen3 2:edd6401d9aa0 86 * @brief Read from buffer (mr) Most Recent oriented (filo)
jeroen3 2:edd6401d9aa0 87 *
jeroen3 2:edd6401d9aa0 88 * @note Buffer state will be preserved
jeroen3 2:edd6401d9aa0 89 *
jeroen3 2:edd6401d9aa0 90 * @warning Consider this opertaion as atomic!
jeroen3 2:edd6401d9aa0 91 *
jeroen3 2:edd6401d9aa0 92 * @details Read n elements back in time.
jeroen3 2:edd6401d9aa0 93 * As for index[0] the most recently added element is returned.
jeroen3 2:edd6401d9aa0 94 * And for index[elementcount] the oldest element is returned.
jeroen3 2:edd6401d9aa0 95 * This makes it possible to keep history. For DSP application.
jeroen3 2:edd6401d9aa0 96 *
jeroen3 2:edd6401d9aa0 97 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 98 * @param[in] index Index relative from most recent
jeroen3 2:edd6401d9aa0 99 *
jeroen3 2:edd6401d9aa0 100 * @return Contents of element or 0 if failed (element can hold 0)
jeroen3 2:edd6401d9aa0 101 */
jeroen3 2:edd6401d9aa0 102 uint32_t xifo_read_mr(xifo_t *c, uint32_t index){
jeroen3 2:edd6401d9aa0 103 /* Verify there is valid data to read */
jeroen3 2:edd6401d9aa0 104 if(index+1 > c->elementcount){
jeroen3 2:edd6401d9aa0 105 return 0; /* Nothing to read there */
jeroen3 2:edd6401d9aa0 106 }
jeroen3 2:edd6401d9aa0 107 /* Set pointer */
jeroen3 2:edd6401d9aa0 108 c->ptemp = (c->read) - index;
jeroen3 2:edd6401d9aa0 109 /* Validate pointer */
jeroen3 2:edd6401d9aa0 110 if(c->ptemp < c->startpool){
jeroen3 2:edd6401d9aa0 111 /* We exceeded pool boundaries */
jeroen3 2:edd6401d9aa0 112 /* Calculate overshoot (startpool - indexptr) and subtract from end */
jeroen3 2:edd6401d9aa0 113 /* Since one element of overshoot results in end - 1 you would miss the last value */
jeroen3 2:edd6401d9aa0 114 c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
jeroen3 2:edd6401d9aa0 115 }
jeroen3 2:edd6401d9aa0 116 /* Read most recent */
jeroen3 2:edd6401d9aa0 117 return *c->ptemp;
jeroen3 2:edd6401d9aa0 118 }
jeroen3 2:edd6401d9aa0 119
jeroen3 2:edd6401d9aa0 120 /**
jeroen3 2:edd6401d9aa0 121 * @brief Pop (mr) most recent from buffer (filo)
jeroen3 2:edd6401d9aa0 122 *
jeroen3 2:edd6401d9aa0 123 * @note Buffer state will be altered
jeroen3 2:edd6401d9aa0 124 *
jeroen3 2:edd6401d9aa0 125 * @warning Consider this opertaion as atomic!
jeroen3 2:edd6401d9aa0 126 *
jeroen3 2:edd6401d9aa0 127 * @details Read and remove the most recently added from the buffer.
jeroen3 2:edd6401d9aa0 128 * Using this results in a stack type of buffer.
jeroen3 2:edd6401d9aa0 129 *
jeroen3 2:edd6401d9aa0 130 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 131 *
jeroen3 2:edd6401d9aa0 132 * @return Contents of element or 0 if failed (element can hold 0)
jeroen3 2:edd6401d9aa0 133 */
jeroen3 2:edd6401d9aa0 134 uint32_t xifo_pop_mr(xifo_t *c){
jeroen3 2:edd6401d9aa0 135 /* Verify there is valid data read */
jeroen3 2:edd6401d9aa0 136 if(c->elementcount == 0){
jeroen3 2:edd6401d9aa0 137 return 0; /* Nothing to read there */
jeroen3 2:edd6401d9aa0 138 }
jeroen3 2:edd6401d9aa0 139 /* Read */
jeroen3 2:edd6401d9aa0 140 c->temp = *c->read;
jeroen3 2:edd6401d9aa0 141 /* Empty */
jeroen3 2:edd6401d9aa0 142 *c->read = 0;
jeroen3 2:edd6401d9aa0 143 /* Most recent element read, return write pointer */
jeroen3 2:edd6401d9aa0 144 c->write = c->read;
jeroen3 2:edd6401d9aa0 145 /* Decrement read pointer */
jeroen3 2:edd6401d9aa0 146 c->read--;
jeroen3 2:edd6401d9aa0 147 /* Validate pointer */
jeroen3 2:edd6401d9aa0 148 if( c->read < c->startpool ){
jeroen3 2:edd6401d9aa0 149 /* We exceeded pool boundaries */
jeroen3 2:edd6401d9aa0 150 c->read = c->endpool;
jeroen3 2:edd6401d9aa0 151 }
jeroen3 2:edd6401d9aa0 152 /* Reduce elementcount */
jeroen3 2:edd6401d9aa0 153 c->elementcount--;
jeroen3 2:edd6401d9aa0 154 if(c->elementcount < c->size)
jeroen3 2:edd6401d9aa0 155 c->full = 0;
jeroen3 2:edd6401d9aa0 156 return c->temp;
jeroen3 2:edd6401d9aa0 157 }
jeroen3 2:edd6401d9aa0 158
jeroen3 2:edd6401d9aa0 159 /**
jeroen3 2:edd6401d9aa0 160 * @brief Pop (lr) least recent from buffer (fifo)
jeroen3 2:edd6401d9aa0 161 *
jeroen3 2:edd6401d9aa0 162 * @note Buffer state will be altered
jeroen3 2:edd6401d9aa0 163 *
jeroen3 2:edd6401d9aa0 164 * @warning Consider this opertaion as atomic!
jeroen3 2:edd6401d9aa0 165 *
jeroen3 2:edd6401d9aa0 166 * @details Read and remove the least recently added from the buffer.
jeroen3 2:edd6401d9aa0 167 * Using this results in a fifo type of buffer.
jeroen3 2:edd6401d9aa0 168 *
jeroen3 2:edd6401d9aa0 169 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 170 *
jeroen3 2:edd6401d9aa0 171 * @return Contents of element or 0 if failed (element can hold 0)
jeroen3 2:edd6401d9aa0 172 */
jeroen3 2:edd6401d9aa0 173 uint32_t xifo_pop_lr(xifo_t *c){
jeroen3 2:edd6401d9aa0 174 /* Verify there is valid data read */
jeroen3 2:edd6401d9aa0 175 if(c->elementcount == 0){
jeroen3 2:edd6401d9aa0 176 return 0; /* Nothing to read there */
jeroen3 2:edd6401d9aa0 177 }
jeroen3 2:edd6401d9aa0 178 /* Derive least recent buffer element */
jeroen3 2:edd6401d9aa0 179 c->ptemp = c->read+1 - c->elementcount;
jeroen3 2:edd6401d9aa0 180 /* Validate pointer */
jeroen3 2:edd6401d9aa0 181 if(c->ptemp < c->startpool){
jeroen3 2:edd6401d9aa0 182 /* We exceeded pool boundaries */
jeroen3 2:edd6401d9aa0 183 /* Calculate overshoot (startpool - indexptr) and subtract from end */
jeroen3 2:edd6401d9aa0 184 /* Since one element of overshoot results in end - 1 you would miss the last value */
jeroen3 2:edd6401d9aa0 185 c->ptemp = (c->endpool+1) - (c->startpool - c->ptemp);
jeroen3 2:edd6401d9aa0 186 }
jeroen3 2:edd6401d9aa0 187 /* Read oldest buffer element */
jeroen3 2:edd6401d9aa0 188 { /* block with temporary variable to prevent stack use */
jeroen3 2:edd6401d9aa0 189 register uint32_t element;
jeroen3 2:edd6401d9aa0 190 /* Read to temp register */
jeroen3 2:edd6401d9aa0 191 element = *c->ptemp;
jeroen3 2:edd6401d9aa0 192 /* Empty */
jeroen3 2:edd6401d9aa0 193 *c->ptemp = 0;
jeroen3 2:edd6401d9aa0 194 /* Clear temp register */
jeroen3 2:edd6401d9aa0 195 c->temp = element;
jeroen3 2:edd6401d9aa0 196 }
jeroen3 2:edd6401d9aa0 197 /* Reduce elementcount */
jeroen3 2:edd6401d9aa0 198 c->elementcount--;
jeroen3 2:edd6401d9aa0 199 /* Check full flag */
jeroen3 2:edd6401d9aa0 200 if(c->elementcount < c->size)
jeroen3 2:edd6401d9aa0 201 c->full = 0;
jeroen3 2:edd6401d9aa0 202 return c->temp;
jeroen3 2:edd6401d9aa0 203 }
jeroen3 2:edd6401d9aa0 204
jeroen3 2:edd6401d9aa0 205 /**
jeroen3 2:edd6401d9aa0 206 * @brief Write to buffer
jeroen3 2:edd6401d9aa0 207 *
jeroen3 2:edd6401d9aa0 208 * @note Readpointer is automatically set to the last added element.
jeroen3 2:edd6401d9aa0 209 *
jeroen3 2:edd6401d9aa0 210 * @warning Consider this opertaion as atomic!
jeroen3 2:edd6401d9aa0 211 *
jeroen3 2:edd6401d9aa0 212 * @details Adds a value to the buffer.
jeroen3 2:edd6401d9aa0 213 * Automatically overwrites oldest elements when full.
jeroen3 2:edd6401d9aa0 214 *
jeroen3 2:edd6401d9aa0 215 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 216 * @param[in] data Data to add to buffer
jeroen3 2:edd6401d9aa0 217 *
jeroen3 2:edd6401d9aa0 218 * @return Number of free buffer elements
jeroen3 2:edd6401d9aa0 219 */
jeroen3 2:edd6401d9aa0 220 uint32_t xifo_write(xifo_t *c, uint32_t data){
jeroen3 2:edd6401d9aa0 221 /* Write data */
jeroen3 2:edd6401d9aa0 222 *c->write = data;
jeroen3 2:edd6401d9aa0 223 /* Update read pointer to most recent element */
jeroen3 2:edd6401d9aa0 224 c->read = c->write;
jeroen3 2:edd6401d9aa0 225 /* Write pointer increment */
jeroen3 2:edd6401d9aa0 226 c->write += 1;
jeroen3 2:edd6401d9aa0 227 /* Validate pointer */
jeroen3 2:edd6401d9aa0 228 if( c->write > c->endpool){
jeroen3 2:edd6401d9aa0 229 /* We exceeded pool boundaries */
jeroen3 2:edd6401d9aa0 230 c->write = c->startpool;
jeroen3 2:edd6401d9aa0 231 }
jeroen3 2:edd6401d9aa0 232 /* Update elementcount */
jeroen3 2:edd6401d9aa0 233 c->elementcount++;
jeroen3 2:edd6401d9aa0 234 /* Verify full */
jeroen3 2:edd6401d9aa0 235 if( c->elementcount >= c->size ){
jeroen3 2:edd6401d9aa0 236 c->full = 1;
jeroen3 2:edd6401d9aa0 237 c->elementcount = c->size;
jeroen3 2:edd6401d9aa0 238 }
jeroen3 2:edd6401d9aa0 239 /* return free elements count */
jeroen3 2:edd6401d9aa0 240 return c->size - c->elementcount;
jeroen3 2:edd6401d9aa0 241 }
jeroen3 2:edd6401d9aa0 242
jeroen3 2:edd6401d9aa0 243 /**
jeroen3 2:edd6401d9aa0 244 * @brief Get buffer size
jeroen3 2:edd6401d9aa0 245 *
jeroen3 2:edd6401d9aa0 246 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 247 *
jeroen3 2:edd6401d9aa0 248 * @return Size of memory pool in elements
jeroen3 2:edd6401d9aa0 249 */
jeroen3 2:edd6401d9aa0 250 uint32_t xifo_get_size(xifo_t *c){
jeroen3 2:edd6401d9aa0 251 return c->size;
jeroen3 2:edd6401d9aa0 252 }
jeroen3 2:edd6401d9aa0 253
jeroen3 2:edd6401d9aa0 254 /**
jeroen3 2:edd6401d9aa0 255 * @brief Get number of used elements
jeroen3 2:edd6401d9aa0 256 *
jeroen3 2:edd6401d9aa0 257 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 258 *
jeroen3 2:edd6401d9aa0 259 * @return Number of used buffer elements
jeroen3 2:edd6401d9aa0 260 */
jeroen3 2:edd6401d9aa0 261 uint32_t xifo_get_used(xifo_t *c){
jeroen3 2:edd6401d9aa0 262 return c->elementcount;
jeroen3 2:edd6401d9aa0 263 }
jeroen3 2:edd6401d9aa0 264
jeroen3 2:edd6401d9aa0 265 /**
jeroen3 2:edd6401d9aa0 266 * @brief Get number of free elements
jeroen3 2:edd6401d9aa0 267 *
jeroen3 2:edd6401d9aa0 268 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 269 *
jeroen3 2:edd6401d9aa0 270 * @return Number of free elements
jeroen3 2:edd6401d9aa0 271 */
jeroen3 2:edd6401d9aa0 272 uint32_t xifo_get_free(xifo_t *c){
jeroen3 2:edd6401d9aa0 273 return c->size - c->elementcount;
jeroen3 2:edd6401d9aa0 274 }
jeroen3 2:edd6401d9aa0 275
jeroen3 2:edd6401d9aa0 276 /**
jeroen3 2:edd6401d9aa0 277 * @brief Get full flag
jeroen3 2:edd6401d9aa0 278 *
jeroen3 2:edd6401d9aa0 279 * @param[in] c Pointer to @p xifo_t used for configuration.
jeroen3 2:edd6401d9aa0 280 *
jeroen3 2:edd6401d9aa0 281 * @return 1 if full
jeroen3 2:edd6401d9aa0 282 */
jeroen3 2:edd6401d9aa0 283 uint32_t xifo_get_full(xifo_t *c){
jeroen3 2:edd6401d9aa0 284 return c->full;
jeroen3 2:edd6401d9aa0 285 }
jeroen3 2:edd6401d9aa0 286
jeroen3 2:edd6401d9aa0 287 /** @} */