kopia lustrzana https://github.com/F5OEO/rpitx
Working on dmabuffer
rodzic
c6b3905fd3
commit
11af187182
83
src/dma.cpp
83
src/dma.cpp
|
@ -13,6 +13,8 @@ extern "C"
|
|||
|
||||
dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize) // Fixme! Need to check to be 256 Aligned for UserMem
|
||||
{
|
||||
fprintf(stderr,"Channel %d CBSize %d UsermemSize %d\n",Channel,CBSize,UserMemSize);
|
||||
|
||||
channel=Channel;
|
||||
mbox.handle = mbox_open();
|
||||
if (mbox.handle < 0)
|
||||
|
@ -127,3 +129,84 @@ uint32_t dma::getcbposition()
|
|||
// dma_reg.gpioreg[DMA_CONBLK_AD+channel*0x40]-mem_virt_to_phys((void *)cbarray );
|
||||
}
|
||||
|
||||
bool dma::isrunning()
|
||||
{
|
||||
return ((dma_reg.gpioreg[DMA_CS+channel*0x40]&DMA_CS_ACTIVE)>0);
|
||||
}
|
||||
|
||||
//**************************************** BUFFER DMA ********************************************************
|
||||
bufferdma::bufferdma(int Channel,uint32_t tbuffersize,uint32_t tcbbysample,uint32_t tregisterbysample):dma(Channel,tbuffersize*tcbbysample,tbuffersize*tregisterbysample)
|
||||
{
|
||||
buffersize=tbuffersize;
|
||||
cbbysample=tcbbysample;
|
||||
registerbysample=tregisterbysample;
|
||||
fprintf(stderr,"BufferSize %d , cb %d user %d\n",tbuffersize,tbuffersize*cbbysample,tbuffersize*registerbysample);
|
||||
|
||||
|
||||
|
||||
current_sample=0;
|
||||
last_sample=0;
|
||||
sample_available=buffersize;
|
||||
|
||||
sampletab=usermem;
|
||||
}
|
||||
|
||||
void bufferdma::SetDmaAlgo()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t bufferdma::GetBufferAvailable()
|
||||
{
|
||||
int diffsample=0;
|
||||
if(isrunning())
|
||||
{
|
||||
current_sample=getcbposition()/cbbysample;
|
||||
int diffsample=current_sample-last_sample;
|
||||
if(diffsample<0)
|
||||
diffsample+=buffersize;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_sample=(buffersize-1)*cbbysample;
|
||||
diffsample=buffersize;
|
||||
current_sample=0;
|
||||
fprintf(stderr,"Warning DMA stopped\n");
|
||||
}
|
||||
return (uint32_t)diffsample;
|
||||
|
||||
}
|
||||
|
||||
int bufferdma::GetUserMemIndex()
|
||||
{
|
||||
|
||||
int IndexAvailable=-1;
|
||||
if(GetBufferAvailable()>0)
|
||||
{
|
||||
IndexAvailable=last_sample+1;
|
||||
if(IndexAvailable==(int)buffersize) IndexAvailable=0;
|
||||
}
|
||||
return IndexAvailable;
|
||||
}
|
||||
|
||||
int bufferdma::PushSample(int Index)
|
||||
{
|
||||
if(Index<0) return -1; // No buffer available
|
||||
|
||||
/*dma_cb_t *cbp;
|
||||
cbp=&cbarray[last_sample*cbbysample+cbbysample-1];
|
||||
cbp->next=mem_virt_to_phys(&cbarray[Index]);
|
||||
*/
|
||||
last_sample=Index;
|
||||
/*
|
||||
cbp=&cbarray[Index*cbbysample+cbbysample-1];
|
||||
cbp->next=0;
|
||||
*/
|
||||
if(isrunning()==false)
|
||||
{
|
||||
//start();
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
|
27
src/dma.h
27
src/dma.h
|
@ -88,6 +88,33 @@ class dma
|
|||
int start();
|
||||
int stop();
|
||||
uint32_t getcbposition();
|
||||
bool isrunning();
|
||||
|
||||
};
|
||||
|
||||
#define PHYSICAL_BUS 0x7E000000
|
||||
|
||||
class bufferdma:public dma
|
||||
{
|
||||
protected:
|
||||
|
||||
|
||||
uint32_t current_sample;
|
||||
uint32_t last_sample;
|
||||
uint32_t sample_available;
|
||||
|
||||
public:
|
||||
uint32_t buffersize;
|
||||
uint32_t cbbysample;
|
||||
uint32_t registerbysample;
|
||||
uint32_t *sampletab;
|
||||
|
||||
public:
|
||||
bufferdma(int Channel,uint32_t tbuffersize,uint32_t tcbbysample,uint32_t tregisterbysample);
|
||||
void SetDmaAlgo();
|
||||
uint32_t GetBufferAvailable();
|
||||
int GetUserMemIndex();
|
||||
int PushSample(int Index);
|
||||
|
||||
};
|
||||
#endif
|
||||
|
|
101
src/gpio.cpp
101
src/gpio.cpp
|
@ -73,7 +73,7 @@ int clkgpio::SetPllNumber(int PllNo,int MashType)
|
|||
Mash=MashType;
|
||||
else
|
||||
Mash=0;
|
||||
gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(0 << 4) ; //4 is START CLK
|
||||
gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is START CLK
|
||||
usleep(100);
|
||||
Pllfrequency=GetPllFrequency(pllnumber);
|
||||
return 0;
|
||||
|
@ -102,27 +102,108 @@ int clkgpio::SetClkDivFrac(uint32_t Div,uint32_t Frac)
|
|||
|
||||
gpioreg[GPCLK_DIV] = 0x5A000000 | ((Div)<<12) | Frac;
|
||||
usleep(10);
|
||||
gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber |(1<<4) ; //4 is START CLK
|
||||
usleep(10);
|
||||
//gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber |(1<<4) ; //4 is START CLK
|
||||
// usleep(10);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int clkgpio::SetFrequency(uint64_t Frequency)
|
||||
int clkgpio::SetMasterMultFrac(uint32_t Mult,uint32_t Frac)
|
||||
{
|
||||
|
||||
double Freqresult=(double)Pllfrequency/(double)Frequency;
|
||||
uint32_t FreqDivider=(uint32_t)Freqresult;
|
||||
uint32_t FreqFractionnal=(uint32_t) (4096*(Freqresult-(double)FreqDivider));
|
||||
if((FreqDivider>4096)||(FreqDivider<2)) fprintf(stderr,"Frequency out of range\n");
|
||||
printf("DIV/FRAC %u/%u \n",FreqDivider,FreqFractionnal);
|
||||
gpioreg[PLLA_CTRL] = (0x5a<<24) | (0x21<<12) | Mult;
|
||||
//usleep(10);
|
||||
gpioreg[PLLA_FRAC]= 0x5A000000 | Frac ; //4 is START CLK
|
||||
// usleep(10);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int clkgpio::SetFrequency(int Frequency)
|
||||
{
|
||||
if(ModulateFromMasterPLL)
|
||||
{
|
||||
double FloatMult=((double)(CentralFrequency+Frequency)*PllFixDivider)/(double)(XOSC_FREQUENCY);
|
||||
uint32_t freqctl = FloatMult*((double)(1<<20)) ;
|
||||
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
|
||||
freqctl&=0xFFFFF; // Fractionnal is 20bits
|
||||
uint32_t FracMultiply=freqctl&0xFFFFF;
|
||||
SetMasterMultFrac(IntMultiply,FracMultiply);
|
||||
}
|
||||
else
|
||||
{
|
||||
double Freqresult=(double)Pllfrequency/(double)(CentralFrequency+Frequency);
|
||||
uint32_t FreqDivider=(uint32_t)Freqresult;
|
||||
uint32_t FreqFractionnal=(uint32_t) (4096*(Freqresult-(double)FreqDivider));
|
||||
if((FreqDivider>4096)||(FreqDivider<2)) fprintf(stderr,"Frequency out of range\n");
|
||||
//printf("DIV/FRAC %u/%u \n",FreqDivider,FreqFractionnal);
|
||||
|
||||
SetClkDivFrac(FreqDivider,FreqFractionnal);
|
||||
SetClkDivFrac(FreqDivider,FreqFractionnal);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
uint32_t clkgpio::GetMasterFrac(int Frequency)
|
||||
{
|
||||
if(ModulateFromMasterPLL)
|
||||
{
|
||||
double FloatMult=((double)(CentralFrequency+Frequency)*PllFixDivider)/(double)(XOSC_FREQUENCY);
|
||||
uint32_t freqctl = FloatMult*((double)(1<<20)) ;
|
||||
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
|
||||
freqctl&=0xFFFFF; // Fractionnal is 20bits
|
||||
uint32_t FracMultiply=freqctl&0xFFFFF;
|
||||
return FracMultiply;
|
||||
}
|
||||
else
|
||||
return 0; //Not in Master CLk mode
|
||||
|
||||
}
|
||||
|
||||
int clkgpio::ComputeBestLO(uint64_t Frequency)
|
||||
{
|
||||
for(int i=1;i<4096;i++)
|
||||
{
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clkgpio::SetCenterFrequency(uint64_t Frequency)
|
||||
{
|
||||
CentralFrequency=Frequency;
|
||||
if(ModulateFromMasterPLL)
|
||||
{
|
||||
//Choose best PLLDiv and Div
|
||||
ComputeBestLO(Frequency);
|
||||
SetClkDivFrac(PllFixDivider,0); // NO MASH !!!!
|
||||
}
|
||||
else
|
||||
{
|
||||
GetPllFrequency(pllnumber);// Be sure to get the master PLL frequency
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clkgpio::SetPhase(bool inversed)
|
||||
{
|
||||
uint32_t StateBefore=clkgpio::gpioreg[GPCLK_CNTL];
|
||||
clkgpio::gpioreg[GPCLK_CNTL]= (0x5A<<24) | StateBefore | ((inversed?1:0)<<8) | 1<<5;
|
||||
clkgpio::gpioreg[GPCLK_CNTL]= (0x5A<<24) | StateBefore | ((inversed?1:0)<<8) | 0<<5;
|
||||
}
|
||||
|
||||
void clkgpio::SetAdvancedPllMode(bool Advanced)
|
||||
{
|
||||
ModulateFromMasterPLL=Advanced;
|
||||
if(ModulateFromMasterPLL)
|
||||
{
|
||||
SetPllNumber(clk_plla,0); // Use PPL_A , Do not USE MASH which generates spurious
|
||||
gpioreg[0x104/4]=0x5A00020A; // Enable Plla_PER
|
||||
gpioreg[PLLA_PER]=0x5A000002; // Div ?
|
||||
}
|
||||
}
|
||||
|
||||
void clkgpio::print_clock_tree(void)
|
||||
{
|
||||
|
||||
|
|
15
src/gpio.h
15
src/gpio.h
|
@ -108,19 +108,28 @@ enum {clk_gnd,clk_osc,clk_debug0,clk_debug1,clk_plla,clk_pllc,clk_plld,clk_hdmi}
|
|||
|
||||
class clkgpio:public gpio
|
||||
{
|
||||
protected:
|
||||
int pllnumber;
|
||||
int Mash;
|
||||
uint64_t Pllfrequency;
|
||||
|
||||
bool ModulateFromMasterPLL=false;
|
||||
|
||||
uint64_t CentralFrequency=0;
|
||||
int PllFixDivider=8; //Fix divider from the master clock in advanced mode
|
||||
public:
|
||||
clkgpio();
|
||||
~clkgpio();
|
||||
int SetPllNumber(int PllNo,int MashType);
|
||||
uint64_t GetPllFrequency(int PllNo);
|
||||
void print_clock_tree(void);
|
||||
int SetFrequency(uint64_t Frequency);
|
||||
int SetFrequency(int Frequency);
|
||||
int SetClkDivFrac(uint32_t Div,uint32_t Frac);
|
||||
|
||||
void SetPhase(bool inversed);
|
||||
void SetAdvancedPllMode(bool Advanced);
|
||||
int SetCenterFrequency(uint64_t Frequency);
|
||||
int ComputeBestLO(uint64_t Frequency);
|
||||
int SetMasterMultFrac(uint32_t Mult,uint32_t Frac);
|
||||
uint32_t GetMasterFrac(int Frequency);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -5,13 +5,16 @@
|
|||
#include "ngfmdmasync.h"
|
||||
|
||||
|
||||
ngfmdmasync::ngfmdmasync(uint64_t TuneFrequency,uint32_t SampleRate,int Channel,uint32_t FifoSize):dma(Channel,FifoSize*3,FifoSize*2)
|
||||
ngfmdmasync::ngfmdmasync(uint64_t TuneFrequency,uint32_t SampleRate,int Channel,uint32_t FifoSize):bufferdma(Channel,FifoSize,2,1)
|
||||
{
|
||||
tunefreq=TuneFrequency;
|
||||
clkgpio::SetPllNumber(clk_plla,0); // Use PPL_A , Do not USE MASH which generates spurious
|
||||
clkgpio::gpioreg[0x104/4]=0x5A00020A; // Enable Plla_PER
|
||||
clkgpio::gpioreg[PLLA_PER]=0x5A000002; // Div ?
|
||||
|
||||
|
||||
tunefreq=TuneFrequency;
|
||||
clkgpio::SetAdvancedPllMode(true);
|
||||
clkgpio::SetCenterFrequency(TuneFrequency); // Write Mult Int and Frac : FixMe carrier is already there
|
||||
|
||||
|
||||
/*
|
||||
double FloatMult=((double)TuneFrequency)/(double)(XOSC_FREQUENCY);
|
||||
uint32_t freqctl = FloatMult*((double)(1<<20)) ;
|
||||
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
|
||||
|
@ -20,16 +23,19 @@ ngfmdmasync::ngfmdmasync(uint64_t TuneFrequency,uint32_t SampleRate,int Channel,
|
|||
uint32_t FracMultiply=freqctl&0xFFFFC; // Check if last 2 bits are really there
|
||||
|
||||
clkgpio::gpioreg[PLLA_CTRL] = (0x5a<<24) | (0x21<<12) | IntMultiply;
|
||||
//clkgpio::gpioreg[PLLA_FRAC] = (0x5a<<24) | (0xFFFF);
|
||||
SetClkDivFrac(2,0); // CLK is not divided for now !
|
||||
|
||||
|
||||
SetClkDivFrac(4,0); // CLK is not divided for now !
|
||||
*/
|
||||
|
||||
pwmgpio::SetPllNumber(clk_osc,1);
|
||||
pwmgpio::SetFrequency(SampleRate);
|
||||
pwmgpio::SetMode(0);
|
||||
fprintf(stderr,"PLLA Div %d Frac %d\n",IntMultiply,FracMultiply);
|
||||
//clkgpio::print_clock_tree();
|
||||
SetDmaAlgo();
|
||||
FillMemory(IntMultiply,FracMultiply);
|
||||
|
||||
|
||||
|
||||
//SetDmaAlgo();
|
||||
|
||||
//FillMemory(IntMultiply,FracMultiply);
|
||||
|
||||
// Note : Spurious are at +/-(19.2MHZ/2^20)*Div*N : (N=1,2,3...) So we need to have a big div to spurious away BUT
|
||||
// Spurious are ALSO at +/-(19.2MHZ/2^20)*(2^20-Div)*N
|
||||
|
@ -41,32 +47,38 @@ ngfmdmasync::~ngfmdmasync()
|
|||
{
|
||||
}
|
||||
|
||||
void ngfmdmasync::SetPhase(bool inversed)
|
||||
{
|
||||
clkgpio::SetPhase(inversed);
|
||||
}
|
||||
|
||||
void ngfmdmasync::SetDmaAlgo()
|
||||
{
|
||||
dma_cb_t *cbp = cbarray;
|
||||
for (uint32_t samplecnt = 0; samplecnt < usermemsize/2; samplecnt++)
|
||||
for (uint32_t samplecnt = 0; samplecnt < buffersize; samplecnt++)
|
||||
{
|
||||
|
||||
// Write a frequency sample
|
||||
|
||||
// Write INT Mult
|
||||
/*
|
||||
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
|
||||
cbp->src = mem_virt_to_phys(&usermem[samplecnt*2]);
|
||||
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample]);
|
||||
cbp->dst = 0x7E000000 + (PLLA_CTRL<<2) + CLK_BASE ;
|
||||
cbp->length = 4;
|
||||
cbp->stride = 0;
|
||||
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
|
||||
cbp++;
|
||||
*/
|
||||
|
||||
// Write a frequency sample
|
||||
|
||||
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
|
||||
cbp->src = mem_virt_to_phys(&usermem[samplecnt*2+1]);
|
||||
cbp->src = mem_virt_to_phys(&usermem[samplecnt*registerbysample]);
|
||||
cbp->dst = 0x7E000000 + (PLLA_FRAC<<2) + CLK_BASE ;
|
||||
cbp->length = 4;
|
||||
cbp->stride = 0;
|
||||
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
|
||||
fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
|
||||
cbp++;
|
||||
|
||||
|
||||
|
@ -78,7 +90,7 @@ void ngfmdmasync::SetDmaAlgo()
|
|||
cbp->length = 4;
|
||||
cbp->stride = 0;
|
||||
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||
//fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
|
||||
fprintf(stderr,"cbp : sample %x src %x dest %x next %x\n",samplecnt,cbp->src,cbp->dst,cbp->next);
|
||||
cbp++;
|
||||
}
|
||||
|
||||
|
@ -87,6 +99,12 @@ void ngfmdmasync::SetDmaAlgo()
|
|||
//fprintf(stderr,"Last cbp : src %x dest %x next %x\n",cbp->src,cbp->dst,cbp->next);
|
||||
}
|
||||
|
||||
void ngfmdmasync::SetFrequencySample(uint32_t Index,int Frequency)
|
||||
{
|
||||
sampletab[Index]=(0x5A<<24)|GetMasterFrac(Frequency);
|
||||
PushSample(Index);
|
||||
}
|
||||
|
||||
void ngfmdmasync::FillMemory(uint32_t MultInt,uint32_t FirstFrac)
|
||||
{
|
||||
|
||||
|
@ -102,9 +120,9 @@ void ngfmdmasync::FillMemory(uint32_t MultInt,uint32_t FirstFrac)
|
|||
fprintf(stderr,"Cross Int\n");
|
||||
tempmul=MultInt+1;
|
||||
}
|
||||
usermem[samplecnt*2]=(0x5a<<24) | (0x21<<12) | tempmul;
|
||||
usermem[samplecnt*2+1]=0x5A000000 | Frac;
|
||||
//usermem[samplecnt]=0x5A000000 | FirstFrac;
|
||||
//usermem[samplecnt*2]=(0x5a<<24) | (0x21<<12) | tempmul;
|
||||
//usermem[samplecnt*2+1]=0x5A000000 | Frac;
|
||||
usermem[samplecnt*2]=0x5A000000 | FirstFrac;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "dma.h"
|
||||
#include "gpio.h"
|
||||
|
||||
class ngfmdmasync:public dma,clkgpio,pwmgpio
|
||||
class ngfmdmasync:public bufferdma,public clkgpio,public pwmgpio
|
||||
{
|
||||
protected:
|
||||
uint64_t tunefreq;
|
||||
|
@ -14,6 +14,8 @@ class ngfmdmasync:public dma,clkgpio,pwmgpio
|
|||
~ngfmdmasync();
|
||||
void SetDmaAlgo();
|
||||
void FillMemory(uint32_t MultInt,uint32_t FirstFrac);
|
||||
void SetPhase(bool inversed);
|
||||
void SetFrequencySample(uint32_t Index,int Frequency);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,8 +10,35 @@ int main(int argc, char* argv[])
|
|||
|
||||
generalgpio generalio;
|
||||
generalio.enableclk();
|
||||
ngfmdmasync ngfmtest(144200000*2,5000,14,512);
|
||||
ngfmtest.start();
|
||||
|
||||
/*clkgpio clk;
|
||||
clk.SetPllNumber(clk_plld,1);
|
||||
clk.SetAdvancedPllMode(true);
|
||||
clk.SetCenterFrequency(144100000);
|
||||
for(int i=0;i<1000000;i+=10)
|
||||
{
|
||||
clk.SetFrequency(i);
|
||||
usleep(10);
|
||||
}
|
||||
sleep(5);*/
|
||||
|
||||
//dma mydma(14,32,16);
|
||||
//bufferdma mydma(14,16,2,1);
|
||||
|
||||
ngfmdmasync ngfmtest(144100000,5000,14,16);
|
||||
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
int Index=ngfmtest.GetUserMemIndex();
|
||||
if(Index>=0)
|
||||
{
|
||||
ngfmtest.SetFrequencySample(Index,i);
|
||||
|
||||
}
|
||||
else
|
||||
usleep(100);
|
||||
}
|
||||
fprintf(stderr,"End\n");
|
||||
sleep(10);
|
||||
ngfmtest.stop();
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue