kopia lustrzana https://github.com/F5OEO/rpitx
First implementation of new PLL method
rodzic
4951e011a9
commit
abdadd634e
|
@ -15,10 +15,10 @@ LDFLAGS = -lm -lrt -lpthread
|
|||
CCP = g++
|
||||
CC = gcc
|
||||
|
||||
v2rpitx: gpio.h gpio.cpp dma.h dma.cpp mailbox.c raspberry_pi_revision.c v2rpitx.cpp fmdmasync.h fmdmasync.cpp
|
||||
v2rpitx: gpio.h gpio.cpp dma.h dma.cpp mailbox.c raspberry_pi_revision.c v2rpitx.cpp fmdmasync.h fmdmasync.cpp ngfmdmasync.h ngfmdmasync.cpp
|
||||
$(CC) $(CFLAGS) -c -o mailbox.o mailbox.c
|
||||
$(CC) $(CFLAGS) -c -o raspberry_pi_revision.o raspberry_pi_revision.c
|
||||
$(CCP) $(CFLAGS) -o v2rpitx fmdmasync.cpp dma.cpp gpio.cpp mailbox.o raspberry_pi_revision.o v2rpitx.cpp $(LDFLAGS)
|
||||
$(CCP) $(CFLAGS) -o v2rpitx ngfmdmasync.cpp fmdmasync.cpp dma.cpp gpio.cpp mailbox.o raspberry_pi_revision.o v2rpitx.cpp $(LDFLAGS)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ void fmdmasync::SetDmaAlgo()
|
|||
|
||||
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
|
||||
cbp->src = mem_virt_to_phys(&usermem[samplecnt]);
|
||||
cbp->dst = 0x7E000000 | (GPCLK_DIV<<2) | CLK_BASE ;
|
||||
cbp->dst = 0x7E000000 + (GPCLK_DIV<<2) + CLK_BASE ;
|
||||
cbp->length = 4;
|
||||
cbp->stride = 0;
|
||||
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||
|
@ -34,7 +34,7 @@ void fmdmasync::SetDmaAlgo()
|
|||
|
||||
cbp->info = /*BCM2708_DMA_SRC_IGNOR | */BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
|
||||
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
|
||||
cbp->dst = 0x7E000000 | (PWM_FIFO<<2) | PWM_BASE ;
|
||||
cbp->dst = 0x7E000000 + (PWM_FIFO<<2) + PWM_BASE ;
|
||||
cbp->length = 4;
|
||||
cbp->stride = 0;
|
||||
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||
|
|
39
src/gpio.cpp
39
src/gpio.cpp
|
@ -73,7 +73,8 @@ int clkgpio::SetPllNumber(int PllNo,int MashType)
|
|||
Mash=MashType;
|
||||
else
|
||||
Mash=0;
|
||||
gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is START CLK
|
||||
gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(0 << 4) ; //4 is START CLK
|
||||
usleep(100);
|
||||
Pllfrequency=GetPllFrequency(pllnumber);
|
||||
return 0;
|
||||
}
|
||||
|
@ -95,6 +96,18 @@ uint64_t clkgpio::GetPllFrequency(int PllNo)
|
|||
return Freq;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int clkgpio::SetFrequency(uint64_t Frequency)
|
||||
{
|
||||
|
||||
|
@ -103,9 +116,9 @@ int clkgpio::SetFrequency(uint64_t Frequency)
|
|||
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[GPCLK_DIV] = 0x5A000000 | ((FreqDivider)<<12) | FreqFractionnal;
|
||||
//gpioreg[GPCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber |4 ; //4 is START CLK
|
||||
|
||||
SetClkDivFrac(FreqDivider,FreqFractionnal);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -162,6 +175,7 @@ void clkgpio::print_clock_tree(void)
|
|||
printf("TIMER CTL=%08x DIV=%8x\n",gpioreg[58],gpioreg[59]);
|
||||
printf("UART CTL=%08x DIV=%8x ",gpioreg[60],gpioreg[61]);
|
||||
printf("VEC CTL=%08x DIV=%8x\n",gpioreg[62],gpioreg[63]);
|
||||
|
||||
|
||||
printf("PULSE CTL=%08x DIV=%8x ",gpioreg[100],gpioreg[101]);
|
||||
printf("PLLT CTL=%08x DIV=????????\n",gpioreg[76]);
|
||||
|
@ -170,10 +184,15 @@ void clkgpio::print_clock_tree(void)
|
|||
printf("DSI1P CTL=%08x DIV=%8x\n",gpioreg[88],gpioreg[89]);
|
||||
printf("AVE0 CTL=%08x DIV=%8x\n",gpioreg[90],gpioreg[91]);
|
||||
|
||||
printf("SDC CTL=%08x DIV=%8x ",gpioreg[106],gpioreg[107]);
|
||||
printf("ARM CTL=%08x DIV=%8x\n",gpioreg[108],gpioreg[109]);
|
||||
printf("AVE0 CTL=%08x DIV=%8x ",gpioreg[110],gpioreg[111]);
|
||||
printf("EMMC CTL=%08x DIV=%8x\n",gpioreg[112],gpioreg[113]);
|
||||
printf("CMPLLA=%08x ",gpioreg[0x104/4]);
|
||||
printf("CMPLLC=%08x \n",gpioreg[0x108/4]);
|
||||
printf("CMPLLD=%08x ",gpioreg[0x10C/4]);
|
||||
printf("CMPLLH=%08x \n",gpioreg[0x110/4]);
|
||||
|
||||
printf("EMMC CTL=%08x DIV=%8x\n",gpioreg[112],gpioreg[113]);
|
||||
printf("EMMC CTL=%08x DIV=%8x\n",gpioreg[112],gpioreg[113]);
|
||||
printf("EMMC CTL=%08x DIV=%8x\n",gpioreg[112],gpioreg[113]);
|
||||
|
||||
|
||||
// Sometimes calculated frequencies are off by a factor of 2
|
||||
// ANA1 bit 14 may indicate that a /2 prescaler is active
|
||||
|
@ -248,6 +267,7 @@ int pwmgpio::SetPllNumber(int PllNo,int MashType)
|
|||
else
|
||||
Mash=0;
|
||||
clk.gpioreg[PWMCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(0 << 4) ; //4 is STOP CLK
|
||||
usleep(100);
|
||||
Pllfrequency=GetPllFrequency(pllnumber);
|
||||
return 0;
|
||||
}
|
||||
|
@ -266,8 +286,9 @@ int pwmgpio::SetFrequency(uint64_t Frequency)
|
|||
uint32_t FreqFractionnal=(uint32_t) (4096*(Freqresult-(double)FreqDivider));
|
||||
if((FreqDivider>4096)||(FreqDivider<2)) fprintf(stderr,"Frequency out of range\n");
|
||||
clk.gpioreg[PWMCLK_DIV] = 0x5A000000 | ((FreqDivider)<<12) | FreqFractionnal;
|
||||
usleep(10);
|
||||
usleep(100);
|
||||
clk.gpioreg[PWMCLK_CNTL]= 0x5A000000 | (Mash << 9) | pllnumber|(1 << 4) ; //4 is STAR CLK
|
||||
usleep(100);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ class clkgpio:public gpio
|
|||
uint64_t GetPllFrequency(int PllNo);
|
||||
void print_clock_tree(void);
|
||||
int SetFrequency(uint64_t Frequency);
|
||||
int SetClkDivFrac(uint32_t Div,uint32_t Frac);
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
#include "stdio.h"
|
||||
#include "ngfmdmasync.h"
|
||||
|
||||
|
||||
ngfmdmasync::ngfmdmasync(uint64_t TuneFrequency,uint32_t SampleRate,int Channel,uint32_t FifoSize):dma(Channel,FifoSize*2,FifoSize)
|
||||
{
|
||||
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 ?
|
||||
|
||||
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
|
||||
freqctl&=0xFFFFF; // Fractionnal is 20bits
|
||||
//fprintf(stderr,"freqctl=%d\n", freqctl);
|
||||
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 !
|
||||
|
||||
pwmgpio::SetPllNumber(clk_osc,1);
|
||||
pwmgpio::SetFrequency(SampleRate);
|
||||
pwmgpio::SetMode(0);
|
||||
|
||||
//clkgpio::print_clock_tree();
|
||||
SetDmaAlgo();
|
||||
FillMemory(FracMultiply);
|
||||
}
|
||||
|
||||
ngfmdmasync::~ngfmdmasync()
|
||||
{
|
||||
}
|
||||
|
||||
void ngfmdmasync::SetDmaAlgo()
|
||||
{
|
||||
dma_cb_t *cbp = cbarray;
|
||||
for (uint32_t samplecnt = 0; samplecnt < cbsize/2; samplecnt++) { //cbsize/2 because we have 2 CB by sample
|
||||
|
||||
|
||||
// Write a frequency sample
|
||||
|
||||
cbp->info = BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP ;
|
||||
cbp->src = mem_virt_to_phys(&usermem[samplecnt]);
|
||||
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);
|
||||
cbp++;
|
||||
|
||||
|
||||
// Delay
|
||||
|
||||
cbp->info = /*BCM2708_DMA_SRC_IGNOR | */BCM2708_DMA_NO_WIDE_BURSTS | BCM2708_DMA_WAIT_RESP | BCM2708_DMA_D_DREQ | BCM2708_DMA_PER_MAP(DREQ_PWM);
|
||||
cbp->src = mem_virt_to_phys(cbarray); // Data is not important as we use it only to feed the PWM
|
||||
cbp->dst = 0x7E000000 + (PWM_FIFO<<2) + PWM_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++;
|
||||
}
|
||||
|
||||
cbp--;
|
||||
cbp->next = mem_virt_to_phys(cbarray); // We loop to the first CB
|
||||
//fprintf(stderr,"Last cbp : src %x dest %x next %x\n",cbp->src,cbp->dst,cbp->next);
|
||||
}
|
||||
|
||||
void ngfmdmasync::FillMemory(uint32_t FirstFrac)
|
||||
{
|
||||
if(FirstFrac<usermemsize) FirstFrac=usermemsize;
|
||||
for (uint32_t samplecnt = 0; samplecnt < usermemsize; samplecnt++)
|
||||
{
|
||||
uint32_t Frac=(FirstFrac+samplecnt*((samplecnt%2==0)?1:-1))&0xFFFFF;
|
||||
|
||||
usermem[samplecnt]=0x5A000000 | Frac;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef DEF_NGFMDMASYNC
|
||||
#define DEF_NGFMDMASYNC
|
||||
|
||||
#include "stdint.h"
|
||||
#include "dma.h"
|
||||
#include "gpio.h"
|
||||
|
||||
class ngfmdmasync:public dma,clkgpio,pwmgpio
|
||||
{
|
||||
protected:
|
||||
uint64_t tunefreq;
|
||||
public:
|
||||
ngfmdmasync(uint64_t TuneFrequency,uint32_t SampleRate,int Channel,uint32_t FifoSize);
|
||||
~ngfmdmasync();
|
||||
void SetDmaAlgo();
|
||||
void FillMemory(uint32_t FirstFrac);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -2,38 +2,38 @@
|
|||
#include "dma.h"
|
||||
#include "gpio.h"
|
||||
#include "fmdmasync.h"
|
||||
#include "ngfmdmasync.h"
|
||||
#include "stdio.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
clkgpio clk;
|
||||
//clk.print_clock_tree();
|
||||
clk.SetPllNumber(clk_plld,1);
|
||||
|
||||
generalgpio generalio;
|
||||
generalio.enableclk();
|
||||
ngfmdmasync ngfmtest(751000000,10000,14,1024);
|
||||
ngfmtest.start();
|
||||
sleep(30);
|
||||
ngfmtest.stop();
|
||||
|
||||
|
||||
|
||||
// Test Fmdmasync
|
||||
/*
|
||||
pwmgpio pwm;
|
||||
pwm.SetPllNumber(clk_osc,1);
|
||||
pwm.SetFrequency(10000);
|
||||
pwm.SetFrequency(5000);
|
||||
pwm.SetMode(0);
|
||||
//clk.SetFrequency(89100000);
|
||||
|
||||
fmdmasync fmtest(14,400);
|
||||
fmdmasync fmtest(14,72);
|
||||
fmtest.start();
|
||||
for(int i=0;i<10000;i++)
|
||||
{
|
||||
|
||||
}
|
||||
sleep(10);
|
||||
fmtest.stop();
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
for(int i=0;i<10000;i++)
|
||||
{
|
||||
usleep(50);
|
||||
clk.SetFrequency(89000000+(i%2)*200000);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
sleep(180);
|
||||
fmtest.stop();
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue