Working on dmabuffer

v2beta
F5OEO 2018-03-05 14:00:30 +00:00
rodzic c6b3905fd3
commit 11af187182
7 zmienionych plików z 285 dodań i 38 usunięć

Wyświetl plik

@ -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;
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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)
{

Wyświetl plik

@ -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);
};

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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();