Generate sine waves with 2 mbeds synchronised. Configurable amplitude and phase. Built for 50 Hz mains simulations.
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
Download, or Download C# Code (Visual Studio 2010)
Diff: xIFO.c
- Revision:
- 2:edd6401d9aa0
- Child:
- 3:67b9a01ad7b0
diff -r b97d61d415ff -r edd6401d9aa0 xIFO.c --- /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; +} + +/** @} */