First implementation of new PLL method

v2beta
F5OEO 2018-03-01 12:54:32 +00:00
rodzic 4951e011a9
commit abdadd634e
7 zmienionych plików z 153 dodań i 31 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

19
src/ngfmdmasync.h 100644
Wyświetl plik

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

Wyświetl plik

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