Compare commits
32 commits
simplify_d
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
dbb26b33c7 | ||
|
d514817b65 | ||
|
e0a4588df8 | ||
|
c9ea7cacb8 | ||
|
b0172f908b | ||
|
a7def5d4ba | ||
|
f6dfbeae03 | ||
|
b571c4a308 | ||
|
0aec0363e2 | ||
|
fd366412f7 | ||
|
d139ff56fb | ||
|
d318058a17 | ||
|
1cd126f230 | ||
|
5aabd38264 | ||
|
c360d016ca | ||
|
692db75eef | ||
|
b90473b76e | ||
|
93cf35a7ba | ||
|
02599bd7f2 | ||
|
7f6f1be34e | ||
|
e48ebd5b23 | ||
|
5c857b9f7d | ||
|
3b929185ff | ||
|
2d2d854280 | ||
|
a3611e265e | ||
|
5b5a4ee083 | ||
|
5c1613589d | ||
|
7c8849756d | ||
|
2d1bf3042b | ||
|
c9714b2a7d | ||
|
6bb567b63e | ||
|
5475c41ccf |
21 changed files with 2390 additions and 307 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.gch
|
|
@ -1,7 +1,7 @@
|
||||||
all: testrpitx
|
all: testrpitx
|
||||||
|
|
||||||
CFLAGS = -Wall -g -O3 -Wno-unused-variable
|
CFLAGS = -Wall -g -O3 -Wno-unused-variable -I /opt/vc/include
|
||||||
LDFLAGS = -lm -lrt -lpthread
|
LDFLAGS = -lm -lrt -lpthread -L/opt/vc/lib -lbcm_host
|
||||||
CCP = g++
|
CCP = g++
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
||||||
|
|
1800
app/bcmstat.sh
Executable file
1800
app/bcmstat.sh
Executable file
File diff suppressed because it is too large
Load diff
BIN
app/testrpitx
BIN
app/testrpitx
Binary file not shown.
|
@ -283,9 +283,9 @@ void SimpleTestAm(uint64_t Freq)
|
||||||
void SimpleTestOOK(uint64_t Freq)
|
void SimpleTestOOK(uint64_t Freq)
|
||||||
{
|
{
|
||||||
|
|
||||||
int SR = 1000;
|
int SR = 10; //10 HZ
|
||||||
int FifoSize = 21; //24
|
int FifoSize = 21; //24
|
||||||
ookburst ook(Freq, SR, 14, FifoSize);
|
ookburst ook(Freq, SR, 14, FifoSize,100);
|
||||||
|
|
||||||
unsigned char TabSymbol[FifoSize] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0};
|
unsigned char TabSymbol[FifoSize] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0};
|
||||||
|
|
||||||
|
@ -701,6 +701,54 @@ void SimpleTestAtv(uint64_t Freq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void info(uint64_t Freq)
|
||||||
|
{
|
||||||
|
generalgpio genpio;
|
||||||
|
fprintf(stderr, "GPIOPULL =%x\n", genpio.gpioreg[GPPUDCLK0]);
|
||||||
|
|
||||||
|
#define PULL_OFF 0
|
||||||
|
#define PULL_DOWN 1
|
||||||
|
#define PULL_UP 2
|
||||||
|
/*genpio.gpioreg[GPPUD] = 0; //PULL_DOWN;
|
||||||
|
usleep(150);
|
||||||
|
genpio.gpioreg[GPPUDCLK0] = (1 << 4); //GPIO CLK is GPIO 4
|
||||||
|
usleep(150);
|
||||||
|
genpio.gpioreg[GPPUDCLK0] = (0); //GPIO CLK is GPIO 4
|
||||||
|
*/
|
||||||
|
//genpio.setpulloff(4);
|
||||||
|
|
||||||
|
padgpio pad;
|
||||||
|
pad.setlevel(7);
|
||||||
|
|
||||||
|
clkgpio clk;
|
||||||
|
clk.print_clock_tree();
|
||||||
|
/* // THis fractional works on pi4
|
||||||
|
clk.SetPllNumber(clk_plld, 2);
|
||||||
|
clk.enableclk(4);
|
||||||
|
*/
|
||||||
|
clk.SetPllNumber(clk_pllc, 2);
|
||||||
|
clk.SetAdvancedPllMode(true);
|
||||||
|
clk.enableclk(4);
|
||||||
|
//clk.SetAdvancedPllMode(true);
|
||||||
|
//clk.SetPLLMasterLoop(0,4,0);
|
||||||
|
//clk.Setppm(+7.7);
|
||||||
|
clk.SetCenterFrequency(Freq, 1000);
|
||||||
|
clk.SetFrequency(0);
|
||||||
|
double freqresolution = clk.GetFrequencyResolution();
|
||||||
|
double RealFreq = clk.GetRealFrequency(0);
|
||||||
|
fprintf(stderr, "Frequency resolution=%f Error freq=%f\n", freqresolution, RealFreq);
|
||||||
|
int Deviation = 0;
|
||||||
|
|
||||||
|
for(int i=0;i<1000;i++)
|
||||||
|
{
|
||||||
|
clk.SetFrequency(i*100);
|
||||||
|
usleep(10000);
|
||||||
|
}
|
||||||
|
sleep(10);
|
||||||
|
clk.disableclk(4);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
terminate(int num)
|
terminate(int num)
|
||||||
{
|
{
|
||||||
|
@ -723,7 +771,7 @@ int main(int argc, char *argv[])
|
||||||
sa.sa_handler = terminate;
|
sa.sa_handler = terminate;
|
||||||
sigaction(i, &sa, NULL);
|
sigaction(i, &sa, NULL);
|
||||||
}
|
}
|
||||||
dbg_setlevel(0);
|
dbg_setlevel(1);
|
||||||
//SimpleTest(Freq);
|
//SimpleTest(Freq);
|
||||||
//SimpleTestbpsk(Freq);
|
//SimpleTestbpsk(Freq);
|
||||||
//SimpleTestFileIQ(Freq);
|
//SimpleTestFileIQ(Freq);
|
||||||
|
@ -734,5 +782,8 @@ int main(int argc, char *argv[])
|
||||||
//SimpleTestOOKTiming(Freq);
|
//SimpleTestOOKTiming(Freq);
|
||||||
//AlectoOOK(Freq);
|
//AlectoOOK(Freq);
|
||||||
//RfSwitchOOK(Freq);
|
//RfSwitchOOK(Freq);
|
||||||
SimpleTestAtv(Freq);
|
//SimpleTestbpsk(Freq);
|
||||||
|
|
||||||
|
//SimpleTestAtv(Freq);
|
||||||
|
info(Freq);
|
||||||
}
|
}
|
||||||
|
|
44
src/Makefile
44
src/Makefile
|
@ -1,16 +1,36 @@
|
||||||
CFLAGS = -Wall -O3 -Wno-unused-variable
|
CFLAGS ?= -Wall -O3 -Wno-unused-variable
|
||||||
CXXFLAGS = -std=c++11 -Wall -O3 -Wno-unused-variable
|
CFLAGS += -std=c++11 -fPIC
|
||||||
LDFLAGS = -lm -lrt -lpthread
|
CXXFLAGS ?= -std=c++11 -Wall -O3 -Wno-unused-variable -I /opt/vc/include
|
||||||
CCP = c++
|
CXXFLAGS += -std=c++11 -Wall -O3 -Wno-unused-variable -fPIC
|
||||||
CC = cc
|
LDFLAGS ?= -lm -lrt -lpthread -L/opt/vc/lib -lbcm_host
|
||||||
|
LDFLAGS += -fPIC
|
||||||
|
CXX ?= c++
|
||||||
|
CC ?= cc
|
||||||
|
PREFIX ?= /usr/local/
|
||||||
|
SRCCC=$(wildcard *.c)
|
||||||
|
SRCXX=$(wildcard *.cpp)
|
||||||
|
OBJS=$(SRCCC:.c=.o)
|
||||||
|
OBJS+=$(SRCXX:.cpp=.o)
|
||||||
|
|
||||||
librpitx: librpitx.h gpio.h gpio.cpp dma.h dma.cpp mailbox.c raspberry_pi_revision.c fmdmasync.h fmdmasync.cpp ngfmdmasync.h ngfmdmasync.cpp dsp.h dsp.cpp iqdmasync.h iqdmasync.cpp serialdmasync.h serialdmasync.cpp phasedmasync.h phasedmasync.cpp fskburst.h fskburst.cpp ookburst.cpp ookburst.h atv.h atv.cpp util.h
|
all: librpitx.a librpitx.so
|
||||||
#$(CC) $(CFLAGS) -c -o mailbox.o mailbox.c
|
|
||||||
$(CC) $(CFLAGS) -c -o raspberry_pi_revision.o raspberry_pi_revision.c
|
|
||||||
$(CCP) $(CXXFLAGS) -c dsp.cpp iqdmasync.cpp ngfmdmasync.cpp fmdmasync.cpp dma.cpp gpio.cpp serialdmasync.cpp phasedmasync.cpp amdmasync.h amdmasync.cpp fskburst.cpp ookburst.cpp atv.cpp util.cpp mailbox.c
|
|
||||||
$(AR) rc librpitx.a dsp.o iqdmasync.o ngfmdmasync.o fmdmasync.o dma.o gpio.o mailbox.o raspberry_pi_revision.o serialdmasync.o phasedmasync.o amdmasync.o fskburst.o ookburst.o atv.o util.o mailbox.o
|
|
||||||
|
|
||||||
install: librpitx
|
%.o: %.c
|
||||||
|
$(CXX) $(CFLAGS) -c $^
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CXX) $(CXXFLAGS) -c $^
|
||||||
|
|
||||||
|
librpitx.a: $(OBJS)
|
||||||
|
$(AR) rc $@ $^
|
||||||
|
|
||||||
|
librpitx.so: $(OBJS)
|
||||||
|
$(CXX) -fPIC -shared -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
|
install: librpitx.a
|
||||||
|
mkdir -p $(PREFIX)/include/librpitx
|
||||||
|
install *.h $(PREFIX)/include/librpitx
|
||||||
|
mkdir -p $(PREFIX)/lib
|
||||||
|
install librpitx.a $(PREFIX)/lib
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o *.a
|
rm -f $(OBJS) *.a *.so
|
||||||
|
|
Binary file not shown.
|
@ -158,7 +158,7 @@ void atv::SetDmaAlgo()
|
||||||
}
|
}
|
||||||
cbp--;
|
cbp--;
|
||||||
cbp->next = mem_virt_to_phys(cbarray); // We loop to the first CB
|
cbp->next = mem_virt_to_phys(cbarray); // We loop to the first CB
|
||||||
dbg_printf(1, "Last cbp : %d \n", ((unsigned int)(cbp) - (unsigned int)(cbarray)) / sizeof(dma_cb_t));
|
dbg_printf(1, "Last cbp : %d \n", ((uintptr_t)(cbp) - (uintptr_t)(cbarray)) / sizeof(dma_cb_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void atv::SetFrame(unsigned char *Luminance, size_t Lines)
|
void atv::SetFrame(unsigned char *Luminance, size_t Lines)
|
||||||
|
|
44
src/dma.cpp
44
src/dma.cpp
|
@ -19,6 +19,7 @@ This program is free software: you can redistribute it and/or modify
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "rpi.h"
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
@ -32,9 +33,24 @@ extern "C"
|
||||||
|
|
||||||
dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize) // Fixme! Need to check to be 256 Aligned for UserMem
|
dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize) // Fixme! Need to check to be 256 Aligned for UserMem
|
||||||
{
|
{
|
||||||
dbg_printf(1,"Channel %d CBSize %u UsermemSize %u\n",Channel,CBSize,UserMemSize);
|
|
||||||
|
//Channel DMA is now hardcoded according to Raspi Model (DMA 7 for Pi4, DMA 14 for others)
|
||||||
|
uint32_t BCM2708_PERI_BASE =bcm_host_get_peripheral_address();
|
||||||
|
|
||||||
channel=Channel;
|
channel=Channel;
|
||||||
|
if(BCM2708_PERI_BASE==0xFE000000)
|
||||||
|
{
|
||||||
|
channel= 7; // Pi4
|
||||||
|
dbg_printf(1,"dma PI4 using channel %d\n",channel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channel = 14; // Other Pi
|
||||||
|
dbg_printf(1,"dma (NOT a PI4) using channel %d\n",channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg_printf(1,"channel %d CBSize %u UsermemSize %u\n",channel,CBSize,UserMemSize);
|
||||||
|
|
||||||
mbox.handle = mbox_open();
|
mbox.handle = mbox_open();
|
||||||
if (mbox.handle < 0)
|
if (mbox.handle < 0)
|
||||||
{
|
{
|
||||||
|
@ -45,6 +61,7 @@ dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize) // Fixme! Need to che
|
||||||
usermemsize=UserMemSize;
|
usermemsize=UserMemSize;
|
||||||
|
|
||||||
GetRpiInfo(); // Fill mem_flag and dram_phys_base
|
GetRpiInfo(); // Fill mem_flag and dram_phys_base
|
||||||
|
|
||||||
uint32_t MemoryRequired=CBSize*sizeof(dma_cb_t)+UserMemSize*sizeof(uint32_t);
|
uint32_t MemoryRequired=CBSize*sizeof(dma_cb_t)+UserMemSize*sizeof(uint32_t);
|
||||||
int NumPages=(MemoryRequired/PAGE_SIZE)+1;
|
int NumPages=(MemoryRequired/PAGE_SIZE)+1;
|
||||||
dbg_printf(1,"%d Size NUM PAGES %d PAGE_SIZE %d\n",MemoryRequired,NumPages,PAGE_SIZE);
|
dbg_printf(1,"%d Size NUM PAGES %d PAGE_SIZE %d\n",MemoryRequired,NumPages,PAGE_SIZE);
|
||||||
|
@ -71,27 +88,16 @@ dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize) // Fixme! Need to che
|
||||||
|
|
||||||
void dma::GetRpiInfo()
|
void dma::GetRpiInfo()
|
||||||
{
|
{
|
||||||
RASPBERRY_PI_INFO_T info;
|
dram_phys_base= bcm_host_get_sdram_address();
|
||||||
if (getRaspberryPiInformation(&info) > 0)
|
|
||||||
{
|
|
||||||
if(info.peripheralBase==RPI_BROADCOM_2835_PERIPHERAL_BASE)
|
|
||||||
{
|
|
||||||
|
|
||||||
dram_phys_base = 0x40000000;
|
|
||||||
mem_flag = MEM_FLAG_L1_NONALLOCATING|MEM_FLAG_HINT_PERMALOCK|MEM_FLAG_NO_INIT;//0x0c;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((info.peripheralBase==RPI_BROADCOM_2836_PERIPHERAL_BASE)||(info.peripheralBase==RPI_BROADCOM_2837_PERIPHERAL_BASE))
|
mem_flag = MEM_FLAG_HINT_PERMALOCK|MEM_FLAG_NO_INIT;//0x0c;
|
||||||
{
|
switch(dram_phys_base)
|
||||||
|
|
||||||
dram_phys_base = 0xc0000000;
|
|
||||||
mem_flag = MEM_FLAG_DIRECT|MEM_FLAG_HINT_PERMALOCK|MEM_FLAG_NO_INIT;// 0x04;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
dbg_printf(1,"Unknown Raspberry architecture\n");
|
case 0x40000000 : mem_flag |=MEM_FLAG_L1_NONALLOCATING;break;
|
||||||
|
case 0xC0000000 : mem_flag |=MEM_FLAG_DIRECT;break;
|
||||||
|
default: dbg_printf(0,"Unknown Raspberry architecture\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dma::~dma()
|
dma::~dma()
|
||||||
|
|
200
src/fskburst.cpp
200
src/fskburst.cpp
|
@ -20,108 +20,124 @@ This program is free software: you can redistribute it and/or modify
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
fskburst::fskburst(uint64_t TuneFrequency,uint32_t SymbolRate,float Deviation,int Channel,uint32_t FifoSize):bufferdma(Channel,FifoSize+3,2,1),freqdeviation(Deviation)
|
fskburst::fskburst(uint64_t TuneFrequency, float SymbolRate, float Deviation, int Channel, uint32_t FifoSize, size_t upsample,float RatioRamp) : bufferdma(Channel, FifoSize * upsample + 3, 2, 1), freqdeviation(Deviation), SR_upsample(upsample)
|
||||||
{
|
|
||||||
|
|
||||||
clkgpio::SetAdvancedPllMode(true);
|
|
||||||
clkgpio::SetCenterFrequency(TuneFrequency,SymbolRate); // Write Mult Int and Frac : FixMe carrier is already there
|
|
||||||
clkgpio::SetFrequency(0);
|
|
||||||
disableclk(4);
|
|
||||||
syncwithpwm=false;
|
|
||||||
|
|
||||||
if(syncwithpwm)
|
|
||||||
{
|
|
||||||
pwmgpio::SetPllNumber(clk_plld,1);
|
|
||||||
pwmgpio::SetFrequency(SymbolRate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pcmgpio::SetPllNumber(clk_plld,1);
|
|
||||||
pcmgpio::SetFrequency(SymbolRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Should be obligatory place before setdmaalgo
|
|
||||||
Originfsel=clkgpio::gengpio.gpioreg[GPFSEL0];
|
|
||||||
dbg_printf(1,"FSK Origin fsel %x\n",Originfsel);
|
|
||||||
|
|
||||||
SetDmaAlgo();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fskburst::~fskburst()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void fskburst::SetDmaAlgo()
|
|
||||||
{
|
{
|
||||||
|
|
||||||
sampletab[buffersize*registerbysample-2]=(Originfsel & ~(7 << 12)) | (4 << 12); //Gpio Clk
|
|
||||||
sampletab[buffersize*registerbysample-1]=(Originfsel & ~(7 << 12)) | (0 << 12); //Gpio In
|
|
||||||
|
|
||||||
dma_cb_t *cbp = cbarray;
|
clkgpio::SetAdvancedPllMode(true);
|
||||||
// We must fill the FIFO (PWM or PCM) to be Synchronized from start
|
clkgpio::SetCenterFrequency(TuneFrequency, Deviation*10); // Write Mult Int and Frac : FixMe carrier is already there
|
||||||
// PWM FIFO = 16
|
clkgpio::SetFrequency(0);
|
||||||
// PCM FIFO = 64
|
disableclk(4);
|
||||||
if(syncwithpwm)
|
syncwithpwm = false;
|
||||||
{
|
Ramp = SR_upsample * RatioRamp; //Ramp time = 10%
|
||||||
SetEasyCB(cbp++,0,dma_pwm,16+1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetEasyCB(cbp++,0,dma_pcm,64+1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
SetEasyCB(cbp++,buffersize*registerbysample-2,dma_fsel,1);//Enable clk
|
if (syncwithpwm)
|
||||||
|
|
||||||
|
|
||||||
for (uint32_t samplecnt = 0; samplecnt < buffersize-2; samplecnt++)
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
// Write a frequency sample
|
|
||||||
SetEasyCB(cbp++,samplecnt*registerbysample,dma_pllc_frac,1);//FReq
|
|
||||||
|
|
||||||
// Delay
|
|
||||||
SetEasyCB(cbp++,samplecnt*registerbysample,syncwithpwm?dma_pwm:dma_pcm,1);
|
|
||||||
|
|
||||||
}
|
|
||||||
lastcbp=cbp;
|
|
||||||
|
|
||||||
SetEasyCB(cbp,buffersize*registerbysample-1,dma_fsel,1);//Disable clk
|
|
||||||
|
|
||||||
cbp->next = 0; // Stop DMA
|
|
||||||
|
|
||||||
dbg_printf(2,"Last cbp : src %x dest %x next %x\n",cbp->src,cbp->dst,cbp->next);
|
|
||||||
}
|
|
||||||
void fskburst::SetSymbols(unsigned char *Symbols,uint32_t Size)
|
|
||||||
{
|
{
|
||||||
if(Size>buffersize-3) {dbg_printf(1,"Buffer overflow\n");return;}
|
pwmgpio::SetPllNumber(clk_plld, 1);
|
||||||
|
pwmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
|
||||||
dma_cb_t *cbp=cbarray;
|
}
|
||||||
cbp+=2; // Skip the first 2 CB (initialisation)
|
else
|
||||||
for(unsigned int i=0;i<Size;i++)
|
{
|
||||||
|
pcmgpio::SetPllNumber(clk_plld, 1);
|
||||||
|
pcmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Should be obligatory place before setdmaalgo
|
||||||
|
Originfsel = clkgpio::gengpio.gpioreg[GPFSEL0];
|
||||||
|
dbg_printf(1, "FSK Origin fsel %x\n", Originfsel);
|
||||||
|
|
||||||
|
SetDmaAlgo();
|
||||||
|
}
|
||||||
|
|
||||||
|
fskburst::~fskburst()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fskburst::SetDmaAlgo()
|
||||||
|
{
|
||||||
|
|
||||||
|
sampletab[buffersize * registerbysample - 2] = (Originfsel & ~(7 << 12)) | (4 << 12); //Gpio Clk
|
||||||
|
sampletab[buffersize * registerbysample - 1] = (Originfsel & ~(7 << 12)) | (0 << 12); //Gpio In
|
||||||
|
|
||||||
|
dma_cb_t *cbp = cbarray;
|
||||||
|
// We must fill the FIFO (PWM or PCM) to be Synchronized from start
|
||||||
|
// PWM FIFO = 16
|
||||||
|
// PCM FIFO = 64
|
||||||
|
if (syncwithpwm)
|
||||||
|
{
|
||||||
|
SetEasyCB(cbp++, 0, dma_pwm, 16 + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetEasyCB(cbp++, 0, dma_pcm, 64 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetEasyCB(cbp++, buffersize * registerbysample - 2, dma_fsel, 1); //Enable clk
|
||||||
|
|
||||||
|
for (uint32_t samplecnt = 0; samplecnt < buffersize - 2; samplecnt++)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Write a frequency sample
|
||||||
|
SetEasyCB(cbp++, samplecnt * registerbysample, dma_pllc_frac, 1); //FReq
|
||||||
|
|
||||||
|
// Delay
|
||||||
|
SetEasyCB(cbp++, samplecnt * registerbysample, syncwithpwm ? dma_pwm : dma_pcm, 1);
|
||||||
|
}
|
||||||
|
lastcbp = cbp;
|
||||||
|
|
||||||
|
SetEasyCB(cbp, buffersize * registerbysample - 1, dma_fsel, 1); //Disable clk
|
||||||
|
|
||||||
|
cbp->next = 0; // Stop DMA
|
||||||
|
|
||||||
|
dbg_printf(2, "Last cbp : src %x dest %x next %x\n", cbp->src, cbp->dst, cbp->next);
|
||||||
|
}
|
||||||
|
void fskburst::SetSymbols(unsigned char *Symbols, uint32_t Size)
|
||||||
|
{
|
||||||
|
if (Size > buffersize - 3)
|
||||||
|
{
|
||||||
|
dbg_printf(1, "Buffer overflow\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_cb_t *cbp = cbarray;
|
||||||
|
cbp += 2; // Skip the first 2 CB (initialisation)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < Size; i++)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < SR_upsample - Ramp; j++)
|
||||||
{
|
{
|
||||||
sampletab[i]=(0x5A<<24)|GetMasterFrac(freqdeviation*Symbols[i]);
|
sampletab[i * SR_upsample + j] = (0x5A << 24) | GetMasterFrac(freqdeviation * Symbols[i]);
|
||||||
cbp++;//SKIP FREQ CB
|
cbp++; //SKIP FREQ CB
|
||||||
cbp->next = mem_virt_to_phys(cbp + 1);
|
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||||
cbp++;
|
cbp++;
|
||||||
}
|
}
|
||||||
cbp--;
|
for (size_t j = 0 ; j < Ramp; j++)
|
||||||
cbp->next = mem_virt_to_phys(lastcbp);
|
|
||||||
|
|
||||||
|
|
||||||
dma::start();
|
|
||||||
while(isrunning()) //Block function : return until sent completely signal
|
|
||||||
{
|
{
|
||||||
//dbg_printf(1,"GPIO %x\n",clkgpio::gengpio.gpioreg[GPFSEL0]);
|
if (i < Size - 1)
|
||||||
usleep(100);
|
{
|
||||||
|
sampletab[i * SR_upsample + j + SR_upsample - Ramp] = (0x5A << 24) | GetMasterFrac(freqdeviation * Symbols[i] + j* (freqdeviation * Symbols[i + 1] - freqdeviation * Symbols[i]) / (float)Ramp);
|
||||||
|
dbg_printf(2, "Ramp %f ->%f : %d %f\n",freqdeviation * Symbols[i],freqdeviation * Symbols[i+1], j,freqdeviation * Symbols[i] + j* (freqdeviation * Symbols[i + 1] - freqdeviation * Symbols[i]) / (float)Ramp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sampletab[i * SR_upsample + j + SR_upsample -Ramp] = (0x5A << 24) | GetMasterFrac(freqdeviation * Symbols[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
cbp++; //SKIP FREQ CB
|
||||||
|
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||||
|
cbp++;
|
||||||
}
|
}
|
||||||
dbg_printf(1,"FSK burst end Tx\n",cbp->src,cbp->dst,cbp->next);
|
|
||||||
usleep(100);//To be sure last symbol Tx ?
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
cbp--;
|
||||||
|
cbp->next = mem_virt_to_phys(lastcbp);
|
||||||
|
|
||||||
|
dma::start();
|
||||||
|
while (isrunning()) //Block function : return until sent completely signal
|
||||||
|
{
|
||||||
|
//dbg_printf(1,"GPIO %x\n",clkgpio::gengpio.gpioreg[GPFSEL0]);
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
dbg_printf(1, "FSK burst end Tx\n", cbp->src, cbp->dst, cbp->next);
|
||||||
|
usleep(100); //To be sure last symbol Tx ?
|
||||||
|
}
|
||||||
|
|
|
@ -12,8 +12,10 @@ class fskburst:public bufferdma,public clkgpio,public pwmgpio,public pcmgpio
|
||||||
uint32_t Originfsel;
|
uint32_t Originfsel;
|
||||||
bool syncwithpwm;
|
bool syncwithpwm;
|
||||||
dma_cb_t *lastcbp;
|
dma_cb_t *lastcbp;
|
||||||
|
size_t SR_upsample=0;
|
||||||
|
size_t Ramp=0;
|
||||||
public:
|
public:
|
||||||
fskburst(uint64_t TuneFrequency,uint32_t SymbolRate,float Deviation,int Channel,uint32_t FifoSize);
|
fskburst(uint64_t TuneFrequency,float SymbolRate,float Deviation,int Channel,uint32_t FifoSize,size_t upsample=1,float RatioRamp=0);
|
||||||
~fskburst();
|
~fskburst();
|
||||||
void SetDmaAlgo();
|
void SetDmaAlgo();
|
||||||
|
|
||||||
|
|
219
src/gpio.cpp
219
src/gpio.cpp
|
@ -24,12 +24,15 @@ extern "C" {
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/timex.h>
|
#include <sys/timex.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "rpi.h"
|
||||||
|
|
||||||
gpio::gpio(uint32_t base, uint32_t len)
|
gpio::gpio(uint32_t base, uint32_t len)
|
||||||
{
|
{
|
||||||
|
|
||||||
gpioreg = (uint32_t *)mapmem(base, len);
|
|
||||||
|
gpioreg = (uint32_t *)mapmem(GetPeripheralBase()+base, len);
|
||||||
gpiolen=len;
|
gpiolen=len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,33 +42,85 @@ gpio::~gpio()
|
||||||
unmapmem((void*)gpioreg,gpiolen);
|
unmapmem((void*)gpioreg,gpiolen);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t get_hwbase(void)
|
||||||
|
{
|
||||||
|
const char *ranges_file = "/proc/device-tree/soc/ranges";
|
||||||
|
uint8_t ranges[12];
|
||||||
|
FILE *fd;
|
||||||
|
uint32_t ret = 0;
|
||||||
|
|
||||||
|
memset(ranges, 0, sizeof(ranges));
|
||||||
|
|
||||||
|
if ((fd = fopen(ranges_file, "rb")) == NULL)
|
||||||
|
{
|
||||||
|
printf("Can't open '%s'\n", ranges_file);
|
||||||
|
}
|
||||||
|
else if (fread(ranges, 1, sizeof(ranges), fd) >= 8)
|
||||||
|
{
|
||||||
|
ret = (ranges[4] << 24) |
|
||||||
|
(ranges[5] << 16) |
|
||||||
|
(ranges[6] << 8) |
|
||||||
|
(ranges[7] << 0);
|
||||||
|
if (!ret)
|
||||||
|
ret = (ranges[8] << 24) |
|
||||||
|
(ranges[9] << 16) |
|
||||||
|
(ranges[10] << 8) |
|
||||||
|
(ranges[11] << 0);
|
||||||
|
if ((ranges[0] != 0x7e) ||
|
||||||
|
(ranges[1] != 0x00) ||
|
||||||
|
(ranges[2] != 0x00) ||
|
||||||
|
(ranges[3] != 0x00) ||
|
||||||
|
((ret != 0x20000000) && (ret != 0x3f000000) && (ret != 0xfe000000)))
|
||||||
|
{
|
||||||
|
printf("Unexpected ranges data (%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x)\n",
|
||||||
|
ranges[0], ranges[1], ranges[2], ranges[3],
|
||||||
|
ranges[4], ranges[5], ranges[6], ranges[7],
|
||||||
|
ranges[8], ranges[9], ranges[10], ranges[11]);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Ranges data too short\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t gpio::GetPeripheralBase()
|
uint32_t gpio::GetPeripheralBase()
|
||||||
{
|
{
|
||||||
RASPBERRY_PI_INFO_T info;
|
RASPBERRY_PI_INFO_T info;
|
||||||
uint32_t BCM2708_PERI_BASE = 0;
|
uint32_t BCM2708_PERI_BASE =bcm_host_get_peripheral_address();
|
||||||
if (getRaspberryPiInformation(&info) > 0)
|
dbg_printf(0,"Peri Base = %x SDRAM %x\n",/*get_hwbase()*/bcm_host_get_peripheral_address(),bcm_host_get_sdram_address());
|
||||||
|
if(BCM2708_PERI_BASE==0xFE000000) // Fixme , could be inspect without this hardcoded value
|
||||||
{
|
{
|
||||||
if (info.peripheralBase == RPI_BROADCOM_2835_PERIPHERAL_BASE)
|
dbg_printf(0,"RPi4 GPIO detected\n");
|
||||||
{
|
pi_is_2711=true; //Rpi4
|
||||||
BCM2708_PERI_BASE = info.peripheralBase;
|
XOSC_FREQUENCY=54000000;
|
||||||
}
|
|
||||||
|
|
||||||
if ((info.peripheralBase == RPI_BROADCOM_2836_PERIPHERAL_BASE) || (info.peripheralBase == RPI_BROADCOM_2837_PERIPHERAL_BASE))
|
|
||||||
{
|
|
||||||
BCM2708_PERI_BASE = info.peripheralBase;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if(BCM2708_PERI_BASE==0)
|
||||||
|
{
|
||||||
|
dbg_printf(0,"Unknown peripheral base, switch to PI4 \n");
|
||||||
|
BCM2708_PERI_BASE=0xfe000000;
|
||||||
|
XOSC_FREQUENCY=54000000;
|
||||||
|
pi_is_2711=true;
|
||||||
|
}
|
||||||
|
if(pi_is_2711)
|
||||||
|
dbg_printf(1,"Running on Pi4\n");
|
||||||
return BCM2708_PERI_BASE;
|
return BCM2708_PERI_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//******************** DMA Registers ***************************************
|
//******************** DMA Registers ***************************************
|
||||||
|
|
||||||
dmagpio::dmagpio() : gpio(GetPeripheralBase() + DMA_BASE, DMA_LEN)
|
dmagpio::dmagpio() : gpio( DMA_BASE, DMA_LEN)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// ***************** CLK Registers *****************************************
|
// ***************** CLK Registers *****************************************
|
||||||
clkgpio::clkgpio() : gpio(GetPeripheralBase() + CLK_BASE, CLK_LEN)
|
clkgpio::clkgpio() : gpio(CLK_BASE, CLK_LEN)
|
||||||
{
|
{
|
||||||
SetppmFromNTP();
|
SetppmFromNTP();
|
||||||
padgpio level;
|
padgpio level;
|
||||||
|
@ -81,7 +136,7 @@ clkgpio::~clkgpio()
|
||||||
|
|
||||||
int clkgpio::SetPllNumber(int PllNo, int MashType)
|
int clkgpio::SetPllNumber(int PllNo, int MashType)
|
||||||
{
|
{
|
||||||
//print_clock_tree();
|
print_clock_tree();
|
||||||
if (PllNo < 8)
|
if (PllNo < 8)
|
||||||
pllnumber = PllNo;
|
pllnumber = PllNo;
|
||||||
else
|
else
|
||||||
|
@ -109,21 +164,26 @@ uint64_t clkgpio::GetPllFrequency(int PllNo)
|
||||||
Freq = XOSC_FREQUENCY;
|
Freq = XOSC_FREQUENCY;
|
||||||
break;
|
break;
|
||||||
case clk_plla:
|
case clk_plla:
|
||||||
Freq = XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLA_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLA_FRAC] / (1 << 20);
|
Freq = (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLA_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLA_FRAC] / (1 << 20))/(2*(gpioreg[PLLA_CTRL] >> 12)&0x7);
|
||||||
break;
|
break;
|
||||||
//case clk_pllb:Freq=XOSC_FREQUENCY*((uint64_t)gpioreg[PLLB_CTRL]&0x3ff) +XOSC_FREQUENCY*(uint64_t)gpioreg[PLLB_FRAC]/(1<<20);break;
|
//case clk_pllb:Freq=XOSC_FREQUENCY*((uint64_t)gpioreg[PLLB_CTRL]&0x3ff) +XOSC_FREQUENCY*(uint64_t)gpioreg[PLLB_FRAC]/(1<<20);break;
|
||||||
case clk_pllc:
|
case clk_pllc:
|
||||||
Freq = XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLC_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLC_FRAC] / (1 << 20);
|
//Freq = (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLC_CTRL] & 0x3ff) + (XOSC_FREQUENCY * (uint64_t)gpioreg[PLLC_FRAC]) / (1 << 20)) / (2*gpioreg[PLLC_PER] >> 1)) /((gpioreg[PLLC_CTRL] >> 12)&0x7) ;
|
||||||
|
//dbg_printf(1, "Gpio reg %x %x\n",gpioreg[PLLC_PER],gpioreg[PLLC_CTRL] >> 12);
|
||||||
|
if((gpioreg[PLLC_PER]!=0)&&(gpioreg[PLLC_CTRL] >> 12 != 0))
|
||||||
|
Freq =( (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLC_CTRL] & 0x3ff) + (XOSC_FREQUENCY * (uint64_t)gpioreg[PLLC_FRAC]) / (1 << 20)) / (2*gpioreg[PLLC_PER] >> 1))/((gpioreg[PLLC_CTRL] >> 12)&0x7) ;
|
||||||
break;
|
break;
|
||||||
case clk_plld:
|
case clk_plld:
|
||||||
Freq = (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLD_CTRL] & 0x3ff) + (XOSC_FREQUENCY * (uint64_t)gpioreg[PLLD_FRAC]) / (1 << 20)) / (gpioreg[PLLD_PER] >> 1);
|
Freq =( (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLD_CTRL] & 0x3ff) + (XOSC_FREQUENCY * (uint64_t)gpioreg[PLLD_FRAC]) / (1 << 20)) / (2*gpioreg[PLLD_PER] >> 1))/((gpioreg[PLLD_CTRL] >> 12)&0x7) ;
|
||||||
break;
|
break;
|
||||||
case clk_hdmi:
|
case clk_hdmi:
|
||||||
Freq = XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLH_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLH_FRAC] / (1 << 20);
|
Freq =( XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLH_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLH_FRAC] / (1 << 20))/(2*(gpioreg[PLLH_CTRL] >> 12)&0x7) ;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(!pi_is_2711) // FixMe : Surely a register which say it is a 2x
|
||||||
|
Freq*=2LL;
|
||||||
Freq=Freq*(1.0-clk_ppm*1e-6);
|
Freq=Freq*(1.0-clk_ppm*1e-6);
|
||||||
dbg_printf(1, "Freq PLL no %d= %llu\n",PllNo, Freq);
|
dbg_printf(1, "Pi4=%d Xosc = %llu Freq PLL no %d= %llu\n",pi_is_2711,XOSC_FREQUENCY,PllNo, Freq);
|
||||||
|
|
||||||
return Freq;
|
return Freq;
|
||||||
}
|
}
|
||||||
|
@ -157,9 +217,26 @@ int clkgpio::SetFrequency(double Frequency)
|
||||||
|
|
||||||
double FloatMult=0;
|
double FloatMult=0;
|
||||||
if(PllFixDivider==1) //Using PDIV thus frequency/2
|
if(PllFixDivider==1) //Using PDIV thus frequency/2
|
||||||
FloatMult = ((double)(CentralFrequency + Frequency) ) / ((double)(XOSC_FREQUENCY*2) * (1 - clk_ppm * 1e-6));
|
{
|
||||||
|
if(pi_is_2711)
|
||||||
|
FloatMult = ((double)(CentralFrequency + Frequency)*2 ) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FloatMult = ((double)(CentralFrequency + Frequency) ) / ((double)(XOSC_FREQUENCY*2) * (1 - clk_ppm * 1e-6));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
FloatMult = ((double)(CentralFrequency + Frequency)*PllFixDivider ) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6));
|
{
|
||||||
|
if(pi_is_2711)
|
||||||
|
FloatMult = ((double)(CentralFrequency + Frequency)*PllFixDivider*2 ) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FloatMult = ((double)(CentralFrequency + Frequency)*PllFixDivider ) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t freqctl = FloatMult * ((double)(1 << 20));
|
uint32_t freqctl = FloatMult * ((double)(1 << 20));
|
||||||
int IntMultiply = freqctl >> 20; // Need to be calculated to have a center frequency
|
int IntMultiply = freqctl >> 20; // Need to be calculated to have a center frequency
|
||||||
freqctl &= 0xFFFFF; // Fractionnal is 20bits
|
freqctl &= 0xFFFFF; // Fractionnal is 20bits
|
||||||
|
@ -187,10 +264,26 @@ uint32_t clkgpio::GetMasterFrac(double Frequency)
|
||||||
if (ModulateFromMasterPLL)
|
if (ModulateFromMasterPLL)
|
||||||
{
|
{
|
||||||
double FloatMult=0;
|
double FloatMult=0;
|
||||||
if(PllFixDivider==1) //Using PDIV thus frequency/2
|
if((PllFixDivider==1))//There is no Prediv on Pi4 //Using PDIV thus frequency/2
|
||||||
FloatMult = ((double)(CentralFrequency + Frequency) ) / ((double)(XOSC_FREQUENCY*2) * (1 - clk_ppm * 1e-6));
|
{
|
||||||
|
if(pi_is_2711) // No PDIV on pi4
|
||||||
|
FloatMult = ((double)(CentralFrequency + Frequency)*2 ) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FloatMult = ((double)(CentralFrequency + Frequency) ) / ((double)(XOSC_FREQUENCY*2) * (1 - clk_ppm * 1e-6));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
FloatMult = ((double)(CentralFrequency + Frequency)*PllFixDivider ) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6));
|
{
|
||||||
|
if(pi_is_2711)
|
||||||
|
FloatMult = ((double)(CentralFrequency + Frequency)*PllFixDivider*2 ) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FloatMult = ((double)(CentralFrequency + Frequency)*PllFixDivider ) / ((double)(XOSC_FREQUENCY) * (1 - clk_ppm * 1e-6));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
uint32_t freqctl = FloatMult * ((double)(1 << 20));
|
uint32_t freqctl = FloatMult * ((double)(1 << 20));
|
||||||
int IntMultiply = freqctl >> 20; // Need to be calculated to have a center frequency
|
int IntMultiply = freqctl >> 20; // Need to be calculated to have a center frequency
|
||||||
freqctl &= 0xFFFFF; // Fractionnal is 20bits
|
freqctl &= 0xFFFFF; // Fractionnal is 20bits
|
||||||
|
@ -212,7 +305,8 @@ int clkgpio::ComputeBestLO(uint64_t Frequency, int Bandwidth)
|
||||||
#define MIN_PLL_RATE 200e6
|
#define MIN_PLL_RATE 200e6
|
||||||
#define MIN_PLL_RATE_USE_PDIV 1500e6 //1700 works but some ticky breaks in clock..PLL should be at limit
|
#define MIN_PLL_RATE_USE_PDIV 1500e6 //1700 works but some ticky breaks in clock..PLL should be at limit
|
||||||
#define MAX_PLL_RATE 4e9
|
#define MAX_PLL_RATE 4e9
|
||||||
#define XTAL_RATE 19.2e6
|
#define XTAL_RATE XOSC_FREQUENCY
|
||||||
|
//Pi4 seems 54Mhz
|
||||||
double xtal_freq_recip = 1.0 / XTAL_RATE; // todo PPM correction
|
double xtal_freq_recip = 1.0 / XTAL_RATE; // todo PPM correction
|
||||||
int best_divider = 0;
|
int best_divider = 0;
|
||||||
|
|
||||||
|
@ -222,6 +316,8 @@ int clkgpio::ComputeBestLO(uint64_t Frequency, int Bandwidth)
|
||||||
double Multiplier=0.0;
|
double Multiplier=0.0;
|
||||||
best_divider = 0;
|
best_divider = 0;
|
||||||
bool cross_boundary=false;
|
bool cross_boundary=false;
|
||||||
|
|
||||||
|
|
||||||
if(Frequency<MIN_PLL_RATE/4095)
|
if(Frequency<MIN_PLL_RATE/4095)
|
||||||
{
|
{
|
||||||
dbg_printf(1, "Frequency too low !!!!!!\n");
|
dbg_printf(1, "Frequency too low !!!!!!\n");
|
||||||
|
@ -268,6 +364,7 @@ int clkgpio::ComputeBestLO(uint64_t Frequency, int Bandwidth)
|
||||||
if (best_divider!=0)
|
if (best_divider!=0)
|
||||||
{
|
{
|
||||||
PllFixDivider = best_divider;
|
PllFixDivider = best_divider;
|
||||||
|
|
||||||
if(cross_boundary) dbg_printf(1,"Warning : cross boundary frequency\n");
|
if(cross_boundary) dbg_printf(1,"Warning : cross boundary frequency\n");
|
||||||
dbg_printf(1, "Found PLL solution for frequency %4.1fMHz : divider:%d VCO: %4.1fMHz\n", (Frequency/1e6), PllFixDivider,(Frequency/1e6) *((PllFixDivider==1)?2.0:(double)PllFixDivider));
|
dbg_printf(1, "Found PLL solution for frequency %4.1fMHz : divider:%d VCO: %4.1fMHz\n", (Frequency/1e6), PllFixDivider,(Frequency/1e6) *((PllFixDivider==1)?2.0:(double)PllFixDivider));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -312,15 +409,24 @@ int clkgpio::SetCenterFrequency(uint64_t Frequency, int Bandwidth)
|
||||||
if (ModulateFromMasterPLL)
|
if (ModulateFromMasterPLL)
|
||||||
{
|
{
|
||||||
//Choose best PLLDiv and Div
|
//Choose best PLLDiv and Div
|
||||||
ComputeBestLO(Frequency, Bandwidth); //FixeDivider update
|
|
||||||
|
|
||||||
|
if(pi_is_2711)
|
||||||
|
{
|
||||||
|
ComputeBestLO(Frequency*2, Bandwidth); //FixeDivider update
|
||||||
|
//PllFixDivider=PllFixDivider/2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ComputeBestLO(Frequency, Bandwidth); //FixeDivider update
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(PllFixDivider==1)
|
if(PllFixDivider==1)
|
||||||
{
|
{
|
||||||
//We will use PDIV by 2, means like we have a 2 times more
|
//We will use PDIV by 2, means like we have a 2 times more
|
||||||
SetClkDivFrac(2, 0x0); // NO MASH !!!!
|
SetClkDivFrac(2, 0x0); // NO MASH !!!!
|
||||||
|
dbg_printf(1, "Pll Fix Divider\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -346,7 +452,7 @@ int clkgpio::SetCenterFrequency(uint64_t Frequency, int Bandwidth)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ana[1]|=(0<<14); // No use prediv means Frequency
|
ana[1]|=(0<<14); // No use prediv means Frequenc
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* ANA register setup is done as a series of writes to
|
* ANA register setup is done as a series of writes to
|
||||||
|
@ -402,6 +508,7 @@ void clkgpio::SetPhase(bool inversed)
|
||||||
clkgpio::gpioreg[GPCLK_CNTL] = (0x5A << 24) | StateBefore | ((inversed ? 1 : 0) << 8) | 0 << 5;
|
clkgpio::gpioreg[GPCLK_CNTL] = (0x5A << 24) | StateBefore | ((inversed ? 1 : 0) << 8) | 0 << 5;
|
||||||
//clkgpio::gpioreg[GPCLK_CNTL_2] = (0x5A << 24) | StateBefore | ((inversed ? 1 : 0) << 8) | 0 << 5;
|
//clkgpio::gpioreg[GPCLK_CNTL_2] = (0x5A << 24) | StateBefore | ((inversed ? 1 : 0) << 8) | 0 << 5;
|
||||||
}
|
}
|
||||||
|
//https://elinux.org/The_Undocumented_Pi
|
||||||
//Should inspect https://github.com/raspberrypi/linux/blob/ffd7bf4085b09447e5db96edd74e524f118ca3fe/drivers/clk/bcm/clk-bcm2835.c#L695
|
//Should inspect https://github.com/raspberrypi/linux/blob/ffd7bf4085b09447e5db96edd74e524f118ca3fe/drivers/clk/bcm/clk-bcm2835.c#L695
|
||||||
void clkgpio::SetAdvancedPllMode(bool Advanced)
|
void clkgpio::SetAdvancedPllMode(bool Advanced)
|
||||||
{
|
{
|
||||||
|
@ -432,7 +539,14 @@ void clkgpio::SetAdvancedPllMode(bool Advanced)
|
||||||
|
|
||||||
|
|
||||||
gpioreg[PLLC_CORE0] = 0x5A000000|(1<<8);//Disable
|
gpioreg[PLLC_CORE0] = 0x5A000000|(1<<8);//Disable
|
||||||
gpioreg[PLLC_PER] = 0x5A000001; // Divisor
|
if(pi_is_2711)
|
||||||
|
gpioreg[PLLC_PER] = 0x5A000002; // Divisor by 2 (1 seems not working on pi4)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gpioreg[PLLC_PER] = 0x5A000001; // Divisor 1 for max frequence
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
usleep(100);
|
usleep(100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,24 +649,25 @@ void clkgpio::print_clock_tree(void)
|
||||||
|
|
||||||
// Sometimes calculated frequencies are off by a factor of 2
|
// Sometimes calculated frequencies are off by a factor of 2
|
||||||
// ANA1 bit 14 may indicate that a /2 prescaler is active
|
// ANA1 bit 14 may indicate that a /2 prescaler is active
|
||||||
|
double xoscmhz=XOSC_FREQUENCY/1e6;
|
||||||
printf("PLLA PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLA_CTRL] >> 12)&0x7, gpioreg[PLLA_CTRL] & 0x3ff, gpioreg[PLLA_FRAC]);
|
printf("PLLA PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLA_CTRL] >> 12)&0x7, gpioreg[PLLA_CTRL] & 0x3ff, gpioreg[PLLA_FRAC]);
|
||||||
printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLA_CTRL] & 0x3ff) + ((float)gpioreg[PLLA_FRAC]) / ((float)(1 << 20))));
|
printf(" %f MHz\n", xoscmhz * ((float)(gpioreg[PLLA_CTRL] & 0x3ff) + ((float)gpioreg[PLLA_FRAC]) / ((float)(1 << 20))));
|
||||||
printf("DSI0=%d CORE=%d PER=%d CCP2=%d\n\n", gpioreg[PLLA_DSI0], gpioreg[PLLA_CORE], gpioreg[PLLA_PER], gpioreg[PLLA_CCP2]);
|
printf("DSI0=%d CORE=%d PER=%d CCP2=%d\n\n", gpioreg[PLLA_DSI0], gpioreg[PLLA_CORE], gpioreg[PLLA_PER], gpioreg[PLLA_CCP2]);
|
||||||
|
|
||||||
printf("PLLB PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLB_CTRL] >> 12)&0x7, gpioreg[PLLB_CTRL] & 0x3ff, gpioreg[PLLB_FRAC]);
|
printf("PLLB PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLB_CTRL] >> 12)&0x7, gpioreg[PLLB_CTRL] & 0x3ff, gpioreg[PLLB_FRAC]);
|
||||||
printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLB_CTRL] & 0x3ff) + ((float)gpioreg[PLLB_FRAC]) / ((float)(1 << 20))));
|
printf(" %f MHz\n", xoscmhz * ((float)(gpioreg[PLLB_CTRL] & 0x3ff) + ((float)gpioreg[PLLB_FRAC]) / ((float)(1 << 20))));
|
||||||
printf("ARM=%d SP0=%d SP1=%d SP2=%d\n\n", gpioreg[PLLB_ARM], gpioreg[PLLB_SP0], gpioreg[PLLB_SP1], gpioreg[PLLB_SP2]);
|
printf("ARM=%d SP0=%d SP1=%d SP2=%d\n\n", gpioreg[PLLB_ARM], gpioreg[PLLB_SP0], gpioreg[PLLB_SP1], gpioreg[PLLB_SP2]);
|
||||||
|
|
||||||
printf("PLLC PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLC_CTRL] >> 12)&0x7, gpioreg[PLLC_CTRL] & 0x3ff, gpioreg[PLLC_FRAC]);
|
printf("PLLC PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLC_CTRL] >> 12)&0x7, gpioreg[PLLC_CTRL] & 0x3ff, gpioreg[PLLC_FRAC]);
|
||||||
printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLC_CTRL] & 0x3ff) + ((float)gpioreg[PLLC_FRAC]) / ((float)(1 << 20))));
|
printf(" %f MHz\n", xoscmhz * ((float)(gpioreg[PLLC_CTRL] & 0x3ff) + ((float)gpioreg[PLLC_FRAC]) / ((float)(1 << 20))));
|
||||||
printf("CORE2=%d CORE1=%d PER=%d CORE0=%d\n\n", gpioreg[PLLC_CORE2], gpioreg[PLLC_CORE1], gpioreg[PLLC_PER], gpioreg[PLLC_CORE0]);
|
printf("CORE2=%d CORE1=%d PER=%d CORE0=%d\n\n", gpioreg[PLLC_CORE2], gpioreg[PLLC_CORE1], gpioreg[PLLC_PER], gpioreg[PLLC_CORE0]);
|
||||||
|
|
||||||
printf("PLLD %x PDIV=%d NDIV=%d FRAC=%d ", gpioreg[PLLD_CTRL], (gpioreg[PLLD_CTRL] >> 12)&0x7, gpioreg[PLLD_CTRL] & 0x3ff, gpioreg[PLLD_FRAC]);
|
printf("PLLD %x PDIV=%d NDIV=%d FRAC=%d ", gpioreg[PLLD_CTRL], (gpioreg[PLLD_CTRL] >> 12)&0x7, gpioreg[PLLD_CTRL] & 0x3ff, gpioreg[PLLD_FRAC]);
|
||||||
printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLD_CTRL] & 0x3ff) + ((float)gpioreg[PLLD_FRAC]) / ((float)(1 << 20))));
|
printf(" %f MHz\n", xoscmhz * ((float)(gpioreg[PLLD_CTRL] & 0x3ff) + ((float)gpioreg[PLLD_FRAC]) / ((float)(1 << 20))));
|
||||||
printf("DSI0=%d CORE=%d PER=%d DSI1=%d\n\n", gpioreg[PLLD_DSI0], gpioreg[PLLD_CORE], gpioreg[PLLD_PER], gpioreg[PLLD_DSI1]);
|
printf("DSI0=%d CORE=%d PER=%d DSI1=%d\n\n", gpioreg[PLLD_DSI0], gpioreg[PLLD_CORE], gpioreg[PLLD_PER], gpioreg[PLLD_DSI1]);
|
||||||
|
|
||||||
printf("PLLH PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLH_CTRL] >> 12)&0x7, gpioreg[PLLH_CTRL] & 0x3ff, gpioreg[PLLH_FRAC]);
|
printf("PLLH PDIV=%d NDIV=%d FRAC=%d ", (gpioreg[PLLH_CTRL] >> 12)&0x7, gpioreg[PLLH_CTRL] & 0x3ff, gpioreg[PLLH_FRAC]);
|
||||||
printf(" %f MHz\n", 19.2 * ((float)(gpioreg[PLLH_CTRL] & 0x3ff) + ((float)gpioreg[PLLH_FRAC]) / ((float)(1 << 20))));
|
printf(" %f MHz\n", xoscmhz * ((float)(gpioreg[PLLH_CTRL] & 0x3ff) + ((float)gpioreg[PLLH_FRAC]) / ((float)(1 << 20))));
|
||||||
printf("AUX=%d RCAL=%d PIX=%d STS=%d\n\n", gpioreg[PLLH_AUX], gpioreg[PLLH_RCAL], gpioreg[PLLH_PIX], gpioreg[PLLH_STS]);
|
printf("AUX=%d RCAL=%d PIX=%d STS=%d\n\n", gpioreg[PLLH_AUX], gpioreg[PLLH_RCAL], gpioreg[PLLH_PIX], gpioreg[PLLH_STS]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +737,7 @@ void clkgpio::SetppmFromNTP()
|
||||||
|
|
||||||
// ************************************** GENERAL GPIO *****************************************************
|
// ************************************** GENERAL GPIO *****************************************************
|
||||||
|
|
||||||
generalgpio::generalgpio() : gpio(GetPeripheralBase() + GENERAL_BASE, GENERAL_LEN)
|
generalgpio::generalgpio() : gpio(/*GetPeripheralBase() + */GENERAL_BASE, GENERAL_LEN)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,18 +759,32 @@ int generalgpio::setmode(uint32_t gpio, uint32_t mode)
|
||||||
|
|
||||||
int generalgpio::setpulloff(uint32_t gpio)
|
int generalgpio::setpulloff(uint32_t gpio)
|
||||||
{
|
{
|
||||||
gpioreg[GPPUD]=0;
|
if(!pi_is_2711)
|
||||||
usleep(150);
|
{
|
||||||
gpioreg[GPPUDCLK0]=1<<gpio;
|
gpioreg[GPPUD]=0;
|
||||||
usleep(150);
|
usleep(150);
|
||||||
gpioreg[GPPUDCLK0]=0;
|
gpioreg[GPPUDCLK0]=1<<gpio;
|
||||||
|
usleep(150);
|
||||||
|
gpioreg[GPPUDCLK0]=0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t bits;
|
||||||
|
uint32_t pull=0; // 0 OFF, 1 = UP, 2= DOWN
|
||||||
|
int shift = (gpio & 0xf) << 1;
|
||||||
|
bits = gpioreg[GPPUPPDN0 + (gpio>>4)];
|
||||||
|
bits &= ~(3 << shift);
|
||||||
|
bits |= (pull << shift);
|
||||||
|
gpioreg[GPPUPPDN0 + (gpio>>4)] = bits;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ********************************** PWM GPIO **********************************
|
// ********************************** PWM GPIO **********************************
|
||||||
|
|
||||||
pwmgpio::pwmgpio() : gpio(GetPeripheralBase() + PWM_BASE, PWM_LEN)
|
pwmgpio::pwmgpio() : gpio(/*GetPeripheralBase() + */PWM_BASE, PWM_LEN)
|
||||||
{
|
{
|
||||||
|
|
||||||
gpioreg[PWM_CTL] = 0;
|
gpioreg[PWM_CTL] = 0;
|
||||||
|
@ -805,7 +934,7 @@ int pwmgpio::SetPrediv(int predivisor) //Mode should be only for SYNC or a Data
|
||||||
|
|
||||||
// ********************************** PCM GPIO (I2S) **********************************
|
// ********************************** PCM GPIO (I2S) **********************************
|
||||||
|
|
||||||
pcmgpio::pcmgpio() : gpio(GetPeripheralBase() + PCM_BASE, PCM_LEN)
|
pcmgpio::pcmgpio() : gpio(PCM_BASE, PCM_LEN)
|
||||||
{
|
{
|
||||||
gpioreg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block
|
gpioreg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block
|
||||||
}
|
}
|
||||||
|
@ -890,7 +1019,7 @@ int pcmgpio::SetPrediv(int predivisor) //Carefull we use a 10 fixe divisor for n
|
||||||
|
|
||||||
// ********************************** PADGPIO (Amplitude) **********************************
|
// ********************************** PADGPIO (Amplitude) **********************************
|
||||||
|
|
||||||
padgpio::padgpio() : gpio(GetPeripheralBase() + PADS_GPIO, PADS_GPIO_LEN)
|
padgpio::padgpio() : gpio(PADS_GPIO, PADS_GPIO_LEN)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
17
src/gpio.h
17
src/gpio.h
|
@ -7,7 +7,9 @@
|
||||||
|
|
||||||
class gpio
|
class gpio
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
bool pi_is_2711=false;
|
||||||
|
uint64_t XOSC_FREQUENCY=19200000;
|
||||||
public:
|
public:
|
||||||
volatile uint32_t *gpioreg = NULL;
|
volatile uint32_t *gpioreg = NULL;
|
||||||
uint32_t gpiolen;
|
uint32_t gpiolen;
|
||||||
|
@ -57,7 +59,7 @@ class dmagpio : public gpio
|
||||||
//************************************ GENERAL GPIO ***************************************
|
//************************************ GENERAL GPIO ***************************************
|
||||||
|
|
||||||
#define GENERAL_BASE (0x00200000)
|
#define GENERAL_BASE (0x00200000)
|
||||||
#define GENERAL_LEN 0xB4
|
#define GENERAL_LEN 0xD0
|
||||||
|
|
||||||
#define GPFSEL0 (0x00 / 4)
|
#define GPFSEL0 (0x00 / 4)
|
||||||
#define GPFSEL1 (0x04 / 4)
|
#define GPFSEL1 (0x04 / 4)
|
||||||
|
@ -66,6 +68,11 @@ class dmagpio : public gpio
|
||||||
#define GPPUDCLK0 (0x98 / 4)
|
#define GPPUDCLK0 (0x98 / 4)
|
||||||
#define GPPUDCLK1 (0x9C / 4)
|
#define GPPUDCLK1 (0x9C / 4)
|
||||||
|
|
||||||
|
#define GPPUPPDN0 (0xBC/4)
|
||||||
|
#define GPPUPPDN1 (0xC0/4)
|
||||||
|
#define GPPUPPDN2 (0xC4/4)
|
||||||
|
#define GPPUPPDN3 (0xC8/4)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
fsel_input,
|
fsel_input,
|
||||||
|
@ -104,6 +111,8 @@ class generalgpio : public gpio
|
||||||
#define GPCLK_DIV_2 (0x84 / 4)
|
#define GPCLK_DIV_2 (0x84 / 4)
|
||||||
#define EMMCCLK_CNTL (0x1C0 / 4)
|
#define EMMCCLK_CNTL (0x1C0 / 4)
|
||||||
#define EMMCCLK_DIV (0x1C4 / 4)
|
#define EMMCCLK_DIV (0x1C4 / 4)
|
||||||
|
#define CM_EMMC2CTL (0x1d0/4)
|
||||||
|
#define CM_EMMC2DIV (0x1d4/4)
|
||||||
|
|
||||||
#define CM_VPUCTL 0x008
|
#define CM_VPUCTL 0x008
|
||||||
#define CM_VPUDIV 0x00c
|
#define CM_VPUDIV 0x00c
|
||||||
|
@ -246,8 +255,8 @@ class generalgpio : public gpio
|
||||||
#define PLLH_STS (0x1660 / 4)
|
#define PLLH_STS (0x1660 / 4)
|
||||||
|
|
||||||
#define XOSC_CTRL (0x1190 / 4)
|
#define XOSC_CTRL (0x1190 / 4)
|
||||||
#define XOSC_FREQUENCY 19200000
|
//#define XOSC_FREQUENCY 19200000
|
||||||
|
//#define XOSC_FREQUENCY 54000000
|
||||||
//Parent PLL
|
//Parent PLL
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,15 +11,15 @@
|
||||||
|
|
||||||
class iqdmasync:public bufferdma,public clkgpio,public pwmgpio,public pcmgpio
|
class iqdmasync:public bufferdma,public clkgpio,public pwmgpio,public pcmgpio
|
||||||
{
|
{
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint64_t tunefreq;
|
uint64_t tunefreq;
|
||||||
bool syncwithpwm;
|
bool syncwithpwm;
|
||||||
dsp mydsp;
|
dsp mydsp;
|
||||||
int ModeIQ=MODE_IQ;
|
|
||||||
uint32_t Originfsel; //Save the original FSEL GPIO
|
uint32_t Originfsel; //Save the original FSEL GPIO
|
||||||
uint32_t SampleRate;
|
uint32_t SampleRate;
|
||||||
public:
|
public:
|
||||||
|
int ModeIQ=MODE_IQ;
|
||||||
iqdmasync(uint64_t TuneFrequency,uint32_t SR,int Channel,uint32_t FifoSize,int Mode);
|
iqdmasync(uint64_t TuneFrequency,uint32_t SR,int Channel,uint32_t FifoSize,int Mode);
|
||||||
~iqdmasync();
|
~iqdmasync();
|
||||||
void SetDmaAlgo();
|
void SetDmaAlgo();
|
||||||
|
|
251
src/ookburst.cpp
251
src/ookburst.cpp
|
@ -20,139 +20,144 @@ This program is free software: you can redistribute it and/or modify
|
||||||
#include "ookburst.h"
|
#include "ookburst.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
ookburst::ookburst(uint64_t TuneFrequency, float SymbolRate, int Channel, uint32_t FifoSize, size_t upsample, float RatioRamp) : bufferdma(Channel, FifoSize * upsample + 2, 2, 1),SR_upsample(upsample)
|
||||||
ookburst::ookburst(uint64_t TuneFrequency,uint32_t SymbolRate,int Channel,uint32_t FifoSize):bufferdma(Channel,FifoSize+2,2,1)
|
|
||||||
{
|
|
||||||
|
|
||||||
clkgpio::SetAdvancedPllMode(true);
|
|
||||||
|
|
||||||
clkgpio::SetCenterFrequency(TuneFrequency,0); // Bandwidth is 0 because frequency always the same
|
|
||||||
clkgpio::SetFrequency(0);
|
|
||||||
|
|
||||||
syncwithpwm=false;
|
|
||||||
|
|
||||||
if(syncwithpwm)
|
|
||||||
{
|
|
||||||
pwmgpio::SetPllNumber(clk_plld,1);
|
|
||||||
pwmgpio::SetFrequency(SymbolRate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pcmgpio::SetPllNumber(clk_plld,1);
|
|
||||||
pcmgpio::SetFrequency(SymbolRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Originfsel=clkgpio::gengpio.gpioreg[GPFSEL0];
|
|
||||||
SetDmaAlgo();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ookburst::~ookburst()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ookburst::SetDmaAlgo()
|
|
||||||
{
|
{
|
||||||
dma_cb_t *cbp=cbarray;
|
|
||||||
// We must fill the FIFO (PWM or PCM) to be Synchronized from start
|
clkgpio::SetAdvancedPllMode(true);
|
||||||
// PWM FIFO = 16
|
|
||||||
// PCM FIFO = 64
|
clkgpio::SetCenterFrequency(TuneFrequency, 0); // Bandwidth is 0 because frequency always the same
|
||||||
if(syncwithpwm)
|
clkgpio::SetFrequency(0);
|
||||||
|
|
||||||
|
syncwithpwm = false;
|
||||||
|
Ramp = SR_upsample * RatioRamp; //Ramp time
|
||||||
|
|
||||||
|
if (syncwithpwm)
|
||||||
|
{
|
||||||
|
pwmgpio::SetPllNumber(clk_plld, 1);
|
||||||
|
pwmgpio::SetFrequency(SymbolRate * (float)upsample);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pcmgpio::SetPllNumber(clk_plld, 1);
|
||||||
|
pcmgpio::SetFrequency(SymbolRate * float(upsample));
|
||||||
|
}
|
||||||
|
|
||||||
|
Originfsel = clkgpio::gengpio.gpioreg[GPFSEL0];
|
||||||
|
SetDmaAlgo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ookburst::~ookburst()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ookburst::SetDmaAlgo()
|
||||||
|
{
|
||||||
|
dma_cb_t *cbp = cbarray;
|
||||||
|
// We must fill the FIFO (PWM or PCM) to be Synchronized from start
|
||||||
|
// PWM FIFO = 16
|
||||||
|
// PCM FIFO = 64
|
||||||
|
if (syncwithpwm)
|
||||||
|
{
|
||||||
|
SetEasyCB(cbp++, 0, dma_pwm, 16 + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetEasyCB(cbp++, 0, dma_pcm, 64 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t samplecnt = 0; samplecnt < buffersize - 2; samplecnt++)
|
||||||
|
{
|
||||||
|
|
||||||
|
//Set Amplitude to FSEL for amplitude=0
|
||||||
|
SetEasyCB(cbp++, samplecnt * registerbysample, dma_fsel, 1);
|
||||||
|
// Delay
|
||||||
|
SetEasyCB(cbp++, samplecnt * registerbysample, syncwithpwm ? dma_pwm : dma_pcm, 1);
|
||||||
|
}
|
||||||
|
lastcbp = cbp;
|
||||||
|
|
||||||
|
// Last CBP before stopping : disable output
|
||||||
|
sampletab[buffersize * registerbysample - 1] = (Originfsel & ~(7 << 12)) | (0 << 12); //Disable Clk
|
||||||
|
SetEasyCB(cbp, buffersize * registerbysample - 1, dma_fsel, 1);
|
||||||
|
cbp->next = 0; // Stop DMA
|
||||||
|
}
|
||||||
|
void ookburst::SetSymbols(unsigned char *Symbols, uint32_t Size)
|
||||||
|
{
|
||||||
|
if (Size > buffersize - 2)
|
||||||
|
{
|
||||||
|
dbg_printf(1, "Buffer overflow\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma_cb_t *cbp = cbarray;
|
||||||
|
cbp++; // Skip the first which is the Fiiling of Fifo
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < Size; i++)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < SR_upsample - Ramp; j++)
|
||||||
|
{
|
||||||
|
sampletab[i * SR_upsample + j] = (Symbols[i] == 0) ? ((Originfsel & ~(7 << 12)) | (0 << 12)) : ((Originfsel & ~(7 << 12)) | (4 << 12));
|
||||||
|
cbp++; //SKIP FSEL CB
|
||||||
|
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||||
|
cbp++;
|
||||||
|
}
|
||||||
|
for (size_t j = 0; j < Ramp; j++)
|
||||||
|
{
|
||||||
|
if (i < Size - 1)
|
||||||
{
|
{
|
||||||
SetEasyCB(cbp++,0,dma_pwm,16+1);
|
sampletab[i * SR_upsample + j + SR_upsample - Ramp] = (Symbols[i] == 0) ? ((Originfsel & ~(7 << 12)) | (0 << 12)) : ((Originfsel & ~(7 << 12)) | (4 << 12));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetEasyCB(cbp++,0,dma_pcm,64+1);
|
sampletab[i * SR_upsample + j + SR_upsample - Ramp] = (Symbols[i] == 0) ? ((Originfsel & ~(7 << 12)) | (0 << 12)) : ((Originfsel & ~(7 << 12)) | (4 << 12));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t samplecnt = 0; samplecnt < buffersize-2; samplecnt++)
|
|
||||||
{
|
|
||||||
|
|
||||||
//Set Amplitude to FSEL for amplitude=0
|
|
||||||
SetEasyCB(cbp++,samplecnt*registerbysample,dma_fsel,1);
|
|
||||||
// Delay
|
|
||||||
SetEasyCB(cbp++,samplecnt*registerbysample,syncwithpwm?dma_pwm:dma_pcm,1);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
lastcbp=cbp;
|
|
||||||
|
|
||||||
// Last CBP before stopping : disable output
|
cbp++; //SKIP FREQ CB
|
||||||
sampletab[buffersize*registerbysample-1]=(Originfsel & ~(7 << 12)) | (0 << 12); //Disable Clk
|
|
||||||
SetEasyCB(cbp,buffersize*registerbysample-1,dma_fsel,1);
|
|
||||||
cbp->next = 0; // Stop DMA
|
|
||||||
|
|
||||||
}
|
|
||||||
void ookburst::SetSymbols(unsigned char *Symbols,uint32_t Size)
|
|
||||||
{
|
|
||||||
if(Size>buffersize-2) {dbg_printf(1,"Buffer overflow\n");return;}
|
|
||||||
|
|
||||||
dma_cb_t *cbp=cbarray;
|
|
||||||
cbp++; // Skip the first which is the Fiiling of Fifo
|
|
||||||
|
|
||||||
|
|
||||||
for(unsigned i=0;i<Size;i++)
|
|
||||||
{
|
|
||||||
|
|
||||||
sampletab[i]=(Symbols[i]==0)?((Originfsel & ~(7 << 12)) | (0 << 12)):((Originfsel & ~(7 << 12)) | (4 << 12));
|
|
||||||
|
|
||||||
cbp++;//SKIP FSEL CB
|
|
||||||
cbp->next = mem_virt_to_phys(cbp + 1);
|
cbp->next = mem_virt_to_phys(cbp + 1);
|
||||||
|
cbp++;
|
||||||
//dbg_printf(1,"cbp : sample %d pointer %p src %x dest %x next %x\n",i,cbp,cbp->src,cbp->dst,cbp->next);
|
|
||||||
cbp++;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
cbp--;
|
|
||||||
cbp->next = mem_virt_to_phys(lastcbp);
|
cbp--;
|
||||||
|
cbp->next = mem_virt_to_phys(lastcbp);
|
||||||
|
|
||||||
dma::start();
|
dma::start();
|
||||||
|
|
||||||
|
while (isrunning()) //Block function : return until sent completely signal
|
||||||
while(isrunning()) //Block function : return until sent completely signal
|
{
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
usleep(100); //To be sure last symbol Tx ?
|
||||||
|
}
|
||||||
|
|
||||||
|
//****************************** OOK BURST TIMING *****************************************
|
||||||
|
// SampleRate is set to 0.1MHZ,means 10us granularity, MaxMessageDuration in us
|
||||||
|
ookbursttiming::ookbursttiming(uint64_t TuneFrequency, size_t MaxMessageDuration) : ookburst(TuneFrequency, 1e5, 14, MaxMessageDuration / 10)
|
||||||
|
{
|
||||||
|
m_MaxMessage = MaxMessageDuration;
|
||||||
|
ookrenderbuffer = new unsigned char[m_MaxMessage];
|
||||||
|
}
|
||||||
|
|
||||||
|
ookbursttiming::~ookbursttiming()
|
||||||
|
{
|
||||||
|
if (ookrenderbuffer != nullptr)
|
||||||
|
delete[] ookrenderbuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ookbursttiming::SendMessage(SampleOOKTiming *TabSymbols, size_t Size)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
for (size_t i = 0; i < Size; i++)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < TabSymbols[i].duration / 10; j++)
|
||||||
{
|
{
|
||||||
usleep(100);
|
ookrenderbuffer[n++] = TabSymbols[i].value;
|
||||||
|
if (n >= m_MaxMessage)
|
||||||
}
|
|
||||||
usleep(100);//To be sure last symbol Tx ?
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//****************************** OOK BURST TIMING *****************************************
|
|
||||||
// SampleRate is set to 0.1MHZ,means 10us granularity, MaxMessageDuration in us
|
|
||||||
ookbursttiming::ookbursttiming(uint64_t TuneFrequency,size_t MaxMessageDuration):ookburst(TuneFrequency,1e5,14,MaxMessageDuration/10)
|
|
||||||
{
|
|
||||||
m_MaxMessage=MaxMessageDuration;
|
|
||||||
ookrenderbuffer=new unsigned char[m_MaxMessage];
|
|
||||||
}
|
|
||||||
|
|
||||||
ookbursttiming::~ookbursttiming()
|
|
||||||
{
|
|
||||||
if(ookrenderbuffer!=nullptr)
|
|
||||||
delete []ookrenderbuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ookbursttiming::SendMessage(SampleOOKTiming *TabSymbols,size_t Size)
|
|
||||||
{
|
|
||||||
size_t n=0;
|
|
||||||
for (size_t i=0;i<Size;i++)
|
|
||||||
{
|
|
||||||
for(size_t j=0;j<TabSymbols[i].duration/10;j++)
|
|
||||||
{
|
{
|
||||||
ookrenderbuffer[n++]=TabSymbols[i].value;
|
dbg_printf(1, "OOK Message too long abort time(%d/%d)\n", n, m_MaxMessage);
|
||||||
if(n>=m_MaxMessage)
|
return;
|
||||||
{
|
}
|
||||||
dbg_printf(1,"OOK Message too long abort time(%d/%d)\n",n,m_MaxMessage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SetSymbols(ookrenderbuffer,n);
|
|
||||||
}
|
}
|
||||||
|
SetSymbols(ookrenderbuffer, n);
|
||||||
|
}
|
||||||
|
|
|
@ -12,8 +12,10 @@ class ookburst:public bufferdma,public clkgpio,public pwmgpio,public pcmgpio
|
||||||
uint32_t Originfsel;
|
uint32_t Originfsel;
|
||||||
bool syncwithpwm;
|
bool syncwithpwm;
|
||||||
dma_cb_t *lastcbp;
|
dma_cb_t *lastcbp;
|
||||||
|
size_t SR_upsample=1;
|
||||||
|
size_t Ramp=0.0;
|
||||||
public:
|
public:
|
||||||
ookburst(uint64_t TuneFrequency,uint32_t SymbolRate,int Channel,uint32_t FifoSize);
|
ookburst(uint64_t TuneFrequency,float SymbolRate,int Channel,uint32_t FifoSize, size_t upsample=1,float RatioRamp=0.0);
|
||||||
~ookburst();
|
~ookburst();
|
||||||
void SetDmaAlgo();
|
void SetDmaAlgo();
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ phasedmasync::phasedmasync(uint64_t TuneFrequency,uint32_t SampleRateIn,int Numb
|
||||||
clkgpio::SetAdvancedPllMode(true);
|
clkgpio::SetAdvancedPllMode(true);
|
||||||
|
|
||||||
clkgpio::ComputeBestLO(tunefreq,0); // compute PWM divider according to MasterPLL clkgpio::PllFixDivider
|
clkgpio::ComputeBestLO(tunefreq,0); // compute PWM divider according to MasterPLL clkgpio::PllFixDivider
|
||||||
double FloatMult=((double)(tunefreq)*clkgpio::PllFixDivider)/(double)(XOSC_FREQUENCY);
|
double FloatMult=((double)(tunefreq)*clkgpio::PllFixDivider)/(double)(pwmgpio::XOSC_FREQUENCY);
|
||||||
uint32_t freqctl = FloatMult*((double)(1<<20)) ;
|
uint32_t freqctl = FloatMult*((double)(1<<20)) ;
|
||||||
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
|
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
|
||||||
freqctl&=0xFFFFF; // Fractionnal is 20bits
|
freqctl&=0xFFFFF; // Fractionnal is 20bits
|
||||||
|
|
31
src/rpi.c
Normal file
31
src/rpi.c
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "stdint.h"
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
static unsigned get_dt_ranges(const char *filename, unsigned offset)
|
||||||
|
{
|
||||||
|
unsigned address = ~0;
|
||||||
|
FILE *fp = fopen(filename, "rb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
unsigned char buf[4];
|
||||||
|
fseek(fp, offset, SEEK_SET);
|
||||||
|
if (fread(buf, 1, sizeof buf, fp) == sizeof buf)
|
||||||
|
address = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3] << 0;
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned bcm_host_get_peripheral_address(void)
|
||||||
|
{
|
||||||
|
unsigned address = get_dt_ranges("/proc/device-tree/soc/ranges", 4);
|
||||||
|
if (address == 0)
|
||||||
|
address = get_dt_ranges("/proc/device-tree/soc/ranges", 8);
|
||||||
|
return address == ~0u ? 0x20000000 : address;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned bcm_host_get_sdram_address(void)
|
||||||
|
{
|
||||||
|
unsigned address = get_dt_ranges("/proc/device-tree/axi/vc_mem/reg", 8);
|
||||||
|
return address == ~0u ? 0x40000000 : address;
|
||||||
|
}
|
3
src/rpi.h
Normal file
3
src/rpi.h
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
unsigned get_dt_ranges(const char *filename, unsigned offset);
|
||||||
|
unsigned bcm_host_get_peripheral_address(void);
|
||||||
|
unsigned bcm_host_get_sdram_address(void);
|
|
@ -7,6 +7,11 @@ void dbg_setlevel(int Level)
|
||||||
debug_level=Level;
|
debug_level=Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dbg_getlevel()
|
||||||
|
{
|
||||||
|
return debug_level;
|
||||||
|
}
|
||||||
|
|
||||||
void dbg_printf(int Level, const char *fmt, ...)
|
void dbg_printf(int Level, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
if (Level <= debug_level)
|
if (Level <= debug_level)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
void dbg_setlevel(int Level);
|
void dbg_setlevel(int Level);
|
||||||
|
int dbg_getlevel();
|
||||||
void dbg_printf(int Level, const char *fmt, ...);
|
void dbg_printf(int Level, const char *fmt, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue