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
|
||||
|
||||
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
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)
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
44
src/Makefile
44
src/Makefile
|
@ -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.
|
@ -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)
|
||||
|
|
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 "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)
|
||||
{
|
||||
if(info.peripheralBase==RPI_BROADCOM_2835_PERIPHERAL_BASE)
|
||||
{
|
||||
dram_phys_base= bcm_host_get_sdram_address();
|
||||
|
||||
dram_phys_base = 0x40000000;
|
||||
mem_flag = MEM_FLAG_L1_NONALLOCATING|MEM_FLAG_HINT_PERMALOCK|MEM_FLAG_NO_INIT;//0x0c;
|
||||
mem_flag = 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()
|
||||
|
|
116
src/fskburst.cpp
116
src/fskburst.cpp
|
@ -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)
|
||||
{
|
||||
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::SetCenterFrequency(TuneFrequency, Deviation*10); // Write Mult Int and Frac : FixMe carrier is already there
|
||||
clkgpio::SetFrequency(0);
|
||||
disableclk(4);
|
||||
syncwithpwm=false;
|
||||
syncwithpwm = false;
|
||||
Ramp = SR_upsample * RatioRamp; //Ramp time = 10%
|
||||
|
||||
if(syncwithpwm)
|
||||
if (syncwithpwm)
|
||||
{
|
||||
pwmgpio::SetPllNumber(clk_plld,1);
|
||||
pwmgpio::SetFrequency(SymbolRate);
|
||||
pwmgpio::SetPllNumber(clk_plld, 1);
|
||||
pwmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
|
||||
}
|
||||
else
|
||||
{
|
||||
pcmgpio::SetPllNumber(clk_plld,1);
|
||||
pcmgpio::SetFrequency(SymbolRate);
|
||||
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);
|
||||
Originfsel = clkgpio::gengpio.gpioreg[GPFSEL0];
|
||||
dbg_printf(1, "FSK Origin fsel %x\n", Originfsel);
|
||||
|
||||
SetDmaAlgo();
|
||||
}
|
||||
|
||||
fskburst::~fskburst()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fskburst::~fskburst()
|
||||
{
|
||||
}
|
||||
|
||||
void fskburst::SetDmaAlgo()
|
||||
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
|
||||
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)
|
||||
if (syncwithpwm)
|
||||
{
|
||||
SetEasyCB(cbp++,0,dma_pwm,16+1);
|
||||
SetEasyCB(cbp++, 0, dma_pwm, 16 + 1);
|
||||
}
|
||||
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
|
||||
SetEasyCB(cbp++,samplecnt*registerbysample,dma_pllc_frac,1);//FReq
|
||||
SetEasyCB(cbp++, samplecnt * registerbysample, dma_pllc_frac, 1); //FReq
|
||||
|
||||
// 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;
|
||||
|
||||
SetEasyCB(cbp,buffersize*registerbysample-1,dma_fsel,1);//Disable clk
|
||||
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);
|
||||
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)
|
||||
void fskburst::SetSymbols(unsigned char *Symbols, uint32_t Size)
|
||||
{
|
||||
if (Size > buffersize - 3)
|
||||
{
|
||||
if(Size>buffersize-3) {dbg_printf(1,"Buffer overflow\n");return;}
|
||||
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++)
|
||||
dma_cb_t *cbp = cbarray;
|
||||
cbp += 2; // Skip the first 2 CB (initialisation)
|
||||
|
||||
|
||||
|
||||
for (unsigned int i = 0; i < Size; i++)
|
||||
{
|
||||
sampletab[i]=(0x5A<<24)|GetMasterFrac(freqdeviation*Symbols[i]);
|
||||
cbp++;//SKIP FREQ CB
|
||||
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->next = mem_virt_to_phys(cbp + 1);
|
||||
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->next = mem_virt_to_phys(lastcbp);
|
||||
|
||||
|
||||
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]);
|
||||
usleep(100);
|
||||
|
||||
}
|
||||
dbg_printf(1,"FSK burst end Tx\n",cbp->src,cbp->dst,cbp->next);
|
||||
usleep(100);//To be sure last symbol Tx ?
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
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();
|
||||
|
||||
|
|
201
src/gpio.cpp
201
src/gpio.cpp
|
@ -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)
|
||||
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;
|
||||
}
|
||||
|
||||
if ((info.peripheralBase == RPI_BROADCOM_2836_PERIPHERAL_BASE) || (info.peripheralBase == RPI_BROADCOM_2837_PERIPHERAL_BASE))
|
||||
{
|
||||
BCM2708_PERI_BASE = info.peripheralBase;
|
||||
}
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
17
src/gpio.h
17
src/gpio.h
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
155
src/ookburst.cpp
155
src/ookburst.cpp
|
@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
clkgpio::SetAdvancedPllMode(true);
|
||||
|
||||
clkgpio::SetCenterFrequency(TuneFrequency,0); // Bandwidth is 0 because frequency always the same
|
||||
clkgpio::SetCenterFrequency(TuneFrequency, 0); // Bandwidth is 0 because frequency always the same
|
||||
clkgpio::SetFrequency(0);
|
||||
|
||||
syncwithpwm=false;
|
||||
syncwithpwm = false;
|
||||
Ramp = SR_upsample * RatioRamp; //Ramp time
|
||||
|
||||
if(syncwithpwm)
|
||||
if (syncwithpwm)
|
||||
{
|
||||
pwmgpio::SetPllNumber(clk_plld,1);
|
||||
pwmgpio::SetFrequency(SymbolRate);
|
||||
pwmgpio::SetPllNumber(clk_plld, 1);
|
||||
pwmgpio::SetFrequency(SymbolRate * (float)upsample);
|
||||
}
|
||||
else
|
||||
{
|
||||
pcmgpio::SetPllNumber(clk_plld,1);
|
||||
pcmgpio::SetFrequency(SymbolRate);
|
||||
pcmgpio::SetPllNumber(clk_plld, 1);
|
||||
pcmgpio::SetFrequency(SymbolRate * float(upsample));
|
||||
}
|
||||
|
||||
|
||||
Originfsel=clkgpio::gengpio.gpioreg[GPFSEL0];
|
||||
Originfsel = clkgpio::gengpio.gpioreg[GPFSEL0];
|
||||
SetDmaAlgo();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
ookburst::~ookburst()
|
||||
{
|
||||
}
|
||||
|
||||
void ookburst::SetDmaAlgo()
|
||||
ookburst::~ookburst()
|
||||
{
|
||||
dma_cb_t *cbp=cbarray;
|
||||
}
|
||||
|
||||
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)
|
||||
if (syncwithpwm)
|
||||
{
|
||||
SetEasyCB(cbp++,0,dma_pwm,16+1);
|
||||
SetEasyCB(cbp++, 0, dma_pwm, 16 + 1);
|
||||
}
|
||||
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++)
|
||||
{
|
||||
|
||||
//Set Amplitude to FSEL for amplitude=0
|
||||
SetEasyCB(cbp++,samplecnt*registerbysample,dma_fsel,1);
|
||||
SetEasyCB(cbp++, samplecnt * registerbysample, dma_fsel, 1);
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
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)
|
||||
void ookburst::SetSymbols(unsigned char *Symbols, uint32_t Size)
|
||||
{
|
||||
if (Size > buffersize - 2)
|
||||
{
|
||||
if(Size>buffersize-2) {dbg_printf(1,"Buffer overflow\n");return;}
|
||||
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
|
||||
|
||||
|
||||
for(unsigned i=0;i<Size;i++)
|
||||
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
|
||||
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);
|
||||
|
||||
//dbg_printf(1,"cbp : sample %d pointer %p src %x dest %x next %x\n",i,cbp,cbp->src,cbp->dst,cbp->next);
|
||||
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->next = mem_virt_to_phys(lastcbp);
|
||||
|
||||
|
||||
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 ?
|
||||
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];
|
||||
}
|
||||
|
||||
//****************************** 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;
|
||||
}
|
||||
|
||||
ookbursttiming::~ookbursttiming()
|
||||
void ookbursttiming::SendMessage(SampleOOKTiming *TabSymbols, size_t Size)
|
||||
{
|
||||
size_t n = 0;
|
||||
for (size_t i = 0; i < Size; i++)
|
||||
{
|
||||
if(ookrenderbuffer!=nullptr)
|
||||
delete []ookrenderbuffer;
|
||||
}
|
||||
|
||||
void ookbursttiming::SendMessage(SampleOOKTiming *TabSymbols,size_t Size)
|
||||
for (size_t j = 0; j < TabSymbols[i].duration / 10; j++)
|
||||
{
|
||||
size_t n=0;
|
||||
for (size_t i=0;i<Size;i++)
|
||||
ookrenderbuffer[n++] = TabSymbols[i].value;
|
||||
if (n >= m_MaxMessage)
|
||||
{
|
||||
for(size_t j=0;j<TabSymbols[i].duration/10;j++)
|
||||
{
|
||||
ookrenderbuffer[n++]=TabSymbols[i].value;
|
||||
if(n>=m_MaxMessage)
|
||||
{
|
||||
dbg_printf(1,"OOK Message too long abort time(%d/%d)\n",n,m_MaxMessage);
|
||||
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;
|
||||
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();
|
||||
|
||||
|
|
|
@ -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
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;
|
||||
}
|
||||
|
||||
int dbg_getlevel()
|
||||
{
|
||||
return debug_level;
|
||||
}
|
||||
|
||||
void dbg_printf(int Level, const char *fmt, ...)
|
||||
{
|
||||
if (Level <= debug_level)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <stdarg.h>
|
||||
|
||||
void dbg_setlevel(int Level);
|
||||
int dbg_getlevel();
|
||||
void dbg_printf(int Level, const char *fmt, ...);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue