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
CFLAGS = -Wall -g -O3 -Wno-unused-variable
LDFLAGS = -lm -lrt -lpthread
CFLAGS = -Wall -g -O3 -Wno-unused-variable -I /opt/vc/include
LDFLAGS = -lm -lrt -lpthread -L/opt/vc/lib -lbcm_host
CCP = g++
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)
{
int SR = 1000;
int SR = 10; //10 HZ
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};
@ -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
terminate(int num)
{
@ -723,7 +771,7 @@ int main(int argc, char *argv[])
sa.sa_handler = terminate;
sigaction(i, &sa, NULL);
}
dbg_setlevel(0);
dbg_setlevel(1);
//SimpleTest(Freq);
//SimpleTestbpsk(Freq);
//SimpleTestFileIQ(Freq);
@ -734,5 +782,8 @@ int main(int argc, char *argv[])
//SimpleTestOOKTiming(Freq);
//AlectoOOK(Freq);
//RfSwitchOOK(Freq);
SimpleTestAtv(Freq);
//SimpleTestbpsk(Freq);
//SimpleTestAtv(Freq);
info(Freq);
}

View file

@ -1,16 +1,36 @@
CFLAGS = -Wall -O3 -Wno-unused-variable
CXXFLAGS = -std=c++11 -Wall -O3 -Wno-unused-variable
LDFLAGS = -lm -lrt -lpthread
CCP = c++
CC = cc
CFLAGS ?= -Wall -O3 -Wno-unused-variable
CFLAGS += -std=c++11 -fPIC
CXXFLAGS ?= -std=c++11 -Wall -O3 -Wno-unused-variable -I /opt/vc/include
CXXFLAGS += -std=c++11 -Wall -O3 -Wno-unused-variable -fPIC
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
#$(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
all: librpitx.a librpitx.so
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:
rm -f *.o *.a
rm -f $(OBJS) *.a *.so

Binary file not shown.

View file

@ -158,7 +158,7 @@ void atv::SetDmaAlgo()
}
cbp--;
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)

View file

@ -19,6 +19,7 @@ This program is free software: you can redistribute it and/or modify
#include "dma.h"
#include "stdio.h"
#include "util.h"
#include "rpi.h"
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
{
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;
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();
if (mbox.handle < 0)
{
@ -45,6 +61,7 @@ dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize) // Fixme! Need to che
usermemsize=UserMemSize;
GetRpiInfo(); // Fill mem_flag and dram_phys_base
uint32_t MemoryRequired=CBSize*sizeof(dma_cb_t)+UserMemSize*sizeof(uint32_t);
int NumPages=(MemoryRequired/PAGE_SIZE)+1;
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()
{
RASPBERRY_PI_INFO_T info;
if (getRaspberryPiInformation(&info) > 0)
dram_phys_base= bcm_host_get_sdram_address();
mem_flag = MEM_FLAG_HINT_PERMALOCK|MEM_FLAG_NO_INIT;//0x0c;
switch(dram_phys_base)
{
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))
{
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()

View file

@ -20,108 +20,124 @@ This program is free software: you can redistribute it and/or modify
#include "util.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)
{
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()
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)
{
sampletab[buffersize*registerbysample-2]=(Originfsel & ~(7 << 12)) | (4 << 12); //Gpio Clk
sampletab[buffersize*registerbysample-1]=(Originfsel & ~(7 << 12)) | (0 << 12); //Gpio In
clkgpio::SetAdvancedPllMode(true);
clkgpio::SetCenterFrequency(TuneFrequency, Deviation*10); // Write Mult Int and Frac : FixMe carrier is already there
clkgpio::SetFrequency(0);
disableclk(4);
syncwithpwm = false;
Ramp = SR_upsample * RatioRamp; //Ramp time = 10%
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 (syncwithpwm)
{
if(Size>buffersize-3) {dbg_printf(1,"Buffer overflow\n");return;}
pwmgpio::SetPllNumber(clk_plld, 1);
pwmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
}
else
{
pcmgpio::SetPllNumber(clk_plld, 1);
pcmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
}
dma_cb_t *cbp=cbarray;
cbp+=2; // Skip the first 2 CB (initialisation)
for(unsigned int i=0;i<Size;i++)
//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]);
cbp++;//SKIP FREQ CB
sampletab[i * SR_upsample + j] = (0x5A << 24) | GetMasterFrac(freqdeviation * Symbols[i]);
cbp++; //SKIP FREQ CB
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
}
cbp--;
cbp->next = mem_virt_to_phys(lastcbp);
dma::start();
while(isrunning()) //Block function : return until sent completely signal
for (size_t j = 0 ; j < Ramp; j++)
{
//dbg_printf(1,"GPIO %x\n",clkgpio::gengpio.gpioreg[GPFSEL0]);
usleep(100);
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++;
}
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 ?
}

View file

@ -12,8 +12,10 @@ class fskburst:public bufferdma,public clkgpio,public pwmgpio,public pcmgpio
uint32_t Originfsel;
bool syncwithpwm;
dma_cb_t *lastcbp;
size_t SR_upsample=0;
size_t Ramp=0;
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();
void SetDmaAlgo();

View file

@ -24,12 +24,15 @@ extern "C" {
#include <unistd.h>
#include <sys/timex.h>
#include <math.h>
#include <string.h>
#include "util.h"
#include "rpi.h"
gpio::gpio(uint32_t base, uint32_t len)
{
gpioreg = (uint32_t *)mapmem(base, len);
gpioreg = (uint32_t *)mapmem(GetPeripheralBase()+base, len);
gpiolen=len;
}
@ -39,33 +42,85 @@ gpio::~gpio()
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()
{
RASPBERRY_PI_INFO_T info;
uint32_t BCM2708_PERI_BASE = 0;
if (getRaspberryPiInformation(&info) > 0)
uint32_t BCM2708_PERI_BASE =bcm_host_get_peripheral_address();
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)
{
BCM2708_PERI_BASE = info.peripheralBase;
}
if ((info.peripheralBase == RPI_BROADCOM_2836_PERIPHERAL_BASE) || (info.peripheralBase == RPI_BROADCOM_2837_PERIPHERAL_BASE))
{
BCM2708_PERI_BASE = info.peripheralBase;
}
dbg_printf(0,"RPi4 GPIO detected\n");
pi_is_2711=true; //Rpi4
XOSC_FREQUENCY=54000000;
}
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;
}
//******************** DMA Registers ***************************************
dmagpio::dmagpio() : gpio(GetPeripheralBase() + DMA_BASE, DMA_LEN)
dmagpio::dmagpio() : gpio( DMA_BASE, DMA_LEN)
{
}
// ***************** CLK Registers *****************************************
clkgpio::clkgpio() : gpio(GetPeripheralBase() + CLK_BASE, CLK_LEN)
clkgpio::clkgpio() : gpio(CLK_BASE, CLK_LEN)
{
SetppmFromNTP();
padgpio level;
@ -81,7 +136,7 @@ clkgpio::~clkgpio()
int clkgpio::SetPllNumber(int PllNo, int MashType)
{
//print_clock_tree();
print_clock_tree();
if (PllNo < 8)
pllnumber = PllNo;
else
@ -109,21 +164,26 @@ uint64_t clkgpio::GetPllFrequency(int PllNo)
Freq = XOSC_FREQUENCY;
break;
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;
//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:
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;
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;
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;
}
if(!pi_is_2711) // FixMe : Surely a register which say it is a 2x
Freq*=2LL;
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;
}
@ -157,9 +217,26 @@ int clkgpio::SetFrequency(double Frequency)
double FloatMult=0;
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
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));
int IntMultiply = freqctl >> 20; // Need to be calculated to have a center frequency
freqctl &= 0xFFFFF; // Fractionnal is 20bits
@ -187,10 +264,26 @@ uint32_t clkgpio::GetMasterFrac(double Frequency)
if (ModulateFromMasterPLL)
{
double FloatMult=0;
if(PllFixDivider==1) //Using PDIV thus frequency/2
FloatMult = ((double)(CentralFrequency + Frequency) ) / ((double)(XOSC_FREQUENCY*2) * (1 - clk_ppm * 1e-6));
if((PllFixDivider==1))//There is no Prediv on Pi4 //Using PDIV thus frequency/2
{
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
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));
int IntMultiply = freqctl >> 20; // Need to be calculated to have a center frequency
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_USE_PDIV 1500e6 //1700 works but some ticky breaks in clock..PLL should be at limit
#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
int best_divider = 0;
@ -222,6 +316,8 @@ int clkgpio::ComputeBestLO(uint64_t Frequency, int Bandwidth)
double Multiplier=0.0;
best_divider = 0;
bool cross_boundary=false;
if(Frequency<MIN_PLL_RATE/4095)
{
dbg_printf(1, "Frequency too low !!!!!!\n");
@ -268,6 +364,7 @@ int clkgpio::ComputeBestLO(uint64_t Frequency, int Bandwidth)
if (best_divider!=0)
{
PllFixDivider = best_divider;
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));
return 0;
@ -312,15 +409,24 @@ int clkgpio::SetCenterFrequency(uint64_t Frequency, int Bandwidth)
if (ModulateFromMasterPLL)
{
//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)
{
//We will use PDIV by 2, means like we have a 2 times more
SetClkDivFrac(2, 0x0); // NO MASH !!!!
dbg_printf(1, "Pll Fix Divider\n");
}
else
@ -346,7 +452,7 @@ int clkgpio::SetCenterFrequency(uint64_t Frequency, int Bandwidth)
}
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
@ -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_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
void clkgpio::SetAdvancedPllMode(bool Advanced)
{
@ -432,7 +539,14 @@ void clkgpio::SetAdvancedPllMode(bool Advanced)
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);
}
}
@ -535,24 +649,25 @@ void clkgpio::print_clock_tree(void)
// Sometimes calculated frequencies are off by a factor of 2
// 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(" %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("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("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("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("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]);
}
@ -622,7 +737,7 @@ void clkgpio::SetppmFromNTP()
// ************************************** 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)
{
gpioreg[GPPUD]=0;
usleep(150);
gpioreg[GPPUDCLK0]=1<<gpio;
usleep(150);
gpioreg[GPPUDCLK0]=0;
if(!pi_is_2711)
{
gpioreg[GPPUD]=0;
usleep(150);
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;
}
// ********************************** PWM GPIO **********************************
pwmgpio::pwmgpio() : gpio(GetPeripheralBase() + PWM_BASE, PWM_LEN)
pwmgpio::pwmgpio() : gpio(/*GetPeripheralBase() + */PWM_BASE, PWM_LEN)
{
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) **********************************
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
}
@ -890,7 +1019,7 @@ int pcmgpio::SetPrediv(int predivisor) //Carefull we use a 10 fixe divisor for n
// ********************************** 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
{
public:
bool pi_is_2711=false;
uint64_t XOSC_FREQUENCY=19200000;
public:
volatile uint32_t *gpioreg = NULL;
uint32_t gpiolen;
@ -57,7 +59,7 @@ class dmagpio : public gpio
//************************************ GENERAL GPIO ***************************************
#define GENERAL_BASE (0x00200000)
#define GENERAL_LEN 0xB4
#define GENERAL_LEN 0xD0
#define GPFSEL0 (0x00 / 4)
#define GPFSEL1 (0x04 / 4)
@ -66,6 +68,11 @@ class dmagpio : public gpio
#define GPPUDCLK0 (0x98 / 4)
#define GPPUDCLK1 (0x9C / 4)
#define GPPUPPDN0 (0xBC/4)
#define GPPUPPDN1 (0xC0/4)
#define GPPUPPDN2 (0xC4/4)
#define GPPUPPDN3 (0xC8/4)
enum
{
fsel_input,
@ -104,6 +111,8 @@ class generalgpio : public gpio
#define GPCLK_DIV_2 (0x84 / 4)
#define EMMCCLK_CNTL (0x1C0 / 4)
#define EMMCCLK_DIV (0x1C4 / 4)
#define CM_EMMC2CTL (0x1d0/4)
#define CM_EMMC2DIV (0x1d4/4)
#define CM_VPUCTL 0x008
#define CM_VPUDIV 0x00c
@ -246,8 +255,8 @@ class generalgpio : public gpio
#define PLLH_STS (0x1660 / 4)
#define XOSC_CTRL (0x1190 / 4)
#define XOSC_FREQUENCY 19200000
//#define XOSC_FREQUENCY 19200000
//#define XOSC_FREQUENCY 54000000
//Parent PLL
enum
{

View file

@ -11,15 +11,15 @@
class iqdmasync:public bufferdma,public clkgpio,public pwmgpio,public pcmgpio
{
protected:
uint64_t tunefreq;
bool syncwithpwm;
dsp mydsp;
int ModeIQ=MODE_IQ;
uint32_t Originfsel; //Save the original FSEL GPIO
uint32_t SampleRate;
public:
int ModeIQ=MODE_IQ;
iqdmasync(uint64_t TuneFrequency,uint32_t SR,int Channel,uint32_t FifoSize,int Mode);
~iqdmasync();
void SetDmaAlgo();

View file

@ -20,139 +20,144 @@ This program is free software: you can redistribute it and/or modify
#include "ookburst.h"
#include "util.h"
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()
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)
{
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)
clkgpio::SetAdvancedPllMode(true);
clkgpio::SetCenterFrequency(TuneFrequency, 0); // Bandwidth is 0 because frequency always the same
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
{
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
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++; //SKIP FREQ CB
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--;
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
{
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];
}
while(isrunning()) //Block function : return until sent completely signal
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);
}
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;
if (n >= m_MaxMessage)
{
ookrenderbuffer[n++]=TabSymbols[i].value;
if(n>=m_MaxMessage)
{
dbg_printf(1,"OOK Message too long abort time(%d/%d)\n",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);
}

View file

@ -12,8 +12,10 @@ class ookburst:public bufferdma,public clkgpio,public pwmgpio,public pcmgpio
uint32_t Originfsel;
bool syncwithpwm;
dma_cb_t *lastcbp;
size_t SR_upsample=1;
size_t Ramp=0.0;
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();
void SetDmaAlgo();

View file

@ -41,7 +41,7 @@ phasedmasync::phasedmasync(uint64_t TuneFrequency,uint32_t SampleRateIn,int Numb
clkgpio::SetAdvancedPllMode(true);
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)) ;
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
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;
}
int dbg_getlevel()
{
return debug_level;
}
void dbg_printf(int Level, const char *fmt, ...)
{
if (Level <= debug_level)

View file

@ -5,6 +5,7 @@
#include <stdarg.h>
void dbg_setlevel(int Level);
int dbg_getlevel();
void dbg_printf(int Level, const char *fmt, ...);
#endif