Hello!,
I´m trying to develop a double circular buffer using DMA to get frames of an extabilished size from ADC converted data.
To reach this goal I wrote this code using a String to ceck how works this main file. I discovered that It works in the right way only one time, and once both buffers are full it stops to write them.
-Is there any way to force the initial address once the last buffer is full?
- How is possible to reduce ISR time?
#include "msp430x54xA.h"
#include "stdint.h"
#define Num_Samples 20
volatile uint8_t buffer0[Num_Samples];
volatile uint8_t buffer1[Num_Samples];
static char Switch=1; //index for Switch/double buffer
static char string1[] = { "Hello World this is an array written to test the duoble circular buffer" };
int volatile audioread;
void Port_init()
{ P10OUT &= ~BIT7; // P10.7 clear
P10DIR |= BIT7; // P10.7 output
P4DIR |= BIT1; // P4.1 output
P4SEL |= BIT1; // P4.1 select
P6SEL = P6SEL | 0x80; //P6.7 --> ADC function
P6DIR = P6DIR & 0x7F;
}
void TimerB_init()
{ //Setup Timer B0
/* Configure TimerB to produce the triggers for the ADC */
TBR = 0;
TBCTL = TBSSEL_1 | MC_1 | TBCLR; // Use ACLK, count up, reset counter and direction
TBCCR0 = 4096; // Init TBCCR0 w/ sample period
TBCCR1 = 4036; // Trigger for ADC12 Sample Conversion
TBCCTL1 = OUTMOD_7; // Reset OUT1 on EQU1, set on EQU0
}
void ADC_init()
{ // Setup ADC12
ADC12CTL0 &= ~ADC12ENC;
ADC12CTL0 = ADC12ON + //Turn on ADC12
ADC12SHT0_1+// 32 cycles per sample (Sampling time)
ADC12MSC + //multiple sample
ADC12REFON; //enable int ref
ADC12CTL1 = ADC12SHP + //pulse mode
ADC12CONSEQ_0 +//single channel single conversion
ADC12SSEL_3 + //clock source SMCLK
ADC12CSTARTADD_0;//select first (in order) register (7)
ADC12CTL2 = ADC12RES_0 + ADC12REFBURST; // 8bit res, 9 clock cycles to convert,Reference buffer on only during sample-and-conversion
ADC12CTL2 &= ~(ADC12DF); //ADC12DF=0 --> unsigned format
ADC12MCTL0 = ADC12SREF_7 +
ADC12EOS +
ADC12INCH_7; //End of Sequence --> Bit7 = 1; ADC12SREF = 0b111; ADC12INCH = 0b0111;
__delay_cycles(75); // 35us delay to allow Ref to settle
// based on default DCO frequency.
// See Datasheet for typical settle
// time.
ADC12CTL0 |= ADC12ENC; // Enable conversions
ADC12CTL0 |= ADC12SC; // Start conversion
audioread=ADC12MEM0;
// Setup DMA0 double buffer
DMACTL0 = DMA0TSEL_6; // ADC12IFGx triggered
// DMA0SA = (__SFR_FARPTR)(unsigned int)&ADC12MEM0;
DMA0SA =(__SFR_FARPTR)(unsigned int)&string1; // Source block address
//DMA0SZ = sizeof Num_Samples; // Block size
DMA0SZ = sizeof string1-1; // Block size
DMA0CTL = DMADT_4 +//Rpt single block
DMASRCINCR_3 +//Source address increment
DMADSTINCR_3 + //Destination address increment
//DMASRCBYTE +
DMALEVEL +
DMASBDB; //Transfer byte to byte
__bis_SR_register(LPM0_bits + GIE); // LPM0 w/ interrupts
__no_operation(); // used for debugging
}
void main(void)
{
WDTCTL = WDTPW+WDTHOLD; // Hold WDT
Port_init();
TimerB_init();
ADC_init(); //store audio on Ram
DMA0CTL |= DMAIE;//Interrupt enable
__bis_SR_register(LPM0_bits + GIE);
__no_operation(); // used for debugging
}
//------------------------------------------------------------------------------
// DMA Interrupt Service Routine \\2 CLOCK MCLK PER TRANSFER after synchronization and 1 of wait
//------------------------------------------------------------------------------
#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
//Depending on Index Change destination address of DMAs
if(Switch==1)
{
DMA0DA = (__SFR_FARPTR)(unsigned int)&buffer0[0];
DMA0CTL |= DMAEN; // Enable
DMA0CTL |= DMAREQ; // Trigger block transfer
//DMA1DA = (__SFR_FARPTR)(unsigned long)&dataBuff2.bufferA5[0];
}
else
{
DMA0DA = (__SFR_FARPTR)(unsigned int)&buffer1[0];
DMA0CTL |= DMAEN; // Enable
DMA0CTL |= DMAREQ; // Trigger block transfer
//DMA1DA = (__SFR_FARPTR)(unsigned long)&dataBuff1.bufferA5[0];
}
//Clear IFGs
__bic_SR_register_on_exit(LPM0_bits);
}
#pragma vector = DMA_VECTOR
__interrupt void DMA_ISR(void)
{
Switch^=1;
__bic_SR_register_on_exit(LPM0_bits);
}
Thank you!