Compare commits

..

No commits in common. "master" and "simplify_dma" have entirely different histories.

21 changed files with 302 additions and 2385 deletions

3
.gitignore vendored
View file

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

View file

@ -1,7 +1,7 @@
all: testrpitx
CFLAGS = -Wall -g -O3 -Wno-unused-variable -I /opt/vc/include
LDFLAGS = -lm -lrt -lpthread -L/opt/vc/lib -lbcm_host
CFLAGS = -Wall -g -O3 -Wno-unused-variable
LDFLAGS = -lm -lrt -lpthread
CCP = g++
CC = gcc

File diff suppressed because it is too large Load diff

BIN
app/testrpitx Executable file

Binary file not shown.

View file

@ -283,9 +283,9 @@ void SimpleTestAm(uint64_t Freq)
void SimpleTestOOK(uint64_t Freq)
{
int SR = 10; //10 HZ
int SR = 1000;
int FifoSize = 21; //24
ookburst ook(Freq, SR, 14, FifoSize,100);
ookburst ook(Freq, SR, 14, FifoSize);
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,54 +701,6 @@ 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)
{
@ -771,7 +723,7 @@ int main(int argc, char *argv[])
sa.sa_handler = terminate;
sigaction(i, &sa, NULL);
}
dbg_setlevel(1);
dbg_setlevel(0);
//SimpleTest(Freq);
//SimpleTestbpsk(Freq);
//SimpleTestFileIQ(Freq);
@ -782,8 +734,5 @@ int main(int argc, char *argv[])
//SimpleTestOOKTiming(Freq);
//AlectoOOK(Freq);
//RfSwitchOOK(Freq);
//SimpleTestbpsk(Freq);
//SimpleTestAtv(Freq);
info(Freq);
SimpleTestAtv(Freq);
}

View file

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

BIN
src/amdmasync.h.gch Normal file

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", ((uintptr_t)(cbp) - (uintptr_t)(cbarray)) / sizeof(dma_cb_t));
dbg_printf(1, "Last cbp : %d \n", ((unsigned int)(cbp) - (unsigned int)(cbarray)) / sizeof(dma_cb_t));
}
void atv::SetFrame(unsigned char *Luminance, size_t Lines)

View file

@ -19,7 +19,6 @@ 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"
{
@ -33,24 +32,9 @@ extern "C"
dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize) // Fixme! Need to check to be 256 Aligned for UserMem
{
//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();
dbg_printf(1,"Channel %d CBSize %u UsermemSize %u\n",Channel,CBSize,UserMemSize);
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)
{
@ -61,7 +45,6 @@ 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);
@ -88,16 +71,27 @@ dma::dma(int Channel,uint32_t CBSize,uint32_t UserMemSize) // Fixme! Need to che
void dma::GetRpiInfo()
{
dram_phys_base= bcm_host_get_sdram_address();
mem_flag = MEM_FLAG_HINT_PERMALOCK|MEM_FLAG_NO_INIT;//0x0c;
switch(dram_phys_base)
RASPBERRY_PI_INFO_T info;
if (getRaspberryPiInformation(&info) > 0)
{
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_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");
}
}
dma::~dma()

View file

@ -20,124 +20,108 @@ This program is free software: you can redistribute it and/or modify
#include "util.h"
#include <unistd.h>
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, 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%
if (syncwithpwm)
fskburst::fskburst(uint64_t TuneFrequency,uint32_t SymbolRate,float Deviation,int Channel,uint32_t FifoSize):bufferdma(Channel,FifoSize+3,2,1),freqdeviation(Deviation)
{
pwmgpio::SetPllNumber(clk_plld, 1);
pwmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
}
else
{
pcmgpio::SetPllNumber(clk_plld, 1);
pcmgpio::SetFrequency(SymbolRate * (float)SR_upsample);
}
//Should be obligatory place before setdmaalgo
Originfsel = clkgpio::gengpio.gpioreg[GPFSEL0];
dbg_printf(1, "FSK Origin fsel %x\n", Originfsel);
SetDmaAlgo();
}
fskburst::~fskburst()
{
}
void fskburst::SetDmaAlgo()
{
sampletab[buffersize * registerbysample - 2] = (Originfsel & ~(7 << 12)) | (4 << 12); //Gpio Clk
sampletab[buffersize * registerbysample - 1] = (Originfsel & ~(7 << 12)) | (0 << 12); //Gpio In
dma_cb_t *cbp = cbarray;
// We must fill the FIFO (PWM or PCM) to be Synchronized from start
// PWM FIFO = 16
// PCM FIFO = 64
if (syncwithpwm)
{
SetEasyCB(cbp++, 0, dma_pwm, 16 + 1);
}
else
{
SetEasyCB(cbp++, 0, dma_pcm, 64 + 1);
}
SetEasyCB(cbp++, buffersize * registerbysample - 2, dma_fsel, 1); //Enable clk
for (uint32_t samplecnt = 0; samplecnt < buffersize - 2; samplecnt++)
{
// Write a frequency sample
SetEasyCB(cbp++, samplecnt * registerbysample, dma_pllc_frac, 1); //FReq
// Delay
SetEasyCB(cbp++, samplecnt * registerbysample, syncwithpwm ? dma_pwm : dma_pcm, 1);
}
lastcbp = cbp;
SetEasyCB(cbp, buffersize * registerbysample - 1, dma_fsel, 1); //Disable clk
cbp->next = 0; // Stop DMA
dbg_printf(2, "Last cbp : src %x dest %x next %x\n", cbp->src, cbp->dst, cbp->next);
}
void fskburst::SetSymbols(unsigned char *Symbols, uint32_t Size)
{
if (Size > buffersize - 3)
{
dbg_printf(1, "Buffer overflow\n");
return;
}
dma_cb_t *cbp = cbarray;
cbp += 2; // Skip the first 2 CB (initialisation)
clkgpio::SetAdvancedPllMode(true);
clkgpio::SetCenterFrequency(TuneFrequency,SymbolRate); // Write Mult Int and Frac : FixMe carrier is already there
clkgpio::SetFrequency(0);
disableclk(4);
syncwithpwm=false;
for (unsigned int i = 0; i < Size; i++)
{
for (size_t j = 0; j < SR_upsample - Ramp; j++)
if(syncwithpwm)
{
sampletab[i * SR_upsample + j] = (0x5A << 24) | GetMasterFrac(freqdeviation * Symbols[i]);
cbp++; //SKIP FREQ CB
cbp->next = mem_virt_to_phys(cbp + 1);
cbp++;
pwmgpio::SetPllNumber(clk_plld,1);
pwmgpio::SetFrequency(SymbolRate);
}
for (size_t j = 0 ; j < Ramp; j++)
else
{
if (i < Size - 1)
pcmgpio::SetPllNumber(clk_plld,1);
pcmgpio::SetFrequency(SymbolRate);
}
//Should be obligatory place before setdmaalgo
Originfsel=clkgpio::gengpio.gpioreg[GPFSEL0];
dbg_printf(1,"FSK Origin fsel %x\n",Originfsel);
SetDmaAlgo();
}
fskburst::~fskburst()
{
}
void fskburst::SetDmaAlgo()
{
sampletab[buffersize*registerbysample-2]=(Originfsel & ~(7 << 12)) | (4 << 12); //Gpio Clk
sampletab[buffersize*registerbysample-1]=(Originfsel & ~(7 << 12)) | (0 << 12); //Gpio In
dma_cb_t *cbp = cbarray;
// We must fill the FIFO (PWM or PCM) to be Synchronized from start
// PWM FIFO = 16
// PCM FIFO = 64
if(syncwithpwm)
{
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);
SetEasyCB(cbp++,0,dma_pwm,16+1);
}
else
{
sampletab[i * SR_upsample + j + SR_upsample -Ramp] = (0x5A << 24) | GetMasterFrac(freqdeviation * Symbols[i]);
SetEasyCB(cbp++,0,dma_pcm,64+1);
}
SetEasyCB(cbp++,buffersize*registerbysample-2,dma_fsel,1);//Enable clk
cbp++; //SKIP FREQ CB
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++)
{
sampletab[i]=(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);
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);
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 ?
}
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,10 +12,8 @@ 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,float SymbolRate,float Deviation,int Channel,uint32_t FifoSize,size_t upsample=1,float RatioRamp=0);
fskburst(uint64_t TuneFrequency,uint32_t SymbolRate,float Deviation,int Channel,uint32_t FifoSize);
~fskburst();
void SetDmaAlgo();

View file

@ -24,15 +24,12 @@ 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(GetPeripheralBase()+base, len);
gpioreg = (uint32_t *)mapmem(base, len);
gpiolen=len;
}
@ -42,85 +39,33 @@ 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 =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
uint32_t BCM2708_PERI_BASE = 0;
if (getRaspberryPiInformation(&info) > 0)
{
dbg_printf(0,"RPi4 GPIO detected\n");
pi_is_2711=true; //Rpi4
XOSC_FREQUENCY=54000000;
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;
}
}
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( DMA_BASE, DMA_LEN)
dmagpio::dmagpio() : gpio(GetPeripheralBase() + DMA_BASE, DMA_LEN)
{
}
// ***************** CLK Registers *****************************************
clkgpio::clkgpio() : gpio(CLK_BASE, CLK_LEN)
clkgpio::clkgpio() : gpio(GetPeripheralBase() + CLK_BASE, CLK_LEN)
{
SetppmFromNTP();
padgpio level;
@ -136,7 +81,7 @@ clkgpio::~clkgpio()
int clkgpio::SetPllNumber(int PllNo, int MashType)
{
print_clock_tree();
//print_clock_tree();
if (PllNo < 8)
pllnumber = PllNo;
else
@ -164,26 +109,21 @@ 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))/(2*(gpioreg[PLLA_CTRL] >> 12)&0x7);
Freq = XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLA_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLA_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:
//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) ;
Freq = XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLC_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLC_FRAC] / (1 << 20);
break;
case clk_plld:
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) ;
Freq = (XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLD_CTRL] & 0x3ff) + (XOSC_FREQUENCY * (uint64_t)gpioreg[PLLD_FRAC]) / (1 << 20)) / (gpioreg[PLLD_PER] >> 1);
break;
case clk_hdmi:
Freq =( XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLH_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLH_FRAC] / (1 << 20))/(2*(gpioreg[PLLH_CTRL] >> 12)&0x7) ;
Freq = XOSC_FREQUENCY * ((uint64_t)gpioreg[PLLH_CTRL] & 0x3ff) + XOSC_FREQUENCY * (uint64_t)gpioreg[PLLH_FRAC] / (1 << 20);
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, "Pi4=%d Xosc = %llu Freq PLL no %d= %llu\n",pi_is_2711,XOSC_FREQUENCY,PllNo, Freq);
dbg_printf(1, "Freq PLL no %d= %llu\n",PllNo, Freq);
return Freq;
}
@ -217,26 +157,9 @@ int clkgpio::SetFrequency(double Frequency)
double FloatMult=0;
if(PllFixDivider==1) //Using PDIV thus frequency/2
{
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));
}
}
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));
int IntMultiply = freqctl >> 20; // Need to be calculated to have a center frequency
freqctl &= 0xFFFFF; // Fractionnal is 20bits
@ -264,26 +187,10 @@ uint32_t clkgpio::GetMasterFrac(double Frequency)
if (ModulateFromMasterPLL)
{
double FloatMult=0;
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));
}
}
if(PllFixDivider==1) //Using PDIV thus frequency/2
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));
int IntMultiply = freqctl >> 20; // Need to be calculated to have a center frequency
freqctl &= 0xFFFFF; // Fractionnal is 20bits
@ -305,8 +212,7 @@ 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 XOSC_FREQUENCY
//Pi4 seems 54Mhz
#define XTAL_RATE 19.2e6
double xtal_freq_recip = 1.0 / XTAL_RATE; // todo PPM correction
int best_divider = 0;
@ -316,8 +222,6 @@ 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");
@ -364,7 +268,6 @@ 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;
@ -409,24 +312,15 @@ int clkgpio::SetCenterFrequency(uint64_t Frequency, int Bandwidth)
if (ModulateFromMasterPLL)
{
//Choose best PLLDiv and Div
if(pi_is_2711)
{
ComputeBestLO(Frequency*2, Bandwidth); //FixeDivider update
//PllFixDivider=PllFixDivider/2;
}
else
{
ComputeBestLO(Frequency, Bandwidth); //FixeDivider update
}
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
@ -452,7 +346,7 @@ int clkgpio::SetCenterFrequency(uint64_t Frequency, int Bandwidth)
}
else
{
ana[1]|=(0<<14); // No use prediv means Frequenc
ana[1]|=(0<<14); // No use prediv means Frequency
}
/*
* ANA register setup is done as a series of writes to
@ -508,7 +402,6 @@ 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)
{
@ -539,14 +432,7 @@ void clkgpio::SetAdvancedPllMode(bool Advanced)
gpioreg[PLLC_CORE0] = 0x5A000000|(1<<8);//Disable
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
}
gpioreg[PLLC_PER] = 0x5A000001; // Divisor
usleep(100);
}
}
@ -649,25 +535,24 @@ 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", xoscmhz * ((float)(gpioreg[PLLA_CTRL] & 0x3ff) + ((float)gpioreg[PLLA_FRAC]) / ((float)(1 << 20))));
printf(" %f MHz\n", 19.2 * ((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", xoscmhz * ((float)(gpioreg[PLLB_CTRL] & 0x3ff) + ((float)gpioreg[PLLB_FRAC]) / ((float)(1 << 20))));
printf(" %f MHz\n", 19.2 * ((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", xoscmhz * ((float)(gpioreg[PLLC_CTRL] & 0x3ff) + ((float)gpioreg[PLLC_FRAC]) / ((float)(1 << 20))));
printf(" %f MHz\n", 19.2 * ((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", xoscmhz * ((float)(gpioreg[PLLD_CTRL] & 0x3ff) + ((float)gpioreg[PLLD_FRAC]) / ((float)(1 << 20))));
printf(" %f MHz\n", 19.2 * ((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", xoscmhz * ((float)(gpioreg[PLLH_CTRL] & 0x3ff) + ((float)gpioreg[PLLH_FRAC]) / ((float)(1 << 20))));
printf(" %f MHz\n", 19.2 * ((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]);
}
@ -737,7 +622,7 @@ void clkgpio::SetppmFromNTP()
// ************************************** GENERAL GPIO *****************************************************
generalgpio::generalgpio() : gpio(/*GetPeripheralBase() + */GENERAL_BASE, GENERAL_LEN)
generalgpio::generalgpio() : gpio(GetPeripheralBase() + GENERAL_BASE, GENERAL_LEN)
{
}
@ -759,32 +644,18 @@ 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;
}
gpioreg[GPPUD]=0;
usleep(150);
gpioreg[GPPUDCLK0]=1<<gpio;
usleep(150);
gpioreg[GPPUDCLK0]=0;
return 0;
}
// ********************************** PWM GPIO **********************************
pwmgpio::pwmgpio() : gpio(/*GetPeripheralBase() + */PWM_BASE, PWM_LEN)
pwmgpio::pwmgpio() : gpio(GetPeripheralBase() + PWM_BASE, PWM_LEN)
{
gpioreg[PWM_CTL] = 0;
@ -934,7 +805,7 @@ int pwmgpio::SetPrediv(int predivisor) //Mode should be only for SYNC or a Data
// ********************************** PCM GPIO (I2S) **********************************
pcmgpio::pcmgpio() : gpio(PCM_BASE, PCM_LEN)
pcmgpio::pcmgpio() : gpio(GetPeripheralBase() + PCM_BASE, PCM_LEN)
{
gpioreg[PCM_CS_A] = 1; // Disable Rx+Tx, Enable PCM block
}
@ -1019,7 +890,7 @@ int pcmgpio::SetPrediv(int predivisor) //Carefull we use a 10 fixe divisor for n
// ********************************** PADGPIO (Amplitude) **********************************
padgpio::padgpio() : gpio(PADS_GPIO, PADS_GPIO_LEN)
padgpio::padgpio() : gpio(GetPeripheralBase() + PADS_GPIO, PADS_GPIO_LEN)
{
}

View file

@ -7,9 +7,7 @@
class gpio
{
public:
bool pi_is_2711=false;
uint64_t XOSC_FREQUENCY=19200000;
public:
volatile uint32_t *gpioreg = NULL;
uint32_t gpiolen;
@ -59,7 +57,7 @@ class dmagpio : public gpio
//************************************ GENERAL GPIO ***************************************
#define GENERAL_BASE (0x00200000)
#define GENERAL_LEN 0xD0
#define GENERAL_LEN 0xB4
#define GPFSEL0 (0x00 / 4)
#define GPFSEL1 (0x04 / 4)
@ -68,11 +66,6 @@ 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,
@ -111,8 +104,6 @@ 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
@ -255,8 +246,8 @@ class generalgpio : public gpio
#define PLLH_STS (0x1660 / 4)
#define XOSC_CTRL (0x1190 / 4)
//#define XOSC_FREQUENCY 19200000
//#define XOSC_FREQUENCY 54000000
#define XOSC_FREQUENCY 19200000
//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,144 +20,139 @@ This program is free software: you can redistribute it and/or modify
#include "ookburst.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)
{
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)
ookburst::ookburst(uint64_t TuneFrequency,uint32_t SymbolRate,int Channel,uint32_t FifoSize):bufferdma(Channel,FifoSize+2,2,1)
{
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++)
clkgpio::SetAdvancedPllMode(true);
clkgpio::SetCenterFrequency(TuneFrequency,0); // Bandwidth is 0 because frequency always the same
clkgpio::SetFrequency(0);
syncwithpwm=false;
if(syncwithpwm)
{
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++;
pwmgpio::SetPllNumber(clk_plld,1);
pwmgpio::SetFrequency(SymbolRate);
}
for (size_t j = 0; j < Ramp; j++)
else
{
if (i < Size - 1)
pcmgpio::SetPllNumber(clk_plld,1);
pcmgpio::SetFrequency(SymbolRate);
}
Originfsel=clkgpio::gengpio.gpioreg[GPFSEL0];
SetDmaAlgo();
}
ookburst::~ookburst()
{
}
void ookburst::SetDmaAlgo()
{
dma_cb_t *cbp=cbarray;
// We must fill the FIFO (PWM or PCM) to be Synchronized from start
// PWM FIFO = 16
// PCM FIFO = 64
if(syncwithpwm)
{
sampletab[i * SR_upsample + j + SR_upsample - Ramp] = (Symbols[i] == 0) ? ((Originfsel & ~(7 << 12)) | (0 << 12)) : ((Originfsel & ~(7 << 12)) | (4 << 12));
SetEasyCB(cbp++,0,dma_pwm,16+1);
}
else
{
sampletab[i * SR_upsample + j + SR_upsample - Ramp] = (Symbols[i] == 0) ? ((Originfsel & ~(7 << 12)) | (0 << 12)) : ((Originfsel & ~(7 << 12)) | (4 << 12));
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;
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
// 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)
{
usleep(100);
}
usleep(100); //To be sure last symbol Tx ?
}
if(Size>buffersize-2) {dbg_printf(1,"Buffer overflow\n");return;}
//****************************** 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++)
dma_cb_t *cbp=cbarray;
cbp++; // Skip the first which is the Fiiling of Fifo
for(unsigned i=0;i<Size;i++)
{
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;
}
sampletab[i]=(Symbols[i]==0)?((Originfsel & ~(7 << 12)) | (0 << 12)):((Originfsel & ~(7 << 12)) | (4 << 12));
cbp++;//SKIP FSEL CB
cbp->next = mem_virt_to_phys(cbp + 1);
//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);
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];
}
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)
{
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,10 +12,8 @@ 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,float SymbolRate,int Channel,uint32_t FifoSize, size_t upsample=1,float RatioRamp=0.0);
ookburst(uint64_t TuneFrequency,uint32_t SymbolRate,int Channel,uint32_t FifoSize);
~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)(pwmgpio::XOSC_FREQUENCY);
double FloatMult=((double)(tunefreq)*clkgpio::PllFixDivider)/(double)(XOSC_FREQUENCY);
uint32_t freqctl = FloatMult*((double)(1<<20)) ;
int IntMultiply= freqctl>>20; // Need to be calculated to have a center frequency
freqctl&=0xFFFFF; // Fractionnal is 20bits

View file

@ -1,31 +0,0 @@
#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;
}

View file

@ -1,3 +0,0 @@
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,11 +7,6 @@ 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,7 +5,6 @@
#include <stdarg.h>
void dbg_setlevel(int Level);
int dbg_getlevel();
void dbg_printf(int Level, const char *fmt, ...);
#endif