Compare commits

...

32 commits

Author SHA1 Message Date
f5oeo
dbb26b33c7 Try to fix some weird null registry 2023-01-29 17:35:45 +00:00
F5OEO
d514817b65 Misspelling dependancy 2021-02-25 09:36:11 +01:00
F5OEO
e0a4588df8
Merge pull request #17 from jmfriedt/master
Makefile: explicit rules to generale static and dynamic libraries
2021-02-23 11:46:33 +01:00
Jean-Michel Friedt
c9ea7cacb8 Makefile: explicit rules to generale static and dynamic libraries 2021-02-23 11:24:22 +01:00
Your Name
b0172f908b Remove rpi warning 2021-01-13 10:40:16 +00:00
F5OEO
a7def5d4ba
Merge pull request #16 from jmfriedt/master
remove bcm_host dependency + Makefile constants CC/CXX overwritable from command line
2021-01-13 09:38:33 +01:00
jfriedt
f6dfbeae03 Makefile: add install rule 2021-01-12 15:13:17 +01:00
jfriedt
b571c4a308 remove bcm_host dependency + Makefile constants CC/CXX overwritable from command line 2021-01-12 14:37:14 +01:00
f5oeo
0aec0363e2 Compliant to 64bit 2020-11-03 13:50:48 +00:00
f5oeo
fd366412f7 Remove object from git 2020-11-03 13:50:25 +00:00
F5OEO
d139ff56fb Fix PLL rate for non PI4 2020-11-03 10:52:37 +00:00
f5oeo
d318058a17 Move optparse used by ook to rpitx 2020-11-02 13:20:25 +00:00
f5oeo
1cd126f230 Merge branch 'master' of https://github.com/F5OEO/librpitx 2020-11-02 13:16:32 +00:00
f5oeo
5aabd38264 Remove testapp binary 2020-11-02 13:15:45 +00:00
f5oeo
c360d016ca Add tool 2020-11-02 13:11:01 +00:00
f5oeo
692db75eef Few fixes and remove binaries 2020-11-02 13:10:21 +00:00
F5OEO
b90473b76e Fix DMA for high frequency 2020-11-02 10:49:55 +00:00
F5OEO
93cf35a7ba Fix for higher frequencies : 434MHz is ok 2020-11-02 10:49:55 +00:00
F5OEO
02599bd7f2 Just some tests 2020-11-02 10:49:54 +00:00
F5OEO
7f6f1be34e Change a bit pi4 freq/2 method 2020-11-02 10:49:54 +00:00
F5OEO
e48ebd5b23 Overwrite dma channel paramter to adpat to pi model 2020-11-02 10:49:53 +00:00
F5OEO
5c857b9f7d IQmod public 2020-11-02 10:49:53 +00:00
F5OEO
3b929185ff PI4 working but need cleaner implementation 2020-11-02 10:46:20 +00:00
F5OEO
2d2d854280 pi4 detection and CLKOSC according 2020-11-02 10:46:19 +00:00
F5OEO
a3611e265e Try to set right Peripherals base 2020-11-02 10:46:19 +00:00
F5OEO
5b5a4ee083 Work on PI4 2020-11-02 10:46:19 +00:00
F5OEO
5c1613589d
Merge pull request #15 from psa-jforestier/libsendook
Improve logging and command line parser
2020-09-09 10:35:20 +02:00
psa-jforestier
7c8849756d add new function to parse command line (got it from rtl_433) 2020-09-08 18:21:24 +02:00
psa-jforestier
2d1bf3042b improve logging function 2020-09-08 18:20:50 +02:00
Pedro
c9714b2a7d mode_IQ 2020-06-06 16:25:04 -03:00
Pedro
6bb567b63e mode_IQ 2020-06-06 16:24:30 -03:00
F5OEO
5475c41ccf Add ramp for smooth transition on FSK 2019-01-10 15:19:48 +00:00
21 changed files with 2390 additions and 307 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
*.o
*.a
*.gch

View file

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

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

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

View file

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

View file

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

View file

@ -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_HINT_PERMALOCK|MEM_FLAG_NO_INIT;//0x0c;
mem_flag = MEM_FLAG_L1_NONALLOCATING|MEM_FLAG_HINT_PERMALOCK|MEM_FLAG_NO_INIT;//0x0c; switch(dram_phys_base)
{
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");
} }
if((info.peripheralBase==RPI_BROADCOM_2836_PERIPHERAL_BASE)||(info.peripheralBase==RPI_BROADCOM_2837_PERIPHERAL_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");
}
} }
dma::~dma() dma::~dma()

View file

@ -20,24 +20,25 @@ 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::SetAdvancedPllMode(true);
clkgpio::SetCenterFrequency(TuneFrequency,SymbolRate); // Write Mult Int and Frac : FixMe carrier is already there clkgpio::SetCenterFrequency(TuneFrequency, Deviation*10); // Write Mult Int and Frac : FixMe carrier is already there
clkgpio::SetFrequency(0); clkgpio::SetFrequency(0);
disableclk(4); disableclk(4);
syncwithpwm = false; syncwithpwm = false;
Ramp = SR_upsample * RatioRamp; //Ramp time = 10%
if (syncwithpwm) if (syncwithpwm)
{ {
pwmgpio::SetPllNumber(clk_plld, 1); pwmgpio::SetPllNumber(clk_plld, 1);
pwmgpio::SetFrequency(SymbolRate); pwmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
} }
else else
{ {
pcmgpio::SetPllNumber(clk_plld, 1); pcmgpio::SetPllNumber(clk_plld, 1);
pcmgpio::SetFrequency(SymbolRate); pcmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
} }
//Should be obligatory place before setdmaalgo //Should be obligatory place before setdmaalgo
@ -45,9 +46,6 @@ This program is free software: you can redistribute it and/or modify
dbg_printf(1, "FSK Origin fsel %x\n", Originfsel); dbg_printf(1, "FSK Origin fsel %x\n", Originfsel);
SetDmaAlgo(); SetDmaAlgo();
} }
fskburst::~fskburst() fskburst::~fskburst()
@ -71,22 +69,18 @@ This program is free software: you can redistribute it and/or modify
else else
{ {
SetEasyCB(cbp++, 0, dma_pcm, 64 + 1); SetEasyCB(cbp++, 0, dma_pcm, 64 + 1);
} }
SetEasyCB(cbp++, buffersize * registerbysample - 2, dma_fsel, 1); //Enable clk SetEasyCB(cbp++, buffersize * registerbysample - 2, dma_fsel, 1); //Enable clk
for (uint32_t samplecnt = 0; samplecnt < buffersize - 2; samplecnt++) for (uint32_t samplecnt = 0; samplecnt < buffersize - 2; samplecnt++)
{ {
// Write a frequency sample // Write a frequency sample
SetEasyCB(cbp++, samplecnt * registerbysample, dma_pllc_frac, 1); //FReq SetEasyCB(cbp++, samplecnt * registerbysample, dma_pllc_frac, 1); //FReq
// Delay // Delay
SetEasyCB(cbp++, samplecnt * registerbysample, syncwithpwm ? dma_pwm : dma_pcm, 1); SetEasyCB(cbp++, samplecnt * registerbysample, syncwithpwm ? dma_pwm : dma_pcm, 1);
} }
lastcbp = cbp; lastcbp = cbp;
@ -98,30 +92,52 @@ This program is free software: you can redistribute it and/or modify
} }
void fskburst::SetSymbols(unsigned char *Symbols, uint32_t Size) void fskburst::SetSymbols(unsigned char *Symbols, uint32_t Size)
{ {
if(Size>buffersize-3) {dbg_printf(1,"Buffer overflow\n");return;} if (Size > buffersize - 3)
{
dbg_printf(1, "Buffer overflow\n");
return;
}
dma_cb_t *cbp = cbarray; dma_cb_t *cbp = cbarray;
cbp += 2; // Skip the first 2 CB (initialisation) cbp += 2; // Skip the first 2 CB (initialisation)
for (unsigned int i = 0; i < Size; i++) for (unsigned int i = 0; i < Size; i++)
{ {
sampletab[i]=(0x5A<<24)|GetMasterFrac(freqdeviation*Symbols[i]); for (size_t j = 0; j < SR_upsample - Ramp; j++)
{
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++;
} }
for (size_t j = 0 ; j < Ramp; j++)
{
if (i < Size - 1)
{
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++;
}
}
cbp--; cbp--;
cbp->next = mem_virt_to_phys(lastcbp); 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
{ {
//dbg_printf(1,"GPIO %x\n",clkgpio::gengpio.gpioreg[GPFSEL0]); //dbg_printf(1,"GPIO %x\n",clkgpio::gengpio.gpioreg[GPFSEL0]);
usleep(100); usleep(100);
} }
dbg_printf(1, "FSK burst end Tx\n", cbp->src, cbp->dst, cbp->next); dbg_printf(1, "FSK burst end Tx\n", cbp->src, cbp->dst, cbp->next);
usleep(100); //To be sure last symbol Tx ? usleep(100); //To be sure last symbol Tx ?
} }

View file

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

View file

@ -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
XOSC_FREQUENCY=54000000;
}
if(BCM2708_PERI_BASE==0)
{ {
BCM2708_PERI_BASE = info.peripheralBase; dbg_printf(0,"Unknown peripheral base, switch to PI4 \n");
} BCM2708_PERI_BASE=0xfe000000;
XOSC_FREQUENCY=54000000;
if ((info.peripheralBase == RPI_BROADCOM_2836_PERIPHERAL_BASE) || (info.peripheralBase == RPI_BROADCOM_2837_PERIPHERAL_BASE)) pi_is_2711=true;
{
BCM2708_PERI_BASE = info.peripheralBase;
}
} }
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 else
{
FloatMult = ((double)(CentralFrequency + Frequency) ) / ((double)(XOSC_FREQUENCY*2) * (1 - clk_ppm * 1e-6));
}
}
else
{
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)); 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 else
{
FloatMult = ((double)(CentralFrequency + Frequency) ) / ((double)(XOSC_FREQUENCY*2) * (1 - clk_ppm * 1e-6));
}
}
else
{
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)); 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)
{ {
} }
@ -643,19 +758,33 @@ int generalgpio::setmode(uint32_t gpio, uint32_t mode)
} }
int generalgpio::setpulloff(uint32_t gpio) int generalgpio::setpulloff(uint32_t gpio)
{
if(!pi_is_2711)
{ {
gpioreg[GPPUD]=0; gpioreg[GPPUD]=0;
usleep(150); usleep(150);
gpioreg[GPPUDCLK0]=1<<gpio; gpioreg[GPPUDCLK0]=1<<gpio;
usleep(150); usleep(150);
gpioreg[GPPUDCLK0]=0; 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)
{ {
} }

View file

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

View file

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

View file

@ -20,8 +20,7 @@ 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::SetAdvancedPllMode(true);
@ -30,24 +29,21 @@ This program is free software: you can redistribute it and/or modify
clkgpio::SetFrequency(0); clkgpio::SetFrequency(0);
syncwithpwm = false; syncwithpwm = false;
Ramp = SR_upsample * RatioRamp; //Ramp time
if (syncwithpwm) if (syncwithpwm)
{ {
pwmgpio::SetPllNumber(clk_plld, 1); pwmgpio::SetPllNumber(clk_plld, 1);
pwmgpio::SetFrequency(SymbolRate); pwmgpio::SetFrequency(SymbolRate * (float)upsample);
} }
else else
{ {
pcmgpio::SetPllNumber(clk_plld, 1); pcmgpio::SetPllNumber(clk_plld, 1);
pcmgpio::SetFrequency(SymbolRate); pcmgpio::SetFrequency(SymbolRate * float(upsample));
} }
Originfsel = clkgpio::gengpio.gpioreg[GPFSEL0]; Originfsel = clkgpio::gengpio.gpioreg[GPFSEL0];
SetDmaAlgo(); SetDmaAlgo();
} }
ookburst::~ookburst() ookburst::~ookburst()
@ -67,7 +63,6 @@ This program is free software: you can redistribute it and/or modify
else else
{ {
SetEasyCB(cbp++, 0, dma_pcm, 64 + 1); SetEasyCB(cbp++, 0, dma_pcm, 64 + 1);
} }
for (uint32_t samplecnt = 0; samplecnt < buffersize - 2; samplecnt++) for (uint32_t samplecnt = 0; samplecnt < buffersize - 2; samplecnt++)
@ -77,8 +72,6 @@ This program is free software: you can redistribute it and/or modify
SetEasyCB(cbp++, samplecnt * registerbysample, dma_fsel, 1); SetEasyCB(cbp++, samplecnt * registerbysample, dma_fsel, 1);
// Delay // Delay
SetEasyCB(cbp++, samplecnt * registerbysample, syncwithpwm ? dma_pwm : dma_pcm, 1); SetEasyCB(cbp++, samplecnt * registerbysample, syncwithpwm ? dma_pwm : dma_pcm, 1);
} }
lastcbp = cbp; lastcbp = cbp;
@ -86,43 +79,55 @@ This program is free software: you can redistribute it and/or modify
sampletab[buffersize * registerbysample - 1] = (Originfsel & ~(7 << 12)) | (0 << 12); //Disable Clk sampletab[buffersize * registerbysample - 1] = (Originfsel & ~(7 << 12)) | (0 << 12); //Disable Clk
SetEasyCB(cbp, buffersize * registerbysample - 1, dma_fsel, 1); SetEasyCB(cbp, buffersize * registerbysample - 1, dma_fsel, 1);
cbp->next = 0; // Stop DMA cbp->next = 0; // Stop DMA
} }
void ookburst::SetSymbols(unsigned char *Symbols, uint32_t Size) void ookburst::SetSymbols(unsigned char *Symbols, uint32_t Size)
{ {
if(Size>buffersize-2) {dbg_printf(1,"Buffer overflow\n");return;} if (Size > buffersize - 2)
{
dbg_printf(1, "Buffer overflow\n");
return;
}
dma_cb_t *cbp = cbarray; dma_cb_t *cbp = cbarray;
cbp++; // Skip the first which is the Fiiling of Fifo cbp++; // Skip the first which is the Fiiling of Fifo
for (unsigned i = 0; i < Size; i++) for (unsigned i = 0; i < Size; i++)
{ {
for (size_t j = 0; j < SR_upsample - Ramp; j++)
sampletab[i]=(Symbols[i]==0)?((Originfsel & ~(7 << 12)) | (0 << 12)):((Originfsel & ~(7 << 12)) | (4 << 12)); {
sampletab[i * SR_upsample + j] = (Symbols[i] == 0) ? ((Originfsel & ~(7 << 12)) | (0 << 12)) : ((Originfsel & ~(7 << 12)) | (4 << 12));
cbp++; //SKIP FSEL CB cbp++; //SKIP FSEL CB
cbp->next = mem_virt_to_phys(cbp + 1); cbp->next = mem_virt_to_phys(cbp + 1);
//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++;
}
for (size_t j = 0; j < Ramp; j++)
{
if (i < Size - 1)
{
sampletab[i * SR_upsample + j + SR_upsample - Ramp] = (Symbols[i] == 0) ? ((Originfsel & ~(7 << 12)) | (0 << 12)) : ((Originfsel & ~(7 << 12)) | (4 << 12));
} }
else
{
sampletab[i * SR_upsample + j + SR_upsample - Ramp] = (Symbols[i] == 0) ? ((Originfsel & ~(7 << 12)) | (0 << 12)) : ((Originfsel & ~(7 << 12)) | (4 << 12));
}
cbp++; //SKIP FREQ CB
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
}
}
cbp--; cbp--;
cbp->next = mem_virt_to_phys(lastcbp); 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);
} }
usleep(100); //To be sure last symbol Tx ? usleep(100); //To be sure last symbol Tx ?
} }
//****************************** OOK BURST TIMING ***************************************** //****************************** OOK BURST TIMING *****************************************

View file

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

View file

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

View file

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

View file

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